在WebGL中的两个着色器之间使用相同的统一变量。

问题描述 投票:0回答:1

我正在使用 WebGL 尝试渲染一个具有颜色和纹理的场景,颜色通过顶点着色器渲染,纹理通过片段着色器渲染。两个着色器都使用了一些相同的统一变量,但 WebGL 不允许我在两者之间传递这些变量,只能传递一个或另一个。我收到的错误信息是 "Uniform变量无法在所附着色器之间链接"。我翻阅了其他用户关于这个问题的类似帖子,然而我无法找到符合我情况的帖子。我的代码如下。

const vertex_shader = `

attribute vec4 vertex;
attribute vec2 textureCoordinates;
attribute vec4 normal;

uniform mat4 model_transform;
uniform mat4 vp_transform;
uniform mat4 normal_transform;

varying vec2 vTexCoords;
varying vec4 obj_loc;
varying vec4 transformed_normal;
varying vec4 vColor;
uniform vec4 light_position;
uniform vec4 light_ambient;
uniform vec4 light_diffuse;

uniform vec4 mat_ambient;
uniform vec4 mat_diffuse;
uniform vec4 mat_specular;
uniform float mat_shininess;

uniform vec4 light_specular;

uniform vec4 camera_position;

uniform int flags;

void main()
{
    obj_loc = model_transform * vertex; // vertex in model coordinates
    gl_Position = vp_transform * obj_loc; // vertex in device independent coordinates
    transformed_normal = normal_transform * normal;  // normal in model coordinates
    vTexCoords = textureCoordinates;

    vec4 l_vec = normalize(light_position - obj_loc);
    vec4 n_vec = normalize(normal_transform * normal);
    float lndot = dot(l_vec, n_vec);
    float diffuse_scale = max(0.0, lndot);
    vec4 diffuse_color = diffuse_scale * light_diffuse * mat_diffuse;
    if( (flags - 2*(flags/2)) == 0)
        diffuse_color = vec4(0.0, 0.0, 0.0, 1.0);

    vec4 h_vec = normalize(l_vec + normalize(camera_position - obj_loc));
    float spec_scale = pow(max(0.0, dot(h_vec, n_vec)), mat_shininess);
    vec4 specular_color;
    if(lndot < 0.0) {
        specular_color = vec4(0.0, 0.0, 0.0, 1.0);
    } else {
        specular_color = spec_scale * mat_specular * light_specular;
    }
    if( (flags - 4*(flags/4)) < 2 ) {
        specular_color = vec4(0.0, 0.0, 0.0, 1.0);
    }      

    vec4 ambient_color = mat_ambient * light_ambient; 
    if(flags < 4) {
        ambient_color = vec4(0.0, 0.0, 0.0, 1.0);
    }
}`;

const fragment_shader = `
precision mediump float;

uniform vec4 light_position;
uniform vec4 light_ambient;
uniform vec4 light_diffuse;

varying vec2 vTexCoords;
varying vec4 obj_loc;
varying vec4 transformed_normal;
uniform sampler2D sampler;

void
main()
{
    vec4 texture_sample = texture2D(sampler, vTexCoords);

    vec4 l_vec = normalize(light_position - obj_loc);
    vec4 n_vec = normalize(transformed_normal);
    float lndot = dot(l_vec, n_vec);
    float diffuse_scale = max(0.0, lndot);
    vec4 diffuse_color = diffuse_scale * light_diffuse * texture_sample;

    vec4 ambient_color = light_ambient * texture_sample;


    gl_FragColor = diffuse_color + ambient_color;
    gl_FragColor.a = 1.0;
}
`;

我想在两个着色器之间使用的变量是 light_position, light_ambient, 和 light_diffuse. 我应该怎么做呢?

先谢谢您。

javascript shader webgl textures
1个回答
2
投票

链接错误是由顶点着色器和片段着色器的精度不同引起的。请看 4.5 精度与精度限定

来自 OpenGL ES Shading Language 1.00 规范 - 4.5.3 默认精度限定符

顶点语言有以下预先声明的全局范围默认精度语句。

precision highp float;

片段着色器没有默认精度,用于 float因此,您指定了默认的精度 mediump:

precision mediump float;

因此在片段着色器和顶点着色器中,浮点统一的精度是不同的。

要么设置一个显式的 mediump 精度 float或改变顶点着色器中的精度。

const vertex_shader = `
precision mediump float;
...

或者改变片段着色器的精度,从... mediumhigh.

另外,你也可以为顶点着色器和片段着色器中使用的统一变量设置一个explicite精度限定符。例如

uniform mediump vec4 light_position;
© www.soinside.com 2019 - 2024. All rights reserved.