WebGL学习系列-第一个程序
Posted 那个天真的人
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了WebGL学习系列-第一个程序相关的知识,希望对你有一定的参考价值。
前言
本篇学习第一个WebGL程序——画一个点,通过此程序来理解WebGL程序的结构,这是所有后续知识的开端。
画一个点
先看一下效果图:
为了画这么一个点,在WebGL可不太简单,它会涉及到WebGL上下文以及着色器的概念,不要着急,咱们慢慢来理解。
WebGL上下文
学过Canvas的同学应该都知道,想要在浏览器中使用Canvas画图,需要先取得一个上下文,就像创建一个场景一样,有了场景才可以绘制。在WebGL中,想要进行绘制,一样需要先获取一个上下文,而且跟Canvas 2D开发上下文的获取非常的类似。
1、首先,要有一个canvas dom元素
<canvas id="webgl" width="400" height="400">
您的浏览器不支持canvas,建议使用Chrome浏览器
</canvas>
2、获取上一步得到的 canvas dom元素,然后获取WebGL上下文
var canvas = document.getElementById('webgl');
// 获取WebGL上下文
function createWebGLContext(canvas)
var names = ["experimental-webgl", "webgl" , "webkit-3d", "moz-webgl"];
var webglContext = null;
for (var i = 0; i < names.length; i++)
try
webglContext = canvas.getContext(names[i]);
if(webglContext)
break;
catch(e)
return webglContext;
考虑到兼容性,所以我们尝试多种获取WebGL上下文的方式,只要任何一种获取成功即可返回WebGL上下文。
背景清除
学习WebGL开发的时候,有个非常重要的概念就是清除重绘。打个比方,我们想要在界面上画两个矩形,先画第一个,然后隔5秒后再画第二个,最终界面上显示2个矩形。那么正确的做法是先绘制第一个矩形,然后使用一个5秒的定时器,5秒后清空之前绘制的所有内容,然后绘制两个矩形。说白了,就是你所看到的东西是一次性绘制出来的,而不能先绘制一点,隔一会再绘制一点,每一次绘制都要进行整个画面的重绘。而在重绘的时候,一般我们都会设置一个重绘的默认背景颜色,设置一次即可。
// 这里指定默认背景色为黑色,不透明
context.clearColor(0.0, 0.0, 0.0, 1.0);
设置完默认背景色之后,在每一次绘制之前,我们手动清除绘制区域,然后重绘整个画面。
// 清空
context.clear(context.COLOR_BUFFER_BIT);
注意到这里我们使用 context.COLOR_BUFFER_BIT,其实,我们每一次绘制的时候,可能要画非常多的图形,不是说我们画一个图形就立马在浏览器上显示的,那样很可能出现闪屏,所以我们绘制其实是绘制在称为颜色缓冲区的一块内存空间来的,等全部绘制好之后,再一次性刷新到浏览器展现,这样才不会闪屏。除了COLOR_BUFFER_BIT(颜色缓冲区),以后我们还会接触context.DEPTH_BUFFER_BIT(深度缓冲区),后续篇章再解释。
绘制
有了上下文,知道了绘制的方法,接下来我们就要绘制了,本篇我们要绘制一个点,为了绘制一个点,我们要有绘制点的api,要知道点的位置,大小和颜色。
我们使用 context.drawArrays(context.POINTS, 0, 1); 来绘制一个点,drawArrays可以用于绘制点、线段、扇形等各类形状,参数简要介绍如下:
绘制基本图形:
drawArrays(mode , first , count)
mode: 绘制的形状,用于决定点是怎么连接成图形的
first: 顶点开始索引
count: 使用多少个顶点进行绘制
此api能够绘制的基本图形如下所示:
有了绘制的api还不够,我们发现没有地方指定点的位置、大小、颜色之类的属性,这对于新学习的朋友一定感到很迷惑,到现在还没有看到可以设置点属性的地方,这也是WebGL比较麻烦,但也是非常精华的一部分,这一块实际上是由着色器来完成的。
先来看一张图:
在WebGL中,有两类着色器,分别为顶点着色器和片元着色器,它们的作用上图已经表述得很清楚了,着色器其实就是一段代码,然后会被底层不断的调用,从而获取绘制所需要的点的一些信息。为了使用着色器,需要创建一个program对象,program对象内部再绑定顶点着色器和片元着色器对象,而着色器对象又是需要我们创建的,创建后指定代码片段字符串即可,最后在context中,使用这个program即可,drawArrays接口内部会自行跟program中的着色器通信对接。
再来看一张顶点着色器的示意图:
再对应到代码中就很容易理解了,片元着色器的使用流程也是一样的。
本示例中我们的顶点着色器代码片段如下:
// 顶点着色器代码(决定顶点在哪里、大小、颜色)
var VSHADER_SOURCE =
'void main() \\n' +
' gl_Position = vec4(0.0, 0.0, 0.0, 1.0);\\n' + // 设置顶点的位置
' gl_PointSize = 10.0;\\n' + // 设置顶点的大小
'\\n';
注意,着色器的代码片段是以字符串形式存在 的,而且像其他语言一样有个main函数,顶点着色器有几个内置变量,目前我们使用了gl_Position 和 gl_PointSize ,分别表示顶点的位置和大小,而且我们在这里固化了变量的值,以后再来研究怎么实现动态变量,现在你要知道,当我们执行drawArrays的时候,底层会执行顶点着色器的代码,获取点的位置和大小。
片元着色器的代码如下:
var FSHADER_SOURCE =
'void main() \\n' +
' gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);\\n' + // 设置顶点的颜色
'\\n';`````````
在片元着色器中,我们使用了内部属性 gl_FragColor,用于表示像素的颜色值,此代码片段在真正执行时,对于每一个像素,都会被调用一次,所以称之为片元着色器也挺符合的。
小结
经过上面的分析,我们发现在WebGL中绘制一个点确实不太容易,但是当理清了各个涉及到的知识点之后,画其他东西原理都差不多的,最主要还是要理解着色器的概念,这只是第一篇,往后随着不断学习,不断加深对着色器的理解。
源码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>第一个WebGL程序-画一个点</title>
</head>
<body onload="main()">
<canvas id="webgl" width="400" height="400">
您的浏览器不支持canvas,建议使用Chrome浏览器
</canvas>
<script>
// 主程序入口
function main()
var canvas = document.getElementById('webgl');
var context = createWebGLContext(canvas);
var program = createProgram(context , VSHADER_SOURCE ,FSHADER_SOURCE);
context.program = program;
context.useProgram(program);
// 每一次重绘时的背景色
context.clearColor(0.0, 0.0, 0.0, 1.0);
// 清除 <canvas>
context.clear(context.COLOR_BUFFER_BIT);
// 画一个点
context.drawArrays(context.POINTS, 0, 1);
// 获取WebGL上下文
function createWebGLContext(canvas)
var names = ["experimental-webgl", "webgl" , "webkit-3d", "mozwebgl"];
var webglContext = null;
for (var i = 0; i < names.length; i++)
try
webglContext = canvas.getContext(names[i]);
if(webglContext)
break;
catch(e)
return webglContext;
// 创建一个program(相当于着色器的上下文)
function createProgram(context, vshader, fshader)
var vertexShader = loadShader(context, context.VERTEX_SHADER,vshader);
var fragmentShader = loadShader(context,context.FRAGMENT_SHADER,fshader);
var program = context.createProgram();
context.attachShader(program, vertexShader);
context.attachShader(program, fragmentShader);
context.linkProgram(program);
return program;
function loadShader(context, type, source)
var shader = context.createShader(type);
context.shaderSource(shader, source);
context.compileShader(shader);
return shader;
// 顶点着色器代码(决定顶在哪里,大小)
var VSHADER_SOURCE =
'void main() \\n' +
' gl_Position = vec4(0.0, 0.0, 0.0, 1.0);\\n' + // 设置顶点的位置
' gl_PointSize = 10.0;\\n' + // 设置顶点的大小
'\\n';
// 片元着色器代码(给像素上色)
var FSHADER_SOURCE =
'void main() \\n' +
' gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);\\n' + // 设置顶点的颜色
'\\n';
</script>
</body>
</html>
源码下载
以上是关于WebGL学习系列-第一个程序的主要内容,如果未能解决你的问题,请参考以下文章