Skip to content

Commit

Permalink
\#4: WIP shader preprocessor, port advectParticles
Browse files Browse the repository at this point in the history
  • Loading branch information
loganzartman committed Feb 21, 2023
1 parent 2f00b92 commit 045b486
Show file tree
Hide file tree
Showing 5 changed files with 136 additions and 21 deletions.
19 changes: 0 additions & 19 deletions src/advectParticles.frag.glsl

This file was deleted.

112 changes: 112 additions & 0 deletions src/glslpp.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
class UncompiledGLSL {
strings: string[];
values: any[];

constructor(strings: string[], values: any[]) {
this.strings = strings;
this.values = values;
}
}

export class GLSLFragment {
glsl: UncompiledGLSL;

constructor(glsl: UncompiledGLSL) {
this.glsl = glsl;
}
}

export class GLSLUniform {
name: string;
type: string;

constructor(name: string, type: string) {
this.name = name;
this.type = type;
}
}

export class GLSLDefinition {
name: string;
definition: UncompiledGLSL;

constructor(name: string, definition: UncompiledGLSL) {
this.name = name;
this.definition = definition;
}
}

type GLSLReference = GLSLUniform | GLSLDefinition;

export const glsl = (
strings: TemplateStringsArray,
...values: GLSLReference[]
) => new UncompiledGLSL(Array.from(strings), values);

type Context = {uniforms: Set<GLSLUniform>; defs: Map<GLSLDefinition, string>};

const makeContext = (): Context => ({uniforms: new Set(), defs: new Map()});

const generateReference = (value: any, context: Context) => {
if (value instanceof GLSLUniform) {
context.uniforms.add(value);
return value.name;
}
if (value instanceof GLSLDefinition) {
if (!context.defs.has(value))
context.defs.set(value, compileBody(value.definition, context));
return value.name;
}
throw new Error('Unsupported reference: ' + value);
};

const generateUniforms = (context: Context) =>
Array.from(context.uniforms)
.map((u) => `uniform ${u.type} ${u.name};`)
.join('\n');

const generateDefs = (context: Context) =>
Array.from(context.defs)
.map(([_, compiled]) => compiled)
.join('\n');

const compileBody = (uncompiled: UncompiledGLSL, context: Context) => {
const body = [];

for (let i = 0; i < uncompiled.strings.length; ++i) {
body.push(uncompiled.strings[i]);
if (i < uncompiled.values.length) {
const value = uncompiled.values[i];
if (typeof value === 'string') {
body.push(value);
}
body.push(generateReference(value, context));
}
}

return body.join('');
};

export const compile = (
uncompiled: UncompiledGLSL,
context: Context = makeContext()
) => {
const body = compileBody(uncompiled, context);

const generatedDefs = generateDefs(context);
const generatedUniforms = generateUniforms(context);
const precisions = [
'precision highp sampler2D;',
'precision highp isampler2D;',
'precision highp float;',
'precision highp int;',
].join('\n');

return [
'#version 300 es',
precisions,
generatedUniforms,
generatedDefs,
body,
].join('\n');
};
16 changes: 16 additions & 0 deletions src/shader/advectParticles.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import {compile, glsl} from '../glslpp';
import {dt, positionSampler, velocitySampler} from './uniforms';

export const advectParticlesFs = compile(glsl`
out vec4 outPosition;
void main() {
ivec2 texCoord = ivec2(gl_FragCoord.xy);
vec2 position = texelFetch(${positionSampler}, texCoord, 0).rg;
vec2 velocity = texelFetch(${velocitySampler}, texCoord, 0).rg;
position += velocity * ${dt};
outPosition = vec4(position, 0.0, 0.0);
}
`);
6 changes: 6 additions & 0 deletions src/shader/uniforms.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import {GLSLUniform} from '../glslpp';

export const positionSampler = new GLSLUniform('positionSampler', 'sampler2D');
export const velocitySampler = new GLSLUniform('velocitySampler', 'sampler2D');

export const dt = new GLSLUniform('dt', 'float');
4 changes: 2 additions & 2 deletions src/simulationGPU.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import {createProgram, createShader} from './gl';
import {GPUState, State} from './state';
import {memoize} from './util';
import advectParticlesFrag from './advectParticles.frag.glsl';
import {advectParticlesFs} from './shader/advectParticles';
import updateVelocityFrag from './updateVelocity.frag.glsl';
import {Params} from './params';
import {getCopyVertexVert, getQuadVAO} from './gpuUtil';
Expand Down Expand Up @@ -417,7 +417,7 @@ export const updateVelocityGuessGPU = (
};

const getAdvectParticlesFrag = memoize((gl: WebGL2RenderingContext) =>
createShader(gl, {source: advectParticlesFrag, type: gl.FRAGMENT_SHADER})
createShader(gl, {source: advectParticlesFs, type: gl.FRAGMENT_SHADER})
);

const getAdvectParticlesProgram = memoize((gl: WebGL2RenderingContext) =>
Expand Down

0 comments on commit 045b486

Please sign in to comment.