您现在的位置是:首页 > 唯美句子

搭建WebGL开发环境

作者:言安琪时间:2024-04-16 19:18:29分类:唯美句子

简介  文章浏览阅读1.5k次,点赞24次,收藏23次。本篇文章介绍如何搭建WebGL开发环境。_webgl 建立

点击全文阅读

前言

本篇文章介绍如何搭建WebGL开发环境

WebGL

WebGL的技术规范继承自免费和开源的OpenGL ES标准,从某种意义上说,WebGL就是Web版的OpenGL ES,而OpenGL ES是从OpenGL中派生出来的。他们的应用环境有区别,一般来说:

OpenGL:一般应用于桌面级别的三维图形渲染,同类的还有微软的DirectX和苹果公司的Metal技术OpenGL ES:OpenGL的子集,删除了很多用处不大的接口和特性,但仍然能进行三维渲染,应用于智能手机、嵌入式计算机、家用游戏机等WebGL:从OpenGL ES派生出来的。需要浏览器内核的支持。WebGL广泛应用于所有的网页渲染。因为需要运行在浏览器上,所以浏览器在背后做了很多工作,包括跨平台的特性。

版本

既然OpenGL、OpenGL ES和WebGL存在继承关系,那必然涉及到版本信息
先看一下OpenGL的版本信息:

OpenGL 1.5:这个版本的OpenGL不支持着色器编程,采用固定渲染管线OpenGL 2.0:这个版本加入GLSL着色器编程语言OpenGL 3.3:2010年发布OpenGL 4.3:2013年发布

看一下OpenGL ES的版本信息:

OpenGL ES 1.1:OpenGL 1.5的子集,应用范围有限OpenGL ES 2.0:OpenGL 2.0的子集,应用最广泛的版本OpenGL ES 3.0:OpenGL 3.3的子集,增加了很多新功能,包括: 遮挡查询变缓反馈(Transform Feedback)实例渲染(Instanced Rendering)四个或更多渲染目标支持着色语言全面支持整数和32位浮点操作纹理功能大幅增强,支持浮点纹理、3D纹理、深度纹理、顶点纹理、NPOT纹理、R/RG单双通道纹理、不可变纹理、2D阵列纹理、无二次幂限制纹理、阴影对比、调配(swizzle)、LOD与mip level clamps、无缝立方体贴图、采样对象、纹理MSAA抗锯齿渲染器一系列广泛的精确尺寸纹理和渲染缓冲格式

看一下WebGL的版本信息:

WebGL 1.0:基于OpenGL ES 2.0,并提供了3D图形的API,它使用HTML5Canvas并允许利用文档对象模型接口。WebGL 2.0:WebGL 2.0基于OpenGL ES 3.0,确保了提供许多选择性的WebGL 1.0扩展,并引入新的API。可利用部分Javascript实现自动存储器管理

WebGL程序组成

一个最简单的WebGL程序之需要一个html文件和几个js文件就可以了,下面详细介绍

html部分

html主要是为了放置canvas元素,因为WebGL的渲染都是在canvas进行的。
下面是一个html部分:

<!DOCTYPE html><html lang="cn"><head>    <meta charset="utf-8">    <title>wgl render ins</title></head><body onload="main()">    <canvas id="wglCanvas" width="960" height="540">        当前浏览器不支持canvas    </canvas><script src="sk_init.js"></script><script src="sk_shader.js"></script><script src="sk_utils.js"></script></body></html>

这个简单的不能再简单的html就已经够用了。

上面的html我们命名为main.html。从上面的html中,可以发现我们需要一个main函数,这个函数一般来说在js中实现,这也是我们WebGL程序正式开始的入口函数,我们添加一个js文件sk_init.js,并实现该函数,当然我们也需要在html中加入引用js的代码,为了保持代码的简洁,已经在上面的html中加入了该代码。

js部分

下面是sk_init.js的代码:

var gl;function main(){    var canvas = document.getElementById("wglCanvas");    gl = create3DContext(canvas);    if(!gl)    {        console.log("获取webgl渲染上下文失败");        return;    }    gl.clearColor(0.0,0.0,0.0,1.0);    gl.clear(gl.COLOR_BUFFER_BIT);}var create3DContext = function(canvas) {var names = ["webgl", "experimental-webgl", "webkit-3d", "moz-webgl"];var context = null;for (var ii = 0; ii < names.length; ++ii) {try {context = canvas.getContext(names[ii]);} catch(e) {}if (context) {break;}}return context;}

上面这个代码分为几部分:

获取canvas对象获取webgl上下文设置canvas画布背景色使用背景色清空绘图区

虽然代码很简单,但是这几步是所有webgl程序都需要做的事情,当前main.html已经可以运行了。不过只会显示一个黑色背景。下面我们开始加入些东西

shader

想编写一个真正可以使用的webgl程序,首先需要写shader,由于本篇文章我们着重介绍WebGL框架,所以我们只是简单说明一下,关于shader语法,会有专门文章介绍。

WebGL程序的shader一般有两个,顶点着色器片元着色器着色器是以字符串的形式嵌入到js文件中的

下面是两个简单的着色器代码,我们创建一个sk_shader.js存放这部分代码:
顶点着色器:

var VERTEX_SHADER=`attribute vec4 a_Position;uniform float u_PointSize;void main() {  gl_Position = a_Position;  gl_PointSize = u_PointSize;}`;

片元着色器:

var FRAG_SHADER=`void main() {  gl_FragColor = vec4(1.0,0.0,0.0,1.0);}`;

初始化着色器

创建好了着色器以后,下一步就要初始化着色器了

加载着色器代码

我们新建一个sk_util.js文件,里面封装一些公共的方法,首先我们要添加的方法就是加载着色器代码的方法:

// gl: webgl上下文// type: 着色器类型// source: 着色器代码function loadShader(gl, type, source) {  var shader = gl.createShader(type);  if (shader == null) {    console.log('unable to create shader');    return null;  }  gl.shaderSource(shader, source);  gl.compileShader(shader);  var compiled = gl.getShaderParameter(shader, gl.COMPILE_STATUS);  if (!compiled) {    var error = gl.getShaderInfoLog(shader);    console.log('Failed to compile shader: ' + error);    gl.deleteShader(shader);    return null;  }  return shader;}

加载一个着色器需要以下步骤:

创建着色器对象:使用gl.createShader接口,参数为着色器类型,着色器类型一般有两类: gl.VERTEX_SHADER:顶点着色器gl.FRAGMENT_SHADER:片元着色器 加载着色器代码:使用gl.shaderSource接口,第一个参数为第一步创建的着色器对象,第二个参数为着色器的字符串表示编译着色器代码:使用gl.compileShader接口,参数为第一步创建的着色器对象获取着色器编译状态,如果编译失败,获取错误信息

创建着色器程序

下面是创建着色器程序的代码:

function createProgram(gl, vshader, fshader) {  var vertexShader = loadShader(gl, gl.VERTEX_SHADER, vshader);  var fragmentShader = loadShader(gl, gl.FRAGMENT_SHADER, fshader);  if (!vertexShader || !fragmentShader) {    return null;  }  var program = gl.createProgram();  if (!program) {    return null;  }  gl.attachShader(program, vertexShader);  gl.attachShader(program, fragmentShader);  gl.linkProgram(program);  var linked = gl.getProgramParameter(program, gl.LINK_STATUS);  if (!linked) {    var error = gl.getProgramInfoLog(program);    console.log('Failed to link program: ' + error);    gl.deleteProgram(program);    gl.deleteShader(fragmentShader);    gl.deleteShader(vertexShader);    return null;  }  return program;}

创建着色器程序的步骤如下:

创建着色器程序:使用gl.createProgram接口,返回着色器程序对象关联着色器对象:使用gl.attachShader接口,第一个参数是第一步创建的着色器程序对象,第二个参数是关联的着色器对象链接着色器程序:使用gl.linkProgram接口链接程序,参数是第一步创建的着色器程序对象获取着色器程序链接状态,如果链接失败,获取错误信息

使用着色器对象

使用gl.useProgram接口使用我们上一步创建的着色器程序对象。将着色器程序对象赋给gl.program,方便我们后面传递数据的时候使用

代码如下:

function initShaders(gl, vshader, fshader) {    var program = createProgram(gl, vshader, fshader);    if (!program) {      console.log('Failed to create program');      return false;    }    gl.useProgram(program);    gl.program = program;    return true;}

经过这三步以后,着色器程序已经初始化完成了,接下来就是向着色器传递数据

传递数据

所谓的传递数据就是将内存的数据传递给显存
一般情况下shader中使用的数据有三种:

使用attribute标记的数据,这个也叫做顶点数据,就是每个顶点都会有自己的数值使用uniform标记的数据,这个也叫做统一数据,就是所有顶点共用的数据使用varying标记的数据,这个是在着色器之间传递的数据

获取shader的数据标记

使用gl.getAttribLocation接口获取attribute数据的标记,第一个参数是着色器程序对象,第二个参数是数据在shader中的名称的字符串表示使用gl.getUniformLocation接口获取uniform数据的标记,第一个参数是着色器程序对象,第二个参数是数据在shader中的名称的字符串表示

下面我们获取前面着色器程序的a_Position和u_PointSize的标记:

var u_PointSize = gl.getUniformLocation(gl.program, "u_PointSize");if (u_PointSize < 0) {console.log('Failed to get the storage location of u_PointSize');return -1;}var a_Position = gl.getAttribLocation(gl.program, 'a_Position');if (a_Position < 0) {console.log('Failed to get the storage location of a_Position');return -1;}

从内存传递attribute数据到显存

创建缓冲区,使用gl.createBuffer()创建缓冲区绑定缓冲区,使用gl.bindBuffer接口绑定缓冲区,第一个参数是缓冲区类型,这里我们使用gl.ARRAY_BUFFER,第二个参数是上一步创建的缓冲区传递数据,使用gl.bufferData接口传递数据,第一参数是缓冲区类型,这里我们使用gl.ARRAY_BUFFER,第二个参数是内存数据指针,第三个参数是数据的使用方式,这里我们使用gl.STATIC_DRAW
代码如下:
var verticesTexCoords = new Float32Array([    -0.5, 0.5, 0.0, 1.0,    -0.5, -0.5, 0.0, 1.0,    0.5, 0.5, 0.0, 1.0,    0.5, -0.5, 0.0, 1.0,      ]);var FSIZE = verticesTexCoords.BYTES_PER_ELEMENT;var vertexTexCoordBuffer = gl.createBuffer();if (!vertexTexCoordBuffer) {console.log('Failed to create the buffer object');return -1;}gl.bindBuffer(gl.ARRAY_BUFFER, vertexTexCoordBuffer);gl.bufferData(gl.ARRAY_BUFFER, verticesTexCoords, gl.STATIC_DRAW);

传递uniform数据到显存

使用gl.uniform1f接口传递单个float数值到显存,在当前程序中用来传递u_PointSize的值
代码如下:

gl.uniform1f(u_PointSize, 10);

绑定缓冲区与attribute顶点属性

使用gl.vertexAttribPointer接口绑定缓冲区与attribute顶点属性使用gl.enableVertexAttribArray接口开启顶点属性数组,如果不开启的话,默认会使用静态属性,就是所有顶点数据都使用一个默认的值
代码如下:
gl.vertexAttribPointer(a_Position, 4, gl.FLOAT, false, FSIZE * 4, 0);gl.enableVertexAttribArray(a_Position);

绘制

当前程序使用gl.drawArrays来开始绘制操作
gl.drawArrays的第一个参数是绘制的类型,我们当前程序就使用gl.POINTS方式
gl.drawArrays的第二个参数是绘制顶点的偏移,当前为0
gl.drawArrays的第三个参数是绘制顶点的数量,当前为4
代码如下:

gl.clearColor(0.0,0.0,0.0,1.0);gl.clear(gl.COLOR_BUFFER_BIT);gl.drawArrays(gl.POINTS, 0, 4);

代码结构调整

我们把创建WebGL上下文和初始化着色器的方法放进sk_utils.js我们把shader字符串放进sk_shader.js我们把传递数据的部分放进sk_init.jsmain.html中需要添加对这3个js的引用,我们已经添加好了

完整的代码已经上传gitlab:
https://gitlab.com/lingyanTools/sk_webgl.git
该例子绘制了四个顶点
在这里插入图片描述

点击全文阅读

郑重声明:

本站所有活动均为互联网所得,如有侵权请联系本站删除处理

我来说两句