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\$

1 Answer 1

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\$
0

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .