解决Three.js辉光背景不透明

news2025/1/11 17:53:15

使用此pass canvas元素的background都能看到 不过相应的辉光颜色和背景颜色不相容的地方看起来颜色会怪一些
如图
不过如果是纯色就没什么问题了
在这里插入图片描述

//@ts-nocheck
/*
 * @Author: hongbin
 * @Date: 2023-04-06 11:44:14
 * @LastEditors: hongbin
 * @LastEditTime: 2023-04-06 11:49:23
 * @Description:
 */
import {
    AdditiveBlending,
    Color,
    LinearFilter,
    MeshBasicMaterial,
    RGBAFormat,
    ShaderMaterial,
    Texture,
    UniformsUtils,
    Vector2,
    Vector3,
    WebGLRenderer,
    WebGLRenderTarget,
} from "three";

import { Pass } from "three/examples/jsm/postprocessing/Pass";

// typescript definitions doesn't have FullScreenQuad
//@ts-ignore
import { FullScreenQuad } from "three/examples/jsm/postprocessing/Pass";

import { CopyShader } from "three/examples/jsm/shaders/CopyShader.js";
import { LuminosityHighPassShader } from "three/examples/jsm/shaders/LuminosityHighPassShader.js";

/**
 * Thanks to https://github.com/mrdoob/three.js/issues/14104#issuecomment-429664412 for this fragmentShaderfix
 *
 * UnrealBloomPass is inspired by the bloom pass of Unreal Engine. It creates a
 * mip map chain of bloom textures and blurs them with different radii. Because
 * of the weighted combination of mips, and because larger blurs are done on
 * higher mips, this effect provides good quality and performance.
 *
 * Reference:
 * - https://docs.unrealengine.com/latest/INT/Engine/Rendering/PostProcessEffects/Bloom/
 */
class TransparentBackgroundFixedUnrealBloomPass extends Pass {
    strength: number;
    radius: number;
    threshold: number;
    resolution: Vector2;
    clearColor: Color;
    renderTargetsHorizontal: any[];
    renderTargetsVertical: any[];
    nMips: number;
    renderTargetBright: WebGLRenderTarget;
    highPassUniforms: any;
    materialHighPassFilter: ShaderMaterial;
    separableBlurMaterials: any[];
    compositeMaterial: ShaderMaterial;
    bloomTintColors: Vector3[];
    copyUniforms: any;
    materialCopy: ShaderMaterial;
    _oldClearColor: Color;
    oldClearAlpha: number;
    basic: MeshBasicMaterial;
    fsQuad: Pass.FullScreenQuad;
    static BlurDirectionX: any;
    static BlurDirectionY: any;
    constructor(
        resolution: Vector2,
        strength: number,
        radius: number,
        threshold: number
    ) {
        super();

        this.strength = strength !== undefined ? strength : 1;
        this.radius = radius;
        this.threshold = threshold;
        this.resolution =
            resolution !== undefined
                ? new Vector2(resolution.x, resolution.y)
                : new Vector2(256, 256);

        // create color only once here, reuse it later inside the render function
        this.clearColor = new Color(0, 0, 0);

        // render targets
        const pars = {
            minFilter: LinearFilter,
            magFilter: LinearFilter,
            format: RGBAFormat,
        };
        this.renderTargetsHorizontal = [];
        this.renderTargetsVertical = [];
        this.nMips = 5;
        let resx = Math.round(this.resolution.x / 2);
        let resy = Math.round(this.resolution.y / 2);

        this.renderTargetBright = new WebGLRenderTarget(resx, resy, pars);
        this.renderTargetBright.texture.name = "UnrealBloomPass.bright";
        this.renderTargetBright.texture.generateMipmaps = false;

        for (let i = 0; i < this.nMips; i++) {
            const renderTargetHorizonal = new WebGLRenderTarget(
                resx,
                resy,
                pars
            );

            renderTargetHorizonal.texture.name = "UnrealBloomPass.h" + i;
            renderTargetHorizonal.texture.generateMipmaps = false;

            this.renderTargetsHorizontal.push(renderTargetHorizonal);

            const renderTargetVertical = new WebGLRenderTarget(
                resx,
                resy,
                pars
            );

            renderTargetVertical.texture.name = "UnrealBloomPass.v" + i;
            renderTargetVertical.texture.generateMipmaps = false;

            this.renderTargetsVertical.push(renderTargetVertical);

            resx = Math.round(resx / 2);

            resy = Math.round(resy / 2);
        }

        // luminosity high pass material

        if (LuminosityHighPassShader === undefined)
            console.error(
                "THREE.UnrealBloomPass relies on LuminosityHighPassShader"
            );

        const highPassShader = LuminosityHighPassShader;
        this.highPassUniforms = UniformsUtils.clone(highPassShader.uniforms);

        this.highPassUniforms["luminosityThreshold"].value = threshold;
        this.highPassUniforms["smoothWidth"].value = 0.01;

        this.materialHighPassFilter = new ShaderMaterial({
            uniforms: this.highPassUniforms,
            vertexShader: highPassShader.vertexShader,
            fragmentShader: highPassShader.fragmentShader,
            defines: {},
        });

        // Gaussian Blur Materials
        this.separableBlurMaterials = [];
        const kernelSizeArray = [3, 5, 7, 9, 11];
        resx = Math.round(this.resolution.x / 2);
        resy = Math.round(this.resolution.y / 2);

        for (let i = 0; i < this.nMips; i++) {
            this.separableBlurMaterials.push(
                this.getSeperableBlurMaterial(kernelSizeArray[i])
            );

            this.separableBlurMaterials[i].uniforms["texSize"].value =
                new Vector2(resx, resy);

            resx = Math.round(resx / 2);

            resy = Math.round(resy / 2);
        }

        // Composite material
        this.compositeMaterial = this.getCompositeMaterial(this.nMips);
        this.compositeMaterial.uniforms["blurTexture1"].value =
            this.renderTargetsVertical[0].texture;
        this.compositeMaterial.uniforms["blurTexture2"].value =
            this.renderTargetsVertical[1].texture;
        this.compositeMaterial.uniforms["blurTexture3"].value =
            this.renderTargetsVertical[2].texture;
        this.compositeMaterial.uniforms["blurTexture4"].value =
            this.renderTargetsVertical[3].texture;
        this.compositeMaterial.uniforms["blurTexture5"].value =
            this.renderTargetsVertical[4].texture;
        this.compositeMaterial.uniforms["bloomStrength"].value = strength;
        this.compositeMaterial.uniforms["bloomRadius"].value = 0.1;
        this.compositeMaterial.needsUpdate = true;

        const bloomFactors = [1.0, 0.8, 0.6, 0.4, 0.2];
        this.compositeMaterial.uniforms["bloomFactors"].value = bloomFactors;
        this.bloomTintColors = [
            new Vector3(1, 1, 1),
            new Vector3(1, 1, 1),
            new Vector3(1, 1, 1),
            new Vector3(1, 1, 1),
            new Vector3(1, 1, 1),
        ];
        this.compositeMaterial.uniforms["bloomTintColors"].value =
            this.bloomTintColors;

        // copy material
        if (CopyShader === undefined) {
            console.error("THREE.UnrealBloomPass relies on CopyShader");
        }

        const copyShader = CopyShader;

        this.copyUniforms = UniformsUtils.clone(copyShader.uniforms);
        this.copyUniforms["opacity"].value = 1.0;

        this.materialCopy = new ShaderMaterial({
            uniforms: this.copyUniforms,
            vertexShader: copyShader.vertexShader,
            fragmentShader: copyShader.fragmentShader,
            blending: AdditiveBlending,
            depthTest: false,
            depthWrite: false,
            transparent: true,
        });

        this.enabled = true;
        this.needsSwap = false;

        this._oldClearColor = new Color();
        this.oldClearAlpha = 1;

        this.basic = new MeshBasicMaterial();

        this.fsQuad = new FullScreenQuad(null);
    }

    dispose() {
        for (let i = 0; i < this.renderTargetsHorizontal.length; i++) {
            this.renderTargetsHorizontal[i].dispose();
        }

        for (let i = 0; i < this.renderTargetsVertical.length; i++) {
            this.renderTargetsVertical[i].dispose();
        }

        this.renderTargetBright.dispose();
    }

    setSize(width: number, height: number) {
        let resx = Math.round(width / 2);
        let resy = Math.round(height / 2);

        this.renderTargetBright.setSize(resx, resy);

        for (let i = 0; i < this.nMips; i++) {
            this.renderTargetsHorizontal[i].setSize(resx, resy);
            this.renderTargetsVertical[i].setSize(resx, resy);

            this.separableBlurMaterials[i].uniforms["texSize"].value =
                new Vector2(resx, resy);

            resx = Math.round(resx / 2);
            resy = Math.round(resy / 2);
        }
    }

    render(
        renderer: WebGLRenderer,
        writeBuffer: any,
        readBuffer: { texture: Texture },
        deltaTime: any,
        maskActive: any
    ) {
        renderer.getClearColor(this._oldClearColor);
        this.oldClearAlpha = renderer.getClearAlpha();
        const oldAutoClear = renderer.autoClear;
        renderer.autoClear = false;

        renderer.setClearColor(this.clearColor, 0);

        if (maskActive) renderer.state.buffers.stencil.setTest(false);

        // Render input to screen

        if (this.renderToScreen) {
            this.fsQuad.material = this.basic;
            this.basic.map = readBuffer.texture;

            renderer.setRenderTarget(null);
            renderer.clear();
            this.fsQuad.render(renderer);
        }

        // 1. Extract Bright Areas

        this.highPassUniforms["tDiffuse"].value = readBuffer.texture;
        this.highPassUniforms["luminosityThreshold"].value = this.threshold;
        this.fsQuad.material = this.materialHighPassFilter;

        renderer.setRenderTarget(this.renderTargetBright);
        renderer.clear();
        this.fsQuad.render(renderer);

        // 2. Blur All the mips progressively

        let inputRenderTarget = this.renderTargetBright;

        for (let i = 0; i < this.nMips; i++) {
            this.fsQuad.material = this.separableBlurMaterials[i];

            this.separableBlurMaterials[i].uniforms["colorTexture"].value =
                inputRenderTarget.texture;
            this.separableBlurMaterials[i].uniforms["direction"].value =
                TransparentBackgroundFixedUnrealBloomPass.BlurDirectionX;
            renderer.setRenderTarget(this.renderTargetsHorizontal[i]);
            renderer.clear();
            this.fsQuad.render(renderer);

            this.separableBlurMaterials[i].uniforms["colorTexture"].value =
                this.renderTargetsHorizontal[i].texture;
            this.separableBlurMaterials[i].uniforms["direction"].value =
                TransparentBackgroundFixedUnrealBloomPass.BlurDirectionY;
            renderer.setRenderTarget(this.renderTargetsVertical[i]);
            renderer.clear();
            this.fsQuad.render(renderer);

            inputRenderTarget = this.renderTargetsVertical[i];
        }

        // Composite All the mips

        this.fsQuad.material = this.compositeMaterial;
        this.compositeMaterial.uniforms["bloomStrength"].value = this.strength;
        this.compositeMaterial.uniforms["bloomRadius"].value = this.radius;
        this.compositeMaterial.uniforms["bloomTintColors"].value =
            this.bloomTintColors;

        renderer.setRenderTarget(this.renderTargetsHorizontal[0]);
        renderer.clear();
        this.fsQuad.render(renderer);

        // Blend it additively over the input texture

        this.fsQuad.material = this.materialCopy;
        this.copyUniforms["tDiffuse"].value =
            this.renderTargetsHorizontal[0].texture;

        if (maskActive) renderer.state.buffers.stencil.setTest(true);

        if (this.renderToScreen) {
            renderer.setRenderTarget(null);
            this.fsQuad.render(renderer);
        } else {
            renderer.setRenderTarget(readBuffer);
            this.fsQuad.render(renderer);
        }

        // Restore renderer settings

        renderer.setClearColor(this._oldClearColor, this.oldClearAlpha);
        renderer.autoClear = oldAutoClear;
    }

    getSeperableBlurMaterial(kernelRadius: number) {
        return new ShaderMaterial({
            defines: {
                KERNEL_RADIUS: kernelRadius,
                SIGMA: kernelRadius,
            },

            uniforms: {
                colorTexture: { value: null },
                texSize: { value: new Vector2(0.5, 0.5) },
                direction: { value: new Vector2(0.5, 0.5) },
            },

            vertexShader: `varying vec2 vUv;
				void main() {
					vUv = uv;
					gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
				}`,

            fragmentShader: `#include <common>
				varying vec2 vUv;
				uniform sampler2D colorTexture;
				uniform vec2 texSize;
				uniform vec2 direction;

				float gaussianPdf(in float x, in float sigma) {
					return 0.39894 * exp( -0.5 * x * x/( sigma * sigma))/sigma;
				}
				void main() {
          vec2 invSize = 1.0 / texSize;
          float fSigma = float(SIGMA);
          float weightSum = gaussianPdf(0.0, fSigma);
          float alphaSum = 0.0;
          vec3 diffuseSum = texture2D( colorTexture, vUv).rgb * weightSum;
          for( int i = 1; i < KERNEL_RADIUS; i ++ ) {
            float x = float(i);
            float w = gaussianPdf(x, fSigma);
            vec2 uvOffset = direction * invSize * x;
            vec4 sample1 = texture2D( colorTexture, vUv + uvOffset);
            vec4 sample2 = texture2D( colorTexture, vUv - uvOffset);
            diffuseSum += (sample1.rgb + sample2.rgb) * w;
            alphaSum += (sample1.a + sample2.a) * w;
            weightSum += 2.0 * w;
          }
          gl_FragColor = vec4(diffuseSum/weightSum, alphaSum/weightSum);
        }`,
        });
    }

    getCompositeMaterial(nMips: number) {
        return new ShaderMaterial({
            defines: {
                NUM_MIPS: nMips,
            },

            uniforms: {
                blurTexture1: { value: null },
                blurTexture2: { value: null },
                blurTexture3: { value: null },
                blurTexture4: { value: null },
                blurTexture5: { value: null },
                dirtTexture: { value: null },
                bloomStrength: { value: 1.0 },
                bloomFactors: { value: null },
                bloomTintColors: { value: null },
                bloomRadius: { value: 0.0 },
            },

            vertexShader: `varying vec2 vUv;
				void main() {
					vUv = uv;
					gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
				}`,

            fragmentShader: `varying vec2 vUv;
				uniform sampler2D blurTexture1;
				uniform sampler2D blurTexture2;
				uniform sampler2D blurTexture3;
				uniform sampler2D blurTexture4;
				uniform sampler2D blurTexture5;
				uniform sampler2D dirtTexture;
				uniform float bloomStrength;
				uniform float bloomRadius;
				uniform float bloomFactors[NUM_MIPS];
				uniform vec3 bloomTintColors[NUM_MIPS];

				float lerpBloomFactor(const in float factor) {
					float mirrorFactor = 1.2 - factor;
					return mix(factor, mirrorFactor, bloomRadius);
				}

				void main() {
					gl_FragColor = bloomStrength * ( lerpBloomFactor(bloomFactors[0]) * vec4(bloomTintColors[0], 1.0) * texture2D(blurTexture1, vUv) +
						lerpBloomFactor(bloomFactors[1]) * vec4(bloomTintColors[1], 1.0) * texture2D(blurTexture2, vUv) +
						lerpBloomFactor(bloomFactors[2]) * vec4(bloomTintColors[2], 1.0) * texture2D(blurTexture3, vUv) +
						lerpBloomFactor(bloomFactors[3]) * vec4(bloomTintColors[3], 1.0) * texture2D(blurTexture4, vUv) +
						lerpBloomFactor(bloomFactors[4]) * vec4(bloomTintColors[4], 1.0) * texture2D(blurTexture5, vUv) );
				}`,
        });
    }
}

TransparentBackgroundFixedUnrealBloomPass.BlurDirectionX = new Vector2(
    1.0,
    0.0
);
TransparentBackgroundFixedUnrealBloomPass.BlurDirectionY = new Vector2(
    0.0,
    1.0
);

export { TransparentBackgroundFixedUnrealBloomPass as UnrealBloomPass };

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

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

相关文章

Node.js crypto模块 加密算法

背景 微信小程序调用飞蛾热敏纸打印机&#xff0c;需要进行参数sig签名校验&#xff0c;使用的是sha1进行加密 // 通过crypto.createHash()函数&#xff0c;创建一个hash实例&#xff0c;但是需要调用md5&#xff0c;sha1&#xff0c;sha256&#xff0c;sha512算法来实现实例的…

python-图片之乐-ASCII 文本图形

ASCII&#xff1a;一个简单的字符编码方案 pillow模块&#xff1a;读取图像&#xff0c;访问底层数据 numpy模块&#xff1a;计算平均值 import sys, random, argparse import numpy as np import math from PIL import Image定义灰度等级和网格 定义两种灰度等级作为全局值…

Git小白入门——了解分布式版本管理和安装

Git是什么&#xff1f; Git是目前世界上最先进的分布式版本控制系统&#xff08;没有之一&#xff09; 什么是版本控制系统&#xff1f; 程序员开发过程中&#xff0c;对于每次开发对各种文件的修改、增加、删除&#xff0c;达到预期阶段的一个快照就叫做一个版本。 如果有一…

EVO大赛是什么

价格是你所付出的东西&#xff0c;而价值是你得到的东西 EVO大赛是什么&#xff1f; “EVO”大赛全称“Evolution Championship Series”&#xff0c;是北美最高规格格斗游戏比赛&#xff0c;大赛正式更名后已经连续举办12年&#xff0c;是全世界最大规模的格斗游戏赛事。常见…

Python Qt学习(四)Radio Button

代码 # -*- coding: utf-8 -*-# Form implementation generated from reading ui file D:\Works\Python\Qt\qt_radiobutton.ui # # Created by: PyQt5 UI code generator 5.15.9 # # WARNING: Any manual changes made to this file will be lost when pyuic5 is # run again.…

2023年高教社杯 国赛数学建模思路 - 案例:异常检测

文章目录 赛题思路一、简介 -- 关于异常检测异常检测监督学习 二、异常检测算法2. 箱线图分析3. 基于距离/密度4. 基于划分思想 建模资料 赛题思路 &#xff08;赛题出来以后第一时间在CSDN分享&#xff09; https://blog.csdn.net/dc_sinor?typeblog 一、简介 – 关于异常…

(笔记四)利用opencv识别标记视频中的目标

预操作&#xff1a; 通过cv2将视频的某一帧图片转为HSV模式&#xff0c;并通过鼠标获取对应区域目标的HSV值&#xff0c;用于后续的目标识别阈值区间的选取 img cv.imread(r"D:\data\123.png") img cv.cvtColor(img, cv.COLOR_BGR2HSV) plt.figure(1), plt.imshow…

科技助力图书馆新趋势:机器人“图书管理员”展风采

原创 | 文 BFT机器人 PART1 机器人“图书管理员”横空出世 随着科技的日新月异&#xff0c;知识的获取变得更加方便快捷&#xff0c;图书馆不再只是借阅书籍的场所&#xff0c;其渐渐演变成了人们社交、休闲、学习的不二之选。在此场景下&#xff0c;“智能化图书馆”的概念深…

gitbash的使用

目录 1. 安装git 2. gitbash配置 2.1 设置 2.2 生成key 2.3 初始化本地仓库 2.4 clone远程仓库的工程到本地 2.5 本地修改提交 1. 安装git 默认安装。 2. gitbash配置 2.1 设置 打开gitbash&#xff0c;设置用户名和邮箱&#xff1a; git config --global user.name &…

IP协议分片重组问题

分片是什么&&为什么会有分片 IP数据报分片的主要目的是为了防止IP数据报文长度超过下一跳链路MTU(最大传输单元)。 数据链路层之MTU 数据链路层中有一个东西叫做MTU&#xff08;最大传输单元&#xff09;&#xff0c;它的作用主要是控制上层给的数据报不要太大&#…

算法通关村第8关【白银】| 二叉树的深度和高度问题

1.最大深度问题 思路&#xff1a;递归三部曲 第一步&#xff1a;确定参数和返回值 题目要求求二叉树的深度&#xff0c;也就是有多少层&#xff0c;需要传递一个root从底层向上统计 int maxDepth(TreeNode root) 第二步&#xff1a;确定终止条件 当递归到null时就说明到底了…

实训笔记8.28

实训笔记8.28 8.28笔记一、大数据计算场景主要分为两种1.1 离线计算场景1.2 实时计算场景 二、一般情况下大数据项目的开发流程2.1 数据采集存储阶段2.2 数据清洗预处理阶段2.3 数据统计分析阶段2.4 数据挖掘预测阶段2.5 数据迁移阶段2.6 数据可视化阶段 三、纯大数据离线计算项…

最新企业网盘产品推荐榜发布

随着数字化发展&#xff0c;传统的文化存储方式已无法跟上企业发展的步伐。云存储的出现为企业提供了新的文件管理存储模式。企业网盘作为云存储的代表性工具&#xff0c;被越来越多的企业所青睐。那么在众多企业网盘产品中&#xff0c;企业该如何找到合适的企业网盘呢&#xf…

汽车类 ±0.25°C SPI 温度传感器,TMP126EDBVRQ1、TMP126EDCKRQ1、TMP127EDBVRQ1引脚配置图

一、概述 TMP126-Q1 是一款精度为 0.25C 的数字温度传感器 &#xff0c; 支持的环境温度范围为 -55C 至 175C 。TMP126-Q1 具 有 14 位 &#xff08; 有符号 &#xff09; 温度分辨率(0.03125C/LSB)&#xff0c;并且可在 1.62V 至 5.5V 的电源电压范围内工作。TMP126-Q1 具有转…

Python爬虫网络安全:优劣势和适用范围分析

各位Python程序猿大佬们&#xff01;在当今数字化时代&#xff0c;网络安全是至关重要的。保护你的网络通信安全对于个人和组织来说都是非常重要的任务。在本文中&#xff0c;我将与你一起探讨Python网络安全编程中的代理、虚拟专用网络和TLS这三个关键概念&#xff0c;分析它们…

「2024」预备研究生mem-分析推理强化: 分组型 (上)

一、分析推理强化: 分组型 (上) 二、课后题

助力乡村振兴 泰格智能AI英语携手中国善网在行动

近日&#xff0c;泰格智能AI英语与中国善网宣布达成战略合作&#xff0c;共同投身乡村教育事业。此次合作旨在通过中国善网的会员公益机构&#xff0c;向乡村英语老师和学生捐赠共12000个英语教育智能AI训练产品账号&#xff0c;其总价值超过350万人民币。这一举措是为了让乡村…

为何直线导轨要保持日常清洁?

随着时代的发展&#xff0c;已逐步从传统的工业发展模式发展到工业自动化&#xff0c;直线滑轨在工业生产中得到了广泛的应用&#xff0c;大大提高了生产效率&#xff0c;带动了经济效益的增长。 众所周知&#xff0c;想要直线导轨的使用达到预期的效果&#xff0c;日常的保养和…

Vue3 学习

基础 js:https://www.bilibili.com/video/BV15T411j7pJ/?spm_id_from333.337.search-card.all.click&vd_source9747207be61edfe4ec62226fc79b3589 官方文档&#xff1a; https://cn.vuejs.org/ 版本之间差异在关于---》版本发布 https://cn.vuejs.org/about/release…