Я хочу проверить, как работают шейдеры и вычислительные шейдеры.
Вычислительный шейдер должен просто окрасить пиксель в белый цвет и вернуть его. а затем шейдер должен использовать этот цвет для рисования нижней части экрана.
шейдер работает нормально, но когда я попытался реализовать вычислительный шейдер, он просто не работал.
Взгляните на эту реализацию рендерера.
это шейдеры вычислительный шейдер
#version 310 es
precision highp float;
precision highp image2D;
layout (local_size_x = 1, local_size_y = 1) in; // run only for one pixel
layout (rgba32f, binding = 0) uniform writeonly image2D outputImage;
void main() {
ivec2 pixelCoords = ivec2(gl_GlobalInvocationID.xy);
imageStore(outputImage, pixelCoords, vec4(1.0)); // just color it white and return
}
#ifdef GL_FRAGMENT_PRECISION_HIGH
precision highp float;
#else
precision mediump float;
#endif
// 'varying' values are passed from the vertex shader to the fragment shader
varying vec2 vTexCoord;
uniform vec3 Accelerometer;// I removed the part of code that puts this data for simplicity
uniform sampler2D ColorSet;// single pixel texture returned from compute shader
void main() {
if (gl_FragCoord.y > 250.0) {
float x = Accelerometer[0] / 20.0;
float y = Accelerometer[1] / 20.0;
float z = Accelerometer[2] / 20.0;
gl_FragColor = vec4(x + 0.5, y + 0.5, z + 0.5, 1.0);
} else {
gl_FragColor = texture2D(ColorSet, vec2(1.0));
}
}
Я думаю, что это правильно, но, пожалуйста, раскритиковайте меня, если я ошибаюсь, проблема должна быть в реализации средства рендеринга
Renderer< /strong>
fun dispatchComputeShader() {
GLES31.glUseProgram(computeProgram)
GLES31.glBindImageTexture(0, textures[0], 0, false, 0, GLES31.GL_WRITE_ONLY, GLES31.GL_RGBA32F)
// Assuming resolution width and height are divisible by 16 or 1 (for testing)
GLES31.glDispatchCompute(1, 1, 1)
GLES31.glMemoryBarrier(GLES31.GL_SHADER_IMAGE_ACCESS_BARRIER_BIT)
}
fun readAndLogPixelFromTexture(texture: Int, pixel:Pair) {
val pixelData = FloatArray(4)
GLES31.glBindTexture(GLES31.GL_TEXTURE_2D, textures[texture])
GLES31.glReadPixels(pixel.first, pixel.second, 1, 1, GLES31.GL_RGBA, GLES31.GL_FLOAT, java.nio.FloatBuffer.wrap(pixelData))
// Log the color value to verify it
val r = pixelData[0]
val g = pixelData[1]
val b = pixelData[2]
val a = pixelData[3]
Timber.d("SET-COLOR: R: $r, G: $g, B: $b, A: $a")
}
private fun drawTexture() {
GLES31.glUseProgram(renderProgram)
val positionHandle = GLES31.glGetAttribLocation(renderProgram, "aPosition")
GLES31.glEnableVertexAttribArray(positionHandle)
val textureCoordHandle = GLES31.glGetAttribLocation(renderProgram, "aTexCoord")
GLES31.glEnableVertexAttribArray(textureCoordHandle)
val textureHandle = GLES31.glGetUniformLocation(renderProgram, "ColorSet")
GLES31.glActiveTexture(GLES31.GL_TEXTURE0)
GLES31.glBindTexture(GLES31.GL_TEXTURE_2D, textures[0])
GLES31.glUniform1i(textureHandle, 0)
// Example vertices and texture coordinates
val vertices = floatArrayOf(
-1.0f, 1.0f, // top left
-1.0f, -1.0f, // bottom left
1.0f, -1.0f, // bottom right
1.0f, 1.0f // top right
)
val textureCoords = floatArrayOf(
0.0f, 0.0f, // top left
0.0f, 1.0f, // bottom left
1.0f, 1.0f, // bottom right
1.0f, 0.0f // top right
)
val vertexBuffer = ByteBuffer.allocateDirect(vertices.size * 4).run {
order(ByteOrder.nativeOrder())
asFloatBuffer().apply {
put(vertices)
position(0)
}
}
val textureCoordBuffer = ByteBuffer.allocateDirect(textureCoords.size * 4).run {
order(ByteOrder.nativeOrder())
asFloatBuffer().apply {
put(textureCoords)
position(0)
}
}
GLES31.glVertexAttribPointer(
positionHandle, 2,
GLES31.GL_FLOAT, false,
0, vertexBuffer
)
GLES31.glVertexAttribPointer(
textureCoordHandle, 2,
GLES31.GL_FLOAT, false,
0, textureCoordBuffer
)
GLES31.glDrawArrays(GLES31.GL_TRIANGLE_FAN, 0, 4)
GLES31.glDisableVertexAttribArray(positionHandle)
GLES31.glDisableVertexAttribArray(textureCoordHandle)
}
При такой настройке нижняя часть экрана должна быть белой, но она остается черной.
Я попробовал записать цвет единственного пикселя текстура и она тоже оказалась RGBA(0,0,0,0)
Может кто-нибудь мне помочь.
Я хочу проверить, как работают шейдеры и вычислительные шейдеры. Вычислительный шейдер должен просто окрасить пиксель в белый цвет и вернуть его. а затем шейдер должен использовать этот цвет для рисования нижней части экрана. шейдер работает нормально, но когда я попытался реализовать вычислительный шейдер, он просто не работал. Взгляните на эту реализацию рендерера. это шейдеры [b]вычислительный шейдер [code]#version 310 es precision highp float; precision highp image2D;
layout (local_size_x = 1, local_size_y = 1) in; // run only for one pixel layout (rgba32f, binding = 0) uniform writeonly image2D outputImage;
void main() { ivec2 pixelCoords = ivec2(gl_GlobalInvocationID.xy); imageStore(outputImage, pixelCoords, vec4(1.0)); // just color it white and return } [/code] фрагментный шейдер[/b] [code]#ifdef GL_FRAGMENT_PRECISION_HIGH precision highp float; #else precision mediump float; #endif
// 'varying' values are passed from the vertex shader to the fragment shader varying vec2 vTexCoord;
uniform vec3 Accelerometer;// I removed the part of code that puts this data for simplicity uniform sampler2D ColorSet;// single pixel texture returned from compute shader
void main() { if (gl_FragCoord.y > 250.0) { float x = Accelerometer[0] / 20.0; float y = Accelerometer[1] / 20.0; float z = Accelerometer[2] / 20.0; gl_FragColor = vec4(x + 0.5, y + 0.5, z + 0.5, 1.0); } else { gl_FragColor = texture2D(ColorSet, vec2(1.0)); } } [/code] Я думаю, что это правильно, но, пожалуйста, раскритиковайте меня, если я ошибаюсь, проблема должна быть в реализации средства рендеринга Renderer< /strong> [code]class MyGLRenderer( ) : GLSurfaceView.Renderer { private var computeShaderProgram = 0 private var program = 0
private val uniformLocations: MutableList = mutableListOf() private val uniformValues: MutableMap = mutableMapOf()
private var textures = IntArray(1)// only one texture private var resolution = floatArrayOf(0f,0f)
override fun onSurfaceCreated(unused: GL10?, config: EGLConfig?) {
// Allocate storage for the texture with the correct format and type GLES31.glTexImage2D( GLES31.GL_TEXTURE_2D, 0, GLES31.GL_RGBA8, // Use RGBA32F for floating-point support 1, // Texture width 1, // Texture height 0, GLES31.GL_RGBA, GLES31.GL_FLOAT, // Ensure FLOAT format for the shader compatibility null // No initial data; just allocate storage ) // Unbind the texture GLES31.glBindTexture(GLES31.GL_TEXTURE_2D, 0) }
private fun createVertexShader(): Int { return compileShader(GLES31.GL_VERTEX_SHADER,vertexCode) }
private fun createComputeProgram(): Int { return GLES31.glCreateShader(GLES31.GL_COMPUTE_SHADER).also { shader -> GLES31.glShaderSource(shader,computeCode) GLES31.glCompileShader(shader)
val compileStatus = IntArray(1) GLES31.glGetShaderiv(shader, GLES31.GL_COMPILE_STATUS, compileStatus, 0)
if (compileStatus[0] == 0) { val infoLog = GLES31.glGetShaderInfoLog(shader) GLES31.glDeleteShader(shader) throw RuntimeException("Compute Shader compilation failed: $infoLog") } } } private fun createRenderProgram(): Int {
// Assuming resolution width and height are divisible by 16 or 1 (for testing) GLES31.glDispatchCompute(1, 1, 1) GLES31.glMemoryBarrier(GLES31.GL_SHADER_IMAGE_ACCESS_BARRIER_BIT) } fun readAndLogPixelFromTexture(texture: Int, pixel:Pair) { val pixelData = FloatArray(4) GLES31.glBindTexture(GLES31.GL_TEXTURE_2D, textures[texture]) GLES31.glReadPixels(pixel.first, pixel.second, 1, 1, GLES31.GL_RGBA, GLES31.GL_FLOAT, java.nio.FloatBuffer.wrap(pixelData))
// Log the color value to verify it val r = pixelData[0] val g = pixelData[1] val b = pixelData[2] val a = pixelData[3] Timber.d("SET-COLOR: R: $r, G: $g, B: $b, A: $a") } private fun drawTexture() { GLES31.glUseProgram(renderProgram)
val positionHandle = GLES31.glGetAttribLocation(renderProgram, "aPosition") GLES31.glEnableVertexAttribArray(positionHandle)
val textureCoordHandle = GLES31.glGetAttribLocation(renderProgram, "aTexCoord") GLES31.glEnableVertexAttribArray(textureCoordHandle)
val textureHandle = GLES31.glGetUniformLocation(renderProgram, "ColorSet") GLES31.glActiveTexture(GLES31.GL_TEXTURE0) GLES31.glBindTexture(GLES31.GL_TEXTURE_2D, textures[0]) GLES31.glUniform1i(textureHandle, 0)
// Example vertices and texture coordinates val vertices = floatArrayOf( -1.0f, 1.0f, // top left -1.0f, -1.0f, // bottom left 1.0f, -1.0f, // bottom right 1.0f, 1.0f // top right )
val textureCoords = floatArrayOf( 0.0f, 0.0f, // top left 0.0f, 1.0f, // bottom left 1.0f, 1.0f, // bottom right 1.0f, 0.0f // top right )
GLES31.glDisableVertexAttribArray(positionHandle) GLES31.glDisableVertexAttribArray(textureCoordHandle) } [/code] При такой настройке нижняя часть экрана должна быть белой, но она остается черной. Я попробовал записать цвет единственного пикселя текстура и она тоже оказалась RGBA(0,0,0,0) Может кто-нибудь мне помочь.