要把Cesium,three.js 这些玩明白还是要有WebGL的知识的,不然只是官方demo的ctrl-cv侠,本笔记参考的教程 : 2022年WebGL入门教程(完结)_哔哩哔哩_bilibili
WebGL的工作区在canvas标签中运行,并与canvas有个边距,其内部是一个空间直角坐标系,x,y,z的范围都是∈[ -1 , 1 ] ,z轴是从屏幕里往外延申,最里面是-1
▲ 图:webGL坐标系
顶点缓冲区:功能大概像画画一样,先把图形边框绘制出来,绘制出点位
uniform数据:把顶点缓冲区的数据传给顶点着色器
顶点着色器:给顶点画颜色
图元装配:把顶点数据转换为矢量数据,如:存在3个顶点,这3个点是要绘制成一个面,还是三条线,还是一个点一条直线,还是三个点,等等。
光栅器:矢量转栅格
片元着色器:给栅格数据附上纹理和颜色
归属测试:暂定
模板测试:暂定
深度测试:暂定
融合:融合各方面的数据
抖动:动态效果
颜色缓冲区:用户可以看到的区域
流程:初始化webgl控件、初始化着色器、初始化缓冲区、开始绘制
Document
// 第三方库,集成了一些坐标投影函数
相较于固定输入的一个点位,新增的难点:获取点击时候的显示器坐标、显示器坐标转换为WebGL坐标(像素坐标转归一化zuo)
/** 其他省略,和上一个代码区域里面一样
.....
*/
// 使用顶点缓冲区
function initBuffer() {
let aPsotion = webgl.getAttribLocation(webgl.program, "a_position");
document.addEventListener("mousedown", function (e) {
debugger;
let x = e.clientX;
let y = e.clientY;
let rect = e.target.getBoundingClientRect();
let pointx = (x - rect.left - 512) / 512; // 屏幕转WebGL坐标
let pointy = (350 - (y - rect.top)) / 350;
points.push(pointx);
points.push(pointy);
points.push(0);
let pointPosition = new Float32Array(points);
let pointBuffer = webgl.createBuffer(); // 创建缓冲区
webgl.bindBuffer(webgl.ARRAY_BUFFER, pointBuffer); // 绑定缓冲区
webgl.bufferData(webgl.ARRAY_BUFFER, pointPosition, webgl.STATIC_DRAW); // 缓冲区输入数据
webgl.enableVertexAttribArray(aPsotion); // 启动:开始向GPU传输数据
webgl.vertexAttribPointer(aPsotion, 3, webgl.FLOAT, false, 0, 0); // 配置项:位置、一次从顶点数组取几个数、顶点数组数据类型、是否归一化、间隔字节、偏移字节
webgl.clearColor(0.0, 0.0, 0.0, 1.0);
webgl.clear(webgl.COLOR_BUFFER_BIT | webgl.DEPTH_BUFFER_BIT);
webgl.drawArrays(webgl.POINTS, 0, points.length / 3); // 绘制点
});
let uniformProj = webgl.getUniformLocation(webgl.program, "proj");
webgl.uniformMatrix4fv(uniformProj, false, projMat4);
}
function draw() {
webgl.clearColor(0.0, 0.0, 0.0, 1.0);
webgl.clear(webgl.COLOR_BUFFER_BIT | webgl.DEPTH_BUFFER_BIT);
}
var points = [];
var colors=[];
function initBuffer() {
let aPsotion = webgl.getAttribLocation(webgl.program, "a_position");
let arr = [100.0,100.0,0, 200.0,200.0,0, 300.0,200.0,0 ,400,600,0];
let vertexArr = new Float32Array(arr);
let trangleBuffer = webgl.createBuffer();
webgl.bindBuffer(webgl.ARRAY_BUFFER,trangleBuffer);
webgl.bufferData(webgl.ARRAY_BUFFER,vertexArr,webgl.STATIC_DRAW);
webgl.enableVertexAttribArray(aPsotion);
webgl.vertexAttribPointer(aPsotion,3, webgl.FLOAT, false, 0, 0);
let uniformProj = webgl.getUniformLocation(webgl.program, "proj");
webgl.uniformMatrix4fv(uniformProj, false, projMat4);
}
function draw() {
webgl.clearColor(0.0, 0.0, 0.0, 1.0);
webgl.clear(webgl.COLOR_BUFFER_BIT | webgl.DEPTH_BUFFER_BIT);
webgl.drawArrays(webgl.LINES,0,4); // 绘制线
//webgl.drawArrays(webgl.LINE_STRIP,0,4) // 绘制折现
//webgl.drawArrays(webgl.LINE_LOOP,0,4) // 绘制闭合线
}
var points = [];
var colors=[];
function initBuffer() {
let aPsotion = webgl.getAttribLocation(webgl.program, "a_position");
let arr = [100.0,100.0,0, 200.0,200.0,0, 300.0,200.0,0 ,400,600,0];
let vertexArr = new Float32Array(arr);
let trangleBuffer = webgl.createBuffer();
webgl.bindBuffer(webgl.ARRAY_BUFFER,trangleBuffer);
webgl.bufferData(webgl.ARRAY_BUFFER,vertexArr,webgl.STATIC_DRAW);
webgl.enableVertexAttribArray(aPsotion);
webgl.vertexAttribPointer(aPsotion,3, webgl.FLOAT, false, 0, 0);
let uniformProj = webgl.getUniformLocation(webgl.program, "proj");
webgl.uniformMatrix4fv(uniformProj, false, projMat4);
}
function draw() {
webgl.clearColor(0.0, 0.0, 0.0, 1.0);
webgl.clear(webgl.COLOR_BUFFER_BIT | webgl.DEPTH_BUFFER_BIT);
webgl.drawArrays(webgl.TRIANGLES,0,3);
// webgl.drawArrays(webgl.TRIANGLE_STRIP,0,4);
// webgl.drawArrays(webgl.TRIANGLE_FAN,0,4);
}
图 三角形的绘制类型
1.3.5 索引缓冲区
使用索引实现点位复用,以达到不用传入多个相同的点
理论: 在片元着色器中运行。原理:图片四个点作为控制点,然后插值映射到接受区域。
(1)理论:一次性绘制多个纹理
(2) 图像坐标系与纹理坐标系
▲ 图:图像坐标转纹理坐标
(1)基本理论
Matrix4进行矩阵运算,一秒内快速变换数十次位置,形成动画。
(2)数学运算
▲图:平移、缩放、旋转的矩阵运算
意义:camera视角控制
图:视点、目标点、视线
意义:提升渲染效率
(1)正视投影
图:正视投影
(2)透视投影
图:透视投影
深度缓冲区:三维空间中,保存对象z值的缓冲区
深度冲突:z值相同或十分相近的两个物体对象,会产生重影,解决方案就是深度检测算法
多边形偏移:进行z值的offset偏移设置,使得z值稍微有差距,解决重影问题。
略
知识点:三维场景中,逆时针绘画为正面,顺时针为背面
1. 基本概念
光源:平行光,点光源,环境光(各个方向光照一样)
反射光:镜面反射,漫反射,环境反射
法线:垂直于表面的向量
未完待续