Three.js-绘制矩形shader

news2024/12/23 17:50:40

在这里插入图片描述
绘制图中的嵌套矩形框

方法:

vec3 drawRect(
    vec2 st,
    vec2 center,
    float width,
    float height,
    float thickness,
    vec3 fillColor, 
    vec3 strokeColor
    )
{
    vec3 color = vec3(0);
    
    float halfWidth = width * .5;
    float halfHeight = height * .5;
    float halfTickness = thickness * .5;
    
    vec2 bottomLeft = vec2(center.x - halfWidth, center.y - halfHeight);
    vec2 topRight = vec2(center.x + halfWidth, center.y + halfHeight);
    
    //STROKE
    vec2 stroke = vec2(0.0);
    stroke += step(bottomLeft-halfTickness, st) * (1.0 - step(bottomLeft+halfTickness, st));
    stroke += step(topRight-halfTickness, st) * (1.0 - step(topRight+halfTickness, st));
    vec2 strokeLimit = step(bottomLeft-halfTickness, st) * (1.0 - step(topRight+halfTickness, st));
    stroke *= strokeLimit.x * strokeLimit.y;

    color = mix (color, strokeColor, min(stroke.x + stroke.y, 1.0));
    //
    
    //FILL
    vec2 fill = vec2(0.0);
    fill += step(bottomLeft+halfTickness, st) * (1.0 - step(topRight-halfTickness, st));
    vec2 fillLimit = step(bottomLeft+halfTickness, st) * (1.0 - step(topRight-halfTickness, st));
    fill *=  fillLimit.x * fillLimit.y;
    
    color = mix (color, fillColor, min(fill.x + fill.y, 1.0));

    return color;
}
	color += drawRect(uv,vec2(0.5),0.9,0.9,0.03,vec3(1),vec3(0));

封装自定义shader

/*
 * @Author: hongbin
 * @Date: 2023-09-02 19:16:55
 * @LastEditors: hongbin
 * @LastEditTime: 2023-09-11 12:18:54
 * @Description:根据音频频域数据 绘制矩形
 */
import * as THREE from "three";
import { autoUpdateUniform } from "./AudioMaterial";

const drawRect = `
vec3 drawRect(
    vec2 st,
    vec2 center,
    float width,
    float height,
    float thickness,
    vec3 fillColor, 
    vec3 strokeColor
    )
{
    vec3 color = vec3(0);
    
    float halfWidth = width * .5;
    float halfHeight = height * .5;
    float halfTickness = thickness * .5;
    
    vec2 bottomLeft = vec2(center.x - halfWidth, center.y - halfHeight);
    vec2 topRight = vec2(center.x + halfWidth, center.y + halfHeight);
    
    //STROKE
    vec2 stroke = vec2(0.0);
    stroke += step(bottomLeft-halfTickness, st) * (1.0 - step(bottomLeft+halfTickness, st));
    stroke += step(topRight-halfTickness, st) * (1.0 - step(topRight+halfTickness, st));
    vec2 strokeLimit = step(bottomLeft-halfTickness, st) * (1.0 - step(topRight+halfTickness, st));
    stroke *= strokeLimit.x * strokeLimit.y;

    color = mix (color, strokeColor, min(stroke.x + stroke.y, 1.0));
    //
    
    //FILL
    vec2 fill = vec2(0.0);
    fill += step(bottomLeft+halfTickness, st) * (1.0 - step(topRight-halfTickness, st));
    vec2 fillLimit = step(bottomLeft+halfTickness, st) * (1.0 - step(topRight-halfTickness, st));
    fill *=  fillLimit.x * fillLimit.y;
    
    color = mix (color, fillColor, min(fill.x + fill.y, 1.0));

    return color;
}
`;

const defaultParams = {
    /** 采用固定值0.3 还是跟随音频数据 默认矩形框一整个显示 */
    ttf: false,
    /** 线条的宽度
     * @default '0.001 + 0.001* float(i)' */
    lineWidth: "0.001 + 0.001* float(i)",
    /** 矩形框的数量 */
    count: 10,
    lightColor: new THREE.Color("#fff"),
    brightness: 1,
    transparent: false,
    sampling: 0.6,
    side: THREE.FrontSide as THREE.Side,
    columnar: false,
    columnHeight: 0.1,
    columnMargin: 0,
};
export class AudioRectMaterial extends THREE.ShaderMaterial {
    @autoUpdateUniform
    static audioTexture: THREE.DataTexture;
    static audioTextureUniforms: Array<Record<string, THREE.IUniform>> = [];

    constructor(p?: Partial<typeof defaultParams>) {
        const params = { ...defaultParams, ...p };
        const floatCount = 1 / params.count;
        params.count = Math.floor(10 / params.count);

        const uniforms = {
            iChannel0: { value: AudioRectMaterial.audioTexture },
            lightColor: {
                value: p?.lightColor || params.lightColor.clone(),
            },
            brightness: { value: params.brightness },
        };

        AudioRectMaterial.audioTextureUniforms.push(uniforms);

        const rectFrame = `
        float f =  float(i+1) * 0.${params.count} ;
        color += drawRect(uv,vec2(0.5),f,f,${params.lineWidth},back,white); `;

        const columnar = `
        color += drawRect(uv,vec2(0.5,float(${
            params.columnMargin
        }) + float(i) * float(${floatCount}) + ${
            params.columnHeight / 2
        }),1.,0.,${params.columnHeight},back,white);
        `;

        super({
            uniforms,
            vertexShader: ` 
            varying vec2 vUv;
            
            void main() {
                vUv = uv;
                vec4 modelViewPosition = modelViewMatrix * vec4(position, 1.0);
                gl_Position = projectionMatrix * modelViewPosition;
            }`,
            fragmentShader: `
            varying vec2 vUv;
            uniform sampler2D iChannel0;
            uniform vec3 lightColor;
            uniform float brightness;
            const vec3 back = vec3(0);
            const vec3 white = vec3(1);
            
            ${drawRect}
            
            void main()
            {
                ${
                    params.ttf
                        ? "float fft  = texture( iChannel0, vUv).x;"
                        : `float fft  = texture( iChannel0, vec2(${params.sampling})).x * 1.2;`
                }
                // fft = 1.;

                vec2 uv = vUv;

                int stepCount = int(fft * 10.) / ${params.count};

                vec3 color;
                for (int i = 0; i < stepCount; i++) {
                    ${params.columnar ? columnar : rectFrame}
                }
             
                gl_FragColor = vec4(color * lightColor * brightness, ${
                    params.transparent ? `color.r` : "1."
                });
            }
            `,
            transparent: params.transparent,
            side: params.side,
        });
    }
}

./AudioMaterial音频纹理 请见three.js shadertoy使用手册 - 使用音频Channel和图片Channel/将音频传入glsl shader

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

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

相关文章

《向量数据库指南》——Milvus Cloud当初为什么选择向量数据库这个赛道呢?

我们公司专注于向量数据库大约可以追溯到 2018 年左右。当时&#xff0c;向量数据库的概念并不广泛。我们的 CEO 力排众议&#xff0c;认为这个领域有巨大潜力&#xff0c;因为这与我们的愿景高度契合。我们的公司定位是构建一个能够在云上处理非结构化数据的基础设施产品。经过…

window11wifi图标没了win11wifi图标消失连不上网的三种解决方法

最近win11系统有很多小伙伴都去安装体验,不过有的小伙伴在安装完之后说自己的wifi图标消失连不上网,那么如果遇到这种情况应该怎么办呢?下面就和小编一起来看看win11wifi图标消失连不上网的三种解决方法吧。 笔记本专用Win11娱乐版 V2023 [电脑系统] 笔记本专用Win11娱乐版…

UG\NX CAM二次开发 设置2D工序部件边界 UF_CAMBND_append_bnd_from_curve

文章作者:代工 来源网站:NX CAM二次开发专栏 简介: UG\NX CAM二次开发 设置2D工序部件边界 UF_CAMBND_append_bnd_from_curve 效果: 代码: static int init_proc(UF_UI_selection_p_t select, void* user_data) { int errorCode = 0; int num_triples = 1; …

自动创建设备节点udev机制的实现过程

udev是用户空间的一个应用程序&#xff0c;在内核里面安装一个驱动时&#xff0c;需要给这个驱动创建一个结点&#xff0c;安装驱动时向用户空间提交创建结点的信息&#xff0c;udev可以拿到提交的信息&#xff0c;自动在dev下创建结点。 创建结点的逻辑放在用户空间。内核空间…

每日刷题-5

目录 一、选择题 二、算法题 1、不要二 2、把字符串转换成整数 一、选择题 1、 解析&#xff1a;printf(格式化串&#xff0c;参数1&#xff0c;参数2,.….)&#xff0c;格式化串: printf第一个参数之后的参数要按照什么格式打印&#xff0c;比如%d--->按照整形方式打印&am…

JAVA设计模式6:代理模式,用于控制对目标对象的访问

作者主页&#xff1a;Designer 小郑 作者简介&#xff1a;3年JAVA全栈开发经验&#xff0c;专注JAVA技术、系统定制、远程指导&#xff0c;致力于企业数字化转型&#xff0c;CSDN博客专家&#xff0c;阿里云社区专家博主&#xff0c;蓝桥云课讲师。 目录 一、什么是代理模式二、…

c++day5---9.12

实现一个图形类&#xff08;Shape&#xff09;&#xff0c;包含受保护成员属性&#xff1a;周长、面积&#xff0c; 公共成员函数&#xff1a;特殊成员函数书写 定义一个圆形类&#xff08;Circle&#xff09;&#xff0c;继承自图形类&#xff0c;包含私有属性&#xff1a;半径…

AMD R7 7840HS 核显 780M 性能怎么样

目录 1. 基本数据 2.性能对比 2.1对比一 2.2 对比二 3.综合 1. 基本数据 2.性能对比 2.1对比一 锐龙77840h相当于i几 答&#xff1a;类似于I7-12700H R7 7840H介于13500-13700之间。 R7 7840H是AMD锐龙旗下高性能的一款处理器&#xff0c;主要应用在主流的游戏本中。各…

教育领域数据可视化:点亮知识之路

教育领域一直以来都在不断进步和演变&#xff0c;而数据可视化技术正在为这一领域带来一场革命。在过去的几年里&#xff0c;教育者们越来越意识到&#xff0c;通过将教育数据转化为可视化图表和图形&#xff0c;可以更好地理解学生的表现、需求和趋势&#xff0c;从而提供更好…

03-rnn-由国家名和开始字符生成1个name

一、查漏补缺、熟能生巧&#xff1a; 1.原来没有optimizer.step()的时候&#xff0c;也可以这么做&#xff1a; 二、具体代码&#xff1a; NLP From Scratch: Generating Names with a Character-Level RNN — PyTorch Tutorials 2.0.1cu117 documentation

2023年全国大学生电子设计竞赛-E题国家级二等奖

系列文章目录 文章目录 系列文章目录前言一、又一年电赛过去了二、E题注意事项1.注意事项 总结 前言 一、又一年电赛过去了 比较幸运的是大学生涯作为电子类学生的最后一次电赛&#xff0c;还能拿到国二&#xff0c;跟去年21年也是一样&#xff0c;两年国二&#xff1b;一路来…

【C++】类和对象核心总结

类和对象核心知识目录&#xff1a; 一、面向过程和面向对象初步认识 二、类的引入定义&#xff08;struct > class&#xff09; 2.1自定义类型 struct 和 class 的区别 2.2类放在内存中的什么存储区&#xff1f; 2.3类中函数定义的方式 2.3.1声明和定义分离&#xff0…

Jmeter+Ant+Git+Jenkins持续集成介绍

一 简介 1.什么是ant? ant是构建工具 2.什么是构建 概念到处可查到&#xff0c;形象来说&#xff0c;你要把代码从某个地方拿来&#xff0c;编译&#xff0c;再拷贝到某个地方去等等操作&#xff0c;当然不仅于此&#xff0c;但是主要用来干这个 3.ant的好处 跨平台 -…

投资理财基础知识分享(二)

大家好&#xff0c;我是财富智星&#xff0c;今天跟大家继续分享投资理财基础知识&#xff0c;今天介绍下投资理财都有哪些产品可以购买的问题&#xff1a; 满足收益性的资产 货币基金和保险是直接购买的投资产品&#xff0c;没有太多技巧可言。 然而&#xff0c;其他投资产品的…

springboot集成Logback 日志写入数据库

springboot集成Logback 日志写入数据库 引入maven依赖 <!-- logback日志--><dependency><groupId>ch.qos.logback</groupId><artifactId>logback-classic</artifactId><version>1.2.3</version></dependency>&l…

【C++从0到王者】第二十九站:二叉搜索树常见题

文章目录 一、根据二叉树创建字符串二、二叉树的最近公共祖先1.解法一&#xff1a;递归2.解法二&#xff1a;借助栈来寻找路径 三、二叉搜索树与双向链表四、前序与中序构建二叉树五、中序与后序构建二叉树 一、根据二叉树创建字符串 题目链接&#xff1a;力扣第606题&#xff…

fabic 在canvas中绘制group元素,如何获取并修改group中某一元素的填充色

1、创建一个Fabric组并向其添加元素 2、标识要修改的组中的特定元素 3、访问并修改该元素的填充颜色 下面是JavaScript中的一个代码示例: // Create a Fabric.js canvas var canvas new fabric.Canvas(canvas);// Create a rectangle and a circle var rectangle new fabric…

Linux——环境变量

✅<1>主页&#xff1a;&#xff1a;我的代码爱吃辣 &#x1f4c3;<2>知识讲解&#xff1a;Linux——环境变量 ☂️<3>开发环境&#xff1a;Centos7 &#x1f4ac;<4>前言&#xff1a;环境变量(environment variables)一般是指在操作系统中用来指定操作…

2023年一级建造师建设工程经济真题

2023年一级建造师建设工程经济真题 1.根据《建设工程工程量清单计价规范》规定&#xff0c;代表专业工程的项目编码是 ()。 A、1&#xff0c;2 B、3&#xff0c;4 C、5&#xff0c;6 D、7&#xff0c;8&#xff0c;9 【答案】B 2.某公司希望所投资项目在第5年末回收1000万…

银行笔试篇---职业能力测试(行测)

数字推理 数字推理可分为等差数列、等比数列、和数列、积数列、幂数列以及分数数列六类&#xff0c;做题时的总体原则为&#xff1a; 关键点1&#xff1a;凡是一次变化找不到规律的&#xff0c;直接放弃&#xff01;所谓一次变化指的是&#xff1a;1.通过一次相邻两数作差、作…