performance: Material.d3dSucks

This commit is contained in:
FMS-Cat
2021-03-24 22:35:26 +09:00
parent 42e007f601
commit df0962dffe
4 changed files with 149 additions and 98 deletions

View File

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

View File

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

View File

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

View File

@@ -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<T extends MaterialTag = MaterialTag> = { [ 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 = '';