Advertisement

Bent Normals - Verifying correctness of implementation and thought process

Started by November 07, 2024 12:32 PM
1 comment, last by JoeJ 1 month ago

Hi all,

I am trying to compute bent normals to use for my lighting calculations such as ambient occlusion. The way I understand it is that bent normals point in a direction that represents the "average unoccluded direction" of ambient light around a point on a surface.

For this I am ray marching some directions around the current fragment and checking for intersections. For each direction I am checking if there is an intersection seach step, if not, we increment a counter and if there is we decrement it. To know if this direction never intersected, the counter should matcht the number of steps taken. If there is no intersection for a particular direction we compute the bent normal and the weighting using lambert cosine term.

I am struggling to find some view-space bent normal outputs or resources to verify if my approach is correct and would appreciate any insight or feedback. Thanks in advance.

This is my current output.

vec3 ComputeBentNormal(vec3 samplePos, vec3 sampleDir)
{
	RANDOMVALUE = (uv.x * uv.y) * debugRenderer.stepCount;
	RANDOMVALUE += fract(debugRenderer.time) * debugRenderer.stepCount;

    const int numSteps = debugRenderer.stepCount;         
    float stepSize = debugRenderer.maxDistance / float(numSteps); 
	
	vec3 WorldNormal = normalize(texture(gBuffNormal, uv).xyz);
	vec4 viewSpaceNormal = ubo.view * vec4(WorldNormal, 0.0);
	viewSpaceNormal = normalize(viewSpaceNormal);

    // Convert pos and dir to screen space
    vec3 screenPos = worldToScreen(samplePos);
    vec3 screenDir = normalize(worldToScreen(samplePos + sampleDir) - screenPos) * stepSize;


    vec3 rayPos = screenPos + screenDir * RANDOMVALUE; // Apply jitter 

    vec3 bentNormal = vec3(0.0);
    float totalVisibility = 0.0;
	int stepsTaken = 0;
	
    for(int i = 0; i < numSteps; i++)
    {
        rayPos += screenDir;

        if(clamp(rayPos.xy, 0.0, 1.0) != rayPos.xy) break;


		rayPos = BinarySearch(rayPos, screenDir);
        // Fetch depth at current screen position
        float sceneDepth = texture(depthTex, rayPos.xy).x;
        float sampleDepth = rayPos.z;

        if((sampleDepth - sceneDepth) > 0 && (sampleDepth - sceneDepth) < debugRenderer.thickness)
        {
            // We intersected
            occlusion += 1.0;
			stepsTaken -= 1; // reduce this since we intersected while marching
            break;
        }

		

		// no intersection? increment counter
		stepsTaken += 1;

    }

	// this would mean we stepped numSteps times and didnt intersect anything
	if(stepsTaken == numSteps)
	{
		// Accumulate bent normal
		vec4 viewSpaceDir = normalize(ubo.view * vec4(sampleDir, 0.0));

		float NdotL = max(dot(viewSpaceNormal.xyz, viewSpaceDir.xyz), 0.0);
		bentNormal = bentNormal + viewSpaceDir.xyz * NdotL;
		totalVisibility += NdotL;
		
	}

    // Normalize bent normal
    if (totalVisibility > 0.0) {
        bentNormal /= totalVisibility;
        bentNormal = normalize(bentNormal);
    } 


    bentNormal;
}

vec4 BentNormal()
{
    vec3 WorldPos = texture(gBuffPosition, uv).xyz;
    vec3 WorldNormal = normalize(texture(gBuffNormal, uv).xyz);

    
    vec3 bentNormal = vec3(0.0);

    // March rays in screen space
    float NUM_DIRECTIONS = debugRenderer.numDirections;
    for (int i = 0; i < NUM_DIRECTIONS; i++)
    {
        // Sample random direction
        vec2 RandomVals = randomVec2(uv * float(i));

        vec3 SampleRandomDirection = CosWeightedHemisphere(WorldNormal, RandomVals);

        // Use the compute bent normal
        bentNormal =+ ComputeBentNormal(WorldPos, SampleRandomDirection);
    }


    bentNormal = normalize(bentNormal); // Normalize the bent normal

    return vec4(vec3(bentNormal), 1.0);
}

Idk, but this is the first paper coming to my mind: https://graphics.tudelft.nl/Publications-new/2012/KRES12/paper.pdf

Your random number generator surely is bad, and you probably need some blur for the noise.

This topic is closed to new replies.

Advertisement