webgl_进入三维世界(1)

激动的心颤抖的手,今天就开始三维空间的学习。
首先我们就从最简单的立方体开始分析吧;
立方体由三角形构成
首先我们要明白三维物体也是由二维图形(特别是三角形)组成的。如图所示,12个三角形组成了一个立方体。
在这里插入图片描述
那么我们可能就想,既然三维物体是由三角形组成的,那只需逐个绘制组成物体的每个三角形,最终就可以绘制出整个三维物体了。但是,三维与二维还有一个显著区别;在绘制二维图形时,只需要考虑顶点的x和y坐标,而绘制三维物体时,还得考虑它们的深度信息(也就是z轴)。其次在三维空间站会有视点和视线的概念。你可以理解成为一个观察者,即﹔在什么地方、朝哪里看、视野有多宽、能看多远。

视点和视线
我们将观察者所处的位置称为视点,从视点出发沿着观察方向的射线称作视线
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
模型矩阵
在这里插入图片描述
模型视图矩阵
如果顶点数量很多,每个顶点都要计算视图矩阵×模型矩阵,这一步操作就会造成不必要的开销。但是无论对哪个顶点而言,式7.1中的两个矩阵相乘的结果都是一样的。所以我们先把这两个矩阵相乘的结果计算出来,再传给顶点着色器。这两个矩阵相乘得到的结果被称为模型视图矩阵:
在这里插入图片描述
可视空间
在这里插入图片描述
代码来直观的体验一下,盒装可视空间

var VSHADER_SOURCE = "" +
 "attribute vec4 a_Position;\n" +//
 "attribute vec4 a_Color;\n" +//
 "uniform mat4 u_ViewModelMatrix ;\n" +
 "varying vec4 v_Color;\n" +//
 "void main(){\n" +
 "   gl_Position = u_ViewModelMatrix * 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("triangle");  
    var nearFar = document.getElementById("nearFar");  
    var gl = getWebGLContext(canvas); 
    if(!gl){
        console.log("你的电脑不支持WebGL!"); 
        return;
    }
    if(!initShaders(gl,VSHADER_SOURCE,FSHADER_SOURCE)){
        console.log("初始化着色器失败!");
        return;
    }
    //设置顶点的相关信息 
    var n = initVertexBuffers(gl);
    if(n < 0){
        console.log("无法获取到点的数据");
        return;
    }
   
    //获取u_ViewMatrix变量的存储地址
    var u_ViewModelMatrix = gl.getUniformLocation(gl.program,'u_ViewModelMatrix');
    //设置视点,视线和上方向
   var viewMatrix = new Matrix4();
   var modelMatrix = new Matrix4();
   viewMatrix.setLookAt(0.2,0.25,0.25,0,0,0,0,1,0);
   modelMatrix.setRotate(-50,0,0,1);
   var viewModelMatrix = new Matrix4();//viewMatrix.multiply(modelMatrix);
   //注册点击事件
   document.onkeydown = function(ev){keydown(ev,gl,n,u_ViewModelMatrix,viewModelMatrix,nearFar)};
   draw(gl,n,u_ViewModelMatrix,viewModelMatrix,nearFar);
   //将视图矩阵传给u_ViewMatrix
//    gl.uniformMatrix4fv(u_ViewModelMatrix,false,viewModelMatrix.elements);
   //绘制三角形
//    gl.drawArrays(gl.TRIANGLES,0,n);
}
var g_near = 0.0,g_far = 0.5;
function keydown(ev,gl,n,u_ViewModelMatrix,viewModelMatrix,nf){
    switch(ev.keyCode){
        case 39 : g_near += 0.01;break;  //右键
        case 37 : g_near -= 0.01;break;  //左键
        case 38 : g_far += 0.01;break;  //上键
        case 40 : g_far -= 0.01;break;  //下键
        default : return; //其他键
    }
    draw(gl,n,u_ViewModelMatrix,viewModelMatrix,nearFar);
}
function draw(gl,n,u_ViewModelMatrix,viewModelMatrix,nf){
    //使用矩阵置换设置可视空间
    viewModelMatrix.setOrtho(-1,1,-1,1,g_near,g_far);
     //将视图矩阵传给u_ViewMatrix
   gl.uniformMatrix4fv(u_ViewModelMatrix,false,viewModelMatrix.elements);
   gl.clear(gl.COLOR_BUFFER_BIT);
   nf.innerHTML = 'near:' + Math.round(g_near *100)/100 + ",far:"+Math.round(g_far*100)/100
   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 n = 9;
    var vertexColorBuffer = gl.createBuffer();
    if(!vertexColorBuffer){
        console.log("无法创建缓冲区");
        return -1;  
    } 
    gl.bindBuffer(gl.ARRAY_BUFFER,vertexColorBuffer); 
    gl.bufferData(gl.ARRAY_BUFFER,verticesColors,gl.STATIC_DRAW);
    var a_Position = gl.getAttribLocation(gl.program,"a_Position");
    if(a_Position < 0){
        console.log("无法获取到存储位置");
        return;
    }
    //获取数组一个值所占的字节数
    var fsize = verticesColors.BYTES_PER_ELEMENT;
    //将顶点坐标的位置赋值
    gl.vertexAttribPointer(a_Position,3,gl.FLOAT,false,fsize*6,0);
    gl.enableVertexAttribArray(a_Position);
    var a_Color = gl.getAttribLocation(gl.program,"a_Color");
    if(a_Color < 0){
        console.log("无法获取到存储位置");
        return;
    }
    //将顶点坐标的位置赋值
    gl.vertexAttribPointer(a_Color,3,gl.FLOAT,false,fsize*6,3*fsize);
    gl.enableVertexAttribArray(a_Color);
    return n;
   } 

在这里插入图片描述
代码体验(细节自己调整):

var VSHADER_SOURCE = "" +

 "attribute vec4 a_Position;\n" +//
 "attribute vec4 a_Color;\n" +//
 "uniform mat4 u_MvpMatrix ;\n" +
 "varying vec4 v_Color;\n" +//
 "void main(){\n" +
 "   gl_Position = u_MvpMatrix * 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 = getWebGLContext(canvas); 
    if(!gl){
        console.log("你的电脑不支持WebGL!"); 
        return;
    }
    if(!initShaders(gl,VSHADER_SOURCE,FSHADER_SOURCE)){
        console.log("初始化着色器失败!");
        return;
    }
    //设置顶点的相关信息 
    var n = initVertexBuffers(gl);
    if(n < 0){
        console.log("无法获取到点的数据");
        return;
    }
     //获取u_ViewMatrix变量的存储地址
     var u_MvpMatrix = gl.getUniformLocation(gl.program, 'u_MvpMatrix');
     //设置视点,视线和上方向
     var modelMatrix = new Matrix4(); //模型
     var viewMatrix = new Matrix4(); //视图
     var projMatrix = new Matrix4();//投影
     var mvpMatrix = new Matrix4(); //模型视图投影
     modelMatrix.setTranslate(0.75,0,0)
     viewMatrix.setLookAt(0, 0, 1, 0, 0, -100, 0, 1, 0);
     projMatrix.setPerspective(100, canvas.width/canvas.height, 1, 100);
     mvpMatrix.set(projMatrix).multiply(viewMatrix).multiply(modelMatrix);
     //将视图矩阵传给u_ViewMatrix
     gl.uniformMatrix4fv(u_MvpMatrix, false, mvpMatrix.elements);
     //绘制三角形
     gl.drawArrays(gl.TRIANGLES,0,n);
}

function initVertexBuffers(gl) {
    var verticesColors = new Float32Array([  
        //右侧
        0.75,1.0,-4.0,0.4,1.0,0.4,   //绿色,后面
        0.25,-1.0,-4.0,0.4,1.0,0.4,
        1.25,-1.0,-4.0,1.0,0.4,0.4,

        0.75,1.0,-2.0,1.0,0.4,0.4,   //黄色,中间
        0.25,-1.0,-2.0,1.0,1.0,0.4,
        1.25,-1.0,-2.0,1.0,1.0,0.4,

        0.75,1.0,0.0,0.4,0.4,1.0,   //蓝色,中间
        0.25,-1.0,0.0,0.4,0.4,1.0,
        1.25,-1.0,0.0,1.0,0.4,0.4,

        //左侧
        -0.75,1.0,-4.0,0.4,1.0,0.4,   //绿色,后面
        -0.25,-1.0,-4.0,0.4,1.0,0.4,
        -1.25,-1.0,-4.0,1.0,0.4,0.4,

        -0.75,1.0,-2.0,1.0,0.4,0.4,   //黄色,中间
        -0.25,-1.0,-2.0,1.0,1.0,0.4,
        -1.25,-1.0,-2.0,1.0,1.0,0.4,

        -0.75,1.0,0.0,0.4,0.4,1.0,   //蓝色,中间
        -0.25,-1.0,0.0,0.4,0.4,1.0,
        -1.25,-1.0,0.0,1.0,0.4,0.4
    ]);
   
    var n = 18;
    var vertexColorBuffer = gl.createBuffer();
    if(!vertexColorBuffer){
        console.log("无法创建缓冲区");
        return -1;  
    } 
    gl.bindBuffer(gl.ARRAY_BUFFER,vertexColorBuffer); 
    gl.bufferData(gl.ARRAY_BUFFER,verticesColors,gl.STATIC_DRAW);
    var a_Position = gl.getAttribLocation(gl.program,"a_Position");
    if(a_Position < 0){
        console.log("无法获取到存储位置");
        return;
    }
    //获取数组一个值所占的字节数
    var fsize = verticesColors.BYTES_PER_ELEMENT;
    //将顶点坐标的位置赋值
    gl.vertexAttribPointer(a_Position,3,gl.FLOAT,false,fsize*6,0);
    gl.enableVertexAttribArray(a_Position);

    var a_Color = gl.getAttribLocation(gl.program,"a_Color");
    if(a_Color < 0){
        console.log("无法获取到存储位置");
        return;
    }
    //将顶点坐标的位置赋值
    gl.vertexAttribPointer(a_Color,3,gl.FLOAT,false,fsize*6,3*fsize);
    gl.enableVertexAttribArray(a_Color);

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值