pythonopenglfloating-pointfragment-shaderpyopengl

Not able to get precise float values from fragment shader output


I am using OpenGL on desktop (using PyOpenGL) for some image processing operation and doing some floating point operations per pixel in fragment shader.After that when I read the pixels using glReadPixels buffers are not as expected.

Pasted below is the portion of the relevant code:

vertex_src = """
#version 330 core
in vec3 a_position;
in vec2 vTexcoords;
out vec2 fTexcoords;
void main() {
    gl_Position = vec4(a_position, 1.0);
    fTexcoords = vTexcoords;
}
"""

fragment_src = """
#version 330 core
out vec4 out_color;
in vec2 fTexcoords;

void main() {
    vec4 tempcolor = vec4(0.0);
    float ran = 0.003921568627451;
    for(int i = 0;i < 100;i++)
        tempcolor = tempcolor + ran*ran;
 
    out_color = tempcolor;
}
"""
# Routine calls for OpenGL setup...

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
glDrawElements(GL_TRIANGLES, len(vertices) * 4, GL_UNSIGNED_SHORT,None)
buffer = glReadPixels(0, 0, 1280, 720, GL_RGB, GL_FLOAT,None)
print(buffer[1][1])

The print statement prints all 0's

[0. 0. 0.]

If I do the same operation in Python as below

import numpy as np
tempcolor = np.array([0.],dtype='float32')

ran = 0.003921568627451
for i in range(100):
    tempcolor = tempcolor + ran * ran;

out_color = tempcolor
print(out_color)

I get the expected output

[0.00153787 0.00153787 0.00153787]  

Is this something to do with the precsion of output of fragment shader? I was hoping all the operations in fragment shader are done in float32 precision and output will also be float32.

Just to add , in the fragment shader if I add the below statement after the for loop , I get some non-zero output

tempcolor += 0.002383698627451;  

Output:

[0.00392157 0.00392157 0.00392157]  

Solution

  • The problem is the internal format of the frame buffer. If the frame buffer only has 8 bits per color channel, the values you get cannot be more precise than that. Note that the format of the default framebuffer cannot be changed as it is created with the OpenGL window. Usually, the format of the default framebuffer is a fixed normalized format that can only store values in the range 0.0 to 1.0 (independent of the bit depth).
    However, you can render into a named framebuffer. When creating the framebuffer, the format and type can be specified. See Framebuffer Object