I am trying to modify pixels from a texture and output it as another texture using a custom script.
The copying part of it is pretty straight forward:
for (int y = 0; y < height; y++)
{
for (int x = 0; x < width; x++)
{
float u = x / (float)width;
float v = y / (float)height;
textureIn.SetPixel(x, y, textureOut.GetPixelBilinear(u, v));
}
}
This code works perfectly fine at any texture dimension, but by looking at it more leads me to confusion. Imagine a texture with a size of only 2x2. At the end of the row or column, x and y are 1, so the uv is only 1 / 2f = 0.5f. A uv of 0.5f is only the center of a texture, so how is it able to read from the correct pixel?
Furthermore, I played around with the code to account for the pixel offset so that for each pixels, I calculated its uv so that it is exactly at the middle of the pixel. For example, the first pixel of a 2x2 texture, the uv is (0.25f, 0.25f).
However, this will result in about one pixel offset when the texture size is big enough. Can someone clarify on this?
Nevermind, the document does say that “Texture coordinates start at lower left corner. UV of (0,0) lands exactly on the bottom left texel; and UV of ((width-1)/width, (height-1)/height) lands exactly on the top right texel.”
If the documentation for this function is correct (which I would still verify experimentally however!), then
“landing exactly on the pixel” I interpret as pixel center, meaning that in your example a uv of 0.5f will sample the exact texel center of the upper texel, and a uv of 0.0 will sample the exact center of the lower texel.
If that’s correct, then this honestly speaking a bit a weird way to map UV coordinates (since for example it allows to address the top right corner of the top right pixel, but not the bottom left corner of the bottom pixel), but it makes the trivial loop code that doesn’t think about pixel centers happen to look up the correct locations.
Yea, it was weird at first before looking at the documentation, as people would normally think that the top right corner to be 1, 1. However, I quite like this set up as it is more convenient for when using with for loop.