Я хочу проверить, как работают шейдеры и вычислительные шейдеры.
Вычислительный шейдер должен просто окрасить пиксель в белый цвет и вернуть его. а затем шейдер должен использовать этот цвет для рисования нижней части экрана.
шейдер работает нормально, но когда я попытался реализовать вычислительный шейдер, он просто не работал.
Взгляните на эту реализацию рендерера.
это шейдеры вычислительный шейдер
вычислительный шейдер
Strong>
#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>
Я хочу проверить, как работают шейдеры и вычислительные шейдеры. Вычислительный шейдер должен просто окрасить пиксель в белый цвет и вернуть его. а затем шейдер должен использовать этот цвет для рисования нижней части экрана. шейдер работает нормально, но когда я попытался реализовать вычислительный шейдер, он просто не работал. Взгляните на эту реализацию рендерера. это шейдеры [b]вычислительный шейдер вычислительный шейдер Strong> [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()
fun bakeProgram(code: String, clear: Boolean): Int { if (clear) GLES31.glClearColor(0.0f, 0.0f, 0.0f, 1.0f) val vertexShader = loadShader(GLES31.GL_VERTEX_SHADER, vertexShaderCode) val fragmentShader = loadShader(GLES31.GL_FRAGMENT_SHADER, code) return GLES31.glCreateProgram().also { GLES31.glAttachShader(it, vertexShader) GLES31.glAttachShader(it, fragmentShader) GLES31.glLinkProgram(it)
// Check for linking errors val linkStatus = IntArray(1) GLES31.glGetProgramiv(it, GLES31.GL_LINK_STATUS, linkStatus, 0) if (linkStatus[0] == 0) { GLES31.glDeleteProgram(it) Log.d("renderer", "not linked successfully for \n${code}") throw RuntimeException("Could not link program: ${GLES31.glGetProgramInfoLog(it)}") } else{ Log.d("renderer", "linked successfully") } } }
fun setupComputeShader() {
// Create and bind texture GLES31.glGenTextures(1, textures, 0)
GLES31.glBindTexture(GLES31.GL_TEXTURE_2D, textures[0]) GLES31.glTexParameteri(GLES31.GL_TEXTURE_2D, GLES31.GL_TEXTURE_MIN_FILTER, GLES31.GL_LINEAR) GLES31.glTexParameteri(GLES31.GL_TEXTURE_2D, GLES31.GL_TEXTURE_MAG_FILTER, GLES31.GL_LINEAR) GLES31.glTexImage2D( GLES31.GL_TEXTURE_2D, 0, GLES31.GL_RGBA32F, 1, // width 1, // height 0, GLES31.GL_RGBA, GLES31.GL_FLOAT, null ) // it is of size 1,1 because for testing, I only need one pixel
// Load and compile compute shader val computeShader = GLES31.glCreateShader(GLES31.GL_COMPUTE_SHADER).also { shader -> GLES31.glShaderSource(shader, computeShaderCode) 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") } } computeShaderProgram = GLES31.glCreateProgram().also { GLES31.glAttachShader(it, computeShader) GLES31.glLinkProgram(it) // Check for linking errors val linkStatus = IntArray(1) GLES31.glGetProgramiv(it, GLES31.GL_LINK_STATUS, linkStatus, 0) if (linkStatus[0] == 0) { GLES31.glDeleteProgram(it) throw RuntimeException("Could not link compute shader program: ${GLES31.glGetProgramInfoLog(it)}") } } }
override fun onDrawFrame(gl: GL10?) {
// IDK this was recommended by gpt GLES31.glEnable(GLES31.GL_BLEND) GLES31.glBlendFunc(GLES31.GL_SRC_ALPHA, GLES31.GL_ONE_MINUS_SRC_ALPHA)
// binding texture[0] to "ColorSet" inside fragment shader GLES31.glActiveTexture(GLES31.GL_TEXTURE0) GLES31.glBindTexture(GLES31.GL_TEXTURE_2D, textures[0]) GLES31.glUniform1i(GLES31.glGetUniformLocation(program, "ColorSet"), 0)
// run the compute shader fun dispatchComputeShader() { GLES31.glUseProgram(computeShaderProgram) 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(resolution[0].toInt(), resolution[1].toInt(), 1) GLES31.glMemoryBarrier(GLES31.GL_SHADER_IMAGE_ACCESS_BARRIER_BIT) }
private fun loadShader(type: Int, shaderCode: String): Int { return GLES31.glCreateShader(type).also { shader -> GLES31.glShaderSource(shader, shaderCode) GLES31.glCompileShader(shader)
// Check for compilation errors val compiled = IntArray(1) GLES31.glGetShaderiv(shader, GLES31.GL_COMPILE_STATUS, compiled, 0) if (compiled[0] == 0) { Timber.e("Shader compilation failed: %s", GLES31.glGetShaderInfoLog(shader)) GLES31.glDeleteShader(shader) } } }
// render the result private fun drawTexture() { val mainProgram = program GLES31.glUseProgram(mainProgram)
val positionHandle = GLES31.glGetAttribLocation(mainProgram, "aPosition") GLES31.glEnableVertexAttribArray(positionHandle)
val textureCoordHandle = GLES31.glGetAttribLocation(mainProgram, "aTexCoord") GLES31.glEnableVertexAttribArray(textureCoordHandle)
// 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] При этой настройке нижняя часть экрана должна быть белой, но она остается черной. Кто-нибудь может мне помочь?