webGL的基本原理详细教程

简介: webGL的基本原理详细教程

前言

hello world欢迎来到前端的新世界


😜当前文章系列专栏:前端可视化

🐱‍👓博主在前端领域还有很多知识和技术需要掌握,正在不断努力填补技术短板。(如果出现错误,感谢大家指出)🌹

💖感谢大家支持!您的观看就是作者创作的动力

WebGL 基本原理


WebGL 的出现使得在浏览器上面实现显示 3D 图像成为可能,WebGL 本质上是基于光栅化的 API ,而不是基于 3D 的 API。


WebGL 只关注两个方面,即投影矩阵的坐标和投影矩阵的颜色。使用 WebGL 程序的任务就是实现具有投影矩阵坐标和颜色的 WebGL 对象即可。可以使用“着色器”来完成上述任务。顶点着色器可以提供投影矩阵的坐标,片段着色器可以提供投影矩阵的颜色。


无论要实现的图形尺寸有多大,其投影矩阵的坐标的范围始终是从 -1 到 1 。下面是一个关于实现 WebGL 对象的一个简单例子。


// Get A WebGL context
var canvas = document.getElementById("canvas");
var gl = canvas.getContext("experimental-webgl");
// setup a GLSL program
var program = createProgramFromScripts(gl, ["2d-vertex-shader", "2d-fragment-shader"]);
gl.useProgram(program);
// look up where the vertex data needs to go.
var positionLocation = gl.getAttribLocation(program, "a_position");
// Create a buffer and put a single clipspace rectangle in
// it (2 triangles)
var buffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
gl.bufferData(
gl.ARRAY_BUFFER,
new Float32Array([
-1.0, -1.0,
 1.0, -1.0,
-1.0,  1.0,
-1.0,  1.0,
 1.0, -1.0,
 1.0,  1.0]),
gl.STATIC_DRAW);
gl.enableVertexAttribArray(positionLocation);
gl.vertexAttribPointer(positionLocation, 2, gl.FLOAT, false, 0, 0);
// draw
gl.drawArrays(gl.TRIANGLES, 0, 6);   


下面是两个着色器。


<script id="2d-vertex-shader" type="x-shader/x-vertex">
attribute vec2 a_position;
void main() {
  gl_Position = vec4(a_position, 0, 1);
}
</script>
<script id="2d-fragment-shader" type="x-shader/x-fragment">
void main() {
  gl_FragColor = vec4(0, 1, 0, 1);  // green
}
</script>    


它将绘出一个绿色的长方形来填充整个画板。


后面内容还会更精彩,我们继续:


我们再次强调一下,无论画板尺寸多大,投影矩阵坐标的范围只会在 -1 到 1 之间。从上面的例子中,我们可以看出我们只是将位置信息直接写在了程序里。 因为位置信息已经在投影矩阵中,所以并没有其他额外的工作要做。 如果想实现 3D 的效果,那么可以使用着色器来将 3D 转换为投影矩阵,这是因为 WebGL 是基于光栅的 API。


对于 2D 的图像,也许会使用像素而不是投影矩阵来表述尺寸,那么这里我们就更改这里的着色器,使得我们实现的矩形可以以像素的方式来度量,下面是新的顶点着色器。


<script id="2d-vertex-shader" type="x-shader/x-vertex">
attribute vec2 a_position;
uniform vec2 u_resolution;
void main() {
   // convert the rectangle from pixels to 0.0 to 1.0
   vec2 zeroToOne = a_position / u_resolution;
   // convert from 0->1 to 0->2
   vec2 zeroToTwo = zeroToOne * 2.0;
   // convert from 0->2 to -1->+1 (clipspace)
   vec2 clipSpace = zeroToTwo - 1.0;
   gl_Position = vec4(clipSpace, 0, 1);
}
</script>    


下面我们将我们的数据从投影矩阵改为像素。


// set the resolution
var resolutionLocation = gl.getUniformLocation(program, "u_resolution");
gl.uniform2f(resolutionLocation, canvas.width, canvas.height);
// setup a rectangle from 10,20 to 80,30 in pixels
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([
10, 20,
80, 20,
10, 30,
10, 30,
80, 20,
80, 30]), gl.STATIC_DRAW);    


上面例子矩阵位于底部边框,下面我们让它位于左上边框:


修改代码如下:


gl_Position = vec4(clipSpace * vec2(1, -1), 0, 1);


效果如下图:


下面我们将上述关于矩阵的实现写成函数以便可以以函数调用的方式来实现不同尺寸的矩阵。 然而,这里的颜色应该是可变的。


首先,我们为片段着色器设计一个关于颜色的输入。


<script id="2d-fragment-shader" type="x-shader/x-fragment">
precision mediump float;
uniform vec4 u_color;
void main() {
   gl_FragColor = u_color;
}
</script>    

例子

下面是实现绘画 50 个尺寸和颜色均随机的矩阵的代码。

var colorLocation = gl.getUniformLocation(program, "u_color");
  ...
  // Create a buffer
  var buffer = gl.createBuffer();
  gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
  gl.enableVertexAttribArray(positionLocation);
  gl.vertexAttribPointer(positionLocation, 2, gl.FLOAT, false, 0, 0);
  // draw 50 random rectangles in random colors
  for (var ii = 0; ii < 50; ++ii) {
// Setup a random rectangle
setRectangle(
gl, randomInt(300), randomInt(300), randomInt(300), randomInt(300));
// Set a random color.
gl.uniform4f(colorLocation, Math.random(), Math.random(), Math.random(), 1);
// Draw the rectangle.
gl.drawArrays(gl.TRIANGLES, 0, 6);
}
// Returns a random integer from 0 to range - 1.
function randomInt(range) {
  return Math.floor(Math.random() * range);
}
// Fills the buffer with the values that define a rectangle.
function setRectangle(gl, x, y, width, height) {
  var x1 = x;
  var x2 = x + width;
  var y1 = y;
  var y2 = y + height;
  gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([
 x1, y1,
 x2, y1,
 x1, y2,
 x1, y2,
 x2, y1,
 x2, y2]), gl.STATIC_DRAW);
}    

下面就是实现出来的效果。

后言

创作不易,要是本文章对广大读者有那么一点点帮助 不妨三连支持一下,您的鼓励就是博主创作的动力


目录
相关文章
|
4月前
|
Apache 图形学
WebGL☀️Unity WebGL适配到各平台的教程
WebGL☀️Unity WebGL适配到各平台的教程
|
7月前
|
存储 缓存 前端开发
WebGL 底层是如何工作的详细教程
WebGL 底层是如何工作的详细教程
97 0
|
存储 缓存 前端开发
WebGL简介
WebGL简介
135 0
WebGL简介
|
前端开发 定位技术
从零开始手把手教你使用javascript+canvas开发一个塔防游戏01地图创建
从零开始手把手教你使用javascript+canvas开发一个塔防游戏01地图创建
165 0
从零开始手把手教你使用javascript+canvas开发一个塔防游戏01地图创建
|
存储 前端开发 JavaScript
WebGL 基础概念
WebGL 基础概念
166 0
WebGL 基础概念
|
移动开发 JavaScript 前端开发
webgl入门指南(一)
本文适合对图形感兴趣的小伙伴阅读。
webgl入门指南(一)
|
存储 缓存 前端开发
几个简单的小例子手把手带你入门webgl(二)
实战——绘制个三角形 在进行实战之前,我们先给你看一张图,让你能大概了解,用原生webgl生成一个三角形需要那些步骤: draw 我们就跟着这个流程图一步一步去操作: 初始化canvas 新建一个webgl画布 <canvas id="webgl" width="500" height="500"></canvas> 创建webgl 上下文: const gl = document.getElementById('webgl').getContext('webgl') 创建着色器程序 着色器的程序这些代码,其实是重复的,我们还是先看下图,看下我们到底需要哪些步骤: shader 那我们就跟着这
几个简单的小例子手把手带你入门webgl(二)
|
缓存 异构计算
几个简单的小例子手把手带你入门webgl(一)
各位同学们大家好,又到了周末写文章的时间,之前群里有粉丝提问, 就是shader不是很理解。然后今天他就来了, 废话不多说,读完今天的这篇文章你可以学到以下几点: 为什么需要有shader ? shader的作用是什么???? shader 中的每个参数到底是什么意思??怎么去用??? 你如果会了,这篇文章你可以不用看👀,不用浪费时间,去看别的文章。如果哪里写的有问题欢迎大家指正,我也在不断地学习当中。 why need shader 这里我结合自己的思考🤔,讲讲webgl的整个的一个渲染过程。 渲染管线 「Webgl」的渲染依赖底层「GPU」的渲染能力。所以「WEBGL」 渲染流程
几个简单的小例子手把手带你入门webgl(一)
|
前端开发 JavaScript 异构计算
WebGL基础笔记
WebGL基础笔记
199 0
|
监控 前端开发 索引
如何用webgl(three.js)搭建一个3D库房,3D密集架,3D档案室,-第二课
闲话少叙,我们接着第一课继续讲(http://www.cnblogs.com/yeyunfei/p/7899613.html),很久没有做技术分享了。很多人问第二课有没有,我也是抽空写一下第二课。 第一课程提到了在库房的基础上添加上下架 消防 温湿度等等控制 刚好 最近有接到一个客户的需求 是和库房...
2263 0