WebGL颜色与纹理

WEBGL中的着色器变量包括以下种类:

  • 属性变量(Attribute Variables):这些变量用于接收从应用程序中传递的顶点数据,比如顶点位置和颜色,是只读的不可修改。
  • 统一变量(Uniform Variables):这些变量是着色器中的全局变量,用于接收从应用程序中传递的值,比如投影矩阵,旋转矩阵等。
  • 纹理坐标变量(Texture Coordinate Variables):这些变量用于指定在纹理图像中采样的位置。
  • 法线向量变量(Normal Vector Variables):这些变量用于计算光照效果,用于标识几何体表面的法向量。
  • 输出变量(Output Variables):这些变量用于将着色器的输出传递给渲染管线的下一阶段,比如像素着色器的颜色值。

一、varying变量

1.varying变量定义

在WebGL中,varying变量是在顶点着色器和片元着色器之间传递数据的一种特殊类型的变量。它们被用于在顶点着色器和片元着色器之间传递信息,以便在渲染过程中进行插值。在顶点着色器中,varying变量的值被计算并传递到片元着色器中,然后在片元着色器中进行插值,然后被用来确定要绘制的像素的颜色。

Varying变量通常被用于将光照和纹理坐标等信息从顶点着色器传递到片元着色器中。由于它们是在渲染过程中插值的,所以它们可以用来创建平滑的过渡,使得渲染出来的图像更加真实和细腻。

例如,如果你想在三角形中使用纹理映射,那么你需要将纹理坐标从顶点着色器传递到片元着色器中。你可以通过定义一个varying变量来传递这个纹理坐标,然后在片元着色器中使用它来获取纹理的颜色,从而创建一个真实的纹理映射效果。

2.varying执行流程

在WebGL中,varying变量用于在顶点着色器和片元着色器之间传递数据。它们的执行原理如下:

  1. 在顶点着色器中声明一个varying变量,并对其进行赋值。
  2. 这个varying变量的值会被传递到片元着色器中。
  3. 在片元着色器中,可以通过读取这个varying变量的值来进行后续的计算。
  4. 由于每个像素都会执行片元着色器,因此varying变量的值也会被相应地插值,以便在不同像素之间进行平滑的过渡。
  5. 最终的像素颜色将由片元着色器中的计算结果和其他因素(如光照)共同决定。

varying变量的执行原理是通过在顶点着色器和片元着色器之间传递数据,使得像素颜色可以根据这些数据进行计算。
在这里插入图片描述

3.使用varying绘制彩色三角形

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>varying变量</title><script src="../../lib/index.js"></script><style>* {margin: 0;padding: 0;}canvas {margin: 50px auto 0;display: block;background: yellow;}</style>
</head>
<body><canvas id="canvas" width="400" height="400">此浏览器不支持webGL</canvas>
</body>
</html><script>const ctx = document.getElementById('canvas')const gl = ctx.getContext('webgl');//着色器//创建着色器源码const VERTEX_SHADER_SOURCE = `attribute vec4 aPosition;//需要同时在顶点和片元着色器中声明,将数据从顶点着色器传递到片元着色器varying vec4 vColor;void main(){vColor = aPosition;//要绘制的坐标gl_Position = aPosition;//要绘制的大小(着色器变量使用的是浮点型)gl_PointSize = 10.0;}`; //顶点着色器const FRAGMENT_SHADER_SOURCE = `precision lowp float;varying vec4 vColor;void main(){//要绘制的颜色gl_FragColor = vColor;}`; //片元着色器const program =  initShader(gl,VERTEX_SHADER_SOURCE,FRAGMENT_SHADER_SOURCE)const aPosition = gl.getAttribLocation(program, 'aPosition')const points = new Float32Array([-0.5,-0.5,0.5,-0.5,0.0,0.5,])const buffer = gl.createBuffer();gl.bindBuffer(gl.ARRAY_BUFFER,buffer);gl.bufferData(gl.ARRAY_BUFFER,points,gl.STATIC_DRAW)gl.vertexAttribPointer(aPosition,2,gl.FLOAT,false,0,0);gl.enableVertexAttribArray(aPosition)gl.drawArrays(gl.TRIANGLES,0,3)</script>

在这里插入图片描述

二、使用纹理渲染图片背景

1.创建纹理对象

纹理对象主要用于存储纹理图像数据。

const texture = gl.createTexture();

同时也可以通过gl.deleteTexture(texture)来删除纹理对象。

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>渲染图片背景</title><script src="../../lib/index.js"></script><style>* {margin: 0;padding: 0;}canvas {margin: 50px auto 0;display: block;background: yellow;}</style>
</head>
<body><canvas id="canvas" width="400" height="400">此浏览器不支持webGL</canvas>
</body>
</html><script>const ctx = document.getElementById('canvas')const gl = ctx.getContext('webgl');//着色器//创建着色器源码const VERTEX_SHADER_SOURCE = `attribute vec4 aPosition;attribute vec4 aTex;varying vec2 vTex;void main(){//要绘制的坐标gl_Position = aPosition;vTex = vec2(aTex.x,aTex.y);}`; //顶点着色器const FRAGMENT_SHADER_SOURCE = `precision lowp float;uniform sampler2D uSampler;//纹理坐标varying vec2 vTex;void main(){//要绘制的颜色gl_FragColor = texture2D(uSampler,vTex);}`; //片元着色器const program =  initShader(gl,VERTEX_SHADER_SOURCE,FRAGMENT_SHADER_SOURCE)const aPosition = gl.getAttribLocation(program, 'aPosition')const aTex = gl.getAttribLocation(program, 'aTex')const uSampler = gl.getUniformLocation(program, 'uSampler')const points = new Float32Array([-0.5,0.5,0.0,1.0,-0.5,-0.5,0.0,0.0,0.5,0.5,1.0,1.0,0.5,-0.5,1.0,0.0,])const buffer = gl.createBuffer();const BYTES = points.BYTES_PER_ELEMENT;gl.bindBuffer(gl.ARRAY_BUFFER,buffer);gl.bufferData(gl.ARRAY_BUFFER,points,gl.STATIC_DRAW)gl.vertexAttribPointer(aPosition,2,gl.FLOAT,false,BYTES*4,0);gl.vertexAttribPointer(aTex,2,gl.FLOAT,false,BYTES*4,BYTES*2);gl.enableVertexAttribArray(aPosition)gl.enableVertexAttribArray(aTex)const img = new Image();img.onload = function(){console.log("加载图片",img)//创建纹理图像存储纹理数据const texture = gl.createTexture();//翻转 图片 Y轴gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL,1)//开启一个纹理单元gl.activeTexture(gl.TEXTURE0);//绑定纹理对象gl.bindTexture(type,texture)/*type有两种类型gl.TEXTURE_2D:二维纹理gl.TEXTURE_CUBE_MAP:立方体纹理*/gl.bindTexture(gl.TEXTURE_2D,texture);//处理放大缩小的逻辑gl.texParamteri(type,pname,param)/*type 同上pname:gl.TEXTURE_MAG_FILTER 放大gl.TEXTURE_MIN_FILTER 缩小gl.TEXTURE_WRAP_S 横向(水平填充)gl.TEXTURE_WRAP_T 纵向(垂直填充)param:设置给放大和缩小的有 gl.NEAREST 使用像素颜色值gl.LINEAR 使用四周的加权平均值设置给填充的有  gl.REPEAT 平铺重复gl.MIRRORED_REPEAT 镜像对称 gl.CLAMP_TO_EDGE 边缘延伸                */gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_MAG_FILTER,gl.LINEAR);gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_MIN_FILTER,gl.LINEAR);//水平垂直的填充模式gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_WRAP_S,gl.CLAMP_TO_EDGE);gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_WRAP_T,gl.CLAMP_TO_EDGE);//配置纹理图集gl.texImage2D(type,level,internalformat,format,dataType,image)/*internalformat:图像的内部格式 gl.RGB, gl.RGBA,gl.ALPHA,gl.LUMINANCE(使用物体表面的红绿蓝分量的加权平均值来计算),gl.LUMINANCE_ALPHAformat:纹理的内部格式,必须和internalformat相同dataType: 纹理的数据类型 gl.UNSIGNED_BYTE,gl.UNSIGNED_SHORT_5_6_5,gl.UNSIGNED_SHORT_4_4_4_4,gl.UNSIGNED_SHORT_5_5_5_1,*/gl.texImage2D(gl.TEXTURE_2D,0,gl.RGB,gl.RGB,gl.UNSIGNED_BYTE,img);gl.uniform1i(uSampler,0)gl.drawArrays(gl.TRIANGLE_STRIP,0,4)}img.src = "../../picture/test.jpg";</script>

在这里插入图片描述

三、使用多重纹理

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>使用多重纹理</title><script src="../../lib/index.js"></script><style>* {margin: 0;padding: 0;}canvas {margin: 50px auto 0;display: block;background: yellow;}</style>
</head>
<body><canvas id="canvas" width="400" height="400">此浏览器不支持webGL</canvas>
</body>
</html><script>const ctx = document.getElementById('canvas')const gl = ctx.getContext('webgl');//着色器//创建着色器源码const VERTEX_SHADER_SOURCE = `attribute vec4 aPosition;attribute vec4 aTex;varying vec2 vTex;void main(){//要绘制的坐标gl_Position = aPosition;vTex = vec2(aTex.x,aTex.y);}`; //顶点着色器const FRAGMENT_SHADER_SOURCE = `precision lowp float;uniform sampler2D uSampler1;uniform sampler2D uSampler2;//纹理坐标varying vec2 vTex;void main(){vec4 c1 = texture2D(uSampler1,vTex);vec4 c2 = texture2D(uSampler2,vTex);gl_FragColor = c1*c2;}`; //片元着色器const program =  initShader(gl,VERTEX_SHADER_SOURCE,FRAGMENT_SHADER_SOURCE)const aPosition = gl.getAttribLocation(program, 'aPosition')const aTex = gl.getAttribLocation(program, 'aTex')const uSampler1 = gl.getUniformLocation(program, 'uSampler1')const uSampler2 = gl.getUniformLocation(program, 'uSampler2')const points = new Float32Array([-0.5,0.5,0.0,1.0,-0.5,-0.5,0.0,0.0,0.5,0.5,1.0,1.0,0.5,-0.5,1.0,0.0,])const buffer = gl.createBuffer();const BYTES = points.BYTES_PER_ELEMENT;gl.bindBuffer(gl.ARRAY_BUFFER,buffer);gl.bufferData(gl.ARRAY_BUFFER,points,gl.STATIC_DRAW)gl.vertexAttribPointer(aPosition,2,gl.FLOAT,false,BYTES*4,0);gl.vertexAttribPointer(aTex,2,gl.FLOAT,false,BYTES*4,BYTES*2);gl.enableVertexAttribArray(aPosition)gl.enableVertexAttribArray(aTex)Promise.all([getImage(gl,"../../picture/test.jpg",uSampler1,0),getImage(gl,"../../picture/test2.jpeg",uSampler2,1)]).then(()=>{gl.drawArrays(gl.TRIANGLE_STRIP,0,4)})</script>

要叠加的图片
请添加图片描述

在这里插入图片描述

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

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

相关文章

STM32篇:开发环境安装

编程语言&#xff1a;C语言 需要安装的软件有两个&#xff1a;Keil5 和 STM32CubeMX 一.Keil5 的安装 使用 Keil4 写 STM32 代码其实也是可以&#xff0c;但需要很复杂的配置&#xff0c;不建议新手操作。 比较推荐 Keil5 编写 STM32 &#xff0c;只需要一些简单的设置就可…

定了,东湖高新区下半年中高级职称申报时间

2024年东湖高新区中级职称申报开始了&#xff0c;水测成绩上周已出&#xff0c;本周已经开始申报了&#xff0c;时间确实挺着急的。 报送材料起止时间及地点&#xff1a; &#xff08;一&#xff09;网上报名时间&#xff1a; 2024年9月14日至9月30日24:00 &#xff08;二&…

C++ | Leetcode C++题解之第429题N叉树的层序遍历

题目&#xff1a; 题解&#xff1a; class Solution { public:vector<vector<int>> levelOrder(Node* root) {if (!root) {return {};}vector<vector<int>> ans;queue<Node*> q;q.push(root);while (!q.empty()) {int cnt q.size();vector<…

C/C++中的内存管理

文章目录 前言一、C/C中的内存分布二、C语言中动态内存管理方式&#xff1a;malloc/calloc/realloc/free 三、C中的内存管理方式四、operator new与operator delete函数五、new和delete的实现原理 六、定位new表达式(placement-new) 七、malloc/free和new/delete的区别 总结 前…

django学习入门系列之第十点《A 案例: 员工管理系统15》

文章目录 15 认识Ajax15.4 ajax请求的返回值实例2&#xff1a;前端输入数据提交到后端实例3&#xff1a;传输多个数据 往期回顾 15 认识Ajax 15.4 ajax请求的返回值 一般数据交互整合的都是json格式 后端一般会返回一个JSON格式 返回json格式一般有以下两种写法 上面注释的…

【全网最全】2024年华为杯研究生数学建模A题成品论文

您的点赞收藏是我继续更新的最大动力! 一定要点击如下的卡片&#xff0c;那是获取资料的入口&#xff01; 点击链接获取群聊【2024华为杯研赛资料汇总】&#xff1a;https://qm.qq.com/q/yB6JDUTaWAhttps://qm.qq.com/q/yB6JDUTaWAA题第一问是关于如何建立一个低复杂度模型&a…

Java--File

FIle 概述 File的构造方法 > 1. 一个File对象代表硬盘中实际存在的一个文件或者目录。 > 2. 无论该路径下是否存在文件或者目录&#xff0c;都不影响File对象的创建。 代码演示&#xff1a; // 文件路径名 String pathname "D:\\aaa.txt"; File file1 new …

一些迷你型信息系统 - 2

1 Linux内核数据结构信息查询 Linux内核的数据结构众多&#xff0c;成千上万&#xff0c;做一个程序来存储查询信息&#xff1b;自己录入数据&#xff1b; 代码字段最长可录入65535个字符&#xff1b;每个字段录入时长度超限会有红色告警&#xff1b; 其他的以后想到再做&#…

5分钟快速制作高质量、美观的Excel甘特图

你是否还在为如何制作甘特图而感到苦恼&#xff1f; 是否因为甘特图制作过程繁琐、耗时过长而影响了你的工作效率&#xff1f; 是否每当任务计划发生变更时&#xff0c;都需要反复重新绘制甘特图&#xff0c;让你感到疲惫不堪&#xff1f; 又或者&#xff0c;你是否一直渴望…

【AI算法岗面试八股面经【超全整理】——NLP】

AI算法岗面试八股面经【超全整理】 概率论【AI算法岗面试八股面经【超全整理】——概率论】信息论【AI算法岗面试八股面经【超全整理】——信息论】机器学习【AI算法岗面试八股面经【超全整理】——机器学习】深度学习【AI算法岗面试八股面经【超全整理】——深度学习】NLP【A…

cmd快速进入文件夹目录下

首先&#xff0c;将文件夹直接点击左键拖动至cmd窗口中&#xff0c;就可以得到目录路径。 还有就是&#xff0c;在命令行直接敲入D:或者C:就可以在磁盘之间进行转换&#xff0c;注意冒号不要丢。 再有&#xff0c;如果进入某磁盘中的一个文件夹&#xff0c;使用cd命令。路径获取…

新质农业——水肥一体化技术

橙蜂智能公司致力于提供先进的人工智能和物联网解决方案&#xff0c;帮助企业优化运营并实现技术潜能。公司主要服务包括AI数字人、AI翻译、埃域知识库、大模型服务等。其核心价值观为创新、客户至上、质量、合作和可持续发展。 橙蜂智农的智慧农业产品涵盖了多方面的功能&…

开机容易关机难?合宙Air201资产定位模组LuatOS的PWRKEY控制来实现!

关于合宙Air201&#xff0c;我们已经发布了5期基础知识啦&#xff01;你是不是已经都学会了&#xff1f; 来来来&#xff0c;我们继续高阶学习&#xff1a;合宙Air201应用示例——PWRKEY控制关机功能 PWRKEY控制关机功能 合宙Air201资产定位模组——是一个集成超低功耗4G通信…

命名管道详解

命名管道 匿名管道应用的限制就是只能在具有共同祖先的进程间通信。如果我们想要在不相关的进程之间交换数据&#xff0c;可以使用使用FIFO文件来做这项工作&#xff0c;它被称为命名管道。命名管道是一种特殊类型的文件。 mkfifo函数 命名管道可以从命名行上创建&#xff0c…

iOS V2签名网站系统源码,开源免授权(含视频教程)

这是一款iOS签名站的开源源码&#xff0c;免去了授权&#xff0c;它支持UDID获取、软件选择以及签名码功能。 同时&#xff0c;用户可以多开APP进行安装。这是一个自主可下载的版本&#xff0c;感兴趣的用户可以自行获取。 源码下载&#xff1a;https://download.csdn.net/do…

云和恩墨携手华为,发布zCloud数据库备份管理一体机并宣布共建数据保护生态...

为期三天的第九届华为全联接大会&#xff08;HUAWEI CONNECT 2024&#xff09;于9月19日在上海世博中心&展览馆盛大召开。20日下午&#xff0c;一场围绕“全场景数据保护&#xff0c;护航数智化时代”的专题论坛举办&#xff0c;云和恩墨受邀参加&#xff0c;并期待与华为合…

【Linux的进程管理】

进程管理 Linux的进程进程的管理进程的状态不同状态的进程由不同的功能的链表进行管理Linux的进程切换和进程上下文进程调度抢占和非抢占式调度调度算法先来先服务CPU密集和I/O密集 最短作业优先调度算法高响应比优先调度算法时间片轮转调度算法时间片的长度设置 最高优先级调度…

ava总结篇系列:Java泛型Java sort用法详解

一. 泛型概念的提出&#xff08;为什么需要泛型&#xff09;&#xff1f; 首先&#xff0c;我们看下下面这段简短的代码: 1 public class GenericTest { 2 3 public static void main(String[] args) { 4 List list new ArrayList(); 5 list.add(&q…

(学习记录)使用 STM32CubeMX——GPIO引脚输出配置

学习总结&#xff1a;&#xff08;学习总结&#xff09;STM32CubeMX HAL库 学习笔记撰写心得https://blog.csdn.net/Wang2869902214/article/details/142435481 STM32F103C8T6的GPIO引脚输出配置 时钟配置 &#xff08;学习记录&#xff09;使用 STM32CubeMX——配置时钟&…

原子结构与电荷

1.原子结构与电荷 1.1 物质到底是由什么构成的 阴极射线 电磁波 电磁波 我们生活中的物质。究竟是由什么构成的呢&#xff1f;这个问题其实困扰了人们很久。 1.提出“原子”的概念 早在2400年前&#xff0c;古希腊哲学家德莫克里特就提出了原子的概念。当时他就认为&…