【问题标题】:Using the same uniform variable between two shaders in WebGL在 WebGL 中的两个着色器之间使用相同的统一变量
【发布时间】:2020-08-18 14:32:33
【问题描述】:

我正在使用 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。我该怎么做呢?

【问题讨论】:

    标签: javascript glsl shader webgl textures


    【解决方案1】:

    链接错误是由于顶点着色器和片段着色器的精度不同造成的。见4.5 Precision and Precision Qualifiers

    来自OpenGL ES Shading Language 1.00 Specification - 4.5.3 Default Precision Qualifiers

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

    precision highp float;
    

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

    precision mediump float;
    

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

    在顶点着色器中为floats 设置显式mediump 精度:

    const vertex_shader = `
    precision mediump float;
    ...
    

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

    或者,您可以为顶点着色器和片段着色器中使用的统一变量设置显式精度限定符。例如:

    uniform mediump vec4 light_position;
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-05-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多