为什么统一变量在 GLSL 中不起作用? [英] Why are Uniform variables not working in GLSL?

查看:17
本文介绍了为什么统一变量在 GLSL 中不起作用?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我目前正在尝试使用 LWJGL 创建一个用于后处理目的的模糊着色器,但偶然发现了一个问题.

我想改变的 Uniforms 是分辨率、半径和模糊方向(水平或垂直,所以我可以对两个方向使用一个着色器).我将输出渲染到 FrameBuffer,然后渲染到屏幕上.但不知何故,纹理只是黑色.当我使用常量值而不是uniforms 时,它完全按预期工作,所以问题一定是uniform 变量.

这是我的片段着色器的代码:

#version 330 核心出 vec4 fragColor;在 vec2 坐标中;vec4 颜色;在浮动采样器索引中;统一采样器2D采样器[32];//只是一个整数从 0 到 31 的数组统一的浮动半径;统一的 vec2 分辨率;//屏幕分辨率,或宽度&帧缓冲区的高度统一的 vec2 方向;//x 和 y 为 1 或 0无效主(){int index = int(samplerIndex);vec4 总和 = vec4(0.0);浮动模糊X =半径/分辨率.x *方向.x;浮动模糊Y =半径/分辨率.y *方向.y;sum += texture2D(samplers[index], vec2(coords.x - 4.0 * blurX, coords.y - 4.0 * blurY)) * 0.0162162162;sum += texture2D(samplers[index], vec2(coords.x - 3.0 * blurX, coords.y - 3.0 * blurY)) * 0.0540540541;sum += texture2D(samplers[index], vec2(coords.x - 2.0 * blurX, coords.y - 2.0 * blurY)) * 0.1216216216;sum += texture2D(samplers[index], vec2(coords.x - 1.0 * blurX, coords.y - 1.0 * blurY)) * 0.1945945946;sum += texture2D(samplers[index], vec2(coords.x, coords.y)) * 0.2270270270;sum += texture2D(samplers[index], vec2(coords.x + 1.0 * blurX, coords.y + 1.0 * blurY)) * 0.1945945946;sum += texture2D(samplers[index], vec2(coords.x + 2.0 * blurX, coords.y + 2.0 * blurY)) * 0.1216216216;sum += texture2D(samplers[index], vec2(coords.x + 3.0 * blurX, coords.y + 3.0 * blurY)) * 0.0540540541;sum += texture2D(samplers[index], vec2(coords.x + 4.0 * blurX, coords.y + 4.0 * blurY)) * 0.0162162162;fragColor = 颜色 * vec4(sum.rgb, 1.0);}

这就是我渲染 FrameBuffer 的方式:

 public void render(boolean fixed) {model.setTextureID(Shader.getTextureID(texture));模型缓冲区(顶点);index.put(0).put(1).put(2).put(2).put(3).put(0);顶点翻转();指数.翻转();着色器绑定();纹理绑定();shader.setUniform1iv("samplers", Shader.SAMPLERS);shader.setUniform1f("半径", 10.0f);shader.setUniform2f("分辨率", width, height);shader.setUniform2f(方向",水平,垂直);如果(固定){shader.setUniformMatrix4f("camProjection", Camera.fixedProjection);shader.setUniformMatrix4f("camTranslation", Camera.fixedTranslation);} 别的 {shader.setUniformMatrix4f("camProjection", Camera.projection);shader.setUniformMatrix4f("camTranslation", Camera.translation);}vao.bind();vbo.bind();vbo.uploadSubData(0, vertices);ibo.bind();ibo.uploadSubData(0, 指数);GL11.glDrawElements(GL11.GL_TRIANGLES, Model.INDICES, GL11.GL_UNSIGNED_INT, 0);vao.unbind();纹理.unbind();shader.unbind();vertices.clear();指数.清除();}

尽管取样器制服工作得很好,但问题似乎只影响其他三个制服.我对 OpenGL 和 GLSL 没有太多经验,我缺少什么?

解决方案

你的着色器代码根本无法工作,因为

<块引用>

samplers[index]

samplers 是一个 sampler2D 数组,index 是从顶点着色器输入 samplerIndex 设置的:<块引用>

int index = int(samplerIndex);

请参阅您使用的 GLSL 3.30 版(来自 OpenGL着色语言 3.30 规范 - 4.1.7 采样器 ):

<块引用>

采样器聚合成数组在着色器中(使用方括号 [ ])只能用整数常量表达式索引

请参阅 GLSL 版本 4.60(最新)(来自 OpenGL 着色语言 4.60 规范 - 4.1.7. 不透明类型):
(此规则适用于 GLSL 4.00 之后的所有版本)

<块引用>

当在着色器中聚合到数组中时,这些类型只能使用动态统一表达式进行索引,否则纹理查找将导致未定义的值.

因此,无论是在您使用的 GLSL 版本中,还是在最新版本中,采样器数组都不能由顶点着色器输入(属性)索引.

从 GLSL 4.00 开始,可以通过统一变量索引采样器数组,因为通过统一变量索引是一个 动态统一表达式.

<小时>

我建议使用 sampler2DArray(参见 Sampler) 而不是 sampler2D 的数组.
当您使用 sampler2DArray 时,您根本不需要任何索引,因为索引"在纹理查找时编码在纹理坐标的第三个组件中(请参阅 texture).

I am currently trying to create a Blur Shader for postprocessing purposes using LWJGL, but stumbled across a problem.

The Uniforms I want to change are resolution, radius and direction of the blur (horizontal or vertical, so I am able to use one Shader for both directions). I render the output to a FrameBuffer, which then gets rendered to the screen. But somehow, the Texture is just black. When I use constant values instead of uniforms, it works exactly as expected, so the problem must be the uniform variables.

This is the code of my fragment shader:

#version 330 core

out vec4 fragColor;

in vec2 coords;
in vec4 color;
in float samplerIndex;

uniform sampler2D samplers[32]; //Just an Array with ints from 0 to 31
uniform float radius;
uniform vec2 resolution; //Screen Resolution, or width & height of Framebuffer
uniform vec2 direction; //Either 1 or 0 for x and y

void main() {
    int index = int(samplerIndex);

    vec4 sum = vec4(0.0);

    float blurX = radius / resolution.x * direction.x;
    float blurY = radius / resolution.y * direction.y;

    sum += texture2D(samplers[index], vec2(coords.x - 4.0 * blurX, coords.y - 4.0 * blurY)) * 0.0162162162;
    sum += texture2D(samplers[index], vec2(coords.x - 3.0 * blurX, coords.y - 3.0 * blurY)) * 0.0540540541;
    sum += texture2D(samplers[index], vec2(coords.x - 2.0 * blurX, coords.y - 2.0 * blurY)) * 0.1216216216;
    sum += texture2D(samplers[index], vec2(coords.x - 1.0 * blurX, coords.y - 1.0 * blurY)) * 0.1945945946;
    sum += texture2D(samplers[index], vec2(coords.x, coords.y)) * 0.2270270270;
    sum += texture2D(samplers[index], vec2(coords.x + 1.0 * blurX, coords.y + 1.0 * blurY)) * 0.1945945946;
    sum += texture2D(samplers[index], vec2(coords.x + 2.0 * blurX, coords.y + 2.0 * blurY)) * 0.1216216216;
    sum += texture2D(samplers[index], vec2(coords.x + 3.0 * blurX, coords.y + 3.0 * blurY)) * 0.0540540541;
    sum += texture2D(samplers[index], vec2(coords.x + 4.0 * blurX, coords.y + 4.0 * blurY)) * 0.0162162162;

    fragColor = color * vec4(sum.rgb, 1.0);
}

This is how I render the FrameBuffer:

    public void render(boolean fixed) {
        model.setTextureID(Shader.getTextureID(texture));

        model.buffer(vertices);
        indices.put(0).put(1).put(2).put(2).put(3).put(0);

        vertices.flip();
        indices.flip();

        shader.bind();
        texture.bind();

        shader.setUniform1iv("samplers", Shader.SAMPLERS);
        shader.setUniform1f("radius", 10.0f);
        shader.setUniform2f("resolution", width, height);
        shader.setUniform2f("direction", horizontal, vertical);
        if(fixed) {
            shader.setUniformMatrix4f("camProjection", Camera.fixedProjection);
            shader.setUniformMatrix4f("camTranslation", Camera.fixedTranslation);
        } else {
            shader.setUniformMatrix4f("camProjection", Camera.projection);
            shader.setUniformMatrix4f("camTranslation", Camera.translation);
        }

        vao.bind();

        vbo.bind();
        vbo.uploadSubData(0, vertices);
        ibo.bind();
        ibo.uploadSubData(0, indices);

        GL11.glDrawElements(GL11.GL_TRIANGLES, Model.INDICES, GL11.GL_UNSIGNED_INT, 0);

        vao.unbind();

        texture.unbind();
        shader.unbind();

        vertices.clear();
        indices.clear();
    }

The sampler uniform works perfectly fine though, the problem only seems to affect the other three uniforms. I don't have much experience with OpenGL and GLSL, what am I missing?

解决方案

Your shader code can't work at all, because of

samplers[index]

samplers is an array of sampler2D and index is set from the vertex shader input samplerIndex:

int index = int(samplerIndex);

See GLSL version 3.30, which you use (from OpenGL Shading Language 3.30 Specification - 4.1.7 Samplers ):

Samplers aggregated into arrays within a shader (using square brackets [ ]) can only be indexed with integral constant expressions

See GLSL version 4.60 (most recent) (from OpenGL Shading Language 4.60 Specification - 4.1.7. Opaque Types):
(This rule applies to all the versions since GLSL 4.00)

When aggregated into arrays within a shader, these types can only be indexed with a dynamically uniform expression, or texture lookup will result in undefined values.

Thus, neither in the GLSL version which you use, nor in the most recent version, array of samplers can be indexed by an vertex shader input (attribute).

Since GLSL 4.00 it would be possible to index an array of samplers by an uniform, because indexing by a uniform variable is a dynamically uniform expression.


I recommend to use sampler2DArray (see Sampler) rather than an array of sampler2D.
When you use a sampler2DArray, then you don't need any indexing at all, because the "index" is encoded in the 3rd component of the texture coordinate at texture lookup (see texture).

这篇关于为什么统一变量在 GLSL 中不起作用?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆