我使用webgl创建了5个3D模型,并将它们放在同一张画布上。这三个模型中有两个面对用户,但是其余的都背向我。我已经使用照明来照亮模型。
我希望没有面对我的三个模型面对我,但是我似乎无法使其正常工作。我尝试使用矩阵变换将它们旋转180度,但是当它们面对我时它们是黑色的(因为它们没有点亮)。有什么办法可以解决这个问题,或者有可以使用的翻转方法吗?
我的顶点着色器如下:
<script id="vertex-shader" type="x-shader/x-vertex">
attribute vec4 vPosition;
attribute vec3 vNormal;
attribute vec4 vColor;
varying vec4 fColor;
uniform vec4 ambientProduct, diffuseProduct, specularProduct;
uniform mat4 modelViewMatrix;
uniform mat4 projectionMatrix;
uniform vec4 lightPosition;
uniform float shininess;
uniform vec3 theta;
uniform vec3 delta;
uniform vec3 omega;
void main()
{
vec3 angles = radians( theta );
vec3 c = cos( angles );
vec3 s = sin( angles );
mat4 tr = mat4( 1.0, 0.0, 0.0, delta[0],
0.0, 1.0, 0.0, delta[1],
0.0, 0.0, 1.0, delta[2],
0.0, 0.0, 0.0, 1.0 );
mat4 sc = mat4( omega[0], 0.0, 0.0, 0.0,
0.0, omega[1], 0.0, 0.0,
0.0, 0.0, omega[2], 0.0,
0.0, 0.0, 0.0, 1.0 );
mat4 rx = mat4( 1.0, 0.0, 0.0, 0.0,
0.0, c.x, s.x, 0.0,
0.0, -s.x, c.x, 0.0,
0.0, 0.0, 0.0, 1.0 );
mat4 ry = mat4( c.y, 0.0, -s.y, 0.0,
0.0, 1.0, 0.0, 0.0,
s.y, 0.0, c.y, 0.0,
0.0, 0.0, 0.0, 1.0 );
mat4 rz = mat4( c.z, -s.z, 0.0, 0.0,
s.z, c.z, 0.0, 0.0,
0.0, 0.0, 1.0, 0.0,
0.0, 0.0, 0.0, 1.0 );
vec3 pos = -(modelViewMatrix * vPosition).xyz;
vec3 light = lightPosition.xyz;
vec3 L = normalize( light - pos );
vec3 E = normalize( -pos );
vec3 H = normalize( L + E );
vec4 NN = vec4(vNormal,0);
vec3 N = normalize( (modelViewMatrix*NN).xyz);
vec4 ambient = ambientProduct;
float Kd = max( dot(L, N), 0.0 );
vec4 diffuse = Kd*diffuseProduct*vColor;
float Ks = pow( max(dot(N, H), 0.0), shininess );
vec4 specular = Ks * specularProduct;
if( dot(L, N) < 0.0 ) {
specular = vec4(0.0, 0.0, 0.0, 1.0);
}
gl_Position = projectionMatrix * modelViewMatrix * sc * rz * ry * rx *vPosition* tr ;
fColor = ambient + diffuse+specular;
fColor.a = 1.0;
}
</script>
我的主要js文件:
var canvas;
var gl;
var lightPosition = vec4(1.0, 3.0, 10.0, 1.0);
var lightAmbient = vec4(0.2, 0.2, 0.2, 1.0);
var lightDiffuse = vec4(1.0, 1.0, 1.0, 1.0);
var lightSpecular = vec4(1.0, 1.0, 1.0, 1.0);
var materialAmbient = vec4(0.0, 0.0, 0.0, 1);
var materialDiffuse = vec4(0.0, 0.0, 0.0, 1);
var materialSpecular = vec4(0.0, 0.0, 0.0, 1);
var materialShininess = 100.0;
var ctm;
var ambientColor, diffuseColor, specularColor;
var modelView, projection;
var viewerPos;
var program;
var theta = 1;
var thetaLoc;
var omega = [ 0, 0, 0 ];
var omegaLoc;
var modelX = 0.2;
var modelY = -0.856;
var modelZ = 0.0;
var delta = [ 0, 0, 0 ];
var deltaLoc;
window.onload = function init()
{
canvas = document.getElementById("gl-canvas");
gl = WebGLUtils.setupWebGL(canvas);
if (!gl) {
alert("WebGL isn't available");
}
gl.viewport(0, 0, canvas.width, canvas.height);
gl.clearColor(1.0, 1.0, 1.0, 1.0);
gl.enable(gl.DEPTH_TEST);
gl.clear( gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
program = initShaders(gl, "vertex-shader", "fragment-shader");
gl.useProgram(program);
scale(0.075,0.075,0.075);
translate(modelX, modelY, modelZ);
rotate(0,180,0);
color();
render(i,b,bc,n);
requestAnimFrame(init);
};
function render(index,vertex,color,normal){
var iBuffer = gl.createBuffer();
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, iBuffer);
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(index), gl.STATIC_DRAW);
var nBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, nBuffer);
gl.bufferData(gl.ARRAY_BUFFER, flatten(normal), gl.STATIC_DRAW);
var vNormal = gl.getAttribLocation(program, "vNormal");
gl.vertexAttribPointer(vNormal, 3, gl.FLOAT, false, 0, 0);
gl.enableVertexAttribArray(vNormal);
var vBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, vBuffer);
gl.bufferData(gl.ARRAY_BUFFER, flatten(vertex), gl.STATIC_DRAW);
var vPosition = gl.getAttribLocation(program, "vPosition");
gl.vertexAttribPointer(vPosition, 4, gl.FLOAT, false, 0, 0);
gl.enableVertexAttribArray(vPosition);
var cBuffer = gl.createBuffer();
gl.bindBuffer( gl.ARRAY_BUFFER, cBuffer );
gl.bufferData( gl.ARRAY_BUFFER, flatten(color), gl.STATIC_DRAW );
var vColor = gl.getAttribLocation( program, "vColor" );
gl.vertexAttribPointer( vColor, 4, gl.FLOAT, false, 0, 0 );
gl.enableVertexAttribArray( vColor );
var numVertices= index.length;
viewerPos = vec3(0.0, 0.0, -20.0);
projection = ortho(-1, 1, -1, 1, -100, 100);
ambientProduct = vec4(0.0,0.0,0.0,0.0);
diffuseProduct = vec4(1.0,1.0,1.0,1.0);
specularProduct = vec4(1.0,1.0,1.0,1.0);
gl.uniform4fv(gl.getUniformLocation(program, "ambientProduct"),
flatten(ambientProduct));
gl.uniform4fv(gl.getUniformLocation(program, "diffuseProduct"),
flatten(diffuseProduct));
gl.uniform4fv(gl.getUniformLocation(program, "specularProduct"),
flatten(specularProduct));
gl.uniform4fv(gl.getUniformLocation(program, "lightPosition"),
flatten(lightPosition));
gl.uniform1f(gl.getUniformLocation(program,
"shininess"), materialShininess);
gl.uniformMatrix4fv(gl.getUniformLocation(program, "projectionMatrix"),
false, flatten(projection));
modelView = mat4();
gl.uniformMatrix4fv(gl.getUniformLocation(program,
"modelViewMatrix"), false, flatten(modelView));
gl.drawArrays(gl.TRIANGLES, 0, numVertices);
}
function scale(a,b,c){
omega=vec3(a,b,c);
omegaLoc = gl.getUniformLocation(program, "omega");
gl.uniform3fv(omegaLoc, omega);
};
function translate(d,e,f){
delta=vec3(d,e,f);
deltaLoc = gl.getUniformLocation(program, "delta");
gl.uniform3fv(deltaLoc, delta);
};
function rotate(g,h,i){
theta=vec3(g,h,i);
thetaLoc = gl.getUniformLocation(program, "theta");
gl.uniform3fv(thetaLoc, theta);
};
我模型的js文件(其中一个不面向我)
var b = [];
var n = [];
//VERTICES
var v = [
...
vec4(-1.75, 10.8, -1.2,1.0), //0
vec4(-1.75, 11.2, -1.2,1.0), //1
vec4(-1.25, 11.2, -1.2,1.0), //2
vec4(-1.25, 10.8, -1.2,1.0), //3
vec4(-1.75, 10.8, -1.4,1.0), //4
vec4(-1.75, 11.2, -1.4,1.0), //5
vec4(-1.25, 11.2, -1.4,1.0), //6
vec4(-1.25, 10.8, -1.4,1.0), //7
];
//VERTEX COLORS
var c = [
...
vec4( 0.73, 0.60, 0.50, 1.0 ), // black 0
vec4( 0.73, 0.60, 0.50, 1.0 ), // red 1
vec4( 0.73, 0.60, 0.50, 1.0 ), // yellow 2
vec4( 0.73, 0.60, 0.50, 1.0 ), // green 3
vec4( 0.73, 0.60, 0.50, 1.0 ), // blue 4
vec4( 0.73, 0.60, 0.50, 1.0 ), // magenta 5
vec4( 0.73, 0.60, 0.50, 1.0 ), // white 6
vec4( 0.73, 0.60, 0.50, 1.0 ), // cyan 7
];
var bc=new Array();
for(var j=0;j<c.length;j++)
{
for(var i=0;i<36;i++)
{
bc.push(c[j]);
}
j+=7;
}
//INDICES
var i=[
1, 0, 3,
3, 2, 1,
2, 3, 7,
7, 6, 2,
3, 0, 4,
4, 7, 3,
6, 5, 1,
1, 2, 6,
4, 5, 6,
6, 7, 4,
5, 4, 0,
0, 1, 5,
...
577, 576, 579,
579, 578, 577,
578, 579, 583,
583, 582, 578,
579, 576, 580,
580, 583, 579,
582, 581, 577,
577, 578, 582,
580, 581, 582,
582, 583, 580,
581, 580, 576,
576, 577, 581,
];
function quadrants(a, b, c, d) {
var t1 = subtract(v[b], v[a]);
var t2 = subtract(v[c], v[b]);
var normal = cross(t1, t2);
var normal = vec3(normal);
b.push(v[a]);
n.push(normal);
b.push(v[b]);
n.push(normal);
b.push(v[c]);
n.push(normal);
b.push(v[a]);
n.push(normal);
b.push(v[c]);
n.push(normal);
b.push(v[d]);
n.push(normal);
}
function color() {
quadrants(1, 0, 3, 2);
quadrants(2, 3, 7, 6);
quadrants(3, 0, 4, 7);
quadrants(6, 5, 1, 2);
quadrants(4, 5, 6, 7);
quadrants(5, 4, 0, 1);
...
quadrants(577, 576, 579, 578);
quadrants(578, 579, 583, 582);
quadrants(579, 576, 580, 583);
quadrants(582, 581, 577, 578);
quadrants(580, 581, 582, 583);
quadrants(581, 580, 576, 577);
}
问题是这些行和/或与其相关的JS代码
vec3 pos = -(modelViewMatrix * vPosition).xyz;
vec3 light = lightPosition.xyz;
vec3 L = normalize( light - pos );
查看代码pos
是相对于视图的,它在视图空间中,但是light
在世界空间中。您可以通过使用“模型矩阵”而不是“模型视图矩阵”来计算pos
来修复它,以便在世界空间中以pos
的方式进行计算。或者,您可以通过设置lightPosition
来修复它,使其位于JavaScript的视图空间中。
由于JavaScipt代码未执行任何矩阵数学运算,因此很难告诉您确切要更改的内容。在着色器中执行大量矩阵数学运算并不常见。我在您的着色器中看到有tr
,sc
,rx
,ry
,rz
。那行得通,但这并不常见。
更为常见的方法是进行矩阵数学运算,以至少使用场景图来计算JavaScript中的至少世界矩阵(模型矩阵)。这意味着您不必编写新的着色器即可更改矩阵的乘法方式。参见this和this,也许还有this