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_ALPHA
        format:纹理的内部格式,必须和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.mfbz.cn/a/882372.html

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

相关文章

AI浪潮新崛起:借助AI+实景/视频直播创新魅力,开启无人自动直播新时代!

AI浪潮新崛起&#xff1a;借助AI实景/视频直播创新魅力&#xff0c;开启无人自动直播新时代&#xff01; 在科技日新月异的今天&#xff0c;人工智能&#xff08;AI&#xff09;已不再仅仅是科幻电影中的桥段&#xff0c;它正以不可阻挡之势渗透到我们生活的方方面面&#xff…

力扣718-最长重复子数组(Java详细题解)

题目链接&#xff1a;718. 最长重复子数组 - 力扣&#xff08;LeetCode&#xff09; 前情提要&#xff1a; 因为本人最近都来刷dp类的题目所以该题就默认用dp方法来做。 dp五部曲。 1.确定dp数组和i下标的含义。 2.确定递推公式。 3.dp初始化。 4.确定dp的遍历顺序。 5…

【编程底层原理】Java常用读写锁的使用和原理

一、引言 在Java的并发世界中&#xff0c;合理地管理对共享资源的访问是至关重要的。读写锁&#xff08;ReadWriteLock&#xff09;正是一种能让多个线程同时读取共享资源&#xff0c;而写入资源时需要独占访问的同步工具。本文将带你了解读写锁的使用方法、原理以及它如何提高…

这8款AI论文工具帮你一键搞定!ai论文一键生成任务书

在当今学术研究和论文写作领域&#xff0c;AI技术的应用已经成为一种趋势。通过智能算法和大数据分析&#xff0c;AI工具能够帮助学者和学生提高写作效率、优化内容结构&#xff0c;并确保论文的原创性和质量。以下是8款值得推荐的AI论文工具&#xff0c;其中特别推荐千笔-AIPa…

选择排序(C语言实现)

目录 1.基本思想 2.代码实现 代码思路 代码实现 代码测试 3.复杂度分析 1&#xff09;时间复杂度 2&#xff09;空间复杂度 4.特性总结 1.基本思想 选择排序是一种简单直观的比较排序算法。该算法的基本思想是在每一轮中选出当前未排序部分的最小&#xff08;或最大&a…

通过 LabVIEW 正则表达式读取数值(整数或小数)

在LabVIEW开发中&#xff0c;字符串处理是一个非常常见的需求&#xff0c;尤其是在处理包含复杂格式的数字时。本文通过一个具体的例子来说明如何利用 Match Regular Expression Function 和 Match Pattern Function 读取并解析字符串中的数字&#xff0c;并重点探讨这两个函数…

日期和时间类【Date】【Calendar日历类】【LocalDate】Date-Time API详解

我们先来介绍一下与时间相关的基础知识。 GMT - 格林尼治标准时间&#xff08;Greenwich Mean Time&#xff09;&#xff0c;简称GMT&#xff0c;实际上与世界时UT&#xff08;universal time &#xff09;基本一致。 UTC - 协调世界时&#xff08;Universal Time Coordinated&…

matlab恢复默认窗口布局

1.点击主页&#xff0c;选择布局 2.选择默认&#xff0c;即可恢复到默认的窗口布局

Linux系统上搭建Vulhub靶场

Linux系统上搭建Vulhub靶场 ​vulhub​ 是一个开源的漏洞靶场&#xff0c;它提供了各种易受攻击的服务和应用程序&#xff0c;供安全研究人员和学习者测试和练习。要在 Linux 系统上安装和运行 vulhub​&#xff0c;可以按照以下步骤进行&#xff1a; 1. 安装 Docker 和 Docke…

C#软键盘设计字母数字按键处理相关事件函数

应用场景&#xff1a;便携式设备和检测设备等小型设备经常使用触摸屏来代替键盘鼠标的使用&#xff0c;因此在查询和输入界面的文本或者数字输入控件中使用软件盘来代替真正键盘的输入。 软键盘界面&#xff1a;软键盘界面实质上就是一个普通的窗体上面摆放了很多图片按钮&…

二叉树---java---黑马

二叉树 遍历 遍历分两种 广度优先遍历 尽可能先访问距离根节点最近的节点&#xff0c;也称之为层序遍历。 深度优先遍历 对于二叉树&#xff0c;进一步分为三种 pre-order前序遍历&#xff0c;对于每一颗子树&#xff0c;先访问该节点&#xff0c;然后是左子树&#xf…

探索RESTful风格的网络请求:构建高效、可维护的API接口【后端 20】

探索RESTful风格的网络请求&#xff1a;构建高效、可维护的API接口 在当今的软件开发领域&#xff0c;RESTful&#xff08;Representational State Transfer&#xff09;风格的网络请求已经成为构建Web服务和API接口的标配。RESTful风格以其简洁、无状态、可缓存以及分层系统等…

利用影刀实现批量发布文章的RPA流程(附视频演示)

前言 大家好&#xff0c;我是小智。在这篇文章中&#xff0c;我将分享一个实战案例&#xff0c;展示如何利用影刀实现批量发布文章的RPA流程。这里主要介绍其中一个简单步骤&#xff0c;其它步骤将通过视频演示。有使用方面的疑问可以留言。 影刀是一款强大的自动化工具&#x…

Java项目实战II基于Java+Spring Boot+MySQL的网上租贸系统设计与实现(开发文档+源码+数据库)

目录 一、前言 二、技术介绍 三、系统实现 四、论文参考 五、核心代码 六、源码获取 全栈码农以及毕业设计实战开发&#xff0c;CSDN平台Java领域新星创作者&#xff0c;专注于大学生项目实战开发、讲解和毕业答疑辅导。获取源码联系方式请查看文末 一、前言 "随着…

简单的云存储靶场

搭建靶场 我这里使用tx云&#xff0c;请自行搭建 https://shuihui2211-1329809954.cos.ap-nanjing.myqcloud.com 复现 私有读写 访问权限为私有读写时&#xff0c;我们访问url则会出现如下提示 目录遍历 漏洞成因 将policy权限设置为所有操作时 复现 我这里上传了一…

java-----异常

目录 异常&#xff1a;代表程序出现的问题 运行时异常和编译时异常的区别&#xff1f; 异常的作用&#xff1a; 异常的处理方式: 异常中常见的方法: 抛出异常: 自定义异常: 异常&#xff1a;代表程序出现的问题 Exception:叫做异常&#xff0c;代表程序可能出现的问题。…

Python 连接mysql数据库,并且执行查询

之前一直在写Java&#xff0c;但是随着python的崛起&#xff0c;自己也被慢慢的带入到了这样的一个阵营&#xff0c;学习python&#xff0c;了解机器学习 曾经有一个.... 不谈曾经&#xff0c;现在的我是一个小菜鸟&#xff0c;用学习Java实现业务的需求来学习python 项目的目…

科研绘图系列:R语言树结构聚类热图(cluster heatmap)

文章目录 介绍加载R包导入数据数据预处理画图修改图形导出数据系统信息介绍 热图结合树结构展示聚类结果通常用于展示数据集中的模式和关系,这种图形被称为聚类热图或层次聚类热图。在这种图中,热图部分显示了数据矩阵的颜色编码值,而树结构(通常称为树状图或聚类树)则显…

iptables限制网速

1、使用hashlimit来限速 #从eth0网卡进入INPUT链数据&#xff0c;使用模块hashlimit 限制网速为100kb/s或2mb/s,超过限制的数据包会被DROP。OUTPUT链同理&#xff0c;mode为srcip&#xff0c;有4个mode选项: srcip&#xff08;默认匹配每个源地址IP&#xff0c;配置指定源地址…

计算机网络33——文件系统

1、chmod 2、chown 需要有root权限 3、link 链接 4、unlink 创建临时文件&#xff0c;用于非正常退出 5、vi vi可以打开文件夹 ../是向外一个文件夹 6、ls ls 可以加很多路径&#xff0c;路径可以是文件夹&#xff0c;也可以是文件 ---------------------------------…