That's why I was hoping someone can point out what I'm doing wrong or what I'm missing.

-> see below

**Edited by lipsryme, 03 November 2012 - 01:05 PM.**

5 replies to this topic

Posted 22 October 2012 - 12:16 PM

I'm trying to implement a microfacet brdf but my results are wrong somehow.

That's why I was hoping someone can point out what I'm doing wrong or what I'm missing.

-> see below

That's why I was hoping someone can point out what I'm doing wrong or what I'm missing.

-> see below

**Edited by lipsryme, 03 November 2012 - 01:05 PM.**

Portfolio/Blog: http://marcel-schindler.weebly.com

Posted 03 November 2012 - 12:16 PM

Actually doing it like that makes it not work at all.

My View direction is being calculated like this:

Have to say I got it working now with a phong distribution but anything else (the commented out part) gives me wrong results.

Beckmann or Trowbridge-Reitz doesn't...

My View direction is being calculated like this:

// Calculate Position from linear view space depth float3 ViewRay = input.PositionVS.xyz; float depth = DepthTarget.Sample(PointSampler, input.UV).r; float3 ViewDir = ViewRay * depth; // subtraction by the cam position not needed since we're already in view space

Have to say I got it working now with a phong distribution but anything else (the commented out part) gives me wrong results.

// Compute Fresnel Term (F) using Schlick's approximation float LdotH = max(0, dot(-L, H)); float base = 1 - LdotH; float exponent = pow(base, 5.0f); float3 F = saturate(SpecularAlbedo + (1 - SpecularAlbedo) * exponent); // Lambert float3 kd = NdotL; Lr.rgb += (kd / PI) * Ei; // Normalized Blinn-Phong distribution (D) float D = 0.0f; float NdotH = max(0, dot(N, H)); D = ((SpecularPower + 2) / 2 * PI) * pow(NdotH, SpecularPower); // Beckmann distribution (D) //float NdotH = max(0, dot(N, H)); //float NdotH2 = NdotH * NdotH; //float NdotH4 = NdotH * NdotH * NdotH * NdotH; //float SpecularPower2 = SpecularPower * SpecularPower; //float Beckmann_exponent = -((1 - NdotH2) / (SpecularPower2 * NdotH2)); //float D = 1 * exp(Beckmann_exponent) / PI * SpecularPower2 * NdotH4; // Trowbridge-Reitz (GGX) distribution //float NdotH = max(0, dot(N, H)); //float SpecPow2 = SpecularPower * SpecularPower; //float D = SpecPow2 / PI * pow(((NdotH*NdotH) * (SpecPow2 - 1) + 1), 2); // Cook-Torrance approximation (G) float NdotV = max(0, dot(N, V)); float G = 1.0f; float3 nominator = F * G * D; float denominator = 4 * ((LdotH+0.000001f) * (LdotH+0.000001f)); Ls.rgb += nominator / denominator;

Beckmann or Trowbridge-Reitz doesn't...

**Edited by lipsryme, 03 November 2012 - 01:06 PM.**

Portfolio/Blog: http://marcel-schindler.weebly.com

Posted 03 November 2012 - 08:27 PM

Pretty sure the Beckmann distribution is actually this (and same comment for GGX, I would guess):

This is my path tracer code for Beckmann, it uses a raw BRDF so you'll have to modify the inputs (the incident vector goes towards the surface, the exitant vector goes away from it). The vector * vector operation is the dot product. Also I'm not using the tangent formula trick yet whereas you seem to be.. sorry:

http://pastebin.com/pHqCH1dc

Might have gone overboard with the absolute values but I was dealing with refraction at the same time and didn't want to take risks

EDIT: dammit, why are the code tags munching my newlines?

EDIT: pastebin it is!

float D = 1 * exp(Beckmann_exponent) / (PI * SpecularPower2 * NdotH4);

This is my path tracer code for Beckmann, it uses a raw BRDF so you'll have to modify the inputs (the incident vector goes towards the surface, the exitant vector goes away from it). The vector * vector operation is the dot product. Also I'm not using the tangent formula trick yet whereas you seem to be.. sorry:

http://pastebin.com/pHqCH1dc

Might have gone overboard with the absolute values but I was dealing with refraction at the same time and didn't want to take risks

EDIT: dammit, why are the code tags munching my newlines?

EDIT: pastebin it is!

**Edited by Bacterius, 03 November 2012 - 08:39 PM.**

*“If I understand the standard right it is legal and safe to do this but the resulting value could be anything.”*

Posted 04 November 2012 - 05:01 PM

Your GGX distribution is missing a parenthesis. Everything should be in the denominator except the alpha^2. So the correct implementation would be:

float NdotH = max(0, dot(N, H));

float SpecPow2 = SpecularPower * SpecularPower;

float D = SpecPow2 / (PI * pow(((NdotH*NdotH) * (SpecPow2 - 1) + 1), 2));

Don't do it this way, you are wasting instructions this way. Do it like that:

float G = min(1, 2 * NdH / VdH * min(NdV, NdL));

float NdotH = max(0, dot(N, H));

float SpecPow2 = SpecularPower * SpecularPower;

float D = SpecPow2 / (PI * pow(((NdotH*NdotH) * (SpecPow2 - 1) + 1), 2));

float G = min(1, min(2 * NdH * NdV / VdH, 2 * NdH * NdL / VdH));

Don't do it this way, you are wasting instructions this way. Do it like that:

float G = min(1, 2 * NdH / VdH * min(NdV, NdL));

Posted 05 November 2012 - 07:31 AM

I'm still getting crazy high values (basically the entire mesh white). Does the input alpha have to be ridiculously high ?

edit: hmm no higher values don't seem to fix this.

edit2: ok so when only outputting D or D*F it looks more like it should (still very bright). Is there something wrong with my Geometry term ?

edit: hmm no higher values don't seem to fix this.

edit2: ok so when only outputting D or D*F it looks more like it should (still very bright). Is there something wrong with my Geometry term ?

**Edited by lipsryme, 05 November 2012 - 09:02 AM.**

Portfolio/Blog: http://marcel-schindler.weebly.com