12.三维场景绘制

1.基本概念:

    (1)视点:观察者所处的三维空间中的位置称为视点,视点坐标用(eyeX,eyeY,eyeZ)表示

    (2)视线:从视点出发沿着观察方向的射线称作视线。

    (3)观察目标点:被观察目标所在的点,以此来确定视线。视线穿过观察目标并继续延伸。观察目标点坐标用(atX,atY,atZ)表示

    (4)上方向:最终绘制在屏幕上的影像中的向上的方向,用(upX,upY,upZ)表示。(因为仅确定了视点和观察点,观察者还是可能以视线为轴进行旋转)

    根据上述三个矢量可以创建一个视图矩阵,然后将该矩阵传给顶点着色器,视图矩阵表示了观察者的状态。

    WebGL中默认状态是:视点位于(0,0,0),视线为Z轴负方向,观察点为(0,0,-1),上方向为Y轴正方向(0,1,0)

2.根据视图矩阵绘制看到的场景

    事实上,根据观察者的状态绘制看到的景象,与使用默认观察状态,再对对象进行旋转、平移、缩放变换的效果是等价的。所以只要将视图矩阵与三维对象顶点(a_Position)相乘就可以得到观察者看到的场景

var VSHADER_SOURCE =
'attribute vec4 a_Position;\n' +
'attribute vec4 a_Color;\n' +
'uniform mat4 u_ViewMatrix;\n' +
'varying vec4 v_Color;\n' +
'void main(){\n' +
'gl_Position = u_ViewMatrix * a_Position;\n' +
'v_Color = a_Color;\n' +
'}\n';
var FSHADER_SOURCE =
'precision mediump float;\n' +
'varying vec4 v_Color;\n' +
'void main(){\n' +
'gl_FragColor = v_Color;\n' +
'}\n';


function main()
{
var canvas = document.getElementById('webgl');
var gl = canvas.getContext('webgl');
initShaders(gl,VSHADER_SOURCE,FSHADER_SOURCE);
var n = initVertexBuffers(gl);

var u_ViewMatrix = gl.getUniformLocation(gl.program,'u_ViewMatrix');
//设置视点、视线和上方向
var viewMatrix = new Matrix4();
viewMatrix.setLookAt(0.20,0.25,0.25,0,0,-2,0,1,0);//存储顺序是:视点坐标,观察点坐标,上方向
gl.uniformMatrix4fv(u_ViewMatrix,false,viewMatrix.elements);
gl.drawArrays(gl.TRIANGLES,0,n);


}

function initVertexBuffers(gl)
{
var verticesColors = new Float32Array([
0.0,0.5,-0.4,0.4,1.0,0.4,
-0.5,-0.5,-0.4,0.4,1.0,0.4,
0.5,-0.5,-0.4,1.0,0.4,0.4,

0.5,0.4,-0.2,1.0,0.4,0.4,
-0.5,0.4,-0.2,1.0,1.0,0.4,
0.0,-0.6,-0.2,1.0,1.0,0.4,

0.0,0.5,0.0,0.4,0.4,1.0,
-0.5,-0.5,0.0,0.4,0.4,1.0,
0.5,-0.5,0.0,1.0,0.4,0.4
]);
var FSIZE = verticesColors.BYTES_PER_ELEMENT;
var n = 9;
var a_Position = gl.getAttribLocation(gl.program,'a_Position');
var a_Color = gl.getAttribLocation(gl.program,'a_Color');
var vertexColorBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER,vertexColorBuffer);
gl.bufferData(gl.ARRAY_BUFFER,verticesColors,gl.STATIC_DRAW);
gl.vertexAttribPointer(a_Position,3,gl.FLOAT,false,FSIZE*6,0);
gl.enableVertexAttribArray(a_Position);

gl.vertexAttribPointer(a_Color,3,gl.FLOAT,false,FSIZE*6,FSIZE*3);
gl.enableVertexAttribArray(a_Color);
return n;
}

API:Matrix4.setLookAt(eyeX,eyeY,eyeZ,atX,atY,atZ,upX,upY,upZ)

        eyeX,eyeY,eyeZ:指定视点

        atX,atY,atZ:指定观察点

        upX,upY,upZ:指定上方向

3.模型矩阵

    <变换后顶点坐标>=<变换矩阵>*<原始顶点坐标>

    <从视点看去的顶点坐标> = <视图矩阵>*<变换后顶点坐标>=<视图矩阵>*<变换矩阵>*<原始顶点坐标>=<模型视图矩阵>*<原始顶点坐标>

    此时的变换矩阵称为模型矩阵,可以是平移、缩放、旋转矩阵的任意组合。然而在着色器中运算矩阵相乘开销较大,我们可以将视图矩阵和模型矩阵相乘的过程放在js中,使用Matrix4.multiply()方法

var VSHADER_SOURCE =
'attribute vec4 a_Position;\n' +
'attribute vec4 a_Color;\n' +
'uniform mat4 u_ModelViewMatrix;\n' +
'varying vec4 v_Color;\n' +
'void main(){\n' +
'gl_Position = u_ModelViewMatrix * a_Position;\n' +
'v_Color = a_Color;\n' +
'}\n';
var FSHADER_SOURCE =
'precision mediump float;\n' +
'varying vec4 v_Color;\n' +
'void main(){\n' +
'gl_FragColor = v_Color;\n' +
'}\n';


function main()
{
var canvas = document.getElementById('webgl');
var gl = canvas.getContext('webgl');
initShaders(gl,VSHADER_SOURCE,FSHADER_SOURCE);
var n = initVertexBuffers(gl);

var u_ModelViewMatrix = gl.getUniformLocation(gl.program,'u_ModelViewMatrix');
//设置视点、视线和上方向
var viewMatrix = new Matrix4();
viewMatrix.setLookAt(0.20,0.25,0.25,0,0,0,0,1,0);//存储顺序是:视点坐标,观察点坐标,上方向

var modelMatrix = new Matrix4();
modelMatrix.setRotate(-10,0,0,1);

var modelViewMatrix = viewMatrix.multiply(modelMatrix);

gl.uniformMatrix4fv(u_ModelViewMatrix,false,modelViewMatrix.elements);
gl.drawArrays(gl.TRIANGLES,0,n);


}

function initVertexBuffers(gl)
{
var verticesColors = new Float32Array([
0.0,0.5,-0.4,0.4,1.0,0.4,
-0.5,-0.5,-0.4,0.4,1.0,0.4,
0.5,-0.5,-0.4,1.0,0.4,0.4,

0.5,0.4,-0.2,1.0,0.4,0.4,
-0.5,0.4,-0.2,1.0,1.0,0.4,
0.0,-0.6,-0.2,1.0,1.0,0.4,

0.0,0.5,0.0,0.4,0.4,1.0,
-0.5,-0.5,0.0,0.4,0.4,1.0,
0.5,-0.5,0.0,1.0,0.4,0.4
]);
var FSIZE = verticesColors.BYTES_PER_ELEMENT;
var n = 9;
var a_Position = gl.getAttribLocation(gl.program,'a_Position');
var a_Color = gl.getAttribLocation(gl.program,'a_Color');
var vertexColorBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER,vertexColorBuffer);
gl.bufferData(gl.ARRAY_BUFFER,verticesColors,gl.STATIC_DRAW);
gl.vertexAttribPointer(a_Position,3,gl.FLOAT,false,FSIZE*6,0);
gl.enableVertexAttribArray(a_Position);

gl.vertexAttribPointer(a_Color,3,gl.FLOAT,false,FSIZE*6,FSIZE*3);
gl.enableVertexAttribArray(a_Color);
return n;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值