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

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

Сообщение Anonymous »

Я хочу проверить, как работают шейдеры и вычислительные шейдеры.
Вычислительный шейдер должен просто окрасить пиксель в белый цвет и вернуть его. а затем шейдер должен использовать этот цвет для рисования нижней части экрана.
шейдер работает нормально, но когда я попытался реализовать вычислительный шейдер, он просто не работал.
Взгляните на эту реализацию рендерера.
это шейдеры
вычислительный шейдер
вычислительный шейдер
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
}
фрагментный шейдер[/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)

private var resolution = floatArrayOf(0f,0f)

override fun onSurfaceCreated(unused: GL10?, config: EGLConfig?) {
GLES31.glClearColor(0.0f, 0.0f, 0.0f, 1.0f)

setupComputeShader()

program = bakeProgram(fragmentShader, true)

uniformLocations.add(mutableMapOf())
resourcesAsked.forEach { uniformLocations.last()[it] = GLES31.glGetUniformLocation(program, it) }
}

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)

// running compute shader
dispatchComputeShader()
// running fragment shader
drawTexture()
}

override fun onSurfaceChanged(gl: GL10?, width: Int, height: Int) {
resolution = floatArrayOf(width.toFloat(), height.toFloat())
GLES31.glViewport(0, 0, width, height)
}

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

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)
}
}
При этой настройке нижняя часть экрана должна быть белой, но она остается черной.
Кто-нибудь может мне помочь?

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

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

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

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

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

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