UNPKG

@woosh/meep-engine

Version:

Pure JavaScript game engine. Fully featured and production ready.

193 lines (150 loc) 4.41 kB
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); } }