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

时间:2021-09-24 11:46:21

I'm trying to get this tutorial to work but I ran into two issues, one of which is the following.

我试着让这个教程工作,但是我遇到了两个问题,其中一个是。

When I run the code as is I get an error in the fragment shader saying: THREE.WebGLShader: gl.getShaderInfoLog() ERROR: 0:2: '' : No precision specified for (float). So what I did was specifying a precision for every float/vector I define like so varying highp vec3 vNormal. This eliminates the error but I don't get why? I can't find any other example where precision values are added to variable declarations. Can anybody explain why this occurs? Does it have something to do with my Browser (Chrome 38)?

当我运行代码时,我在片段着色器中得到一个错误:3。WebGLShader: gl.getShaderInfoLog()错误:0:2::没有指定的精度(浮点数)。因此,我所做的是为每一个我定义的浮点/向量指定一个精度,就像如此不同的highp vec3 vNormal。这消除了错误,但我不明白为什么?我找不到任何其他的例子,精确值被添加到变量声明中。有人能解释为什么会这样吗?这和我的浏览器有关系吗(Chrome 38)?

2 个解决方案

#1


5  

Jessy's answer is correct that most fragment shaders set a default precision at the top of the fragment shader code.

Jessy的答案是正确的,大部分的片段着色器在片段着色器代码的顶部设置了一个默认的精度。

However you are using Three.js's RawShaderMaterial which does not prepend any of the built-in uniforms, attributes, and precision declarations. So you have to define it yourself.

但是你用了三个。js的RawShaderMaterial不预置任何内置的制服、属性和精确声明。所以你必须自己定义它。

On the other hand the tutorial you linked to is using Three.js's ShaderMaterial for its material so Three.js will have the precision declaration prepended automatically.

另一方面,您链接到的教程使用了3。js材质的材质有三种。js将会自动进行精确声明。

If you remove the default uniforms/attributes from your shader code and use ShaderMaterial instead it will work without the precision code.

如果您从您的着色代码中移除默认的制服/属性,并使用材质,它将会在没有精确代码的情况下工作。

Vertex Shader

顶点着色器

varying vec3 vNormal;

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

Fragment Shader

片段着色器

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
}

Update to the material

更新的材料

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

Here is a fiddle of your code without the precision declarations.

这里是您的代码的小提琴,没有精确的声明。

#2


11  

There is no default precision in WebGL fragment shaders. (High precision is default for vertex shaders.) The easiest solution is to add

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

precision highp float;

to all of your fragment shaders, which will eliminate the need to define the precision for all floating point vector variables, but generally,

对于所有的片段着色器,它将消除定义所有浮点向量变量的精度的需要,但一般来说,

precision mediump float;

will be preferable, for performance. I do not advise lowp; the good mobile hardware of today doesn't even support it anymore, and does the equivalent of typedeffing lowp to mediump.

将会是更好的表现。我不建议lowp;如今,好的移动硬件甚至不再支持它了,它的作用相当于把lowp的类型定义为mediump。

#1


5  

Jessy's answer is correct that most fragment shaders set a default precision at the top of the fragment shader code.

Jessy的答案是正确的,大部分的片段着色器在片段着色器代码的顶部设置了一个默认的精度。

However you are using Three.js's RawShaderMaterial which does not prepend any of the built-in uniforms, attributes, and precision declarations. So you have to define it yourself.

但是你用了三个。js的RawShaderMaterial不预置任何内置的制服、属性和精确声明。所以你必须自己定义它。

On the other hand the tutorial you linked to is using Three.js's ShaderMaterial for its material so Three.js will have the precision declaration prepended automatically.

另一方面,您链接到的教程使用了3。js材质的材质有三种。js将会自动进行精确声明。

If you remove the default uniforms/attributes from your shader code and use ShaderMaterial instead it will work without the precision code.

如果您从您的着色代码中移除默认的制服/属性,并使用材质,它将会在没有精确代码的情况下工作。

Vertex Shader

顶点着色器

varying vec3 vNormal;

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

Fragment Shader

片段着色器

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
}

Update to the material

更新的材料

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

Here is a fiddle of your code without the precision declarations.

这里是您的代码的小提琴,没有精确的声明。

#2


11  

There is no default precision in WebGL fragment shaders. (High precision is default for vertex shaders.) The easiest solution is to add

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

precision highp float;

to all of your fragment shaders, which will eliminate the need to define the precision for all floating point vector variables, but generally,

对于所有的片段着色器,它将消除定义所有浮点向量变量的精度的需要,但一般来说,

precision mediump float;

will be preferable, for performance. I do not advise lowp; the good mobile hardware of today doesn't even support it anymore, and does the equivalent of typedeffing lowp to mediump.

将会是更好的表现。我不建议lowp;如今,好的移动硬件甚至不再支持它了,它的作用相当于把lowp的类型定义为mediump。