diff --git a/src/entities/ConditionChar.ts b/src/entities/ConditionChar.ts index 0a7cf71..a669494 100644 --- a/src/entities/ConditionChar.ts +++ b/src/entities/ConditionChar.ts @@ -1,13 +1,14 @@ import { Mesh } from '../heck/components/Mesh'; import { Entity } from '../heck/Entity'; import { Geometry } from '../heck/Geometry'; -import { Material, MaterialMap } from '../heck/Material'; +import { Material } from '../heck/Material'; import svgVert from '../shaders/svg.vert'; import conditionCharFrag from '../shaders/condition-char.frag'; import { gl, glCat } from '../globals/canvas'; import { Vector3 } from '@fms-cat/experimental'; import { GLCatTexture } from '@fms-cat/glcat-ts'; import { auto } from '../globals/automaton'; +import { dummyRenderTargetFourDrawBuffers, dummyRenderTargetOneDrawBuffers } from '../globals/dummyRenderTarget'; const POINTS_MAX = 256; @@ -23,34 +24,6 @@ export class ConditionChar extends Entity { this.transform.position = this.transform.position.add( new Vector3( [ 2 * pos, 0, 0 ] ) ); - // -- create geometries / materials ------------------------------------------------------------ - const geometry = this.__createGeometry(); - const materials = this.__createMaterials(); - - // -- create meshes ---------------------------------------------------------------------------- - const mesh = new Mesh( { - geometry, - materials, - name: process.env.DEV && `ConditionChar/mesh${ i }`, - } ); - this.components.push( mesh ); - - // -- material uniforms ------------------------------------------------------------------------ - for ( const material of Object.values( materials ) ) { - material.addUniform( 'svgi', '1f', i ); - material.addUniformTexture( 'samplerSvg', table ); - - auto( 'Condition/phaseOffset', ( { value } ) => { - material.addUniform( 'phaseOffset', '1f', value ); - } ); - - auto( 'Condition/phaseWidth', ( { value } ) => { - material.addUniform( 'phaseWidth', '1f', value ); - } ); - } - } - - private __createGeometry(): Geometry { // -- create buffers --------------------------------------------------------------------------- const arrayPos = []; const arrayInd = []; @@ -80,7 +53,7 @@ export class ConditionChar extends Entity { const bufferInd = glCat.createBuffer(); bufferInd.setIndexbuffer( new Uint16Array( arrayInd ) ); - // -- create attributes ------------------------------------------------------------------------ + // -- create geometry -------------------------------------------------------------------------- const geometry = new Geometry(); geometry.vao.bindVertexbuffer( bufferPos, 0, 2 ); @@ -90,27 +63,38 @@ export class ConditionChar extends Entity { geometry.mode = gl.TRIANGLES; geometry.indexType = gl.UNSIGNED_SHORT; - return geometry; - } + // -- create materials ------------------------------------------------------------------------- + const initOptions = { + geometry, + target: dummyRenderTargetFourDrawBuffers, + }; - private __createMaterials(): MaterialMap<'forward' | 'deferred' | 'shadow'> { - const forward = new Material( - svgVert, - conditionCharFrag, - { defines: { 'FORWARD': 'true' } }, - ); - - const deferred = new Material( - svgVert, - conditionCharFrag, - { defines: { 'DEFERRED': 'true' } }, - ); - - const shadow = new Material( - svgVert, - conditionCharFrag, - { defines: { 'SHADOW': 'true' } }, - ); + const materials = { + forward: new Material( + svgVert, + conditionCharFrag, + { + defines: { 'FORWARD': 'true' }, + initOptions: { geometry, target: dummyRenderTargetOneDrawBuffers }, + }, + ), + deferred: new Material( + svgVert, + conditionCharFrag, + { + defines: { 'DEFERRED': 'true' }, + initOptions: { geometry, target: dummyRenderTargetFourDrawBuffers }, + }, + ), + shadow: new Material( + svgVert, + conditionCharFrag, + { + defines: { 'SHADOW': 'true' }, + initOptions: { geometry, target: dummyRenderTargetOneDrawBuffers }, + }, + ), + }; if ( process.env.DEV ) { if ( module.hot ) { @@ -120,14 +104,34 @@ export class ConditionChar extends Entity { '../shaders/condition-char.frag', ], () => { - forward.replaceShader( svgVert, conditionCharFrag ); - deferred.replaceShader( svgVert, conditionCharFrag ); - shadow.replaceShader( svgVert, conditionCharFrag ); + materials.forward.replaceShader( svgVert, conditionCharFrag ); + materials.deferred.replaceShader( svgVert, conditionCharFrag ); + materials.shadow.replaceShader( svgVert, conditionCharFrag ); }, ); } } - return { forward, deferred, shadow }; + // -- create meshes ---------------------------------------------------------------------------- + const mesh = new Mesh( { + geometry, + materials, + name: process.env.DEV && `ConditionChar/mesh${ i }`, + } ); + this.components.push( mesh ); + + // -- material uniforms ------------------------------------------------------------------------ + for ( const material of Object.values( materials ) ) { + material.addUniform( 'svgi', '1f', i ); + material.addUniformTexture( 'samplerSvg', table ); + + auto( 'Condition/phaseOffset', ( { value } ) => { + material.addUniform( 'phaseOffset', '1f', value ); + } ); + + auto( 'Condition/phaseWidth', ( { value } ) => { + material.addUniform( 'phaseWidth', '1f', value ); + } ); + } } } diff --git a/src/entities/Raymarcher.ts b/src/entities/Raymarcher.ts index 85d3863..9f1bf86 100644 --- a/src/entities/Raymarcher.ts +++ b/src/entities/Raymarcher.ts @@ -3,17 +3,16 @@ import { TRIANGLE_STRIP_QUAD, Vector3 } from '@fms-cat/experimental'; import { gl, glCat } from '../globals/canvas'; import { Entity } from '../heck/Entity'; import { Geometry } from '../heck/Geometry'; -import { Material, MaterialMap } from '../heck/Material'; +import { Material } from '../heck/Material'; import quadVert from '../shaders/quad.vert'; import raymarcherFrag from '../shaders/raymarcher.frag'; import { Lambda } from '../heck/components/Lambda'; import { randomTexture, randomTextureStatic } from '../globals/randomTexture'; import { auto } from '../globals/automaton'; +import { dummyRenderTargetFourDrawBuffers, dummyRenderTargetOneDrawBuffers } from '../globals/dummyRenderTarget'; export class Raymarcher { - public materials: MaterialMap<'deferred' | 'shadow'>; public mesh: Mesh; - public geometry: Geometry; public readonly entity: Entity; public constructor() { @@ -21,19 +20,57 @@ export class Raymarcher { this.entity.transform.position = new Vector3( [ 0.0, 0.0, 0.3 ] ); this.entity.transform.scale = new Vector3( [ 16.0, 9.0, 1.0 ] ).scale( 0.15 ); - this.geometry = this.__createGeoemtry(); - this.materials = this.__createMaterials(); + // -- geometry --------------------------------------------------------------------------------- + const geometry = new Geometry(); - for ( const material of Object.values( this.materials ) ) { + const bufferPos = glCat.createBuffer(); + bufferPos.setVertexbuffer( new Float32Array( TRIANGLE_STRIP_QUAD ) ); + + geometry.vao.bindVertexbuffer( bufferPos, 0, 2 ); + + geometry.count = 4; + geometry.mode = gl.TRIANGLE_STRIP; + + // -- materials -------------------------------------------------------------------------------- + const materials = { + deferred: new Material( + quadVert, + raymarcherFrag, + { + defines: { 'DEFERRED': 'true' }, + initOptions: { geometry, target: dummyRenderTargetFourDrawBuffers }, + }, + ), + shadow: new Material( + quadVert, + raymarcherFrag, + { + defines: { 'SHADOW': 'true' }, + initOptions: { geometry, target: dummyRenderTargetOneDrawBuffers } + }, + ), + }; + + if ( process.env.DEV ) { + if ( module.hot ) { + module.hot.accept( '../shaders/raymarcher.frag', () => { + materials.deferred.replaceShader( quadVert, raymarcherFrag ); + materials.shadow.replaceShader( quadVert, raymarcherFrag ); + } ); + } + } + + for ( const material of Object.values( materials ) ) { material.addUniform( 'range', '4f', -1.0, -1.0, 1.0, 1.0 ); material.addUniformTexture( 'samplerRandom', randomTexture.texture ); material.addUniformTexture( 'samplerRandomStatic', randomTextureStatic.texture ); } + // -- updater ---------------------------------------------------------------------------------- this.entity.components.push( new Lambda( { onDraw: ( event ) => { - for ( const material of Object.values( this.materials ) ) { + for ( const material of Object.values( materials ) ) { material.addUniform( 'cameraNearFar', '2f', @@ -56,42 +93,13 @@ export class Raymarcher { name: process.env.DEV && 'Raymarcher/updater', } ) ); + // -- mesh ------------------------------------------------------------------------------------- this.mesh = new Mesh( { - geometry: this.geometry, - materials: this.materials, + geometry: geometry, + materials: materials, name: process.env.DEV && 'Raymarcher/mesh', } ); this.mesh.cull = MeshCull.None; this.entity.components.push( this.mesh ); } - - protected __createGeoemtry(): Geometry { - const geometry = new Geometry(); - - const bufferPos = glCat.createBuffer(); - bufferPos.setVertexbuffer( new Float32Array( TRIANGLE_STRIP_QUAD ) ); - - geometry.vao.bindVertexbuffer( bufferPos, 0, 2 ); - - geometry.count = 4; - geometry.mode = gl.TRIANGLE_STRIP; - - return geometry; - } - - protected __createMaterials(): MaterialMap<'deferred' | 'shadow'> { - const deferred = new Material( quadVert, raymarcherFrag, { defines: { 'DEFERRED': 'true' } } ); - const shadow = new Material( quadVert, raymarcherFrag, { defines: { 'SHADOW': 'true' } } ); - - if ( process.env.DEV ) { - if ( module.hot ) { - module.hot.accept( '../shaders/raymarcher.frag', () => { - deferred.replaceShader( quadVert, raymarcherFrag ); - shadow.replaceShader( quadVert, raymarcherFrag ); - } ); - } - } - - return { deferred, shadow }; - } } diff --git a/src/globals/dummyRenderTarget.ts b/src/globals/dummyRenderTarget.ts new file mode 100644 index 0000000..a72e727 --- /dev/null +++ b/src/globals/dummyRenderTarget.ts @@ -0,0 +1,13 @@ +import { BufferRenderTarget } from '../heck/BufferRenderTarget'; + +export const dummyRenderTargetOneDrawBuffers = new BufferRenderTarget( { + width: 1, + height: 1, + numBuffers: 4, +} ); + +export const dummyRenderTargetFourDrawBuffers = new BufferRenderTarget( { + width: 1, + height: 1, + numBuffers: 4, +} ); diff --git a/src/heck/Material.ts b/src/heck/Material.ts index b1f0799..c0b887a 100644 --- a/src/heck/Material.ts +++ b/src/heck/Material.ts @@ -1,6 +1,8 @@ import { GLCatProgram, GLCatProgramLinkOptions, GLCatProgramUniformType, GLCatTexture, GLCatTextureCubemap } from '@fms-cat/glcat-ts'; -import { gl } from '../globals/canvas'; +import { gl, glCat } from '../globals/canvas'; import { injectCodeToShader } from '../utils/injectCodeToShader'; +import { Geometry } from './Geometry'; +import { RenderTarget } from './RenderTarget'; import { SHADERPOOL } from './ShaderPool'; export type MaterialTag = @@ -10,6 +12,11 @@ export type MaterialTag = export type MaterialMap = { [ tag in T ]: Material }; +export interface MaterialInitOptions { + target: RenderTarget; + geometry: Geometry; +} + export class Material { protected __linkOptions: GLCatProgramLinkOptions; @@ -76,15 +83,24 @@ export class Material { public constructor( vert: string, frag: string, - options?: { + { defines, linkOptions, initOptions }: { defines?: { [ key: string ]: ( string | undefined ) }, linkOptions?: GLCatProgramLinkOptions, - }, + initOptions?: MaterialInitOptions, + } = {}, ) { this.__vert = vert; this.__frag = frag; - this.__linkOptions = options?.linkOptions ?? {}; - this.__defines = options?.defines ?? {}; + this.__linkOptions = linkOptions ?? {}; + this.__defines = defines ?? {}; + + if ( initOptions ) { + this.d3dSucks( initOptions ); + } else { + if ( process.env.DEV ) { + console.warn( 'Material created without initOptions' ); + } + } } public addUniform( name: string, type: GLCatProgramUniformType, ...value: number[] ): void { @@ -163,6 +179,16 @@ export class Material { } } + /** + * https://scrapbox.io/fms-cat/WebGL:_%E3%82%B7%E3%82%A7%E3%83%BC%E3%83%80%E3%81%AE%E3%82%B3%E3%83%B3%E3%83%91%E3%82%A4%E3%83%AB%E3%81%8C%E9%81%85%E3%81%84 + */ + public d3dSucks( { geometry, target }: MaterialInitOptions ): void { + target.bind(); + glCat.useProgram( this.program, () => { + geometry.drawElementsOrArrays(); + } ); + } + protected __withDefines( code: string ): string { let inject = '';