Three.js - Fireflies Shader
Aus Wikizone
Version vom 6. Februar 2022, 11:07 Uhr von 134.3.74.15 (Diskussion)
Links[Bearbeiten]
Three.js - Shaders
Beispiel[Bearbeiten]
script.js
import firefliesVertexShader from './shaders/fireflies/vertex.glsl'
import firefliesFragmentShader from './shaders/fireflies/fragment.glsl'
//...
/**
* Fireflies
*/
const firefliesGeometry = new THREE.BufferGeometry()
const firefliesCount = 30
const positionArray = new Float32Array(firefliesCount * 3)
const scaleArray = new Float32Array(firefliesCount)
for(let i = 0; i < firefliesCount; i++){
positionArray[i * 3 + 0] = ( Math.random() -0.5) * 4.5 // from -0.5 to 4
positionArray[i * 3 + 1] = ( Math.random() + 0.05) * 3 // from 0.05 to 2.95
positionArray[i * 3 + 2] = ( Math.random() ) * 4.5 // from 0 to 4.5
scaleArray[i] = Math.random()
}
firefliesGeometry.setAttribute('position', new THREE.BufferAttribute(positionArray, 3))
firefliesGeometry.setAttribute('aScale', new THREE.BufferAttribute(scaleArray, 1))
//const firefliesMaterial = new THREE.PointsMaterial({ size: 0.1, sizeAttenuation: true })
const firefliesMaterial = new THREE.ShaderMaterial({
transparent: true,
blending: THREE.AdditiveBlending,
depthWrite: false, // fixes some clipping issues
uniforms:{
uPixelRatio : {value: Math.min(window.devicePixelRatio, 2)},
uSize: { value: 100 },
uTime: { value: 0 }
},
vertexShader: firefliesVertexShader,
fragmentShader: firefliesFragmentShader
})
const fireflies = new THREE.Points(firefliesGeometry, firefliesMaterial)
scene.add(fireflies)
gui.add(firefliesMaterial.uniforms.uSize, 'value').min(0).max(500).step(1).name('firefliesSize')
// ...
window.addEventListener('resize', () =>
{
// ...
// Update fireflies
// Update ratio in case s.o. has different screens
firefliesMaterial.uniforms.uPixelRatio.value = Math.min(window.devicePixelRatio, 2)
})
vertex.glsl
uniform float uPixelRatio;
uniform float uSize;
uniform float uTime;
attribute float aScale;
void main()
{
vec4 modelPosition = modelMatrix * vec4(position, 1.0);
modelPosition.y += sin(uTime + modelPosition.x * 100.0) * aScale * 0.2;
// move up and down and use x pos to create a offset
// * aScale -> reduce Amplitude more for smaller fireflies
// * 0.2 -> reduce amplitude in general
vec4 viewPosition = viewMatrix * modelPosition;
vec4 projectionPosition = projectionMatrix * viewPosition;
gl_Position = projectionPosition;
// Take care of retinas etc but not more than 2 (performance)
gl_PointSize = uSize * uPixelRatio * aScale;
gl_PointSize *= (1.0 / - viewPosition.z); // size attenuation (far->smaller)
}
fragment.glsl
void main()
{
//gl_FragColor = vec4(gl_PointCoord, 1.0, 1.0);
float distanceToCenter = distance(gl_PointCoord, vec2(0.5));
float strength = 0.05 / distanceToCenter - 0.1; // -0.1 that our formular reaches 0. Otherwise we'd see borders
gl_FragColor = vec4(1.0, 1.0, 1.0, strength);
}