У меня проблема с моими шейдерами glsl на устройстве Android 2.3.4 Tegra 2.Почему текстуры-координаты GLSL в моем шейдере не линейны?
Я хочу сделать некоторые вычисления, чтобы создать координаты текстуры в шейдере фрагмента в glsl-шейдере, и заметил проблему и попытался ее сузить и, следовательно, сделал тестовую программу. Я визуализировал текстуру шириной 256 пикселей на ровно 256 пикселей на экране, сохранил фреймбуфер и проверил его пиксель за пикселем (сравните с источником), и он отобразится правильно. Согласно спецификации opengl, когда я использую координаты текстуры от 0.0 до 1.0, он должен пробовать каждый пиксель в центре (0.5/256, 1.5/256, 2.5/256 и т. Д.), Что кажется правильным.
Затем я сам написал координаты текстуры x в текстуру и проверил их. Результаты несколько отключаются, и я не знаю, почему. Вместо того, чтобы получить градиент 0..255, который я ожидал, я получил 1,128,128..255. Это означает, что значение 0 пропущено, и значение 128 появляется дважды, что означает, что они не являются совершенно линейными. Если значение было округлено каким-либо образом, то не так, как это очевидно для меня. Я также проверил значения субпикселя для текстурных координат, и они - то, что я ожидал. Их значение всегда равно 0,5/256, что должно быть половинным пикселем и гарантировать правильную выборку текстуры внутри пикселя.
Опять же, текстура, визуализированная с этими координатами, является именно тем, что я хочу, но сами координаты не то, что я ожидал. Это проблема для меня, потому что я хочу рендерить с вычисленными координатами текстуры, и хотя я вычисляю их так, чтобы это было правильно, результирующая текстура была неправильной. Мне нужно, чтобы эти координаты были правильными для уровня пикселей, и я не знаю, почему они отключены.
Кто-нибудь знает, что вызывает такое поведение и как я могу его исправить?
Это фрагмент шейдера, что делает текстуру правильно:
precision mediump float;
varying vec2 vtex;
uniform sampler2D samp0;
void main() {
gl_FragColor = texture2D(samp0, vtex);
};
Это фрагмент шейдера, что создает градиент с текстурой координаты, что является 1..128,128..255, а не 0..255 как я ожидал:
precision mediump float;
varying vec2 vtex;
uniform sampler2D samp0;
void main() {
gl_FragColor = vec4(vtex.x, 0, 0, 1.0);
};
Это пиксельный шейдер, который создает цвет для значений субпикселей координат текстуры и обеспечивает текстуру со всеми значениями 127, как я ожидал, и который должен быть центром пикселей:
precision mediump float;
varying vec2 vtex;
uniform sampler2D samp0;
void main() {
gl_FragColor = vec4(fract(vtex.x * 256.0), 0, 0, 1.0);
};
Остальные тестовые программы абсолютно идентичны. Я только меняю шейдеры. К ним относятся некоторые важные фрагменты кода:
String vertexshader =
"attribute vec4 a_pos; \n" + // in position
"attribute vec2 a_tex; \n" + // in Texture coordinates
"varying vec2 vtex; \n" + // out Texture coordinates
"void main(void) { \n" +
" gl_Position = vec4(a_pos); \n" +
" vtex = a_tex; \n" +
"}";
// Initialization
GLES20.glUseProgram(shader);
// Vertex
vdata.position(0);
GLES20.glVertexAttribPointer(handlepos, 2, GLES20.GL_FLOAT, false, 4*4, vdata);
GLES20.glEnableVertexAttribArray(handlepos);
vdata.position(2);
GLES20.glVertexAttribPointer(handletex, 2, GLES20.GL_FLOAT, false, 4*4, vdata);
GLES20.glEnableVertexAttribArray(handletex);
// Texture
GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, maplookupid[1]);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_NEAREST);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_NEAREST);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_REPEAT);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_REPEAT);
GLES20.glUniform1i(handlesampler0, 0);
GLES20.glDisable(GLES20.GL_DITHER);
// Rendering
GLES20.glViewport(0, 0, screenx, screeny);
//
vdata.put(0*4+0, 0.0f * (2.0f/screenx));
vdata.put(0*4+1, 256.0f * (2.0f/screeny));
vdata.put(0*4+2, 0.0f * (1.0f/256.0f));
vdata.put(0*4+3, 256.0f * (1.0f/256.0f));
//
vdata.put(1*4+0, 0.0f * (2.0f/screenx));
vdata.put(1*4+1, 0.0f * (2.0f/screeny));
vdata.put(1*4+2, 0.0f * (1.0f/256.0f));
vdata.put(1*4+3, 0.0f * (1.0f/256.0f));
//
vdata.put(2*4+0, 256.0f * (2.0f/screenx));
vdata.put(2*4+1, 256.0f * (2.0f/screeny));
vdata.put(2*4+2, 256.0f * (1.0f/256.0f));
vdata.put(2*4+3, 256.0f * (1.0f/256.0f));
//
vdata.put(3*4+0, 256.0f * (2.0f/screenx));
vdata.put(3*4+1, 0.0f * (2.0f/screeny));
vdata.put(3*4+2, 256.0f * (1.0f/256.0f));
vdata.put(3*4+3, 0.0f * (1.0f/256.0f));
GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4);
Попробуйте изменить GL_NEAREST на GL_LINEAR –
Я сделал, и это не повлияло. – HardCoder