You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于LibGDX Shader实现视差效果遇白屏问题求助

解决直接用ShaderProgram渲染Mesh实现视差效果的白屏问题

我当年第一次脱离SpriteBatch直接用Shader渲染Mesh的时候也踩过这些坑,白屏简直是家常便饭。结合你的情况,大概率是遗漏了直接渲染Mesh时的几个基础要点,咱们一步步排查:

1. 先确认Shader本身没编译/链接错误

很多时候白屏的根源是Shader代码写错了,但你没察觉。一定要在创建ShaderProgram后做检查:

parallaxShader = new ShaderProgram(vertexShaderCode, fragmentShaderCode);
if (!parallaxShader.isCompiled()) {
    Gdx.app.error("Shader", "Vertex shader compile error: " + parallaxShader.getVertexShaderLog());
}
if (!parallaxShader.isLinked()) {
    Gdx.app.error("Shader", "Program link error: " + parallaxShader.getProgramLog());
}

要是日志里有错误,先把Shader的语法问题解决,比如变量名不匹配、GLSL版本不兼容(比如你用了GLSL 300但LibGDX默认是100)。

2. 确保全屏Quad的顶点数据和Shader属性对应

视差效果需要顶点的UV坐标来采样纹理,所以你的全屏Mesh必须包含位置和UV这两个顶点属性,而且要和Shader里的attribute变量名完全一致。比如Shader里写的是attribute vec2 a_position和attribute vec2 a_uv,那创建Mesh时就要对应:

private Mesh createFullscreenQuad() {
    Mesh mesh = new Mesh(true, 4, 6,
            new VertexAttribute(VertexAttributes.Usage.Position, 2, "a_position"),
            new VertexAttribute(VertexAttributes.Usage.TextureCoordinates, 2, "a_uv"));

    // 顶点数据:x,y, u,v
    float[] vertices = {
        -1f, -1f, 0f, 0f,
        1f, -1f, 1f, 0f,
        1f, 1f, 1f, 1f,
        -1f, 1f, 0f, 1f
    };
    short[] indices = {0, 1, 2, 0, 2, 3}; // 用三角面渲染全屏

    mesh.setVertices(vertices);
    mesh.setIndices(indices);
    return mesh;
}

要是顶点属性的名字或者分量数和Shader不匹配,Shader就拿不到正确的数据,自然会显示白屏。

3. 渲染时的Shader绑定与Uniform设置不能漏

脱离SpriteBatch后,所有的Uniform都得手动设置,包括纹理:

public void render() {
    // 先清屏,不然可能残留上一帧的内容
    Gdx.gl.glClearColor(0f, 0f, 0f, 1f);
    Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);

    // 启用Shader
    parallaxShader.begin();

    // 设置纹理Uniform:注意纹理单元要对应
    parallaxShader.setUniformi("u_mainTexture", 0);
    Gdx.gl.glActiveTexture(GL20.GL_TEXTURE0);
    yourMainTexture.bind(); // 你的视差基础纹理

    // 视差效果需要的深度纹理也要设置
    parallaxShader.setUniformi("u_depthTexture", 1);
    Gdx.gl.glActiveTexture(GL20.GL_TEXTURE1);
    yourDepthTexture.bind(); // 你的深度图纹理

    // 其他视差参数,比如位移强度、视角位置等
    parallaxShader.setUniformf("u_parallaxStrength", 0.15f);
    parallaxShader.setUniformf("u_viewPos", camera.position.x, camera.position.y);

    // 渲染Mesh:注意图元类型要和你的索引/顶点数据匹配
    fullscreenQuad.render(parallaxShader, GL20.GL_TRIANGLES);

    // 一定要关闭Shader
    parallaxShader.end();
}

这里最容易忘的是纹理单元的激活,比如你设置了u_depthTexture对应单元1,但没调用glActiveTexture(GL_TEXTURE1)就绑定纹理,Shader就会采样到错误的纹理(甚至是空的),导致白屏。

4. 检查OpenGL状态设置

有时候其他代码修改了GL状态,影响渲染:

  • 如果你的视差效果不需要深度测试,可以关闭:Gdx.gl.glDisable(GL20.GL_DEPTH_TEST);
  • 如果纹理带透明,要开启混合:Gdx.gl.glEnable(GL20.GL_BLEND); Gdx.gl.glBlendFunc(GL20.GL_SRC_ALPHA, GL20.GL_ONE_MINUS_SRC_ALPHA);
  • 确保纹理的Wrap模式和过滤设置正确,比如重复纹理要设置yourTexture.setWrap(Texture.TextureWrap.Repeat, Texture.TextureWrap.Repeat);

最后检查Shader逻辑

如果上面都没问题,那可能是视差计算的逻辑导致全白:

  • 比如片元Shader里深度采样的值不对,导致位移后的UV超出纹理范围,采样到透明或白色;
  • 或者视差强度设置过大,导致UV完全偏离纹理;
  • 可以先把视差逻辑注释掉,直接采样基础纹理,如果能显示,就说明视差计算部分有问题。

内容的提问来源于stack exchange,提问作者Eugene S

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 06:27:03