Передача растрового изображения в шейдер фрагмента glsl с использованием Jetpack ComposeAndroid

Форум для тех, кто программирует под Android
Ответить Пред. темаСлед. тема
Anonymous
 Передача растрового изображения в шейдер фрагмента glsl с использованием Jetpack Compose

Сообщение Anonymous »

Я пытаюсь создать приложение для создания реактивного ранца с помощью шейдера glsl (я знаю, что AGSL существует, но для моего проекта я должен работать с glsl). Благодаря текущему прогрессу я могу правильно создавать шейдеры, но я также хочу иметь возможность передавать растровые изображения в качестве текстур.
Это код рендерера

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

import android.content.ContentResolver
import android.graphics.Bitmap
import android.opengl.GLES20
import android.opengl.GLSurfaceView
import android.opengl.GLUtils
import androidx.compose.ui.geometry.Offset
import com.dhruv.angular_launcher.core.resources.AllResources
import com.dhruv.angular_launcher.core.resources.ShaderData
import com.dhruv.angular_launcher.core.resources.textureBitmaps
import com.dhruv.angular_launcher.utils.ScreenUtils
import java.nio.ByteBuffer
import java.nio.ByteOrder
import javax.microedition.khronos.egl.EGLConfig
import javax.microedition.khronos.opengles.GL10
import kotlin.math.min

class MyGLRenderer(
contentResolver: ContentResolver,
val shaderData: ShaderData,
) : GLSurfaceView.Renderer {

private val vertexShaderCode =
"attribute vec4 aPosition;" +
"attribute vec2 aTexCoord;" +
"varying vec2 vTexCoord;" +
"void main() {" +
"   gl_Position = aPosition;" +
"   vTexCoord = aTexCoord / vec2(${ScreenUtils.screenSizeDp.height/ ScreenUtils.screenSizeDp.width}., 1.);" +
"}"

private val fragmentShaderCode = shaderData.code

private var program: Int = 0

private val uniformLocations: MutableMap = mutableMapOf()
private val uniformValues: MutableMap = mutableMapOf()

private val textures: List = shaderData.textureBitmaps(contentResolver)
private val textureIds: IntArray = IntArray(textures.size)

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

fun PrepareData(key: String, value: Any){
uniformValues[key] = value
}

override fun onSurfaceCreated(gl: GL10?, config: EGLConfig?) {
GLES20.glClearColor(0.0f, 0.0f, 0.0f, 1.0f)
setupShader()
loadTextures()
}

private fun setupShader() {
val vertexShader = loadShader(GLES20.GL_VERTEX_SHADER, vertexShaderCode)
val fragmentShader = loadShader(GLES20.GL_FRAGMENT_SHADER, fragmentShaderCode)

program = GLES20.glCreateProgram().also {
GLES20.glAttachShader(it, vertexShader)
GLES20.glAttachShader(it, fragmentShader)
GLES20.glLinkProgram(it)
}

shaderData.resourcesAsked.forEach { uniformLocations[it] = GLES20.glGetUniformLocation(program, it) }
textures.forEach { (name, bitmap) ->  uniformLocations[name] = GLES20.glGetUniformLocation(program, name) }
}

private fun loadShader(type: Int, shaderCode: String): Int {
return GLES20.glCreateShader(type).also { shader ->
GLES20.glShaderSource(shader, shaderCode)
GLES20.glCompileShader(shader)
}
}

private fun loadTextures() {
GLES20.glGenTextures(textures.size, textureIds, 0) // Generate texture IDs

for (i in textures.indices) {
val bitmap = textures[i].second
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureIds[i])
GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, bitmap, 0)
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_LINEAR)
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR)
}
}

override fun onDrawFrame(gl: GL10?) {
GLES20.glDisable(GL10.GL_DITHER)
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT or GLES20.GL_DEPTH_BUFFER_BIT)

if (uniformLocations.containsKey(AllResources.Frame.name)){
GLES20.glUniform1i(uniformLocations[AllResources.Frame.name]!!, frame)
frame += 1
}
uniformLocations.forEach{(key, location) ->
location?.let { l ->
uniformValues.getOrDefault(key, null)?.let { value ->
insertData(l, value)
}
}
}

for (i in textures.indices) {
GLES20.glActiveTexture(GLES20.GL_TEXTURE0 + i)
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureIds[i])
GLES20.glUniform1i(GLES20.glGetUniformLocation(program, textures[i].first), i)
println("name: ${textures[i].first} location: ${GLES20.glGetUniformLocation(program, textures[i].first)}, id: ${textureIds[i]}")
}
drawTexture()
}

private fun insertData(l: Int, value: Any){
if (value is Float) GLES20.glUniform1f(l, value)
if (value is FloatArray) {
when (value.size) {
1 -> {GLES20.glUniform1f(l, value[0])}
2 -> {GLES20.glUniform2f(l, value[0], value[1])}
3 -> {GLES20.glUniform3f(l, value[0], value[1], value[2])}
4 -> {GLES20.glUniform4f(l, value[0], value[1], value[2], value[3])}
else -> {}
}
}
if (value is Int) GLES20.glUniform1i(l, value)
if (value is IntArray) {
when (value.size) {
1 -> {GLES20.glUniform1i(l, value[0])}
2 -> {GLES20.glUniform2i(l, value[0], value[1])}
3 -> {GLES20.glUniform3i(l, value[0], value[1], value[2])}
4 -> {GLES20.glUniform4i(l, value[0], value[1], value[2], value[3])}
6 -> {
GLES20.glUniform3i(l, value[0], value[1], value[2])
GLES20.glUniform3i(l+3, value[3], value[4], value[5])
}
else -> {}
}
}
if (value is Boolean) GLES20.glUniform1i(l, if (value) 1 else 0)
if (value is List) {
val len = value.size
if (len > 0 && value[0] is Offset) {
for (i in 0 until  min(len, 100)) {
val offset = value[i] as Offset
GLES20.glUniform2f(l + i, offset.x, offset.y)
}
}
if (len > 0 &&  value[0] is FloatArray) {
if ((value[0] as FloatArray).size == 1)
for (i in 0 until  min(len, 100)) {
val v = value[i] as FloatArray
GLES20.glUniform1f(l + i, v[0])
}
if ((value[0] as FloatArray).size == 2)
for (i in 0 until  min(len, 100)) {
val v = value[i] as FloatArray
GLES20.glUniform2f(l + i, v[0], v[1])
}
if ((value[0] as FloatArray).size == 3)
for (i in 0 until  min(len, 100)) {
val v = value[i] as FloatArray
GLES20.glUniform3f(l + i, v[0], v[1], v[2])
}
if ((value[0] as FloatArray).size == 4)
for (i in 0 until  min(len, 100)) {
val v = value[i] as FloatArray
GLES20.glUniform4f(l + i, v[0], v[1], v[2], v[3])
}
}
}
}

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

private fun drawTexture() {
GLES20.glUseProgram(program)

val positionHandle = GLES20.glGetAttribLocation(program, "aPosition")
GLES20.glEnableVertexAttribArray(positionHandle)

val textureCoordHandle = GLES20.glGetAttribLocation(program, "aTexCoord")
GLES20.glEnableVertexAttribArray(textureCoordHandle)

// Define vertices and texture coordinates here and pass them to OpenGL ES buffers
// 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)
}
}

GLES20.glVertexAttribPointer(
positionHandle, 2,
GLES20.GL_FLOAT, false,
0, vertexBuffer
)

GLES20.glVertexAttribPointer(
textureCoordHandle, 2,
GLES20.GL_FLOAT, false,
0, textureCoordBuffer
)

GLES20.glDrawArrays(GLES20.GL_TRIANGLE_FAN, 0, 4)

GLES20.glDisableVertexAttribArray(positionHandle)
GLES20.glDisableVertexAttribArray(textureCoordHandle)
}
}
Это код glsl, который использует эти текстуры

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

#version 100
#ifdef GL_FRAGMENT_PRECISION_HIGH
precision highp float;
#else
precision mediump float;
#endif

varying vec2 vTexCoord;
uniform sampler2D TEX0;

void main() {
vec4 color = texture2D(TEX0, vTexCoord);
gl_FragColor = color;
}
ПРИМЕЧАНИЕ
  • список текстур содержит имя текстуры с соответствующим растровым изображением.< /li>
    названия текстур присутствуют во фрагментном шейдере.
помощь ИИ< /p>
chat gpt написал этот код, который работает, но только для одной текстуры, а не для нескольких текстур. В моей собственной реализации я просто добавил способ передачи различных данных в шейдер и обеспечения их совместимости с различными модулями моего приложения.

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

import android.content.Context
import android.graphics.Bitmap
import android.graphics.BitmapFactory
import android.opengl.GLES20
import android.opengl.GLUtils
import javax.microedition.khronos.egl.EGLConfig
import javax.microedition.khronos.opengles.GL10

class MyGLRenderer(private val context: Context) : GLSurfaceView.Renderer {
private var textureHandle: Int = 0
private lateinit var bitmap: Bitmap

private val vertexShaderCode =
"attribute vec4 aPosition;" +
"attribute vec2 aTexCoord;" +
"varying vec2 vTexCoord;" +
"void main() {" +
"  gl_Position = aPosition;" +
"  vTexCoord = aTexCoord;" +
"}"

private val fragmentShaderCode =
"precision mediump float;" +
"uniform sampler2D uTexture;" +
"varying vec2 vTexCoord;" +
"void main() {" +
"  gl_FragColor = texture2D(uTexture, vTexCoord);"  +
"}"

private var program: Int = 0

override fun onSurfaceCreated(gl: GL10?, config: EGLConfig?) {
GLES20.glClearColor(0.0f, 0.0f, 0.0f, 1.0f)
loadTexture()
setupShader()
}

override fun onDrawFrame(gl: GL10?) {
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT or GLES20.GL_DEPTH_BUFFER_BIT)
drawTexture()
}

override fun onSurfaceChanged(gl: GL10?, width: Int, height: Int) {
GLES20.glViewport(0, 0, width, height)
}

private fun loadTexture() {
// Load the bitmap from drawable
bitmap = BitmapFactory.decodeResource(context.resources, R.drawable.your_png_resource)

val textures = IntArray(1)
GLES20.glGenTextures(1, textures, 0)
textureHandle = textures[0]

GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureHandle)

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)

GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, bitmap, 0)

bitmap.recycle()
}

private fun setupShader() {
val vertexShader = loadShader(GLES20.GL_VERTEX_SHADER, vertexShaderCode)
val fragmentShader = loadShader(GLES20.GL_FRAGMENT_SHADER, fragmentShaderCode)

program = GLES20.glCreateProgram().also {
GLES20.glAttachShader(it, vertexShader)
GLES20.glAttachShader(it, fragmentShader)
GLES20.glLinkProgram(it)
}
}

private fun loadShader(type: Int, shaderCode: String): Int {
return GLES20.glCreateShader(type).also { shader ->
GLES20.glShaderSource(shader, shaderCode)
GLES20.glCompileShader(shader)
}
}

private fun drawTexture() {
GLES20.glUseProgram(program)

val positionHandle = GLES20.glGetAttribLocation(program, "aPosition")
GLES20.glEnableVertexAttribArray(positionHandle)

val textureCoordHandle = GLES20.glGetAttribLocation(program, "aTexCoord")
GLES20.glEnableVertexAttribArray(textureCoordHandle)

val textureUniformHandle = GLES20.glGetUniformLocation(program, "uTexture")

GLES20.glActiveTexture(GLES20.GL_TEXTURE0)
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureHandle)
GLES20.glUniform1i(textureUniformHandle, 0)

// Define vertices and texture coordinates here and pass them to OpenGL ES buffers

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

GLES20.glVertexAttribPointer(
positionHandle, 2,
GLES20.GL_FLOAT, false,
0, vertexBuffer
)

GLES20.glVertexAttribPointer(
textureCoordHandle, 2,
GLES20.GL_FLOAT, false,
0, textureCoordBuffer
)

GLES20.glDrawArrays(GLES20.GL_TRIANGLE_FAN, 0, 4)

GLES20.glDisableVertexAttribArray(positionHandle)
GLES20.glDisableVertexAttribArray(textureCoordHandle)
}
}
Если кто-то знает об этом, пожалуйста, помогите.


Подробнее здесь: https://stackoverflow.com/questions/783 ... ck-compose
Реклама
Ответить Пред. темаСлед. тема

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

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

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

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

  • Похожие темы
    Ответы
    Просмотры
    Последнее сообщение
  • Как мне проанализировать шейдер из ShaderToy в GLSL для использования в Android?
    Anonymous » » в форуме Android
    0 Ответы
    23 Просмотры
    Последнее сообщение Anonymous
  • GLSL Шейдер работает по -разному на разных устройствах
    Anonymous » » в форуме C++
    0 Ответы
    6 Просмотры
    Последнее сообщение Anonymous
  • Передача данных из std::vector в юниформ-массив в glsl
    Anonymous » » в форуме C++
    0 Ответы
    33 Просмотры
    Последнее сообщение Anonymous
  • Отображение фрагмента в Jetpack Compose с использованием AndroidFragment<>
    Anonymous » » в форуме Android
    0 Ответы
    27 Просмотры
    Последнее сообщение Anonymous
  • Отображение фрагмента в Jetpack Compose с использованием AndroidFragment<>
    Anonymous » » в форуме Android
    0 Ответы
    22 Просмотры
    Последнее сообщение Anonymous

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