0
\$\begingroup\$

I am writing a software renderer with allegro5, but without using its own triangle drawing functions, I use the al_draw_prim function to draw the triangles but with all the z coordinates at zero, the problem I have is precisely with the textures that are not visible In perspective, I have looked for a lot of information about it and I know that I have to take into account the z or w coordinate of the projection matrix in some way, but I can't make it work, this is my drawing function to draw the triangles:

It works this way:

  1. the function receives a matrix with the result of the multiplication of all the matrices, whether rotation or translation, and multiplies them by the projection matrix.
  2. then I multiply this 4x4 matrix by all the vertices of the triangle
  3. I order the triangles with the furthest one first in the array and the closest one last.
  4. I painted the triangle with al_draw_prim from allegro5 and all the z coordinates at zero.

If you look at my cube, you'll see the wrong perspective of the texture.

enter image description here

Note: I have to multiply the texture coordinates by the width and height since the Allegro 5 function only accepts pixels.

void drawTrianglePerspective(typeFace *caras, int lenCaras, typeMatrix &m1, int modo, ALLEGRO_BITMAP *imagen, float fov, float nearFov,float anchoPantalla,float altoPantalla) {
    typeVertex nv;
    float escala = 0;
    float x = 0;
    float y = 0;
    float z = 0;
    float u = 0;
    float v = 0;
    float anchoImagen = (imagen!=NULL)? al_get_bitmap_width(imagen) : 0;
    float altoImagen = (imagen!=NULL)? al_get_bitmap_height(imagen) : 0;
    
    typeMatrix proyeccion;
    matrixProjection(proyeccion,nearFov,fov,100.0f,anchoPantalla,altoPantalla);
    
    typeMatrix P;
    addMatrix(proyeccion,m1,P); // multiply two matrices, the projection matrix and the result of the rotations, translations, etc. and save the result in P
    
    dcaras Tri[lenCaras]; // triangle
    
    for(int i = 0; i < lenCaras; i++ ) {

        Tri[i].vert[0] = { .x = 0, .y = 0, .z = 0, .u = 0, .v = 0 };
        Tri[i].vert[1] = { .x = 0, .y = 0, .z = 0, .u = 0, .v = 0 };
        Tri[i].vert[2] = { .x = 0, .y = 0, .z = 0, .u = 0, .v = 0 };
        
        matrixToVector(P, *caras[i].v0 ,nv);
        
        //escala = fov / ( nearFov + nv.z );
        x = (nv.x+1.0f) * 0.5f * anchoPantalla;//nv.x * escala + anchoPantalla / 2;
        y = (nv.y+1.0f) * 0.5f * altoPantalla;//nv.y * escala + altoPantalla / 2;
        Tri[i].vert[0].x = x;
        Tri[i].vert[0].y = y;
        Tri[i].z[0] = nv.z; // to paint the triangle in order of depth
        Tri[i].vert[0].u = (*caras[i].v0).u*anchoImagen;
        Tri[i].vert[0].v = (*caras[i].v0).v*altoImagen;
        Tri[i].vert[0].color = al_map_rgba_f((*caras[i].v0).r, (*caras[i].v0).g, (*caras[i].v0).b, (*caras[i].v0).a);
        
        
        matrixToVector(P, *caras[i].v1 ,nv);
        
        //escala = fov / ( nearFov + nv.z );
        x = (nv.x+1.0f) * 0.5f * anchoPantalla;//nv.x * escala + anchoPantalla / 2;
        y = (nv.y+1.0f) * 0.5f * altoPantalla;//nv.y * escala + altoPantalla / 2;
        Tri[i].vert[1].x = x;
        Tri[i].vert[1].y = y;
        Tri[i].z[1] = nv.z; // to paint the triangle in order of depth
        Tri[i].vert[1].u = (*caras[i].v1).u*anchoImagen;
        Tri[i].vert[1].v = (*caras[i].v1).v*altoImagen;
        Tri[i].vert[1].color = al_map_rgba_f((*caras[i].v1).r, (*caras[i].v1).g, (*caras[i].v1).b, (*caras[i].v1).a);
        
        
        matrixToVector(P, *caras[i].v2 ,nv);
        
        //escala = fov / ( nearFov + nv.z );
        x = (nv.x+1.0f) * 0.5f * anchoPantalla;//nv.x * escala + anchoPantalla / 2;
        y = (nv.y+1.0f) * 0.5f * altoPantalla;//nv.y * escala + altoPantalla / 2; 
        Tri[i].vert[2].x = x;                          
        Tri[i].vert[2].y = y;
        Tri[i].z[2] = nv.z; // to paint the triangle in order of depth
        Tri[i].vert[2].u = (*caras[i].v2).u*anchoImagen;
        Tri[i].vert[2].v = (*caras[i].v2).v*altoImagen;
        Tri[i].vert[2].color = al_map_rgba_f((*caras[i].v2).r, (*caras[i].v2).g, (*caras[i].v2).b, (*caras[i].v2).a);
        
    }
    
    // arranges the triangles in the array in order, the furthest one is painted first and the nearest one last
    ZOrden(Tri,lenCaras);
    
    // paint the triangle with allegro 5 with al_draw_prim the z coordinate is ignored
    for(int i = 0; i < lenCaras; i++ ) {
        al_draw_prim(Tri[i].vert, NULL, imagen, 0, 3, ALLEGRO_PRIM_TRIANGLE_STRIP);
        al_draw_prim(Tri[i].vert, NULL, NULL, 0, 3, ALLEGRO_PRIM_LINE_LOOP);
    }
}
\$\endgroup\$
5
  • 1
    \$\begingroup\$ You're using affine texture mapping, which does not account for the nonlinearity induced by the depth divide in a perspective projection. Check out past Q&A on perspective-correct texturing to see how to fix this. \$\endgroup\$
    – DMGregory
    Apr 2 at 2:38
  • \$\begingroup\$ Hello, thanks for your comment, but the problem with those solutions is that they are designed for a custom triangle drawing algorithm, but I use allegro to draw the triangle so I can only adjust the texture by the UV of the triangle vertices. and not per pixel \$\endgroup\$
    – Ivan Rojas
    Apr 2 at 10:24
  • \$\begingroup\$ You'll need to remove the perspective projection and z-flattening steps from your code and instead provide the perspective transformation to Allegro, so it can both transform the vertices and apply perspective-correct interpolation. Without access to this depth information, it won't be able to adjust the texturing correctly. \$\endgroup\$
    – DMGregory
    Apr 2 at 11:31
  • \$\begingroup\$ I had also tried passing the Z coordinate to the allegro function, but the cube was not displayed, I handle all the vertices manually with math, rotation, translation, etc, but when multiplying the vertices by the matrix containing all the rotation, translation transformations , projection, etc. There was simply nothing shown on the screen, I thought it was because I was behind the camera but no, when I set the z coordinate of the vertices to zero it does work, the idea of what I do is to control the vertices with mathematics \$\endgroup\$
    – Ivan Rojas
    Apr 2 at 12:40
  • \$\begingroup\$ , I try From learning software to render well with math, I know I could pass the z coordinate to allegro and try to control the vertices with math but it doesn't work and I'm using 4x4 matrices that are supposed to be for 3D transformations \$\endgroup\$
    – Ivan Rojas
    Apr 2 at 12:40

0

You must log in to answer this question.

Browse other questions tagged .