WebGL进阶(五)-可视域
理论基础:
顶点着色器 Vertex Shader
主要是负责处理顶点位置、顶点颜色、顶点向量等顶点的数据;处理一些顶点的变换:例如在进行视图变换和投影变换时MVP矩阵会改变顶点的位置信息。
输入:
顶点着色器输入部分主要是声明:
①储存着每个顶点属性的attribute变量;
②所有顶点都会实现的(例如MVP矩阵、透视变换矩阵等)全局的uniform变量;
③一些会传递给片元着色器的varying变量。
// 变量
attribute vwc3 aVertexPosition; // 顶点位置
attribute vec3 aNormalPosition; // 法线
attribute vec2 aTextureCoord; // uv坐标varying highp vec2 vTextureCoord; // 顶点着色器传递给片元着色器
varying highp vec3 vFragPos;
varying highp vec3 vNormal;// 矩阵
uniform mat4 uModelViewMatrix; // 视图变换矩阵
uniform mat4 uProjectionMatrix; // 透视变换矩阵
输出:
①顶点坐标gl_Position;
②给输入部分声明的varying变量赋值;
矩阵运算从右往左运算
vFragPos = aVertexPosition;
vNormal = aNormalPosition;// 计算点坐标
gl_Position = uProjextionMatrix * uModelViewMatrix * vec4(aVertexPosition,1.0);vTextureCoord = aTextureCoord;
片元着色器 Fragment Shader
用于颜色、贴图、光照阴影等
//除了上述出现的“着色器不支持高精度,限定浮点类型为中精度”
precision mediump float;//还有表示支持高精度的:“着色器支持高精度,限定浮点类型为高精度”
precision highp float;//以及仅支持低精度的:
prcision lowp float;
输入:
uniform声明
/声明一个纹理相关的变量,sampler2D 也是一种数据类型
//它是一种取样器类型的变量,该变量对应传入的纹理2D图片的像素数据
uniform sampler2D uSampler;
//Blinn-Phong需要的漫反射项kd、高光项ks、光源位置、相机位置、光强
uniform vec3 uKd;
uniform vec3 uKs;
uniform vec3 uLightPos;
uniform vec3 uCameraPos;
uniform float uLightIntensity;
// 这个TextureSample参数作用应该是:
// 以左上角为原点,通过UV截取图片,如果==1,则正常取值
uniform int uTextureSample;
varing变量
//继承varying参数
varying highp vec2 vTextureCoord;
varying highp vec3 vFragPos;
varying highp vec3 vNormal;
输出:
一般设置为gl_FragColor
参考:GAMES101-现代计算机图形学入门-闫令琪_哔哩哔哩_bilibili

gl.compileShader(shader), 传递需要编译的着色器,函数实现着色器编译。
gl.getShaderParameter(shader,COMPILE_STATUS),COMPILE_STATUS为:
gl.DELETE_STATUS:标示着色器是否被删除,删除(GL_TRUE)未删除(GL_FALSE).gl.COMPILE_STATUS: 标示着色器是否编译成功,是(GL_TRUE)不是(GL_FALSE)gl.SHADER_TYPE: 标示着色器类型,是顶点着色器 (gl.VERTEX_SHADER) 还是片段着色器 (gl.FRAGMENT_SHADER)
WebGLRenderingContext.enableVertexAttribArray()
在 WebGL 中,作用于顶点的数据会先储存在attributes。这些数据仅对 JavaScript 代码和顶点着色器可用。属性由索引号引用到 GPU 维护的属性列表中。在不同的平台或 GPU 上,某些顶点属性索引可能具有预定义的值。创建属性时,WebGL 层会分配其他属性。
类型为GLuint 的索引,指向要激活的顶点属性。可以使用getAttribLocation方法来获取索引.
WebGLRenderingContext.vertexAttribPointer(index,size,type,normalized,stride,offset)
打开属性数组列表中指定索引处的通用顶点属性数组,
index:定要修改的顶点属性的索引。
size:指定每个顶点属性的组成数量,必须是 1,2,3 或 4。
type:
指定数组中每个元素的数据类型可能是:
-
gl.BYTE: signed 8-bit integer, with values in [-128, 127] 有符号的 8 位整数,范围 [-128, 127] -
gl.SHORT: signed 16-bit integer, with values in [-32768, 32767] 有符号的 16 位整数,范围 [-32768, 32767] -
gl.UNSIGNED_BYTE: unsigned 8-bit integer, with values in [0, 255] 无符号的 8 位整数,范围 [0, 255] -
gl.UNSIGNED_SHORT: unsigned 16-bit integer, with values in [0, 65535] 无符号的 16 位整数,范围 [0, 65535] -
gl.FLOAT: 32-bit IEEE floating point number 32 位 IEEE 标准的浮点数 -
When using a WebGL 2 context, the following values are available additionally: 使用 WebGL2 版本的还可以使用以下值:
gl.HALF_FLOAT: 16-bit IEEE floating point number 16 位 IEEE 标准的浮点数
normalize:
当转换为浮点数时是否应该将整数数值归一化到特定的范围。
- or types
gl.BYTEandgl.SHORT, normalizes the values to [-1, 1] if true. 对于类型gl.BYTE和gl.SHORT,如果是 true 则将值归一化为 [-1, 1] - For types
gl.UNSIGNED_BYTEandgl.UNSIGNED_SHORT, normalizes the values to [0, 1] if true. 对于类型gl.UNSIGNED_BYTE和gl.UNSIGNED_SHORT,如果是 true 则将值归一化为 [0, 1] - For types
gl.FLOATandgl.HALF_FLOAT, this parameter has no effect. 对于类型gl.FLOAT和gl.HALF_FLOAT,此参数无效
stride:
一个 GLsizei,以字节为单位指定连续顶点属性开始之间的偏移量 (即数组中一行长度)。不能大于 255。如果 stride 为 0,则假定该属性是紧密打包的,即不交错属性,每个属性在一个单独的块中,下一个顶点的属性紧跟当前顶点之后。
offset:
指定顶点属性数组中第一部分的字节偏移量。必须是类型的字节长度的倍数。
WebGLRenderingContext.uniformMatrix[234]fv(location,transpose,value)
该方法的 3 个版本(uniformMatrix2fv()、uniformMatrix3fv() 和 unifomMatrix4fv()),分别以二阶、三阶和四阶方阵作为输入值,它们应是分别具有 4、9、16 个浮点数的数组。
WebGLRenderingContext.uniformMatrix2fv(location, transpose, value);
WebGLRenderingContext.uniformMatrix3fv(location, transpose, value);
WebGLRenderingContext.uniformMatrix4fv(location, transpose, value);
location
WebGLUniformLocation 对象包含了要修改的 uniform attribute 位置。位置使用 getUniformLocation()获得。
transpose
GLboolean 指定是否转置矩阵。必须为 false。
value
Float32Array 型或者是 GLfloat 序列值。这些值被假定按列主序(column major order)的方式提供。
源码:
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><script src="gl-matrix.js"></script><script>let vertexstring = `attribute vec4 a_position;uniform mat4 u_formMatrix;uniform mat4 proj;attribute vec4 a_color;varying vec4 color;void main(void){gl_Position = u_formMatrix * a_position;color = a_color;} `;let fragmentstring = `precision mediump float;varying vec4 color;void main(void){gl_FragColor =color;}`;var webgl;var near=0;var far= 50;function init() {initWebgl();initShader();initBuffer();draw();inittext(near,far)initEvent();}function inittext(near,far){document.getElementById("text").innerHTML = "near:"+near +"<br/>"+ "far:"+far;}function initEvent() {document.onkeydown = handleKeyDown;}function handleKeyDown(event) {if (String.fromCharCode(event.keyCode) == 'W') {near += 1;}else if (String.fromCharCode(event.keyCode) == 'S') {near -=1;}else if (String.fromCharCode(event.keyCode) == 'A') {far -= 1;}else if (String.fromCharCode(event.keyCode) == 'D') {far += 1;}inittext(near,far)initBuffer();draw();}function initWebgl() {let webglDiv = document.getElementById('myCanvas');webgl = webglDiv.getContext("webgl");webgl.viewport(0, 0, webglDiv.clientWidth, webglDiv.clientHeight);}function initShader() {let vsshader = webgl.createShader(webgl.VERTEX_SHADER);let fsshader = webgl.createShader(webgl.FRAGMENT_SHADER);webgl.shaderSource(vsshader, vertexstring);webgl.shaderSource(fsshader, fragmentstring);webgl.compileShader(vsshader);webgl.compileShader(fsshader);if (!webgl.getShaderParameter(vsshader, webgl.COMPILE_STATUS)) {var err = webgl.getShaderInfoLog(vsshader);alert(err);return;}if (!webgl.getShaderParameter(fsshader, webgl.COMPILE_STATUS)) {var err = webgl.getShaderInfoLog(fsshader);alert(err);return;}let program = webgl.createProgram();webgl.attachShader(program, vsshader);webgl.attachShader(program, fsshader)webgl.linkProgram(program);webgl.useProgram(program);webgl.program = program}function initBuffer() {let ProjMatrix = glMatrix.mat4.create();glMatrix.mat4.identity(ProjMatrix);glMatrix.mat4.ortho(ProjMatrix,-100,100,-100,100,near,far) //修改可视域范围let arr = [0.0, 70, -40, 1, 1, 0, 0, 1,-50, -30, -40, 1, 1, 0, 0, 1, // 绿色50, -30, -40, 1, 1, 0, 0, 1,50, 40, -20, 1, 1.0, 1.0, 0.4, 1,-50, 40, -20, 1, 1.0, 1.0, 0.4, 1,0.0, -60,-20, 1, 1.0, 1.0, 0.4, 1,// 黄色0.0, 50, 0.0, 1, 0.4, 0.4, 1.0, 1,-50, -50, 0.0, 1, 0.4, 0.4, 1.0, 1,50, -50, 0.0, 1, 0.4, 0.4, 1.0, 1, // 蓝色]let pointPosition = new Float32Array(arr);let aPsotion = webgl.getAttribLocation(webgl.program, "a_position");let triangleBuffer = webgl.createBuffer();webgl.bindBuffer(webgl.ARRAY_BUFFER, triangleBuffer);webgl.bufferData(webgl.ARRAY_BUFFER, pointPosition, webgl.STATIC_DRAW);webgl.enableVertexAttribArray(aPsotion);webgl.vertexAttribPointer(aPsotion, 4, webgl.FLOAT, false, 8 * 4, 0);let aColor = webgl.getAttribLocation(webgl.program, "a_color");webgl.enableVertexAttribArray(aColor);webgl.vertexAttribPointer(aColor, 4, webgl.FLOAT, false, 8 * 4, 4 * 4);let uniformMatrix1 = webgl.getUniformLocation(webgl.program, "u_formMatrix");webgl.uniformMatrix4fv(uniformMatrix1, false, ProjMatrix)}function draw() {webgl.clearColor(0.0, 1.0, 0.0, 1.0);webgl.clear(webgl.COLOR_BUFFER_BIT);webgl.drawArrays(webgl.TRIANGLES, 0, 9);}</script>
</head><body onload="init()"><canvas id='myCanvas' width="1024" height='768'></canvas><div id="text"></div>
</body></html>
效果展示:

可操作键盘方向键进行显示变换。
复盘:
相关文章:
WebGL进阶(五)-可视域
理论基础: 顶点着色器 Vertex Shader 主要是负责处理顶点位置、顶点颜色、顶点向量等顶点的数据;处理一些顶点的变换:例如在进行视图变换和投影变换时MVP矩阵会改变顶点的位置信息。 输入: 顶点着色器输入部分主要是声明&…...
2024性价比家居好物有哪些?推荐五款值得每个家庭拥有的好物品牌!
每年双11的时候我都特别喜欢买一些家居好物,今年双11也不例外,经过我一两周的精心挑选,专门选了五款性价比高的家居好物,接下来给大家分享一下! 家居好物一、希亦ACE Pro内衣洗衣机 我买过、评测过的内衣洗衣机&#…...
字节青训-查找热点数据问题
问题描述 给你一个整数数组 nums 和一个整数 k,请你返回其中出现频率前 k 高的元素。请按升序排列。 1 < nums.length < 10^5k 的取值范围是 [1, 数组中不相同的元素的个数]题目数据保证答案唯一,换句话说,数组中前 k 个高频元素的集合…...
Codeforces Round 981 (Div. 3) (A~F)
文章目录 A. Sakurako and Kosuke思路code B. Sakurako and Water思路code C. Sakurakos Field Trip思路code D. Kousukes Assignment思路code E. Sakurako, Kosuke, and the Permutation思路code F. Kosukes Sloth思路code Codeforces Round 981 (Div. 3) A. Sakurako and Ko…...
shell脚本实例(4)while实现1+...+100,linux新增用户
while实现1到100求和 #!/bin/bash/ s0 i1 #-le小于等于 while [ $i -le 100 ] dos$[ $s$i ]i$[ $i1 ] done echo $s echo $i 执行结果如下 修改用户名密码脚本 #!/bin/bash/ #提示用户输入用户名 read -p "请输入用户名:"username useradd $username #提…...
docker XML详解
下列为一个基本的运行docker镜像文件 {"Id": "62a82b0e69930e54c291095f632adde58dd0b247adba3a048385a55c87e38eba","Created": "2024-07-11T04:00:09.36091853Z","Path": "java","Args": ["-ja…...
web前端边框详解,弹性盒子的使用(仿写购物网页)
边框详解 1. 边框宽度(border - width) - 具体取值:可以是具体的长度值,如 px (像素)、 pt (点)、 em (相对单位)等。例如, border - width: 2px…...
【ACM出版,EI稳定检索,九大高校联合举办, IEEE Fellow支持】2024年计算机视觉与艺术研讨会(CVA 2024)
在线投稿:学术会议-学术交流征稿-学术会议在线-艾思科蓝 2024年计算机视觉与艺术国际学术会议(CVA 2024)作为2024年人工智能、数字媒体技术与交互设计国际学术会议(ICADI 2024)的分会。此次大会旨在汇聚全球在计算机视觉与艺术…...
认识软件测试
博主主页: 码农派大星. 数据结构专栏:Java数据结构 数据库专栏:MySQL数据库 JavaEE专栏:JavaEE 软件测试专栏:软件测试 关注博主带你了解更多知识 1. 什么是测试? 测试在⽣活中处处可⻅ 例子: 对某款购物软件进⾏测试 启动测试:点击软件图标&#…...
poi处理excel文档时,与lombok的@Accessors(chain = true)注解冲突
poi在反射封装数据时会判断set方法的返回是不是Void,加上Accessors会造成NoSuchMethodException异常...
我接触csdn中的c++的时间
大家好,我是AC使者,不知不觉我也来到CSDN半年了!在这半年我也看到了自身的不足,我也还有了很多粉丝,所以我今天来总结一下这半年的东西。 第一篇--------结构体数组 关于结构体数组的理解-CSDN博客 第二篇--------字…...
go语言多态性(接口interface)的使用
前言 在Go语言中,接口类型(interface)完全可以作为一个函数的参数。这是Go语言多态性的一个重要体现,允许函数接受任何实现了接口中定义的方法的类型的实例。 一、接口(interface)定义 type Reader inte…...
如何将markdown文件转换为pdf
最近笔者在用vscode写markdown,但是提交时往往需要交pdf。所以就涉及到如何将markdown转化为pdf格式。 首先,需要在vscode上安装插件 markdown Preview Enhanced 之后在vscode的右上角即可看到下述图标,点击,vscode右半面就会显示…...
【python实操】python小程序之测试报告
引言 python小程序之测试报告 文章目录 引言一、测试报告1.1 概念1.1.1 使用Pytest和Allure生成测试报告1.1.2 使用unittest和HTMLTestRunner生成测试报告1.1.3 总结 1.2 题目1.3 代码1.3 代码解释 二、思考 一、测试报告 1.1 概念 python生成测试报告,常用的方法包…...
【Java基础】2、Java基础语法
f2/fnf2:选中点中的文件名 1.注释 为什么要有注释? 给别人和以后的自己可以看懂的解释 注释含义 注释是在程序指定位置的说明性信息;简单理解,就是对代码的一种解释 注释分类 单行注释 //注释信息 多行注释…...
MATLAB基础应用精讲-【数模应用】本量利分析(Cost-Volume-Profit Analysis)
目录 前言 几个高频面试题目 本量利分析与量本利分析的区别 算法原理 发展历程 几个相关概念 什么是CVP分析 基本假设 注意事项 本量利分析的作用 基本原理 多种产品量本利分析 盈亏平衡分析 目标利润分析 敏感性分析 边际分析 本量利分析基本模型 应用场景 …...
实习冲刺Day7
算法题 合并两个有序链表 class Solution { public:void merge(vector<int>& nums1, int m, vector<int>& nums2, int n) {for (int i 0; i<n; i) {nums1[m i] nums2[i];//直接将num2的数据插入到num1的尾部}sort(nums1.begin(), nums1.end());//排…...
《Python游戏编程入门》注-第4章1
《Python游戏编程入门》的第4章是“用户输入:Bomb Cathcer游戏”,通过轮询键盘和鼠标设备状态实现Bomb Cathcer游戏。 1 Bomb Cathcer游戏介绍 “4.1 认识Bomb Cathcer游戏”内容介绍了Bomb Cathcer游戏的玩法,即通过鼠标来控制红色“挡板”…...
一些硬件知识【2024/10/29】
千兆以太网有8条信号线,百兆以太网有4条线: 网络变压器构造图: 百兆以太网拓扑: BOB Smith电路: 【以太网接口电 路设计】https://www.bilibili.com/video/BV1i3411u7bv?vd_source3cc3c07b09206097d0d8b0aefdf07958&a…...
利用弱监督学习在全切片病理图像中检测和分型基底细胞癌|文献速递-基于生成模型的数据增强与疾病监测应用
Title 题目 Detection and subtyping of basal cell carcinoma in whole-slide histopathology using weakly-supervised learning 利用弱监督学习在全切片病理图像中检测和分型基底细胞癌 01 文献速递介绍 基底细胞癌 (BCC) 的发病率正在给病理诊断带来压力。BCC 的发病率…...
安宝特方案丨XRSOP人员作业标准化管理平台:AR智慧点检验收套件
在选煤厂、化工厂、钢铁厂等过程生产型企业,其生产设备的运行效率和非计划停机对工业制造效益有较大影响。 随着企业自动化和智能化建设的推进,需提前预防假检、错检、漏检,推动智慧生产运维系统数据的流动和现场赋能应用。同时,…...
AtCoder 第409场初级竞赛 A~E题解
A Conflict 【题目链接】 原题链接:A - Conflict 【考点】 枚举 【题目大意】 找到是否有两人都想要的物品。 【解析】 遍历两端字符串,只有在同时为 o 时输出 Yes 并结束程序,否则输出 No。 【难度】 GESP三级 【代码参考】 #i…...
C# SqlSugar:依赖注入与仓储模式实践
C# SqlSugar:依赖注入与仓储模式实践 在 C# 的应用开发中,数据库操作是必不可少的环节。为了让数据访问层更加简洁、高效且易于维护,许多开发者会选择成熟的 ORM(对象关系映射)框架,SqlSugar 就是其中备受…...
今日学习:Spring线程池|并发修改异常|链路丢失|登录续期|VIP过期策略|数值类缓存
文章目录 优雅版线程池ThreadPoolTaskExecutor和ThreadPoolTaskExecutor的装饰器并发修改异常并发修改异常简介实现机制设计原因及意义 使用线程池造成的链路丢失问题线程池导致的链路丢失问题发生原因 常见解决方法更好的解决方法设计精妙之处 登录续期登录续期常见实现方式特…...
处理vxe-table 表尾数据是单独一个接口,表格tableData数据更新后,需要点击两下,表尾才是正确的
修改bug思路: 分别把 tabledata 和 表尾相关数据 console.log() 发现 更新数据先后顺序不对 settimeout延迟查询表格接口 ——测试可行 升级↑:async await 等接口返回后再开始下一个接口查询 ________________________________________________________…...
【C++特殊工具与技术】优化内存分配(一):C++中的内存分配
目录 一、C 内存的基本概念 1.1 内存的物理与逻辑结构 1.2 C 程序的内存区域划分 二、栈内存分配 2.1 栈内存的特点 2.2 栈内存分配示例 三、堆内存分配 3.1 new和delete操作符 4.2 内存泄漏与悬空指针问题 4.3 new和delete的重载 四、智能指针…...
LLMs 系列实操科普(1)
写在前面: 本期内容我们继续 Andrej Karpathy 的《How I use LLMs》讲座内容,原视频时长 ~130 分钟,以实操演示主流的一些 LLMs 的使用,由于涉及到实操,实际上并不适合以文字整理,但还是决定尽量整理一份笔…...
jmeter聚合报告中参数详解
sample、average、min、max、90%line、95%line,99%line、Error错误率、吞吐量Thoughput、KB/sec每秒传输的数据量 sample(样本数) 表示测试中发送的请求数量,即测试执行了多少次请求。 单位,以个或者次数表示。 示例:…...
(一)单例模式
一、前言 单例模式属于六大创建型模式,即在软件设计过程中,主要关注创建对象的结果,并不关心创建对象的过程及细节。创建型设计模式将类对象的实例化过程进行抽象化接口设计,从而隐藏了类对象的实例是如何被创建的,封装了软件系统使用的具体对象类型。 六大创建型模式包括…...
手机平板能效生态设计指令EU 2023/1670标准解读
手机平板能效生态设计指令EU 2023/1670标准解读 以下是针对欧盟《手机和平板电脑生态设计法规》(EU) 2023/1670 的核心解读,综合法规核心要求、最新修正及企业合规要点: 一、法规背景与目标 生效与强制时间 发布于2023年8月31日(OJ公报&…...
