Jump to content

  • Log In with Google      Sign In   
  • Create Account

Awesome job so far everyone! Please give us your feedback on how our article efforts are going. We still need more finished articles for our May contest theme: Remake the Classics

[SOLVED]Perspective Correct Texture Coordinates (Frag Shader)


Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

  • You cannot reply to this topic
16 replies to this topic

#1 k.pedersen   Members   -  Reputation: 100

Like
0Likes
Like

Posted 16 March 2012 - 11:36 AM

Hi,

I have been attempting to replace all fixed functionality from an OpenGL project I wrote a while ago and have run into a snag which I havn't been able to resolve in the many hours I have spent on it.

After much research I have found it is due to the texture coordinates not being perspective correct. What I have not been able to find is a way to fix this in the shader.

(I have attached a screenshot demonstrating the issue and as you can see, the brick texture is not drawing correctly, creating a seam.)

The line of code in my frag shader which I believe to be causing the issue is as follows.
#version 120
uniform sampler2D tex;
varying vec2 pass_tex_coord;
...
gl_FragColor = texture2D(tex, pass_tex_coord);

So far I am under the impression that I need to obtain the w value from the pass_tex_coord s and t values.
I am unsure of how to do this because I am simply passing in the uv texture coordinates from my model (VBO). I have also noticed that the model of the cat has the correct texture coord mapping (because the triangles are smaller?)

If anyone could help shed some light on this or offer some example shader code to do this, I would be very greatful!

Best Regards,

Karsten

Attached Thumbnails

  • example.png

Wavefront Animation Studio - Create simple animations for .obj 3D models.
libwavefront - Open-source C++/OpenGL library to load animated .obj models.

Sponsor:

#2 NumberXaero   Members   -  Reputation: 725

Like
0Likes
Like

Posted 16 March 2012 - 02:58 PM

Did the brick object ever draw correctly? It looks like UVs might be incorrect.

#3 k.pedersen   Members   -  Reputation: 100

Like
0Likes
Like

Posted 16 March 2012 - 03:44 PM

Hello NumberXaero,

Yes, I can confirm that the brick texture draws correctly when using the fixed function shader.

Also, my same code is loading the brick structure as the cat, so I know the texture coordinates are not the issue here.

Any other suggestions to this?
Wavefront Animation Studio - Create simple animations for .obj 3D models.
libwavefront - Open-source C++/OpenGL library to load animated .obj models.

#4 NumberXaero   Members   -  Reputation: 725

Like
0Likes
Like

Posted 16 March 2012 - 04:06 PM

What does the vertex shader that passes "pass_tex_coord" look like?

#5 k.pedersen   Members   -  Reputation: 100

Like
0Likes
Like

Posted 16 March 2012 - 05:54 PM

Here is a simplified version of my vertex shader.

#version 120

uniform mat4 in_projection;
uniform mat4 in_modelview;
attribute vec2 in_tex_coord;
attribute vec3 in_position;
varying vec2 pass_tex_coord;

void main()
{
  gl_Position = in_projection * in_modelview * vec4(in_position, 1);
  pass_tex_coord = in_tex_coord;
}


All I am really doing is passing through the texture coordinates.
Wavefront Animation Studio - Create simple animations for .obj 3D models.
libwavefront - Open-source C++/OpenGL library to load animated .obj models.

#6 NumberXaero   Members   -  Reputation: 725

Like
0Likes
Like

Posted 16 March 2012 - 07:12 PM

What does it look like if you display the texture coord as a color

gl_FragColor = vec4(pass_tex_coord.x, pass_tex_coord.y, 0.0, 1.0);

#7 k.pedersen   Members   -  Reputation: 100

Like
0Likes
Like

Posted 17 March 2012 - 06:29 AM

I have attached the result.

(Edit: Submitted new screenshot)

Tbh, I wasn't expecting the cat model or the brick platform model to be completely red.

However, I also have exactly the same problem with the skybox and as you can see in the screenshot, that looks about what I would expect.

The cat model gets it's texture from a single unwrapped texture sheet, the brick platform model gets its coordinates from gtkradiant.

All 3 models (cat, bricks, skybox) seems to work fine when using no shader at all (fixed function) so I really don't think there is anything wrong with my texture coordinates. However I am really not sure why 2 of them are showing up as red.

The cat's texture coordinates are usually between -1 and 1
The brick platform's texture coordinates can usually be between -10 and 10.

Could this have anything to do with it? Again, both these models also work with Blender too.

When I increase the size of the cat (like glScale) it also begins to get the strange coordinate skew (i.e when the faces become large enough to notice).

Attached Thumbnails

  • newss.png

Wavefront Animation Studio - Create simple animations for .obj 3D models.
libwavefront - Open-source C++/OpenGL library to load animated .obj models.

#8 MarkS   Members   -  Reputation: 571

Like
0Likes
Like

Posted 17 March 2012 - 07:28 AM

I'm very new to shaders, but when I was researching how to write a texture shader, this is what I found:

Pulled from Lighthouse3D.com...

vertex shader:

void main() {



	gl_TexCoord[0] = gl_MultiTexCoord0;

	gl_Position = ftransform();

}


fragment shader:

uniform sampler2D tex;



void main()

{

	vec4 color = texture2D(tex,gl_TexCoord[0].st);

	gl_FragColor = color;

}


Again, I am new to this, so you are probably doing this in a manor that I am unfamiliar with and most likely correct, but I have never seen a texture shader written like yours.

#9 k.pedersen   Members   -  Reputation: 100

Like
0Likes
Like

Posted 17 March 2012 - 08:20 AM

Hello MarkS,

Thanks for the info and this probably does work but is unfortunately no longer the correct way to do this.

This uses the fixed function pipeline in OpenGL such as the ftransform() and is also using the built in and deprecated matrix system provided by OpenGL.

The way the texture coordinates are passed in also uses the gl_TexCoord[0] keyword which is also deprecated but also will not work on the OpenGL ES 2.0 or 4.0 Core profiles.

Though AFAIK those texture coordinates are probably still not perspective correct either. I cannot test this because I am using the GLM matrix code rather than the OpenGL provided one and thus ftransform will not work.
Wavefront Animation Studio - Create simple animations for .obj 3D models.
libwavefront - Open-source C++/OpenGL library to load animated .obj models.

#10 MarkS   Members   -  Reputation: 571

Like
0Likes
Like

Posted 17 March 2012 - 08:29 AM

Ah. I was looking at the "#version 120". I didn't know you were trying for 4.0.

#11 k.pedersen   Members   -  Reputation: 100

Like
0Likes
Like

Posted 17 March 2012 - 01:29 PM

I went with GLSL 1.20 to ensure compatibility.. Same reason why I am looking to use stuff compatible with the 4.0 core profile and not use deprecated functionality Posted Image.

This is a screenshot of the tex coordinates as a color. (The last one was the result of my fiddling). :/

So looking at this screenshot, my texture coordinates look spot on, but I am still getting that strange perspective warp.

I have also noticed that as I look around the scene, even the colors seem to warp and change. This seems to suggest the perspective issue again :/
Do you notice the slight indent in the color where the odd texture split would be?

Attached Thumbnails

  • newss.png

Wavefront Animation Studio - Create simple animations for .obj 3D models.
libwavefront - Open-source C++/OpenGL library to load animated .obj models.

#12 k.pedersen   Members   -  Reputation: 100

Like
0Likes
Like

Posted 19 March 2012 - 05:24 AM

Hello,

I hate to bump my own topics but I still cannot seem to find a solution to this.

All the example code I have found on the internet uses deprecated methods or just plain ignores the issue.

I guess the simple question is, do I need to manipulate the UV coordinates in the vertex shader before sending them through to the fragment shader?

Best Regards,

Karsten
Wavefront Animation Studio - Create simple animations for .obj 3D models.
libwavefront - Open-source C++/OpenGL library to load animated .obj models.

#13 Relfos   Members   -  Reputation: 217

Like
0Likes
Like

Posted 19 March 2012 - 05:31 AM

I guess the simple question is, do I need to manipulate the UV coordinates in the vertex shader before sending them through to the fragment shader?


No, even under OpenGL ES 2.0 you just pass the UVs directly to the shader, and straight to texture2D()
Show how you are passing the UVs to the shader, your problem probably is there.

#14 Madhed   Members   -  Reputation: 1245

Like
0Likes
Like

Posted 19 March 2012 - 07:38 AM

This really looks like the long known perspective distortion problem which all current hardware automatically resolves.
Keep in mind that I don't know OpenGL but I found the following:

glHint(GL_PERSPECTIVE_CORRECTION_HINT,GL_NICEST);

This should tell the driver to enable perspective correction, even though I believe all drivers do this without explicitly telling them.
Tell us if it fixed anything.

EDIT: Upon further inspection of the screenshot I see that you are only using "nearest" texture lookup. Is it possible that the rendering is somehow done in software with perspective correction turned off?

#15 k.pedersen   Members   -  Reputation: 100

Like
1Likes
Like

Posted 19 March 2012 - 10:51 AM

The following is the texture coordinate related code that I use. I have missed off the vertex and normal stuff so not to spam everyone with lots of code.

Does this appear to be correct?

Defines
GLuint coodBuffer;
GLuint inTexCoord;
std::vector<float> coords;

Load
inTexCoord = glGetAttribLocation(shaderProgram, "in_tex_coord");
glGenBuffersARB(1, &coordBuffer);

for(int i = 0; faces.size(); i++)
{
  coords.push_back(faces.at(i)->getA()->getU());
  coords.push_back(faces.at(i)->getA()->getV());

  coords.push_back(faces.at(i)->getB()->getU());
  coords.push_back(faces.at(i)->getB()->getV());

  coords.push_back(faces.at(i)->getC()->getU());
  coords.push_back(faces.at(i)->getC()->getV());
}

glBindBufferARB(GL_ARRAY_BUFFER_ARB, coordBuffer);
glBufferDataARB(GL_ARRAY_BUFFER_ARB, coords.size() * sizeof(float), &coords[0], GL_STATIC_DRAW_ARB);

Draw
glEnableVertexAttribArray(inTexCoord);
glBindBuffer(GL_ARRAY_BUFFER_ARB, coordBuffer);
glVertexAttribPointerARB(inTexCoord, 2, GL_FLOAT, GL_FALSE, 0, 0);
glDrawArrays(GL_TRIANGLES, 0, faces.size() * 3);
glDisableVertexAttribArray(inTexCoord);

I have also attempted to use

glHint(GL_PERSPECTIVE_CORRECTION_HINT,GL_NICEST);

But it makes no difference. I assume this hint only has an effect when using fixed functionality?

Edit:
From Madhed's software rendering suggestion, I tried it on a different machine (with newer gfx card) and it all works perfectly.
I noticed that it ran slower using shaders than just using the fixed function pipeline suggesting that it is indeed doing some sort of software emulation.
The graphics card in question is an intel GMA 945 running on Fedora 15's Xorg.

Hmm, I guess I am forced to stick with the fixed function pipeline with this card? So much for compatibility... lol

Thank you everyone for your help. Really appreciated! I have marked the topic as solved.

Attached Thumbnails

  • working.png

Wavefront Animation Studio - Create simple animations for .obj 3D models.
libwavefront - Open-source C++/OpenGL library to load animated .obj models.

#16 Madhed   Members   -  Reputation: 1245

Like
0Likes
Like

Posted 19 March 2012 - 04:28 PM

The card, despite low end, should handle shaders up to SM2.0, probably even 3.0 just well. Driver issue?
As I said, I'm no expert on OpenGL, neither Linux...

#17 k.pedersen   Members   -  Reputation: 100

Like
0Likes
Like

Posted 20 March 2012 - 04:29 AM

True, the specs of the hardware do confirm that it should be able to work fine with the shader, they even mention the hardware perspective correction.

So yeah, it is probably a Linux driver issue. I did try out the software using the same version of Linux but on an nvidia card (using the open-source nouveau) driver and it worked fine. So it seems to be an issue with the intel drivers and my card.

This is a bit of a pain because I have spent so long on this issue lol.
Wavefront Animation Studio - Create simple animations for .obj 3D models.
libwavefront - Open-source C++/OpenGL library to load animated .obj models.




Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.



PARTNERS