Last active
September 13, 2020 18:06
-
-
Save cmbruns/5b1c2b211766cdcb3b29689e0c32a63d to your computer and use it in GitHub Desktop.
Rendering an infinite plane 3: https://biospud.blogspot.com/2020/05/infinite-plane-rendering-3-image.html
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#version 450 core | |
// Vertex shader for rendering an infinite plane. | |
void main() {} // vertex shader does nothing. All the work is done in the geometry shader |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#version 450 core | |
// Geometry shader for rendering an infinite plane. | |
// Creates a screen-space imposter polygon for rendering the plane. | |
// Most of the polygon edges lie along the screen edges. | |
// Call from host side with glDrawArrays(GL_POINTS, 0, 1) | |
layout (points) in; | |
layout (triangle_strip) out; | |
layout (max_vertices = 5) out; | |
layout(location = 1) uniform mat4 projection = mat4(1); | |
layout(location = 2) uniform mat4 view = mat4(1); | |
layout(location = 3) uniform mat4 model = mat4(1); | |
// corners of the display screen in counter-clockwise order | |
// in clip space (normalized device coordinates) | |
const float sz = 0.5; // Exact z value does not matter | |
const int num_corners = 4; | |
const vec4 screen_quad[num_corners] = vec4[num_corners]( | |
vec4(-1, -1, sz, 1), // lower left | |
vec4( 1, -1, sz, 1), // lower right | |
vec4( 1, 1, sz, 1), // upper right | |
vec4(-1, 1, sz, 1)); // upper left | |
// Output coordinates of view/plane intersection in view space | |
out vec4 point; | |
vec3 dehomog(vec4 v) | |
{ | |
return v.xyz/v.w; | |
} | |
struct EdgeVertex | |
{ | |
vec4 pos; // screen edge location in clip space | |
vec4 point; // view/plane intersection in view space | |
}; | |
void emit_vertex(in EdgeVertex v) | |
{ | |
gl_Position = v.pos; | |
point = v.point; | |
EmitVertex(); | |
} | |
void main() | |
{ | |
int vertex_count = 0; | |
EdgeVertex e = EdgeVertex(vec4(0), vec4(0)); | |
EdgeVertex vertices[5] = EdgeVertex[5](e, e, e, e, e); | |
// Perform all computations in view space | |
mat4 MV = view * model; | |
vec3 N = normalize((MV * vec4(0, 1, 0, 0))).xyz; // plane normal | |
vec3 T = dehomog(MV * vec4(0, 0, 0, 1)); // plane translation | |
float d = -dot(N, T); | |
mat4 Pinv = inverse(projection); | |
// Walk around the display screen in counter-clockwise direction, | |
// and add vertices as needed. | |
for (int c = 0; c < num_corners; ++c) | |
{ | |
vec3 D = (Pinv * screen_quad[c]).xyz; // view direction | |
float w = dot(D, N); // plane determinant | |
// does this corner overlap the view of the plane? | |
if (w * d < 0) { | |
// plane overlaps this corner, so use this vertex | |
vertices[vertex_count].point = vec4(-d * D, w); | |
vertices[vertex_count].pos = screen_quad[c]; | |
++vertex_count; | |
} | |
// does the plane edge cross the screen edge between this corner and the next? | |
int c2 = (c + 1) % num_corners; | |
vec3 D2 = (Pinv * screen_quad[c2]).xyz; | |
float w2 = dot(D2, N); | |
if (w * w2 < 0) { | |
// plane edge crosses the screen edge before the next corner | |
// interpolate and add a vertex | |
float alpha = w / (w - w2); | |
vec3 Dmid = mix(D, D2, alpha); | |
vec4 posMid = mix(screen_quad[c], screen_quad[c2], alpha); | |
vertices[vertex_count].point = vec4(-d * Dmid, dot(Dmid, N)); | |
vertices[vertex_count].pos = posMid; | |
++vertex_count; | |
} | |
} | |
if (vertex_count < 3) | |
return; // not enough for even one triangle | |
// create triangle strip order by staggering the vertices | |
int order[] = int[](0, 1, vertex_count - 1, 2, vertex_count - 2, 3); | |
for (int v = 0; v < vertex_count; ++v) | |
emit_vertex(vertices[order[v]]); | |
EndPrimitive(); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#version 450 core | |
uniform sampler2D image; | |
layout(location = 1) uniform mat4 projection = mat4(1); | |
layout(location = 2) uniform mat4 view = mat4(1); | |
layout(location = 3) uniform mat4 model = mat4(1); | |
in vec4 point; | |
out vec4 frag_color; | |
float texture_coordinate(vec3 direction, vec3 translation) | |
{ | |
vec3 uhat = (view * model * vec4(direction, 0)).xyz; | |
float uscale = length(uhat); | |
uhat /= uscale * uscale; | |
float du = -dot(translation, uhat); | |
// above uhat/du could be computed on the host | |
// below is per-fragment | |
float u = dot(uhat, point.xyz)/point.w + du; | |
return u; | |
} | |
vec3 dehomog(vec4 v) { return v.xyz/v.w; } | |
vec2 texture_coordinates() | |
{ | |
vec3 T = dehomog(view * model * vec4(0, 0, 0, 1)); | |
float u = texture_coordinate(vec3(1, 0, 0), T); | |
float v = texture_coordinate(vec3(0, 0, 1), T); | |
return vec2(u, v); | |
} | |
void color_by_texture() { | |
vec2 tc = texture_coordinates(); | |
frag_color = texture(image, tc); | |
} | |
void color_solid() { | |
frag_color = vec4(0.1, 0.1, 0.8, 1); | |
} | |
void set_depth() { | |
vec4 ndc = projection * point; | |
gl_FragDepth = (ndc.z / ndc.w + 1.0) / 2.0; | |
} | |
void main() | |
{ | |
color_by_texture(); | |
set_depth(); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment