Неверный результат при использовании 3D-текстур

Я использую современное ядро ​​OpenGL 4.3.

Я только что понял, что набор тайлов 1024p x 1024p слишком мал для моих нужд. Итак, я заменил его на 3D-текстуру 1024p x 1024p x 4p. (Я знаю, что это не лучшее решение, и мне лучше использовать массив 2D-текстур. Мне просто интересно, почему мое текущее решение не работает.)

Координаты текстур x и y работают нормально, как и раньше. z тоже работают, но немного некорректно. Я ожидаю, что 1-й слой будет иметь z == 0.0, 2-й слой - z == 0.3333333, 3-й слой - z == 0.66666666 и 4-й слой - z == 1.0.

1-й и 4-й слои работают как положено. Но 0.33333333 и 0.66666666 дают неверные результаты:
0,33333333 -> 1-й слой смешивается со 2-м слоем
0,66666666 -> 3-й слой смешивается с 4-м слоем
(я использую линейную фильтрацию, поэтому они смешиваются вместе. )

Я попытался выбрать правильные значения z для 2-го и 3-го слоев:
2-й отображается нормально, когда z == 0.38
3-й отображается нормально, когда z == 0.62
(эти цифры, конечно, приблизительны).

Любые идеи, почему это происходит и как я могу это исправить?


Вот как я создаю текстуру:

glActiveTexture(GL_TEXTURE1);
glGenTextures(1, &maintex);
glBindTexture(GL_TEXTURE_3D, maintex);
glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA8, TEXSIZE, TEXSIZE, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE, textemp);
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);

И это мой шейдер:

const char *vertex = 1+R"(
#version 430
uniform layout(location = 3) vec2 fac;
in layout(location = 0) vec2 vpos; // vertex coords
in layout(location = 1) vec3 tpos; // texture coords
in layout(location = 2) vec4 c_off;  // color offset    = vec4(0,0,0,0) by default
in layout(location = 3) vec4 c_mult; // color multiplicator    = vec4(1,1,1,1) by default
// These two are used to do some sort of gamma correction 

out vec3 var_tpos;
out vec4 var_c_off;
out vec4 var_c_mult;
void main()
{
    var_tpos = tpos;
    var_c_off = c_off;
    var_c_mult = c_mult;
    gl_Position = vec4(vpos.x * fac.x - 1, vpos.y * fac.y + 1, 0, 1);
})";


const char *fragment = 1+R"(
#version 430
uniform layout(location = 0) sampler3D tex;
in vec3 var_tpos;
in vec4 var_c_off;
in vec4 var_c_mult;
out vec4 color;
void main()
{
    color = texture(tex, vec3(var_tpos.x / 1024, var_tpos.y / 1024, var_tpos.z));
    color.x *= var_c_mult.x;
    color.y *= var_c_mult.y;
    color.z *= var_c_mult.z;
    color.w *= var_c_mult.w;
    color   += var_c_off;
})";

person HolyBlackCat    schedule 13.11.2014    source источник
comment
Вместо 3D-текстур для листов спрайтов попробуйте текстуры 2D-массивов. Они не смешиваются между слоями.   -  person Colonel Thirty Two    schedule 13.11.2014
comment
@ColonelThirtyTwo Я понимаю, что есть лучшее решение. Я задал этот вопрос, потому что меня смутило поведение моей программы.   -  person HolyBlackCat    schedule 13.11.2014
comment
Однако люди, читающие ваш вопрос, могут этого не делать, поэтому его все же стоит упомянуть.   -  person Colonel Thirty Two    schedule 13.11.2014
comment
@ColonelThirtyTwo Хорошо, я добавил к вопросу информацию о массивах 2D-текстур.   -  person HolyBlackCat    schedule 14.11.2014


Ответы (1)


Это потому, что 0 — это «крайняя левая» часть левого текселя, а 1 — самая правая точка в самом правом текселе. Предположим, что у нас есть 4 текселя, тогда координаты следующие:

0       1/4      1/2      3/4       1
|  tx1   |  tx2   |  tx3   |  tx4   |

поскольку вам нужно попасть точно в центр вокселя, вы должны использовать адреса, которые на 1/2 вокселя выше, чем вы ожидали (+0,25/2 = +0,125), таким образом, центры вокселей соответствуют описанию в нижней строке таблицы. следующую схему.

|  tx1   |  tx2   |  tx3   |  tx4   |
    |        |        |        |
  0.125    0.375     0.625    0.875
person BDL    schedule 13.11.2014
comment
Благодарю вас! Я совершенно забыл о механике текстурных координат. - person HolyBlackCat; 13.11.2014