马上注册,结交更多好友,享用更多功能^_^
您需要 登录 才可以下载或查看,没有账号?立即注册
x
本帖最后由 weiter 于 2024-7-11 15:54 编辑
声明:本人极度业余,本系列无法实现有条理的编排,文中会出现很多问题,望周知。
<=上篇
渲染管线
WebGL相当于一座流水线工厂,而渲染会走过以下流程(虽然我看不懂但还是要放上来)
图中的顶点缓冲区会在后续内容中多次出现(应该吧),那么什么是顶点缓冲区呢?
知周所众,一个3D的模型是由一堆三角形堆起来的,而众多三角形的顶点位置就会决定建模的形状。顶点缓冲区就是存贮这些顶点的地方。
图中出现的图元装配就是指将从顶点缓冲区拿来的点按指令组装成一个个点、线、三角形。
光栅器起到将矢量图转化为像素图的作用(光栅化)。
光栅化的目的是将图形矢量数据(顶点坐标、uv等)转化成带有矢量插值信息的像素数据。
——哔站的一条弹幕
片元着色器负责给模型上纹理。
3D渲染前的准备
端出一盘菜,得先有装菜的盘子。而canvas就是使用WebGL进行3D渲染时用的“盘子”。
如果不了解canvas的用法可以点击此处前往小甲鱼大大的Canvas绘图使用详解~
本段代码创建一个canvas元素,<body onload="main()">
<canvas id="glcanvas" width="640" height="480">
你的浏览器似乎不支持或者禁用了 HTML5 <code><canvas></code> 元素。
</canvas>
</body>
而这一段代码设置了一个事件处理程序用以设置WebGL的上下文并开始渲染。(怎么感觉好绕口)// 从这里开始
function main() {
const canvas = document.querySelector("#glcanvas");
// 初始化 WebGL 上下文
const gl = canvas.getContext("webgl");
// 确认 WebGL 支持性
if (!gl) {
alert("无法初始化 WebGL,你的浏览器、操作系统或硬件等可能不支持 WebGL。");
return;
}
// 使用完全不透明的黑色清除所有图像
gl.clearColor(0.0, 0.0, 0.0, 1.0);
// 用上面指定的颜色清除缓冲区
gl.clear(gl.COLOR_BUFFER_BIT);
}
我们所要做的第一件事就是是获取 canvas 的引用,把它保存在‘canvas’变量里。
当我们获取到 canvas 之后,我们会调用getContext 函数并向它传递 "webgl" 参数,来尝试获取WebGLRenderingContext。如果浏览器不支持 webgl, getContext 将会返回 null,我们就可以显示一条消息给用户然后退出。
如果 WebGL 上下文成功初始化,变量‘gl’会用来引用该上下文。在这个例子里,我们用黑色清除上下文内已有的元素。(用背景颜色重绘 canvas)
效果大概就是一个被黑色填满的canvas。
坐标系
WebGL渲染时会用到canvas,然鹅WebGL的坐标系却不是直接套用的canvas坐标系,需要进行转换。
而WebGL的x/y/z坐标取值有所限制,或者说只有在规定范围内的值才能让图像得以渲染。
Mdn上是这么说的——
裁剪空间
在 WebGL 程序中,数据通常上传到具有自己的坐标系统的 GPU 上,然后顶点着色器将这些点转换到一个称为裁剪空间的特殊坐标系上。
延展到裁剪空间之外的任何数据都会被剪裁并且不会被渲染。
如果一个三角形超出了该空间的边界,则将其裁切成新的三角形,并且仅保留新三角形在裁剪空间中的部分。
上面的图像裁剪空间的可视化,所有点都必须被包含在其中。
它是一个角在 (-1, -1, -1),对角在 (1, 1, 1),中心点在 (0, 0, 0) 的每边 2 个单位的立方体。
裁剪空间使用的这个两个立方米坐标系称为归一化设备坐标(NDC)。
在研究和使用 WebGL 代码时,你可能时不时的会使用这个术语。
道生一
要想用WebGL画出想要的东西,首先要能画出一个点。小甲鱼说得好,“道生一,一生二,二生三,三生万物。”嘛。完了忘了是哪个视频里的,呜呜呜呜呜呜呜。
本着不重复造轮子的原则,这里直接上大佬的代码,不得不说大佬的注释真的对小白非常友好。
***以下代码来源于WebGL零基础入门教程(郭隆邦)。<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>使用WebGL绘制一个点</title>
</head>
<body>
<!--canvas标签创建一个宽高均为500像素,背景为蓝色的矩形画布-->
<canvas id="webgl" width="500" height="500" style="background-color: blue"></canvas>
<script>
//通过getElementById()方法获取canvas画布
var canvas=document.getElementById('webgl');
//通过方法getContext()获取WebGL上下文
var gl=canvas.getContext('webgl');
//顶点着色器源码
var vertexShaderSource = '' +
'void main(){' +
//给内置变量gl_PointSize赋值像素大小
' gl_PointSize=20.0;' +
//顶点位置,位于坐标原点
' gl_Position =vec4(0.0,0.0,0.0,1.0);' +
'}';
//片元着色器源码
var fragShaderSource = '' +
'void main(){' +
//定义片元颜色
' gl_FragColor = vec4(1.0,0.0,0.0,1.0);' +
'}';
//初始化着色器
var program = initShader(gl,vertexShaderSource,fragShaderSource);
//开始绘制,显示器显示结果
gl.drawArrays(gl.POINTS,0,1);
//声明初始化着色器函数
function initShader(gl,vertexShaderSource,fragmentShaderSource){
//创建顶点着色器对象
var vertexShader = gl.createShader(gl.VERTEX_SHADER);
//创建片元着色器对象
var fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);
//引入顶点、片元着色器源代码
gl.shaderSource(vertexShader,vertexShaderSource);
gl.shaderSource(fragmentShader,fragmentShaderSource);
//编译顶点、片元着色器
gl.compileShader(vertexShader);
gl.compileShader(fragmentShader);
//创建程序对象program
var program = gl.createProgram();
//附着顶点着色器和片元着色器到program
gl.attachShader(program,vertexShader);
gl.attachShader(program,fragmentShader);
//链接program
gl.linkProgram(program);
//使用program
gl.useProgram(program);
//返回程序program对象
return program;
}
</script>
</body>
</html>
***以上代码来源于WebGL零基础入门教程(郭隆邦)。
实现的效果如下——你在期待什么这只是在画一个点。
诶不是画一个点吗?怎么看着是一个方块呢?这就是光栅化,输出了一个像素化的结果。而且本来canvas的点也是方的,像素点。
|