<p>I strongly suspect that you are simply running out of floating point precision (at least in "U" dimension). With this sort of mathematics, the LSBs will soon become noisy resulting in the jagged appearance when you are (effectively) doing yes/no comparisons against known constants.</p>

<p>May I suggest instead that, rather than doing point sampling of your texture, try doing (at the very least) bilinear filtering which will hide the precision artefacts and also IMHO look better than having little squares.</p>

<p><strong>UPDATE</strong> It just occurred to me that one of the possible causes of inaccuracy is that you are doing increments for each pixel X step, e.g. these two</p>

<pre><code>w  += wStep;
texCoords += texCoordsStep;
</code></pre>

<p>These will soon cause errors to accumulate. Remove them and replace with multiplies by the X value and I expect things should improve.</p>

<p><strong>UPDATE2</strong> It will also be affected by how far away from the origin of the texture you are when you sample it. If, for example, your source texture is defined over [0..1]x[0..1] and then repeats outside of that range, you might expect sampling  at uv = (1000000.125, 100000.125) to be the same as (0.125,0.125) but, because the precision of FP decreases with increasing magnitude (i.e. the steps between floats also increases), you might end up with something quite different.</p>

CC BY-SA 3.0
2016-10-11T19:12:49.050Z
Yeah, that's kind of what I expected. But it has to work somehow...
lelgetrekt
CC BY-SA 3.0
2016-10-11T19:13:44.920Z
I already have bilinear filtering but I like to have both. This gives it sort of a retro look
lelgetrekt
CC BY-SA 3.0
2016-10-12T08:14:38.900Z
@Leon2806 see update re not doing per-pixel increments.
Simon F
CC BY-SA 3.0
2016-10-12T12:44:28.677Z
I'm not sure if I completely  understand what you mean. Should I multiply the step value by x? because that gives me the exact same result.
lelgetrekt
CC BY-SA 3.0
2016-10-12T13:17:32.900Z
In real mathematics it does, but not in the world of floating point.  I believe the appropriate quote is _"Floating point numbers are like piles of sand; every time you move them around, you lose a little sand and pick up a little dirt.”_ ( — Brian Kernighan and P. J. Plauger).  Every time you do an operation (e.g an add or a mul) you'll typically lose up to 1/2 a ULP of accuracy.  Replacing a sequence "+C+C+C...+C"  with +N*C will thus improve your sand to dirt ratio :-)
Simon F
CC BY-SA 3.0
2016-10-12T14:19:22.677Z
Thanks for the explanation, now it makes sense to me :)   Unfortunately it does not change anything. But I think another problem regarding accuracy might be that I'm calculating a new step value for each scanline, which is unnecessary because it should be constant across the whole triangle. That's not only more expensive but also gives me slightly different results every time which causes the visual artifacts.
lelgetrekt
CC BY-SA 3.0
2016-10-11T11:52:18.917Z
2016-10-12T14:52:27.147Z
2016-10-12T14:52:27.147Z
Simon F
<p>In my case, i fixed the problem adding Dx' for interpolation of x-direction.
In edge scan line of x-direction, I use integer-type for speed-up but ingnored dx' as below. I changed variable type from interger to float and adding dx'.
(picture 1)
<a href="https://i.sstatic.net/sqqTx.jpg" rel="nofollow noreferrer"><img src="https://i.sstatic.net/sqqTx.jpg" alt="enter image description here"></a></p>

CC BY-SA 3.0
2017-01-09T10:12:46.850Z
when you use interger type with shift, same as float-type
zeroe
CC BY-SA 3.0
2017-01-09T09:41:49.727Z
2017-01-09T09:41:49.727Z
zeroe
<p>I'm currently writing a software renderer. I managed to implement texture mapping and it works fine. Only issue is, that the edges between the pixels are sometimes jagged in x direction as you can see here:</p>

<p><a href="https://i.sstatic.net/v9Mf6.png" rel="nofollow noreferrer"><img src="https://i.sstatic.net/v9Mf6.png" alt="example"></a></p>

<p>Could this be caused by a lack of precision? If so, how can I improve it?
What I'm doing is simply stepping along the edges of a triangle and interpolating the UVs for each scanline.</p>

<p>EDIT:
Here's my code for edge stepping and drawing of scanlines. The Edge class has a method step which increments the interpolants for each scanline.</p>

<p><strong>edge.h</strong></p>

<pre class="lang-cpp prettyprint-override"><code>Edge(const Vertex&amp; minY, const Vertex&amp; maxY){
    float dy = maxY.position.y - minY.position.y;

    yStart = static_cast&lt;int&gt;(ceil(minY.position.y));
    yEnd = static_cast&lt;int&gt;(ceil(maxY.position.y));

    float prestep = yStart - minY.position.y;

    xStep = (maxY.position.x - minY.position.x) / dy;
    x = minY.position.x + xStep * prestep;

    wStep = (1.0f / maxY.position.w - 1.0f / minY.position.w) / dy;
    w = 1.0f / minY.position.w + wStep * prestep;

    texCoordsStep = (maxY.textureCoordinates / maxY.position.w - minY.textureCoordinates / minY.position.w) / dy;
    texCoords = minY.textureCoordinates / minY.position.w + texCoordsStep * prestep;
}
</code></pre>

<p><strong>renderTarget.cpp</strong></p>

<pre class="lang-cpp prettyprint-override"><code>void RenderTarget::DrawScanLine(const Edge&amp; left, const Edge&amp; right, int y){
    int xStart = static_cast&lt;int&gt;(ceil(left.GetCurX()));
    int xEnd = static_cast&lt;int&gt;(ceil(right.GetCurX()));
    float dx = static_cast&lt;float&gt;(xEnd - xStart);
    float prestep = xStart - left.GetCurX();

    float w = left.GetCurW();
    float wStep = (right.GetCurW() - w) / dx;

    glm::vec2 texCoordsStep = (right.GetCurTexCoords() - left.GetCurTexCoords()) / dx;
    glm::vec2 texCoords = left.GetCurTexCoords() + texCoordsStep * prestep;

    Uint32* p = pixels + xStart + y * surface-&gt;w;

    for(int x = xStart; x &lt; xEnd; x++){
        float z = 1.0f / w;  //value for perspective correction
        int s = static_cast&lt;int&gt;(texCoords.s * z * texture-&gt;surface-&gt;w) &amp; texture-&gt;surface-&gt;w - 1;
        int t = static_cast&lt;int&gt;(texCoords.t * z * texture-&gt;surface-&gt;h) &amp; texture-&gt;surface-&gt;h - 1;

        *p = texture-&gt;pixels[s + t * texture-&gt;surface-&gt;w];  //copying the texture's pixel to the framebuffer
        p++;
        w += wStep;
        texCoords += texCoordsStep;
        color += colorStep;
    }
}
</code></pre>

CC BY-SA 3.0
2016-10-10T08:59:29.987Z
I'm confused by why there are vertical lines at all. Is it deliberate that the texture is aligned with the image plane instead of the triangle? What happens when you rotate the texture (mapping)?
Dan Hulme
CC BY-SA 3.0
2016-10-10T12:44:07.617Z
@DanHulme It's actually aligned with the triangle, you just can't see it in the screenshot. I tried to change the uv mapping but no difference.Weird thing is though, if I rotate the triangle 90° it's perfect. I think this might have something to do with the triangle itself. The problems occur if one side of the triangle is aligned with the x-axis. When aligned with the y-axis it works...
lelgetrekt
CC BY-SA 3.0
2016-10-11T20:37:13.647Z
The triangle edge jaggies in the top-right corner (against black background) strike me odd though. Why some pixels appear bigger than others? They should all be the same size.
JarkkoL
CC BY-SA 3.0
2016-10-11T20:46:03.460Z
@JarkkoL that's because I scaled the picture in Photoshop in order to make the issue more visible :)
lelgetrekt
CC BY-SA 3.0
2016-10-11T20:47:57.477Z
I thought you might have (: You should scale it properly to make it less confusing.
JarkkoL
CC BY-SA 3.0
2016-10-11T21:20:21.493Z
Would scaling to a power of 2 multiple of the original size ensure all the scaled up pixels are consistent sizes? (To make the diagram more relevant for people answering.)
trichoplax is on Codidact now
CC BY-SA 3.0
2016-10-12T13:05:21.903Z
What's strange though is that some of the jaggies in the image are 7 pixel wide while some are 3 or 4 pixel wide. I would expect 1 pixel deviation in the image if using non-integer upscaling, but that doesn't explain 7px vs 3/4px. Anyway, you should just upscale the image by some integer multiply (e.g. 800% in Photoshop).
JarkkoL
<rendering><texture><mapping>
Texture Mapping jagged pixel edges
lelgetrekt
# Texture Mapping jagged pixel edges

(Asked by: username_0 on 2016-10-09)

I'm currently writing a software renderer. I managed to implement texture mapping and it works fine. Only issue is, that the edges between the pixels are sometimes jagged in x direction as you can see here:

[![example](https://i.sstatic.net/v9Mf6.png)](https://i.sstatic.net/v9Mf6.png)

Could this be caused by a lack of precision? If so, how can I improve it?
What I'm doing is simply stepping along the edges of a triangle and interpolating the UVs for each scanline.

EDIT:
Here's my code for edge stepping and drawing of scanlines. The Edge class has a method step which increments the interpolants for each scanline.

**edge.h**

```cpp
Edge(const Vertex& minY, const Vertex& maxY){
    float dy = maxY.position.y - minY.position.y;

    yStart = static_cast<int>(ceil(minY.position.y));
    yEnd = static_cast<int>(ceil(maxY.position.y));

    float prestep = yStart - minY.position.y;

    xStep = (maxY.position.x - minY.position.x) / dy;
    x = minY.position.x + xStep * prestep;

    wStep = (1.0f / maxY.position.w - 1.0f / minY.position.w) / dy;
    w = 1.0f / minY.position.w + wStep * prestep;

    texCoordsStep = (maxY.textureCoordinates / maxY.position.w - minY.textureCoordinates / minY.position.w) / dy;
    texCoords = minY.textureCoordinates / minY.position.w + texCoordsStep * prestep;
}

```

**renderTarget.cpp**

```cpp
void RenderTarget::DrawScanLine(const Edge& left, const Edge& right, int y){
    int xStart = static_cast<int>(ceil(left.GetCurX()));
    int xEnd = static_cast<int>(ceil(right.GetCurX()));
    float dx = static_cast<float>(xEnd - xStart);
    float prestep = xStart - left.GetCurX();

    float w = left.GetCurW();
    float wStep = (right.GetCurW() - w) / dx;

    glm::vec2 texCoordsStep = (right.GetCurTexCoords() - left.GetCurTexCoords()) / dx;
    glm::vec2 texCoords = left.GetCurTexCoords() + texCoordsStep * prestep;

    Uint32* p = pixels + xStart + y * surface->w;

    for(int x = xStart; x < xEnd; x++){
        float z = 1.0f / w;  //value for perspective correction
        int s = static_cast<int>(texCoords.s * z * texture->surface->w) & texture->surface->w - 1;
        int t = static_cast<int>(texCoords.t * z * texture->surface->h) & texture->surface->h - 1;

        *p = texture->pixels[s + t * texture->surface->w];  //copying the texture's pixel to the framebuffer
        p++;
        w += wStep;
        texCoords += texCoordsStep;
        color += colorStep;
    }
}

```

**Tags:** rendering, texture, mapping

> **Comments:**
> **username_1**: I'm confused by why there are vertical lines at all. Is it deliberate that the texture is aligned with the image plane instead of the triangle? What happens when you rotate the texture (mapping)?  
> **username_0**: @username_1 It's actually aligned with the triangle, you just can't see it in the screenshot. I tried to change the uv mapping but no difference.Weird thing is though, if I rotate the triangle 90° it's perfect. I think this might have something to do with the triangle itself. The problems occur if one side of the triangle is aligned with the x-axis. When aligned with the y-axis it works...  
> **username_2**: The triangle edge jaggies in the top-right corner (against black background) strike me odd though. Why some pixels appear bigger than others? They should all be the same size.  
> **username_0**: @username_2 that's because I scaled the picture in Photoshop in order to make the issue more visible :)  
> **username_2**: I thought you might have (: You should scale it properly to make it less confusing.  
> **username_3**: Would scaling to a power of 2 multiple of the original size ensure all the scaled up pixels are consistent sizes? (To make the diagram more relevant for people answering.)  
> **username_2**: What's strange though is that some of the jaggies in the image are 7 pixel wide while some are 3 or 4 pixel wide. I would expect 1 pixel deviation in the image if using non-integer upscaling, but that doesn't explain 7px vs 3/4px. Anyway, you should just upscale the image by some integer multiply (e.g. 800% in Photoshop).  

---

## 2 answers

### Answer by username_4 on 2016-10-11. Score: 2 | Accepted answer

I strongly suspect that you are simply running out of floating point precision (at least in "U" dimension). With this sort of mathematics, the LSBs will soon become noisy resulting in the jagged appearance when you are (effectively) doing yes/no comparisons against known constants.

May I suggest instead that, rather than doing point sampling of your texture, try doing (at the very least) bilinear filtering which will hide the precision artefacts and also IMHO look better than having little squares.

**UPDATE** It just occurred to me that one of the possible causes of inaccuracy is that you are doing increments for each pixel X step, e.g. these two

```
w  += wStep;
texCoords += texCoordsStep;

```

These will soon cause errors to accumulate. Remove them and replace with multiplies by the X value and I expect things should improve.

**UPDATE2** It will also be affected by how far away from the origin of the texture you are when you sample it. If, for example, your source texture is defined over [0..1]x[0..1] and then repeats outside of that range, you might expect sampling at uv = (1000000.125, 100000.125) to be the same as (0.125,0.125) but, because the precision of FP decreases with increasing magnitude (i.e. the steps between floats also increases), you might end up with something quite different.

> **Comments:**
> **username_0**: Yeah, that's kind of what I expected. But it has to work somehow...  
> **username_0**: I already have bilinear filtering but I like to have both. This gives it sort of a retro look  
> **username_4**: @Leon2806 see update re not doing per-pixel increments.  
> **username_0**: I'm not sure if I completely  understand what you mean. Should I multiply the step value by x? because that gives me the exact same result.  
> **username_4**: In real mathematics it does, but not in the world of floating point.  I believe the appropriate quote is _"Floating point numbers are like piles of sand; every time you move them around, you lose a little sand and pick up a little dirt.”_ ( — Brian Kernighan and P. J. Plauger).  Every time you do an operation (e.g an add or a mul) you'll typically lose up to 1/2 a ULP of accuracy.  Replacing a sequence "+C+C+C...+C"  with +N*C will thus improve your sand to dirt ratio :-)  
> **username_0**: Thanks for the explanation, now it makes sense to me :)   Unfortunately it does not change anything. But I think another problem regarding accuracy might be that I'm calculating a new step value for each scanline, which is unnecessary because it should be constant across the whole triangle. That's not only more expensive but also gives me slightly different results every time which causes the visual artifacts.  

---

### Answer by username_5 on 2017-01-09. Score: 1

In my case, i fixed the problem adding Dx' for interpolation of x-direction.
In edge scan line of x-direction, I use integer-type for speed-up but ingnored dx' as below. I changed variable type from interger to float and adding dx'.
(picture 1)
[![enter image description here](https://i.sstatic.net/sqqTx.jpg)](https://i.sstatic.net/sqqTx.jpg)

> **Comments:**
> **username_5**: when you use interger type with shift, same as float-type  

---

