1

A while ago I asked a question similar to this one, but in that case I was trying to correct the perspective texture mapping of a trapezoid that had the horizontal lines constantly parallel with glTexCoord4f() and this is relatively simple. However, now I'm trying to fix the texture mapping of the floor and ceiling in my engine, the problem is that since both depend on the shape of the map, I need to use triangles to fill in the polygonal shapes that the map may contain.

I tried a few variations of the same method I used for correct texture mapping on trapezoids, the attempt with more "acceptable" results were when I calculated the size of the triangle's edges (with screen coordinates) and used each result in the different 'q' in each glTexCoord4f(), that is how code currently stands.

With that in mind, how can I fix this while using glTexCoord4f()?

Here is the code I used to correct the texture mapping of the walls (functional):

float u, v;
glEnable(GL_TEXTURE_2D);
glEnable(GL_DEPTH_TEST);

float sza = wyaa - wyab; //Size of the first vertical edge on the wall
float szb = wyba - wybb; //Size of the second vertical edge on the wall
    
//Does the wall have streeched textures?
if(!(*wall).streechTexture){
    u = -texLength;
    v = -texHeight;
}else{
    u = -1;
    v = -1;
}

glBindTexture (GL_TEXTURE_2D, texture.at((*wall).texture));
glBegin(GL_TRIANGLE_STRIP);

glTexCoord4f(0, 0, 0, sza);
glVertex3f(wxa, wyaa + shearing, -tza * 0.001953);

glTexCoord4f(u * szb, 0, 0, szb);
glVertex3f(wxb, wyba + shearing, -tzb * 0.001953);

glTexCoord4f(0, v * sza, 0, sza);
glVertex3f(wxa, wyab + shearing, -tza * 0.001953);

glTexCoord4f(u * szb, v * szb, 0, szb);
glVertex3f(wxb, wybb + shearing, -tzb * 0.001953);
            
glEnd();
glDisable(GL_TEXTURE_2D);

And here the current code that renders both the floor and the ceiling (which needs to be fixed):

glEnable(GL_TEXTURE_2D);
glBindTexture (GL_TEXTURE_2D, texture.at((*floor).texture));
float difA, difB, difC;

difA = vectorMag(Vertex(fxa, fyaa), Vertex(fxb, fyba)); //Size of the first edge on the triangle
difB = vectorMag(Vertex(fxb, fyba), Vertex(fxc, fyca)); //Size of the second edge on the triangle
difC = vectorMag(Vertex(fxc, fyca), Vertex(fxa, fyaa)); //Size of the third edge on the triangle

glBegin(GL_TRIANGLE_STRIP); //Rendering the floor
glTexCoord4f(ua * difA, va * difA, 0, difA);
glVertex3f(fxa, fyaa + shearing, -tza * 0.001953);

glTexCoord4f(ub * difB, vb * difB, 0, difB);
glVertex3f(fxb, fyba + shearing, -tzb * 0.001953);

glTexCoord4f(uc * difC, vc * difC, 0, difC);
glVertex3f(fxc, fyca + shearing, -tzc * 0.001953);
glEnd();


glBegin(GL_TRIANGLE_STRIP); //Rendering the ceiling
glTexCoord4f(uc, vc, 0, 1);
glVertex3f(fxc, fycb + shearing, -tzc * 0.001953);

glTexCoord4f(ub, vb, 0, 1);
glVertex3f(fxb, fybb + shearing, -tzb * 0.001953);

glTexCoord4f(ua, va, 0, 1);
glVertex3f(fxa, fyab + shearing, -tza * 0.001953);
glEnd();

glDisable(GL_TEXTURE_2D);

Here a picture of how it looks visually (for comparison purposes, the floor has the failed attempt at correct texture mapping, while the ceiling has affine texture mapping):

I understand that it would be easier if I just set a normal perspective view, but that would simply defeat the whole purpose of the engine.

Rabbid76
  • 202,892
  • 27
  • 131
  • 174
Dr. Ether
  • 11
  • 1
  • As I mentioned in the previous post, I understand that it would be much easier, but the point of the thing is precisely to do 3D rendering manually in more or less the same way as the engines of the time did, while not going that low level. – Dr. Ether Oct 01 '21 at 16:28
  • Why do you repeat the question? Repeating questions to attract attention is not welcome. – Rabbid76 Oct 01 '21 at 16:30
  • In the previous case, I was dealing only with trapezoids, and as is visible in the image, I have already corrected it, but I was mistaken in thinking that it would be just as easy to correct it on triangles. Also, this is only my second post here, I couldn't find a way to close the previous question or just delete it. – Dr. Ether Oct 01 '21 at 16:34
  • I was able to delete the previous post, no big problem now. – Dr. Ether Oct 01 '21 at 16:35
  • @Dr.Ether but you lost all the comments there ... and people that where active there might not see this new incarnation. Its better to edit in new info to original post and notify users by comments ... Even Closed questions can be reopened if they improve enough ... – Spektre Oct 03 '21 at 07:04
  • I realized after a while about this, but the solution you have in this post will also work for that specific case, so that's okay. I'll try to be better oriented in my next posts, sorry! – Dr. Ether Oct 03 '21 at 20:20

1 Answers1

0

This is an issue only for floor and ceiling (unless your camera can tilt). So you can render your wals as you doing. But for floors and ceiling you have these basic options (As I mentioned in your old duplicate post):

  1. Rasterize scan line on your own

    So instead of rendering triangles (which old ray casters did not do) you render vertical lines pixel by pixel using points instead of triangles. That will be much slower of coarse as GL is more suited for polygonal primitives. See draw_scanline functions in here:

  2. Use perspective view and pass z coordinate

    Looks like you added the z coordinate already. So now you just need to set perspective view that matches your wall rendering. OpenGL will do the rest on its own. So you should add something like gluPerspective for your GL_PROJECTION matrix. but just for your floors/ceilings ...

  3. Pass z coordinate and overide fragment shader

    So you just write fragment shader that computes the perspective correct texture mapping correction in it and just output wanted texel color +/- some lighting. Here example of shaders usage:

For more info see:

Spektre
  • 49,595
  • 11
  • 110
  • 380
  • Thanks for the solutions! I already corrected it a while ago using the Z distance, but I didn't understand the concept of "homogeneous coordinates". Only after a while I understood that I should multiply the Z distance to be in scale with the screen coordinates, I had not needed to do this on the walls because the subtraction of the Y position of the two vertices of the wall on the screen returned exactly the same value if I did the calculation "Screen size * Z distance". – Dr. Ether Oct 03 '21 at 20:16