Archive for the ‘viewport matrix’ tag
Added a new effect to Tutorial 5: a single-pass surface and wireframe rendering effect. Note how the wireframe is anti-aliased, fades into the surface color, and displays without z-fighting.
The effect derives directly from the shader in the previously mentioned OpenGL 4.0 Shading Cookbook. The implementation there, according to the author, derives from the one presented in this nVidia whitepaper. I won’t go into detail of the effect (since the explanation is available both in the whitepaper and the book) and will only briefly comment on the implemenation.
In short, it uses a geometry shader to compute the distance of each fragment from each edge of each triangle. The fragment shader then uses those distances to determine whether to use the surface shading color or the wireframe edge color. A mix() call is rather than a discrete choice to antialias the edges. Because it’s a single pass shader, there’s no chance of z-fighting.
Setting the “ViewportMatrix”
A quick note since the OpenGL 4.0 Shading Cookbook does not explain how to set up the “ViewportMatrix”. It’s pretty simple, but just to clarify, here’s the code to set up the viewport matrix:
GLint viewport; gl->getIntegerv(GL_VIEWPORT, viewport); float halfWidth = float(viewport) / 2.0f; float halfHeight = float(viewport) / 2.0f; glm::mat4 m( glm::vec4(halfWidth, 0.0f, 0.0f, 0.0f), glm::vec4(0.0f, halfHeight, 0.0f, 0.0f), glm::vec4(0.0f, 0.0f, 1.0f, 0.0f), glm::vec4(halfWidth, halfHeight, 0.0f, 1.0f) ); gl->uniformMatrix4fv(loc, 1, GL_FALSE, glm::value_ptr(m));
The principle is quite simple. Prior to the viewport matrix transformation, OpenGL coordinates in eye space range from -1 to 1 in x, y, and z. Therefore, these values get scaled by half the width/height and offset by half the width/height. This maps -1 to 0 (e.g. -halfWidth + halfWidth = 0) and 1 to the full width (halfWidth + halfWidth = width). The z values do not get scaled or offset since window coordinate retain the same range as eye coordinates.
One More Image…
One last image of a slightly tweaked version of the shader that fades the wireframe intensity based on the diffuse intensity. Also, snow