Reading back non-normalized vectors?

Hello, I have recently tried reading back some computations of vector data on the GPU, but I can’t seem to get the right numbers. So as a test, I started played around with just reading back vertex data and still could not get it right.

I figured the best way to readback a non-normalised vector, is to save it as a normalized vector with its length. In case the length is greater than 1, I pre-scale that value to the range [0,1]. So my test fragment shader is:

// transformed vertex
varying vec3 g_vertex;

// specify an scale to use eg 10
uniform float scale;

void main()
	vec3 v;
	// we let the 4th coord be the vector scale
	float w = length(g_vertex) / scale;
	v = normalize(g_vertex);
	v = 0.5 * v + 0.5;
	gl_FragColor = vec4(v, w);

reconstruction after readback:

float *pix = vertexmap + 4*i;
vertex[0] = (pix[0] - 0.5) * 2.0;
vertex[1] = (pix[1] - 0.5) * 2.0;
vertex[2] = (pix[2] - 0.5) * 2.0;

vertex[0] *= pix[3] * vmap_scale;
vertex[1] *= pix[3] * vmap_scale;
vertex[2] *= pix[3] * vmap_scale;

It’s ok when the scale is close to one, but for every point further from (0,0,0) I start to get concentric circle effect based on the scale I choose. For example scale = 6, then there will be some bands where vertices will round to. I’ve tried in different spaces object/eye and get the same result, I might be going about it the wrong way. It’s something about that 4th component not working right…

I’ve made 3 snaps of scale = 1, and 3 snaps of scale = 6

Any suggestions?

edit: re-rendered as a 3D point cloud

You mean you readback data in GL_RGBA8 ?? Of course you will loose a lot of precision, with only 8 bits of precision and 8 bits of scale.
You need to use floating point renderbuffers instead.

do you mean like this?

glReadPixels(0, 0, w, h, GL_RGBA, GL_FLOAT, vertexmap);

I always use this method of readback.

I always use this method of readback.

Unless you specifically allocated a floating-point buffer, this doesn’t change the fact that you only have 8 bits of precision for each component. You need to use an FBO and allocate a floating-point buffer. This will also mean you don’t need to normalize the vector, since floating-point images can store arbitrary numbers.

Thanks for the info. Not having used FBO’s before, I think they are a much more elegant than seeing flashes of each rendering pass, something I should have done long ago :stuck_out_tongue:

I render to texture using the following:

glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F_ARB, w, h, 0, GL_RGBA, GL_FLOAT, NULL);

and get a very nice result for vertex reconstruction.

So going back to non-normalized vectors, it seems like this is the best internal format for FBO texture to obtain maximum possible accuracy.

      Sized                       Base             R    G    B    A    L    I
      Internal Format             Internal Format bits bits bits bits bits bits
      --------------------------- --------------- ---- ---- ---- ---- ---- ----
      RGBA32F_ARB                 RGBA            f32  f32  f32  f32

Thank you all for the help

This topic was automatically closed 183 days after the last reply. New replies are no longer allowed.