feature: instanced condition

This commit is contained in:
FMS-Cat
2021-03-25 02:57:55 +09:00
parent cb012552b2
commit c3e4c6e5a1
4 changed files with 186 additions and 53 deletions

View File

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

View File

@@ -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

View File

@@ -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;

View File

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