(七)WebGL中varying和attribute使用详解

在WebGL中,varyingattribute是着色器程序中的两个重要概念,分别用于在顶点着色器(Vertex Shader)和片段着色器(Fragment Shader)之间传递数据。它们在图形渲染流程中扮演着关键角色,理解它们的区别和使用方式对于开发者正确编写着色器程序至关重要。

1. attribute的使用

attribute是顶点着色器中的一种变量,用于存储每个顶点的输入数据。attribute通常是与顶点相关的,例如顶点的位置、颜色、法线、纹理坐标等。

在WebGL中,attribute数据一般通过buffer传递给GPU。这些数据是每个顶点的属性,每次绘制调用时,都会传入一个不同的值。

示例:顶点着色器使用attribute
// 顶点着色器
attribute vec4 a_position;  // 顶点位置
attribute vec4 a_color;     // 顶点颜色

varying vec4 v_color;       // 将颜色传递给片段着色器

void main() {
  gl_Position = a_position;  // 将位置传递给内建变量gl_Position
  v_color = a_color;         // 将颜色传递给片段着色器
}

在这个示例中:

  • a_positiona_colorattribute变量,分别代表每个顶点的位置信息和颜色信息。
  • v_colorvarying变量,用于传递数据到片段着色器。

2. varying的使用

varying是顶点着色器与片段着色器之间传递数据的桥梁。它允许从顶点着色器将数据传递到片段着色器。每个varying变量在顶点着色器和片段着色器中都有声明,它的值会在顶点着色器执行时被计算,并在片段着色器中使用。

示例:片段着色器使用varying
// 片段着色器
precision mediump float;

varying vec4 v_color;  // 从顶点着色器接收到的颜色

void main() {
  gl_FragColor = v_color;  // 设置片段的颜色
}

在这个示例中:

  • v_color是从顶点着色器传递过来的数据,包含了每个顶点的颜色。
  • 片段着色器使用v_color来为每个片段(像素)设置颜色。

3. attributevarying的区别

特性attributevarying
作用顶点着色器的输入,代表每个顶点的属性顶点着色器和片段着色器之间的数据传递
数据来源由CPU通过buffer传递给GPU从顶点着色器传递到片段着色器
是否每个顶点不同每个顶点有不同的值每个片段(像素)会接收不同的值,但相同的片段来自相同的插值
类型由顶点数据定义,如vec3, vec4attribute类型一致

4. 典型的使用场景

  • attribute的常见使用场景:

    • 顶点位置:每个顶点的位置坐标(a_position)。
    • 法线:用于计算光照效果,顶点的法向量(a_normal)。
    • 纹理坐标:定义顶点处的纹理坐标,用于纹理映射(a_texCoord)。
    • 颜色:顶点的颜色(a_color)。
  • varying的常见使用场景:

    • 插值计算:当需要进行插值计算时,使用varying变量传递数据,比如平滑的颜色渐变。
    • 光照计算:在顶点着色器中计算法线信息,然后通过varying传递到片段着色器进行光照计算。
    • 纹理映射:顶点着色器传递纹理坐标到片段着色器进行纹理采样。

5. 完整代码示例:简单的彩色三角形渲染

下面是一个简单的WebGL渲染代码,其中包含了如何使用attributevarying来渲染一个带有颜色的三角形。

HTML部分:
<canvas id="webglCanvas" width="500" height="500"></canvas>
JavaScript部分:
// 获取WebGL上下文
const canvas = document.getElementById("webglCanvas");
const gl = canvas.getContext("webgl");

if (!gl) {
    console.log("WebGL未能初始化");
}

// 顶点着色器代码
const vsSource = `
    attribute vec4 a_position;  // 顶点位置
    attribute vec4 a_color;     // 顶点颜色
    varying vec4 v_color;       // 传递颜色到片段着色器

    void main() {
        gl_Position = a_position;
        v_color = a_color;
    }
`;

// 片段着色器代码
const fsSource = `
    precision mediump float;
    varying vec4 v_color;  // 从顶点着色器接收到的颜色

    void main() {
        gl_FragColor = v_color;  // 设置片段的颜色
    }
`;

// 创建着色器程序
function createShaderProgram(gl, vsSource, fsSource) {
    const vs = createShader(gl, gl.VERTEX_SHADER, vsSource);
    const fs = createShader(gl, gl.FRAGMENT_SHADER, fsSource);
    const program = gl.createProgram();
    gl.attachShader(program, vs);
    gl.attachShader(program, fs);
    gl.linkProgram(program);

    if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
        console.error("无法链接着色器程序:", gl.getProgramInfoLog(program));
        return null;
    }

    gl.useProgram(program);
    return program;
}

function createShader(gl, type, source) {
    const shader = gl.createShader(type);
    gl.shaderSource(shader, source);
    gl.compileShader(shader);
    
    if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
        console.error("着色器编译失败:", gl.getShaderInfoLog(shader));
        return null;
    }
    
    return shader;
}

// 顶点数据
const vertices = new Float32Array([
    0.0,  0.5,  0.0,   1.0, 0.0, 0.0,  // 顶点1:位置 + 颜色(红色)
   -0.5, -0.5,  0.0,   0.0, 1.0, 0.0,  // 顶点2:位置 + 颜色(绿色)
    0.5, -0.5,  0.0,   0.0, 0.0, 1.0   // 顶点3:位置 + 颜色(蓝色)
]);

// 创建和绑定缓冲区
const vertexBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);

// 获取着色器程序中的属性位置
const program = createShaderProgram(gl, vsSource, fsSource);
const positionLocation = gl.getAttribLocation(program, "a_position");
const colorLocation = gl.getAttribLocation(program, "a_color");

// 启用属性
gl.vertexAttribPointer(positionLocation, 3, gl.FLOAT, false, 6 * Float32Array.BYTES_PER_ELEMENT, 0);
gl.vertexAttribPointer(colorLocation, 3, gl.FLOAT, false, 6 * Float32Array.BYTES_PER_ELEMENT, 3 * Float32Array.BYTES_PER_ELEMENT);
gl.enableVertexAttribArray(positionLocation);
gl.enableVertexAttribArray(colorLocation);

// 清除屏幕并绘制三角形
gl.clear(gl.COLOR_BUFFER_BIT);
gl.clearColor(0.0, 0.0, 0.0, 1.0); // 背景色为黑色
gl.drawArrays(gl.TRIANGLES, 0, 3);
解释:
  • 顶点着色器a_position表示顶点的坐标,a_color表示顶点的颜色。varying v_color将颜色传递给片段着色器。
  • 片段着色器:从顶点着色器接收到v_color,并将其设置为片段的最终颜色。
  • JavaScript部分:创建WebGL上下文,编译着色器,绑定顶点数据并设置属性指针,最后

绘制一个带有颜色渐变的三角形。

总结

  • attribute用于存储每个顶点的输入数据,如位置、法线、颜色等。
  • varying用于在顶点着色器和片段着色器之间传递数据,通常用于颜色插值、光照计算等场景。
  • attribute只在顶点着色器中使用,varying则在顶点着色器和片段着色器之间共享。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Unity学习笔记(六)使用状态机重构角色移动、跳跃、冲刺

前言 本文为Udemy课程The Ultimate Guide to Creating an RPG Game in Unity学习笔记 整体状态框架(简化) Player 是操作对象的类&#xff1a; 继承了 MonoBehaviour 用于定义游戏对象的行为&#xff0c;每个挂载在 Unity 游戏对象上的脚本都需要继承自 MonoBehaviour&#x…

AIDD-人工智能药物设计-AlphaFold系列:全面回顾AF1-3的关键研究成果及其对科学界的影响

AlphaFold系列&#xff1a;全面回顾AF1-3的关键研究成果及其对科学界的影响 本文章将围绕 AlphaFold 系列模型在蛋白质结构预测领域的前沿研究展开&#xff0c;重点介绍 AlphaFold1、AlphaFold2 与 AlphaFold3 的关键研究成果&#xff0c;以及它们对科学界和制药工业的深远影响…

Pandas-RFM会员价值度模型

文章目录 一. 会员价值度模型介绍二. RFM计算与显示1. 背景2. 技术点3. 数据4. 代码① 导入模块② 读取数据③ 数据预处理Ⅰ. 数据清洗, 即: 删除缺失值, 去掉异常值.Ⅱ. 查看清洗后的数据Ⅲ. 把前四年的数据, 拼接到一起 ④ 计算RFM的原始值⑤ 确定RFM划分区间⑥ RFM计算过程⑦…

Git 入门指南:如何高效管理你的代码库

文章目录 Git 的介绍安装 Git创建仓库Git 三板斧addcommitpush 冲突问题常用 Git 指令 Git 的介绍 Git 是一个分布式版本控制系统&#xff0c;用于跟踪文件的变化并支持团队协作开发。最初由 Linus Torvalds&#xff08;Linux 操作系统的创始人&#xff09;开发&#xff0c;Gi…

execl条件比较两个sheet每个单元格的值

1.把对比的sheet复制到对比文件中 2.选择首个单元格 3.新建规则 4.选择公式 5.编写公式 A3<>Sheet1!A36.选择差异颜色 7.选择应用范围 $1:$655368.选择应用范围

2025新年源码免费送

2025很开门很开门的源码免费传递。不需要馒头就能获取4套大开门源码。 听泉偷宝&#xff0c;又进来偷我源码啦&#x1f44a;&#x1f44a;&#x1f44a;。欢迎偷源码 &#x1f525;&#x1f525;&#x1f525; 获取免费源码以及更多源码&#xff0c;可以私信联系我 我们常常…

本地LLM部署--Open WebUI(多媒体工具FFMPEG作用)

OpenWebUI 和 FFmpeg 的关系主要体现在 多媒体处理需求 上。OpenWebUI 是一个基于 Web 的接口项目&#xff0c;提供与各种 AI 模型交互的功能&#xff0c;而 FFmpeg 则是一种多媒体处理工具&#xff0c;用于处理音视频数据。二者的关系主要体现为 依赖和功能互补&#xff0c;具…

使用双向链表优化数组操作的性能

&#x1f3ac; 江城开朗的豌豆&#xff1a;个人主页 &#x1f525; 个人专栏 :《 VUE 》 《 javaScript 》 &#x1f4dd; 个人网站 :《 江城开朗的豌豆&#x1fadb; 》 ⛺️ 生活的理想&#xff0c;就是为了理想的生活 ! 目录 背景 双向链表的优势 实现方案 性能优化 …

Inno Setup制作安装包,安装给win加环境变量

加 ; 加环境变量&#xff0c;开启&#xff0c;下面一行 ChangesEnvironmentyes 和 ; 加环境变量wbrj变量名&#xff0c;{app}\project\bin变量值&#xff0c;{app}\后接文件名&#xff0c;{app}表示安装路径。下面一行,{olddata};原来的值上拼接 Root: HKLM; Subkey: “SYSTEM\…

积分与签到设计

积分 在交互系统中&#xff0c;可以通过看视频、发评论、点赞、签到等操作获取积分&#xff0c;获取的积分又可以参与排行榜、兑换优惠券等&#xff0c;提高用户使用系统的积极性&#xff0c;实现引流。这些功能在很多项目中都很常见&#xff0c;关于功能的实现我的思路如下。 …

Taro+Vue实现图片裁剪组件

cropper-image-taro-vue3 组件库 介绍 cropper-image-taro-vue3 是一个基于 Vue 3 和 Taro 开发的裁剪工具组件&#xff0c;支持图片裁剪、裁剪框拖动、缩放和输出裁剪后的图片。该组件适用于 Vue 3 和 Taro 环境&#xff0c;可以在网页、小程序等平台中使用。 源码 https:…

AI赋能服装零售:商品计划智能化,化危机为转机

在服装零售这片竞争激烈的战场上&#xff0c;每一个细微的决策都可能成为品牌兴衰的关键。当市场波动、消费者口味变化、供应链挑战接踵而至时&#xff0c;许多品牌往往将危机归咎于外部环境。然而&#xff0c;真相往往更为深刻——“危机不是外部的&#xff0c;而是你的商品计…

Flutter:吸顶效果

在分页中&#xff0c;实现tab吸顶。 TDNavBar的screenAdaptation: true, 开启屏幕适配。 该属性已自动对不同手机状态栏高度进行适配。我们只需关注如何实现吸顶。 view import package:ducafe_ui_core/ducafe_ui_core.dart; import package:flutter/material.dart; import p…

企业级PHP异步RabbitMQ协程版客户端 2.0 正式发布

概述 workerman/rabbitmq 是一个异步RabbitMQ客户端&#xff0c;使用AMQP协议。 RabbitMQ是一个基于AMQP&#xff08;高级消息队列协议&#xff09;实现的开源消息组件&#xff0c;它主要用于在分布式系统中存储和转发消息。RabbitMQ由高性能、高可用以及高扩展性出名的Erlan…

信号弱开启手机Wifi通话,MIUI显示/隐藏5G开关的方法

1.开启手机Wi-Fi通话&#xff0c;提升无信号或弱信号时的通话质量 Wi-Fi 通话(Wi-Fi calling)&#xff0c;又称VoWiFi&#xff0c;是一项名为“ Voice over Wi-Fi ”的服务&#xff0c;它允许手机用户使用他们的智能手机使用 Wi-Fi网络拨打电话&#xff0c;即在Wi-Fi环境下就能…

Echarts的认识和基本用法

Echarts介绍和使用 Echarts介绍 官网地址&#xff1a;Apache ECharts Echarts是一个基于JavaScript的开源可视化图表库&#xff0c;由百度前端开发团队研发和维护。它提供了丰富的图表类型、数据统计分析、动态数据更新、多维数据展示等功能&#xff0c;可以帮助开发人员在 W…

在JavaScript开发中,如何判断对象自身为空?

前言 如何判断一个对象为空是我们在开发中经常会遇到的问题&#xff0c;今天我们来聊聊几种经常使用的方法&#xff0c;以及在不同的场景下我们如何去使用。 1. JSON.stringify JSON.stringify 方法可以使对象序列化&#xff0c;转为相应的 JSON 格式。 const obj {};cons…

大语言模型训练的数据集从哪里来?

继续上篇文章的内容说说大语言模型预训练的数据集从哪里来以及为什么互联网上的数据已经被耗尽这个说法并不专业&#xff0c;再谈谈大语言模型预训练数据集的优化思路。 1. GPT2使用的数据集是WebText&#xff0c;该数据集大概40GB&#xff0c;由OpenAI创建&#xff0c;主要内…

Wireshark 学习笔记1

1.wireshark是什么 wireshark是一个可以进行数据包的捕获和分析的软件 2.基本使用过程 &#xff08;1&#xff09;选择合适的网卡 &#xff08;2&#xff09;开始捕获数据包 &#xff08;3&#xff09;过滤掉无用的数据包 &#xff08;4&#xff09;将捕获到的数据包保存为文件…

RK3568平台(USB篇)禁用USB端口

一.linux中怎样查看usb的端口号 在USB口插入U盘: [ 198.141319][ T106] usb 3-1.3: new SuperSpeed Gen 1 USB device number 5 using xhci-hcd [ 198.161695][ T106] usb 3-1.3: New USB device found, idVendor=0781, idProduct=5591, bcdDevice= 1.00 [ 198.161721]…