**************** UPDATE ********************** **

I had a stupid issue due to the resolution of the texture, not the code below works as it should.

***************************************************

Hi there!

I'm trying to implement the IBL technique described in here: http://blog.selfshadow.com/publications/s2013-shading-course/karis/s2013_pbs_epic_notes_v2.pdf

Now I'm still trying to get the envBRDF LUT (roughness / NdotV) to render properly as shown in the paper:

What I have now is:

the usual Hammersley functions:

float radicalInverse_VdC(uint bits) { bits = (bits << 16u) | (bits >> 16u); bits = ((bits & 0x55555555u) << 1u) | ((bits & 0xAAAAAAAAu) >> 1u); bits = ((bits & 0x33333333u) << 2u) | ((bits & 0xCCCCCCCCu) >> 2u); bits = ((bits & 0x0F0F0F0Fu) << 4u) | ((bits & 0xF0F0F0F0u) >> 4u); bits = ((bits & 0x00FF00FFu) << 8u) | ((bits & 0xFF00FF00u) >> 8u); return float(bits) * 2.3283064365386963e-10; // / 0x100000000 } // http://holger.dammertz.org/stuff/notes_HammersleyOnHemisphere.html vec2 Hammersley(uint i, uint N) { return vec2(float(i)/float(N), radicalInverse_VdC(i)); }

The ImportanceSampleGGX practically as reported in the paper:

vec3 importanceSampleGGX(vec2 sample, float m, vec3 N){ float phi = sample.x * 2.0f * PI; float cosTheta = sqrt( (1.0f - sample.y) / 1.0f + (m*m - 1.0f) * sample.y ); float sinTheta = sqrt(1.0f - cosTheta*cosTheta); vec3 vector = vec3( sinTheta * cos(phi), sinTheta * sin(phi), cosTheta ); return vector; vec3 up = abs(N.z) < 0.999 ? vec3(0.0,0.0,1.0) : vec3(1.0,0.0,0.0); vec3 tangentX = normalize(cross(up,N)); vec3 tangentY = normalize(cross(N,tangentX)); // Project return tangentX * vector.x + tangentY * vector.y + N * vector.z; }

The integrateBRDF

vec2 IntegrateBRDF( float Roughness, float NoV ){ vec3 V; V.x = sqrt( 1.0f - NoV * NoV ); // sin V.y = 0.0; V.z = NoV; // cos float A = 0.0; float B = 0.0; for( uint i = 0u; i < NUMBER_OF_SAMPLES; i++ ) { vec2 Xi = Hammersley( i, NUMBER_OF_SAMPLES ); vec3 H = ImportanceSampleGGX( Xi, Roughness, vec3(0.0,0.0,1.0) ); vec3 L = 2.0 * dot( V, H ) * H - V; float NoL = max( L.z, 0.0 ); float NoH = max( H.z, 0.0 ); float VoH = max( dot( V, H ), 0.0 ); if( NoL > 0 ) { float G = G_Smith( Roughness, NoV, NoL ); float G_Vis = G * VoH / (NoH * NoV); float Fc = pow( 1.0 - VoH, 5.0 ); A += (1.0 - Fc) * G_Vis; B += Fc * G_Vis; } } return vec2( (A)/float(NUMBER_OF_SAMPLES), (B)/float(NUMBER_OF_SAMPLES)) ; }

As you can see they're almost a copy-paste from the reference, but what I got is completely different:

The roughness is the uv.x and uv.y of a quad that are calculated in the VS as:

vTextureCoordinate = (aVertexPosition.xy+vec2(1,1))/2.0;

Am I missin something very stupid?

**Edited by cifa, 15 July 2014 - 06:27 AM.**