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

3

我正在使用WebGL尝试渲染一个既有颜色又有纹理的场景,颜色是通过顶点着色器渲染,纹理是通过片元着色器渲染。两个着色器都使用了一些相同的全局变量,然而WebGL不允许我在两者之间传递它们,只能选择其中一个。我收到的错误信息是“无法链接附加着色器之间的全局变量”。我已经查看了其他用户发布的相关帖子,但没有找到符合我的情况的解决方案。以下是我的代码:

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。我该如何做到这一点?
1个回答

4
链接错误是由顶点着色器和片段着色器中不同的精度引起的。请参见“4.5 精度和精度限定符”(链接)和“OpenGL ES Shading Language 1.00规范-4.5.3 默认精度限定符”(链接)。

The vertex language has the following predeclared globally scoped default precision statements:

precision highp float;

片元着色器对于float没有默认精度,因此你需要指定默认精度为mediump

precision mediump float;

因此,片元着色器和顶点着色器中的浮点统一变量精度不同。可以在顶点着色器中为浮点数设置明确的 mediump 精度:
const vertex_shader = `
precision mediump float;
...

或者将片段着色器中的精度从medium更改为high

另外,您还可以在顶点着色器和片段着色器中使用显式精度限定符来设置用于统一变量的精度。例如:

uniform mediump vec4 light_position;

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接