0

Let's say I start with a quad that covers the entire screen space just. I then put it through a projection matrix so that it appears as a trapezoid on the screen. There is a texture on this. As the base of the trapezoid is meant to be closer to the camera, opengl correctly renders the texture such that things in the texture appear bigger at the base of the trapezoid (as this is seemingly closer to the camera).

How does OpenGL know to render the texture itself in this perspective-based way rather than just stretching the sides of the texture into the trapezoid shape? Certainly it must be using the vertex z values, but how does it use those to map to textures in the fragment shader? In the fragment shader it feels like I am just working with x and y coordinates of textures with no z values being relevant.

EDIT:

I tried using the information provided in the links in the comments. I am not sure if there is information I am missing related to my question specifically, or if I am doing something incorrectly.

What I am trying to do is make a (if you don't know what this is, it's ok, I explain further what I'm trying to do) pseudo 3D SNES Mode 7-like projection.

Here's how it's coming out now.

enter image description here

As you can see something funny is happening. You can clearly see that the quad is actually 2 triangles and the black text area at the top should be straight, not crooked.

Whatever is happening, it's clear that the triangle on the left and the triangle on the right have their textures being rendered differently. The z-values are not being changed. Based on info in links in the comments I thought that I could simply move the top two vertices of my rectangular quad inward so that it became a trapezoid instead and this would act like a projection.

I know that a "normal" thing to do would be to use glm::lookat for a view matrix and glm::perspective for a projection matrix, but these are a little bit of black boxes to me and I would rather find a more easy-to-understand way.

I may have already provided enough info for someone to answer, but just in case, here is my code:

Vertex Shader:

#version 330 core
layout (location = 0) in vec3 position;
layout (location = 2) in vec2 texCoord;

out vec2 TexCoord;

void main()
{
    // adjust vertex positions to make rectangle into trapezoid
    if( position.y < 0){
        gl_Position = vec4(position.x * 2.0, position.y * 2.0, 0.0, 1.0);
    }else {
        gl_Position = vec4(position.x * 1.0, position.y * 2.0, 0.0, 1.0);
    }

    TexCoord = vec2(texCoord.x, 1.0 - texCoord.y);
}

Fragment Shader:

#version 330 core
in vec2 TexCoord;

out vec4 color;

uniform sampler2D ourTexture1;

uniform mat3 textures_transform_mat_input;

mat3 TexCoord_to_mat3;
mat3 foo_mat3;

void main()
{

    TexCoord_to_mat3[0][0] = 1.0;
    TexCoord_to_mat3[1][1] = 1.0;
    TexCoord_to_mat3[2][2] = 1.0;
    TexCoord_to_mat3[0][2] = TexCoord.x;
    TexCoord_to_mat3[1][2] = TexCoord.y;

    foo_mat3 = TexCoord_to_mat3 * textures_transform_mat_input;
    vec2 foo = vec2(foo_mat3[0][2], foo_mat3[1][2]);

    vec2 bar = vec2(TexCoord.x, TexCoord.y);
    color = texture(ourTexture1, foo);  

    vec2 center = vec2(0.5, 0.5);

}

Relevant code in main (note I am using a C library, CGLM that is like GLM; also, the "center" and "center undo" stuff is just to make sure rotation happens about the center rather than a corner):

if(!init_complete){

    glm_mat3_identity(textures_scale_mat);
    textures_scale_mat[0][0] = 1.0/ASPECT_RATIO /   3.0; 
    textures_scale_mat[1][1] = 1.0/1.0          /   3.0;
}

mat3 center_mat;

center_mat[0][0] = 1.0;
center_mat[1][1] = 1.0;
center_mat[2][2] = 1.0;
center_mat[0][2] = -0.5;
center_mat[1][2] = -0.5; 

mat3 center_undo_mat;

center_undo_mat[0][0] = 1.0;
center_undo_mat[1][1] = 1.0;
center_undo_mat[2][2] = 1.0;
center_undo_mat[0][2] = 0.5;
center_undo_mat[1][2] = 0.5;    

glm_mat3_identity(textures_position_mat);
textures_position_mat[0][2] = player.y / 1.0;
textures_position_mat[1][2] = player.x / 1.0;

glm_mat3_identity(textures_orientation_mat);
textures_orientation_mat[0][0] = cos(player_rotation_radians);
textures_orientation_mat[0][1] = sin(player_rotation_radians);
textures_orientation_mat[1][0] = -sin(player_rotation_radians);
textures_orientation_mat[1][1] = cos(player_rotation_radians);

glm_mat3_identity(textures_transform_mat);
glm_mat3_mul(center_mat, textures_orientation_mat, textures_transform_mat);
glm_mat3_mul(textures_transform_mat, center_undo_mat, textures_transform_mat);

glm_mat3_mul(textures_transform_mat, textures_scale_mat, textures_transform_mat);
glm_mat3_mul(textures_transform_mat, textures_position_mat, textures_transform_mat);

glUniformMatrix3fv(glGetUniformLocation(shader_perspective, "textures_transform_mat_input"), 1, GL_FALSE, textures_transform_mat);

glBindTexture(GL_TEXTURE_2D, texture_mute_city);

glDrawArrays(GL_TRIANGLES, 0, 6);
Steven2163712
  • 169
  • 2
  • 12
  • "*I then put it through a projection matrix so that it appears as a trapezoid on the screen.*" If a quad "covers the entire screen space", why would its projection be a trapezoid? – Nicol Bolas Mar 04 '18 at 14:33
  • Possible duplicate of [How exactly does OpenGL do perspectively correct linear interpolation?](https://stackoverflow.com/questions/24441631/how-exactly-does-opengl-do-perspectively-correct-linear-interpolation) – Nico Schertler Mar 04 '18 at 18:39
  • It would be a trapezoid because after multiplying the position vector of the vertices by a projection matrix, I would get a trapezoid shape rather than just a rectangle. Thank you all for the references that for some reason I wasn't able to find before. I think it will solve my problem. – Steven2163712 Mar 04 '18 at 21:45

0 Answers0