PDA

View Full Version : Save vertices to texture problem



foCus
06-04-2011, 03:51 PM
Hello,

The problem is as follows:
I am trying to store vertex positions into textures in OpenGL and pass them into GLSL and is succeding quite well appart from some vertices are missing or missplaced :S. I think the problem lies in the generations of the texture, when one applies glTexParameters to the texture such as GL_NEAREST or GL_REPEAT. I have checked with normal gl_Vertex and they work fine.. so the vertices position is correct.

I have stored vertices position and normals in textures in OpenGL like this:

Code:

glGenTextures(2, textures);

float *surfels = new float[ o.vertexList.size()*3];
int k = 0;
for(int i= 0; i < (const int) o.vertexList.size(); i++)
{

surfels[k] = o.vertexList.at(i).x;
surfels[k+1] =o.vertexList.at(i).y;
surfels[k+2] = o.vertexList.at(i).z;
k = k+3;
}

glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, textures[0]);

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB32F_ARB, ceil(sqrt((float)o.vertexList.size())),ceil(sqrt(( float)o.vertexList.size())), 0, GL_RGB, GL_FLOAT, surfels);


The relevant parts of the vertex shader:

Code:

uniform sampler2D positionMap;
void main(void)
{
st = gl_MultiTexCoord0.xy;
vec4 v = vec4(texture2D(positionMap,st).xyz,1.0);
gl_Position = gl_ModelViewProjectionMatrix*v;
}


The problem is that almost every point is nicely placed in openGL but some of the vertices position are lost or placed at another place. Can it have soemthing to do with using GL_NEAREST in the glTexParametri.

Maybe there is a better way to store vertices to a texture and pass it to a fragmentshader ? FBO:s? but won't I run in to the same problem?

it seems that the problem is not the data it self because I've checked that. However the problem is that if I use GL_NEIREST it will copy the value next to during mip_mapping, but I only want the specific value on the specific pixel.

I've read that the problem also could be the size of the image..should be 2^n +2. Since I now take the square root of the entire image to use as the width and height and then ceil to get more pixels than need which should be ok I think.

So the question is: How do I store vertex positions in a texture, in a good way?

I have googled it a many times but can't find anyone that has a good answer to this specific question.

Thank you for taking your time.

mhagain
06-04-2011, 04:40 PM
Any particular reason why you're using a texture here? Would a VBO not do?

It's hard to say anything further because there's no sense of why you're doing this, of what effect you're trying to achieve.

foCus
06-05-2011, 01:20 AM
Ok, The reason why I use textures is that I want to send it to the fragment-shader in GLSL. I want access to all vertices so I can loop over them and calculate point-based ambient occlusion for each vertex.

I have not worked with VBO:s but correct me if I'm wrong, I don't think you can access the vertices in a vbo through a fragment-shader and that is why I use textures instead.

Maybe FBO will do a better job storing the vertices?

Thank you mhagain for your reply.

Alfonse Reinheart
06-05-2011, 01:53 AM
The reason why I use textures is that I want to send it to the fragment-shader in GLSL. I want access to all vertices so I can loop over them and calculate point-based ambient occlusion for each vertex.

That doesn't explain why you're using a texture in your vertex shader.

Perhaps you should use a buffer texture. You can (in theory) bind a buffer object as an attribute array and as a buffer texture. That will allow you to use regular vertex attributes, but also access the vertex data from the fragment shader as a buffer texture.


Maybe FBO will do a better job storing the vertices?

Um, how? Framebuffer Objects are containers for textures or renderbuffers. They don't "store" anything, nor can they be accessed by a shader. They're just an arrangement of render targets.

foCus
06-05-2011, 02:01 AM
Wow, quick replies here :) Thank you guys!

I use the texture in the vertex shader in order to see if the texture is correctly stored by applying the texture to the gl_Position like this:

Vertex shader:

uniform sampler2D positionMap;
uniform sampler2D normalMap;
varying vec2 st;
varying vec2 uv;
void main( void )
{
st = gl_MultiTexCoord0.xy;
uv = gl_MultiTexCoord1.xy;
vec4 v = vec4(texture2D(positionMap,st).xyz,1.0);
gl_Position = gl_ModelViewProjectionMatrix*v;
gl_Normal = texture2D(normalMap,uv).xyz;
}

The problem is that it almost works fine accept for some vertices are lost :p Probably due to the GL_NEIREST or the size of the texture.

I will look into buffer textures and see if they can work better.

Thank you very much Alfonse Reinheart.

mhagain
06-05-2011, 07:01 AM
You could write the input positions to an output texcoord register in your vertex shader, something like:

gl_TexCoord[3].xyz = gl_Position.xyz; // 3 is just an arbitrary number for demo purposes here

foCus
06-05-2011, 10:38 AM
Hello again, I haven't had the time to test the buffer textures yet. What I've read though is that they don't do any kind of mip mapping which sounds good because I don't want any interpolations of that sort.

mhagain: hmm can I store them into a texCoord and then use them, but then I need to do one pass only for that purpose, right?


The thing is this, I want to pass two textures to a GLSL shader one with the normals, and one with the vertices, and work with them in the shaders instead.

Right now it is:

Sampler2D positionMap;
Sampler2D normalMap;

Then I fetch values from these textures like this:

for(int i = 0; i < numberOfSurfels; i++)
{
for(int j = 0; j < numberOfSurfels; j++)
{
float dx = (float) i/(float) numberOfSurfels;
float dy = (float) j/(float) numberOfSurfels;
ePosition = texture2D(positionMap,vec2( dx, dy)).xyz;
eNormal = texture2D(normalMap,vec2( dx, dy));
eArea = eNormal.w;

....Ambient occlusion stuff...

}
}

And it works nice accept for that some positions are lost.

When I check the positionMap in the vertex-Shader like this:

uniform sampler2D positionMap;
varying vec2 st;
void main( void )
{
st = gl_MultiTexCoord0.xy;
uv = gl_MultiTexCoord1.xy;
vec4 v = vec4(texture2D(positionMap,st).xyz,1.0);
gl_Position = gl_ModelViewProjectionMatrix*v;
}
I stated before, I almost get every point but some are missing :p. My guess is that they are placed at the neirest neighbor in the texture since I have to use some kind of interpoliations with mipmaps I chose the GL_NEIREST like this, but I don't want any interpolation at all. This is how it looks when I load the texture:


const int size = (const int) o.vertexList.size();
float *surfels = new float[size*3];

int k = 0;
for(int i= 0; i < (const int) o.vertexList.size(); i++)
{

surfels[k] = o.vertexList.at(i).x;
surfels[k+1] =o.vertexList.at(i).y;
surfels[k+2] = o.vertexList.at(i).z;
k = k+3;
}

glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, textures[0]);

glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTE R,GL_NEAREST);
glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTE R,GL_NEAREST);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB32F_ARB, ceil(sqrt((float)o.vertexList.size())),ceil(sqrt(( float)o.vertexList.size())), 0, GL_RGB, GL_FLOAT, surfels);

I do not see the problem with this method accept for maybe the interpolation with mipmapping.

Is this a very bad method for uploading textures to GLSL and work with them as data storage?

Thank you for taking your time.

mbentrup
06-05-2011, 11:06 PM
You should sample the texture at the texel centers, so a small rounding error will not throw you into a neighbour texel.



float dx = ((float) i + 0.5)/(float) numberOfSurfels;
float dy = ((float) j + 0.5)/(float) numberOfSurfels;


And have a look at buffer textures, they were basically made for cases like this.

foCus
06-06-2011, 02:06 AM
mbentrup: Thank you! :) good to know and is now implemented.

I now have time to look into buffer textures, so hopefully it will do the trick. Thank you guys!

foCus
06-06-2011, 06:03 AM
Just to check that I'm not totaly off here.

Instead of sampler2D I should now use SamplerBuffer Like this:

samplerBuffer positionMap; and then use texelFetch(positionMap,P); where P is an index that is used to get the specific texel instead of using texture2D(positionMap,st); where st is the texture coordinates.

It gets a little bit trickier because I have to come up with a whay to fetch the right point in the samplerBuffer.

foCus
06-09-2011, 03:04 AM
Just wanted to say thank for all your help, the texture buffer did the job.

Thanks!