【threejs】创建及管理场景内的后期处理效果(以bloom为例,开箱即用)

场景内使用

//创建后期通道this.effectManager = new EffectManager({ renderer, camera, scene, dom })//循环渲染// 动画----------effect为我控制后期特效的开关animate() {requestAnimationFrame(this.animate);let { camera, controls, effectManager, effect } = thisif (!camera) returnif (!controls) returnlet { scene, renderer, renderer_3d, stats, } = this.glcontrols.update();renderer_3d.render(scene, camera);// effect 执行renderif (effect.active) {effectManager.render()} else {renderer.render(scene, camera);}stats.update();}animate()//执行动画//使用loadConfig方法修改辉光通道let blooms =  [{BLOOM_LEVEL: "1",threshold: 0,strength: 1,radius: 0.1,exposure: .1},{BLOOM_LEVEL: "2",threshold: 0,strength: .1,radius: 0.7,exposure: .9},]this.effectManager.loadConfig(blooms )// 使特定的物体发光//找到mesh,假设已经有一个bloom_mesh(THREE.mesh) bloom_mesh.BLOOM_LEVEL="2" //使用  BLOOM_LEVEL: "2",渲染,场景发光
/**
do sth........................
later......
*/bloom_mesh.BLOOM_LEVEL="1" //使用  BLOOM_LEVEL: "1",渲染,可以随时修改

创建后期处理通道的类


import * as THREE from 'three'
import { RenderPass } from 'three/examples/jsm/postprocessing/RenderPass.js';
import { EffectComposer } from 'three/examples/jsm/postprocessing/EffectComposer.js';
import { ShaderPass } from 'three/examples/jsm/postprocessing/ShaderPass.js';
import { UnrealBloomPass } from 'three/examples/jsm/postprocessing/UnrealBloomPass.js';
import { OutputPass } from 'three/examples/jsm/postprocessing/OutputPass.js';
import BloomEffect from './BloomEffect';
import { FXAAShader } from 'three/examples/jsm/shaders/FXAAShader.js'
import { SMAAPass } from 'three/examples/jsm/postprocessing/SMAAPass.js';
export default class EffectManager {constructor({ renderer, camera, scene, dom }) {// 当有多个类型的后期处理时,通过这里修改配置项this.effects = {blooms: [{BLOOM_LEVEL: "1",threshold: 0,strength: 1,radius: 0.1,exposure: .1},{BLOOM_LEVEL: "2",threshold: 0,strength: .1,radius: 0.7,exposure: .9},]}this.renderer = rendererthis.camera = camerathis.scene = scenethis.dom = domthis.blooms = []this.materials = {}this.bloomHandleList = {}this.darkMaterial = new THREE.MeshBasicMaterial({ color: 'black' });this.sceneBgCache = nullthis.createDefuaultPass()this.upDate()}// 一些默认的通道createDefuaultPass() {let { renderer, camera, scene, dom } = thisconst renderScene = new RenderPass(scene, camera);const outputPass = new OutputPass();const effectFXAAfix = new ShaderPass(FXAAShader);this.renderScene = renderScenethis.effectFXAAfix = effectFXAAfixthis.outputPass = outputPass}// 渲染通道:bloomupDateBlooms() {let list = this.effects.bloomslet { renderer, camera, scene, renderScene, dom } = thisthis.blooms = list.map(_c => new BloomEffect(renderer, camera, scene, renderScene, dom,{threshold: _c.threshold,strength: _c.strength,radius: _c.radius,exposure: _c.exposure},_c.BLOOM_LEVEL))}// 更新通道,upDate() {let { renderScene, effectFXAAfix, outputPass, renderer, camera, dom, scene } = thisconst finalComposer = new EffectComposer(renderer);finalComposer.addPass(renderScene);this.upDateBlooms()this.blooms.forEach(bloom => {finalComposer.addPass(bloom.mixPass)})// finalComposer.addPass(smaaPass)finalComposer.addPass(effectFXAAfix)finalComposer.addPass(outputPass);this.finalComposer = finalComposer}darkenNonBloomed() {let { scene, materials, bloomHandleList, darkMaterial } = thisscene.traverse((obj) => {if (obj.material) {materials[obj.uuid] = obj.material;obj.material = darkMaterial;}if (obj.BLOOM_LEVEL) {if (bloomHandleList[obj.BLOOM_LEVEL]) {bloomHandleList[obj.BLOOM_LEVEL].push(obj)} else {bloomHandleList[obj.BLOOM_LEVEL] = [obj]}}})this.sceneBgCache = scene.backgroundscene.background = darkMaterial}restoreMaterial() {let { materials, scene } = thisscene.traverse((obj) => {if (materials[obj.uuid]) {obj.material = materials[obj.uuid];delete materials[obj.uuid];}})scene.background = this.sceneBgCache}render() {let {materials, bloomHandleList,finalComposer,blooms} = thisthis.darkenNonBloomed()blooms.forEach(bloom => {bloom.render(materials, bloomHandleList)})this.restoreMaterial()finalComposer.render();}setCamera(_camera) {this.camera = _camerathis.renderScene.camera = this.camera}// 通道和composer无法修改分辨率只能用updateresize(x, y) {this.upDate()this.finalComposer.setSize(x, y)}// 改变blooms 可以是别的类型的特效 这里以辉光为例loadConfig(data) {console.log('改变blooms', data);let { blooms } = dataif (blooms) {this.effects.blooms = blooms// this.u}this.upDate()}// reRenderEffect重置}

后期类内部的辉光通道类


import * as THREE from 'three'
import { RenderPass } from 'three/examples/jsm/postprocessing/RenderPass.js';
import { EffectComposer } from 'three/examples/jsm/postprocessing/EffectComposer.js';
import { ShaderPass } from 'three/examples/jsm/postprocessing/ShaderPass.js';
import { UnrealBloomPass } from 'three/examples/jsm/postprocessing/UnrealBloomPass.js';
import { OutputPass } from 'three/examples/jsm/postprocessing/OutputPass.js';export default class BloomEffect {/*** * @param {*} param0 */constructor(renderer,camera,scene,renderScene,dom,params = {threshold: 0,strength: 1,radius: 0.5,exposure: 1},BLOOM_LEVEL = 0,) {this.renderer = rendererthis.camera = camerathis.scene = scenethis.BLOOM_LEVEL = BLOOM_LEVELconst BLOOM_SCENE = BLOOM_LEVEL;const bloomLayer = new THREE.Layers();bloomLayer.set(BLOOM_SCENE);const darkMaterial = new THREE.MeshBasicMaterial({ color: 'black' });const materials = {};// bloomconst bloomPass = new UnrealBloomPass(new THREE.Vector2(1, 1), 1.5, 0.4, 0.85);bloomPass.threshold = params.threshold;bloomPass.strength = params.strength;bloomPass.radius = params.radius;const bloomComposer = new EffectComposer(renderer);bloomComposer.renderToScreen = false;bloomComposer.addPass(renderScene);bloomComposer.addPass(bloomPass);// mixconst mixPass = new ShaderPass(new THREE.ShaderMaterial({uniforms: {baseTexture: { value: null },bloomTexture: { value: bloomComposer.renderTarget2.texture }},vertexShader:  /*glsl*/ `varying vec2 vUv;void main() {vUv = uv;gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );}`,fragmentShader:   /*glsl*/`uniform sampler2D baseTexture;uniform sampler2D bloomTexture;varying vec2 vUv;void main() {gl_FragColor = ( texture2D( baseTexture, vUv ) + vec4( 1.0 ,1.0,1.0,.0) * texture2D( bloomTexture, vUv ) );}`,defines: {}}), 'baseTexture');mixPass.needsSwap = true;this.BLOOM_SCENE = BLOOM_SCENEthis.bloomLayer = bloomLayerthis.params = paramsthis.darkMaterial = darkMaterialthis.materials = materialsthis.renderScene = renderScenethis.bloomPass = bloomPassthis.bloomComposer = bloomComposerthis.mixPass = mixPassfunction darkenNonBloomed(obj) {if (obj.material && (!obj.BLOOM_LEVEL)) {materials[obj.uuid] = obj.material;obj.material = darkMaterial;}// if (obj.BLOOM_LEVEL && (obj.BLOOM_LEVEL !== BLOOM_LEVEL)) {//     materials[obj.uuid] = obj.material;//     obj.material = darkMaterial;// }}this.darkenNonBloomed = darkenNonBloomedfunction restoreMaterial(obj) {if (materials[obj.uuid]) {obj.material = materials[obj.uuid];delete materials[obj.uuid];}}this.restoreMaterial = restoreMaterial}render(materials, bloomHandleList) {// let { scene, bloomComposer,//     darkenNonBloomed, restoreMaterial,// } = this// scene.traverse(darkenNonBloomed);// bloomComposer.render();// scene.traverse(restoreMaterial);let {BLOOM_LEVEL,scene, bloomComposer} = thislet list = nullif (bloomHandleList[BLOOM_LEVEL]) {list = bloomHandleList[BLOOM_LEVEL]list.forEach(obj => {obj.material = materials[obj.uuid]});}bloomComposer.render();if (list) {list.forEach(obj => {materials[obj.uuid] = obj.materialobj.material = this.darkMaterial});delete bloomHandleList[BLOOM_LEVEL]}}setParams(_params = {}) {let { params, bloomPass } = thisfor (let k in params) {if (_params[k]) {params[k] = params[k]}}Object.assign(bloomPass, params)}setCamera(_camera) {let { renderScene } = thisrenderScene.setCamera(_camera)}}

效果

在这里插入图片描述

我在花朵和瓶子上分别用了1 和2 辉光效果,下图是无光效果对比

在这里插入图片描述

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

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

相关文章

建立用邻接表表示的无向图

创建一个建立用邻接表表示的无向图 #include<stdio.h> #include<stdlib.h> typedef struct node {int adjvex;struct node *next; }Anode; typedef struct {char vertex;Anode *link; }Unode; typedef struct {Unode adjlist[100];int vexnum,arcnum; }Adjgraph; …

芯片需要按一下keyup或者复位按键虚拟或者下载之后芯片能下载却运行不了或者需要额外供电。

这些问题很有可能是因为外围电路器件幅值与设计不同的存在&#xff0c;导致你需要外部供电才能实现一个正常运行&#xff0c;可以检查一下外围电路在供电区域的电流区&#xff0c;电阻幅值是否和原理图设计时看的一模一样或者直接更换 因为按键会失灵&#xff0c;首先检查复位按…

Java直播系统视频聊天系统小程序源码

直播视频聊天系统✨&#xff1a;打造你的专属互动空间 &#x1f680; 引言&#xff1a;直播视频聊天系统的兴起 在这个快节奏的数字时代&#xff0c;直播和视频聊天已成为我们日常沟通的重要工具。从游戏直播到在线教育&#xff0c;从远程办公到家庭聚会&#xff0c;直播视频…

云轴科技ZStack助力新远科技开启化工行业智能制造新篇章

新远科技基于云轴科技ZStack Cube超融合和ZStack Zaku容器云平台打造了灵活高效的IT基础设施&#xff0c;实现了IaaS和PaaS层的全面覆盖&#xff0c;优化了资源利用率&#xff0c;降低了硬件成本和运维复杂性&#xff0c;同时强化了数据安全和业务连续性。 化工行业的数字化先…

软件测试PO模式

V1&#xff1a;不使用任何设计模式和单元测试框架 V2&#xff1a;使用UnitTest管理用例 V3&#xff1a;使用方法封装的思想&#xff0c;对代码进行优化 V4&#xff1a;采用PO模式的分层思想对代码进行拆分 V5&#xff1a;对PO分层之后的代码继续优化 V6&#xff1a;PO模式深入封…

网页版五子棋——匹配模块(客户端开发)

前一篇文章&#xff1a;网页版五子棋——用户模块&#xff08;客户端开发&#xff09;-CSDN博客 目录 前言 一、前后端交互接口设计 二、游戏大厅页面 1.页面代码编写 2.前后端交互代码编写 3.测试获取用户信息功能 结尾 前言 前面文章介绍完了五子棋项目用户模块的代码…

Spring设计模式

设计模式 是一种软件开发中的解决方案&#xff0c;设计原则。目的是使代码具有扩展性&#xff0c;可维护性&#xff0c;可读性&#xff0c;如&#xff1a; 单例模式&#xff08;Singleton Pattern&#xff09; Spring IoC 容器默认会将 Bean 创建为单例&#xff0c;保证一个类…

【设计模式】结构型模式(一):适配器模式、装饰器模式

结构型模式&#xff08;一&#xff09;&#xff1a;适配器模式、装饰器模式 1.适配器模式&#xff08;Adapter&#xff09;2.装饰器模式&#xff08;Decorator&#xff09;2.1 主要特点2.2 组成部分2.3 示例代码2.3.1 Component 组件2.3.2 ConcreteComponent 具体组件2.3.3 Dec…

Go Energy 跨平台(GUI)应用编译和安装包制作

构建打包 energy cli 平台介绍描述windowNSIS安装包制作工具可通过 energy cli 安装linuxdpkg 命令系统自带macosenergy 仅生成 xxx.app系统自带 安装包制作 config/energy_[os].json是初始化应用时自动生成的应用配置文件&#xff0c;在编译和制作应用安装包时使用 Windows…

【Linux】进程信号全攻略(二)

&#x1f308; 个人主页&#xff1a;Zfox_ &#x1f525; 系列专栏&#xff1a;Linux 目录 一&#xff1a;&#x1f525; 再谈信号的捕捉 &#x1f98b; 关于信号捕捉的细节部分&#xff08;sigaction函数&#xff09; 二&#xff1a;&#x1f525; 穿插话题 - 操作系统是怎么运…

鸿蒙的进击之路

1. 题记&#xff1a; 为什么要写鸿蒙&#xff0c;因为她是华为的&#xff0c;为什么是华为就要写&#xff0c;因为华为背负了国人太多太多的包袱&#xff0c;或点赞或抨击。 我是强烈支持华为的&#xff0c;但我会客观公正地去评价华为的产品&#xff0c;就比如这篇博文&#…

Swagger的介绍和使用方式+常用注解

介绍: 使用Swagger你只需要按照它的规范去定义接口及接口相关的信息&#xff0c;就可以做到生成接口文档&#xff0c;以及在线接口调试页面.简单来说就是我们只需要知道使用Swagger可以帮助我们后端生成接口文档 Swagger官网:https://swagger.io/ 因为单独使用Swagger会有些…

FFmpeg 4.3 音视频-多路H265监控录放C++开发十三:将AVFrame转换成AVPacket。视频编码,AVPacket 重要函数,结构体成员学习

前提&#xff1a; 从前面的学习我们知道 AVFrame中是最原始的 视频数据&#xff0c;这一节开始我们需要将这个最原始的视频数据 压缩成 AVPacket数据&#xff0c; 我们前面&#xff0c;将YUV数据或者 RGBA 数据装进入了 AVFrame里面&#xff0c;并且在SDL中显示。 也就是说&…

QinQ VLAN技术

QinQ VLAN技术的主要作用包括扩展VLAN数量、实现私网VLAN透传、提供二层隔离和多租户环境等。以下是对这些作用的详细介绍&#xff1a; 扩展VLAN数量 解决VLAN ID不足问题&#xff1a;QinQ技术通过在原有的802.1Q标签基础上再增加一层802.1Q标签&#xff0c;从而将VLAN数量从40…

【机器学习】24. 聚类-层次式 Hierarchical Clustering

1. 优势和缺点 优点&#xff1a; 无需提前指定集群的数量 通过对树状图进行不同层次的切割&#xff0c;可以得到所需数量的簇。树状图提供了一个有用的可视化-集群过程的可解释的描述树状图可能揭示一个有意义的分类 缺点&#xff1a; 计算复杂度较大, 限制了其在大规模数据…

分析报告、调研报告、工作方案等的提示词

什么是提示词&#xff1f; 提示词的英文是Prompt&#xff0c;是你与人工智能&#xff08;AI&#xff09;进行交流的方式。简单来说&#xff0c;提示词就是你给AI的一段文字或问题&#xff0c;AI根据这段文字或问题来生成回应或完成任务。 举个例子&#xff1a;假设你在使用一…

Sentinel通过限流对微服务进行保护

目录 雪崩问题 解决雪崩问题的方法&#xff1a; 我们使用sentinel组件实现微服务的保护 一&#xff1a;下载sentinel 二.启动sentinel 三.访问&#xff1a;localhost:8080 默认的账号和密码都是sentinel 微服务整合sentinel 一.导入sentinel依赖 二.在application.yml配…

第三十篇——微分(上):如何从宏观变化了解微观趋势?

目录 一、背景介绍二、思路&方案三、过程1.思维导图2.文章中经典的句子理解3.学习之后对于投资市场的理解4.通过这篇文章结合我知道的东西我能想到什么&#xff1f; 四、总结五、升华 一、背景介绍 微分给我们带来的思维方式的变化&#xff0c;更加符合现在这个时代对于我…

Springboot项目报错记录

SpringBoot测试报错&#xff1a;Unable to find a SpringBootConfiguration, you need to use Context 该测试类所在测试包test下的包名和类路径java下的包名不一致导致的 引发以下报错 java.lang.IllegalStateException: Unable to find a SpringBootConfiguration, you need…

VTK知识学习(3)-显示圆柱

1、添加显示控件 前台界面 <WindowsFormsHost x:Name"windowHost" Grid.Row"1"/> 构造函数中添加。 private RenderWindowControl renderWindowControl new RenderWindowControl();public MainWindow(){InitializeComponent();windowHost.Child …