Страница 1 из 1

Расчёт нормали (аналог ddx/ddy)

СообщениеДобавлено: 14 окт 2017, 12:39
kripto289
День добрый.
Хочу сделать для воды с дисплейсментом по 3-м осям корректный расчёт нормали.
Расчет нормали по вершинам работает точно, но естественно зависит от кол-ва вершин на экране и не сглаживается.
Синтаксис:
Используется csharp
half3 n = normalize(cross(ddx(i.vertexPos.xyz), ddy(i.vertexPos.xyz)));


Хочу вынести расчёт нормали в отдельную текстуру (как делают все нормальные люди).
И тут я уже туплю второй день.
Просто нормаль по высоте (без учёта смещения) расчитываю так.
Синтаксис:
Используется csharp
       
                float s11 = tex2D(_DispTex, i.uv).y;
                float s01 = tex2D(_DispTex, i.uv + float2(-_DispTex_TexelSize.x, 0)).y;
                float s10 = tex2D(_DispTex, i.uv + float2(0, _DispTex_TexelSize.y)).y ;
                float3 va = (float3(float2(2, 0), s11 - s01));
                float3 vb = (float3(float2(0, 2), s11 - s10));
                float3 n= normalize(cross(va, vb));
 

Но у меня высота меняется ещё относительно координат xz. Я пробовал брать tex2D(_DispTex, i.uv).xyz, пробовал к uv добавлять смещение. Всё не корректно.
Как правильно рассчитать нормаль со смещением?

Re: Расчёт нормали (аналог ddx/ddy)

СообщениеДобавлено: 16 окт 2017, 08:03
jetyb

Re: Расчёт нормали (аналог ddx/ddy)

СообщениеДобавлено: 17 окт 2017, 05:52
kripto289
jetyb писал(а):http://www.rorydriscoll.com/2012/01/11/derivative-maps/

Эту ссылку и несколько страниц гугла по деривативам я перешерстил вдоволь. В статье не понятно что за карту градиента он использует. Как оказалось это дельта высоты в один пиксель. (нашёл где-то похожую логику работы на другом рерурсе)

Может кому пригодится. Это аналогично normalize(cross (ddx(v.vertex), ddy(v.vertex))), только сглаженные нормали;


Синтаксис:
Используется csharp
float3 displace = tex2D(_DispTex, i.uv).xyz;
float H_Right = tex2D(_DispTex, i.uv + float2(_DispTex_TexelSize.x, 0)).y;
float H_Up = tex2D(_DispTex, i.uv+ float2(0, _DispTex_TexelSize.y)).y;

float3 smoothNormal = CalculateSurfaceNormal(i.uv.xxy + displace , float3(0, 1, 0), float2(Right  - displace .y,  H_Up - displace .y) *_DispTex_TexelSize.z, i.uv);

float3 CalculateSurfaceNormal(float3 position, float3 normal, float2 gradient, float2 uv)
                {
                        float3 dpdx = ddx(position);
                        float3 dpdy = ddy(position);

                        float dhdx = gradient.x * ddx(uv.x) + gradient.y * ddx(uv.y);
                        float dhdy = gradient.x * ddy(uv.x) + gradient.y * ddy(uv.y);

                        float3 r1 = cross(dpdy, normal);
                        float3 r2 = cross(normal, dpdx);
                        return normalize(normal - (r1 * dhdx + r2 * dhdy) / dot(dpdx, r1));
                }
 


ps для ddx ddy на dx9 надо #pragma target 3.0. Но слава богу юнитеки в 2017.3 отказываются от этого убожества directx9.