Infinite grid similar to Unity Editor

We’re all familiar with the Unity Editor. I’m trying to figure out the best way to render an infinite grid similar to what you see in an empty scene. Think “floor” for 2D gameplay with a perspective camera that can orbit and zoom the gameplay surface.

I can easily throw a frag shader on a quad, but making it super-enormous so that it always fills the view (and fades into the distance) seems like a bad idea (or at least a naive approach).

Another angle I’ve tried is layering multiple cameras, with one dedicated to rendering the quad and resetting the camera position so a more reasonably-sized quad always fills that camera’s view, but it gets hairy trying to match the main camera movement and zooming (by which I mean, it don’t have it working well).

Is it possible to do a “post-processing” effect that actually happens before everything else? Hmm, maybe I can do that on my layered camera, now that I think about it…

Anyway, I’d appreciate some advice about what to chase here.

A few hours later, now it’s obvious from my last post-processing comment that I’ve never played with RenderTexture. It was easy enough to set up a second camera and pass it a RenderTexture and a Material with my shader and mess around with the texture.

I suppose I’m just making notes for myself as I go… the steps to work out are:

  1. define a ray based on camera origin and direction
  2. find the intersection length of that ray with a ground plane
  3. figure out the xy coords of the intersection point on the plane
  4. draw based on how the coords correspond to the grid layout

I imagine it’ll all seem trivial by the time I’m done. :slight_smile:

Hmm, this doesn’t have grid code yet (and I’ll get rid of the branching later) but I can’t see why this frag shader always returns a solid black texture. It should be white towards the bottom of the screen (where the plane is, at origin with Y=1 normal) and black at the top.

            const float4 BLACK = float4(0.0, 0.0, 0.0, 1.0);
            const float4 WHITE = float4(1.0, 1.0, 1.0, 1.0);

            const float3 plane_normal = float3(0.0, 1.0, 0.0);
            const float3 plane_point = float3(0.0, 0.0, 0.0);

            bool intersectPlane(float3 rayOrigin, float3 rayDirection, out float3 intersection)
            {
                float rDotn = dot(rayDirection, plane_normal);
                //parallel to plane or pointing away from plane?
                if (rDotn < 0.0000001) return false;
                float s = dot(plane_normal, (plane_point - rayOrigin)) / rDotn;
                intersection = rayOrigin + s * rayDirection;
                return true;
            }

            float4 frag(v2f_img i) : COLOR {
                float3 camForward = normalize(UNITY_MATRIX_V[2].xyz);
                float3 hitCoord;
                bool hit = intersectPlane(_WorldSpaceCameraPos, camForward, hitCoord);
                return lerp(BLACK, WHITE, abs(hit));
            }

Btw, that “naïve” approach is the right way to do this. That or you actually draw lines directly which is what Unity does AFAIK. The full screen approach is entertaining to explore, but way less efficient. And raytracing is going to be hard to get anti-aliased.

The fact you’re bringing a render texture into the equation is vastly over complicating it too.

1 Like

Good to know… though I’d still like to see the correct “entertaining” solution.

That bit of code probably doesn’t benefit from ignoring i.uv either…

Since this question is asked periodically, it’s pretty simple to convert this GLSL approach to HLSL. (I’d post my own code but I already deleted the project because I wasn’t as happy with the results as I’d hoped – then later realized maybe someone else might want it.)

http://payback-time.com/2016/01/12/i_made_fog/

And in case anything happens to his blog, the vert and frag code:

1 Like

Follow-up: I created a very small repeating texture, generated a very large circular mesh (2000 unit diameter looks smooth with a circumference of only 100 segments – 101 verts & uvs, 303 tris), tiled the texture, and used the vert offset from origin to alpha-fade the edges of the mesh.

It’s kind of a special-case solution, though. My ground-plane is circular and centered at 0,0,0 so the calc is easy and a distance-based fade works. It wouldn’t generally work as an edge-fade with another shape.