在GLSL(330或其他版本)中,是什么导致统一结构的行为与可变结构不同?

时间:2018-08-30 17:11:10

标签: c++ opengl glsl sanity-check

我在OpenGL 3.3中遇到一个奇怪的问题。我用Dual成员“ u”和“ v”定义了一个名为vec4的结构,并开始编写和测试函数,例如稍后将在代码段中看到的“三明治产品”(我将在此测试中,我使用了两套单独的vec4制服,称它们为“ u”和“ v”,以明确其未来的目的,并简单地从中进行双重制造。当我对这种行为感到满意时,我制作了一个统一的Dual,称为“模型”(如在model-view-projection中一样),并开始将对独立向量的引用交换为对模型成员的引用。我出现黑屏,但没有错误。

我已经重新设计了顶点着色器,直到仅通过在两行上切换注释就可以启用/禁用该问题为止:

#version 330

struct Dual { vec4 u, v; };

// (...)

// This should be agnostic to where the args come from
// It was and is correct given local variables/values
Dual sandwich(Dual u, Dual v) { return mul(mul(u, v), conj(u)); }

uniform mat4 projection;

const vec4 u0 = vec4(1,0,0,0), v0 = vec4(0,0,0,0);
uniform vec4 u = u0, v = v0;
uniform Dual model = Dual(u0, v0);

in vec4 pos_in;
out vec4 pos_out;

void main(){
        // Swizzling 'xyz' and then 'yzw' adapts GLSL 'xyzw' to/from 'wxyz'
        // It may look strange, but again, it works for local values
        Dual x = Dual(u0, vec4(0, pos_in.xyz)),
                // mxm = sandwich(model, x); // -> big black canvas
                mxm = sandwich(Dual(u, v), x); // -> big rainbow square
        gl_Position = projection * vec4(mxm.v.yzw, 1);
        pos_out = gl_Position;
}

在我的C ++代码中,我尝试在初始化后设置一次值,每次按一次键到不同的预设,甚至每帧一次,但是现在我依靠着色器中的默认初始化,直到按a关键-如下所示:

auto mu = program.locate("model.u"), mv = program.locate("model.v"),
        u = program.locate("u"), v = program.locate("v");
// ...key 1 is pressed, so set both pairs to the Dual identity...
glUniform4f(mu, 1, 0, 0, 0); glUniform4f(mv, 0, 0, 0, 0);
glUniform4f(u, 1, 0, 0, 0);  glUniform4f(v, 0, 0, 0, 0);
// ...key 2 is pressed, set both to something else, and so on

当然,我的第一个猜测是我在错误地定位成员,但这是我在其他地方看到的语法,我也没有看到错字。由于没有名称不明的关联错误,因此我检查了Telltale -1的位置,但是model.umodel.v分别报告了0和1。

使用常量“ u0”和“ v0”来初始化vec4和模型的成员,但是出于对完整性的检查,我尝试按值初始化它们。该行为与应该的行为完全相同-为什么使用值会产生与初始化为该值的变量不同的结果?即使我扮演魔鬼的拥护者并假定存在一些差异,但是当将它们初始化为命名变量“ u0”和“ v0”而不是独立变量“ u”和“ v”时,为什么相同的问题不会对独立的“ u”和“ v”产生影响他们被赋予的价值?

谢谢您的时间。我觉得如果我只接受这种行为并继续前进,那我就是没有通过健全性检查的人。

1 个答案:

答案 0 :(得分:0)

const vec4 u0 = vec4(1,0,0,0), v0 = vec4(0,0,0,0);
uniform vec4 u = u0, v = v0;
uniform Dual model = Dual(u0, v0);

这三行初始化u0, v0, u, v, model。这些使用提供的值进行的初始化在链接时进行。

我在GLSL规范中找不到有关全局变量顺序的字词。我找到的最接近的是 4.2作用域

  

在声明中,名称的范围在   初始化程序(如果存在)或在声明名称之后立即   不是。

但是“作用域”与“顺序或初始化”不同。

因此,model可能在u0, v0之前被初始化,因此这些值是不确定的。

安全的方法(不依赖于不同的供应商实现)不依赖于其他全局变量,而是使用:

uniform Dual model = Dual(vec4(1,0,0,0), vec4(0,0,0,0));