webgl getUniformLocation returns 0

webgl getUniformLocation returns 0

简而言之,我遇到了一个问题,即通过 getUniformLocation 调用不同的制服似乎都 return 相同的值。

很难验证这一点,因为 returned Glint 对于 javascript 控制台是不透明的。但是,当查看其他人的代码示例时,我注意到您可以在其位置传递标准 javascript 数字,因此此试用代码:

const infoA = gl.getActiveUniform(program, gl.getUniformLocation(program, 'uSampler'));
const infoB = gl.getActiveUniform(program, gl.getUniformLocation(program, 'uRotationMatrix'));
const infoC = gl.getActiveUniform(program, 0);
const infoD = gl.getActiveUniform(program, 1);

infoAinfoB 都等于 'uRotationMatrix' 制服的 WebGLActiveInfo 对象,infoC 也是如此,但是 infoDreturns 'uSampler'.

的信息数据

我能找到的最接近类似问题的是关于优化删除未使用的制服导致 getUniformLocation 总是 returning -1。我不相信这里是这种情况,因为两种制服都被使用并使用 Ben Vanik https://github.com/benvanik/WebGL-Inspector 的 webgl-inspector chrome 扩展,我看到程序面板中列出的两种制服的 idx 值为 0和 1. 但是我确实注意到,提供无效的统一名称不会产生任何错误,并导致 'uRotationMatrix' (infoE) 的信息对象的 'default' return 值;仅使用 -1 导致错误 (infoF)。

const infoE = gl.getActiveUniform(program, gl.getUniformLocation(program, 'INVALID_NAME');
const infoF = gl.getActiveUniform(program, -1); // null

有趣的是,Safari 中的结果是相反的,即大多数调用 return 'uSampler' 的信息对象,而只明确使用 javascript 数字,returns 'uRotationMatrix'

的信息对象

着色器在下面并且非常简单,它们和我在 return 检查相关参数时成功链接它们的程序。即

gl.getShaderParameter(shader, gl.COMPILE_STATUS);
gl.getProgramParameter(program, gl.LINK_STATUS);

顶点。

precision mediump float;

attribute vec2 aPosition;
attribute vec2 aTexCoord;

uniform mat4 uRotationMatrix;

varying vec2 fragTexCoord;

void main() {

  fragTexCoord = aTexCoord;

  gl_Position = uRotationMatrix * vec4(aPosition, 0.0, 1.0);
}

片段。

precision mediump float;

varying vec2 fragTexCoord;
uniform sampler2D uSampler;

void main() {


  vec4 sample = texture2D(uSampler, fragTexCoord);

  gl_FragColor = vec4(sample.rgb, 1.0);
}

有没有人对我应该在哪里查找问题有任何指示?

编辑:

参考确保参数类型和 return 值类型兼容,通过相关函数的 MDN 文档。

"location: A GLuint specifying the index of the uniform attribute to get. This value is returned by getUniformLocation()." Link: getActiveUniform

"Return value: A WebGLUniformLocation value indicating the location of the named variable, ... The WebGLUniformLocation type is compatible with the GLint type when specifying the index or location of a uniform attribute." Link: getUniformLocation

gl.getUniformLocation 不会 return -1 对于 non-existent 制服。它 returns null

这段代码毫无意义

const infoA = gl.getActiveUniform(program, gl.getUniformLocation(program, 'uSampler'));
const infoB = gl.getActiveUniform(program, gl.getUniformLocation(program, 'uRotationMatrix'));

gl.getActiveUniform 需要一个整数。 gl.getUniformLocation returns WebGLUniformLocation object,不是整数,不能转换成整数。充其量它被转换成 NaNNaN 被转换成 0.

gl.getActiveUniform 不采用统一位置,它采用从 0 到 N - 1 的数字,其中 N 是 return 从 gl.getProgramParameter(prg, gl.ACTIVE_UNIFORMS) 编辑而来。它的目的是让你在不知道他们的名字的情况下查询制服。

const numUniforms = gl.getProgramParameter(prg, gl.ACTIVE_UNIFORMS);
for (let i = 0; i < numUniforms; ++i) {
  // get the name, type, and size of a uniform
  const info = gl.getActiveUniform(prg, i);
  // get the location of that uinform
  const loc = gl.getUniformLocation(prg, info.name);
}

请注意,WebGL 选择 gl.getUniformLocation return WebGLUniformLocation object 而不是 int 的原因是因为猜测这些 int 或假设它们是连续的。 OpenGL 不做这样的保证。

  • 两个具有相同制服的程序可能每个制服的位置不同。
  • 这些位置不是 0 和 1,它们可以是任何东西,5323 和 23424。这取决于 driver。各种 drivers return 不同的数字。
  • 类似地,对于像 uniform float foo[2] 这样的统一数组,如果 foo[0] 的位置是 37,那么 不是 意味着 foo[1] 的位置是38.

出于所有这些原因,WebGL 选择包装位置。这样可以避免许多错误 and/or 检查。您不能在 WebGLUniformLocation 上进行数学运算,因此猜测位置错误会消失(您的猜测可能在本地有效,但您正在制作一个必须在其他 GPU 上 运行 的网页)。避免了错误的统一数组数学错误。同样,您不能将一个程序中的 WebGLUniformLocation 与另一个程序一起使用,这意味着可以避免假设具有相同制服的 2 个程序对这些制服具有相同的 int 位置的错误。

虽然我们讨论的是 gl.getActiveUniform 这个话题,但您应该知道它可以 return 提供非制服的信息。示例:https://jsfiddle.net/greggman/n6mzz6jv/