I’m currently using the UnrealBloomPass
from the jsm
and would like to instead use the BloomEffect
from the postprocessing
library.
Here’s my current code:
<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 'https://unpkg.com/three/build/three.module.js';
import {
OrbitControls
} from 'https://unpkg.com/three/examples/jsm/controls/OrbitControls.js';
import {
EffectComposer
} from 'https://unpkg.com/three/examples/jsm/postprocessing/EffectComposer.js';
import {
RenderPass
} from 'https://unpkg.com/three/examples/jsm/postprocessing/RenderPass.js';
import {
ShaderPass
} from 'https://unpkg.com/three/examples/jsm/postprocessing/ShaderPass.js';
import {
UnrealBloomPass
} from 'https://unpkg.com/three/examples/jsm/postprocessing/UnrealBloomPass.js';
const DISTANCE_SCALE = 23.49;
const EARTH_RADIUS = 6371;
const STAR_RADIUS = 696340;
const STAR_OFFSET = STAR_RADIUS / EARTH_RADIUS;
const SUNLIGHT_INTENSITY = Math.floor(3.846 * 1026 / DISTANCE_SCALE);
function setupScene() {
function Sphere(radius, dist, colour, star) {
const obj = new THREE.Group();
obj.position.set(0, 0, dist * DISTANCE_SCALE);
const sphereMat = new THREE.MeshPhongMaterial({});
if (star) {
sphereMat.color = new THREE.Color(colour);
} else {
obj.position.z += STAR_OFFSET;
}
obj.add(new THREE.Mesh(new THREE.SphereGeometry(radius / EARTH_RADIUS, 32, 32), sphereMat));
const objScene = star ? starScene : scene;
objScene.add(obj);
}
Sphere(STAR_RADIUS, 0, "#ff5e00", true);
Sphere(EARTH_RADIUS, 1, "#0000FF", false);
}
function setupLighting() {
starScene.add(new THREE.AmbientLight(0x111111, 1));
const sunLight = new THREE.PointLight(0xFFFFFF, SUNLIGHT_INTENSITY);
scene.add(sunLight);
const renderScene = new RenderPass(starScene, camera);
const bloomPass = new UnrealBloomPass(new THREE.Vector2(window.innerWidth, window.innerHeight), 1.5, 0.4, 0.85);
bloomPass.threshold = 0;
bloomPass.strength = 10;
bloomPass.radius = .55;
bloomComposer = new EffectComposer(renderer);
bloomComposer.addPass(renderScene);
bloomComposer.addPass(bloomPass);
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);
}
function render() {
renderer.autoClear = true;
renderer.render(scene, camera);
renderer.autoClear = false;
finalComposer.render();
bloomComposer.render();
}
const renderer = new THREE.WebGLRenderer({});
renderer.setPixelRatio(window.devicePixelRatio);
renderer.toneMappingExposure = Math.pow(.9, 4.0);
renderer.autoClear = false;
document.body.appendChild(renderer.domElement);
renderer.setSize(window.innerWidth, window.innerHeight);
const camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.05, 20000);
camera.position.set(0, 720, 720);
const controls = new OrbitControls(camera, renderer.domElement);
controls.target.set(0, 0, DISTANCE_SCALE + STAR_OFFSET);
const scene = new THREE.Scene();
const starScene = new THREE.Scene();
setupScene();
let bloomComposer;
let finalComposer;
setupLighting();
renderer.setAnimationLoop(render);
</script>
My progress so far (following the example):
const bloomEffect = new BloomEffect({
intensity: 10,
luminanceThreshold: 0,
luminanceSmoothing: 0.1,
kernelSize: KernelSize.MEDIUM
});
const bloomPass = new EffectPass(camera, bloomEffect);
bloomPass.renderToScreen = true;
const bloomComposer = new EffectComposer(this.renderer);
bloomComposer.autoRenderToScreen = true;
bloomComposer.addPass(renderScene);
bloomComposer.addPass(bloomPass);
Also, the bloomTexture
attribute on line 77 is now:
bloomTexture: {value: bloomComposer.inputBuffer.texture}
But I’m not getting the same result, clearly because they work differently.
Additionally, I have to render the composers after I render the scene that has no bloom effect on it and this means the objects in that scene are not shown.
Any guidance is greatly appreciated.