Javascript GL\u由samplerCube导致的无效\u操作

Javascript GL\u由samplerCube导致的无效\u操作,javascript,glsl,webgl,opengl-es-2.0,Javascript,Glsl,Webgl,Opengl Es 2.0,我目前正在学习WebGL,并且每次都用新的东西扩展我的代码。但是,此错误会不断抛出: [.WebGLRenderingContext-0111BCC8]GL ERROR :GL_INVALID_OPERATION : glFramebufferTexture2D: <- error from previous GL command 我只在这部分代码中使用纹理单元10(仅用于反射立方体贴图) 片段着色器代码: if(uReflects){ vec3 lookup = reflect

我目前正在学习WebGL,并且每次都用新的东西扩展我的代码。但是,此错误会不断抛出:

[.WebGLRenderingContext-0111BCC8]GL ERROR :GL_INVALID_OPERATION : glFramebufferTexture2D: <- error from previous GL command
我只在这部分代码中使用纹理单元10(仅用于反射立方体贴图)

片段着色器代码:

if(uReflects){
    vec3 lookup = reflect(eyeDirection, normal);
    color += textureCube(uReflectionMap, -lookup); //no errors when this line is commented
}
当我评论上面的“突出显示”行时,一切正常(除了没有明显的反射)。因此,我预计
if(uReflects)
是错误的(因此即使没有uReflectionMap集,这段代码也会执行。只需将注释行更改为
color+=vec4(1.)
,只有我设置为反射的对象是完全白色的

此后,我尝试了将
uReflectionMap
设置为纹理单元10(
this.gl.uniform1i(p.uniforms[“uReflectionMap”],10);
在else语句中),不管我的对象是否有reflectionMap

这在我看来似乎很奇怪,因为当uReflects为false时不会执行textureCube函数,但在未设置uReflectionMap时仍会生成错误

我希望这个问题是可以理解的,我有很多代码,不知道应该给这个问题添加什么(因为可能有其他东西在干扰,我已经监督过了)

我已经在Google Chrome 43.0.2357.134 m上做了所有这些测试。只是在IE上运行了它,它似乎给出了一个更详细的错误消息,尽管它的荷兰语写得很糟糕,我不知道如何解释它,更不用说翻译了。我现在将尝试firefox。firefox没有给出任何警告,但它也不起作用


回复@gman:

这是我创建立方体贴图纹理()的代码:

var texture=gl.createTexture();
gl.bindTexture(gl.TEXTURE\u CUBE\u贴图,纹理);
gl.texParameteri(gl.TEXTURE\u CUBE\u MAP、gl.TEXTURE\u WRAP\S、gl.CLAMP\u TO\u EDGE);
gl.texParameteri(gl.TEXTURE\u CUBE\u MAP、gl.TEXTURE\u WRAP\u T、gl.CLAMP\u TO\u EDGE);
gl.texParameteri(gl.TEXTURE\u CUBE\u MAP,gl.TEXTURE\u MAG\u FILTER,gl.NEAREST);
gl.texParameteri(gl.TEXTURE\u CUBE\u MAP,gl.TEXTURE\u MIN\u FILTER,gl.NEAREST);
变量大小=1024;
this.reflectionFrameBuffers=[];
this.reflectionRenderBuffers=[];
对于(变量i=0;i<6;i++){
gl.texImage2D(gl.TEXTURE\u CUBE\u MAP\u POSITIVE\u X+i,0,gl.RGBA,size,size,0,gl.RGBA,gl.UNSIGNED\u字节,null);
this.reflectionRenderBuffers[i]=gl.createRenderbuffer();
gl.binderbuffer(gl.RENDERBUFFER,this.reflectionRenderBuffers[i]);
gl.renderbufferStorage(gl.RENDERBUFFER,gl.DEPTH_组件16,尺寸,尺寸);
this.reflectionFrameBuffers[i]=gl.createFramebuffer();
gl.bindFramebuffer(gl.FRAMEBUFFER,this.reflectionFrameBuffers[i]);
gl.framebufferTexture2D(gl.FRAMEBUFFER,gl.COLOR_ATTACHMENT0,gl.TEXTURE_CUBE_MAP_正片_X+i,纹理,0);
gl.framebufferRenderbuffer(gl.FRAMEBUFFER,gl.DEPTH_附件,gl.RENDERBUFFER,this.reflectionRenderBuffers[i]);
gl.checkFramebufferStatus(gl.FRAMEBUFFER);//这不会抛出错误
}
gl.bindTexture(gl.TEXTURE_2D,空);
gl.bindFramebuffer(gl.FRAMEBUFFER,null);
gl.binderbuffer(gl.RENDERBUFFER,null);
在渲染之前,此部件将清除所有侧面:

this.gl.colorMask(true, true, true, true);
this.gl.clearColor(0, 0, 0, 1);
this.gl.cullFace(this.gl.BACK);

for (var j = 0; j < 6; j++) {
    this.gl.bindFramebuffer(this.gl.FRAMEBUFFER, obj.reflectionFrameBuffers[j]);
    this.gl.clear(this.gl.COLOR_BUFFER_BIT | this.gl.DEPTH_BUFFER_BIT);
}
this.gl.colorMask(真,真,真,真);
这个.gl.clearColor(0,0,0,1);
此.gl.cullFace(此.gl.BACK);
对于(var j=0;j<6;j++){
this.gl.bindFramebuffer(this.gl.FRAMEBUFFER,obj.reflectionFrameBuffers[j]);
this.gl.clear(this.gl.COLOR_BUFFER_BIT | this.gl.DEPTH_BUFFER_BIT);
}
这是渲染到立方体贴图的代码(它被其他for循环包围,代码用于为reflectionMapper着色器提供信息):

for(var k=0;k<6;k++){
this.gl.bindFramebuffer(this.gl.FRAMEBUFFER,obj.reflectionFrameBuffers[k]);
this.gl.uniformMatrix4fv(p.uniforms[“uViewMatrix”],false,obj.reflectionViewMatrix[k].array);//这些视图矩阵确定了要查看的方向
this.gl.drawArray(this.gl.TRIANGLES,0,mesh.facesArray.length/9);
}

问题在于,您有两个不同类型的统一采样器指向同一纹理单元

着色器通常执行所有路径。我的意思是,如果你的着色器中有这个

if (someCondition) {
  a = value1;
} else {
  a = value2;
}
着色器中实际发生的情况类似于

a = value1 * (someCondition ? 1 : 0) + value2 * (someCondition ? 0 : 1);
或者更好

// mix will be 1.0 if someCondition is true, else 0.0
float mix = step(0.5, 1.0 - float(someCondition)); 

a = value1 * mix + value2 * (1 - mix);
现在没有分支。GPU不分支,这就是它们获得速度的方式。请注意,我制作了一个示例,但它显示了一点,即无论条件如何,都使用value1和value2。这假设条件是可变的。在您的示例中

uniform bool uIsCube;
uniform sampler2D uTwoD;
uniform samplerCube uCube;

varying vec3 vTexCoord;

void main(void){
    if(uIsCube){
        gl_FragColor = textureCube(uCube, vTexCoord);
    } else {
        gl_FragColor = texture2D(uTwoD, vTexCoord.st);
    }
}
uIsCube
是可变的。我在编译时不知道,只能在运行时知道,所以总是使用
uCube
uTwoD
,需要使用
gl.uniform1i

另一方面,如果条件是这样的常数

#define IsCube false

void main(void){
    if(IsCube){
        gl_FragColor = textureCube(uCube, vTexCoord);
    } else {
        gl_FragColor = texture2D(uTwoD, vTexCoord.st);
    }
}
然后在编译时,编译器可能会删除其中一个采样器。我说可能是因为IIRC规范不需要驱动程序来优化着色器中未使用的代码

还请注意,制服都默认为0,因此如果不设置制服,则两个采样器都将指向纹理单元

您可以通过检查制服的位置来检查制服是否已优化

var uCubeLoc = gl.getUniformLocation(program, "uCube");
if (!uCubeLoc) {
  // uCubeLoc does not exist or was optimized out
}
要查看与指向同一纹理单元的不同类型的多个采样器相关的代码中是否存在错误,您可以在每次调用
gl.draw\uuuuuu
之前调用类似的函数

function checkForConflictingSamplers() {
  var prg = gl.getParameter(gl.CURRENT_PROGRAM);
  var units = {};
  var numUniforms = gl.getProgramParameter(prg, gl.ACTIVE_UNIFORMS);

  function checkUniform(name, type) {
    var unit = gl.getUniform(prg, gl.getUniformLocation(prg, name));
    var unitInfo = units[unit];
    if (unitInfo === undefined) {
      units[unit] = { 
        type: type,
        name: name,
      };
    } else if (unitInfo.type !== type) {
      console.error("unit " + unit + " is being used by conflicting samplers " + name + " and " + unitInfo.name);
    }
  }    

  for (var ii = 0; ii < numUniforms; ++ii) {
    var uniformInfo = gl.getActiveUniform(prg, ii);
    if (!uniformInfo) {
      continue;
    }
    var name = uniformInfo.name;
    var type = uniformInfo.type;
    var isArray = (uniformInfo.size > 1 && name.substr(-3) === "[0]");
    // remove the array suffix.
    if (name.substr(-3) === "[0]") {
      name = name.substr(0, name.length - 3);
    }

    if (type === gl.SAMPLER_2D || type === gl.SAMPLER_CUBE) {
      if (isArray) {
        for (var ii = 0; ii < uniformInfo.size; ++ii) {
          checkUniform(name + "[" + ii + "]", type);
        }
      } else {
        checkUniform(name, type);
      }
    }
  }
}
conflictingsamplers()的函数检查{
var prg=gl.getParameter(gl.CURRENT_程序);
变量单位={};
var numiniforms=gl.getProgramParameter(prg,gl.ACTIVE\u);
函数checkUniform(名称、类型){
var unit=gl.getUniform(prg,gl.getUniformLocation(prg,名称));
var unitInfo=单位[单位];
如果(unitInfo==未定义){
单位[单位]={
类型:类型,
姓名:姓名,,
};
}else if(unitInfo.type!==type){
控制台错误(“单元”+uni
#define IsCube false

void main(void){
    if(IsCube){
        gl_FragColor = textureCube(uCube, vTexCoord);
    } else {
        gl_FragColor = texture2D(uTwoD, vTexCoord.st);
    }
}
var uCubeLoc = gl.getUniformLocation(program, "uCube");
if (!uCubeLoc) {
  // uCubeLoc does not exist or was optimized out
}
function checkForConflictingSamplers() {
  var prg = gl.getParameter(gl.CURRENT_PROGRAM);
  var units = {};
  var numUniforms = gl.getProgramParameter(prg, gl.ACTIVE_UNIFORMS);

  function checkUniform(name, type) {
    var unit = gl.getUniform(prg, gl.getUniformLocation(prg, name));
    var unitInfo = units[unit];
    if (unitInfo === undefined) {
      units[unit] = { 
        type: type,
        name: name,
      };
    } else if (unitInfo.type !== type) {
      console.error("unit " + unit + " is being used by conflicting samplers " + name + " and " + unitInfo.name);
    }
  }    

  for (var ii = 0; ii < numUniforms; ++ii) {
    var uniformInfo = gl.getActiveUniform(prg, ii);
    if (!uniformInfo) {
      continue;
    }
    var name = uniformInfo.name;
    var type = uniformInfo.type;
    var isArray = (uniformInfo.size > 1 && name.substr(-3) === "[0]");
    // remove the array suffix.
    if (name.substr(-3) === "[0]") {
      name = name.substr(0, name.length - 3);
    }

    if (type === gl.SAMPLER_2D || type === gl.SAMPLER_CUBE) {
      if (isArray) {
        for (var ii = 0; ii < uniformInfo.size; ++ii) {
          checkUniform(name + "[" + ii + "]", type);
        }
      } else {
        checkUniform(name, type);
      }
    }
  }
}