Использование вычислительных шейдеров в OpenGL ES с KotlinAndroid

Форум для тех, кто программирует под Android
Ответить
Anonymous
 Использование вычислительных шейдеров в OpenGL ES с Kotlin

Сообщение Anonymous »

Я хочу проверить, как работают шейдеры и вычислительные шейдеры.
Вычислительный шейдер должен просто окрасить пиксель в белый цвет и вернуть его. а затем шейдер должен использовать этот цвет для рисования нижней части экрана.
шейдер работает нормально, но когда я попытался реализовать вычислительный шейдер, он просто не работал.
Взгляните на эту реализацию рендерера.
это шейдеры
вычислительный шейдер

Код: Выделить всё

#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
}
фрагментный шейдер[/b]

Код: Выделить всё

#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>

Код: Выделить всё

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?) {

createTextures()
vertexShader = createVertexShader()
computeProgram = createComputeProgram()
renderProgram = createRenderProgram()
}

override fun onDrawFrame(gl: GL10?) {
GLES31.glClear(GLES31.GL_COLOR_BUFFER_BIT or GLES31.GL_DEPTH_BUFFER_BIT)

dispatchComputeShader()
readAndLogPixelFromTexture(0, Pair(0,0))
drawTexture()
}
}

Код: Выделить всё

    private fun createTextures() {
GLES31.glGenTextures(1, textures, 0)
GLES31.glBindTexture(GLES31.GL_TEXTURE_2D, textures[0])

// Set texture parameters
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.glTexParameteri(GLES31.GL_TEXTURE_2D, GLES31.GL_TEXTURE_WRAP_S, GLES31.GL_CLAMP_TO_EDGE)
GLES31.glTexParameteri(GLES31.GL_TEXTURE_2D, GLES31.GL_TEXTURE_WRAP_T, GLES31.GL_CLAMP_TO_EDGE)

// 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 {

val fragmentShader = compileShader(GLES31.GL_FRAGMENT_SHADER,rendererCode)
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)
Timber.tag("renderer").d("not linked successfully")
throw RuntimeException("Could not link program: ${GLES31.glGetProgramInfoLog(it)}")
}
else{
Timber.tag("renderer").d("linked successfully")
}
}
}
private fun compileShader(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)
}
}
}

Код: Выделить всё

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)
Может кто-нибудь мне помочь.

Подробнее здесь: https://stackoverflow.com/questions/791 ... ith-kotlin
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «Android»