<p>I finally found the problem.</p>

<p>My precalculation was done with pixel coordinates from <code>0</code> to <code>res[0] - 1</code> (i.e. the resolution width):</p>

<pre><code>for (int i = 0; i &lt; res[0]; i++)
{
    for (int j = 0; j &lt; res[1]; j++)
    {
        reinterpret_cast&lt;float*&gt;(img-&gt;data(i, j))[0] = i / res[0];
        reinterpret_cast&lt;float*&gt;(img-&gt;data(i, j))[1] = j / res[1];
    }
}
</code></pre>

<p>However, pixels in OpenGL are accessed via their center, as can be read <a href="https://stackoverflow.com/questions/5879403/opengl-texture-coordinates-in-pixel-space">in another SO answer</a> or <a href="http://www.realtimerendering.com/" rel="nofollow noreferrer">in Real-Time Rendering (3rd and 4th Edition, p.21)</a>. Meaning, that if I have a pixel with 0 as its left border and 0.1 as its right border, then 0.05 is its center.
That means in my case, I have to offset the precalculated texture coordinate by half a pixel to read out of my prerendered image:</p>

<pre><code>for (int i = 0; i &lt; res[0]; i++)
{
    for (int j = 0; j &lt; res[1]; j++)
    {
        reinterpret_cast&lt;float*&gt;(img-&gt;data(i, j))[0] = i / res[0] + 0.5 * pixelWidth;
        reinterpret_cast&lt;float*&gt;(img-&gt;data(i, j))[1] = j / res[1] + 0.5 * pixelHeight;
    }
} 
</code></pre>

CC BY-SA 4.0
2018-12-05T14:39:41.607Z
2018-12-05T14:39:41.607Z
Tare
<p>It's a bit hard to tell with the images, but I assume the whole viewport is distorted?</p>

<p>My first thought is that there is a difference between the 2 distortion computation methods which might not be obvious. A good first debugging step would be to output only <span class="math-container">$(u_d, v_d)$</span> as a color with the two methods. This will allow isolating (or not) the problem to this computation since this is likely where the problem is. If this is the problem, it will be much easier to reason about and debug with all other factors removed from the final image.</p>

<p>Could you add a (simplified) version of your distortion computation shader and the matching texture generation code?</p>

CC BY-SA 4.0
2018-12-05T11:31:02.770Z
`It's a bit hard to tell with the images, but I assume the whole viewport is distorted?` Yes, it is over the whole viewport.

I will edit my question and add the distortion calculations, but they are pretty much the same.
Tare
CC BY-SA 4.0
2018-12-05T12:20:41.757Z
As seen in the new edit, I can reproduce the issue with a minimal example that has no camera distortion implemented, just once a rendered image read out and written to the frame buffer, and once the rendered image read out with precalculated texture coordinates per pixel and then written to the frame buffer.
Tare
CC BY-SA 4.0
2018-12-05T11:23:09.617Z
2018-12-05T11:23:09.617Z
bernie
<p>I have an application where I simulate a camera distortion. There are two ways to go about it: calculate the distortion per pixel in the shader or precalculate the distortion and store the distortion as a 2D texture. In either case I first render the undistorted image, then calculate different texture coordinates in a new render pass for every pixel and thus read from the original image at a different position.</p>

<p>In the latter case I store tex coords, meaning that for my texture coordinate <span class="math-container">$(u_d, v_d)$</span> in the shader I read out the texture coordinate <span class="math-container">$(u, v)$</span> and thus have a distortion from the original point <span class="math-container">$(u, v)$</span> to my distorted point <span class="math-container">$(u_d, v_d)$</span>. </p>

<p>I can set up my distortion to have no distortion at all (i.e. <span class="math-container">$(u, v) = (u_d, v_d)$</span>). This works fine when I calculate the distortion in the shader, but if I precalculate the distortion and store my new tex coords, read them out in the shader and then apply that "distortion", I get a somewhat blurry image. I have checked my texture with the new texture coordinates, but they seem to store exactly what I want them to (basically their own position).</p>

<p>Here is the same excerpt from my results, first with the shader calculated distortion:</p>

<p><a href="https://i.sstatic.net/ty5aj.png" rel="nofollow noreferrer"><img src="https://i.sstatic.net/ty5aj.png" alt="Distortion calculation done in the shader"></a></p>

<p>And then with the precalculated distortion and blurry result:
<a href="https://i.sstatic.net/M3IkC.png" rel="nofollow noreferrer"><img src="https://i.sstatic.net/M3IkC.png" alt="Distortion precalculated and new texture coordinates read in the shader"></a></p>

<p>I'm a bit at a loss as to why I get this blurry image now, especially when there is actually no offset between the original and the distorted tex coords.</p>

<p>The texture is using <code>GL_FLOAT</code> as the data type and <code>GL_RG32F</code> as the internal format, I don't use mip mapping and the image is usually non power of 2 and non square (e.g. in this case 1920*1079), the prerendered image has the same size as my precalculated texture coordinate texture. This effect occurs with filtering set to <code>GL_LINEAR</code> as well as set to <code>GL_NEAREST</code>.</p>

<hr>

<p><strong><em>Edit2</em></strong></p>

<p>I have managed to reproduce the problem in a more minimal example, excluding any distortion calculations.
That is, in OpenSceneGraph I have two cameras, one (<code>rttCamera</code>) rendering a scene into a texture and one (<code>displayCamera</code>) rendering this texture to the framebuffer. I precalculate a texture which stores texture coordinates, but basically they should return the same texture coordinates at every pixel as the geometry of the screen quad does:</p>

<pre><code>for (int i = 0; i &lt; res[0]; i++)
{
    for (int j = 0; j &lt; res[1]; j++)
    {
        reinterpret_cast&lt;float*&gt;(img-&gt;data(i, j))[0] = i / res[0];
        reinterpret_cast&lt;float*&gt;(img-&gt;data(i, j))[1] = j / res[1];
    }
}
</code></pre>

<p><code>img-&gt;data</code> is the buffer for the texture, <code>i, j</code> are the pixel coordinates, <code>res</code> stores the resolution (1920 * 1080 in this case). The texture itself is again <code>GL_RG32F</code> with data type <code>GL_FLOAT</code>.</p>

<p>The fragment shader code for the <code>displayCamera</code>is the following:</p>

<pre><code>#version 400

uniform sampler2D uRenderedImage;
uniform sampler2D uTexCoordLut;

uniform bool uIsLutUsed;

in vec2 vTexCoord;
out vec4 gl_FragColor;

void main()
{
    vec2 texCoord = texture(uTexCoordLut, vTexCoord).rg;
    // gl_FragColor = vec4(texCoord, 0, 1);
    gl_FragColor = texture(uRenderedImage, vTexCoord);
    if(uIsLutUsed)
    {
        gl_FragColor = texture(uRenderedImage, texCoord);
    }
}
</code></pre>

<p>where the boolean uniform is for me to switch between the geometry texcoord version and my precalculated texcoord version.</p>

<p>The resulting images are the following (again cropped), first the version without the precalculated texture coordinates</p>

<p><a href="https://i.sstatic.net/F4db8.png" rel="nofollow noreferrer"><img src="https://i.sstatic.net/F4db8.png" alt="Using the geometry texture coordinates"></a></p>

<p>and then the version with precalculated texture coordinates</p>

<p><a href="https://i.sstatic.net/czNSb.png" rel="nofollow noreferrer"><img src="https://i.sstatic.net/czNSb.png" alt="Using the precalculated texture coordinates"></a></p>

<hr>

<p><strong><em>Edit3</em></strong></p>

<p>I tried around a bit, and I found one solution (although that doesn't answer my question of 'why').
Currently my prerendered image and my 2D texture that stores my new texture coordinates both have the same resolution. However, in my minimal example from Edit2, if keep the prerendered image at 1920*1080 pixel and increase the texture with my precalculated coordinates to 10000*10000, the difference between precalculated texture coordinates and geoemtry texture coordinates (or the rendered image with said coordinates) is minimal, barely noticable at all.</p>

<texture><glsl>
Why is precalculating a distortion different from calculating it in the shader?
Tare
# Why is precalculating a distortion different from calculating it in the shader?

(Asked by: username_0 on 2018-12-04)

I have an application where I simulate a camera distortion. There are two ways to go about it: calculate the distortion per pixel in the shader or precalculate the distortion and store the distortion as a 2D texture. In either case I first render the undistorted image, then calculate different texture coordinates in a new render pass for every pixel and thus read from the original image at a different position.

In the latter case I store tex coords, meaning that for my texture coordinate $(u\_d, v\_d)$ in the shader I read out the texture coordinate $(u, v)$ and thus have a distortion from the original point $(u, v)$ to my distorted point $(u\_d, v\_d)$.

I can set up my distortion to have no distortion at all (i.e. $(u, v) = (u\_d, v\_d)$). This works fine when I calculate the distortion in the shader, but if I precalculate the distortion and store my new tex coords, read them out in the shader and then apply that "distortion", I get a somewhat blurry image. I have checked my texture with the new texture coordinates, but they seem to store exactly what I want them to (basically their own position).

Here is the same excerpt from my results, first with the shader calculated distortion:

[![Distortion calculation done in the shader](https://i.sstatic.net/ty5aj.png)](https://i.sstatic.net/ty5aj.png)

And then with the precalculated distortion and blurry result:
[![Distortion precalculated and new texture coordinates read in the shader](https://i.sstatic.net/M3IkC.png)](https://i.sstatic.net/M3IkC.png)

I'm a bit at a loss as to why I get this blurry image now, especially when there is actually no offset between the original and the distorted tex coords.

The texture is using `GL_FLOAT` as the data type and `GL_RG32F` as the internal format, I don't use mip mapping and the image is usually non power of 2 and non square (e.g. in this case 1920\*1079), the prerendered image has the same size as my precalculated texture coordinate texture. This effect occurs with filtering set to `GL_LINEAR` as well as set to `GL_NEAREST`.

---

***Edit2***

I have managed to reproduce the problem in a more minimal example, excluding any distortion calculations.
That is, in OpenSceneGraph I have two cameras, one (`rttCamera`) rendering a scene into a texture and one (`displayCamera`) rendering this texture to the framebuffer. I precalculate a texture which stores texture coordinates, but basically they should return the same texture coordinates at every pixel as the geometry of the screen quad does:

```
for (int i = 0; i < res[0]; i++)
{
    for (int j = 0; j < res[1]; j++)
    {
        reinterpret_cast<float*>(img->data(i, j))[0] = i / res[0];
        reinterpret_cast<float*>(img->data(i, j))[1] = j / res[1];
    }
}

```

`img->data` is the buffer for the texture, `i, j` are the pixel coordinates, `res` stores the resolution (1920 \* 1080 in this case). The texture itself is again `GL_RG32F` with data type `GL_FLOAT`.

The fragment shader code for the `displayCamera`is the following:

```
#version 400

uniform sampler2D uRenderedImage;
uniform sampler2D uTexCoordLut;

uniform bool uIsLutUsed;

in vec2 vTexCoord;
out vec4 gl_FragColor;

void main()
{
    vec2 texCoord = texture(uTexCoordLut, vTexCoord).rg;
    // gl_FragColor = vec4(texCoord, 0, 1);
    gl_FragColor = texture(uRenderedImage, vTexCoord);
    if(uIsLutUsed)
    {
        gl_FragColor = texture(uRenderedImage, texCoord);
    }
}

```

where the boolean uniform is for me to switch between the geometry texcoord version and my precalculated texcoord version.

The resulting images are the following (again cropped), first the version without the precalculated texture coordinates

[![Using the geometry texture coordinates](https://i.sstatic.net/F4db8.png)](https://i.sstatic.net/F4db8.png)

and then the version with precalculated texture coordinates

[![Using the precalculated texture coordinates](https://i.sstatic.net/czNSb.png)](https://i.sstatic.net/czNSb.png)

---

***Edit3***

I tried around a bit, and I found one solution (although that doesn't answer my question of 'why').
Currently my prerendered image and my 2D texture that stores my new texture coordinates both have the same resolution. However, in my minimal example from Edit2, if keep the prerendered image at 1920\*1080 pixel and increase the texture with my precalculated coordinates to 10000\*10000, the difference between precalculated texture coordinates and geoemtry texture coordinates (or the rendered image with said coordinates) is minimal, barely noticable at all.

**Tags:** texture, glsl


---

## 2 answers

### Answer by username_0 on 2018-12-05. Score: 1 | Accepted answer

I finally found the problem.

My precalculation was done with pixel coordinates from `0` to `res[0] - 1` (i.e. the resolution width):

```
for (int i = 0; i < res[0]; i++)
{
    for (int j = 0; j < res[1]; j++)
    {
        reinterpret_cast<float*>(img->data(i, j))[0] = i / res[0];
        reinterpret_cast<float*>(img->data(i, j))[1] = j / res[1];
    }
}

```

However, pixels in OpenGL are accessed via their center, as can be read [in another SO answer](https://stackoverflow.com/questions/5879403/opengl-texture-coordinates-in-pixel-space) or [in Real-Time Rendering (3rd and 4th Edition, p.21)](http://www.realtimerendering.com/). Meaning, that if I have a pixel with 0 as its left border and 0.1 as its right border, then 0.05 is its center.
That means in my case, I have to offset the precalculated texture coordinate by half a pixel to read out of my prerendered image:

```
for (int i = 0; i < res[0]; i++)
{
    for (int j = 0; j < res[1]; j++)
    {
        reinterpret_cast<float*>(img->data(i, j))[0] = i / res[0] + 0.5 * pixelWidth;
        reinterpret_cast<float*>(img->data(i, j))[1] = j / res[1] + 0.5 * pixelHeight;
    }
} 

```


---

### Answer by username_1 on 2018-12-05. Score: 0

It's a bit hard to tell with the images, but I assume the whole viewport is distorted?

My first thought is that there is a difference between the 2 distortion computation methods which might not be obvious. A good first debugging step would be to output only $(u\_d, v\_d)$ as a color with the two methods. This will allow isolating (or not) the problem to this computation since this is likely where the problem is. If this is the problem, it will be much easier to reason about and debug with all other factors removed from the final image.

Could you add a (simplified) version of your distortion computation shader and the matching texture generation code?

> **Comments:**
> **username_0**: `It's a bit hard to tell with the images, but I assume the whole viewport is distorted?` Yes, it is over the whole viewport.  I will edit my question and add the distortion calculations, but they are pretty much the same.  
> **username_0**: As seen in the new edit, I can reproduce the issue with a minimal example that has no camera distortion implemented, just once a rendered image read out and written to the frame buffer, and once the rendered image read out with precalculated texture coordinates per pixel and then written to the frame buffer.  

---

