<html lang="zh-CN">

<!--服务器运行地址:http://127.0.0.1:8080/webgl/LearnNeHeWebGL/NeHeWebGL4.html-->
<head>
<title>NeHe's WebGL</title>
<meta charset="UTF-8"/>
<!--引入需要的库文件-->
<script type="text/javascript" src="Oak3D_v_0_5.js"></script> <!--片元着色器;为JavaScript片段指定一个ID编号,后面我可以更具这个ID编号来获取这段片元着色器的JavaScript片段代码-->
<script id="shader-fs" type="x-shader/x-fragment">
precision mediump float; varying vec4 vColor;
void main(void) {
gl_FragColor = vColor;
}
</script> <!--顶点着色器;后面可以通过ID编号来获取这段顶点着色器代码-->
<script id="shader-vs" type="x-shader/x-vertex">
attribute vec3 aVertexPosition;
attribute vec4 aVertexColor; uniform mat4 uMVMatrix;
uniform mat4 uPMatrix; varying vec4 vColor;
void main(void) {
gl_Position = uPMatrix * uMVMatrix * vec4(aVertexPosition, 1.0);
vColor = aVertexColor;
}
</script> <script type="text/javascript"> var gl;
//初始化WEBGL
function initGL(canvas) {
try {
//获取WEBGL上下文
gl = canvas.getContext("experimental-webgl");
//gl这个上下文中存放了一些属性(canvas的宽度、长度和其他相关属性数据)
//设置我的视口的宽度和高度
gl.viewportWidth = canvas.width;
gl.viewportHeight = canvas.height;
} catch (e) {
}
//如果获取失败
if (!gl) {
alert("Could not initialise WebGL, sorry :-(");
}
} //获取我的着色器对象
function getShader(gl, id) {
//根据id获取着色器源程序代码
var shaderScript = document.getElementById(id);
if (!shaderScript) {
return null;
} var str = "";
var k = shaderScript.firstChild;
while (k) {
if (k.nodeType == 3) {
str += k.textContent;
}
k = k.nextSibling;
} var shader;
//1.根据着色器的类型创建相应的着色器对象
if (shaderScript.type == "x-shader/x-fragment") {
shader = gl.createShader(gl.FRAGMENT_SHADER);
} else if (shaderScript.type == "x-shader/x-vertex") {
shader = gl.createShader(gl.VERTEX_SHADER);
} else {
return null;
} //2.向着色器对象中指定相应的GLSL ES源代码(以字符串的形式传递进去)
gl.shaderSource(shader, str);
//3.开始编译着色器(编译成为二进制的可执行文件)
gl.compileShader(shader); //检查下着色器的状态(是否编译成功)
if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
alert(gl.getShaderInfoLog(shader));
return null;
} return shader;
} //一个着色器对象必须包含一个顶点着色器和一个片元着色器
var shaderProgram; //初始化着色器
function initShaders() {
//获取我的顶点着色器和片元着色器
var fragmentShader = getShader(gl, "shader-fs");
var vertexShader = getShader(gl, "shader-vs"); //每一个program中可以存放一个顶点着色器和一个片元着色器
//4.创建我的程序对象
shaderProgram = gl.createProgram();
//5.为程序对象分配着色器对象
gl.attachShader(shaderProgram, vertexShader);
gl.attachShader(shaderProgram, fragmentShader); //6.链接程序对象
/**
* 1.可以保证顶点着色器和片元着色器同名并且是同类型的
* 2.attribute,uniform和varying变量个数不超过着色器的上限
*/
gl.linkProgram(shaderProgram);
//检测是否连接成功
if (!gl.getProgramParameter(shaderProgram, gl.LINK_STATUS)) {
alert("Could not initialise shaders");
}
//7.告诉WEBGL要使用的程序对象
gl.useProgram(shaderProgram); //指定一个新的属性;gl.enableVertexAttribArray,我们使用它来告诉WebGL我们会用一个数组来为属性赋值
//顶点的位置信息
shaderProgram.vertexPositionAttribute = gl.getAttribLocation(shaderProgram, "aVertexPosition");
gl.enableVertexAttribArray(shaderProgram.vertexPositionAttribute); //获取我的顶点着色器中的attribute颜色变量
shaderProgram.textureCoordAttribute = gl.getAttribLocation(shaderProgram, "aVertexColor");
gl.enableVertexAttribArray(shaderProgram.textureCoordAttribute); //从program中取得另外的两个属性值(模型视图投影矩阵)
shaderProgram.pMatrixUniform = gl.getUniformLocation(shaderProgram, "uPMatrix");
shaderProgram.mvMatrixUniform = gl.getUniformLocation(shaderProgram, "uMVMatrix");
} //定义了我的模型视图矩阵和投影矩阵
var mvMatrix;
var pMatrix; //在这里实现我的矩阵的进栈和出栈操作
var mvMatrixStack = [];
function myPushMatrix() {
var copy = new okMat4();
mvMatrix.clone(copy);
mvMatrixStack.push(copy);
} function myPopMatrix() {
if (mvMatrixStack.length == 0) {
throw "Invalid popMatrix!";
}
mvMatrix = mvMatrixStack.pop();
} //把我们新设置的模型视图投影矩阵传给顶点着色器中的uniform变量
function setMatrixUniforms() {
gl.uniformMatrix4fv(shaderProgram.pMatrixUniform, false, pMatrix.toArray());
gl.uniformMatrix4fv(shaderProgram.mvMatrixUniform, false, mvMatrix.toArray());
} //定义我的三角形和矩形缓冲区顶点位置
var pyramidVertexPositionBuffer;
var cubeVertexPositionBuffer;
//定义我的三角形和矩形缓冲区的顶点颜色
var pyramidVertexColorBuffer;
var cubeVertexColorBuffer;
//定义我的立方体索引下标
var cubeVertexIndexBuffer; //缓冲区的初始化
function initBuffers() {
//1.新建三角形顶点缓冲区对象
pyramidVertexPositionBuffer = gl.createBuffer();
//2.绑定目标对象到缓冲区
gl.bindBuffer(gl.ARRAY_BUFFER, pyramidVertexPositionBuffer);
//初始化我的顶点数组
var vertices = [
// Front face
0.0, 1.0, 0.0,
-1.0, -1.0, 1.0,
1.0, -1.0, 1.0, // Right face
0.0, 1.0, 0.0,
1.0, -1.0, 1.0,
1.0, -1.0, -1.0, // Back face
0.0, 1.0, 0.0,
1.0, -1.0, -1.0,
-1.0, -1.0, -1.0, // Left face
0.0, 1.0, 0.0,
-1.0, -1.0, -1.0,
-1.0, -1.0, 1.0
];
//3.缓冲区对象中写入数据
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW); //计算顶点数组的大小和顶点个数
pyramidVertexPositionBuffer.itemSize = 3;
pyramidVertexPositionBuffer.numItems = 12; //1.创建我的颜色缓冲区
pyramidVertexColorBuffer = gl.createBuffer();
//2.绑定我的颜色缓冲区到目标对象
gl.bindBuffer(gl.ARRAY_BUFFER, pyramidVertexColorBuffer);
//初始化我的颜色数组(对每一个顶点指定相应的颜色)
var colors = [
//注意保证在同一个顶点上面的颜色要相同
// Front face
1.0, 0.0, 0.0, 1.0,
0.0, 1.0, 0.0, 1.0,
0.0, 0.0, 1.0, 1.0, // Right face
1.0, 0.0, 0.0, 1.0,
0.0, 0.0, 1.0, 1.0,
0.0, 1.0, 0.0, 1.0, // Back face
1.0, 0.0, 0.0, 1.0,
0.0, 1.0, 0.0, 1.0,
0.0, 0.0, 1.0, 1.0, // Left face
1.0, 0.0, 0.0, 1.0,
0.0, 0.0, 1.0, 1.0,
0.0, 1.0, 0.0, 1.0
];
//3.向缓冲区对象中写入数据
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(colors), gl.STATIC_DRAW);
//计算三角形顶点颜色数组的大小和顶点个数
pyramidVertexColorBuffer.itemSize = 4;
pyramidVertexColorBuffer.numItems = 12; //1.新建矩形顶点缓冲区对象
cubeVertexPositionBuffer = gl.createBuffer();
//2.绑定目标对象到缓冲区
gl.bindBuffer(gl.ARRAY_BUFFER, cubeVertexPositionBuffer);
//立方体的顶点位置数组
vertices = [
// Front face(123第一个三角形, 134第二个三角形)
-1.0, -1.0, 1.0,
1.0, -1.0, 1.0,
1.0, 1.0, 1.0,
-1.0, 1.0, 1.0, // Back face
-1.0, -1.0, -1.0,
-1.0, 1.0, -1.0,
1.0, 1.0, -1.0,
1.0, -1.0, -1.0, // Top face
-1.0, 1.0, -1.0,
-1.0, 1.0, 1.0,
1.0, 1.0, 1.0,
1.0, 1.0, -1.0, // Bottom face
-1.0, -1.0, -1.0,
1.0, -1.0, -1.0,
1.0, -1.0, 1.0,
-1.0, -1.0, 1.0, // Right face
1.0, -1.0, -1.0,
1.0, 1.0, -1.0,
1.0, 1.0, 1.0,
1.0, -1.0, 1.0, // Left face
-1.0, -1.0, -1.0,
-1.0, -1.0, 1.0,
-1.0, 1.0, 1.0,
-1.0, 1.0, -1.0
];
//3.向缓冲区对象中写入数据
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW);
//计算矩形顶点数组每一项数据的大小,和顶点个数(有四个不同的顶点位置,每个顶点由3个数字组成)
cubeVertexPositionBuffer.itemSize = 3;
cubeVertexPositionBuffer.numItems = 24; //1.创建我的立方体的顶点颜色缓冲区
cubeVertexColorBuffer = gl.createBuffer();
//2.绑定目标对象到缓冲区
gl.bindBuffer(gl.ARRAY_BUFFER, cubeVertexColorBuffer);
//定义我的矩形的颜色数组
colors = [
[1.0, 0.0, 0.0, 1.0], // Front face[red]
[1.0, 1.0, 0.0, 1.0], // Back face[yellow]
[0.0, 1.0, 0.0, 1.0], // Top face[green]
[1.0, 0.5, 0.5, 1.0], // Bottom face[]
[1.0, 0.0, 1.0, 1.0], // Right face[]
[0.0, 0.0, 1.0, 1.0] // Left face[blue]
]; //对于矩形的四个顶点赋予相同的颜色
//每一个面的四个顶点都是同样的颜色
/***
* 1.0, 0.0, 0.0, 1.0
* 1.0, 0.0, 0.0, 1.0
* 1.0, 0.0, 0.0, 1.0
* 1.0, 0.0, 0.0, 1.0
* 1.0, 1.0, 0.0, 1.0
* 1.0, 1.0, 0.0, 1.0
* 1.0, 1.0, 0.0, 1.0
* 1.0, 1.0, 0.0, 1.0
* ………………………………
* 0.0, 0.0, 1.0, 1.0
* 0.0, 0.0, 1.0, 1.0
* 0.0, 0.0, 1.0, 1.0
* 0.0, 0.0, 1.0, 1.0
* @type {Array}
*/
var unpackedColors = [];
for (var i in colors) {
var color = colors[i];
for (var j=0; j < 4; j++) {
unpackedColors = unpackedColors.concat(color);
}
} //3.向缓冲区对象中写入数据
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(unpackedColors), gl.STATIC_DRAW);
//计算我的正方形的顶点数组
cubeVertexColorBuffer.itemSize = 4;
cubeVertexColorBuffer.numItems = 24; //开始定义我的顶点位置数组
//1.创建我的顶点索引缓冲区对象
cubeVertexIndexBuffer = gl.createBuffer();
//2.绑定目标对象到缓冲区
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, cubeVertexIndexBuffer);
//设置我的顶点索引数组
var cubeVertexIndices = [
0, 1, 2, 0, 2, 3, // Front face
4, 5, 6, 4, 6, 7, // Back face
8, 9, 10, 8, 10, 11, // Top face
12, 13, 14, 12, 14, 15, // Bottom face
16, 17, 18, 16, 18, 19, // Right face
20, 21, 22, 20, 22, 23 // Left face
];
//3.向缓冲区对象写入数据
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(cubeVertexIndices), gl.STATIC_DRAW);
//计算我的顶点索引数组的大小(每一项数据的大小,总共36个数据)
/**
* 1个不同的顶点位置(numItems),每个顶点由36个数字组成(itemSize)
* @type {number}
*/
cubeVertexIndexBuffer.itemSize = 1;
cubeVertexIndexBuffer.numItems = 36;
} //定义我的三角形和我的矩形的初始旋转角度
var rPyramid = 0;
var rCube = 0; //绘制我的场景(三角形和矩形)
function drawScene() {
//设置视口大小
gl.viewport(0, 0, gl.viewportWidth, gl.viewportHeight);
//清空颜色缓存和深度缓存
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); //建立一个透视投影(视场角,视口比例,最近,最远距离)
pMatrix = okMat4Proj(45, gl.viewportWidth / gl.viewportHeight, 0.1, 100.0); //新建一个模型视图矩阵
mvMatrix = new okMat4();
//保存矩阵的初始状态
myPushMatrix(); //设置我的模型视图矩阵为平移矩阵
//mvMatrix = okMat4Trans(-1.5, 0.0, -7.0);
mvMatrix.translate(OAK.SPACE_WORLD, -1.5, 0.0, -8.0, true);
//三角形的椎体绕着Y轴旋转(本地坐标系旋转)
mvMatrix.rotY(OAK.SPACE_LOCAL, rPyramid, true); //1.绑定三角形顶点数据到缓冲区对象
gl.bindBuffer(gl.ARRAY_BUFFER, pyramidVertexPositionBuffer);
gl.vertexAttribPointer(shaderProgram.vertexPositionAttribute, pyramidVertexPositionBuffer.itemSize, gl.FLOAT, false, 0, 0); //2.绑定三角形颜色信息到缓冲区对象,并且传递给顶点着色器
gl.bindBuffer(gl.ARRAY_BUFFER, pyramidVertexColorBuffer);
gl.vertexAttribPointer(shaderProgram.textureCoordAttribute, pyramidVertexColorBuffer.itemSize, gl.FLOAT, false, 0, 0); //告诉WEBGL当前使用的模型视图投影矩阵
setMatrixUniforms();
//开始绘制三角形(从第0个位置开始,绘制numItems个顶点)
gl.drawArrays(gl.TRIANGLES, 0, pyramidVertexPositionBuffer.numItems);
//绘制完毕后再次恢复我的模型视图矩阵
myPopMatrix(); //再次保存我的模型视图矩阵
myPushMatrix();
//开始绘制立方体
mvMatrix.translate(OAK.SPACE_WORLD, 1.5, 0.0, -8.0, true);
//让我的矩形绕着XYZ轴旋转
//mvMatrix.rotX(OAK.SPACE_LOCAL, rCube, true);
mvMatrix.rot(OAK.SPACE_LOCAL, rCube, 1.0, 1.0, 1.0, true); //绑定四边形的顶点信息(与索引下标绑定在一起)
gl.bindBuffer(gl.ARRAY_BUFFER, cubeVertexPositionBuffer);
gl.vertexAttribPointer(shaderProgram.vertexPositionAttribute, cubeVertexPositionBuffer.itemSize, gl.FLOAT, false, 0, 0); //开始传递颜色数据
gl.bindBuffer(gl.ARRAY_BUFFER, cubeVertexColorBuffer);
gl.vertexAttribPointer(shaderProgram.textureCoordAttribute, cubeVertexColorBuffer.itemSize, gl.FLOAT, false, 0, 0); //开始绑定索引下标信息
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, cubeVertexIndexBuffer); setMatrixUniforms(); //开始绘制立方体
//gl.drawArrays(gl.TRIANGLE_STRIP, 0, cubeVertexPositionBuffer.numItems);
gl.drawElements(gl.TRIANGLES, cubeVertexIndexBuffer.numItems, gl.UNSIGNED_SHORT, 0); //绘制完毕后,恢复我的模型视图矩阵的初始状态
myPopMatrix();
} //这里是我的主函数
function webGLStart() {
//获取canvas元素
var canvas = document.getElementById("lesson01-canvas"); //初始化WEBGL上下文信息
initGL(canvas); //初始化着色器
initShaders(); //出事阿虎缓冲区
initBuffers(); //指定清空画布的颜色,开启隐藏面消除的功能
gl.clearColor(0.0, 0.0, 0.0, 1.0);
gl.enable(gl.DEPTH_TEST); //开始绘制我的场景
//drawScene();
//开始使用动画效果来绘制我的图形
tick();
} //实现我的动画绘制函数
function tick() {
//重复调用tick函数
okRequestAnimationFrame(tick); //开始绘制场景
drawScene(); //改变我的三角形和我的矩阵的旋转角度
animate();
} //开始不断修改我的旋转角度
var lastTime = 0;
function animate() {
var timeNow = new Date().getTime();
if (lastTime != 0) {
var elapsed = timeNow - lastTime; //三角形 90/s, 矩形 75/s
rPyramid += (90 * elapsed) / 1000.0;
rCube -= (75 * elapsed) / 1000.0;
}
lastTime = timeNow;
} </script> </head> <body onload="webGLStart();">
<canvas id="lesson01-canvas" style="border: none;" width="500" height="500"></canvas>
</body> </html>
												

WEBGL学习【四】模型视图矩阵的更多相关文章

  1. OpenGL(五) 三维变换之模型视图矩阵

    计算机三维图形学中,一个基本的任务是如何描述三维空间中一个物体位置的变化,也就是如何 描述物体的运动.通常情况下,物体位置的变化包含三个基本的变化:平移.旋转和缩放,物体的运动也可以用这三个基本的运动 ...

  2. 【GISER&&Painter】Chapter02:WebGL中的模型视图变换

    上一节我们提到了如何在一张画布上画一个简单几何图形,通过创建画布,获取WebGLRendering上下文,创建一个简单的着色器,然后将一些顶点数据绑定到gl的Buffer中,最后通过绑定buffer数 ...

  3. WEBGL学习【八】模型视图投影矩阵

    <!--探讨WEBGL中不同图形的绘制方法:[待测试2017.11.6]--> <!DOCTYPE HTML> <html lang="en"> ...

  4. webgl开发第一道坎——矩阵与坐标变换

    一.齐次坐标 在3D世界中表示一个点的方式是:(x, y, z);然而在3D世界中表示一个向量的方式也是:(x, y, z);如果我们只给一个三元组(x, y, z)鬼知道这是向量还是点,毕竟点与向量 ...

  5. WEBGL学习【六】动起来的三棱锥和立方体

    <html lang="zh-CN"> <!--服务器运行地址:http://127.0.0.1:8080/webgl/LearnNeHeWebGL/NeHeWe ...

  6. WEBGL学习【五】纹理贴图

    <html lang="zh-CN"> <!--服务器运行地址:http://127.0.0.1:8080/webgl/LearnNeHeWebGL/NeHeWe ...

  7. WEBGL学习【三】颜色选择

    <html lang="zh-CN"> <head> <title>NeHe's WebGL</title> <meta ch ...

  8. WEBGL学习【二】平面图形

    <html lang="zh-CN"> <head> <title>NeHe's WebGL</title> <meta ch ...

  9. WEBGL学习【一】初识WEBGL

    <html lang="zh-CN"> <head> <title>NeHe's WebGL</title> <meta ch ...

随机推荐

  1. 0912MySQL 执行计划explain详解

    转自http://blog.itpub.net/29773961/viewspace-1767044/ 该博客内容是比较全的,虽然写的比较晦涩,多读几遍还是不错的 explain命令是查看查询优化器如 ...

  2. 【ACM】hdu_zs1_1001_水仙花数_201307271504

    水仙花数 Time Limit : 2000/1000ms (Java/Other)   Memory Limit : 65536/32768K (Java/Other)Total Submissio ...

  3. Spring MVC + Shiro + Redis 实现集群会话管理

    之前用的单机Shiro实现用户单点登陆,基本问题不大,但是集群间的session共享单靠Shiro就不好实现了.所以就借助Redis数据库来实现. 这里Redis的搭建我之前说过,感兴趣的可以去看看: ...

  4. 通俗编程——白话NIO之Buffer

    Buffer简单介绍 Buffer意为缓冲区.其本质上就是是一块可写入数据,然后能够从中读取数据的内存区域.通过该种方式有助于降低系统开销和提高外设效率.对于缓冲区我们早有所了解,比方在C中标准I/O ...

  5. 公布IOS产品被拒后怎样再上传新公布包

    问题描写叙述: 前两天提交公司产品2.0.7版本号到苹果审核,昨天提示被拒绝. 被拒原因就不描写叙述了. 我们经过改动后.又一次打包上传,但是怎么也提交不了.由于在苹果后台上已经存在2.0.7版本号的 ...

  6. Android开发策略:缓存

    1.使用缓存策略时,优先考虑使用sdcard(需先推断有无sd卡及其剩余空间是否足够,够的话就开辟一定空间如10M): 2.获取图片时.先从sdcard上找,有的话使用该图片并更新图片最后被使用的时间 ...

  7. Centos7操作系统部署指南

    一.硬件环境: Dell R620 二.软件环境: Centos6.4 X86_64 +KVM Windows7+vnc 三.安装说明 操作系统更新之迅速,让作为新手的系统运维人员有点措手不及,相对于 ...

  8. DevExpress14.1.2 xe XE6 高速安装

    之前在在网上下载的DevExpress14.1.2 xe-XE6都是一个个包文件.须要一个个去查找编译安装,并且须要有一定的顺序要求. 所下面载了好久了都没有安装. 近期在网上找了个旧版的安装方法.以 ...

  9. 详解Google第二代TPU 既能推理又能训练 性能霸道

    详解Google第二代TPU 既能推理又能训练 性能霸道 转自:http://www.cnbeta.com/articles/tech/613639.htm 5月18日凌晨,Google CEO Su ...

  10. java.lang.RuntimeException: Unable to get provider

    java.lang.RuntimeException: Unable to get provider  dev.dworks.apps.candidcamera.provider.MediaDocum ...