<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="theme-color" content="#ff9900" />
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="icon" href="/content/262266b215d30ab360225b38ae5104d43d60ce122be4f5b5a9e15f125ee21b9fi0" type="image/svg+xml">
<script>
// pristine pixelpunk test with ordengine@0.6.0 ~ bop.xbt
fiber = true
vfx = true
</script>
<script id="ordengine" src="/content/a9bf75af51c9b738b9f044175cf248c39e5d04edce8c63d130f6dab49b3ad92fi0" type="module" defer></script>
<style>
* {
pointer-events: all;
touch-action: auto;
}
</style>
<title>~pristine~</title>
</head>
<body style="margin: 0; background: #000">
<script type="module">
window.init = async function() {
const Cam = () => {
const ref = useRef();
useFrame(() => {
ref.current.rotate(-0.0025, 0, true)
})
useEffect(() => {
ref.current.smoothTime = 0.12
ref.current.minDistance = 6
ref.current.maxDistance = 30
ref.current.rotateAzimuthTo(0.8, false);
ref.current.rotatePolarTo(1.4, false);
ref.current.zoomTo(2.4, true);
window.cam = ref.current
}, [ref])
return html`
<${CameraControls} ref=${ref} makeDefault/>`
}
const Postprocessing = () => {
return html`
<${POST.EffectComposer} disableNormalPass multisampling=0>
<${POST.Bloom} intensity=0.8 luminanceThreshold=0.3 kernelSize=4 />
<${POST.Bloom} intensity=0.5 luminanceThreshold=0.3 mipmapBlur/>
<${POST.Vignette} darkness=0.46/>
<${POST.Noise} opacity=0.015 />
<//>
`
}
const TopBlock = () => {
const ref = useRef();
window.topBlock = ref
const [, api] = useSpring(() => ({
metalness: 0.2,
config: {
mass: 2,
friction: 50,
tension: 300,
},
onChange: (v) => {
ref.current.material.metalness = v.value.metalness;
}
}))
const enPointerEnter = useCallback(() => {
api.start({
metalness: -0.15
})
}, [api])
const enPointerLeave = useCallback(() => {
api.start({
metalness: 0.0
})
}, [api])
const onPointerDown = useCallback(() => {
api.start({
metalness: 0
})
ref.current.material.color = new Color(Math.random() * 1.5, Math.random() * 1.5, Math.random().toFixed(1) * 1.5)
}, [])
return html`
<${DREI.RoundedBox} ref=${ref} args=${[0.6, 0.6, 0.3]} position-y=0.11 onPointerDown=${onPointerDown} onPointerEnter=${enPointerEnter} onPointerLeave=${enPointerLeave}>
<meshStandardMaterial envMapIntensity=0.0 metalness=0.0 roughness=0.8 color=${new Color(1.5, 0.6, 0)} />
</>
`
}
const BottomBlock = () => {
const ref = useRef();
const [, api] = useSpring(() => ({
metalness: -0.65,
config: {
mass: 2,
friction: 50,
tension: 500,
},
onChange: (v) => {
ref.current.material.metalness = v.value.metalness;
}
}))
const enPointerEnter = useCallback(() => {
api.start({
metalness: -1.9
})
}, [])
const enPointerLeave = useCallback(() => {
api.start({
metalness: -0.32
})
}, [])
const onPointerDown = useCallback(() => {
api.start({
metalness: -0.32
})
ref.current.material.color = new Color(Math.random() * 1.5, Math.random() * 1.5, Math.random().toFixed(1) * 1.5)
}, [])
return html`
<${DREI.RoundedBox} ref=${ref} args=${[0.23, 0.23, 0.27]} position=${[-0.185, -0.32, 0]} onPointerDown=${onPointerDown} onPointerEnter=${enPointerEnter} onPointerLeave=${enPointerLeave}>
<meshStandardMaterial envMapIntensity=-0.3 metalness=-0.32 roughness=0.8 color=${new Color(1.5, 0.6, 0)} />
</>
`
}
const FloorMat = DREI.shaderMaterial({
time: 0,
color: new THREE.Color(0.2, 0.0, 0.1)
},
`
varying vec2 vUv;
void main() {
vUv = uv;
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
}
`,
`
uniform float time;
uniform vec3 color;
varying vec2 vUv;
void main() {
vec3 c = vec3(0.03, 0.03, 0.05);
float a = 0.5;
if (fract(vUv.x * 100.) < 0.1) {
c.r = 0.5;
c.g = 0.2;
}
if (fract(vUv.y * 100.) < 0.05) {
c.r = 0.5;
c.g = 0.2;
}
float dist = distance(vUv, vec2(0.5, 0.5));
a -= dist * 4.;
a -= sin(vUv.x * 2.) * 0.3;
if (a < 0.) {
a = 0.;
}
gl_FragColor.rgba = vec4(c, a);
}
`, (mat) => {
// mat.depthWrite = false;
mat.transparent = true;
}
)
FIBER.extend({
FloorMat
})
const Floor = () => {
return html`
<mesh rotation-x=${-Math.PI/2} position-y=-1>
<planeGeometry args=${[40, 40]} />
<floorMat />
</mesh>
`
}
const Particles = () => {
const lifetime = VCF.useParticleLifetime()
const velocity = VCF.useParticleAttribute(() => new Vector3())
const color = VCF.useParticleAttribute(() => new Color())
const time = useConst(() => SC.Time())
const rotation = VCF.useParticleAttribute(() => 0)
return html`
<${VCF.InstancedParticles} frustumCulled=${false}>
<dodecahedronGeometry args=${[0.03]} />
<${MCF.composable.meshBasicMaterial}
side=${THREE.DoubleSide}
transparent
blending=${THREE.AdditiveBlending}
>
<${MCF.modules.Color} color=${SC.Gradient(
lifetime.progress,
[new Color(0, 0, 0), 0],
[color, 0.1],
[new Color(0.0, 0.0, 0.0), 0.9],
)} />
<${MCF.modules.Rotate} rotation=${SC.Rotation3DX(SC.Mul(time, rotation))} />
<${MCF.modules.Billboard} />
<${MCF.modules.Velocity} direction=${velocity} time=${lifetime.age} />
<${MCF.modules.Acceleration}
direction=${new Vector3(0, -0.5, 0)}
time=${lifetime.age}
/>
<${MCF.modules.Lifetime} progress=${lifetime.progress} />
<//>
<${VCF.Emitter}
rate=${24}
setup=${({ mesh, position }) => {
lifetime.write(mesh, RAN.between(1, 3))
if (!window.topBlock.current) return
const c = topBlock.current.material.color
color.write(mesh, (v) => (c.r + c.g + c.b > 2) ? c : new Color(0, 0, 0))
position.x = RAN.between(-0.3, 0.3);
position.y = RAN.between(-0.3, 0.3);
position.z = RAN.between(-0.1, 0.1);
rotation.write(mesh, RAN.plusMinus(2.9))
velocity.write(mesh, (v) =>
v.set(RAN.plusMinus(c.r * 0.3), RAN.between(0.2, c.g), RAN.plusMinus(0.3))
)
}}
/>
<//>
`
}
const Canvas = (props) => {
return html`
<${FIBER.Canvas} ...${props}>
<ambientLight intensity=0.9/>
<directionalLight position=${[3, 4, 2]}/>
<directionalLight position=${[-3, -2, -2]}/>
<${Cam}/>
<${TopBlock} />
<${BottomBlock} />
<${Particles} />
<${Floor} />
<${Postprocessing}/>
<//>
`
}
render({
mainScene: {
component: Canvas,
props: {
dpr: window.devicePixelRatio * 0.12,
camera: {
near: 0.1,
far: 100,
fov: 24,
position: [0, 0, 10],
zppm: 0.001,
},
gl: {
alpha: false,
depth: false,
stencil: false,
antialias: false
}
},
},
})
}
</script>
</body>
</html>
No replies yet