Hi,
I am tryng to use Compute shader to create texture image. I read quite a lot of tutorial and forum. But i still got trouble to anderstand the processing and how correctly implement it on
android mobile phonne with ARM mali G72 GPU.
The goal is to feed the texture color using compute shader and than display the output image texture created using imageStore in fragment shader for display.
So i initialize the texture like this :
tex_output = new int[1];
GLES20.glGenTextures(1, tex_output,0);
checkGlError();
GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
checkGlError();
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, tex_output[0]);
checkGlError();
GLES31.glTexStorage2D(GLES20.GL_TEXTURE_2D, 1, GLES31.GL_RGBA8, 256, 256);
checkGlError();
GLES20.glGenerateMipmap(GLES20.GL_TEXTURE_2D);
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_CLAMP_TO_EDGE);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_CLAMP_TO_EDGE);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, 0);
checkGlError();
i am using this compute shader :
"#version 320 es",
"layout(local_size_x = 16, local_size_y = 16) in;",
"layout(rgba8, binding = 0) uniform writeonly highp image2D img_output;",
//"layout(rgba32f,location = 0, binding = 0) writeonly uniform highp image2D img_output;",
"void main() {",
// gl_LocalInvocationID.xy * gl_WorkGroupID.xy == gl_GlobalInvocationID
" ivec2 coords = ivec2(gl_GlobalInvocationID.xy);",
// Pour mettre en evidence. Les groupes de travail locaux on dessine un damier.
" vec4 pixel;",
" if ( ((gl_WorkGroupID.x & 1u) != 1u) != ((gl_WorkGroupID.y & 1u) == 1u)) {",
" pixel = vec4(0.0,1.0,0.0,1.0);",
" }else {",
" pixel = vec4(0.0,0.0,1.0,1.0);",
" }",
" imageStore(img_output, coords, pixel);",
"}"
for the rendering i use the compute program :
GLES20.glUseProgram(programComp);
GLES31.glBindImageTexture(0, tex_output[0], 0, false, 0, GLES31.GL_WRITE_ONLY, GLES31.GL_RGBA8);
Log.e(TAG, " glDispatchCompute ");
GLES31.glDispatchCompute(16,16,1);
Log.e(TAG, " glMemoryBarrier ");
GLES31.glMemoryBarrier( GLES31.GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
and the vertex/fragment shader program inside the same glDraw() function :
GLES20.glUseProgram(program);
GLES20.glEnableVertexAttribArray(positionHandle);
GLES20.glEnableVertexAttribArray(textureCoordsHandle);
GLES20.glUniform1i(textureHandle, 0);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, tex_output[0]);
GLES20.glUniformMatrix4fv(mvpMatrixHandle, 1, false, mMVPMatrix, 0);
// Load position data.
vertexBuffer.position(0);
GLES20.glVertexAttribPointer(positionHandle, POSITION_COORDS_PER_VERTEX, GLES20.GL_FLOAT,
false, VERTEX_STRIDE_BYTES, vertexBuffer);
// Load texture data.
vertexBuffer.position(POSITION_COORDS_PER_VERTEX);
GLES20.glVertexAttribPointer(textureCoordsHandle, TEXTURE_COORDS_PER_VERTEX, GLES20.GL_FLOAT,
false, VERTEX_STRIDE_BYTES, vertexBuffer);
// Render.
GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, vertexData.length / COORDS_PER_VERTEX);
GLES20.glDisableVertexAttribArray(positionHandle);
GLES20.glDisableVertexAttribArray(textureCoordsHandle);
vertex shader :
"uniform mat4 uMvpMatrix;",
// 3D position data.
"attribute vec3 aPosition;",
// 2D UV vertices.
"attribute vec2 aTexCoords;",
"varying vec2 vTexCoords;",
"varying vec2 vCoords2;",
"vec2 vCoords;",
// Standard transformation.
"void main() {",
" gl_Position = uMvpMatrix * vec4(aPosition, 1.0);",
" vTexCoords = aTexCoords;",
" vCoords = aPosition.xy / vec2(" + SIZE + ", " + SIZE + ");",
" vCoords2 = vec4(vCoords,1.0,1.0).xy;",
"}"
fragment shader :
"precision mediump float;",
// Standard texture rendering shader with extra alpha channel.
"uniform sampler2D uTexture;",
"varying vec2 vTexCoords;",
"varying vec2 vCoords2;",
"void main() {",
// Simple ring shader that is white between the radii and transparent elsewhere.
" float r = length(vCoords2);",
// Blend the edges of the ring at .55 +/- .05 and .85 +/- .05.
" float alpha = smoothstep(0.25, 0.3, r) * (1.0 - smoothstep(0.8, 0.9, r));",
" vec4 reticle = alpha * vec4(0.0,1.0,0.0,1.0);",
" gl_FragColor = texture2D(uTexture, vTexCoords)*0.75 + reticle;",
"}"
So i can see my reticule displayed, that for i use it ;)). But nothing else, the texture is transparent.
if i use internalformat GL_RGBA32F insted of GL_RGBA8 and if i remove the
GLES20.glGenerateMipmap(GLES20.GL_TEXTURE_2D);
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_CLAMP_TO_EDGE);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_CLAMP_TO_EDGE);
I can get a black transparent texture displayed ?
I spend the all day yestaday tryng to make it work whitout succes. And i still not anderstand the process of image compute shader.
For me it is a way to read,write, modified texture using compute shader. So we do not need to retreive the texture data to CPU to do modification. Modification are made directly on the openGL texture object. So no need to read to CPU memorie do the modification and than send it back to the GPU.
Thanks in advance for the help.