************** 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?