WebGL颜色与纹理

news2024/9/23 9:00:35

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.coloradmin.cn/o/2157124.html

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

相关文章

通过docker启动ElasticSearch后为ElasticSearch设置用户和密码

文章目录 0. 前言1. 没有设置用户名和密码的情况2. 为ElasticSearch设置用户名和密码2.1 进入 ElasticSearch 容器内部2.2 修改 ElasticSearch 的配置文件2.3 设置用户名和密码 3. 在 kibana 容器中指定访问 ElasticSearch 的用户名和密码4. 设置用户名和密码后的情况4.1 访问 …

QT For Android开发-打开PPT文件

一、前言 需求&#xff1a; Qt开发Android程序过程中&#xff0c;点击按钮就打开一个PPT文件。 Qt在Windows上要打开PPT文件或者其他文件很容易。可以使用QDesktopServices打开文件&#xff0c;非常方便。QDesktopServices提供了静态接口调用系统级别的功能。 这里用的QDesk…

C语言理解 —— printf 格式化输出

目 录 printf 函数一、短整型输出二、长整型输出三、浮点型输出四、字符型输出五、字符串输出六、注意问题 printf 函数 在软件开发过程中&#xff0c;通常需要打印一些字符串信息&#xff0c;或把一些变量值输出到上位机显示。打印函数printf是最常用的。 一般格式&#xff…

架构设计笔记-5-软件工程基础知识

知识要点 按软件过程活动&#xff0c;将软件工具分为软件开发工具、软件维护工具、软件管理和软件支持工具。 软件开发工具&#xff1a;需求分析工具、设计工具、编码与排错工具。 软件维护工具&#xff1a;版本控制工具、文档分析工具、开发信息库工具、逆向工程工具、再工…

计算机毕业设计 基于Python的荣誉证书管理系统 Django+Vue 前后端分离 附源码 讲解 文档

&#x1f34a;作者&#xff1a;计算机编程-吉哥 &#x1f34a;简介&#xff1a;专业从事JavaWeb程序开发&#xff0c;微信小程序开发&#xff0c;定制化项目、 源码、代码讲解、文档撰写、ppt制作。做自己喜欢的事&#xff0c;生活就是快乐的。 &#x1f34a;心愿&#xff1a;点…

【永磁同步电机(PMSM)】 6. 矢量空间算法(SVPWM)

【永磁同步电机&#xff08;PMSM&#xff09;】 6. 矢量空间算法&#xff08;SVPWM&#xff09; 1. SVPWM 的基本原理1.1 SVPWM 的优点1.2 SVPWM 的电路拓扑1.3 连续旋转的空间矢量 2. SVPWM 的算法实现2.1 电压矢量组合方案2.2 SVPWM 的实现步骤 3. 基于 Simulink 的 SVPWM 仿…

软考高级:系统安全 -区块链特点:去中心化、开放性、自治性、安全性、匿名性

讲解 生活化例子 想象一下&#xff0c;你和朋友们玩一个共享账本的游戏。每个人都可以在账本上记账&#xff0c;没人可以单独改动账本&#xff0c;大家都可以随时查看账本内容&#xff0c;也不用再信任某个单独的人来管理账本。这就类似于区块链的工作原理。 概念讲解 去中…

软考高级:敏捷开发 SCRUM

生活化例子 想象你和朋友们要组织一场周末聚会。你们首先会决定聚会的主题、场地、时间等大方向&#xff0c;然后每个人分配不同的任务&#xff0c;比如有人负责买零食&#xff0c;有人负责准备音乐&#xff0c;有人负责布置场地。你们每天都简单沟通下进展&#xff0c;看看大…

【C++笔试强训】如何成为算法糕手Day1

学习编程就得循环渐进&#xff0c;扎实基础&#xff0c;勿在浮沙筑高台 循环渐进Forward-CSDN博客 笔试强训第一天 目录 循环渐进Forward-CSDN博客 第一题&#xff1a;两个数组的交集 暴力循环法&#xff1a; 哈希法 &#xff1a; 数组下标法&#xff1a; 第二题&#x…

“滑动窗口”思想在算法里面的应用

目录 一 无重复字符串的最长子串 链接&#xff1a;无重复字符的最长子串 1. 题目分析 解法一&#xff1a;暴力求解 借助2个“指针”&#xff1a;left &#xff0c; right 指针&#xff0c;依次固定left 指针&#xff0c;让right指针进行遍历&#xff0c;每遇到一个最大的 …

24/9/19 算法笔记 kaggle BankChurn数据分类

题目是要预测银行里什么样的客户会流失&#xff0c;流失的概率是多少 我这边先展示一下我写的二分类的算法 import numpy as np import pandas as pd import matplotlib.pyplot as plt from sklearn.model_selection import train_test_split from sklearn.linear_model impo…

亚马逊IP关联揭秘:发生ip关联如何处理

在亚马逊这一全球领先的电商平台上&#xff0c;IP关联是一个不可忽视的问题&#xff0c;尤其是对于多账号运营的卖家而言。本文将深入解析亚马逊IP关联的含义、影响以及应对策略&#xff0c;帮助卖家更好地理解和应对这一问题。 什么是亚马逊IP关联&#xff1f; 亚马逊IP关联…

awk从0学习

1. 入门 1.1 什么是 awk&#xff1f; ①Awk是一种文本处理工具&#xff0c;适用于处理结构化数据&#xff0c;例如表格数据。 ②它可以读取一个或多个文本文件&#xff0c;并执行模式扫描和处理等指定的操作。 ③基本逻辑涉及数据的提取&#xff0c;排序和计算。 ④支持复…

Leetcode 2464. 有效分割中的最少子数组数目

1.题目基本信息 1.1.题目描述 给定一个整数数组 nums。 如果要将整数数组 nums 拆分为 子数组 后是 有效的&#xff0c;则必须满足: 每个子数组的第一个和最后一个元素的最大公约数 大于 1&#xff0c;且 nums 的每个元素只属于一个子数组。 返回 nums 的 有效 子数组拆分中…

Lumos学习王佩丰Excel第十五讲:条件格式与公式

一、使用简单的条件格式 1、为特定范围的数值标记特殊颜色 条件格式-需选择设定范围&#xff08;大于/小于/介于/......&#xff09;&#xff1a; 数值会动态根据条件判断更新颜色&#xff1a; 模糊匹配&#xff0b;条件格式&#xff1a;选择包含部分文本的特殊值 2、查找重复…

linux-----进程控制

提示&#xff1a;以下是本篇文章正文内容&#xff0c;下面案例可供参考 一、fork()函数 返回值&#xff1a;子进程返回0&#xff0c;父进程返回子进程的id,出错就返回-1. fork创建子进程&#xff0c;如果父子一方发生写入时&#xff0c;就会发生写实拷贝&#xff0c;操作系统就…

专业学习|动态规划(概念、模型特征、解题步骤及例题)

一、引言 &#xff08;一&#xff09;从斐波那契数列引入自底向上算法 &#xff08;1&#xff09;知识讲解 &#xff08;2&#xff09;matlap实现递归 &#xff08;3&#xff09;带有备忘录的遗传算法 &#xff08;4&#xff09;matlap实现带有备忘录的递归算法 “&#xff1…

0基础跟德姆(dom)一起学AI 数据处理和统计分析06-数据组合和缺失值处理

* 数据组合 * concat * merge * join(了解) * 缺失值处理 * apply方法详解 --- 1.DataFrame数据组合-concat连接 * 概述 * 连接是指把某行或某列追加到数据中, 数据被分成了多份可以使用连接把数据拼接起来 * 把计算的结果追加到现有数据集&#xff0c;也可以使用连…

Redis:常用命令总结

目录 1 . 前置内容 1.1 基本全局命令 KEYS EXISTS DEL EXPIRE TTL TYPE 1.2 数据结构和内部编码 2. String类型 SET GET MGET MSET INCR INCRBY DECR DECRBY INCRBYFLOAT 命令小结​编辑 内部编码 3 . Hash 哈希类型 HSET HGET HEXISTS HDEL HKEYS …

Qemu开发ARM篇-5、buildroot制作根文件系统并在qemu中进行挂载启动

文章目录 1、 buildroot源码获取2、buildroot配置3、buildroot编译4、挂载根文件系统 在上一篇 Qemu开发ARM篇-4、kernel交叉编译运行演示中&#xff0c;我们编译了kernel&#xff0c;并在qemu上进行了运行&#xff0c;但到最后&#xff0c;在挂载根文件系统时候&#xff0c;挂…