您的位置:首页 > Web前端 > HTML5

WebGL的原生API不可能那么可爱

2014-03-14 17:43 246 查看

本文简介

通过三种方法实现同一目标来展示WebGL原生API,并引导读者入门WebGL(伪)。

本文将分别使用Canvas 2D Context,Three.js,WebGL来绘制一个最简单的图形——一个6*6像素的点。

正文

当你第一次听说浏览器支持WebGL了,你可能欢呼雀跃,暗喜我大前端也有能操纵3D图形的一天。你按捺不住激动的心情拿出冰箱里百威啤酒,猛喝了一口。你潇洒的打开浏览器,Google了一下WebGL的教程,欣赏起了WebGL代码。可是就是你那惊鸿一瞥的刹那间,喷了屏幕一口泡沫/一口老血喷在屏幕上。“我的JavaScript怎么可能长这样?!”,你高声大喊道。是的,你没有看错,这货真不是JavaScript。这混合着attribute,gl_Position,precision等你从未在前端看到的词汇的怪物,到底是何方妖孽!你感到一阵眩晕,胃里也翻滚了起来,就好像你刚一口吞下了一份插着鸡毛的圣代……

而本文就是为了在你伤口上撒点盐,放点葱而存在的!

说到画一个点,大概谁都会。你熟练的从书包里掏出水彩笔,在白纸的正中央用力的点了一点,骄傲的喊道:“老师,我第一个画完了!”老师在你额头上贴了一朵小红花,周围掌声雷动,连绵不息。

但是如果不能用笔呢?我们先来看看如何用Canvas 2D Context画一个点。

Canvas 2D Context

这个比较简单,就不添加注释了,下面是代码。

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title></title>
<style>
#cvs {
border: 2px solid pink;
}
</style>
<script>
addEventListener("DOMContentLoaded", function () {
var cvs = document.getElementById("cvs");
var cxt = cvs.getContext("2d");
var pointSize = 6;
cxt.fillStyle = "rgba(0,0,0,1)";
cxt.fillRect(0, 0, cvs.width, cvs.height);
cxt.fillStyle = "rgba(77,153,204,1)";
cxt.fillRect((cvs.width - pointSize) / 2, (cvs.height - pointSize) / 2, pointSize, pointSize);
});
</script>
</head>
<body>
<canvas id="cvs" width="800" height="600"></canvas>
</body>
</html>

你掰开指头算了一下,刚好七个指头。是的,用这种方法画一个点只要7行代码而已。下面的截图应该和代码在你大脑里运行的结果一样。



黑色的画布里一个蓝点。

Three.js

接下来我们来看看Three.js如何实现在浏览器里画一个简单的点。

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title></title>
<style>
#threejs {
border: 2px solid pink;
width:800px;
height:600px;
}
</style>
<script src="three.js"></script>
<script>
addEventListener("DOMContentLoaded", function () {
var threejs = document.getElementById("threejs");
//点的尺寸
var size = 6;
var width = 800, height = 600;
//新建场景
var scene = new THREE.Scene();
//新建正射投影摄像机,摄像机的可视截面宽为width,高为height,近截面距离为0.1,远截面为1
var camera = new THREE.OrthographicCamera(-width / 2, width / 2, height / 2, -height / 2, 0.1, 1);
//摄像机往z轴移1,才能看到物体
camera.position.z = 1;
//新建渲染器
var renderer = new THREE.WebGLRenderer();
//设置渲染视口大小,你可以改成400,300试试
renderer.setSize(width, height);
//添加画布到文档中
threejs.appendChild(renderer.domElement);
//新建平面几何结构,宽高都为6
var geometry = new THREE.PlaneGeometry(size, size);
//新建材质,颜色为蓝色
var material = new THREE.MeshBasicMaterial({ color: 0x4d99cc });
//结合物体的结构和材质
var plane = new THREE.Mesh(geometry, material);
//添加到场景里才能被渲染
scene.add(plane);
//开始使用给定的摄像机渲染给定的场景
renderer.render(scene, camera);
});
</script>
</head>
<body>
<div id="threejs"></div>
</body>
</html>

你用上了脚趾头发现three.js花了14行代码来画一点简单的点。我们的WebGL选手能不能打破Three.js的记录并夺得最繁琐画点大赛的桂冠呢?

WebGL

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title></title>
<style>
#webgl {
border: 2px solid pink;
}
</style>
<script id="vertexShader" type="x-shader/x-vertex">
//这部分是顶点着色器
//声明一个attribute类型的4维向量a_Position
attribute vec4 a_Position;
void main()
{
//gl_Position和gl_PointSize是预定义变量,表示顶点位置和大小
gl_Position = a_Position;
gl_PointSize = 6.0;
}
</script>
<script id="fragmentShader" type="x-shader/x-fragment">
//这部分是片段着色器
void main()
{
//gl_FragColor是预定义变量,表示片段的颜色
gl_FragColor = vec4(0.3, 0.6, 0.8, 1.0);
}
</script>
<script>
addEventListener("DOMContentLoaded", function () {
var webgl = document.getElementById("webgl");
//获取3D上下文
var gl = webgl.getContext("webgl");
//获取顶点着色器的源代码
var vertexGLSL = document.getElementById("vertexShader").text;
//创建顶点着色器
var vertexShader = gl.createShader(gl.VERTEX_SHADER);
//设置顶点着色器的源代码
gl.shaderSource(vertexShader, vertexGLSL);
//编译顶点着色器
gl.compileShader(vertexShader);
//获取片段着色器的源代码
var fragmentGLSL = document.getElementById("fragmentShader").text;
//创建片段着色器
var fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);
//设置片段着色器的源代码
gl.shaderSource(fragmentShader, fragmentGLSL);
//编译片段着色器
gl.compileShader(fragmentShader);
//创建着色器程序
var program = gl.createProgram();
//程序加入顶点着色器
gl.attachShader(program, vertexShader);
//程序加入片段着色器
gl.attachShader(program, fragmentShader);
//链接程序
gl.linkProgram(program);
//启用程序
gl.useProgram(program);
//获取attribute类型变量a_Position在内存里的位置
var a_Position = gl.getAttribLocation(program, "a_Position");
//给a_Position赋值
gl.vertexAttrib2f(a_Position, 0.0, 0.0);
//将颜色缓冲区的值设置为黑色
gl.clearColor(0, 0, 0, 1);
//使用颜色缓冲区的值来填充
gl.clear(gl.COLOR_BUFFER_BIT);
//画点
gl.drawArrays(gl.POINTS, 0, 1);
});
</script>
</head>
<body>
<canvas id="webgl" width="800" height="600"></canvas>
</body>
</html>

你掰了一会儿指头,无奈的发现指头不够用了。最后你找到了一根绳子,通过打结发现一共有30行。无疑WebGL是夺冠了,你微笑着大声宣布出这个消息,并给WebGL戴上了草结的花圈……

反馈

如果你发现错误或者心存疑问,欢迎在下面留言。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
相关文章推荐