<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 vTextureCoord; uniform sampler2D uSampler; void main(void) {
gl_FragColor = texture2D(uSampler, vec2(vTextureCoord.s, vTextureCoord.t));
}
</script> <!--顶点着色器;后面可以通过ID编号来获取这段顶点着色器代码-->
<script id="shader-vs" type="x-shader/x-vertex">
attribute vec3 aVertexPosition;
attribute vec4 aTextureCoord; uniform mat4 uMVMatrix;
uniform mat4 uPMatrix; varying vec4 vTextureCoord;
void main(void) {
gl_Position = uPMatrix * uMVMatrix * vec4(aVertexPosition, 1.0);
vTextureCoord = aTextureCoord;
}
</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, "aTextureCoord");
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 cubeVertexTextureCoordBuffer ;
//定义我的立方体索引下标
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.创建我的立方体的顶点纹理图片缓冲区
cubeVertexTextureCoordBuffer = gl.createBuffer();
//2.绑定目标对象到缓冲区
gl.bindBuffer(gl.ARRAY_BUFFER, cubeVertexTextureCoordBuffer );
//定义我的矩形的颜色数组
var textureCoords = [
// Front face
0.0, 0.0,
1.0, 0.0,
1.0, 1.0,
0.0, 1.0, // Back face
1.0, 0.0,
1.0, 1.0,
0.0, 1.0,
0.0, 0.0, // Top face
0.0, 1.0,
0.0, 0.0,
1.0, 0.0,
1.0, 1.0, // Bottom face
1.0, 1.0,
0.0, 1.0,
0.0, 0.0,
1.0, 0.0, // Right face
1.0, 0.0,
1.0, 1.0,
0.0, 1.0,
0.0, 0.0, // Left face
0.0, 0.0,
1.0, 0.0,
1.0, 1.0,
0.0, 1.0,
]; //3.向缓冲区对象中写入数据
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(textureCoords), gl.STATIC_DRAW);
//计算我的正方形的顶点数组
cubeVertexTextureCoordBuffer .itemSize = 2;
cubeVertexTextureCoordBuffer .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, cubeVertexTextureCoordBuffer );
gl.vertexAttribPointer(shaderProgram.textureCoordAttribute, cubeVertexTextureCoordBuffer.itemSize, gl.FLOAT, false, 0, 0); //开始使用我的纹理图片来绘制我的立方体(在绘制之前使用这个函数drawElemenets());从TEXTURE0到TEXTURE31
gl.activeTexture(gl.TEXTURE0);
//告诉WEBGL要使用的纹理图片
gl.bindTexture(gl.TEXTURE_2D, neheTexture);
//将0这个值推送到着色器的uniform变量中
gl.uniform1i(shaderProgram.samplerUniform, 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 handleLoadedTexture(texture) {
//绑定当前要使用的纹理图片
gl.bindTexture(gl.TEXTURE_2D, texture);
//修改图片的坐标系(垂直翻转)
gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true);
//将纹理图片传至着色器(图片类型,细节层次,图片个通道的大小, 图片本身)
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, texture.image);
//告诉WebGL如何放大纹理
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
//告诉WebGL如何缩小纹理
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
//把当前纹理清空
gl.bindTexture(gl.TEXTURE_2D, null);
} //实现我的初始化纹理图片
var neheTexture;
function initTexture() {
neheTexture = gl.createTexture();
neheTexture.image = new Image();
//图片加载完毕后调用该函数
neheTexture.image.onload = function () {
handleLoadedTexture(neheTexture);
}
//neheTexture.image.src = "http://127.0.0.1:8080/webgl/images/NeHe.bmp";
neheTexture.image.src = "./resources/NeHe.bmp";
} //这里是我的主函数
function webGLStart() {
//获取canvas元素
var canvas = document.getElementById("lesson01-canvas"); //初始化WEBGL上下文信息
initGL(canvas); //初始化着色器
initShaders(); //出事阿虎缓冲区
initBuffers(); //初始化纹理图片
initTexture(); //指定清空画布的颜色,开启隐藏面消除的功能
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>
												

最新文章

  1. Python初学者之网络爬虫
  2. rqnoj378 约会计划
  3. JVM内存模型和启动参数的关系
  4. NGINX怎样处理惊群的
  5. 解读SQL Server 2014可更新列存储索引——存储机制
  6. Scrum 项目 7.0
  7. linux 内核调试
  8. CopyOnWriteArrayList
  9. c语言学习之基础知识点介绍(十一):字符串的介绍、使用
  10. C语言-04函数
  11. 【PAT】1025. PAT Ranking (25)
  12. OCP-1Z0-051-题目解析-第33题
  13. 用 MVC 5 的 EF6 Code First 入门 系列:MVC程序中实体框架的Code First迁移和部署
  14. Unity 使用 陀螺仪 实现 《王者荣耀》 登入界面 背景动态效果
  15. 【java并发系列】Fork/Join任务(转)
  16. macos 常用快捷键及操作
  17. python-廖雪峰,map/reduce学习笔记
  18. firefox os 会不会是未来移动平板及电视之星
  19. Ant多渠道批量打包
  20. cratedb geo 查询

热门文章

  1. 洛谷 P2046 BZOJ 2007 海拔(NOI2010)
  2. hdu 1829 带权并查集的运用类似于食物链但是更简单些
  3. POJ 1129 Channel Allocation DFS 回溯
  4. JavaThread等待/通知经典范式
  5. 新安装的wampserver怎么使用本机已有的mysql作为数据库
  6. Linux GDB程序调试工具使用简单介绍
  7. bzoj2878 [Noi2012]迷失游乐园 [树形dp]
  8. 弗拉特利定律:Illumina怎样缔造基因革命
  9. js设计模式-组合模式
  10. golang二维码