• News

• Industries

• Learning & Support

• Community

• Marketplace Small tutorial on the shader Im working with.

Ive found some time ago some hlsl scrips for a simple udk pbr shader and after some testing and making a small shading network for it, i wanted to place it here if someone wants to use it also.I suspect i made a few mistakes of using it correctly so feel free to try it.
Made a small video explaining more or less how it works and its pros and cons, and you get the chance to enjoy my engrish trough a cheap low volume microphone(apologies for that last one)

Also, It was very impractical of me, but i actually made this in udk 2014-08 and all most everyone here probably uses a older one.So watch the video and if its interesting, install udk 2014-08 and just copy paste the shading network to your udk(or do it by eye) as its not complex.

The HLSL i am using

float3 H = normalize(L + V);
float NdotL = saturate(dot(N, L));
float NdotH = dot(N, H);
float NdotV = dot(N, V);
float LdotH = dot(V, H);

float NdotH_2 = NdotH * NdotH;
float NdotH_4 = NdotH_2 * NdotH_2;
float m_2 = m * m;
float D = exp((NdotH_2 - 1.0) / (NdotH_2 * m_2));

float3 F = Ks + (1.0 - Ks) * pow(1.0 - LdotH, 5.0);

float G = saturate(2 * NdotH * min(NdotV, NdotL) / LdotH);

float3 Rs = (D * F * G) / (4 * m_2 * NdotH_4 * NdotV);

float gamma = saturate(dot(V - N * NdotV, L - N * NdotL));
float A = 1.0 - 0.5 * (m_2 / (m_2 + 0.33));
float B = 0.45 * (m_2 / (m_2 + 0.09));
float C = sqrt((1.0 - NdotV * NdotV) * (1.0 - NdotL * NdotL)) / max(NdotV, NdotL);

float3 Rd = Kd * (A + B * gamma * C) * (1 - Ks);

return Rs + Rd * NdotL;

And a aditional HLSL i used to use but decided to leave.It is more complex and uses Cook Torrance and Oren-Nayar.

float3 H = normalize(L + V);
float NdotL = saturate(dot(N, L));
float NdotV = dot(N, V);
float NdotH = dot(N, H);
float LdotH = dot(L, H);

float a_2 = a * a;
float NdotL_2 = NdotL * NdotL;
float NdotV_2 = NdotV * NdotV;
float NdotH_2 = NdotH * NdotH;
float OneMinusNdotL_2 = 1.0 - NdotL_2;
float OneMinusNdotV_2 = 1.0 - NdotV_2;

float D = NdotH_2 * (a_2 - 1.0) + 1.0;

float3 Fd = 1.0 - Ks;
float3 Fs = Ks + Fd * exp(-6 * LdotH);

float G1_1 = 1.0 + sqrt(1.0 + a_2 * (OneMinusNdotL_2 / NdotL_2));
float G1_2 = 1.0 + sqrt(1.0 + a_2 * (OneMinusNdotV_2 / NdotV_2));
float G = G1_1 * G1_2;

float gamma = saturate(dot(V - N * NdotV, L - N * NdotL));
float A = 1.0 - 0.5 * (a_2 / (a_2 + 0.33));
float B = 0.45 * (a_2 / (a_2 + 0.09));
float C = sqrt(OneMinusNdotL_2 * OneMinusNdotV_2) / max(NdotL, NdotV);
float OrenNayar = A + B * gamma * C;

float3 Rs = (a_2 * Fs) / (D * D * G * NdotV);
float3 Rd = Kd * Fd * OrenNayar;

return Rs + Rd * NdotL;

Also it is a good idea to blur your cube maps, unless you are using the dx11 image based reflections which give cool results but at a heavy price if you are not careful.

Google drive link, as the one from above will disappear in a month.