@woosh/meep-engine
Version:
Pure JavaScript game engine. Fully featured and production ready.
193 lines (150 loc) • 4.41 kB
JavaScript
import { GLSLCodeGenerator } from "../codegen/glsl/GLSLCodeGenerator.js";
import { ParticleAttributeSpecification } from "../particle/ParticleAttributeSpecification.js";
import { TransformFeedback } from "./TransformFeedback.js";
/**
* Fragment shader is there to satisfy requirement of 2 shaders to compile shader program in WebGL, in actuality it is unused
* @type {string}
*/
export const WRITE_WHITE_FRAGMENT_SHADER = [
'#version 300 es',
'precision lowp float;',
'out vec4 fragColor;',
'void main() {',
' fragColor = vec4(1.0, 1.0, 1.0, 1.0);',
'}'
].join('\n');
/**
*
* @param {string} string
* @return {string}
*/
function addLineNumbers(string) {
const lines = string.split('\n');
for (let i = 0; i < lines.length; i++) {
lines[i] = (i + 1) + ': ' + lines[i];
}
return lines.join('\n');
}
/**
*
* @param {WebGLRenderingContext|WebGL2RenderingContext} gl
* @param shader
* @param type
* @return {string}
*/
export function getShaderErrors(gl, shader, type) {
const status = gl.getShaderParameter(shader, gl.COMPILE_STATUS);
const log = gl.getShaderInfoLog(shader).trim();
if (status && log === '') return '';
// --enable-privileged-webgl-extension
// console.log( '**' + type + '**', gl.getExtension( 'WEBGL_debug_shaders' ).getTranslatedShaderSource( shader ) );
const source = gl.getShaderSource(shader);
return 'THREE.WebGLShader: gl.getShaderInfoLog() ' + type + '\n' + log + addLineNumbers(source);
}
export class GLSLSimulationShader {
constructor() {
/**
*
* @type {NodeGraph}
*/
this.graph = null;
/**
*
* @type {FunctionModuleRegistry}
* @private
*/
this.__function_registry = null;
this.__tf = new TransformFeedback();
}
/**
*
* @param {FunctionModuleRegistry} function_registry
*/
setFunctionRegistry(function_registry) {
this.__function_registry = function_registry;
}
/**
*
* @param {NodeGraph} graph
*/
setGraph(graph) {
this.graph = graph;
}
/**
*
* @param {ParticleAttributeSpecification[]} attributes
*/
setAttributes(attributes) {
this.__tf.setAttributes(attributes);
}
get attributes() {
return this.__tf.attributes;
}
/**
*
* @param {ParticleAttributeSpecification[]} attributes
*/
setUniforms(attributes) {
this.__tf.setUniforms(attributes);
}
get uniforms() {
return this.__tf.uniforms;
}
/**
* @param {NodeGraph} graph
* @param {ParticleAttributeSpecification[]} attributes
* @param {ParticleAttributeSpecification[]} uniforms
* @returns {GLSLSimulationShader}
*/
static from(graph, attributes = [], uniforms = []) {
const r = new GLSLSimulationShader();
r.setGraph(graph);
r.setAttributes(attributes);
r.setUniforms(uniforms);
return r;
}
/**
*
* @return {String}
*/
getSourceCode() {
return this.__tf.getSourceCode();
}
build() {
const gen = new GLSLCodeGenerator();
const code = gen.generate({
graph: this.graph,
modules: this.__function_registry,
attributes: this.attributes,
uniforms: this.uniforms
});
this.__tf.setSourceCode(code);
}
/**
*
* @param {Array} uniform_values
* @param {EmitterAttributeData} attributeSource
*/
execute(uniform_values, attributeSource) {
this.__tf.execute(uniform_values, attributeSource);
this.__copyFromOutput(attributeSource);
}
/**
* GL context uses it's own internal buffers that are not shared with JS context, because of this - it is necessary to copy data out
* @param {EmitterAttributeData} target
* @private
*/
__copyFromOutput(target) {
this.__tf.readOutput(target);
}
dispose() {
this.__tf.dispose();
}
/**
*
* @param {WebGL2RenderingContext} gl
*/
compile(gl) {
this.__tf.compile(gl);
}
}