Unity/C# кодер
Регистрация: 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
В аттаче скомпилированный проект и исходник этого туториала.
|