当前位置: 首页 > news >正文

WebGL2简单实例

一、主代码

<html><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8" /><title>Triangle</title> <!--标题--><script type="text/javascript" src="js/GLUtil.js"></script><script type="text/javascript" src="js/Matrix.js"></script><script type="text/javascript" src="js/MatrixState.js"></script><script type="text/javascript" src="js/Triangle.js"></script><script type="text/javascript" src="js/LoadShaderUtil.js"></script><script>'use strict';//GLES上下文var gl;//变换矩阵管理类对象var ms=new MatrixState();//要绘制的3D物体var ooTri;//着色器程序列表,集中管理var shaderProgArray=new Array();var currentAngle;var incAngle;var canvas;//初始化的方法function start(){
//            //获取3D Canvas
//            var canvas = document.getElementById('bncanvas');
//            //获取GL上下文
//            gl = canvas.getContext('webgl2', { antialias: true });gl = initWebGLCanvas("bncanvas");if (!gl) //若获取GL上下文失败{alert("创建GLES上下文失败,不支持webGL2.0!");//显示错误提示信息return;}//设置视口gl.viewport(0, 0, canvas.width, canvas.height);//设置屏幕背景色RGBAgl.clearColor(0.0,0.0,0.0,1.0);//初始化变换矩阵ms.setInitStack();//设置摄像机
//            ms.setCamera(0,0,17,0,0,0,0,1,0);//立方体摄像机位置ms.setCamera(0,0,-5,0,0,0,0,1,0);//三角形摄像机位置//设置投影参数ms.setProjectFrustum(-1.5,1.5,-1,1,1,100);gl.enable(gl.DEPTH_TEST);//开启深度检测//加载着色器程序loadShaderFile("shader/vtrtex.bns",0);loadShaderFile("shader/fragment.bns",0);if(shaderProgArray[0])//如果着色器已加载完毕{ooTri=new Triangle(gl,shaderProgArray[0]);//创建三角形绘制对象}else{setTimeout(function(){ooTri=new Triangle(gl,shaderProgArray[0]);},90);//休息90ms后再执行}//初始化旋转角度currentAngle = 0;//初始化角度步进值incAngle = 0.4;//定时绘制画面setInterval("drawFrame();",16.6);}//绘制一帧画面的方法function drawFrame(){	  if(!ooTri){console.log("加载未完成!");//提示信息return;}//清除着色缓冲与深度缓冲gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);  //保护现场ms.pushMatrix(); //执行旋转,即按哪个轴旋转ms.rotate(currentAngle,0,1,0);//绘制物体ooTri.drawSelf(ms);//恢复现场ms.popMatrix();//修改旋转角度currentAngle += incAngle;if (currentAngle > 360)//保证角度范围不超过360currentAngle -= 360; 			}   </script>
</head><body onload="start();"><canvas height="800" width="1200" id="bncanvas">若看到这个文字,说明浏览器不支持WebGL!</canvas>
</body>
</html>

1、引入工具函数

        此代码显示一个三角形,在网页首先引入本地几个文 件:

        Triangles.js   三角形绘制 对象 

        GLUtil.js :    GL工具函数

        LoadShaderUtil.js   着色器装载函数  

        Matrix.js    矩阵基础函数

        MatrixState.js: 矩阵状态

2、 启动函数 start()

        代码启动函数为start(),具体流程为:

        1、获取初始化的WebGL句柄

        2、检测获取WebGL句柄的结果,若失败返回

        3、设置视口

        4、设置屏幕背景

        5、初始化变换矩阵

        6、设置摄像机

        7、开启深度检测

        8、加载着色器程序

        9、定时绘制画面

3、渲染函数drawFrame()

绘制一 帧画面的方法drawFrame()流程如下:

        1、检测绘制对象是否加载,若未加载则返回 

        2、清除着色缓冲与深度缓冲

        3、保护现场

        4、执行旋转

        5、绘制物体 

        6、恢复现场

        7、修改旋转角度 

二、GL工具函数( GLUtil)

//初始化WebGL Canvas的方法
function initWebGLCanvas(canvasName) {canvas = document.getElementById(canvasName);//获取Canvas对象var context = canvas.getContext('webgl2', { antialias: true });//获取GL上下文return context;//返回GL上下文对象
}
//加载单个着色器的方法
function loadSingleShader(ctx, shaderScript)
{if (shaderScript.type == "vertex")//若为顶点着色器{var shaderType = ctx.VERTEX_SHADER;//顶点着色器类型}else if (shaderScript.type == "fragment")//若为片元着色器{var shaderType = ctx.FRAGMENT_SHADER;//片元着色器类型}else {//否则打印错误信息console.log("*** Error: shader script of undefined type '"+shaderScript.type+"'");return null;}//根据类型创建着色器程序var shader = ctx.createShader(shaderType);//加载着色器脚本ctx.shaderSource(shader, shaderScript.text);//编译着色器ctx.compileShader(shader);//检查编译状态var compiled = ctx.getShaderParameter(shader, ctx.COMPILE_STATUS);if (!compiled && !ctx.isContextLost()) {//若编译出错var error = ctx.getShaderInfoLog(shader);//获取错误信息console.log("*** Error compiling shader :"+error);//打印错误信息ctx.deleteShader(shader);//删除着色器程序return null;//返回空}return shader;//返回着色器程序
}//加载链接顶点、片元着色器的方法
function loadShaderSerial(gl, vshader, fshader)
{//加载顶点着色器var vertexShader = loadSingleShader(gl, vshader);//加载片元着色器var fragmentShader = loadSingleShader(gl, fshader);//创建着色器程序var program = gl.createProgram();//将顶点着色器和片元着色器挂接到着色器程序gl.attachShader (program, vertexShader);//将顶点着色器添加到着色器程序中gl.attachShader (program, fragmentShader);//将片元着色器添加到着色器程序中//链接着色器程序gl.linkProgram(program);//检查链接是否成功var linked = gl.getProgramParameter(program, gl.LINK_STATUS);if (!linked && !gl.isContextLost())//若链接不成功{//获取并在控制台打印错误信息var error = gl.getProgramInfoLog (program);//获取错误信息console.log("Error in program linking:"+error);//打印错误信息gl.deleteProgram(program);//删除着色器程序gl.deleteProgram(fragmentShader);//删除片元着色器gl.deleteProgram(vertexShader);//删除顶点着色器return null;//返回空}gl.useProgram(program);//gl.enable(gl.DEPTH_TEST);//打开深度检测return program;//返回着色器程序
}

此工具函数 包含三个函数,分别是:

        initWebGLCanvas   初始化WebGL Canvas的方法

        loadSingleShader    加载单个着色器的方法

        loadShaderSerial    加载链接顶点、片元着色器的方法

三、色器装载函数( LoadShaderUtil)

function shaderObject(typeIn,textIn)//声明shaderObject类
{this.type=typeIn;//初始化type成员变量this.text=textIn;//初始化text成员变量
}
var shaderStrArray=["a","a"];//存储着色器
var shaderNumberCount=0;     //数组索引值
var shaderTypeName=["vertex","fragment"];//着色器名称数组
function processLoadShader(req,index)//处理着色器脚本内容的回调函数
{if (req.readyState == 4) //若状态为4{var shaderStr = req.responseText;//获取响应文本shaderStrArray[shaderNumberCount]=new shaderObject(shaderTypeName[shaderNumberCount],shaderStr);//顶点着色器脚本内容shaderNumberCount++;if(shaderNumberCount>1)//如果着色器内容不为空{shaderProgArray[index]=loadShaderSerial(gl,shaderStrArray[0], shaderStrArray[1]);//加载着色器}}
}
//加载着色器的方法
function loadShaderFile(url,index)//从服务器加载着色器脚本的函数
{var req = new XMLHttpRequest();//创建XMLHttpRequest对象req.onreadystatechange = function () //设置响应回调函数{ processLoadShader(req,index) };//调用processLoadShader处理响应req.open("GET", url, true);//用GET方式打开指定URLreq.responseType = "text";//设置响应类型req.send(null);//发送HTTP请求
}

        shaderObject    声明shaderObject类

        processLoadShader   处理着色器脚本内容的回调函数

        loadShaderFile    从服务器加载着色器脚本的函数

四、 矩阵状态(MatrixState)

function MatrixState()
{this.mProjMatrix = new Array(16);//投影矩阵this.mVMatrix = new Array(16);//摄像机矩阵this.currMatrix=new Array(16);//基本变换矩阵this.mStack=new Array(100);//矩阵栈//初始化矩阵的方法this.setInitStack=function(){this.currMatrix=new Array(16);//创建用于存储矩阵元素的数组setIdentityM(this.currMatrix,0);//将元素填充为单位阵的元素值}//保护变换矩阵,当前矩阵入栈this.pushMatrix=function(){this.mStack.push(this.currMatrix.slice(0));}//恢复变换矩阵,当前矩阵出栈this.popMatrix=function(){this.currMatrix=this.mStack.pop();}//执行平移变换this.translate=function(x,y,z)//设置沿xyz轴移动{translateM(this.currMatrix, 0, x, y, z);//将平移变换记录进矩阵}//执行旋转变换this.rotate=function(angle,x,y,z)//设置绕xyz轴移动{rotateM(this.currMatrix,0,angle,x,y,z);//将旋转变换记录进矩阵}//执行缩放变换this.scale=function(x,y,z)//设置绕xyz轴移动{scaleM(this.currMatrix,0,x,y,z)//将缩放变换记录进矩阵}//设置摄像机this.setCamera=function(cx,	//摄像机位置xcy,   //摄像机位置ycz,   //摄像机位置ztx,   //摄像机目标点xty,   //摄像机目标点ytz,   //摄像机目标点zupx,  //摄像机UP向量X分量upy,  //摄像机UP向量Y分量upz   //摄像机UP向量Z分量){setLookAtM(this.mVMatrix,0,cx,cy,cz,tx,ty,tz,upx,upy,upz);}//设置透视投影参数this.setProjectFrustum=function(left,		//near面的leftright,    //near面的rightbottom,   //near面的bottomtop,      //near面的topnear,		//near面距离far       //far面距离){frustumM(this.mProjMatrix, 0, left, right, bottom, top, near, far);}//设置正交投影参数this.setProjectOrtho=function(left,		//near面的leftright,    //near面的rightbottom,   //near面的bottomtop,      //near面的topnear,		//near面与视点的距离far       //far面与视点的距离){orthoM(this.mProjMatrix, 0, left, right, bottom, top, near, far);}//获取具体物体的总变换矩阵this.getFinalMatrix=function(){var mMVPMatrix=new Array(16);multiplyMM(mMVPMatrix, 0, this.mVMatrix, 0, this.currMatrix, 0);multiplyMM(mMVPMatrix, 0, this.mProjMatrix, 0, mMVPMatrix, 0);return mMVPMatrix;}//获取具体物体的变换矩阵this.getMMatrix=function(){return this.currMatrix;}
}

此矩阵状态类,定义了四个矩阵:

        mProjMatrix = new Array(16);//投影矩阵
        mVMatrix = new Array(16);//摄像机矩阵
        currMatrix=new Array(16);//基本变换矩阵
         mStack=new Array(100);//矩阵栈

成员函数如下所示:

        setInitStack   初始化矩阵的方法

        pushMatrix  保护变换矩阵,当前矩阵入栈

        popMatrix  恢复变换矩阵,当前矩阵出栈

        translate   执行平移变换

        rotate  执行旋转变换

        scale   执行缩放变换

        setCamera   设置摄像机

        setProjectFrustum  设置透视投影参数

        setProjectOrtho  设置正交投影参数

        getFinalMatrix   获取具体物体的总变换矩阵

        getMMatrix     获取具体物体的变换矩阵

五 、三角形绘制 对象(Triangles)

function Triangle(								//声明绘制用物体对象所属类gl,						 					//GL上下文programIn									//着色器程序id
){//this.vertexData=vertexDataIn;						//初始化顶点坐标数据this.vertexData= [//三角形顶点3.0,0.0,0.0,0.0,0.0,0.0,0.0,3.0,0.0//立方体顶点// 3.0,3.0,3.0,// 3.0,-3.0,3.0,// -3.0,3.0,3.0,// -3.0,3.0,3.0,// 3.0,-3.0,3.0,// -3.0,-3.0,3.0,//// 3.0,3.0,3.0,// 3.0,-3.0,-3.0,// 3.0,3.0,-3.0,//// 3.0,3.0,3.0,// 3.0,-3.0,3.0,// 3.0,-3.0,-3.0,//// -3.0,3.0,3.0,// -3.0,-3.0,-3.0,// -3.0,3.0,-3.0,//// -3.0,3.0,3.0,// -3.0,-3.0,3.0,// -3.0,-3.0,-3.0,//// 3.0,3.0,-3.0,// 3.0,-3.0,-3.0,// -3.0,3.0,-3.0,//// -3.0,3.0,-3.0,// 3.0,-3.0,-3.0,// -3.0,-3.0,-3.0];this.vcount=this.vertexData.length/3;//得到顶点数量this.vertexBuffer=gl.createBuffer();				//创建顶点坐标数据缓冲gl.bindBuffer(gl.ARRAY_BUFFER,this.vertexBuffer); 	//绑定顶点坐标数据缓冲//将顶点坐标数据送入缓冲gl.bufferData(gl.ARRAY_BUFFER,new Float32Array(this.vertexData),gl.STATIC_DRAW);this.colorsData=[//三角形顶点颜色1.0,1.0,1.0,1.0,0.0,0.0,1.0,1.0,0.0,1.0,0.0,1.0//立方体顶点颜色// 1.0,0.0,1.0,1.0,					//初始化顶点颜色数据// 1.0,0.0,0.0,1.0,// 1.0,0.0,0.0,1.0,// 1.0,1.0,1.0,1.0,					//初始化顶点颜色数据// 0.0,0.0,1.0,1.0,// 0.0,1.0,0.0,1.0,//// 1.0,1.0,1.0,1.0,					//初始化顶点颜色数据// 0.0,0.0,1.0,1.0,// 0.0,1.0,0.0,1.0,//// 1.0,1.0,1.0,1.0,					//初始化顶点颜色数据// 0.0,0.0,1.0,1.0,// 0.0,1.0,0.0,1.0,//// 1.0,1.0,1.0,1.0,					//初始化顶点颜色数据// 0.0,0.0,1.0,1.0,// 0.0,1.0,0.0,1.0,//// 1.0,1.0,1.0,1.0,					//初始化顶点颜色数据// 0.0,0.0,1.0,1.0,// 0.0,1.0,0.0,1.0,//// 1.0,1.0,1.0,1.0,					//初始化顶点颜色数据// 0.0,0.0,1.0,1.0,// 0.0,1.0,0.0,1.0,//// 1.0,1.0,1.0,1.0,					//初始化顶点颜色数据// 0.0,0.0,1.0,1.0,// 0.0,1.0,0.0,1.0];this.colorBuffer=gl.createBuffer();gl.bindBuffer(gl.ARRAY_BUFFER,this.colorBuffer); 	//绑定颜色数据缓冲//将颜色数据送入缓冲gl.bufferData(gl.ARRAY_BUFFER,new Float32Array(this.colorsData),gl.STATIC_DRAW);this.program=programIn;		//初始化着色器程序idthis.drawSelf=function(ms)//绘制物体的方法{gl.useProgram(this.program);//指定使用某套着色器程序//获取总变换矩阵引用idvar uMVPMatrixHandle=gl.getUniformLocation(this.program, "uMVPMatrix");//将总变换矩阵送入渲染管线gl.uniformMatrix4fv(uMVPMatrixHandle,false,new Float32Array(ms.getFinalMatrix()));gl.enableVertexAttribArray(gl.getAttribLocation(this.program, "aPosition"));//启用顶点坐标数据数组gl.bindBuffer(gl.ARRAY_BUFFER, this.vertexBuffer);	//绑定顶点坐标数据缓冲//给管线指定顶点坐标数据gl.vertexAttribPointer(gl.getAttribLocation(this.program,"aPosition"),3,gl.FLOAT,false,0, 0);gl.enableVertexAttribArray(gl.getAttribLocation(this.program, "aColor"));//启用颜色坐标数据数组gl.bindBuffer(gl.ARRAY_BUFFER, this.colorBuffer);	//绑定颜色坐标数据缓冲//给管线指定颜色坐标数据gl.vertexAttribPointer(gl.getAttribLocation(this.program,"aColor"),4,gl.FLOAT,false,0, 0);gl.drawArrays(gl.TRIANGLES, 0, this.vcount);		//用顶点法绘制物体}
}

绘制 对象 具体流程 如下:

缓冲 区初始化: 

        1、定义顶点数据,送数据至顶点坐标数据缓冲

        2、定义颜色数据、送数据至颜色数据缓冲

        3、初始化着色器程序

绘制 方法drawSelf(ms)

        1、指定使用某套着色器程序

         2、获取总变换矩阵,将总变换矩阵送入渲染管线

         3、启用顶点坐标数据数组,绑定顶点坐标数据缓冲,给管线指定顶点坐标数据

         4、启用颜色坐标数据数组,绑定颜色坐标数据缓冲,给管线指定颜色坐标数据

         5、用顶点法绘制物体

六、 着色器

顶点着色器

#version 300 es
uniform mat4 uMVPMatrix; //总变换矩阵
layout (location = 0) in vec3 aPosition;  //顶点位置
layout (location = 1) in vec4 aColor;    //顶点颜色
out  vec4 vColor;  //用于传递给片元着色器的变量void main()
{gl_Position = uMVPMatrix * vec4(aPosition,1); //根据总变换矩阵计算此次绘制此顶点位置vColor = aColor;//将接收的颜色传递给片元着色器
}

片段着色器

#version 300 es
precision mediump float;
in  vec4 vColor; //接收从顶点着色器过来的参数
out vec4 fragColor;//输出到的片元颜色
void main()
{fragColor = vColor;//给此片元颜色值
}

相关文章:

  • VsCode如何使用默认程序打开word Excel pdf等文件
  • 珍爱网:从降本增效到绿色低碳,数字化新基建价值凸显
  • 浅析锁的应用与场景
  • Java大模型开发与应用 - 面试实战
  • SQL 函数进行左边自动补位fnPadLeft和FORMAT
  • 嵌入式开发:基础知识介绍
  • vue-lottie的使用和配置
  • Linux系统中命令设定临时IP
  • Linux:进程的等待
  • 装备制造企业选型:什么样的项目管理系统最合适?
  • java实现网格交易回测
  • MySQL 库的操作 -- 增删改查,备份和恢复,系统编码
  • SIEMENS PLC程序解读 -BLKMOV (指定长度数据批量传输)
  • 深度学习之卷积神经网络入门
  • 火山云的市场竞争
  • HashSet 概述
  • 【实用技巧】如何无损去除图片水印?
  • HashMap的源码解析
  • ZYNQ-GPIO之MIO中断
  • 【kafka初学】启动执行命令
  • IPO周报|4月最后2只新股周一申购,今年以来最低价股来了
  • 人民时评:投资于人,促高质量充分就业
  • 屋顶上的阳光与火光:战争如何改变了加沙的能源格局
  • 网贷放款后自动扣除高额会员费,多家网贷平台被指变相收取“砍头息”
  • 安徽铁塔再通报“会议室不雅行为”事件:涉事员工停职检查
  • 新东方:2025财年前三季度净利增29%,第四财季海外业务将承压