先上图对比方案1-2-3不同点,本文是方案2
方案1(旋转场景情况下发光体不应该遮住另一个,但是遮住了)

方案2(层次正常,发光正常)

方案3(层次正常,发光正常,但是转动场景时候部分辉光会被遮挡,但是还算OK)

方案二,解决分层渲染场景转动时显示不正常,修复了深度信息丢失导致的层级问题
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<style>
* {
margin: 0;
padding: 0;
}
</style>
</head>
<body>
<script type="x-shader/x-vertex" id="vertexshader">
varying vec2 vUv;
void main() {
vUv = uv;
gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
}
</script>
<script type="x-shader/x-fragment" id="fragmentshader">
uniform sampler2D baseTexture;
uniform sampler2D bloomTexture;
varying vec2 vUv;
void main() {
gl_FragColor = ( texture2D( baseTexture, vUv ) + vec4( 1.0 ) * texture2D( bloomTexture, vUv ) );
}
</script>
<script type="module">
import * as THREE from "./build/three.module.js";
import { GUI } from './jsm/libs/dat.gui.module.js';
import { OrbitControls } from "./jsm/controls/OrbitControls.js";
import { EffectComposer } from "./jsm/postprocessing/EffectComposer.js";
import { UnrealBloomPass } from "./jsm/postprocessing/UnrealBloomPass.js";
import { RenderPass } from "./jsm/postprocessing/RenderPass.js";
import { ShaderPass } from "./jsm/postprocessing/ShaderPass.js";
import { FXAAShader } from "./jsm/shaders/FXAAShader.js";
let scene, camera, renderer, bloomComposer, finalComposer;
const ENTIRE_SCENE = 0,
BLOOM_SCENE = 1;
const bloomLayer = new THREE.Layers();
bloomLayer.set(BLOOM_SCENE);
const darkMaterial = new THREE.MeshBasicMaterial({ color: "black" });
const materials = {};
const params = {
exposure: 0,
bloomStrength: 1.5,
bloomThreshold: 0,
bloomRadius: 0,
};
const init = () => {
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera(
70,
window.innerWidth / window.innerHeight,
1,
100000
);
camera.position.set(50, 50, 50);
camera.position.y = 50;
renderer = new THREE.WebGLRenderer({
antialias: true,
});
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.toneMapping = THREE.ReinhardToneMapping;
document.body.appendChild(renderer.domElement);
const light = new THREE.AmbientLight(0xffffff, 0.6);
light.layers.enable(0);
light.layers.enable(1);
scene.add(light);
const controls = new OrbitControls(camera, renderer.domElement);
scene.add(new THREE.AxesHelper(100));
window.onresize = () => {
renderer.setSize(window.innerWidth, window.innerHeight);
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
};
};
let bloomPass
const initComposer = () => {
const effectFXAA = new ShaderPass(FXAAShader);
effectFXAA.uniforms["resolution"].value.set(
0.6 / window.innerWidth,
0.6 / window.innerHeight
);
effectFXAA.renderToScreen = true;
const renderScene = new RenderPass(scene, camera);
bloomPass = new UnrealBloomPass(
new THREE.Vector2(window.innerWidth, window.innerHeight),
1.5,
0.4,
0.85
);
bloomPass.threshold = params.bloomThreshold;
bloomPass.strength = params.bloomStrength;
bloomPass.radius = params.bloomRadius;
bloomComposer = new EffectComposer(renderer);
bloomComposer.renderToScreen = false;
bloomComposer.addPass(renderScene);
bloomComposer.addPass(bloomPass);
bloomComposer.addPass(effectFXAA);
const finalPass = new ShaderPass(
new THREE.ShaderMaterial({
uniforms: {
baseTexture: { value: null },
bloomTexture: { value: bloomComposer.renderTarget2.texture },
},
vertexShader: document.getElementById("vertexshader").textContent,
fragmentShader: document.getElementById("fragmentshader")
.textContent,
defines: {},
}),
"baseTexture"
);
finalPass.needsSwap = true;
finalComposer = new EffectComposer(renderer);
finalComposer.addPass(renderScene);
finalComposer.addPass(finalPass);
finalComposer.addPass(effectFXAA);
};
const render1 = () => {
scene.traverse((obj) => {
if (obj.isMesh && bloomLayer.test(obj.layers) === false) {
materials[obj.uuid] = obj.material;
obj.material = darkMaterial;
}
});
bloomComposer.render();
scene.traverse((obj) => {
if (materials[obj.uuid]) {
obj.material = materials[obj.uuid];
delete materials[obj.uuid];
}
});
finalComposer.render();
requestAnimationFrame(render);
};
const render = () => {
scene.traverse(darkenNonBloomed);
bloomComposer.render();
scene.traverse(restoreMaterial);
finalComposer.render();
requestAnimationFrame(render);
};
const bloomIgnore = [];
function darkenNonBloomed(obj) {
if (obj instanceof THREE.Scene) {
materials.scene = obj.background;
obj.background = null;
return;
}
if (
obj instanceof THREE.Sprite ||
bloomIgnore.includes(obj.type) ||
(obj.isMesh && bloomLayer.test(obj.layers) === false)
) {
materials[obj.uuid] = obj.material;
obj.material = darkMaterial;
}
}
function restoreMaterial(obj) {
if (obj instanceof THREE.Scene) {
obj.background = materials.scene;
delete materials.scene;
return;
}
if (materials[obj.uuid]) {
obj.material = materials[obj.uuid];
delete materials[obj.uuid];
}
}
const main = () => {
init();
initComposer();
addCubes()
addCubes1()
changeBloom()
};
function addCubes1() {
const geometry = new THREE.BoxGeometry(20, 20, 10);
const normalMtl = new THREE.MeshLambertMaterial({ color: 0x35c5ea });
const normalBox = new THREE.Mesh(geometry, normalMtl);
normalBox.position.z = -5;
console.log('查看网格模型默认图层掩码值normalBox', normalBox.layers.mask);
scene.add(normalBox);
const bloomMtl = new THREE.MeshLambertMaterial({ color: 0x9d94ea });
const bloomBox = new THREE.Mesh(geometry, bloomMtl);
bloomBox.position.z = 5;
bloomBox.layers.enable(1);
console.log('查看网格模型默认图层掩码值bloomBox', normalBox.layers.mask);
scene.add(bloomBox);
}
function addCubes() {
let texture = new THREE.TextureLoader().load("./backav9.jpg")
let texture1 = new THREE.TextureLoader().load("./py.png")
var geometry1 = new THREE.BoxGeometry(20, 20, 20);
var material1 = new THREE.MeshBasicMaterial({
map: texture
});
var cube1 = new THREE.Mesh(geometry1, material1);
cube1.layers.set(0)
console.log('查看网格模型默认图层掩码值cube1', cube1.layers.mask);
cube1.position.set(60, 0, 0)
scene.add(cube1);
var geometry2 = new THREE.BoxGeometry(20, 20, 20);
var material2 = new THREE.MeshBasicMaterial({
map: texture1
});
var cube2 = new THREE.Mesh(geometry2, material2);
cube2.position.set(30, 0, 0)
cube2.layers.enable(1);
console.log('查看网格模型默认图层掩码值cube2', cube2.layers.mask);
scene.add(cube2);
}
main();
render();
function changeBloom() {
const gui = new GUI();
gui.add(params, 'exposure', 0.1, 2).onChange(function (value) {
renderer.toneMappingExposure = Math.pow(value, 4.0);
});
gui.add(params, 'bloomThreshold', 0.0, 1.0).onChange(function (value) {
bloomPass.threshold = Number(value);
});
gui.add(params, 'bloomStrength', 0.0, 3.0).onChange(function (value) {
bloomPass.strength = Number(value);
});
gui.add(params, 'bloomRadius', 0.0, 1.0).step(0.01).onChange(function (value) {
bloomPass.radius = Number(value);
});
}
</script>
</body>
</html>
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
· 字符编码:从基础到乱码解决
2019-05-27 ***免费服务器体验