mirror of
https://github.com/FMS-Cat/condition.git
synced 2025-08-11 08:24:22 +02:00
feature: ifs piston
This commit is contained in:
@@ -1,3 +1,4 @@
|
||||
import { gravity } from './gravity';
|
||||
import { hermitePatch } from './hermitePatch';
|
||||
import { repeat } from './repeat';
|
||||
import { sine } from './sine';
|
||||
@@ -5,9 +6,10 @@ import { transpose } from './transpose';
|
||||
|
||||
// quotes! prevent fx names from being mangled
|
||||
const fxDefinitions = {
|
||||
'sine': sine,
|
||||
'repeat': repeat,
|
||||
'gravity': gravity,
|
||||
'hermitePatch': hermitePatch,
|
||||
'repeat': repeat,
|
||||
'sine': sine,
|
||||
'transpose': transpose,
|
||||
};
|
||||
|
||||
|
39
src/automaton-fxs/gravity.ts
Normal file
39
src/automaton-fxs/gravity.ts
Normal file
@@ -0,0 +1,39 @@
|
||||
import type { FxDefinition } from '@fms-cat/automaton';
|
||||
|
||||
export const gravity: FxDefinition = {
|
||||
func( context ) {
|
||||
const dt = context.deltaTime;
|
||||
const v = context.value;
|
||||
|
||||
if ( context.init ) {
|
||||
context.state.pos = v;
|
||||
if ( context.params.preserve ) {
|
||||
const dv = v - context.getValue( context.time - dt );
|
||||
context.state.vel = dv / dt;
|
||||
} else {
|
||||
context.state.vel = 0.0;
|
||||
}
|
||||
}
|
||||
|
||||
const a = Math.sign( v - context.state.pos ) * context.params.a;
|
||||
context.state.vel += a * dt;
|
||||
context.state.pos += context.state.vel * dt;
|
||||
|
||||
if ( Math.sign( a ) !== Math.sign( v - context.state.pos ) ) {
|
||||
context.state.vel *= -context.params.e;
|
||||
context.state.pos = v + context.params.e * ( v - context.state.pos );
|
||||
}
|
||||
|
||||
return context.state.pos;
|
||||
}
|
||||
};
|
||||
|
||||
if ( process.env.DEV ) {
|
||||
gravity.name = 'Gravity';
|
||||
gravity.description = 'Accelerate and bounce the curve.';
|
||||
gravity.params = {
|
||||
a: { name: 'Acceleration', type: 'float', default: 9.8 },
|
||||
e: { name: 'Restitution', type: 'float', default: 0.5, min: 0.0 },
|
||||
preserve: { name: 'Preserve Velocity', type: 'boolean', default: false }
|
||||
};
|
||||
}
|
File diff suppressed because one or more lines are too long
@@ -2,7 +2,7 @@ import { BufferRenderTarget, BufferRenderTargetOptions } from '../heck/BufferRen
|
||||
import { Entity } from '../heck/Entity';
|
||||
import { Geometry } from '../heck/Geometry';
|
||||
import { Lambda } from '../heck/components/Lambda';
|
||||
import { Material, MaterialMap, MaterialTag } from '../heck/Material';
|
||||
import { Material, MaterialMap } from '../heck/Material';
|
||||
import { Mesh } from '../heck/components/Mesh';
|
||||
import { Quad } from '../heck/components/Quad';
|
||||
import { Swap } from '@fms-cat/experimental';
|
||||
@@ -12,7 +12,7 @@ import { objectValuesMap } from '../utils/objectEntriesMap';
|
||||
export interface GPUParticlesOptions {
|
||||
materialCompute: Material;
|
||||
geometryRender: Geometry;
|
||||
materialsRender: Partial<MaterialMap<MaterialTag>>;
|
||||
materialsRender: MaterialMap;
|
||||
computeWidth: number;
|
||||
computeHeight: number;
|
||||
computeNumBuffers: number;
|
||||
|
73
src/entities/IFSPiston.ts
Normal file
73
src/entities/IFSPiston.ts
Normal file
@@ -0,0 +1,73 @@
|
||||
import { Entity } from '../heck/Entity';
|
||||
import { Geometry } from '../heck/Geometry';
|
||||
import { Lambda } from '../heck/components/Lambda';
|
||||
import { MaterialMap } from '../heck/Material';
|
||||
import { Mesh, MeshCull } from '../heck/components/Mesh';
|
||||
import { Quaternion, Vector3 } from '@fms-cat/experimental';
|
||||
import { auto } from '../globals/automaton';
|
||||
import { objectValuesMap } from '../utils/objectEntriesMap';
|
||||
|
||||
interface IFSPistonOptions {
|
||||
group: number;
|
||||
geometry: Geometry;
|
||||
materials: MaterialMap;
|
||||
}
|
||||
|
||||
export class IFSPiston extends Entity {
|
||||
public constructor( { group, geometry, materials }: IFSPistonOptions ) {
|
||||
super();
|
||||
|
||||
const entityCube = new Entity();
|
||||
entityCube.transform.position = new Vector3( [ 0.0, 10.0, 0.0 ] );
|
||||
this.children.push( entityCube );
|
||||
|
||||
// -- animation --------------------------------------------------------------------------------
|
||||
const up = new Vector3( [ 0, 1, 0 ] );
|
||||
|
||||
auto( `IFSPistons/group${ group }/rot`, ( { value } ) => {
|
||||
entityCube.transform.rotation = Quaternion.fromAxisAngle( up, 4.0 * Math.PI * value );
|
||||
} );
|
||||
|
||||
// -- updater ----------------------------------------------------------------------------------
|
||||
entityCube.components.push( new Lambda( {
|
||||
onDraw: ( event ) => {
|
||||
objectValuesMap( materials, ( material ) => {
|
||||
if ( material == null ) { return; }
|
||||
|
||||
material.addUniform(
|
||||
'ifsSeed',
|
||||
'1f',
|
||||
auto( `IFSPistons/group${ group }/rot` ) + 60.0 * group,
|
||||
);
|
||||
|
||||
material.addUniform(
|
||||
'cameraNearFar',
|
||||
'2f',
|
||||
event.camera.near,
|
||||
event.camera.far
|
||||
);
|
||||
|
||||
material.addUniformMatrixVector(
|
||||
'inversePVM',
|
||||
'Matrix4fv',
|
||||
event.projectionMatrix
|
||||
.multiply( event.viewMatrix )
|
||||
.multiply( event.globalTransform.matrix )
|
||||
.inverse!
|
||||
.elements
|
||||
);
|
||||
} );
|
||||
},
|
||||
name: process.env.DEV && 'IFSPiston/updater',
|
||||
} ) );
|
||||
|
||||
// -- mesh -------------------------------------------------------------------------------------
|
||||
const mesh = new Mesh( {
|
||||
geometry,
|
||||
materials,
|
||||
name: process.env.DEV && 'IFSPiston/mesh',
|
||||
} );
|
||||
mesh.cull = MeshCull.None;
|
||||
entityCube.components.push( mesh );
|
||||
}
|
||||
}
|
87
src/entities/IFSPistons.ts
Normal file
87
src/entities/IFSPistons.ts
Normal file
@@ -0,0 +1,87 @@
|
||||
import { Entity } from '../heck/Entity';
|
||||
import { Geometry } from '../heck/Geometry';
|
||||
import { IFSPiston } from './IFSPiston';
|
||||
import { Material } from '../heck/Material';
|
||||
import { Vector3 } from '@fms-cat/experimental';
|
||||
import { auto } from '../globals/automaton';
|
||||
import { dummyRenderTarget, dummyRenderTargetFourDrawBuffers } from '../globals/dummyRenderTarget';
|
||||
import { genCube } from '../geometries/genCube';
|
||||
import { objectValuesMap } from '../utils/objectEntriesMap';
|
||||
import { quatFromUnitVectors } from '../utils/quatFromUnitVectors';
|
||||
import ifsPistonFrag from '../shaders/ifs-piston.frag';
|
||||
import raymarchObjectVert from '../shaders/raymarch-object.vert';
|
||||
|
||||
export class IFSPistons extends Entity {
|
||||
public constructor() {
|
||||
super();
|
||||
|
||||
// -- geometry ---------------------------------------------------------------------------------
|
||||
const cube = genCube( { dimension: [ 1.1, 10.1, 1.1 ] } );
|
||||
|
||||
const geometry = new Geometry();
|
||||
|
||||
geometry.vao.bindVertexbuffer( cube.position, 0, 3 );
|
||||
geometry.vao.bindIndexbuffer( cube.index );
|
||||
|
||||
geometry.count = cube.count;
|
||||
geometry.mode = cube.mode;
|
||||
geometry.indexType = cube.indexType;
|
||||
|
||||
// -- materials --------------------------------------------------------------------------------
|
||||
const deferred = new Material(
|
||||
raymarchObjectVert,
|
||||
ifsPistonFrag,
|
||||
{
|
||||
defines: [ 'DEFERRED 1' ],
|
||||
initOptions: { geometry, target: dummyRenderTargetFourDrawBuffers },
|
||||
},
|
||||
);
|
||||
|
||||
const depth = new Material(
|
||||
raymarchObjectVert,
|
||||
ifsPistonFrag,
|
||||
{
|
||||
defines: [ 'SHADOW 1' ],
|
||||
initOptions: { geometry, target: dummyRenderTarget }
|
||||
},
|
||||
);
|
||||
|
||||
const materials = { deferred, depth };
|
||||
|
||||
if ( process.env.DEV ) {
|
||||
if ( module.hot ) {
|
||||
module.hot.accept( '../shaders/ifs-piston.frag', () => {
|
||||
deferred.replaceShader( raymarchObjectVert, ifsPistonFrag );
|
||||
depth.replaceShader( raymarchObjectVert, ifsPistonFrag );
|
||||
} );
|
||||
}
|
||||
}
|
||||
|
||||
objectValuesMap( materials, ( material ) => {
|
||||
material.addUniform( 'range', '4f', -1.0, -1.0, 1.0, 1.0 );
|
||||
} );
|
||||
|
||||
// -- children pistons -------------------------------------------------------------------------
|
||||
const up = new Vector3( [ 0, 1, 0 ] );
|
||||
|
||||
( [
|
||||
[ new Vector3( [ 1, 1, 0 ] ).normalized, 0 ],
|
||||
[ new Vector3( [ -1, -1, 0 ] ).normalized, 0 ],
|
||||
[ new Vector3( [ -1, 1, 0 ] ).normalized, 1 ],
|
||||
[ new Vector3( [ 1, -1, 0 ] ).normalized, 1 ],
|
||||
] as [ Vector3, number ][] ).map( ( [ v, group ] ) => {
|
||||
const piston = new IFSPiston( { group, geometry, materials } );
|
||||
|
||||
piston.transform.position = v.scale( 1.5 );
|
||||
piston.transform.rotation = quatFromUnitVectors( up, v );
|
||||
|
||||
auto( `IFSPistons/group${ group }/pos`, ( { value } ) => {
|
||||
piston.transform.position = v.scale( value );
|
||||
} );
|
||||
|
||||
this.children.push( piston );
|
||||
|
||||
return piston;
|
||||
} );
|
||||
}
|
||||
}
|
@@ -10,7 +10,11 @@ interface ResultGenCube {
|
||||
indexType: GLenum;
|
||||
}
|
||||
|
||||
export function genCube(): ResultGenCube {
|
||||
export function genCube( options?: {
|
||||
dimension?: [ number, number, number ]
|
||||
} ): ResultGenCube {
|
||||
const dimension = options?.dimension ?? [ 1, 1, 1 ];
|
||||
|
||||
const pos: number[] = [];
|
||||
const nor: number[] = [];
|
||||
const ind: number[] = [];
|
||||
@@ -29,7 +33,7 @@ export function genCube(): ResultGenCube {
|
||||
];
|
||||
|
||||
for ( let i = 0; i < 6; i ++ ) {
|
||||
const func = ( v: number[] ): number[] => {
|
||||
const rotate = ( v: number[] ): number[] => {
|
||||
const vt: number[] = [];
|
||||
|
||||
if ( i < 4 ) {
|
||||
@@ -47,8 +51,16 @@ export function genCube(): ResultGenCube {
|
||||
return vt;
|
||||
};
|
||||
|
||||
pos.push( ...p.map( func ).flat() );
|
||||
nor.push( ...n.map( func ).flat() );
|
||||
const scale = ( v: number[] ): number[] => {
|
||||
return [
|
||||
v[ 0 ] * dimension[ 0 ],
|
||||
v[ 1 ] * dimension[ 1 ],
|
||||
v[ 2 ] * dimension[ 2 ],
|
||||
];
|
||||
};
|
||||
|
||||
pos.push( ...p.map( rotate ).map( scale ).flat() );
|
||||
nor.push( ...n.map( rotate ).flat() );
|
||||
ind.push( ...[ 0, 1, 3, 0, 3, 2 ].map( ( v ) => v + 4 * i ) );
|
||||
}
|
||||
|
||||
|
@@ -10,7 +10,7 @@ export type MaterialTag =
|
||||
| 'forward'
|
||||
| 'depth';
|
||||
|
||||
export type MaterialMap<T extends MaterialTag = MaterialTag> = { [ tag in T ]: Material };
|
||||
export type MaterialMap = { [ tag in MaterialTag ]?: Material };
|
||||
|
||||
export interface MaterialInitOptions {
|
||||
target: RenderTarget;
|
||||
|
@@ -1,6 +1,6 @@
|
||||
import { Component, ComponentDrawEvent, ComponentOptions } from './Component';
|
||||
import { Geometry } from '../Geometry';
|
||||
import { MaterialMap, MaterialTag } from '../Material';
|
||||
import { MaterialMap } from '../Material';
|
||||
import { glCat } from '../../globals/canvas';
|
||||
|
||||
export enum MeshCull {
|
||||
@@ -18,12 +18,12 @@ const meshCullMap = {
|
||||
|
||||
export interface MeshOptions extends ComponentOptions {
|
||||
geometry: Geometry;
|
||||
materials: Partial<MaterialMap<MaterialTag>>;
|
||||
materials: MaterialMap;
|
||||
}
|
||||
|
||||
export class Mesh extends Component {
|
||||
public geometry: Geometry;
|
||||
public materials: Partial<MaterialMap<MaterialTag>>;
|
||||
public materials: MaterialMap;
|
||||
|
||||
public cull: MeshCull = MeshCull.Back;
|
||||
|
||||
@@ -64,7 +64,7 @@ export class Mesh extends Component {
|
||||
program.uniform( 'cameraPos', '3f', ...event.cameraTransform.position.elements );
|
||||
program.uniform( 'cameraNearFar', '2f', event.camera.near, event.camera.far );
|
||||
|
||||
program.uniformMatrixVector( 'normalMatrix', 'Matrix4fv', event.globalTransform.matrix.inverse!.transpose.elements );
|
||||
program.uniformMatrixVector( 'normalMatrix', 'Matrix4fv', event.globalTransform.matrix.inverse!.elements, true );
|
||||
program.uniformMatrixVector( 'modelMatrix', 'Matrix4fv', event.globalTransform.matrix.elements );
|
||||
program.uniformMatrixVector( 'viewMatrix', 'Matrix4fv', event.viewMatrix.elements );
|
||||
program.uniformMatrixVector( 'projectionMatrix', 'Matrix4fv', event.projectionMatrix.elements );
|
||||
|
@@ -6,6 +6,7 @@ import { canvas } from './globals/canvas';
|
||||
import { dog } from './scene';
|
||||
import { getCheckboxActive, getDivCanvasContainer } from './globals/dom';
|
||||
import { music } from './globals/music';
|
||||
import type { AutomatonWithGUI } from '@fms-cat/automaton-with-gui';
|
||||
|
||||
// == dom ==========================================================================================
|
||||
document.body.style.margin = '0';
|
||||
@@ -54,7 +55,7 @@ if ( process.env.DEV ) {
|
||||
music.isPlaying = false;
|
||||
checkboxActive.checked = false;
|
||||
} else if ( event.key === ' ' ) {
|
||||
music.isPlaying = !music.isPlaying;
|
||||
( automaton as AutomatonWithGUI ).togglePlay();
|
||||
} else if ( event.key === 'ArrowLeft' ) {
|
||||
music.time -= 480.0 / MUSIC_BPM;
|
||||
automaton.reset();
|
||||
|
196
src/shaders/ifs-piston.frag
Normal file
196
src/shaders/ifs-piston.frag
Normal file
@@ -0,0 +1,196 @@
|
||||
#version 300 es
|
||||
|
||||
precision highp float;
|
||||
|
||||
#define fs(i) (fract(sin((i)*114.514)*1919.810))
|
||||
#define saturate(x) clamp(x,0.,1.)
|
||||
#define linearstep(a,b,x) saturate(((x)-(a))/((b)-(a)))
|
||||
|
||||
const int MARCH_ITER = 90;
|
||||
const int MTL_UNLIT = 1;
|
||||
const int MTL_PBR = 2;
|
||||
const int MTL_GRADIENT = 3;
|
||||
const int MTL_IRIDESCENT = 4;
|
||||
const float PI = 3.14159265;
|
||||
const float TAU = PI * 2.0;
|
||||
|
||||
#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
|
||||
|
||||
in vec4 vPosition;
|
||||
|
||||
#ifdef SHADOW
|
||||
out vec4 fragColor;
|
||||
#endif
|
||||
|
||||
uniform float deformAmp;
|
||||
uniform float deformFreq;
|
||||
uniform float deformTime;
|
||||
uniform float time;
|
||||
uniform float ifsSeed;
|
||||
uniform vec2 resolution;
|
||||
uniform vec2 cameraNearFar;
|
||||
uniform vec3 cameraPos;
|
||||
uniform mat4 normalMatrix;
|
||||
uniform mat4 modelMatrix;
|
||||
uniform mat4 viewMatrix;
|
||||
uniform mat4 projectionMatrix;
|
||||
uniform mat4 inversePVM;
|
||||
uniform sampler2D samplerRandom;
|
||||
uniform sampler2D samplerRandomStatic;
|
||||
uniform sampler2D samplerCapture;
|
||||
|
||||
vec3 divideByW( vec4 v ) {
|
||||
return v.xyz / v.w;
|
||||
}
|
||||
|
||||
// https://www.iquilezles.org/www/articles/smin/smin.htm
|
||||
float smin( float a, float b, float k ) {
|
||||
float h = max( k - abs( a - b ), 0.0 ) / k;
|
||||
return min( a, b ) - h * h * h * k * ( 1.0 / 6.0 );
|
||||
}
|
||||
|
||||
mat2 rot2d( float t ) {
|
||||
float c = cos( t );
|
||||
float s = sin( t );
|
||||
return mat2( c, -s, s, c );
|
||||
}
|
||||
|
||||
#pragma glslify: orthBasis = require( ./modules/orthBasis );
|
||||
#pragma glslify: cyclicNoise = require( ./modules/cyclicNoise );
|
||||
|
||||
vec3 ifs( vec3 p, vec3 r, vec3 t ) {
|
||||
vec3 s = t;
|
||||
mat3 bas = orthBasis( r );
|
||||
|
||||
for ( int i = 0; i < 6; i ++ ) {
|
||||
p = abs( p ) - abs( s ) * pow( 1.7, -float( i ) );
|
||||
|
||||
s = bas * s;
|
||||
|
||||
p.xy = p.x < p.y ? p.yx : p.xy;
|
||||
p.yz = p.y < p.z ? p.zy : p.yz;
|
||||
}
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
float box( vec3 p, vec3 s ) {
|
||||
vec3 d = abs( p ) - s;
|
||||
return min( 0.0, max( d.x, max( d.y, d.z ) ) ) + length( max( vec3( 0.0 ), d ) );
|
||||
}
|
||||
|
||||
vec4 map( vec3 p ) {
|
||||
p.y += 10.0;
|
||||
|
||||
float d1, d2;
|
||||
|
||||
{
|
||||
float clampbox = box( p - vec3( 0.0, 10.0, 0.0 ), vec3( 1.0, 10.0, 1.0 ) - 0.1 );
|
||||
|
||||
vec3 r = mix(
|
||||
fs( vec3( 4.7, 2.2, 8.3 ) + floor( ifsSeed ) ),
|
||||
fs( vec3( 4.7, 2.2, 8.3 ) + floor( ifsSeed + 1.0 ) ),
|
||||
fract( ifsSeed )
|
||||
);
|
||||
vec3 t = 0.1 * vec3( 3.0, 2.3, 3.5 );
|
||||
vec3 pt = ifs( p, r, t );
|
||||
|
||||
pt = mod( pt - 0.1, 0.2 ) - 0.1;
|
||||
|
||||
d1 = max( box( pt, vec3( 0.02 ) ), clampbox );
|
||||
}
|
||||
|
||||
{
|
||||
float clampbox = box( p - vec3( 0.0, 10.0, 0.0 ), vec3( 1.0, 10.0, 1.0 ) );
|
||||
|
||||
vec3 r = mix(
|
||||
fs( vec3( 5.3, 1.1, 2.9 ) + floor( ifsSeed ) ),
|
||||
fs( vec3( 5.3, 1.1, 2.9 ) + floor( ifsSeed + 1.0 ) ),
|
||||
fract( ifsSeed )
|
||||
);
|
||||
vec3 t = 0.2 * vec3( 3.0, 2.3, 3.5 );
|
||||
vec3 pt = ifs( p, r, t );
|
||||
|
||||
pt = mod( pt - 0.1, 0.2 ) - 0.1;
|
||||
|
||||
d2 = max( box( pt, vec3( 0.07 ) ), clampbox );
|
||||
}
|
||||
|
||||
return d1 < d2 ? vec4( d1, 1, 0, 0 ) : vec4( d2, 2, 0, 0 );
|
||||
}
|
||||
|
||||
vec3 normalFunc( vec3 p, float dd ) {
|
||||
vec2 d = vec2( 0.0, dd );
|
||||
return normalize( vec3(
|
||||
map( p + d.yxx ).x - map( p - d.yxx ).x,
|
||||
map( p + d.xyx ).x - map( p - d.xyx ).x,
|
||||
map( p + d.xxy ).x - map( p - d.xxy ).x
|
||||
) );
|
||||
}
|
||||
|
||||
void main() {
|
||||
vec2 p = ( gl_FragCoord.xy * 2.0 - resolution ) / resolution.y;
|
||||
|
||||
vec3 rayOri = divideByW( inversePVM * vec4( p, 0.0, 1.0 ) );
|
||||
vec3 farPos = divideByW( inversePVM * vec4( p, 1.0, 1.0 ) );
|
||||
vec3 rayDir = normalize( farPos - rayOri );
|
||||
float rayLen = length( vPosition.xyz - cameraPos );
|
||||
vec3 rayPos = rayOri + rayDir * rayLen;
|
||||
vec4 isect;
|
||||
|
||||
for ( int i = 0; i < MARCH_ITER; i ++ ) {
|
||||
isect = map( rayPos );
|
||||
rayLen += 0.5 * isect.x;
|
||||
rayPos = rayOri + rayDir * rayLen;
|
||||
|
||||
if ( abs( isect.x ) < 1E-3 ) { break; }
|
||||
if ( rayLen > cameraNearFar.y ) { break; }
|
||||
}
|
||||
|
||||
if ( 0.01 < isect.x ) {
|
||||
discard;
|
||||
}
|
||||
|
||||
vec3 modelNormal = ( normalMatrix * vec4( normalFunc( rayPos, 1E-3 ), 1.0 ) ).xyz;
|
||||
|
||||
vec4 modelPos = modelMatrix * vec4( rayPos, 1.0 );
|
||||
vec4 projPos = projectionMatrix * viewMatrix * modelPos; // terrible
|
||||
float depth = projPos.z / projPos.w;
|
||||
gl_FragDepth = 0.5 + 0.5 * depth;
|
||||
|
||||
#ifdef DEFERRED
|
||||
fragPosition = vec4( modelPos.xyz, depth );
|
||||
fragNormal = vec4( modelNormal, 1.0 );
|
||||
|
||||
if ( isect.y == 2.0 ) {
|
||||
vec3 noise = cyclicNoise( 6.0 * rayPos );
|
||||
vec3 noiseDetail = cyclicNoise( vec3( 38.0, 1.0, 1.0 ) * ( orthBasis( vec3( 1 ) ) * rayPos ) );
|
||||
float roughness = (
|
||||
0.6 +
|
||||
0.1 * noise.x +
|
||||
0.2 * smoothstep( -0.2, 0.4, noise.y ) * ( 0.8 + 0.2 * sin( 17.0 * noiseDetail.x ) )
|
||||
);
|
||||
|
||||
fragColor = vec4( vec3( 0.4 ), 1.0 );
|
||||
fragWTF = vec4( vec3( roughness, 0.9, 0.0 ), MTL_PBR );
|
||||
} else if ( isect.y == 1.0 ) {
|
||||
fragColor = vec4( vec3( 1.0 ), 1.0 );
|
||||
fragWTF = vec4( vec3( 0.3, 0.1, 0.0 ), MTL_PBR );
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef SHADOW
|
||||
float shadowDepth = linearstep(
|
||||
cameraNearFar.x,
|
||||
cameraNearFar.y,
|
||||
length( cameraPos - rayPos )
|
||||
);
|
||||
fragColor = vec4( shadowDepth, shadowDepth * shadowDepth, shadowDepth, 1.0 );
|
||||
#endif
|
||||
}
|
@@ -34,6 +34,8 @@ uniform float time;
|
||||
uniform vec2 resolution;
|
||||
uniform vec2 cameraNearFar;
|
||||
uniform vec3 cameraPos;
|
||||
uniform mat4 normalMatrix;
|
||||
uniform mat4 modelMatrix;
|
||||
uniform mat4 viewMatrix;
|
||||
uniform mat4 projectionMatrix;
|
||||
uniform mat4 inversePVM;
|
||||
@@ -130,17 +132,17 @@ void main() {
|
||||
discard;
|
||||
}
|
||||
|
||||
vec3 normal = normalFunc( rayPos, 1E-2 );
|
||||
vec4 color = vec4( 0.4, 0.7, 0.9, 1.0 );
|
||||
vec3 modelNormal = ( normalMatrix * vec4( normalFunc( rayPos, 1E-2 ), 1.0 ) ).xyz;
|
||||
|
||||
vec4 projPos = projectionMatrix * viewMatrix * vec4( rayPos, 1.0 ); // terrible
|
||||
vec4 modelPos = modelMatrix * vec4( rayPos, 1.0 );
|
||||
vec4 projPos = projectionMatrix * viewMatrix * modelPos; // terrible
|
||||
float depth = projPos.z / projPos.w;
|
||||
gl_FragDepth = 0.5 + 0.5 * depth;
|
||||
|
||||
#ifdef DEFERRED
|
||||
fragPosition = vec4( rayPos, depth );
|
||||
fragNormal = vec4( normal, 1.0 );
|
||||
fragColor = color;
|
||||
fragPosition = vec4( modelPos.xyz, depth );
|
||||
fragNormal = vec4( modelNormal, 1.0 );
|
||||
fragColor = vec4( 0.4, 0.7, 0.9, 1.0 );
|
||||
fragWTF = vec4( vec3( 0.9, 0.2, 0.0 ), MTL_PBR );
|
||||
#endif
|
||||
|
||||
|
21
src/utils/quatFromUnitVectors.ts
Normal file
21
src/utils/quatFromUnitVectors.ts
Normal file
@@ -0,0 +1,21 @@
|
||||
import { Quaternion, Vector3 } from '@fms-cat/experimental';
|
||||
|
||||
// https://github.com/mrdoob/three.js/blob/94f043c4e105eb73236529231388402da2b07cba/src/math/Quaternion.js#L362
|
||||
export function quatFromUnitVectors( a: Vector3, b: Vector3 ): Quaternion {
|
||||
const r = a.dot( b ) + 1.0;
|
||||
|
||||
if ( r < 1E-4 ) {
|
||||
if ( Math.abs( a.x ) > Math.abs( a.z ) ) {
|
||||
return new Quaternion( [ -a.y, a.x, 0.0, r ] ).normalized;
|
||||
} else {
|
||||
return new Quaternion( [ 0.0, -a.z, a.y, r ] ).normalized;
|
||||
}
|
||||
} else {
|
||||
return new Quaternion( [
|
||||
a.y * b.z - a.z * b.y,
|
||||
a.z * b.x - a.x * b.z,
|
||||
a.x * b.y - a.y * b.x,
|
||||
r,
|
||||
] ).normalized;
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user