1
\$\begingroup\$

I know there are plenty of tutorials how to create tiled frustum with compute shaders, but I`m trying to understand the steps and want to build it on the cpu with pure C# code.

I translated a lof of Intels approach (which can be found at intels post: Deferred Rendering for Current and Future Rendering Pipelines, sorry I have to earn more reputation to link this) to c# code, which was a kinda hard work because I am not familiar with compute shaders.

So now I got some problems with the algorithm.

  1. A single light is contained by a lot of tiles, even if the AttenuationEnd(or sphere radius) of the light is set < 0,1. It seems to have no effect. (the image below shows the rays of each tile with light info)

White: Tiles with no light | Red: Tiles with light enter image description here 2. I dont get right results if calculating a frustum ray from its corners. The following image shows the partially rendered (from 5 to 5.1) rays with origin at 0, 0, 0. Should`nt there be more space between each tile at 70 degree fov? enter image description here

This is the code I`m using. I commented out a lof of stuff, also with debug info, if possible.

        vec4[] frustumPlanes = new vec4[6];


        // There is 1 light with following properties:
        // Position       : 5, 5, 5
        // AttenuationEnd : 0.1 (should fit inside some frusta) 

        // Use a simple 70 fov (70 / 180 * PI) perspective setup.
        // width = 486
        // height = 279
        // near = 0.1
        // far = 10
        mat4 projection = scene.Camera.ProjectionMatrix;
        int TILES_COUNT = 16;

        for (int tX = 0; tX < TILES_COUNT; tX++)
        {
            for (int tY = 0; tY < TILES_COUNT; tY++)
            {
                // tileBias lies between 1 and -1, decreases from 1 to -1
                vec2 tileBias = new vec2(1 - tX / (TILES_COUNT - 1f), 1 - tY / (TILES_COUNT - 1f)) * 2f - 1f;

                vec4 c1 = new vec4(-projection.m00, projection.m01, tileBias.x, projection.m03);
                vec4 c2 = new vec4(projection.m10, -projection.m11, tileBias.y, projection.m13);
                vec4 c4 = new vec4(projection.m30, projection.m31, 1.0f, projection.m33);
                // c1 = { -0.82,     0, 1, 0 }  < 3rd index is tileBias.x for tX = 0
                // c2 = {     0, -1.43, 1, 0 }  < 3rd index is tileBias.y for tY = 0
                // c3 = {     0,     0, 1, 0 }

                frustumPlanes[0] = c4 - c1;
                frustumPlanes[1] = c4 + c1;
                frustumPlanes[2] = c4 - c2;
                frustumPlanes[3] = c4 + c2;

                // The following 3rd and 4th index signs confuse me, why +/-?
                frustumPlanes[4] = new vec4(0f, 0f, 1f, -0.1f); // near
                frustumPlanes[5] = new vec4(0f, 0f, 1f,  10f); // far

                // Normalizing corners
                for (int i = 0; i < 4; i++)
                    frustumPlanes[i] *= 1f / frustumPlanes[i].xyz.Length;


                // An attempt of converting the frustum into a ray.
                vec3 rayDir = frustumPlanes[0].xyz + frustumPlanes[1].xyz + frustumPlanes[2].xyz + frustumPlanes[3].xyz;
                rayDir = rayDir.Normalized;

                // Calculates whether a light is inside the frustum
                bool anyLightInFrustum = false;
                for (int i = 0; i < lights.Count; i++)
                {
                    Light light = lights[i];
                    vec4 lightPos = new vec4(light.Pos, 1.0f);
                    bool inFrustum = true;
                    for (int j = 0; j < 6; j++)
                    {
                        float dist = vec4.Dot(frustumPlanes[j], lightPos);
                        inFrustum = inFrustum && (dist >= -light.AttenuationEnd);
                    }
                    if (inFrustum) anyLightInFrustum = true;
                }

                // Set the color to red, if a light is contained
                vec4 color = new vec4(1);
                if (anyLightInFrustum)
                    color.rgb = vec3.UnitX;

                // Draws a ray with a range from {4} to {5}, origin at {0, 0, 0}
                DrawRayWithColor(tessellator, color, rayDir, 5.0f, 5.1f);
            }
        }

Maybe some of you can give me some hints for this. Even if I just did a translation mistake.

Thanks in advance!

\$\endgroup\$
0
\$\begingroup\$

Try to use tileBias within a range of 0 to 2. You also have to use a cross product of two frustum corners.

For example, vec3 rayDir = vec3.Cross(frustumPlanes[0].xyz, frustumPlanes[2].xyz);.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.