为什么我需要在webgl着色器中定义精度值?

时间:2014-11-21 09:29:31

标签: three.js glsl webgl shader fragment-shader

我正试图让this tutorial工作,但我遇到了两个问题,其中一个是以下问题。

当我按原样运行代码时,我在片段着色器中收到一条错误:THREE.WebGLShader: gl.getShaderInfoLog() ERROR: 0:2: '' : No precision specified for (float)。所以我所做的是为我定义的每个浮点/向量指定精度,如varying highp vec3 vNormal。这消除了错误,但我不明白为什么?我找不到任何其他将精度值添加到变量声明的示例。任何人都能解释为什么会这样吗?它与我的浏览器(Chrome 38)有关吗?

2 个答案:

答案 0 :(得分:15)

WebGL片段着色器中没有默认精度。 (顶点着色器默认为高精度。)最简单的解决方案是添加

precision highp float;

到所有片段着色器,这将消除为所有浮点矢量变量定义精度的需要,但通常,

precision mediump float;
为了表现,

会更好。我不建议低音;今天优秀的移动硬件甚至不再支持它,并且相当于类型降低lowp到mediump。

答案 1 :(得分:7)

Jessy的回答是正确的,大多数片段着色器在片段着色器代码的顶部设置了默认精度。

但是你使用的是Three.js RawShaderMaterial,它不会添加任何内置的制服,属性和精确声明。所以你必须自己定义它。

另一方面,您链接的教程使用Three.js的ShaderMaterial作为其材质,因此Three.js将自动预先附加精确声明。

如果从着色器代码中删除默认的制服/属性并使用ShaderMaterial,则它将在没有精确代码的情况下工作。

顶点着色器

varying vec3 vNormal;

void main() {
    vNormal = normal;
    gl_Position = projectionMatrix *
                modelViewMatrix *
                vec4(position,1.0);
}

片段着色器

varying vec3 vNormal;

void main() {
    vec3 light = vec3(0.5, 0.2, 1.0);

    // ensure it's normalized
    light = normalize(light);

    // calculate the dot product of
    // the light to the vertex normal
    float dProd = max(0.0, dot(vNormal, light));

    // feed into our frag colour
    gl_FragColor = vec4(dProd, // R
                        dProd, // G
                        dProd, // B
                        1.0);  // A
}

更新资料

// create the sphere's material
var shaderMaterial = new THREE.ShaderMaterial({
    vertexShader:   document.getElementById('vertex-shader').innerHTML,
    fragmentShader: document.getElementById('fragment-shader').innerHTML
});

Here是没有精确声明的代码的缩写。