From 1204bdaf37d4e41763489cb9500e4dab75f5d4b6 Mon Sep 17 00:00:00 2001 From: FMS-Cat Date: Wed, 31 Mar 2021 19:10:25 +0900 Subject: [PATCH] feature: add chaos torus --- src/automaton-fxs/ChaosTorus.ts | 84 +++++++++++++++++++++++++++++++++ src/entities/SceneCrystals.ts | 30 +++++++++++- src/shaders/chaos-torus.frag | 58 +++++++++++++++++++++++ src/shaders/chaos-torus.vert | 41 ++++++++++++++++ 4 files changed, 212 insertions(+), 1 deletion(-) create mode 100644 src/automaton-fxs/ChaosTorus.ts create mode 100644 src/shaders/chaos-torus.frag create mode 100644 src/shaders/chaos-torus.vert diff --git a/src/automaton-fxs/ChaosTorus.ts b/src/automaton-fxs/ChaosTorus.ts new file mode 100644 index 0000000..30d55d2 --- /dev/null +++ b/src/automaton-fxs/ChaosTorus.ts @@ -0,0 +1,84 @@ +import { Entity } from '../heck/Entity'; +import { Geometry } from '../heck/Geometry'; +import { Material } from '../heck/Material'; +import { Mesh, MeshCull } from '../heck/components/Mesh'; +import { dummyRenderTarget } from '../globals/dummyRenderTarget'; +import { genTorus } from '../geometries/genTorus'; +import chaosTorusFrag from '../shaders/chaos-torus.frag'; +import chaosTorusVert from '../shaders/chaos-torus.vert'; +import depthFrag from '../shaders/depth.frag'; + +export class ChaosTorus extends Entity { + public constructor() { + super(); + + // -- geometry --------------------------------------------------------------------------------- + const torus = genTorus( { segmentsRadial: 64, segmentsTubular: 8 } ); + + const geometry = new Geometry(); + + geometry.vao.bindVertexbuffer( torus.position, 0, 3 ); + geometry.vao.bindVertexbuffer( torus.normal, 1, 3 ); + geometry.vao.bindIndexbuffer( torus.index ); + + geometry.count = torus.count; + geometry.mode = torus.mode; + geometry.indexType = torus.indexType; + + // -- materials -------------------------------------------------------------------------------- + const cubemap = new Material( + chaosTorusVert, + chaosTorusFrag, + { + defines: [ 'FORWARD 1' ], + initOptions: { geometry, target: dummyRenderTarget }, + }, + ); + + const deferred = new Material( + chaosTorusVert, + chaosTorusFrag, + { + defines: [ 'DEFERRED 1' ], + initOptions: { geometry, target: dummyRenderTarget }, + }, + ); + + const depth = new Material( + chaosTorusVert, + depthFrag, + { initOptions: { geometry, target: dummyRenderTarget } }, + ); + + const materials = { + cubemap, + deferred, + depth, + }; + + if ( process.env.DEV ) { + if ( module.hot ) { + module.hot.accept( + [ + '../shaders/chaos-torus.vert', + '../shaders/chaos-torus.frag', + ], + () => { + cubemap.replaceShader( chaosTorusVert, chaosTorusFrag ); + deferred.replaceShader( chaosTorusVert, chaosTorusFrag ); + depth.replaceShader( chaosTorusVert, depthFrag ); + }, + ); + } + } + + // -- mesh ------------------------------------------------------------------------------------- + const mesh = new Mesh( { + geometry, + materials, + name: process.env.DEV && 'ChaosTorus/mesh', + } ); + mesh.cull = MeshCull.None; + this.components.push( mesh ); + } +} diff --git a/src/entities/SceneCrystals.ts b/src/entities/SceneCrystals.ts index 8c18720..fd3cde4 100644 --- a/src/entities/SceneCrystals.ts +++ b/src/entities/SceneCrystals.ts @@ -1,13 +1,16 @@ +import { ChaosTorus } from '../automaton-fxs/ChaosTorus'; import { Crystal } from './Crystal'; import { Entity } from '../heck/Entity'; import { Lambda } from '../heck/components/Lambda'; -import { Quaternion, Vector3 } from '@fms-cat/experimental'; +import { Quaternion, Vector3, Xorshift } from '@fms-cat/experimental'; import { Rings } from './Rings'; +import { auto } from '../globals/automaton'; export class SceneCrystals extends Entity { public constructor() { super(); + // -- crystals --------------------------------------------------------------------------------- const crystal = new Crystal( { width: 0.4, height: 1.5, noiseOffset: 7.0 } ); this.children.push( crystal ); @@ -28,6 +31,7 @@ export class SceneCrystals extends Entity { speen.children.push( smolCrystal ); } + // -- rings ------------------------------------------------------------------------------------ const rings = new Rings(); rings.transform.rotation = Quaternion.fromAxisAngle( new Vector3( [ 1.0, 0.0, 0.0 ] ), @@ -37,5 +41,29 @@ export class SceneCrystals extends Entity { 0.1, ) ); this.children.push( rings ); + + // -- chaos torus ------------------------------------------------------------------------------ + const rng = new Xorshift( 618954 ); + const chaosToruses = [ ...Array( 6 ).keys() ].map( () => { + const pivot = new Entity(); + pivot.transform.rotation = Quaternion.fromAxisAngle( + new Vector3( [ 1.0, 0.0, 0.0 ] ), + rng.gen() * 6.0, + ).multiply( Quaternion.fromAxisAngle( + new Vector3( [ 0.0, 1.0, 0.0 ] ), + rng.gen() * 6.0, + ) ); + this.children.push( pivot ); + + const chaosTorus = new ChaosTorus(); + chaosTorus.transform.position = new Vector3( [ 2.5, 0.0, 0.0 ] ); + pivot.children.push( chaosTorus ); + + return pivot; + } ); + + auto( 'SceneCrystals/ChaosTorus/active', ( { uninit } ) => { + chaosToruses.map( ( entity ) => ( entity.visible = !uninit ) ); + } ); } } diff --git a/src/shaders/chaos-torus.frag b/src/shaders/chaos-torus.frag new file mode 100644 index 0000000..d914395 --- /dev/null +++ b/src/shaders/chaos-torus.frag @@ -0,0 +1,58 @@ +#version 300 es + +precision highp float; + +const int MTL_PBR = 2; + +in float vLife; +in vec3 vNormal; +in vec4 vPosition; +in vec4 vPositionShaft; + +#ifdef FORWARD + out vec4 fragColor; +#endif + +#ifdef DEFERRED + layout (location = 0) out vec4 fragPosition; + layout (location = 1) out vec4 fragNormal; + layout (location = 2) out vec4 fragColor; + layout (location = 3) out vec4 fragWTF; +#endif + +#ifdef DEPTH + out vec4 fragColor; +#endif + +uniform float time; +uniform vec2 cameraNearFar; +uniform vec3 cameraPos; + +#pragma glslify: cyclicNoise = require( ./modules/cyclicNoise ); + +void main() { + vec3 noisep = vNormal.xyz + 4.0 * time + atan( vPositionShaft.x, vPositionShaft.z ); + float noise = cyclicNoise( 4.0 * noisep ).x; + + if ( noise < 0.0 ) { discard; } + + #ifdef FORWARD + fragColor = vec4( 8.0 * vec3( 0.1, 0.4, 1.0 ), 1.0 ); + #endif + + #ifdef DEFERRED + fragPosition = vPosition; + fragNormal = vec4( normalize( vNormal ), 1.0 ); + fragColor = vec4( vec3( 0.001 ), 1.0 ); + fragWTF = vec4( vec3( 0.99, 0.01, 0.0 ), MTL_PBR ); + #endif + + #ifdef DEPTH + float depth = linearstep( + cameraNearFar.x, + cameraNearFar.y, + length( cameraPos - vPosition.xyz ) + ); + fragColor = vec4( depth, depth * depth, depth, 1.0 ); + #endif +} diff --git a/src/shaders/chaos-torus.vert b/src/shaders/chaos-torus.vert new file mode 100644 index 0000000..5d938eb --- /dev/null +++ b/src/shaders/chaos-torus.vert @@ -0,0 +1,41 @@ +#version 300 es + +const float TAU = 6.283185307; + +layout (location = 0) in vec3 position; +layout (location = 1) in vec3 normal; + +out vec4 vPositionShaft; +out vec4 vPosition; +out vec3 vNormal; + +uniform float time; +uniform vec2 resolution; +uniform mat4 projectionMatrix; +uniform mat4 viewMatrix; +uniform mat4 modelMatrix; +uniform mat4 normalMatrix; + +#pragma glslify: cyclicNoise = require( ./modules/cyclicNoise ); + +mat2 rotate2D( float t ) { + return mat2( cos( t ), sin( t ), -sin( t ), cos( t ) ); +} + +void main() { + vNormal = normalize( ( normalMatrix * vec4( normal, 1.0 ) ).xyz ); + + vPosition = vPositionShaft = vec4( 3.0 * position, 1.0 ); + vPosition.xyz += 0.3 * normal; + + vec3 noisep = vNormal.xyz + time + atan( vPositionShaft.x, vPositionShaft.z ); + vPosition.xyz += 0.5 * cyclicNoise( noisep + 3.0 ); + + vPosition = modelMatrix * vPosition; + + vec4 outPos = projectionMatrix * viewMatrix * vPosition; + outPos.x *= resolution.y / resolution.x; + gl_Position = outPos; + + vPosition.w = outPos.z / outPos.w; +}