WebGL 3着色器和GLSL

news2025/5/17 10:49:51

我们之前提到过着色器和GLSL,但是没有涉及细节,你可能已经对此有所了解, 但以防万一,这里将详细讲解着色器和GLSL。

在工作原理中我们提到,WebGL每次绘制需要两个着色器, 一个顶点着色器和一个片段着色器,每一个着色器都是一个方法

一个顶点着色器和一个片段着色器链接在一起放入一个着色程序中(或者只叫程序)。

一个典型的WebGL应用会有多个着色程序。


顶点着色器

一个顶点着色器的工作是生成裁剪空间坐标值,通常是以下的形式

void main() {
   gl_Position = doMathToMakeClipspaceCoordinates
}

每个顶点调用一次(顶点)着色器,每次调用都需要设置一个特殊的全局变量gl_Position, 该变量的值就是裁剪空间坐标值。

顶点着色器需要的数据,可以通过以下三种方式获得。

Attributes 属性(从缓冲中获取的数据)

最常用的方法是缓冲和属性,在工作原理 中讲到了缓冲和属性,你可以创建缓冲

var buf = gl.createBuffer();

将数据存入缓冲

gl.bindBuffer(gl.ARRAY_BUFFER, buf);
gl.bufferData(gl.ARRAY_BUFFER, someData, gl.STATIC_DRAW);

然后初始化的时候,在你制作的(着色)程序中找到属性所在地址

var positionLoc = gl.getAttribLocation(someShaderProgram, "a_position");

在渲染的时候告诉WebGL怎么从缓冲中获取数据传递给属性

// 开启从缓冲中获取数据
gl.enableVertexAttribArray(positionLoc);
 
var numComponents = 3;  // (x, y, z)
var type = gl.FLOAT;    // 32位浮点数据
var normalize = false;  // 不标准化
var offset = 0;         // 从缓冲起始位置开始获取
var stride = 0;         // 到下一个数据跳多少位内存
                        // 0 = 使用当前的单位个数和单位长度 ( 3 * Float32Array.BYTES_PER_ELEMENT )
 
gl.vertexAttribPointer(positionLoc, numComponents, type, false, stride, offset);

属性可以用 floatvec2vec3vec4mat2mat3 和 mat4 数据类型。

    Uniforms 全局变量(在一次绘制中对所有顶点保持一致值)

    全局变量在一次绘制过程中传递给着色器的值都一样。

    在下面的一个简单的例子中, 用全局变量给顶点着色器添加了一个偏移量

    attribute vec4 a_position;
    uniform vec4 u_offset;
     
    void main() {
       gl_Position = a_position + u_offset;
    }

    现在可以把所有顶点偏移一个固定值,首先在初始化时找到全局变量的地址 

    var offsetLoc = gl.getUniformLocation(someProgram, "u_offset");

    然后在绘制前设置全局变量

    gl.uniform4fv(offsetLoc, [1, 0, 0, 0]);  // 向右偏移一半屏幕宽度

    要注意的是全局变量属于单个着色程序,如果多个着色程序有同名全局变量,需要找到每个全局变量并设置自己的值。 我们调用gl.uniform???的时候只是设置了当前程序的全局变量,当前程序是传递给gl.useProgram 的最后一个程序

    纹理(顶点着色器中)

    同 Textures 纹理(在片段着色器中)。

    片段着色器

    ​​​​​​​一个片段着色器的工作是为当前光栅化的像素提供颜色值,通常是以下的形式

    precision mediump float;
     
    void main() {
       gl_FragColor = doMathToMakeAColor;
    }

    每个像素都将调用一次片段着色器,每次调用需要从特殊全局变量gl_FragColor中获取颜色信息

    Uniform 全局变量(片段着色器中)

    同 Uniforms 全局变量.

    Textures 纹理(片段着色器中 来自 Pixels/Texel 的数据)

    在着色器中获取纹理信息,可以先创建一个sampler2D类型全局变量,然后用GLSL方法texture2D 从纹理中提取信息。

    precision mediump float;
     
    uniform sampler2D u_texture;
     
    void main() {
       vec2 texcoord = vec2(0.5, 0.5);  // 获取纹理中心的值
       gl_FragColor = texture2D(u_texture, texcoord);
    }

    从纹理中获取的数据取决于很多设置。 至少要创建并给纹理填充数据,例如

    var tex = gl.createTexture();
    gl.bindTexture(gl.TEXTURE_2D, tex);
    var level = 0;
    var width = 2;
    var height = 1;
    var data = new Uint8Array([
       255, 0, 0, 255,   // 一个红色的像素
       0, 255, 0, 255,   // 一个绿色的像素
    ]);
    gl.texImage2D(gl.TEXTURE_2D, level, gl.RGBA, width, height, 0, gl.RGBA, gl.UNSIGNED_BYTE, data);
    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);

    在初始化时找到全局变量的地址

    var someSamplerLoc = gl.getUniformLocation(someProgram, "u_texture");

    在渲染的时候WebGL要求纹理必须绑定到一个纹理单元上

    var unit = 5;  // 挑选一个纹理单元
    gl.activeTexture(gl.TEXTURE0 + unit);
    gl.bindTexture(gl.TEXTURE_2D, tex);

    然后告诉着色器你要使用的纹理在那个纹理单元

    gl.uniform1i(someSamplerLoc, unit);

    Varyings 可变量(从 Vertex Shader 传递并插值的数据)

    在工作原理提到过,可变量是一种顶点着色器给片段着色器传值的方式。

    为了使用可变量,要在两个着色器中定义同名的可变量。 给顶点着色器中可变量设置的值,会作为参考值进行内插,在绘制像素时传给片段着色器的可变量。

    顶点着色器

    attribute vec4 a_position;
     
    uniform vec4 u_offset;
     
    varying vec4 v_positionWithOffset;
     
    void main() {
      gl_Position = a_position + u_offset;
      v_positionWithOffset = a_position + u_offset;
    }

    片段着色器

    precision mediump float;
     
    varying vec4 v_positionWithOffset;
     
    void main() {
      // 从裁剪空间 (-1 <-> +1) 转换到颜色空间 (0 -> 1).
      vec4 color = v_positionWithOffset * 0.5 + 0.5;
      gl_FragColor = color;
    }

    上方的示例几乎没有意义,通常情况下直接将裁剪空间的值传给片段着色器当作颜色值是没有意义的, 虽然它可以运行并且可以生成颜色值。

    GLSL

    GLSL全称是 Graphics Library Shader Language (图形库着色器语言),是着色器使用的语言。 它有一些不同于JavaScript的特性,主要目的是为栅格化图形提供常用的计算功能。

    所以它内建的数据类型例如vec2vec3和 vec4分别代表两个值,三个值和四个值, 类似的还有mat2mat3 和 mat4 分别代表 2x2, 3x3 和 4x4 矩阵。 你可以做一些运算例如常量和矢量的乘法

    之后的一些调用方法 以及书写规则等可自行查看,在此就不在赘述

    参考: 

    WebGL 着色器和GLSL

    18.WebGL渲染和执行流程 | 前端技术积累

    本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2377587.html

    如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

    相关文章

    华为OD机试真题——通信系统策略调度(用户调度问题)(2025B卷:100分)Java/python/JavaScript/C/C++/GO最佳实现

    2025 B卷 100分 题型 本专栏内全部题目均提供Java、python、JavaScript、C、C++、GO六种语言的最佳实现方式; 并且每种语言均涵盖详细的问题分析、解题思路、代码实现、代码详解、3个测试用例以及综合分析; 本文收录于专栏:《2025华为OD真题目录+全流程解析+备考攻略+经验分…

    llamafactory SFT 从断点恢复训练

    背景 我使用llamafactory sft 微调模型的时候。gpu停止运行了。日志文件没有任何的报错信息。 显存还是占用状态。 查看llamafactory的进程是下述信息&#xff1a; 151312 151306 91 17:42 ? 03:58:10 [llamafactory-cl] 既然如此&#xff0c;那就只能从断点恢复训练了。 …

    计算机网络-----6分层结构

    目录 “分层” 的设计思想&#xff1a; 计算机网络要完成的功能&#xff1a; 计算机网络的分层结构&#xff1a; 网络体系结构的概念&#xff1a; 各层之间的关系&#xff1a; 数据的传输过程 水平视角&#xff1a; 垂直视角&#xff1a; 相关概念 协议三要素&#x…

    运算放大器相关的电路

    1运算放大器介绍 解释&#xff1a;运算放大器本质就是一个放大倍数很大的元件&#xff0c;就如上图公式所示 Vp和Vn相差很小但是放大后输出还是会很大。 运算放大器不止上面的三个引脚&#xff0c;他需要独立供电&#xff1b; 如图比较器&#xff1a; 解释&#xff1a;Vp&…

    python版本管理工具-pyenv轻松切换多个Python版本

    在使用python环境开发时&#xff0c;相信肯定被使用版本所烦恼&#xff0c;在用第三方库时依赖兼容的python版本不一样&#xff0c;有没有一个能同时安装多个python并能自由切换的工具呢&#xff0c;那就是pyenv&#xff0c;让你可以轻松切换多个Python 版本。 pyenv是什么 p…

    elementUI 循环出来的表单,怎么做表单校验?

    数据结构如下&#xff1a; diversionParamList: [ { length: null, positionNumber: null, value: null, } ] 思路&#xff1a;可根据 index 动态绑定 :props 属性值&#xff0c;校验规则写在:rules <div class"config-item" v-for"(item, index) in form.…

    Leetcode76覆盖最小子串

    覆盖最小子串 代码来自b站左程云 class Solution {public String minWindow(String str, String tar) {char[] s str.toCharArray();char[] t tar.toCharArray();int[] cnt new int[256];for (char cha : t) { cnt[cha]--;}int len Integer.MAX_VALUE;int debt t.length…

    电力杆塔安全监测解决方案

    一、方案背景 在台风、滑坡等自然灾害出现时&#xff0c;极易产生倒杆、断杆、杆塔倾斜、塔基滑动等致使杆塔失稳的状况&#xff0c;进而引发导线断线、线路跳闸等事故&#xff0c;给电网的安全稳定运行造成影响。可借助在铁塔上装设的传感器&#xff0c;能够感知铁塔的工作状态…

    AD 常用系统快捷键

    (1) L: 打开层设置开关选项(在元件移动状态下&#xff0c;按下“L”键换层) (2) S: 打开选择&#xff0c;如SL(线选)、SI(框选)、SE(滑动选择) (3) J: 跳转&#xff0c;如JC(跳转到元件)、JN(跳转到网络) (4) CtrlQ: 英寸和毫米相互切换。 (5) Delete: 删除已被选择的对象 E…

    今日行情明日机会——20250516

    上证缩量收阴线&#xff0c;小盘股表现相对更好&#xff0c;上涨的个股大于下跌的&#xff0c;日线已到前期压力位附近&#xff0c;注意风险。 深证缩量收假阳线&#xff0c;临近日线周期上涨末端&#xff0c;注意风险。 2025年5月16日涨停股行业方向分析 机器人概念&#x…

    AlphaEvolve:LLM驱动的算法进化革命与科学发现新范式

    AlphaEvolve&#xff1a;LLM驱动的算法进化革命与科学发现新范式 本文聚焦Google DeepMind最新发布的AlphaEvolve&#xff0c;探讨其如何通过LLM与进化算法的结合&#xff0c;在数学难题突破、计算基础设施优化等领域实现革命性进展。从48次乘法优化44矩阵相乘到数据中心资源利…

    多尺度对比度调整

    一、背景介绍 受到了前面锐化算法实现的启发&#xff0c;对高频层做增强是锐化&#xff0c;那么对中低频一起做增强&#xff0c;就应该能有局域对比度增强效果。 直接暴力实现了个基本版本&#xff0c;确实有对比度增强效果。然后搜了下关键字&#xff0c;还真找到了已经有人这…

    解决IDEA Maven编译时@spring.profiles.active@没有替换成具体环境变量的问题

    如果不加filtering true&#xff0c;编译后的文件还是 spring.profiles.active 编译前的application.yml 编译后的application.yml【环境变量没有改变】 解决方案 找到 SpringBoot 启动类所在的pom.xml&#xff0c;在 resources 增加 filtering true&#xff0c;然后重新…

    记参加一次数学建模

    题目请到全国大学生数学建模竞赛下载查看。 注&#xff1a;过程更新了很多文件&#xff0c;所有这里贴上的有些内容不是最新的&#xff08;而是草稿&#xff09;。 注&#xff1a;我们队伍并没有获奖&#xff0c;文章内容仅供一乐。 从这次比赛&#xff0c;给出以下赛前建议 …

    Maven使用详解:Maven的概述(二)

    一、核心定义与功能 Maven是由Apache软件基金会开发的开源项目管理工具&#xff0c;专为Java项目设计&#xff0c;主要用于自动化构建、依赖管理和项目标准化。其核心功能包括&#xff1a; 依赖管理&#xff1a;通过pom.xml文件声明依赖库&#xff0c;自动从中央仓库下载并管…

    新型智慧园区技术架构深度解析:数字孪生与零碳科技的融合实践

    &#x1f3ed;在杭州亚运村零碳园区&#xff0c;光伏板与氢燃料大巴构成的能源网络&#xff0c;正通过数字孪生技术实现智能调度。这不仅是格力电器与龙源电力在新能源领域的创新实践&#xff0c;更是智慧园区4.0时代的标杆案例。当AI算法开始接管能源调度&#xff0c;当BIM建模…

    Linux基础开发工具大全

    目录 软件包管理器 1>软件包 2>软件生态 3>yum操作 a.查看软件包 b.安装软件 c.卸载软件 4>知识点 vim编辑器 1>基本概念 2>基本操作 3>正常模式命令集 a.模式切换 b.移动光标 c.删除 d.复制 e.替换 f.撤销 g.更改 4>底行模式命令…

    网页工具-OTU/ASV表格物种分类汇总工具

    AI辅助下开发了个工具&#xff0c;功能如下&#xff0c;分享给大家&#xff1a; 基于Shiny开发的用户友好型网页应用&#xff0c;专为微生物组数据分析设计。该工具能够自动处理OTU/ASV_taxa表格&#xff08;支持XLS/XLSX/TSV/CSV格式&#xff09;&#xff0c;通过调用QIIME1&a…

    2025第三届盘古初赛(计算机部分)

    前言 比赛的时候时间不对&#xff0c;打一会干一会&#xff0c;导致比赛时候思路都跟不上&#xff0c;赛后简单复现一下&#xff0c;希望大家批批一下 计算机取证 1、分析贾韦码计算机检材&#xff0c;计算机系统Build版本为&#xff1f;【标准格式&#xff1a;19000】 183…

    【源码级开发】Qwen3接入MCP,企业级智能体开发实战!

    Qwen3接入MCP智能体开发实战&#xff08;上&#xff09; 一、MCP技术与Qwen3原生MCP能力介绍 1.智能体开发核心技术—MCP 1.1 Function calling技术回顾 如何快速开发一款智能体应用&#xff0c;最关键的技术难点就在于如何让大模型高效稳定的接入一些外部工具。而在MCP技术…