Ideally, what I'd like to do is draw a single quad and have GLSL handle the creation of the actual gridlines.
In my attempt so far the vertex shader:
#version 400
layout (location = 0) in vec4 in_position;
layout (location = 2) in vec3 in_UV;
uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;
smooth out vec3 ex_UV;
smooth out vec3 ex_originalPosition;
void main()
{
gl_Position = projection * view * model * in_position;
ex_UV = in_UV;
ex_originalPosition = vec3(in_position.xyz);
}
The model matrix scales the quad up by some large number, like 10,000.
#version 400
layout (location = 0) out vec4 color;
smooth in vec3 ex_UV;
smooth in vec3 ex_originalPosition;
uniform vec4 lineColor;
void main(void)
{
if(fract(ex_UV.x / 0.001f) < 0.01f || fract(ex_UV.y / 0.001f) < 0.01f)
color = lineColor;
else
color = vec4(0);
}
I've tried using both the Texture coords and the world space positions for this. Both result in the same affect which looks fine at some angles, but at others it starts looking horrid.
I thought maybe I could scale the alpha depending on the distance, so that my grid fades away into nothing, but the problem is that you can see in the second image, from the center of the screen, you can see that even those lines are being rendered with gaps through them (the point of the grid is to give a visual frame of reference around the origin).
Is there a simpler way to do this?
EDIT
Screenshots as requested:
VBO Lines with x8 Multisampled Framebuffer
VBO Lines with x8 Multisampled Framebuffer and glEnable(GL_LINE_SMOOTH)
I settled on
I settled on the either of the above (doesn't really matter which) and simply lowered the alpha as a function of distance from the origin. This serves my purpose though it isn't the question I asked.
A simple case of aliasing. Just like with polygon rendering, your fragment shader is run once per pixel. Colour is computed for a single central coordinate only and is not representative of the true colour.
Mipmapping already does this for textures. Create a grid texture with just a few lines and map it so it repeats for your really large quad (make sure to set
GL_REPEAT
). Set up the correct mipmap filtering parameters for the texture and callglGenerateMipmap
. When you calltexture2D()
/texture()
in the fragment shader OpenGL automatically calculates which level of the mipmap to use based off the texture coordinate delta between the adjacent pixels. Finally, set up anisotropic filtering for an even more amazing looking grid.If you want a grid to be truly "infinite", I've seen some ocean renderers connect the edges of the grid to the horizon with vertical geometry. If you have enough grid before them, you could possibly get away with setting them to one flat colour - the colour at the top level of your mipmap.
Examples (relating to comments):
1024x2 GL_LINES drawn from a VBO
45fps (drawn 100 times for benchmark at HD res)
See the comments regarding multisampling to address GL_LINES aliasing.
A 32^2 texture mapped to a quad with mipmapping
954fps (drawn 100 times for benchmark at HD res)