当前位置: 首页 > news >正文

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>

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

在这里插入图片描述

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 【制作100个unity游戏之32】unity开发属于自己的一个2d/3d桌面宠物,可以实时计算已经获取的工资
  • QT快速安装使用指南
  • Linux学习/复习2--Linux工具
  • 解决 npm ERR! node-sass 和 gyp ERR! node-gyp 报错问题
  • 蓝桥杯15届C/C++B组省赛题目
  • 【深入学习Redis丨第六篇】Redis哨兵模式与操作详解
  • 【Taro】初识 Taro
  • MyBatis系统学习(四)——MyBatis的关联映射和缓存机制
  • 摆脱困境并在 Android 手机上取回删除照片的所有解决方案
  • 使用vite+react+ts+Ant Design开发后台管理项目(一)
  • Python计算机视觉 第10章-OpenCV
  • vulnhub(12):bob 1.0.1(gpg文件解密)
  • 你了解system V的ipc底层如何设计的吗?消息队列互相通信的原理是什么呢?是否经常将信号量和信号混淆呢?——问题详解
  • 构建高可用和高防御力的云服务架构:从DDoS高防到PolarDB
  • (SERIES10)DM逻辑备份还原
  • Android开源项目规范总结
  • CNN 在图像分割中的简史:从 R-CNN 到 Mask R-CNN
  • Hibernate【inverse和cascade属性】知识要点
  • interface和setter,getter
  • Netty 框架总结「ChannelHandler 及 EventLoop」
  • Otto开发初探——微服务依赖管理新利器
  • PAT A1017 优先队列
  • REST架构的思考
  • Vue ES6 Jade Scss Webpack Gulp
  • 纯 javascript 半自动式下滑一定高度,导航栏固定
  • 从零开始的webpack生活-0x009:FilesLoader装载文件
  • 大型网站性能监测、分析与优化常见问题QA
  • 动手做个聊天室,前端工程师百无聊赖的人生
  • 欢迎参加第二届中国游戏开发者大会
  • 如何使用 OAuth 2.0 将 LinkedIn 集成入 iOS 应用
  • 通过获取异步加载JS文件进度实现一个canvas环形loading图
  • 王永庆:技术创新改变教育未来
  • 小程序滚动组件,左边导航栏与右边内容联动效果实现
  • 用Visual Studio开发以太坊智能合约
  • 【云吞铺子】性能抖动剖析(二)
  • Spring Batch JSON 支持
  • 没有任何编程基础可以直接学习python语言吗?学会后能够做什么? ...
  • ​虚拟化系列介绍(十)
  • ## 临床数据 两两比较 加显著性boxplot加显著性
  • (2024最新)CentOS 7上在线安装MySQL 5.7|喂饭级教程
  • (MATLAB)第五章-矩阵运算
  • (不用互三)AI绘画:科技赋能艺术的崭新时代
  • (附源码)springboot助农电商系统 毕业设计 081919
  • (免费领源码)Java#Springboot#mysql农产品销售管理系统47627-计算机毕业设计项目选题推荐
  • (强烈推荐)移动端音视频从零到上手(下)
  • (微服务实战)预付卡平台支付交易系统卡充值业务流程设计
  • (学习日记)2024.01.19
  • (转)h264中avc和flv数据的解析
  • .net dataexcel 脚本公式 函数源码
  • .NET DevOps 接入指南 | 1. GitLab 安装
  • .Net 知识杂记
  • .NET单元测试使用AutoFixture按需填充的方法总结
  • .net之微信企业号开发(一) 所使用的环境与工具以及准备工作
  • ::前边啥也没有
  • ??如何把JavaScript脚本中的参数传到java代码段中