在OpenGL ES 2.0着色器中使用纹理作为调色板

时间:2018-03-31 06:50:57

标签: android opengl-es glsl shader

我正在使用OpenGL ES 2.0着色器生成分形。它运作良好,直到我认为黑白不够,我需要一个调色板。我将调色板作为1D纹理传递给着色器,但我得到的只是黑屏。

着色器基于this one,纹理传递为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错误。着色器在没有纹理的情况下工作,因此这可能是问题所在。可能是什么原因?

1 个答案:

答案 0 :(得分:1)

您必须设置为纹理采样器均匀的值是纹理对象的“名称”,它必须是纹理单元的索引:

- <android.support.design.widget.CoordinatorLayout> or ConstraintLayout
    -<android.support.design.widget.AppBarLayout>
       - <android.support.v7.widget.Toolbar>
       - </android.support.v7.widget.Toolbar>
   - </android.support.design.widget.AppBarLayout>

  -<LinearLayout
     app:layout_behavior="@string/appbar_scrolling_view_behavior">
     -<ListView>
     -</Listview>
  -</LinearLayout>
-</android.support.design.widget.CoordinatorLayout> or ConstraintLayout


OpenGL 4.6 API Compatibility Profile Specification; 7.10 Samplers; page 154

  

采样器是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 ,选择纹理图像单元编号i