Three.js - Fireflies Shader: Unterschied zwischen den Versionen

Aus Wikizone
Wechseln zu: Navigation, Suche
(Die Seite wurde neu angelegt: „script.js <syntaxhighlight lang="javascript"> import firefliesVertexShader from './shaders/fireflies/vertex.glsl' import firefliesFragmentShader from './shader…“)
 
 
Zeile 1: Zeile 1:
 +
== Links ==
 +
[[Three.js - Shaders]]
 +
== Beispiel ==
 
script.js
 
script.js
 
<syntaxhighlight lang="javascript">
 
<syntaxhighlight lang="javascript">

Aktuelle Version vom 6. Februar 2022, 11:07 Uhr

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);
}