【问题标题】:Setting ShaderMaterial `skinning` property to `true` causes 'too many uniforms' error将 ShaderMaterial `skinning` 属性设置为 `true` 会导致“制服过多”错误
【发布时间】:2017-08-28 15:53:41
【问题描述】:

我有以下从 JSON 文件加载网格的函数:

loadJSONModel(filename, modelName) {
let loader = new THREE.JSONLoader();
loader.load(`assets/${filename}`, (geometry, materials) => {

  let material = Shader.createShaderMaterial(Shader.LINEAR_BLEND_SKINNING_VERT, Shader.BASIC_FRAG);
  let mesh = new THREE.SkinnedMesh(geometry, material);
  mesh.material.skinning = true;
  mesh.rotation.x = 0.5 * Math.PI;
  mesh.rotation.z = 0.7 * Math.PI;
  this.scene.add(mesh);

});

Shader.createShaderMaterial 函数执行以下操作:

 static createShaderMaterial(vertex, fragment, uniforms) {
    if (uniforms === undefined) uniforms = {};
    return new THREE.ShaderMaterial({
      uniforms: uniforms,
      vertexShader: vertex,
      fragmentShader: fragment,
    });
  }

现在我不断收到这个卑鄙的错误:

THREE.WebGLProgram: shader error:  0 gl.VALIDATE_STATUS false gl.getProgramInfoLog invalid shaders ERROR: too many uniforms 

如果我不做mesh.material.skinning = true,它就会消失,但当然,我需要在着色器中设置蒙皮标志,所以我需要在那里。

我的问题似乎与我迄今为止通过 Google 找到的其他问题不同。我没有从另一个网格重用我的几何图形。我也在构建一个 SkinnedMesh,而不是任何旧网格。我的设置可以支持 1024 个制服。我很困惑。任何帮助将不胜感激。

【问题讨论】:

    标签: three.js glsl


    【解决方案1】:

    当然,这一定很愚蠢,例如 ThreeJS WebGLProgram 将我的着色器文件中的 MAX_BONES 宏设置为 1024,而我在着色器中使用该值来初始化这个统一:uniform mat4 boneMatrices[MAX_BONES],而我的系统最多只支持 1024 个制服。

    现在的问题是为什么THREE.WebGLProgramsallocateBones 函数会这样做:

    function allocateBones( object ) {
    
            if ( capabilities.floatVertexTextures && object && object.skeleton && object.skeleton.useVertexTexture ) {
    
                return 1024;
    
            } else {
    
                // default for when object is not specified
                // ( for example when prebuilding shader to be used with multiple objects )
                //
                //  - leave some extra space for other uniforms
                //  - limit here is ANGLE's 254 max uniform vectors
                //    (up to 54 should be safe)
    
                var nVertexUniforms = capabilities.maxVertexUniforms;
                var nVertexMatrices = Math.floor( ( nVertexUniforms - 20 ) / 4 );
    
                var maxBones = nVertexMatrices;
    
                if ( object !== undefined && (object && object.isSkinnedMesh) ) {
    
                    maxBones = Math.min( object.skeleton.bones.length, maxBones );
    
                    if ( maxBones < object.skeleton.bones.length ) {
    
                        console.warn( 'WebGLRenderer: too many bones - ' + object.skeleton.bones.length + ', this GPU supports just ' + maxBones + ' (try OpenGL instead of ANGLE)' );
    
                    }
    
                }
    
                return maxBones;
    
            }
    
        }
    

    即。为什么满足capabilities.floatVertexTextures &amp;&amp; object &amp;&amp; object.skeleton &amp;&amp; object.skeleton.useVertexTexture 意味着MAX_BONES 自动为1024。但这是另一个问题,我目前并不特别关心这个问题。所以我决定只使用RawShaderMaterial 并手动将我的MAX_BONES 宏设置为适当的值。

    【讨论】:

    • 这听起来像一个错误......如果可以的话,three.js 会为骨骼使用浮点纹理。如果不能,则使用制服。它使用浮点纹理,因为没有足够的制服。在您的情况下,它看起来像有一个错误,因为在您突出显示的代码中,它认为它可以使用浮点纹理,但实际上它并没有真正使用它们,而是分配了太多的制服。
    • 我最近稍微重构了这一切。你介意检查dev 分支,看看这是否仍然是一个问题?
    • 这不再是问题。 (v103)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-03-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-01-02
    • 2012-12-19
    • 1970-01-01
    相关资源
    最近更新 更多