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 的发病率…...
(LeetCode 每日一题) 3442. 奇偶频次间的最大差值 I (哈希、字符串)
题目:3442. 奇偶频次间的最大差值 I 思路 :哈希,时间复杂度0(n)。 用哈希表来记录每个字符串中字符的分布情况,哈希表这里用数组即可实现。 C版本: class Solution { public:int maxDifference(string s) {int a[26]…...
前端倒计时误差!
提示:记录工作中遇到的需求及解决办法 文章目录 前言一、误差从何而来?二、五大解决方案1. 动态校准法(基础版)2. Web Worker 计时3. 服务器时间同步4. Performance API 高精度计时5. 页面可见性API优化三、生产环境最佳实践四、终极解决方案架构前言 前几天听说公司某个项…...
苍穹外卖--缓存菜品
1.问题说明 用户端小程序展示的菜品数据都是通过查询数据库获得,如果用户端访问量比较大,数据库访问压力随之增大 2.实现思路 通过Redis来缓存菜品数据,减少数据库查询操作。 缓存逻辑分析: ①每个分类下的菜品保持一份缓存数据…...
Android Bitmap治理全解析:从加载优化到泄漏防控的全生命周期管理
引言 Bitmap(位图)是Android应用内存占用的“头号杀手”。一张1080P(1920x1080)的图片以ARGB_8888格式加载时,内存占用高达8MB(192010804字节)。据统计,超过60%的应用OOM崩溃与Bitm…...
Android 之 kotlin 语言学习笔记三(Kotlin-Java 互操作)
参考官方文档:https://developer.android.google.cn/kotlin/interop?hlzh-cn 一、Java(供 Kotlin 使用) 1、不得使用硬关键字 不要使用 Kotlin 的任何硬关键字作为方法的名称 或字段。允许使用 Kotlin 的软关键字、修饰符关键字和特殊标识…...
DeepSeek 技术赋能无人农场协同作业:用 AI 重构农田管理 “神经网”
目录 一、引言二、DeepSeek 技术大揭秘2.1 核心架构解析2.2 关键技术剖析 三、智能农业无人农场协同作业现状3.1 发展现状概述3.2 协同作业模式介绍 四、DeepSeek 的 “农场奇妙游”4.1 数据处理与分析4.2 作物生长监测与预测4.3 病虫害防治4.4 农机协同作业调度 五、实际案例大…...
代理篇12|深入理解 Vite中的Proxy接口代理配置
在前端开发中,常常会遇到 跨域请求接口 的情况。为了解决这个问题,Vite 和 Webpack 都提供了 proxy 代理功能,用于将本地开发请求转发到后端服务器。 什么是代理(proxy)? 代理是在开发过程中,前端项目通过开发服务器,将指定的请求“转发”到真实的后端服务器,从而绕…...
Mobile ALOHA全身模仿学习
一、题目 Mobile ALOHA:通过低成本全身远程操作学习双手移动操作 传统模仿学习(Imitation Learning)缺点:聚焦与桌面操作,缺乏通用任务所需的移动性和灵活性 本论文优点:(1)在ALOHA…...
以光量子为例,详解量子获取方式
光量子技术获取量子比特可在室温下进行。该方式有望通过与名为硅光子学(silicon photonics)的光波导(optical waveguide)芯片制造技术和光纤等光通信技术相结合来实现量子计算机。量子力学中,光既是波又是粒子。光子本…...
【Java学习笔记】BigInteger 和 BigDecimal 类
BigInteger 和 BigDecimal 类 二者共有的常见方法 方法功能add加subtract减multiply乘divide除 注意点:传参类型必须是类对象 一、BigInteger 1. 作用:适合保存比较大的整型数 2. 使用说明 创建BigInteger对象 传入字符串 3. 代码示例 import j…...
