我正在使用 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. 我应该怎么做呢?
先谢谢您。
链接错误是由顶点着色器和片段着色器的精度不同引起的。请看 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;
...
或者改变片段着色器的精度,从... medium
到 high
.
另外,你也可以为顶点着色器和片段着色器中使用的统一变量设置一个explicite精度限定符。例如
uniform mediump vec4 light_position;