Three.js-绘制矩形shader
  dOqWse1dTEyO 2023年11月02日 64 0


Three.js-绘制矩形shader_ide


绘制图中的嵌套矩形框

方法:

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


【版权声明】本文内容来自摩杜云社区用户原创、第三方投稿、转载,内容版权归原作者所有。本网站的目的在于传递更多信息,不拥有版权,亦不承担相应法律责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@moduyun.com

  1. 分享:
最后一次编辑于 2023年11月08日 0

暂无评论

推荐阅读
dOqWse1dTEyO