Search code examples
openglglslopengl-3opengl-4

eye-space pixel width in GLSL vertex shader


I want to compute the eye-space width of a pixel's projected pyramid at the current vertex location in a glsl vertex shader, but I can't seem to get the math right. Here is an obviously incorrect example:

// GLSL VERTEX SHADER
#version 410 compatibility

uniform vec4 viewport; // same as glViewport​
in vec4 gl_Vertex;

void main ()
{
    gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
    float pixelWidth = gl_Position.z / viewport.z;
<snip>

But this does not account for the FOV or clipping planes.


Solution

  • I worked through the math and figured it out. :) As I had hoped there are no additional matrix transformations required, just one divide:

    // GLSL VERTEX SHADER
    #version 410 compatibility
    
    uniform vec4 viewport; // same as glViewport​
    in vec4 gl_Vertex;
    
    float pixelWidthRatio = 2. / (viewport.z * gl_ProjectionMatrix[0][0]);
    
    void main ()
    {
        gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
        float pixelWidth = gl_Position.w * pixelWidthRatio;
        <snip>
    

    Or alternatively:

    <snip>
    float pixelHeightRatio = 2. / (viewport.w * gl_ProjectionMatrix[1][1]);
    
    void main ()
    {
        gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
        float pixelHeight = gl_Position.w * pixelHeightRatio;
    <snip>
    

    As expected, pixelWidth and pixelHeight are the same if the pixels are square.