У меня проблема с моими шейдерами glsl на моем устройстве Android 2.3.4 Tegra 2.
Я хочу провести некоторые вычисления, чтобы создать координаты текстуры в фрагментном шейдере в шейдере 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);