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.
Link to udk:
Link to upk:
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.