Шейдеры с нуля

Работа с 2D и 3D графикой, видео, звуком.

Модератор: Mikle

PilatP
Продвинутый пользователь
Продвинутый пользователь
Аватара пользователя
 
Сообщения: 117
Зарегистрирован: 24.08.2009 (Пн) 1:00
Откуда: Херсон

Шейдеры с нуля

Сообщение PilatP » 20.08.2014 (Ср) 19:47

Народ помогите разобраться с шейдерами, честно говоря инфы много но понять не могу. ну например на аналогиях
например
Код: Выделить всё
d3dDevice.SetTextureStageState 0, D3DTSS_COLOROP, D3DTOP_SELECTARG1
  d3dDevice.SetTextureStageState 0, D3DTSS_COLORARG1, D3DTA_TEXTURE

  d3dDevice.SetTextureStageState 1, D3DTSS_COLOROP, D3DTOP_DOTPRODUCT3
  d3dDevice.SetTextureStageState 1, D3DTSS_COLORARG1, D3DTA_TEXTURE
  d3dDevice.SetTextureStageState 1, D3DTSS_COLORARG2, D3DTA_CURRENT
  d3dDevice.SetTextureStageState 1, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_CAMERASPACENORMAL
  d3dDevice.SetTextureStageState 1, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT2

  d3dDevice.SetTextureStageState 2, D3DTSS_COLOROP, D3DTOP_MODULATE2X
  d3dDevice.SetTextureStageState 2, D3DTSS_COLORARG1, D3DTA_DIFFUSE
  d3dDevice.SetTextureStageState 2, D3DTSS_COLORARG2, D3DTA_CURRENT


на шейдерах это вот так

Код: Выделить всё
vs.1.0
  m4x4 oPos, v0, c0
  mov oD0, v5
  mul r0.x, v0.x, c4.x
  mul r0.yzw, v0.z, c4.x


очень хочется разобраться, помогите
начать лучше с простых примеров, кто понимает отзовитесь
Последний раз редактировалось PilatP 03.09.2014 (Ср) 14:31, всего редактировалось 1 раз.
Я не волшебник, я только учусь)

Mikle
Изобретатель велосипедов
Изобретатель велосипедов
Аватара пользователя
 
Сообщения: 4148
Зарегистрирован: 25.03.2003 (Вт) 14:02
Откуда: Туапсе

Re: Шейдеры с нуля

Сообщение Mikle » 21.08.2014 (Чт) 15:38

Это вообще не соответствующие фрагменты кода. Чуть позже поясню, сейчас занят.

PilatP
Продвинутый пользователь
Продвинутый пользователь
Аватара пользователя
 
Сообщения: 117
Зарегистрирован: 24.08.2009 (Пн) 1:00
Откуда: Херсон

Re: Шейдеры с нуля

Сообщение PilatP » 21.08.2014 (Чт) 23:54

Mikle я знаю что это все разное, я привел это для примера.
Честно говоря стоит вопрос детального текстурирования по шаблону 5 текстур + свет меняющий позицию. (min вариант color+normal+displace+specular+свет)
если сможешь желательно с описанием, чтобы можно было разобраться.

или хотя бы код для старта, а потом пояснения, а то по pixel шейдерам 1.4 мало примеров. вот текстуры для образца, в оригинале они у меня будут в .dds
У вас нет доступа для просмотра вложений в этом сообщении.
Я не волшебник, я только учусь)

Mikle
Изобретатель велосипедов
Изобретатель велосипедов
Аватара пользователя
 
Сообщения: 4148
Зарегистрирован: 25.03.2003 (Вт) 14:02
Откуда: Туапсе

Re: Шейдеры с нуля

Сообщение Mikle » 22.08.2014 (Пт) 8:22

Назови хоть одну причину, почему ты это хочешь сделать на PS_1_4 и, соответственно, на DX8, почему не на DX9.
Дело в том, что с PS_1_4 я в своё время даже не до конца разобрался, а сейчас уже забыл и то, что знал, и нет желания вспоминать - PS_1_4 - это тупик, отрубленная ветка.
Пиксельные шейдеры развиваются линейно с PS_2_0, от всего предыдущего отказались. То есть оно эмулируется ради совместимости, не более того, эмулируется зачастую криво, даже FFP из DX8 в новых версиях DirectX работает не до конца корректно, и это вряд ли уже кто-то будет исправлять. Другое дело - DX9, хоть он и почти такой же старый, но User Interface в Windows от Висты до Восьмёрки работает на нём, с ним будет гораздо меньше проблем.
По приведённому примеру - почему бы три последних чёрно-белых текстуры не объединить в одну RGB, чтобы работать с тремя текстурами?

PilatP
Продвинутый пользователь
Продвинутый пользователь
Аватара пользователя
 
Сообщения: 117
Зарегистрирован: 24.08.2009 (Пн) 1:00
Откуда: Херсон

Re: Шейдеры с нуля

Сообщение PilatP » 22.08.2014 (Пт) 9:43

Mikle, ответ прост, Dx8 я более менее знаю и пишу на нем свободно :oops: мне многое понятно, а Dx9 это только через твой врапер, я бы и рад на него полностью пересесть, но по нему много вопросов, и очень мало примеров
(то есть примеры есть, и они очень достойны, но я не разобрался, со многими моментами, те что мне нужны) например

спрайты, конечно их можно и просто через текстуру заюзать, но нет примеров как сделать например вращение вокруг оси, и с координатами точки вращения, в спрайтах проще там уже все это есть, а спрайты честно говоря очень нужны

с камерой тоже много мне не понятно.

если бы можно было создать тему с простыми примерами (камера, движение, свет,меши как создание так и загрузка, загрузка текстур у тебя везде через Lib "gdiplus", а обычного через Direct3DTexture9,я не встречал, много классов, и модулей нужно подключать, к примеру я для своих нужд написал ландшафтный редактор, грубо говоря то он меньше по обьему, чем простой пример. Пойми меня правильно, я не критикую, не в коем случае, просто очень много не понятного, и не привычного например у тебя переменые передаются через StrPtr, и пр, и не понятно все ли модули и классы которые мне могут понадобится у меня есть, для врапера), по твоему враперу.

вот по этому и играюсь с DX8, да и примеров куча и целый сайт тоже))

Вот если бы ты осветил все по твоему враперу с примерами, было бы круто (Я понимаю что труд огромный :oops: ), по тому и не настаиваю

Да и пишу, для себя в удовольствие. А по поводу текстур, мне их генерирует в таком виде программа Crazybump! Очень хорошая можно сразу видеть что получается и саму текстуру, и в 3D виде, если нужно могу скинуть
Я не волшебник, я только учусь)

Mikle
Изобретатель велосипедов
Изобретатель велосипедов
Аватара пользователя
 
Сообщения: 4148
Зарегистрирован: 25.03.2003 (Вт) 14:02
Откуда: Туапсе

Re: Шейдеры с нуля

Сообщение Mikle » 22.08.2014 (Пт) 10:57

Описать работу с DX9 через мой враппер так, как я уже описал работу с DX8 - это действительно большая работа, и я за неё вряд ли возьмусь.
Но я готов отвечать не конкретные вопросы последовательно. По конкретно написанному сейчас:
PilatP писал(а):спрайты, конечно их можно и просто через текстуру заюзать, но нет примеров как сделать например вращение вокруг оси, и с координатами точки вращения, в спрайтах проще там уже все это есть, а спрайты честно говоря очень нужны

Я не делал многого из D3DX, в том числе спрайтов и мешей, просто мне их D3DX реализация кажется ущербной, например попробуй задействовать меш с вертексным шейдером в D3DX8. Как написать свой класс меша я уже давал пример, сделать свой спрайт - ещё проще, могу с этим помочь.
PilatP писал(а):с камерой тоже много мне не понятно.

А что с камерой? Всё делается так же, как было в DX8.
PilatP писал(а):загрузка текстур у тебя везде через Lib "gdiplus", а обычного через Direct3DTexture9,я не встречал, много классов, и модулей нужно подключать

Лучше вообще подключить сразу все модули из DX_VB и сохранить этот проект, как шаблон, Lib "gdiplus" для использования gdiplus не требуется, это во-первых. А во-вторых - я уже давно сделал полные LoadFromFile() и LoadFromFileEx(), причём для их использования даже не требуется D3DX9_XX.dll, посмотри последние версии DX_VB.
PilatP писал(а):и не привычного например у тебя переменые передаются через StrPtr

Такого нет, есть VarPtr(), всё логично - там, где параметр функции не объектный, а типа Long, и имеет имя, например pTex, pBuf и т. п. - это указатель. Таких моментов не много, это в основном чтение и запись буферов после лока.
Так что задавай вопросы, можно просто фрагменты кода на DX8 - буду давать их перевод на DX9.
PilatP писал(а):по поводу текстур, мне их генерирует в таком виде программа Crazybump! Очень хорошая можно сразу видеть что получается и саму текстуру, и в 3D виде, если нужно могу скинуть

У меня есть, иногда пользуюсь.

PilatP
Продвинутый пользователь
Продвинутый пользователь
Аватара пользователя
 
Сообщения: 117
Зарегистрирован: 24.08.2009 (Пн) 1:00
Откуда: Херсон

Re: Шейдеры с нуля

Сообщение PilatP » 23.08.2014 (Сб) 0:22

по поводу камеры вот к примеру у тебя скачал пример World (land+вода + облака) и он мне очень подходит, и много есть уже готового, что очень здорово.
И очень хороший пример как это делается на шейдерах, но вот к примеру

Код: Выделить всё
Private Sub Moving()
  Dim v As D3DVECTOR
  Dim Mtrx As D3DMATRIX
  Vec3Scale CamVS, CamVS, dTime * Speed
  Vec3Add CamPos, CamPos, CamVS
  CamPos.y = LS.GetHeight(CamPos.x, CamPos.z) + 0.3
End Sub

Public Sub CameraSetMain()
  Dim Mtrx As D3DMATRIX
  MatrixLookAtLH Mtrx, CamPos, Vec3(CamPos.x + SinA * CosD, CamPos.y + SinD, CamPos.z + CosA * CosD), Vec3(0, 1, 0)
  Dev.SetTransform D3DTS_VIEW, Mtrx
End Sub

Public Sub CameraSetRefl()
  Dim Mtrx As D3DMATRIX
  MatrixLookAtLH Mtrx, Vec3(CamPos.x, -CamPos.y, CamPos.z), Vec3(CamPos.x + SinA * CosD, -CamPos.y - SinD, CamPos.z + CosA * CosD), Vec3(0, 1, 0)
  Dev.SetTransform D3DTS_VIEW, Mtrx
End Sub


это для камеры, пытался переделать под обычную типа

Код: Выделить всё
Public Sub SetCam()
Dim t_y As Single
    If LS_enable = True Then t_y = LS.GetHeight(CamPos.X, CamPos.z)
            CamPos.y = t_y + HH
    If t_y > CamPos.y Then CamPos.y = t_y + 5
  D3DXMatrixRotationX matView, pitch
  d3dDevice.SetTransform D3DTS_VIEW, matView

  D3DXMatrixRotationY matView, Angle
  d3dDevice.MultiplyTransform D3DTS_VIEW, matView
 
  D3DXMatrixTranslation matView, -CamPos.X, -CamPos.y, -CamPos.z
  d3dDevice.MultiplyTransform D3DTS_VIEW, matView
            D3DXMatrixIdentity matWorld
            d3dDevice.SetTransform D3DTS_WORLD, matWorld
End Sub


ничего не получилось.

и отрисовка на экран,спору нет выглядит очень красиво,но через рендер в текстуру что мне не подходит.
я понимаю что тут, ты добавил эффекты через шейдер
но мне например нужно отлавливать положение курсора на ланде.

Код: Выделить всё
  Dev.SetRenderTarget 0, SurfMain
  If Dev.BeginScene Then
    Dev.SetRenderState D3DRS_ZENABLE, D3D_FALSE
    Dev.SetSamplerState 0, D3DSAMP_ADDRESSU, D3DTADDRESS_MIRROR
    Dev.SetSamplerState 0, D3DSAMP_ADDRESSV, D3DTADDRESS_MIRROR
    Dev.SetSamplerState 1, D3DSAMP_ADDRESSU, D3DTADDRESS_MIRROR
    Dev.SetSamplerState 1, D3DSAMP_ADDRESSV, D3DTADDRESS_MIRROR
    Dev.SetTexture 0, TexUp
    Dev.SetTexture 1, TexDown
    Dev.SetTexture 2, TexWater
    Dev.SetFVF vFVF
    Dev.SetStreamSource 0, VB, 0, vSize
    Dev.SetPixelShader PS
    Dev.DrawPrimitive D3DPT_TRIANGLESTRIP, 0, 2
    Dev.SetPixelShader Nothing
    Dev.SetSamplerState 0, D3DSAMP_ADDRESSU, D3DTADDRESS_WRAP
    Dev.SetSamplerState 0, D3DSAMP_ADDRESSV, D3DTADDRESS_WRAP
    Dev.SetSamplerState 1, D3DSAMP_ADDRESSU, D3DTADDRESS_WRAP
    Dev.SetSamplerState 1, D3DSAMP_ADDRESSV, D3DTADDRESS_WRAP
    Dev.SetRenderState D3DRS_ZENABLE, D3D_TRUE
    Dev.EndScene
  End If
  Dev.Present
End Sub


тут много моментов что не знаю как изменить.

Со спрайтами то как раз не очень сложно, я о них вспомнил, просто по тому что удобно, а их нет.
По поводу мешей, я с тобой согласен, что в чистом виде к ним красоту не прилепить, и нужно перегонять в вертексы

а по поводу StrPtr то во код в строке
Res = GdipCreateBitmapFromFile(StrPtr(fName), Bmp)

Код: Выделить всё
Public Function GDIPLoadPicture(fName As String, ar() As Long) As Boolean
  Dim Res As Long
  Dim tSI As GdiplusStartupInput
  Dim GDIP As Long
  Dim Bmp As Long
  Dim lData As BitmapData
  Dim r As RECTL
  Dim x As Long, y As Long
 
  tSI.GdiplusVersion = 1
  Res = GdiplusStartup(GDIP, tSI)
  If Res = 0 Then
    [u]Res = GdipCreateBitmapFromFile(StrPtr(fName), Bmp)[/u]
    If Res = 0 Then
      GdipGetImageWidth Bmp, x
      GdipGetImageHeight Bmp, y
      r.Left = 0
      r.Right = x
      r.Top = 0
      r.Bottom = y
      Res = GdipBitmapLockBits(Bmp, r, ImageLockModeRead, PixelFormat32bppARGB, lData)
      If Res = 0 Then
        ReDim ar(x * y - 1)
        CopyMemory ar(0), ByVal lData.scan0, x * y * 4
        GDIPLoadPicture = True
        GdipBitmapUnlockBits Bmp, lData
      End If
      GdipDisposeImage Bmp
    End If
    GdiplusShutdown GDIP
  End If
End Function

я понимаю что он делает, но не понятно, можно ли без него? но думаю что нет вот по тому и не привычно

вот например такой вопрос можно ли сделать твой пример Word, с той камерой что я вывел в примере :oops: , и с простым рендером, не в текстуру, во первых мешает редактировать :oops: , во вторых на старой видяхе Geforce 8500 256мб честно говоря были проблемы, часто не было отрисовки, то есть черный экран и полоса на диагональ, а в верху мелькала видимо отрисовка кадра, полоска в 5 пикселей

Честно говоря,Mikle я очень признателен за помощь.
У вас нет доступа для просмотра вложений в этом сообщении.
Я не волшебник, я только учусь)

Mikle
Изобретатель велосипедов
Изобретатель велосипедов
Аватара пользователя
 
Сообщения: 4148
Зарегистрирован: 25.03.2003 (Вт) 14:02
Откуда: Туапсе

Re: Шейдеры с нуля

Сообщение Mikle » 23.08.2014 (Сб) 9:28

PilatP писал(а):а по поводу StrPtr то во код в строке
Res = GdipCreateBitmapFromFile(StrPtr(fName), Bmp)

Ясно, это из старой версии на GDI+. Сейчас уже нет этого.
По поводу остального отвечу позже, скорее всего - к вечеру в воскресенье, сейчас работаю.

PilatP
Продвинутый пользователь
Продвинутый пользователь
Аватара пользователя
 
Сообщения: 117
Зарегистрирован: 24.08.2009 (Пн) 1:00
Откуда: Херсон

Re: Шейдеры с нуля

Сообщение PilatP » 23.08.2014 (Сб) 11:05

Ну, у меня есть только эта версия, спасибо за оперативность, я подожду.
Я не волшебник, я только учусь)

Mikle
Изобретатель велосипедов
Изобретатель велосипедов
Аватара пользователя
 
Сообщения: 4148
Зарегистрирован: 25.03.2003 (Вт) 14:02
Откуда: Туапсе

Re: Шейдеры с нуля

Сообщение Mikle » 25.08.2014 (Пн) 9:43

PilatP писал(а):можно ли сделать твой пример Word, с той камерой что я вывел в примере , и с простым рендером, не в текстуру

Без рендера в текстуру не сделать ни отражений, ни преломлений. Если воду убрать - то проблем нет. А рендер в текстуру, как мы тут раньше уже выяснили, на dx8vb реализован криво, то есть перевод осложнится не только версией шейдеров, но и этим.
Артефакты при работе на некоторых системах могут быть вызваны тем, что демка работает в оконном режиме, просто окно без бордюра и развёрнуто на весь экран. Полноэкранный режим более устойчив, но оконный проще в отладке.
Вообще, есть более продвинутая версия этой демки вот в этой статье:
http://www.uraldev.ru/articles/id/37
Это тоже ещё на старой версии dx_vb, использующей gdi+, но в отражениях и преломлениях убраны артефакты. Там нет динамического света и облаков - статья не об этом, но всё это легко прикручивается.
А последнюю версию dx_vb можно взять тут:
http://mikle.ucoz.com/load/dx_vb_port_d ... _6/1-1-0-7
Мне пока не ясно, какова твоя конечная цель.
Вот пример простой камеры с ландшафтом, тут нет ничего лишнего, проще разобраться именно с камерой. Два примера - от 1-го лица и от 3-го лица из-за спины ГГ:
У вас нет доступа для просмотра вложений в этом сообщении.

PilatP
Продвинутый пользователь
Продвинутый пользователь
Аватара пользователя
 
Сообщения: 117
Зарегистрирован: 24.08.2009 (Пн) 1:00
Откуда: Херсон

Re: Шейдеры с нуля

Сообщение PilatP » 25.08.2014 (Пн) 10:27

Примеры, просто супер. В общем вода мне и не нужна особо, в моем случае.
Проектов в общем несколько, 1 редактор ландшафта, 2 игра (Airoport).

1 редактор ланд, у меня уже почти есть(основные функции для ланда уже есть, сглаживание, высота уровня, создание карты стат моделей), но он на дх8, и хочется прикрутить туда шейдеры, по описному выше варианту, как для ланда так и для мешей.

2 с игрой проще, все что сделано будет в ланде, будет применено и для игры.

вот вопрос
это реализация у тебя камеры
Код: Выделить всё
Vec3Scale CamVS, CamVS, dTime * Speed
  Vec3Add CamPos, CamPos, CamVS
  CamPos.y = LS.GetHeight(CamPos.x, CamPos.z) + CamHeight

[b] MatrixLookAtLH Mtrx, CamPos, Vec3(CamPos.x + SinA * CosD, CamPos.y + SinD, CamPos.z + CosA * CosD), Vec3(0, 1, 0)[/b]
  Dev.SetTransform D3DTS_VIEW, Mtrx


мне не понятно, почему используется
Код: Выделить всё
  [b]MatrixLookAtLH[/b]

а не
Код: Выделить всё
[b]D3DXMatrixTranslation matView, -CamPos.X, -CamPos.y, -CamPos.z
  d3dDevice.MultiplyTransform D3DTS_VIEW, matView[/b]

или это просто особенность реализации в твоей .dll так?

еще вопрос, как быть с шрифтами, у тебя фпс выводится в лабел, на сколько я понимаю dll, не поддерживает GameFont As D3DXFont?
на сколько я помню в одном из примеров у тебя было реализовано рендер текста в текстуру. можно ли как нить использовать шрифты в системе ttf
Последний раз редактировалось PilatP 03.09.2014 (Ср) 14:32, всего редактировалось 2 раз(а).
Я не волшебник, я только учусь)

Mikle
Изобретатель велосипедов
Изобретатель велосипедов
Аватара пользователя
 
Сообщения: 4148
Зарегистрирован: 25.03.2003 (Вт) 14:02
Откуда: Туапсе

Re: Шейдеры с нуля

Сообщение Mikle » 25.08.2014 (Пн) 10:59

По поводу рендера текста - посмотри, как оно сделано в игре AoS2:
http://mikle.ucoz.com/load/0-0-0-8-20
Остальное посмотрю чуть позже, когда доберусь до компа с бейсиком.

PilatP
Продвинутый пользователь
Продвинутый пользователь
Аватара пользователя
 
Сообщения: 117
Зарегистрирован: 24.08.2009 (Пн) 1:00
Откуда: Херсон

Re: Шейдеры с нуля

Сообщение PilatP » 25.08.2014 (Пн) 11:58

Честно говоря, как по мне не очень удобно, во первых как быть если нужно выводить, текст разной длины? Я делал когда то вывод через текстуру, с tu-tv, а текстуру делал в фотошопе ,правда было нужно выверять tu-tv.
но был плюс что выверка делается один раз.
Может есть более рациональные методы
Я не волшебник, я только учусь)

Mikle
Изобретатель велосипедов
Изобретатель велосипедов
Аватара пользователя
 
Сообщения: 4148
Зарегистрирован: 25.03.2003 (Вт) 14:02
Откуда: Туапсе

Re: Шейдеры с нуля

Сообщение Mikle » 25.08.2014 (Пн) 13:42

PilatP писал(а):как быть если нужно выводить, текст разной длины?

Проверять длину и менять, если надо, размер. Как-то так и D3DX делает, только это непроизводительно, лучше сразу задавать максимально возможных размер текстуры и битмапа, в который производится рендер, а потом смотреть размер надписи по факту и использовать соответствующую часть для рендера.
PilatP писал(а):мне не понятно, почему используется MatrixLookAtLH
а не
D3DXMatrixTranslation matView, -CamPos.X, -CamPos.y, -CamPos.z
d3dDevice.MultiplyTransform D3DTS_VIEW, matView
или это просто особенность реализации в твоей .dll так?

К dll это не имеет отношения, так же можно и в DX8 делать. Нужно понять смысл матриц трансформации:
World - трансформирует выводимую геометрию.
View - трансформирует положение камеры, это обратно трансформации выводимой геометрии,
если мы отодвинули объект на 3 вперёд - это аналогично тому, что камера отодвинулась на 3 назад,
если мы повернули объект вокруг некоторой оси на угол А - это то же самое, что повернуть камеру вокруг той же оси на -А.
То есть это тоже можно считать трансформацией геометрии, но трансформацией противоположного действия.
Proj - и это тоже фактически трансформация выводимой геометрии. Для задания перспективы, сюда загоняют матрицу, описывающую перспективу (уменьшение размеров по X, Z при удалении). Но никто не заставляет сюда записывать именно такую матрицу.
То есть World View и Proj - это условности, для удобства, фактически используется ОДНА матрица, для её получения достаточно перемножить World * View * Proj, при использовании вертексных шейдеров так и делается, там нет отдельных трансформаций, мы сами рассчитываем ОДНУ матрицу как хотим, а затем передаём её в шейдер.

PilatP
Продвинутый пользователь
Продвинутый пользователь
Аватара пользователя
 
Сообщения: 117
Зарегистрирован: 24.08.2009 (Пн) 1:00
Откуда: Херсон

Re: Шейдеры с нуля

Сообщение PilatP » 25.08.2014 (Пн) 14:21

По поводу матриц, я не все конечно понял до конца. Но с ними я потом постараюсь разобраться.
К стати 1 вариант word то что доктор прописал, 2 тоже супер я думаю тоже очень пригодится. теперь осталось к нему прикрутить шейдеры
с чего собственно и началась сама тема. На сколько я понял теперь можно использовать Ps 2.0?
Я не волшебник, я только учусь)

Mikle
Изобретатель велосипедов
Изобретатель велосипедов
Аватара пользователя
 
Сообщения: 4148
Зарегистрирован: 25.03.2003 (Вт) 14:02
Откуда: Туапсе

Re: Шейдеры с нуля

Сообщение Mikle » 25.08.2014 (Пн) 21:48

PilatP писал(а): На сколько я понял теперь можно использовать Ps 2.0?

Можно, можно и 3.0.
Вот перевод на шейдеры, пояснения чуть позже, лучше если будут конкретные вопросы.
У вас нет доступа для просмотра вложений в этом сообщении.

Mikle
Изобретатель велосипедов
Изобретатель велосипедов
Аватара пользователя
 
Сообщения: 4148
Зарегистрирован: 25.03.2003 (Вт) 14:02
Откуда: Туапсе

Работа с шейдерами.

Сообщение Mikle » 26.08.2014 (Вт) 8:56

При использовании шейдеров перестают работать свет, материалы, трансформации, стадии FFP текстурирования, туман. Остаётся Z-буфер и альфаналожение, выборка из текстур (семплирование), плоскости отсечения. Я не пугаю :), на самом деле всё стало на много проще. Как это в общем работает:

Мы по прежнему готовим вертексные и индексные буферы и отправляем их на растеризацию. Данные вертексов поступают на обработку в вертексный шейдер. Если при FFP разные типы данных вертексов (позиция, нормаль, текстурные координаты и т. п.) могли идти только в строго определённом порядке, то теперь можно размещать их в любом удобном порядке. Раньше мы описывали формат вертекса набором флагов, к примеру D3DFVF_XYZ Or D3DFVF_Tex1, теперь мы описываем формат с помощью VertexDeclaration (см. в примере). В DX8 мы и вертексный шейдер, и FVF, "загоняли" в девайс одной и той же командой SetVertexShader, это вызывало путаницу, в DX9 для флагов FVF есть отдельная команда SetFVF, при использовании шейдеров она не нужна. Итак, мы описали вертекс, теперь нужно написать шейдер - это по прежнему программа, переводящая данные вертекса в "приведённый" формат, необходимый для растеризации.

У шейдера есть:
входные регистры - это данные вертекса,
выходные регистры - приведённые данные,
временные регистры - для временного хранения данных и расчётов.
константы - их можно задавать при написании шейдера при помощи def либо перед вызовом шейдера с помощью SetVertexShaderConstant. В примере Diffuse и Ambient заданы в шейдере, а матрица WVP (World*View*Proj) задаётся с помощью SetVertexShaderConstant потому, что она должна меняться в зависимости от позиций камеры и рисуемого объекта.
В примере умножается только View на Proj и не фигурирует World потому, что ландшафт неподвижен и расположен от начала координат без всяких масштабирований, поворотов и т. п.

Выходные данные вертексного шейдера не являются входными для пиксельного. После вертексного шейдера идёт отсечение по пирамиде видимости и плоскостями отсечения (если задать их), это всё делает растеризатор без нашего участия. Далее растеризатор рисует треугольники, данные вершин треугольника интерполируются по его площади, но не линейно, а с учётом весовых коэффициентов (координата w в позиции). Если мы напишем такой вертексный шейдер, который будет давать во все выходные регистры одинаковое значение w - то интерполяция будет линейной. После интерполяции растеризатор проверит видимость каждого пикселя по ZBuffer (если ZBuffer включен) и, если пиксель не скрыт, для пикселя вызывается пиксельный шейдер.
И вот эти интерполированные данные поступают на вход пиксельного шейдера в его входные регистры. Пиксельный шейдер, как и вертексный, имеет входные регистры,
выходные регистры, временные регистры и константы, и смысл их работы похож, а нашей задачей является вычислить цвет пикселя и отправить его в выходной регистр oC0.
Если включен альфаблендинг, то после работы пиксельного шейдера произойдёт альфаналожение на уже имеющееся в бэкбуфере изображение.

PilatP
Продвинутый пользователь
Продвинутый пользователь
Аватара пользователя
 
Сообщения: 117
Зарегистрирован: 24.08.2009 (Пн) 1:00
Откуда: Херсон

Re: Шейдеры с нуля

Сообщение PilatP » 28.08.2014 (Чт) 1:11

Это вроде понятно, но теория теорией, а на практике всегда иначе, Mikle если не сложно то можно с простых примеров, типа (1текстура),(1текстура+ difuse) и тд.

да еще вот
Код: Выделить всё
vsDecl(0) = VertexElement(0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0)
  vsDecl(1) = VertexElement(0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0)
  vsDecl(2) = VertexElement(0, 24, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0)
  vsDecl(3) = VertexElement(0, 32, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 1)
  vsDecl(4) = VertexElementEnd


это насколько я понял обьявление вертексных констант, но интересно почему, в каждой строке идет инкремент +12 (0, 12, D3DDECLTYPE) почему?

Код: Выделить всё
D3DDECLTYPE_FLOAT3-это типа Vec3
D3DDECLTYPE_FLOAT2-это типа Vec2

VertexElementEnd-это я так понял обязательный атрибут в конце
Последний раз редактировалось PilatP 03.09.2014 (Ср) 14:32, всего редактировалось 1 раз.
Я не волшебник, я только учусь)

Mikle
Изобретатель велосипедов
Изобретатель велосипедов
Аватара пользователя
 
Сообщения: 4148
Зарегистрирован: 25.03.2003 (Вт) 14:02
Откуда: Туапсе

Re: Шейдеры с нуля

Сообщение Mikle » 28.08.2014 (Чт) 8:12

PilatP писал(а):в каждой строке идет инкремент +12 (0, 12, D3DDECLTYPE) почему?

Не в каждой. Идёт инкремент на размер предыдущего элемента вертекса в байтах, vsDecl(3) от vsDecl(2) отличается на 8.
PilatP писал(а):D3DDECLTYPE_FLOAT3-это типа Vec3
D3DDECLTYPE_FLOAT2-это типа Vec2

Почти. Просто вектор - это обязательно связанные по смыслу, равноправные величины. А тут просто количество и тип величин. Мы, к примеру, можем через один Vec4 передать две текстурные координаты, альфу и Weight для блендинга.
PilatP писал(а):VertexElementEnd-это я так понял обязательный атрибут в конце

Да.
PilatP писал(а):можно с простых примеров, типа (1текстура),(1текстура+ difuse) и тд.

Хорошо. Тогда я для этого сделаю другой тестовый пример и на нём буду всё демонстрировать, ландшафт - не совсем типичный случай, та же его неподвижность всё упрощает.

PilatP
Продвинутый пользователь
Продвинутый пользователь
Аватара пользователя
 
Сообщения: 117
Зарегистрирован: 24.08.2009 (Пн) 1:00
Откуда: Херсон

Re: Шейдеры с нуля

Сообщение PilatP » 28.08.2014 (Чт) 20:24

Mikle, если не сложно, то можно всеже с ландшафтом.
:oops: будет супер если будет пусть маленкий 30*30 вертексов
и динамическое освещение типа вращающегося по кругу(эфект солнца)
чтото типа.

Код: Выделить всё
LightPos.X = -(((Karta.Land_X * Karta.Land_ScaleXZ) / 2) - Sin(((tHour * 60) + tMinut) / 230) * (Karta.Land_X * Karta.Land_ScaleXZ))
    LightPos.y = -(((Karta.Land_X * Karta.Land_ScaleXZ) / 2) - Cos(((tHour * 60) + tMinut) / 230) * (Karta.Land_X * Karta.Land_ScaleXZ))
    LightPos.z = ((Karta.Land_Z * Karta.Land_ScaleXZ) / 2)
    Light.Direction = LightPos


:oops: это код из моего проекта, типа движение освещения по часам
И вообще шик, если на нем будет обьект например куб.

:oops: наглость конечно второе счастье, но просто на таком примере много моментов будут всплывать сами, и наглядней будет, все же много кто делает динамическое освещение, и может кому исходник пригодится

Mikle писал(а):Не в каждой. Идёт инкремент на размер предыдущего элемента вертекса в байтах, vsDecl(3) от vsDecl(2) отличается на 8.

да сразу и не увидел.
Последний раз редактировалось PilatP 03.09.2014 (Ср) 14:30, всего редактировалось 1 раз.
Я не волшебник, я только учусь)

Mikle
Изобретатель велосипедов
Изобретатель велосипедов
Аватара пользователя
 
Сообщения: 4148
Зарегистрирован: 25.03.2003 (Вт) 14:02
Откуда: Туапсе

Re: Шейдеры с нуля

Сообщение Mikle » 29.08.2014 (Пт) 14:24

PilatP писал(а):будет супер если будет пусть маленкий 30*30 вертексов
и динамическое освещение типа вращающегося по кругу(эфект солнца)
чтото типа.

Размер значения не имеет.
PilatP писал(а):И вообще шик, если на нем будет обьект например куб.

Согласен, только что-нибудь по-сложнее, криволинейное, хоть даже чайник.
Только это всё откладывается примерно до вторника, к 1 сентября много работы.

PilatP
Продвинутый пользователь
Продвинутый пользователь
Аватара пользователя
 
Сообщения: 117
Зарегистрирован: 24.08.2009 (Пн) 1:00
Откуда: Херсон

Re: Шейдеры с нуля

Сообщение PilatP » 29.08.2014 (Пт) 19:16

Супер, я жду с не терпением
Кстати рылся у себя в исходниках, и нашол такой пример динамических теней, заглянь. может пригодится, где нарыл не помню. Кстати неплохо было бы их тоже использовать.
У вас нет доступа для просмотра вложений в этом сообщении.
Я не волшебник, я только учусь)

Mikle
Изобретатель велосипедов
Изобретатель велосипедов
Аватара пользователя
 
Сообщения: 4148
Зарегистрирован: 25.03.2003 (Вт) 14:02
Откуда: Туапсе

Re: Шейдеры с нуля

Сообщение Mikle » 03.09.2014 (Ср) 9:55

Я помню :) Только освободился, ваяю пример.
PS.
PilatP, старайся на будущее код в своих сообщениях оформлять соответствующим тегом, а то посты трудночитаемы.

PilatP
Продвинутый пользователь
Продвинутый пользователь
Аватара пользователя
 
Сообщения: 117
Зарегистрирован: 24.08.2009 (Пн) 1:00
Откуда: Херсон

Re: Шейдеры с нуля

Сообщение PilatP » 03.09.2014 (Ср) 14:30

Mikle :oops: сообщения поправил, в дальнейшем исправлюсь
Я не волшебник, я только учусь)

Mikle
Изобретатель велосипедов
Изобретатель велосипедов
Аватара пользователя
 
Сообщения: 4148
Зарегистрирован: 25.03.2003 (Вт) 14:02
Откуда: Туапсе

Re: Шейдеры с нуля

Сообщение Mikle » 03.09.2014 (Ср) 16:24

Итак, пример: https://yadi.sk/d/LYo8mirXaww3V
Тут пока свет только Diffuse и Ambient, разберёмся с этим - прикрутим Specular, это сложнее.
В вертексный шейдер мы передаём константы:

1. c0..c3 - matrix WorldVievProj, так как одна шейдерная константа - это 4 Float значения, на матрицу тратятся 4 константы, с c0 до c3.
Шейдерные инструкции умножения векторов на матрицы используют матрицы в несколько ином виде - строки со столбцами поменяны, поэтому перед передачей в шейдер матрица транспонируется:
Код: Выделить всё
MatrixTranspose Mtrx, Mtrx


2. В c4 мы передаём направление на источник света. Значение Diffuse вычисляют, как скалярное произведение (инструкция dp3) нормали на направление на источник света (и далее умножаем на сам цвет в константе Diffuse). В случае с ландшафтом - всё просто, так как ландшафт неподвижен, но модели мы двигаем, масштабируем, а главное - поворачиваем. После поворота модели нормаль будет направлена уже в другом направлении, однако её значение в вертексе не меняется. Решение "в лоб" - в шейдере рассчитывать поворот нормали, это ещё одно умножение вектора на матрицу, только не m4x4, а m3x3. Для этого в шейдер ещё придётся передавать матрицу World для модели.
Вместо этого применяют другой приём - передают в шейдер не мировое значение вектора направления света, а значение в системе координат модели. То есть вместо того, чтобы пересчитывать нормали в вертексах (их много), мы пересчитывает направление на источник света (он один). Чтобы пересчитать направление вектора в пространстве модели, достаточно умножить этот вектор на инвертированную мировую матрицу модели, что мы и делаем в классе cMesh:
Код: Выделить всё
  MatrixInverse Mtrx, 0, mWorld
  Vec3TransformNormal v3, DirToLight, Mtrx


3. и 4. - сами значения цветов Diffuse и Ambient. Их использование в шейдере:
dp3 r0, v1, c4 - вычислили скалярное произведение, но оно бывает отрицательным, а яркость света отрицательной не бывает, его нужно ограничить значением 0:
max r0, r0, c4.a - обрати внимание, в c4.a мы поместили значение 0 в коде: v4 = Vec4(v3.x, v3.y, v3.z, 0), то есть, передавая направление на свет, мы так же через c4.a передали константу 0, ведь направление - это 3D вектор, четвёртый компонент не занят, мы его задействовали, чтобы не тратить отдельную константу.
mul r0, r0, c5 - умножили яркость Diffuse на цвет Diffuse.
add oD0, r0, c6 - к полученному добавили Ambient.

В пиксельном шейдере пока всё очень просто:
texld r0, t0, s0 - "семплируем", то есть читаем в регистр r0 по текстурным координатам t0 текстуру s0. То есть, начиная с шейдеров 2.0, у нас уже нет последовательных текстурных стадий - мы читаем текстуру с любым индексом, используя текстурные координаты так же с любым индексом. А текстурные координаты можно ещё и как угодно перерасчитать перед использованием, но это - позже.
mul r0, r0, v0 - умножаем полученный из текстуры цвет на Diffuse + Ambient.
mov oC0, r0 - полученную величину выводим на экран (точнее в бэкбуфер)

PilatP
Продвинутый пользователь
Продвинутый пользователь
Аватара пользователя
 
Сообщения: 117
Зарегистрирован: 24.08.2009 (Пн) 1:00
Откуда: Херсон

Re: Шейдеры с нуля

Сообщение PilatP » 04.09.2014 (Чт) 11:15

Mikle спасибо за оперативность, с шейдерами теперь более менее понятно. :D
буду с нетерпением ждать продолжения
Я не волшебник, я только учусь)

Mikle
Изобретатель велосипедов
Изобретатель велосипедов
Аватара пользователя
 
Сообщения: 4148
Зарегистрирован: 25.03.2003 (Вт) 14:02
Откуда: Туапсе

Re: Шейдеры с нуля

Сообщение Mikle » 05.09.2014 (Пт) 9:46

Спекуляр - это имитация отражения источника света от поверхности, имеющей некоторую шероховатость. Если поверхность абсолютно гладкая - то для точечного источника света мы бы получили яркие точки отражений на тех местах, где угол падения равен углу отражения, то есть угол между нормалью и вектором на свет равен углу между нормалью и вектором на камеру, и эти вектора лежат в одной плоскости.
Чтобы проверить это соответствие, можно использовать кучу разных способов, пробуем первый:
Если нормализовать вектора на свет и на камеру, а потом их сложить, то полученный вектор как раз будет биссектрисой угла свет-объект-камера, то есть угол падения равен углу отражения, и всё это в одной плоскости. Остаётся проверять, на сколько этот суммарный вектор совпадает с нормалью, для этого суммарный вектор нормализуем. Два нормализованных вектора совпадают, если их скалярное произведение равно единице, чем сильнее отличаются вектора - тем меньше скалярное произведение, у перпендикулярных векторов скалярное произведение равно нулю, у противоположных - минус единице. Значения в выходных регистрах oD0 и oD1 предназначены для света, поэтому автоматически ограничиваются диапазоном 0..1, то есть мы можем не беспокоиться об отрицательных значениях - они заменятся нулём. При таком расчёте получится отражение от очень шероховатой поверхности, где яркость падает до нуля, когда угол равен Pi/2. Чтобы сделать поверхность более гладкой - нужно брать диапазон значений, более близкий к единице, например 0.75..1. Если просто ограничить величину этими значениями - свет на краях блика будет резко исчезать, что неестественно. Нужно чтобы яркость к краям стремилась к нулю. Очевидно, что чтобы привести диапазон 0.75..1 к 0..1, нужно величину умножить на 4 и вычесть 3, можно умножить на любое число >1 и вычесть на единицу меньшее, чем больше число - тем более гладкой получается поверхность, более отчётливым блик. Но не нужно забывать, что все эти расчёты мы производим в вертексном шейдере, значения вычисляются только для вершин треугольников и интерполируются внутри него, блик меньше треугольника мы всё равно не получим, при слишком большом значении мы увидим искажения, станут заметны отдельные треугольники в геометрии. Чтобы делать на низкополигональной геометрии чёткие, почти зеркальные блики - нужно расчёты переносить в пиксельный шейдер, что сильно увеличит нагрузку на видеокарту. Но об этом потом... может быть.
Итак, с теорией ясно, практика:
Добавляем в код на бейсике переменную для спекуляра:
Код: Выделить всё
Public Specular As D3DVECTOR

Даём ей некоторое значение:
Код: Выделить всё
Specular = Vec3(0.8, 0.8, 0.7)

Передаём Specular в шейдер, как мы передавали Diffuse и Ambient:
Код: Выделить всё
Dev.SetVertexShaderConstantF 7, VarPtr(Specular), 1

Так же нам теперь требуется направление на камеру, но, в отличие от направления на бесконечно удалённый источник света, направление на камеру для каждого вертекса будет разным, поэтому передаём в шейдер не направление, а позицию камеры, направление будем вычислять в шейдере. Так же, как и для направления на свет, пересчитываем позицию в локальную систему координат модели - умножаем на ту же инвертированную мировую матрицу модели, только сам тип умножения для позиций применяется не тот, что для направлений:
Код: Выделить всё
Vec3TransformCoord v3, CamPos, Mtrx
Dev.SetVertexShaderConstantF 8, VarPtr(v3), 1


С кодом на бейсике всё, остальное - в шейдерах. В вертексном:
sub r1, c8, v0 - вычли из позиции камеры позицию вертекса, то есть нашли направление на камеру.
nrm r2, r1.xyz - нормализовали его.
add r1, c4, r2 - сложили с направлением на свет.
nrm r2, r1.xyz - нормализовали, получили вектор для сравнения с нормалью.
dp3 r1, r2, v1 - сравниваем.
mad r1, r1, c9.x, c9.y - умножаем на c9.x (=4) и прибавляем c9.y (=-3), то есть вычитаем 3. Добавили гладкость. Я константу c9 задал непосредственно в шейдере просто для примера, её можно передавать в шейдер так же, как и все остальные константы.
mul oD1, r1, c7 - домножили на цвет спекуляра и отправили в выходной регистр oD1, это значение после интерполяции попадёт в пиксельный шейдер во входной регистр v1.

В пиксельном шейдере добавили всего две строки кода:
mul r1, r0.a, v1 - домножили цвет спекуляра на его яркость для данной точки, взятую из карты (Specular Map), находящейся в альфаканале текстуры. (Обрати внимание, в текстуре есть альфаканал, хотя прозрачность мы не используем).
add r0, r0, r1 - прибавили к вычисленному цвету пикселя цвет спекуляра перед отправкой в бэкбуфер.

Вроде всё, остальное не отличается от предыдущего примера. Жду вопросы.
Проект: https://yadi.sk/d/P7j1blXcb4pbZ

PilatP
Продвинутый пользователь
Продвинутый пользователь
Аватара пользователя
 
Сообщения: 117
Зарегистрирован: 24.08.2009 (Пн) 1:00
Откуда: Херсон

Re: Шейдеры с нуля

Сообщение PilatP » 05.09.2014 (Пт) 18:35

Спасибо, Mikle за теорию, всего конечно я не понял, но в общем теперь куда понятней, чем было.
честно говоря читал я книгу и на форумах тоже, но у тебя оптимально понятно, :D для 3 по геометрии :oops:
Теперь вопросы

Даём ей некоторое значение:
Код: Выделить всё
Specular = Vec3(0.8, 0.8, 0.7)

я не понял откуда взялись эти цифры, или ты их просто так подставил?

В пиксельном шейдере добавили всего две строки кода:
Код: Выделить всё
mul r1, r0.a, v1
- домножили цвет спекуляра на его яркость для данной точки, взятую из карты (Specular Map), находящейся в альфаканале текстуры. (Обрати внимание, в текстуре есть альфаканал, хотя прозрачность мы не используем).


Ты используеш альфа канал, а как же текстура SPEC, я буду использовать ее, отсюда вопрос, как?
шейдер получает данные из r0.a мне на сколько я понял нужно тогда типа этого
Код: Выделить всё
mul r1, r2, v1
r2 тут будет текстура Specular

Еще вопрос, когда источник света повернулся
Захват-1.png

я отметил места тут должно быть затемнено, то есть свет проходит сквозь обьект
как исправить, и реально ли?

Да еще вопрос а как использовать текстуру NormalMap? Я понимаю так что она создана для придания текстуре объемности?
У вас нет доступа для просмотра вложений в этом сообщении.
Я не волшебник, я только учусь)

Mikle
Изобретатель велосипедов
Изобретатель велосипедов
Аватара пользователя
 
Сообщения: 4148
Зарегистрирован: 25.03.2003 (Вт) 14:02
Откуда: Туапсе

Re: Шейдеры с нуля

Сообщение Mikle » 05.09.2014 (Пт) 20:05

PilatP писал(а): откуда взялись эти цифры, или ты их просто так подставил?

Да, просто так. Это RGB величина, каждый компонент от 0 до 1. Замени, к примеру, на такое:
Код: Выделить всё
Specular = Vec3(0, 1, 0)

И блики станут зелёными.
PilatP писал(а):Ты используеш альфа канал, а как же текстура SPEC, я буду использовать ее, отсюда вопрос, как?

Ты верно написал:
Код: Выделить всё
mul r1, r2, v1

Только перед этим текстуру нужно будет прочитать в регистр r2, как-то так:
Код: Выделить всё
texld r2, t1, s1

или так, если вторая текстура использует те же текстурные координаты, что и первая:
Код: Выделить всё
texld r2, t0, s1

Ну и в VB коде нужна будет строка типа:
Код: Выделить всё
Dev.SetTexture 1, Tex1

PilatP писал(а):должно быть затемнено, то есть свет проходит сквозь обьект
как исправить, и реально ли?

Это уже гораздо сложнее, это - самозатенение.
На счёт использования NormalMap - для полноценного использования нужно все расчёты переносить в пиксельный шейдер, кроме того, модель должна иметь, кроме нормали ещё бинормаль и/или тангент. У меня таких моделей для примера нет. Я могу сгенерировать ландшафт с этими компонентами, но спекуляр для ландшафта не сильно нужен, да и ландшафт неподвижен, с ним проще. Могу на примере какого-нибудь кубика дать - но это же не то.

PilatP
Продвинутый пользователь
Продвинутый пользователь
Аватара пользователя
 
Сообщения: 117
Зарегистрирован: 24.08.2009 (Пн) 1:00
Откуда: Херсон

Re: Шейдеры с нуля

Сообщение PilatP » 06.09.2014 (Сб) 9:08

Mikle
кроме того, модель должна иметь, кроме нормали ещё бинормаль и/или тангент

честно говоря, я не понял, это что какой то генератор их генерирует (бинормаль и/или тангент)

Я могу сгенерировать ландшафт с этими компонентами
будет супер
Могу на примере какого-нибудь кубика дать
пример есть пример, и чем их меньше в сети, тем ценней он :wink:

вообще хочется добится такого
75390019159.png

тут видно, хорошо что пол шероховат
softshadows-screenshot_thumb_700_0.png
У вас нет доступа для просмотра вложений в этом сообщении.
Я не волшебник, я только учусь)

След.

Вернуться в Мультимедиа

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 35

    TopList