PDA

View Full Version : 2D perspective correct texturing ?



SesillaAndromeda
02-03-2015, 05:26 PM
Hi,

Have you idea about opengl texturing skew quad ?

Regards

Ñuño Martínez
05-03-2015, 02:01 PM
Yes I have.

SesillaAndromeda
06-03-2015, 09:00 AM
Good!!!!.....and? ;)


Regards
Sesilla

SilverWarior
06-03-2015, 09:47 AM
Why do I have feeling that Nuno spends too much time on communities like Stack Overflow? ???
I would expect such answer on the Stack Overflow where most people blindly tends to answer the question that was asked and not the question that was intended to be asked.
Yes sometimes it is hard to figure out what asker is trying to ask. But here I think it is quite clear that Sesilla also wants to see an example of how this is done.

So Nuno can you please provide short example for rendering skew quad using OpenGL?

SilverWarior
06-03-2015, 10:01 AM
@Sesilla
While here on PGD we usually don't treat weak or broad questions as plague like they are commonly treated on Stack Overflow it is still good if you can provide more information in your question about what kind of an answer do you expect as this helps us understand of what do you need.

Also sometimes it might be better to provide description of that final results do you expect instead of asking about specific approach. Why? This way you might get answer with multiple possible approaches so you can then chose the one that suits you best.

SesillaAndromeda
06-03-2015, 11:21 AM
@SilverWarior
Thanks for your suggestions! :)

Thi is my quad:

http://www.pascalgamedevelopment.com/attachment.php?attachmentid=1353&stc=1


This is a texture:
http://www.pascalgamedevelopment.com/attachment.php?attachmentid=1354&stc=1


And this the result with possibilities to "deform" the scale or tile of the texture:
http://www.pascalgamedevelopment.com/attachment.php?attachmentid=1355&stc=1


Thanks in advance
Sesilla

SilverWarior
06-03-2015, 12:14 PM
Do you wan't the texture to be projected on your quad so that it looks like rotated plane (texture rotates and scales with the quad) or just use your quad as mask to show only part of the texture as it is done in your image example?

SesillaAndromeda
06-03-2015, 12:25 PM
The first one! :) The texture projected like pseudo 3d!

Sesilla

phibermon
06-03-2015, 04:55 PM
If you're in OpenGL then you're providing texture coordinates for the quad. Perspective correction is automatic. You provide coordinates between 0.0 and 1.0 for each of your vertices. To produce an image like you've posted you have to scale the texture coordinates in relation to your vertex coordinates, or in much older versions of GL you can use automatic texture coordinate generation which in 2D will produce the same result.

The solution for 'perspective' in 2D as you desire is to simply leave your texture coordinates at each corner of the texture while altering the vertices of the quad.

Input the vertex coordinates that would give you a quad like in the image you have provided and in counter-clockwise order (OpenGL defaults to counter-clockwise winding to determine front facing polygons) set your texture coordinates as (x:0,y:0) (x:0,y:1) (x:1,y:1) (x:1,x:0)

As long as you keep your texture coordinates the same, you can draw your (convex) quad at any combination of vertices and openGL will 'skew' the texture automatically.

SesillaAndromeda
06-03-2015, 06:25 PM
Hi phibermon,

with this code:


glBegin(GL_QUADS);

glTexCoord2f(0, 0);

glVertex2f (500, 200);

glTexCoord2f(0, 1);
glVertex2f (600, 200);

glTexCoord2f(1, 1);
glVertex2f (1000, 700);

glTexCoord2f(1, 0);
glVertex2f (50, 700);



this is the rendering:
http://www.pascalgamedevelopment.com/attachment.php?attachmentid=1356&stc=1


Browsing the web i found the Opengl glTexCoord4f function, but it is not clear about use it.

Thanks
Sesilla

phibermon
06-03-2015, 08:28 PM
Your vertices are in clockwise order and your texture coordinates are in counter-clockwise order, the GPU actually draws two triangles and not a quad and because you have opposite winding, the two triangles are getting different relative texture coordinates. Always draw two triangles instead of one quad so this fact is always present in your mind and such issues become more obvious. It's better for all kinds of technical reasons that you don't need to learn if you don't want to. try the following instead :



glBegin(GL_TRIANGLES);

glTexCoord2f(0, 0);
glVertex2f(500, 200);

glTexCoord2f(0, 1);
glVertex2f(50, 700);

glTexCoord2f(1, 1);
glVertex2f (1000, 700);


glTexCoord2f(1, 1);
glVertex2f (1000, 700);

glTexCoord2f(1, 0);
glVertex2f (600, 200);


glTexCoord2f(0, 0);
glVertex2f(500, 200);

glEnd();



Counter-clockwise always for coordinates. OpenGL and other API's like Direct3D use what is called the 'winding order' to determine if a one sided polygon is facing you (the 'camera') ( one sided polygon = default OpenGL state - simply meaning that it will be invisible if viewed from the other side. This implies that you can render two-sided polygons that are visible from both sides and this is true. This would seem preferable as you don't have to care about winding but in reality it slows down rendering as discarding polygons that can't be seen is one of the main principals behind rendering things more quickly. In 2D this isn't really an issue as you'll never be 'looking' from the other side of the polygon but it's best practice and should you move to 3D you'll already be doing things correctly)

SesillaAndromeda
06-03-2015, 08:49 PM
Hi

thanks for your reply, but with your code this is the result:

http://www.pascalgamedevelopment.com/attachment.php?attachmentid=1357&stc=1

Have i done something wrong?

Thanks
Sesilla

phibermon
06-03-2015, 09:22 PM
Ah my apolgies, it's been a long time since I worked in immediate GL mode. The way this would be done now is by using a projection sampler in a shader. However, I believe that immediate GL had a nice friendly trick that does some magic for you. Add the following somewhere in your initialization code, before you call GL_Begin() :

glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);

Hopefully my memory has not failed me and this should produce your desired result.

phibermon
06-03-2015, 09:32 PM
Bare in mind that GLHINT may not produce this same magic on all cards. The correct way is to use 4D texture coordinates so you can control this behaviour in the correct manner.

See this page :

https://home.xyzw.us/~cass/qcoord/

My guess is that some drivers will handle this and other will not so by controlling all four parameters of the texture coords you can guarantee desired behaviour on all cards.

SesillaAndromeda
07-03-2015, 01:22 PM
Hi,

have you idea about to implement this?




See this page :

https://home.xyzw.us/~cass/qcoord/


Thanks
Sesilla

SilverWarior
07-03-2015, 06:12 PM
Didn't you also messed up with the coordinates here? Specifically for second triangle?





glBegin(GL_TRIANGLES);

//FirstTriangle

//TopLeft
glTexCoord2f(0, 0);
glVertex2f(500, 200);

//BottomLeft
glTexCoord2f(0, 1);
glVertex2f(50, 700);

//BottomRight
glTexCoord2f(1, 1);
glVertex2f (1000, 700);


//SecondTriangle

//BottomRight
glTexCoord2f(1, 1);
glVertex2f (1000, 700);

//TopRight
glTexCoord2f(1, 0);
glVertex2f (600, 200);

//TopLeft
glTexCoord2f(0, 0);
glVertex2f(500, 200);

glEnd();




Shouldn't the order of coordinates for second triagnle be TopLeft, BottomRight, TopRight?

Ñuño Martínez
08-03-2015, 07:50 PM
Why do I have feeling that Nuno spends too much time on communities like Stack Overflow? ??? I don't know, because I never used Stack Overflow, and I don't know if any other or the communities I spend too much time on are like that as I never used it.


I would expect such answer on the Stack Overflow where most people blindly tends to answer the question that was asked and not the question that was intended to be asked. I can answer this:

That's because, in my experience, the question that was intended to be asked is often not the actual question that should be asked. And if I've understood correctly the other messages, this is one of these cases. (Please, correct me if I'm wrong in this: I'm still learning English)


So Nuno can you please provide short example for rendering skew quad using OpenGL? Of course I can, but it would be too similar to the one provided by phibermon (http://www.pascalgamedevelopment.com/showthread.php?32437-2D-perspective-correct-texturing&p=146816&viewfull=1#post146816). ;)

[Disclaimer]: I must apoligize. Some times I can be too much sarcastic. Please, no offense intended. If you think I've exceed the limit, please tell me and I'll try to keep my responses under control. Really.


Didn't you also messed up with the coordinates here? Specifically for second triangle?


...

Shouldn't the order of coordinates for second triagnle be TopLeft, BottomRight, TopRight?

Yes, on the first triangle is counter-clockwise and the second is clockwise. Both them should have the same "wise" to use back face culling correctly.

SesillaAndromeda
09-03-2015, 12:17 AM
Hi Ñuño,

sorry for may question, but I need only help for my problem. That's it!

Regards
Sesilla

phibermon
09-03-2015, 03:14 AM
Didn't you also messed up with the coordinates here? Specifically for second triangle?



Shouldn't the order of coordinates for second triagnle be TopLeft, BottomRight, TopRight?

No I didn't mess up, they should be in counter-clockwise order, in this example I did BottomRight, TopRight, TopLeft. You can start at ANY point, as long as you go round in a counter-clockwise direction. Take a look at my coordinates then take a look at a clock. You don't have to start from any specific position, only the winding matters. Imagine yourself standing in the middle of the triangle, now look at each of my points in turn, you are spinning in a counter-clockwise direction.


Yes, on the first triangle is counter-clockwise and the second is clockwise. Both them should have the same "wise" to use back face culling correctly

No, both triangles are counter-clockwise, it's called the winding order and normal determination is used for an awful lot more than just back face culling. I just didn't start from the 'top-left'. There's no such thing as Top Left, Bottom Right etc - these are over simplified descriptions given in examples to teach people. In your world of winding the moment I roll my airpane onto its side, all the polygons disappear. You are mistaken. Please check again.


------------



glBegin(GL_TRIANGLES);

//Triangle 1 (counter-clockwise)

//Top Left
glTexCoord4f(0, 0, 0, 600-500);
glVertex2f(500, 200);

//Bottom Left
glTexCoord4f(0, 1000-50, 0, 1000-50);
glVertex2f(50, 700);

//Bottom Right
glTexCoord4f(1000-50, 1000-50, 0, 1000-50);
glVertex2f(1000, 700);

//Triangle 2 (counter-clockwise)

//Bottom Right
glTexCoord4f(1000-50, 1000-50, 0, 1000-50);
glVertex2f(1000, 700);

//Top Right
glTexCoord4f(600-500, 0, 0, 600-500);
glVertex2f(600, 200);

//Top Left
glTexCoord4f(0, 0, 0, 600-500);
glVertex2f(500, 200);

glEnd();



Note how Q (fourth argument) is set to the width at the top for the top coordinates, and the width of the bottom for the bottom coordinates, then we've used the width as the maximum value of S *OR* T coordinates. You could add 'perspective' like this on any axis, just be sure to set Q as the width and then know that your maximum position on the texture in either axis is Q.


Perhaps it would be best for you to skew your image in another program and just use that modified image on a regular quad in order to save confusion. currently your 'quad' is on a single plane that is parallel with the camera plane and we're 'skewing'. If our quad were specified in 3D coordinates and orientated to the camera to replicate the results of your code then you'd just specify the texture coordinates like you initially did.


note : glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST) is not needed in this example, on *some* drivers it will scale your texture coordinates automatically for polygons specified with glVertex2F (and you may have to use automatic texture coordinate generation) but how we're achieving the results here will work regardless.