我正在使用OpenGL ES 2.0着色器来生成分形。它效果很好,直到我认为黑白还不够,我需要一个调色板。我将调色板作为1D纹理传递给着色器,但我所得到的只是黑屏。
着色器是基于此的,纹理通过的是2D(NX1(,因为OpenGL ES 2.0不允许1D纹理,因此像素颜色是由
获得的。gl_FragColor = texture2D(palette, vec2((j == int(iterations) ? 0.0 : float(j)) / iterations, 0.5));
(我不确定这里的0.5(。
相关纹理加载代码:
Bitmap bitmap = Bitmap.createBitmap(colors, colors.length, 1, Bitmap.Config.ARGB_8888);
int handle = ShaderUtils.loadTexture(bitmap);
GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, handle);
GLES20.glUniform1i(paletteHandle, handle);
[...]
public static int loadTexture(Bitmap bitmap)
{
final int[] textureHandle = new int[1];
GLES20.glGenTextures(1, textureHandle, 0);
if (textureHandle[0] == 0)
{
throw new RuntimeException("Error generating texture name.");
}
// Bind to the texture in OpenGL
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureHandle[0]);
// Set filtering
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);
// Load the bitmap into the bound texture.
GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, bitmap, 0);
// Recycle the bitmap, since its data has been loaded into OpenGL.
bitmap.recycle();
return textureHandle[0];
}
顶点着色器:
attribute vec4 vPosition;
void main() {
gl_Position = vPosition;
}
碎片着色器:
precision mediump float;
uniform sampler2D palette;
uniform float centerX;
uniform float centerY;
uniform float scale;
uniform float iterations;
uniform vec2 resolution;
#define maxiter 1024
void main() {
vec2 center = vec2(centerX, centerY);
vec2 coord = vec2(gl_FragCoord.x, gl_FragCoord.y) / resolution;
vec2 c = (coord - center) / scale;
int j = 0;
vec2 z = c;
for(int i = 0; i<maxiter; i++) {
if (float(i) >= iterations) break;
j++;
float x = (z.x * z.x - z.y * z.y) + c.x;
float y = (z.y * z.x + z.x * z.y) + c.y;
if((x * x + y * y) > 4.0) break;
z.x = x;
z.y = y;
}
gl_FragColor = texture2D(palette, vec2((j == int(iterations) ? 0.0 : float(j)) / iterations, 0.5));
// vec3 color = vec3(float(j)/float(iterations));
// gl_FragColor = vec4(color, 1.0);
}
问题是这很难调试。从IDE内部,我确保位图包含适当的数据,并且LogCat中没有OpenGL错误。着色器没有纹理,因此可能是这里的问题。原因是什么?
您必须将其设置为纹理采样器制服的值是不是纹理对象的"名称",它必须是纹理的索引单位:
GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, handle);
// this is wrong
//GLES20.glUniform1i(paletteHandle, handle);
GLES20.glUniform1i(paletteHandle, 0); // 0, because of GLES20.GL_TEXTURE0
请参阅OpenGL 4.6 API兼容性配置文件规范;7.10个采样器;第154页:
采样器是开放式阴影语言中使用的特殊制服来识别 每个纹理查找使用的纹理对象。采样器的值表示要访问的纹理图像单元。将Sampler的值设置为
i
选择纹理图像单位编号i
。