libgdx/libgdx

Using multiple textures in a single shader

wangchen11 opened this issue · 0 comments

Issue details

我想要实现水下画面折射效果,尝试在单个着色器中使用多个纹理,这似乎无法正常工作。水下的纹理无法渲染出来。
I want to achieve underwater scene refraction effect, trying to use multiple textures in a single shader, but it doesn't seem to work properly. The underwater textures cannot be rendered.

Reproduction steps/code

package com.mygdx.game

import com.badlogic.gdx.ApplicationAdapter
import com.badlogic.gdx.Gdx
import com.badlogic.gdx.graphics.GL20
import com.badlogic.gdx.graphics.Texture
import com.badlogic.gdx.graphics.g2d.SpriteBatch
import com.badlogic.gdx.graphics.glutils.ShaderProgram
import java.lang.IllegalStateException

class UnderWaterEffectTest: ApplicationAdapter() {
    private lateinit var batch: SpriteBatch
    private lateinit var underWater: Texture
    private lateinit var waterSurface: Texture
    private lateinit var underWaterEffectShaderProgram: ShaderProgram
    private var deltaTime = 0f

    override fun create() {
        super.create()
        batch = SpriteBatch()
        underWater = Texture("test/under_water.png")
        waterSurface = Texture("test/water_surface.png")
        underWaterEffectShaderProgram  = ShaderProgram(
            """
        #version 100

        attribute vec4 a_position;
        attribute vec2 a_texCoord0;
        
        varying vec2 v_texCoords;
        
        uniform mat4 u_projTrans;

        void main() {
            gl_Position = u_projTrans * a_position;
            v_texCoords = a_texCoord0;
        }
            """.trimIndent(),
            """
        #version 100
        
        #ifdef GL_ES
        precision mediump float;
        #endif

        uniform sampler2D u_texture;
        uniform sampler2D u_texture_under_water;
        uniform vec2 u_resolution;
        uniform float u_time;

        varying vec2 v_texCoords;

        void main() {
            // 定义波动频率和振幅
            float frequency = 2.0;
            float amplitude = 0.02;
            float tansX = -mod(u_time / 30.0, 1.0);
            float tansY = mod(u_time / 30.0, 1.0);
            
            // 根据纹理坐标计算波动效果
            vec2 uv = v_texCoords;
            uv.y += sin(uv.x * 3.1415 * 2.0 * frequency + u_time) * amplitude;// + tansY;
            uv.x += sin(uv.y * 3.1415 * 2.0 * frequency + u_time) * amplitude;// + tansX;
            
            vec4 color = texture2D(u_texture, uv);
            vec4 colorUnderWater = texture2D(u_texture_under_water, vec2(uv.y, uv.x));
            // 获取纹理颜色并输出
            vec4 texColor = color * 0.5 + colorUnderWater * 0.5;
            gl_FragColor = texColor;
        }
            """.trimIndent()).assertCompiled()
    }

    override fun render() {
        super.render()
        deltaTime += Gdx.graphics.deltaTime
        if (deltaTime > 50f) {
            deltaTime = 0f
        }
        batch.begin()
        Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT)
        Gdx.gl.glClearColor(1f,1f,1f,1f)
        batch.shader = underWaterEffectShaderProgram
        underWaterEffectShaderProgram.setUniformf("u_time", deltaTime)
        underWaterEffectShaderProgram.setUniformi("u_texture_under_water", 2)
        underWater.bind(2)
        batch.draw(waterSurface, 0f, 0f, Gdx.graphics.width.toFloat(), Gdx.graphics.height.toFloat())
        batch.end()
    }
}

fun <T: ShaderProgram> T.assertCompiled(): T {
    val log = this.log
    if (!isCompiled) {
        throw IllegalStateException("Shader compilation failed \n:$log")
    }
    if (this.log.isNotBlank()) {
        Gdx.app.applicationLogger.error("ShaderHelper", "shader log:$log")
    }
    return this
}

under_water

water_surface

Version of libGDX and/or relevant dependencies

1.12.1

Screencap

image

Please select the affected platforms

  • Android
  • iOS
  • HTML/GWT
  • Windows
  • Linux
  • macOS