Показать сообщение отдельно
Старый 21.03.2006, 18:02   #5
pax
Unity/C# кодер
 
Аватар для pax
 
Регистрация: 03.10.2005
Адрес: Россия, Рязань
Сообщений: 7,568
Написано 3,006 полезных сообщений
(для 5,323 пользователей)
Туториал №4. Источники света.

В этом туториале вы узнаете как создавать источники света, настраивать их, и какие они бывают. Как и в предидущем туториале все описание находится в коде.

'-----------------------------------------------------------------------------
' Файл: Lights.vb
'
' Описание: Визуализация 3D геометрии более интересна, когда в сцену добавлены
'    источники света. Для использования освещения в D3D, Вы должны создать один
'    или больше источников света, задать материалы, и убедиться что ваша геометрия 
'    имеет нормали. Источники света могут иметь положение, цвет и бывают следующих типов:
'    направленный (свет исходит из точки, бесконечно удаленной от наблюдателя т.е. просто 
'    имеющий направление света), точечный (свет исходит из точки с координатами x,y,z и 
'    распространяется во всех напавлениях) и "Фонарь".
'    Материалы описывают поверхность геометрии, точнее то как она будет освещаться
'    (цвет рассеяния света, цвет окружающего света и т.д.).
'    Нормали - это составляющие вершин, которые нужны D3D для рассчета освещения поверхности.
'
' Copyright (c) Microsoft Corporation. Все права защищены.
'-----------------------------------------------------------------------------
Imports System
Imports System.Drawing
Imports System.Windows.Forms
Imports Microsoft.DirectX
Imports Microsoft.DirectX.Direct3D
Imports Direct3D = Microsoft.DirectX.Direct3D


Public Class Lights
  Inherits Form
  ' Наши глобальные переменные для этого проекта
  Private device As device = Nothing ' Наше устройство рендеринга 
  Private vertexBuffer As vertexBuffer = Nothing 'Буфер вершин
  'Объект, содержащий параметры устройства вывода
  Private presentParams As New PresentParameters
  Private pause As Boolean = False


  Public Sub New()
    ' Устанавливаем начальный размер нашей формы
    Me.ClientSize = New System.Drawing.Size(400, 300)
    ' и её название
    Me.Text = "Direct3D Tutorial 4 - Источники света"
  End Sub


  Public Function InitializeGraphics() As Boolean
    Try
      ' Здесь давайте проинициализируем D3D устройство 
      presentParams.Windowed = True ' Оконный режим
      presentParams.SwapEffect = SwapEffect.Discard ' Сброс кадров
      presentParams.EnableAutoDepthStencil = True ' Включение трафарета глубины
      presentParams.AutoDepthStencilFormat = DepthFormat.D16 ' Фотмат трафарета
      'Создание устройства
      device = New Device(0, DeviceType.Hardware, Me, _
          CreateFlags.SoftwareVertexProcessing, presentParams)
      AddHandler device.DeviceReset, AddressOf Me.OnResetDevice
      Me.OnCreateDevice(device, Nothing)
      Me.OnResetDevice(device, Nothing)
      pause = False
      Return True
    Catch e As DirectXException
      ' При пойманной ошибке возвращаем сообщение о неудачной инициализации устроцства D3D
      Return False
    End Try
  End Function

  Public Sub OnCreateDevice(ByVal sender As Object, ByVal e As EventArgs)
    Dim dev As Device = CType(sender, Device)
    ' Созаем буфер вершин
    vertexBuffer = New VertexBuffer(GetType(CustomVertex.PositionNormal), 100, dev, Usage.WriteOnly, CustomVertex.PositionNormal.Format, Pool.Default)
    AddHandler vertexBuffer.Created, AddressOf Me.OnCreateVertexBuffer
    Me.OnCreateVertexBuffer(vertexBuffer, Nothing)
  End Sub

  Public Sub OnResetDevice(ByVal sender As Object, ByVal e As EventArgs)
    Dim dev As Device = CType(sender, Device)
    ' Выключаем отсечение задних поверхностей геометрии
    device.RenderState.CullMode = Cull.None
    ' Включаем Z-буфер (ZBuffer)
    device.RenderState.ZBufferEnable = True
    device.RenderState.Lighting = True 'Включаем освещение
  End Sub

  Public Sub OnCreateVertexBuffer(ByVal sender As Object, ByVal e As EventArgs)
    Dim vb As VertexBuffer = CType(sender, VertexBuffer)
    ' Заполняем буфер вершин (100 вершин)

    ' "задерзиваем" буфер (который возвращает наши структуры)
    Dim verts As CustomVertex.PositionNormal() = CType(vb.Lock(0, 0), CustomVertex.PositionNormal())
    Dim i As Integer
    For i = 0 To 49
      ' Заполняем структуры
      Dim theta As Single = CSng(2 * Math.PI * i) / 49
      verts((2 * i)).SetPosition(New Vector3(CSng(Math.Sin(theta)), -1, CSng(Math.Cos(theta))))
      verts((2 * i)).SetNormal(New Vector3(CSng(Math.Sin(theta)), 0, CSng(Math.Cos(theta))))
      verts((2 * i + 1)).SetPosition(New Vector3(CSng(Math.Sin(theta)), 1, CSng(Math.Cos(theta))))
      verts((2 * i + 1)).SetNormal(New Vector3(CSng(Math.Sin(theta)), 0, CSng(Math.Cos(theta))))
    Next i
    ' "отпускаем" (и копируем) данные
    vb.Unlock()
  End Sub

  Private Sub SetupMatrices()
    ' Для нашей мировой матрицы зададим вращение объекта вокруг оси, которая задается
    ' вектором, на угол зависящий от времени работы программы.

    device.Transform.World = Matrix.RotationAxis(New Vector3(CSng(Math.Cos((Environment.TickCount / 250.0F))), _
              1, CSng(Math.Sin((Environment.TickCount / 250.0F)))), _
              Environment.TickCount / 3000.0F)

    ' Настроим видовую матрицу. Для этого необходимо знать 3 параметра: 1) точка
    ' наших глаз в пространстве; 2) направление нашего взгляда; 3) направление, 
    ' которое определяет "верх". Здесь мы устанавливаем, что точка наших глаз находится
    ' в точке (0, 3, -5) , взгляд направлен в начало координат и определяем "верх" осью Y. 
    device.Transform.View = Matrix.LookAtLH(New Vector3(0.0F, 3.0F, -5.0F), New Vector3(0.0F, 0.0F, 0.0F), New Vector3(0.0F, 1.0F, 0.0F))

    ' Для матрици проекций мы установим перспективное преобразование, которое
    ' выполнит преобразовани геометрии из 3D пространства в 2D область обзора на экране.
    ' Перспективная проекция делает объеты меньше на большом расстоянии от экрана и наоборот.
    ' Для создания перспективного преобразования мы должны задать поле зрения(обычно 90 градусов),
    ' соотношение размеров нашей 2D области, ближнюю и дальнюю плоскости отсечения (они определяют
    ' расстояние от точки зрения, на котором будет визуализитоваться сцена).
    device.Transform.Projection = Matrix.PerspectiveFovLH(CSng(Math.PI) / 4.0F, 1.0F, 1.0F, 100.0F)
  End Sub

  Private Sub SetupLights()
    Dim col As System.Drawing.Color = System.Drawing.Color.BlueViolet
    'Проинициализируем материал. Материал здесь имеет цвет рассеяния и цвет окружающего света
    'установленные фиолетовыми. Обратите внимание, что только один материал используется.
    Dim mtrl As New Direct3D.Material
    mtrl.Diffuse = col
    mtrl.Ambient = col
    device.Material = mtrl

    'Устанавливаем белый направленный источник света и задаем его направление.
    'Обратите внимание, что можно использовать много источников света одновременно (но каждый
    'из них замедляет процесс визуализации сцены). Также,
    'нам необходимо установить состояние (renderstate) D3DRS_LIGHTING для включения освещения

    device.Lights(0).Type = LightType.Directional
    device.Lights(0).Diffuse = System.Drawing.Color.White
    device.Lights(0).Direction = New Vector3(CSng(Math.Cos((Environment.TickCount / 250.0F))), _
                  1.0F, CSng(Math.Sin((Environment.TickCount / 250.0F))))

    device.Lights(0).Commit() 'пусть d3d знает о источнике
    device.Lights(0).Enabled = True 'включаем его
    'Наконец, задаем цвет окружающего света.
    'Окружающий свет - это свет который освещает все объекты в не освещенных местах
    '(другими словами это подсветка).
    device.RenderState.Ambient = System.Drawing.Color.FromArgb(&H202020)
  End Sub


  Private Sub Render()
    If pause Then
      Return
    End If
    ' Очистка заднего буфера синим цветом
    device.Clear(ClearFlags.Target Or ClearFlags.ZBuffer, System.Drawing.Color.Blue, 1.0F, 0)
    'Начало сцены
    device.BeginScene()
    ' Инициализируем освещение и матрицы
    SetupLights()
    SetupMatrices()

    device.SetStreamSource(0, vertexBuffer, 0)
    device.VertexFormat = CustomVertex.PositionNormal.Format
    device.DrawPrimitives(PrimitiveType.TriangleStrip, 0, 4 * 25 - 2)
    'Конец сцены
    device.EndScene()
    ' обновление экрана
    device.Present()
  End Sub


  Protected Overrides Sub OnPaint(ByVal e As System.Windows.Forms.PaintEventArgs)
    Me.Render() 'Визуализация сцены при событии Paint 
  End Sub

  Protected Overrides Sub OnKeyPress(ByVal e As System.Windows.Forms.KeyPressEventArgs)
    If Asc(e.KeyChar) = CInt(System.Windows.Forms.Keys.Escape) Then
      Me.Close() ' Обработка клавиши Esc 
    End If
  End Sub

  Protected Overrides Sub OnResize(ByVal e As System.EventArgs)
    pause = (Me.WindowState = FormWindowState.Minimized Or Not Me.Visible)
  End Sub

  '/ <summary>
  '/ Главная точка входа в приложение. 
  '/ </summary>
  Shared Sub Main()

    Dim frm As New Lights
    If Not frm.InitializeGraphics() Then ' Инициализация Direct3D
      MessageBox.Show("Невозможно инициализировать Direct3D. Программа будет закрыта.")
      Return
    End If
    frm.Show()

    While frm.Created
      frm.Render()
      Application.DoEvents()
    End While
  End Sub
End Class
В аттаче скомпилированный проект и исходник этого туториала.
__________________
Blitz3d to Unity Wiki
(Offline)
 
Ответить с цитированием
Эти 2 пользователя(ей) сказали Спасибо pax за это полезное сообщение:
Лit}{Ъ (02.05.2011), Nex (29.05.2009)