mirror of
https://github.com/FMS-Cat/condition.git
synced 2025-08-07 22:46:36 +02:00
feature: instanced condition
This commit is contained in:
@@ -1,39 +1,167 @@
|
|||||||
import { Vector3 } from '@fms-cat/experimental';
|
import { Vector3 } from '@fms-cat/experimental';
|
||||||
import { GLCatTexture } from '@fms-cat/glcat-ts';
|
import { gl, glCat } from '../globals/canvas';
|
||||||
import { Entity } from '../heck/Entity';
|
import { Entity } from '../heck/Entity';
|
||||||
|
import { InstancedGeometry } from '../heck/InstancedGeometry';
|
||||||
import { createSVGTableTexture } from '../utils/createSVGTableTexture';
|
import { createSVGTableTexture } from '../utils/createSVGTableTexture';
|
||||||
import { ConditionChar } from './ConditionChar';
|
import conditionVert from '../shaders/condition.vert';
|
||||||
|
import conditionFrag from '../shaders/condition.frag';
|
||||||
|
import { Material } from '../heck/Material';
|
||||||
|
import { dummyRenderTargetFourDrawBuffers, dummyRenderTargetOneDrawBuffers } from '../globals/dummyRenderTarget';
|
||||||
|
import { Mesh } from '../heck/components/Mesh';
|
||||||
|
import { auto } from '../globals/automaton';
|
||||||
|
|
||||||
|
const POINTS_MAX = 256;
|
||||||
|
|
||||||
export class Condition extends Entity {
|
export class Condition extends Entity {
|
||||||
public constructor() {
|
public constructor() {
|
||||||
super();
|
super();
|
||||||
this.transform.scale = new Vector3( [ 0.05, 0.05, 0.05 ] );
|
this.transform.scale = new Vector3( [ 0.05, 0.05, 0.05 ] );
|
||||||
|
|
||||||
const pathC = createSVGTableTexture( 'M5,5l-9,0l-1,-1l0,-8l1,-1l9,0l0,2l-8,0l0,6l8,0Z' );
|
// -- paths ------------------------------------------------------------------------------------
|
||||||
const pathO = createSVGTableTexture( 'M5,4l0,-8l-1,-1l-8,0l-1,1l0,8l1,1l8,0Z' );
|
const texture = createSVGTableTexture( [
|
||||||
const pathOi = createSVGTableTexture( 'M3,3l0,-6l-6,0l0,6Z' );
|
'M5,5l-9,0l-1,-1l0,-8l1,-1l9,0l0,2l-8,0l0,6l8,0Z',
|
||||||
const pathN = createSVGTableTexture( 'M5,4l0,-9l-2,0l0,8l-6,0l0,-8l-2,0l0,9l1,1l8,0Z' );
|
'M5,4l0,-8l-1,-1l-8,0l-1,1l0,8l1,1l8,0Z',
|
||||||
const pathD = createSVGTableTexture( 'M5,4l0,-8l-1,-1l-9,0l0,10l9,0Z' );
|
'M3,3l0,-6l-6,0l0,6Z',
|
||||||
const pathI = createSVGTableTexture( 'M1,5l0,-10l-2,0l0,10Z' );
|
'M5,4l0,-9l-2,0l0,8l-6,0l0,-8l-2,0l0,9l1,1l8,0Z',
|
||||||
const pathT = createSVGTableTexture( 'M5,5l0,-2l-4,0l0,-8l-2,0l0,8l-4,0l0,2Z' );
|
'M5,4l0,-8l-1,-1l-9,0l0,10l9,0Z',
|
||||||
|
'M1,5l0,-10l-2,0l0,10Z',
|
||||||
|
'M5,5l0,-2l-4,0l0,-8l-2,0l0,8l-4,0l0,2Z',
|
||||||
|
] );
|
||||||
|
|
||||||
const tableAndPos: [ GLCatTexture, number ][] = [
|
const tablePos: number[] = [
|
||||||
[ pathC, -20 ],
|
0, -40,
|
||||||
[ pathO, -14 ],
|
1, -28,
|
||||||
[ pathOi, -14 ],
|
2, -28,
|
||||||
[ pathN, -8 ],
|
3, -16,
|
||||||
[ pathD, -2 ],
|
4, -4,
|
||||||
[ pathOi, -2 ],
|
2, -4,
|
||||||
[ pathI, 2 ],
|
5, 4,
|
||||||
[ pathT, 6 ],
|
6, 12,
|
||||||
[ pathI, 10 ],
|
5, 20,
|
||||||
[ pathO, 14 ],
|
1, 28,
|
||||||
[ pathOi, 14 ],
|
2, 28,
|
||||||
[ pathN, 20 ],
|
3, 40,
|
||||||
];
|
];
|
||||||
tableAndPos.forEach( ( [ table, pos ], i ) => {
|
|
||||||
const svgEntity = new ConditionChar( { table, pos, i } );
|
// -- create buffers ---------------------------------------------------------------------------
|
||||||
this.children.push( svgEntity );
|
const arrayPos = [];
|
||||||
|
const arrayInd = [];
|
||||||
|
|
||||||
|
for ( let i = 0; i < POINTS_MAX; i ++ ) {
|
||||||
|
const x = i / POINTS_MAX;
|
||||||
|
arrayPos.push( x, 0, x, 1, x, 2 );
|
||||||
|
|
||||||
|
for ( let j = 0; j < 3; j ++ ) {
|
||||||
|
const j1 = ( j + 1 ) % 3;
|
||||||
|
arrayInd.push(
|
||||||
|
i * 3 + j,
|
||||||
|
i * 3 + 3 + j,
|
||||||
|
i * 3 + 3 + j1,
|
||||||
|
i * 3 + j,
|
||||||
|
i * 3 + 3 + j1,
|
||||||
|
i * 3 + j1,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
arrayPos.push( 1, 0, 1, 1, 1, 2 );
|
||||||
|
|
||||||
|
const bufferPos = glCat.createBuffer();
|
||||||
|
bufferPos.setVertexbuffer( new Float32Array( arrayPos ) );
|
||||||
|
|
||||||
|
const bufferInd = glCat.createBuffer();
|
||||||
|
bufferInd.setIndexbuffer( new Uint16Array( arrayInd ) );
|
||||||
|
|
||||||
|
const arrayIter: number[] = [];
|
||||||
|
|
||||||
|
for ( let i = 0; i < 16; i ++ ) {
|
||||||
|
for ( let j = 0; j < 12; j ++ ) {
|
||||||
|
arrayIter.push(
|
||||||
|
( tablePos[ j * 2 + 0 ] + 0.5 ) / 7.0,
|
||||||
|
tablePos[ j * 2 + 1 ],
|
||||||
|
i,
|
||||||
|
j,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const bufferIter = glCat.createBuffer();
|
||||||
|
bufferIter.setVertexbuffer( new Float32Array( arrayIter ) );
|
||||||
|
|
||||||
|
// -- create geometry --------------------------------------------------------------------------
|
||||||
|
const geometry = new InstancedGeometry();
|
||||||
|
|
||||||
|
geometry.vao.bindVertexbuffer( bufferPos, 0, 2 );
|
||||||
|
geometry.vao.bindIndexbuffer( bufferInd );
|
||||||
|
geometry.vao.bindVertexbuffer( bufferIter, 1, 4, 1 );
|
||||||
|
|
||||||
|
geometry.count = 18 * POINTS_MAX;
|
||||||
|
geometry.mode = gl.TRIANGLES;
|
||||||
|
geometry.indexType = gl.UNSIGNED_SHORT;
|
||||||
|
geometry.primcount = 12 * 16;
|
||||||
|
|
||||||
|
// -- create materials -------------------------------------------------------------------------
|
||||||
|
const materials = {
|
||||||
|
forward: new Material(
|
||||||
|
conditionVert,
|
||||||
|
conditionFrag,
|
||||||
|
{
|
||||||
|
defines: { 'FORWARD': 'true' },
|
||||||
|
initOptions: { geometry, target: dummyRenderTargetOneDrawBuffers },
|
||||||
|
},
|
||||||
|
),
|
||||||
|
deferred: new Material(
|
||||||
|
conditionVert,
|
||||||
|
conditionFrag,
|
||||||
|
{
|
||||||
|
defines: { 'DEFERRED': 'true' },
|
||||||
|
initOptions: { geometry, target: dummyRenderTargetFourDrawBuffers },
|
||||||
|
},
|
||||||
|
),
|
||||||
|
shadow: new Material(
|
||||||
|
conditionVert,
|
||||||
|
conditionFrag,
|
||||||
|
{
|
||||||
|
defines: { 'SHADOW': 'true' },
|
||||||
|
initOptions: { geometry, target: dummyRenderTargetOneDrawBuffers },
|
||||||
|
},
|
||||||
|
),
|
||||||
|
};
|
||||||
|
|
||||||
|
for ( const material of Object.values( materials ) ) {
|
||||||
|
material.addUniformTexture( 'samplerSvg', texture );
|
||||||
|
|
||||||
|
auto( 'Condition/phaseOffset', ( { value } ) => {
|
||||||
|
material.addUniform( 'phaseOffset', '1f', value );
|
||||||
|
} );
|
||||||
|
|
||||||
|
auto( 'Condition/phaseWidth', ( { value } ) => {
|
||||||
|
material.addUniform( 'phaseWidth', '1f', value );
|
||||||
} );
|
} );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ( process.env.DEV ) {
|
||||||
|
if ( module.hot ) {
|
||||||
|
module.hot.accept(
|
||||||
|
[
|
||||||
|
'../shaders/condition.vert',
|
||||||
|
'../shaders/condition.frag',
|
||||||
|
],
|
||||||
|
() => {
|
||||||
|
materials.forward.replaceShader( conditionVert, conditionFrag );
|
||||||
|
materials.deferred.replaceShader( conditionVert, conditionFrag );
|
||||||
|
materials.shadow.replaceShader( conditionVert, conditionFrag );
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// -- create meshes ----------------------------------------------------------------------------
|
||||||
|
const mesh = new Mesh( {
|
||||||
|
geometry,
|
||||||
|
materials,
|
||||||
|
name: process.env.DEV && `Condition/mesh`,
|
||||||
|
} );
|
||||||
|
this.components.push( mesh );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -10,6 +10,7 @@ const int MTL_UNLIT = 1;
|
|||||||
in float vPhase;
|
in float vPhase;
|
||||||
in vec3 vNormal;
|
in vec3 vNormal;
|
||||||
in vec4 vPosition;
|
in vec4 vPosition;
|
||||||
|
in vec4 vHuh;
|
||||||
|
|
||||||
#ifdef FORWARD
|
#ifdef FORWARD
|
||||||
out vec4 fragColor;
|
out vec4 fragColor;
|
||||||
@@ -30,22 +31,23 @@ in vec4 vPosition;
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
uniform float time;
|
uniform float time;
|
||||||
uniform float svgi;
|
|
||||||
uniform float phaseOffset;
|
uniform float phaseOffset;
|
||||||
uniform float phaseWidth;
|
uniform float phaseWidth;
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
float phase = fract( 2.0 * vPhase + 0.1 * time + 0.1 * svgi + phaseOffset );
|
float phase = fract( 2.0 * vPhase + 0.01 * vHuh.z + 0.1 * time + 0.1 * vHuh.y + phaseOffset );
|
||||||
if ( phase > phaseWidth ) { discard; }
|
if ( phase > phaseWidth ) { discard; }
|
||||||
|
|
||||||
|
vec3 color = 2.0 * vec3( exp( -0.2 * vHuh.z ) );
|
||||||
|
|
||||||
#ifdef FORWARD
|
#ifdef FORWARD
|
||||||
fragColor = vec4( 1.0 );
|
fragColor = vec4( color, 1.0 );
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef DEFERRED
|
#ifdef DEFERRED
|
||||||
fragPosition = vPosition;
|
fragPosition = vPosition;
|
||||||
fragNormal = vec4( vNormal, 1.0 );
|
fragNormal = vec4( vNormal, 1.0 );
|
||||||
fragColor = vec4( 1.0 );
|
fragColor = vec4( color, 1.0 );
|
||||||
fragWTF = vec4( vec3( 0.0, 0.0, 0.0 ), MTL_UNLIT );
|
fragWTF = vec4( vec3( 0.0, 0.0, 0.0 ), MTL_UNLIT );
|
||||||
#endif
|
#endif
|
||||||
|
|
@@ -3,10 +3,12 @@
|
|||||||
const float TAU = 6.283185307;
|
const float TAU = 6.283185307;
|
||||||
|
|
||||||
layout (location = 0) in vec2 what;
|
layout (location = 0) in vec2 what;
|
||||||
|
layout (location = 1) in vec4 huh;
|
||||||
|
|
||||||
out float vPhase;
|
out float vPhase;
|
||||||
out vec3 vNormal;
|
out vec3 vNormal;
|
||||||
out vec4 vPosition;
|
out vec4 vPosition;
|
||||||
|
out vec4 vHuh;
|
||||||
|
|
||||||
uniform float time;
|
uniform float time;
|
||||||
uniform vec2 resolution;
|
uniform vec2 resolution;
|
||||||
@@ -20,9 +22,11 @@ uniform sampler2D samplerSvg;
|
|||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
vPhase = what.x;
|
vPhase = what.x;
|
||||||
vec4 tex = texture( samplerSvg, vec2( what.x, 0.5 ) );
|
vHuh = huh;
|
||||||
|
|
||||||
vPosition = vec4( tex.xy, 0.0, 1.0 );
|
vec4 tex = texture( samplerSvg, vec2( what.x, huh.x ) );
|
||||||
|
|
||||||
|
vPosition = vec4( tex.xy + vec2( huh.y, 0.0 ), 6.0 - 12.0 * huh.z, 1.0 );
|
||||||
|
|
||||||
mat3 basis = orthBasis( vec3( tex.zw, 0.0 ) );
|
mat3 basis = orthBasis( vec3( tex.zw, 0.0 ) );
|
||||||
float theta = what.y / 3.0 * TAU;
|
float theta = what.y / 3.0 * TAU;
|
@@ -1,7 +1,10 @@
|
|||||||
import { GLCatTexture } from '@fms-cat/glcat-ts';
|
import { GLCatTexture } from '@fms-cat/glcat-ts';
|
||||||
import { gl, glCat } from '../globals/canvas';
|
import { gl, glCat } from '../globals/canvas';
|
||||||
|
|
||||||
export function createSVGTableTexture( pathStr: string, width = 1024 ): GLCatTexture {
|
export function createSVGTableTexture( pathStrs: string[], width = 1024 ): GLCatTexture {
|
||||||
|
const table: number[] = []; // x, y, dx, dy
|
||||||
|
|
||||||
|
pathStrs.map( ( pathStr ) => {
|
||||||
const svgNamespaceURI = 'http://www.w3.org/2000/svg';
|
const svgNamespaceURI = 'http://www.w3.org/2000/svg';
|
||||||
const path = document.createElementNS( svgNamespaceURI, 'path' );
|
const path = document.createElementNS( svgNamespaceURI, 'path' );
|
||||||
path.setAttribute( 'd', pathStr );
|
path.setAttribute( 'd', pathStr );
|
||||||
@@ -9,8 +12,6 @@ export function createSVGTableTexture( pathStr: string, width = 1024 ): GLCatTex
|
|||||||
const pathLength = path.getTotalLength();
|
const pathLength = path.getTotalLength();
|
||||||
const eps = 0.25 / width * pathLength;
|
const eps = 0.25 / width * pathLength;
|
||||||
|
|
||||||
const table = new Float32Array( 4 * width ); // x, y, dx, dy
|
|
||||||
|
|
||||||
for ( let i = 0; i < width; i ++ ) {
|
for ( let i = 0; i < width; i ++ ) {
|
||||||
const phase = ( ( i + 0.5 ) / width ) * pathLength;
|
const phase = ( ( i + 0.5 ) / width ) * pathLength;
|
||||||
|
|
||||||
@@ -23,17 +24,15 @@ export function createSVGTableTexture( pathStr: string, width = 1024 ): GLCatTex
|
|||||||
const dy = pointdp.y - pointdn.y;
|
const dy = pointdp.y - pointdn.y;
|
||||||
const dl = Math.sqrt( dx * dx + dy * dy );
|
const dl = Math.sqrt( dx * dx + dy * dy );
|
||||||
|
|
||||||
table[ 4 * i + 0 ] = point.x;
|
table.push( point.x, point.y, dx / dl, dy / dl );
|
||||||
table[ 4 * i + 1 ] = point.y;
|
|
||||||
table[ 4 * i + 2 ] = dx / dl;
|
|
||||||
table[ 4 * i + 3 ] = dy / dl;
|
|
||||||
}
|
}
|
||||||
|
} );
|
||||||
|
|
||||||
const texture = glCat.createTexture();
|
const texture = glCat.createTexture();
|
||||||
texture.setTextureFromArray(
|
texture.setTextureFromArray(
|
||||||
width,
|
width,
|
||||||
1,
|
pathStrs.length,
|
||||||
table,
|
new Float32Array( table ),
|
||||||
{ internalformat: gl.RGBA32F, format: gl.RGBA, type: gl.FLOAT },
|
{ internalformat: gl.RGBA32F, format: gl.RGBA, type: gl.FLOAT },
|
||||||
);
|
);
|
||||||
texture.textureWrap( gl.REPEAT );
|
texture.textureWrap( gl.REPEAT );
|
||||||
|
Reference in New Issue
Block a user