Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • SEARCH
  • Home
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 555615
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: May 13, 20262026-05-13T11:49:59+00:00 2026-05-13T11:49:59+00:00

I’m making a software rasterizer, and I’ve run into a bit of a snag:

  • 0

I’m making a software rasterizer, and I’ve run into a bit of a snag: I can’t seem to get perspective-correct texture mapping to work.

My algorithm is to first sort the coordinates to plot by y. This returns a highest, lowest and center point. I then walk across the scanlines using the delta’s:

// ordering by y is put here

order[0] = &a_Triangle.p[v_order[0]];
order[1] = &a_Triangle.p[v_order[1]];
order[2] = &a_Triangle.p[v_order[2]];

float height1, height2, height3;

height1 = (float)((int)(order[2]->y + 1) - (int)(order[0]->y));
height2 = (float)((int)(order[1]->y + 1) - (int)(order[0]->y));
height3 = (float)((int)(order[2]->y + 1) - (int)(order[1]->y));

// x 

float x_start, x_end;
float x[3];
float x_delta[3];

x_delta[0] = (order[2]->x - order[0]->x) / height1;
x_delta[1] = (order[1]->x - order[0]->x) / height2;
x_delta[2] = (order[2]->x - order[1]->x) / height3;

x[0] = order[0]->x;
x[1] = order[0]->x;
x[2] = order[1]->x;

And then we render from order[0]->y to order[2]->y, increasing the x_start and x_end by a delta. When rendering the top part, the delta’s are x_delta[0] and x_delta[1]. When rendering the bottom part, the delta’s are x_delta[0] and x_delta[2]. Then we linearly interpolate between x_start and x_end on our scanline. UV coordinates are interpolated in the same way, ordered by y, starting at begin and end, to which delta’s are applied each step.

This works fine except when I try to do perspective correct UV mapping. The basic algorithm is to take UV/z and 1/z for each vertex and interpolate between them. For each pixel, the UV coordinate becomes UV_current * z_current. However, this is the result:

alt text

The inversed part tells you where the delta’s are flipped. As you can see, the two triangles both seem to be going towards different points in the horizon.

Here’s what I use to calculate the Z at a point in space:

float GetZToPoint(Vec3 a_Point)
{
    Vec3 projected = m_Rotation * (a_Point - m_Position);

    // #define FOV_ANGLE 60.f
    // static const float FOCAL_LENGTH = 1 / tanf(_RadToDeg(FOV_ANGLE) / 2);
    // static const float DEPTH = HALFHEIGHT * FOCAL_LENGTH; 
    float zcamera = DEPTH / projected.z;

    return zcamera;
}

Am I right, is it a z buffer issue?

  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-05-13T11:49:59+00:00Added an answer on May 13, 2026 at 11:49 am

    ZBuffer has nothing to do with it.

    THe ZBuffer is only useful when triangles are overlapping and you want to make sure that they are drawn correctly (e.g. correctly ordered in the Z). The ZBuffer will, for every pixel of the triangle, determine if a previously placed pixel is nearer to the camera, and if so, not draw the pixel of your triangle.

    Since you are drawing 2 triangles which don’t overlap, this can not be the issue.

    I’ve made a software rasterizer in fixed point once (for a mobile phone), but I don’t have the sources on my laptop. So let me check tonight, how I did it. In essence what you’ve got is not bad! A thing like this could be caused by a very small error

    General tips in debugging this is to have a few test triangles (slope left-side, slope right-side, 90 degree angles, etc etc) and step through it with the debugger and see how your logic deals with the cases.

    EDIT:

    peudocode of my rasterizer (only U, V and Z are taken into account… if you also want to do gouraud you also have to do everything for R G and B similar as to what you are doing for U and V and Z:

    The idea is that a triangle can be broken down in 2 parts. The top part and the bottom part. The top is from y[0] to y[1] and the bottom part is from y[1] to y[2]. For both sets you need to calculate the step variables with which you are interpolating. The below example shows you how to do the top part. If needed I can supply the bottom part too.

    Please note that I do already calculate the needed interpolation offsets for the bottom part in the below ‘pseudocode’ fragment

    • first order the coords(x,y,z,u,v) in the order so that coord[0].y < coord[1].y < coord[2].y
    • next check if any 2 sets of coordinates are identical (only check x and y). If so don’t draw
    • exception: does the triangle have a flat top? if so, the first slope will be infinite
    • exception2: does the triangle have a flat bottom (yes triangles can have these too ;^) ) then the last slope too will be infinite
    • calculate 2 slopes (left side and right side)
      leftDeltaX = (x[1] – x[0]) / (y[1]-y[0]) and rightDeltaX = (x[2] – x[0]) / (y[2]-y[0])
    • the second part of the triangle is calculated dependent on: if the left side of the triangle is now really on the leftside (or needs swapping)

    code fragment:

     if (leftDeltaX < rightDeltaX)
     {
          leftDeltaX2 = (x[2]-x[1]) / (y[2]-y[1])
          rightDeltaX2 = rightDeltaX
          leftDeltaU = (u[1]-u[0]) / (y[1]-y[0]) //for texture mapping
          leftDeltaU2 = (u[2]-u[1]) / (y[2]-y[1])
          leftDeltaV = (v[1]-v[0]) / (y[1]-y[0]) //for texture mapping
          leftDeltaV2 = (v[2]-v[1]) / (y[2]-y[1])
          leftDeltaZ = (z[1]-z[0]) / (y[1]-y[0]) //for texture mapping
          leftDeltaZ2 = (z[2]-z[1]) / (y[2]-y[1])
     }
     else
     {
          swap(leftDeltaX, rightDeltaX);
          leftDeltaX2 = leftDeltaX;
          rightDeltaX2 = (x[2]-x[1]) / (y[2]-y[1])
          leftDeltaU = (u[2]-u[0]) / (y[2]-y[0]) //for texture mapping
          leftDeltaU2 = leftDeltaU
          leftDeltaV = (v[2]-v[0]) / (y[2]-y[0]) //for texture mapping
          leftDeltaV2 = leftDeltaV
          leftDeltaZ = (z[2]-z[0]) / (y[2]-y[0]) //for texture mapping
          leftDeltaZ2 = leftDeltaZ
      }
    
    • set the currentLeftX and currentRightX both on x[0]
    • set currentLeftU on leftDeltaU, currentLeftV on leftDeltaV and currentLeftZ on leftDeltaZ
    • calc start and endpoint for first Y range: startY = ceil(y[0]); endY = ceil(y[1])
    • prestep x,u,v and z for the fractional part of y for subpixel accuracy (I guess this is also needed for floats)
      For my fixedpoint algorithms this was needed to make the lines and textures give the illusion of moving in much finer steps then the resolution of the display)
    • calculate where x should be at y[1]: halfwayX = (x[2]-x[0]) * (y[1]-y[0]) / (y[2]-y[0]) + x[0]
      and same for U and V and z: halfwayU = (u[2]-u[0]) * (y[1]-y[0]) / (y[2]-y[0]) + u[0]
    • and using the halfwayX calculate the stepper for the U and V and z:
      if(halfwayX – x[1] == 0){ slopeU=0, slopeV=0, slopeZ=0 } else { slopeU = (halfwayU – U[1]) / (halfwayX – x[1])} //(and same for v and z)
    • do clipping for the Y top (so calculate where we are going to start to draw in case the top of the triangle is off screen (or off the clipping rectangle))
    • for y=startY; y < endY; y++)
      {

      • is Y past bottom of screen? stop rendering!
      • calc startX and endX for the first horizontal line
        leftCurX = ceil(startx); leftCurY = ceil(endy);
      • clip the line to be drawn to the left horizontal border of the screen (or clipping region)
      • prepare a pointer to the destination buffer (doing it through array indexes everytime is too slow)
        unsigned int buf = destbuf + (ypitch) + startX; (unsigned int in case you are doing 24bit or 32 bits rendering)
        also prepare your ZBuffer pointer here (if you are using this)
      • for(x=startX; x < endX; x++)
        {

        • now for perspective texture mapping (using no bilineair interpolation you do the following):

    code fragment:

             float tv = startV / startZ
             float tu = startU / startZ;
             tv %= texturePitch;  //make sure the texture coordinates stay on the texture if they are too wide/high
             tu %= texturePitch;  //I'm assuming square textures here. With fixed point you could have used &=
             unsigned int *textPtr = textureBuf+tu + (tv*texturePitch);   //in case of fixedpoints one could have shifted the tv. Now we have to multiply everytime. 
             int destColTm = *(textPtr);  //this is the color (if we only use texture mapping)  we'll be needing for the pixel
    
    • dummy line
      • dummy line
        • dummy line
        • optional: check the zbuffer if the previously plotted pixel at this coordinate is higher or lower then ours.
        • plot the pixel
        • startZ += slopeZ; startU+=slopeU; startV += slopeV; //update all interpolators
      • } end of x loop
      • leftCurX+= leftDeltaX; rightCurX += rightDeltaX; leftCurU+= rightDeltaU; leftCurV += rightDeltaV; leftCurZ += rightDeltaZ; //update Y interpolators
    • } end of y loop

      //this is the end of the first part. We now have drawn half the triangle. from the top, to the middle Y coordinate.
      // we now basically do the exact same thing but now for the bottom half of the triangle (using the other set of interpolators)

    sorry about the ‘dummy lines’.. they were needed to get the markdown codes in sync. (took me a while to get everything sort off looking as intended)

    let me know if this helps you solve the problem you are facing!

    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

link Im having trouble converting the html entites into html characters, (&# 8217;) i
I have a jquery bug and I've been looking for hours now, I can't
I have a string like this: La Torre Eiffel paragonata all&#8217;Everest What PHP function
this is what i have right now Drawing an RSS feed into the php,
I have a French site that I want to parse, but am running into
I would like to run a str_replace or preg_replace which looks for certain words
I'm parsing an RSS feed that has an &#8217; in it. SimpleXML turns this
Does anyone know how can I replace this 2 symbol below from the string
I am currently running into a problem where an element is coming back from
I'm making a simple page using Google Maps API 3. My first. One marker

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.