{"version":3,"file":"GPUComputationRenderer.cjs","sources":["../../src/misc/GPUComputationRenderer.js"],"sourcesContent":["import {\n Camera,\n ClampToEdgeWrapping,\n DataTexture,\n FloatType,\n Mesh,\n NearestFilter,\n NoToneMapping,\n PlaneGeometry,\n RGBAFormat,\n Scene,\n ShaderMaterial,\n WebGLRenderTarget,\n} from 'three'\n\n/**\n * GPUComputationRenderer, based on SimulationRenderer by zz85\n *\n * The GPUComputationRenderer uses the concept of variables. These variables are RGBA float textures that hold 4 floats\n * for each compute element (texel)\n *\n * Each variable has a fragment shader that defines the computation made to obtain the variable in question.\n * You can use as many variables you need, and make dependencies so you can use textures of other variables in the shader\n * (the sampler uniforms are added automatically) Most of the variables will need themselves as dependency.\n *\n * The renderer has actually two render targets per variable, to make ping-pong. Textures from the current frame are used\n * as inputs to render the textures of the next frame.\n *\n * The render targets of the variables can be used as input textures for your visualization shaders.\n *\n * Variable names should be valid identifiers and should not collide with THREE GLSL used identifiers.\n * a common approach could be to use 'texture' prefixing the variable name; i.e texturePosition, textureVelocity...\n *\n * The size of the computation (sizeX * sizeY) is defined as 'resolution' automatically in the shader. For example:\n * #DEFINE resolution vec2( 1024.0, 1024.0 )\n *\n * -------------\n *\n * Basic use:\n *\n * // Initialization...\n *\n * // Create computation renderer\n * const gpuCompute = new GPUComputationRenderer( 1024, 1024, renderer );\n *\n * // Create initial state float textures\n * const pos0 = gpuCompute.createTexture();\n * const vel0 = gpuCompute.createTexture();\n * // and fill in here the texture data...\n *\n * // Add texture variables\n * const velVar = gpuCompute.addVariable( \"textureVelocity\", fragmentShaderVel, pos0 );\n * const posVar = gpuCompute.addVariable( \"texturePosition\", fragmentShaderPos, vel0 );\n *\n * // Add variable dependencies\n * gpuCompute.setVariableDependencies( velVar, [ velVar, posVar ] );\n * gpuCompute.setVariableDependencies( posVar, [ velVar, posVar ] );\n *\n * // Add custom uniforms\n * velVar.material.uniforms.time = { value: 0.0 };\n *\n * // Check for completeness\n * const error = gpuCompute.init();\n * if ( error !== null ) {\n *\t\tconsole.error( error );\n * }\n *\n *\n * // In each frame...\n *\n * // Compute!\n * gpuCompute.compute();\n *\n * // Update texture uniforms in your visualization materials with the gpu renderer output\n * myMaterial.uniforms.myTexture.value = gpuCompute.getCurrentRenderTarget( posVar ).texture;\n *\n * // Do your rendering\n * renderer.render( myScene, myCamera );\n *\n * -------------\n *\n * Also, you can use utility functions to create ShaderMaterial and perform computations (rendering between textures)\n * Note that the shaders can have multiple input textures.\n *\n * const myFilter1 = gpuCompute.createShaderMaterial( myFilterFragmentShader1, { theTexture: { value: null } } );\n * const myFilter2 = gpuCompute.createShaderMaterial( myFilterFragmentShader2, { theTexture: { value: null } } );\n *\n * const inputTexture = gpuCompute.createTexture();\n *\n * // Fill in here inputTexture...\n *\n * myFilter1.uniforms.theTexture.value = inputTexture;\n *\n * const myRenderTarget = gpuCompute.createRenderTarget();\n * myFilter2.uniforms.theTexture.value = myRenderTarget.texture;\n *\n * const outputRenderTarget = gpuCompute.createRenderTarget();\n *\n * // Now use the output texture where you want:\n * myMaterial.uniforms.map.value = outputRenderTarget.texture;\n *\n * // And compute each frame, before rendering to screen:\n * gpuCompute.doRenderTarget( myFilter1, myRenderTarget );\n * gpuCompute.doRenderTarget( myFilter2, outputRenderTarget );\n *\n *\n *\n * @param {int} sizeX Computation problem size is always 2d: sizeX * sizeY elements.\n * @param {int} sizeY Computation problem size is always 2d: sizeX * sizeY elements.\n * @param {WebGLRenderer} renderer The renderer\n */\n\nclass GPUComputationRenderer {\n constructor(sizeX, sizeY, renderer) {\n this.variables = []\n\n this.currentTextureIndex = 0\n\n let dataType = FloatType\n\n const scene = new Scene()\n\n const camera = new Camera()\n camera.position.z = 1\n\n const passThruUniforms = {\n passThruTexture: { value: null },\n }\n\n const passThruShader = createShaderMaterial(getPassThroughFragmentShader(), passThruUniforms)\n\n const mesh = new Mesh(new PlaneGeometry(2, 2), passThruShader)\n scene.add(mesh)\n\n this.setDataType = function (type) {\n dataType = type\n return this\n }\n\n this.addVariable = function (variableName, computeFragmentShader, initialValueTexture) {\n const material = this.createShaderMaterial(computeFragmentShader)\n\n const variable = {\n name: variableName,\n initialValueTexture: initialValueTexture,\n material: material,\n dependencies: null,\n renderTargets: [],\n wrapS: null,\n wrapT: null,\n minFilter: NearestFilter,\n magFilter: NearestFilter,\n }\n\n this.variables.push(variable)\n\n return variable\n }\n\n this.setVariableDependencies = function (variable, dependencies) {\n variable.dependencies = dependencies\n }\n\n this.init = function () {\n if (renderer.capabilities.isWebGL2 === false && renderer.extensions.has('OES_texture_float') === false) {\n return 'No OES_texture_float support for float textures.'\n }\n\n if (renderer.capabilities.maxVertexTextures === 0) {\n return 'No support for vertex shader textures.'\n }\n\n for (let i = 0; i < this.variables.length; i++) {\n const variable = this.variables[i]\n\n // Creates rendertargets and initialize them with input texture\n variable.renderTargets[0] = this.createRenderTarget(\n sizeX,\n sizeY,\n variable.wrapS,\n variable.wrapT,\n variable.minFilter,\n variable.magFilter,\n )\n variable.renderTargets[1] = this.createRenderTarget(\n sizeX,\n sizeY,\n variable.wrapS,\n variable.wrapT,\n variable.minFilter,\n variable.magFilter,\n )\n this.renderTexture(variable.initialValueTexture, variable.renderTargets[0])\n this.renderTexture(variable.initialValueTexture, variable.renderTargets[1])\n\n // Adds dependencies uniforms to the ShaderMaterial\n const material = variable.material\n const uniforms = material.uniforms\n\n if (variable.dependencies !== null) {\n for (let d = 0; d < variable.dependencies.length; d++) {\n const depVar = variable.dependencies[d]\n\n if (depVar.name !== variable.name) {\n // Checks if variable exists\n let found = false\n\n for (let j = 0; j < this.variables.length; j++) {\n if (depVar.name === this.variables[j].name) {\n found = true\n break\n }\n }\n\n if (!found) {\n return 'Variable dependency not found. Variable=' + variable.name + ', dependency=' + depVar.name\n }\n }\n\n uniforms[depVar.name] = { value: null }\n\n material.fragmentShader = '\\nuniform sampler2D ' + depVar.name + ';\\n' + material.fragmentShader\n }\n }\n }\n\n this.currentTextureIndex = 0\n\n return null\n }\n\n this.compute = function () {\n const currentTextureIndex = this.currentTextureIndex\n const nextTextureIndex = this.currentTextureIndex === 0 ? 1 : 0\n\n for (let i = 0, il = this.variables.length; i < il; i++) {\n const variable = this.variables[i]\n\n // Sets texture dependencies uniforms\n if (variable.dependencies !== null) {\n const uniforms = variable.material.uniforms\n\n for (let d = 0, dl = variable.dependencies.length; d < dl; d++) {\n const depVar = variable.dependencies[d]\n\n uniforms[depVar.name].value = depVar.renderTargets[currentTextureIndex].texture\n }\n }\n\n // Performs the computation for this variable\n this.doRenderTarget(variable.material, variable.renderTargets[nextTextureIndex])\n }\n\n this.currentTextureIndex = nextTextureIndex\n }\n\n this.getCurrentRenderTarget = function (variable) {\n return variable.renderTargets[this.currentTextureIndex]\n }\n\n this.getAlternateRenderTarget = function (variable) {\n return variable.renderTargets[this.currentTextureIndex === 0 ? 1 : 0]\n }\n\n this.dispose = function () {\n mesh.geometry.dispose()\n mesh.material.dispose()\n\n const variables = this.variables\n\n for (let i = 0; i < variables.length; i++) {\n const variable = variables[i]\n\n if (variable.initialValueTexture) variable.initialValueTexture.dispose()\n\n const renderTargets = variable.renderTargets\n\n for (let j = 0; j < renderTargets.length; j++) {\n const renderTarget = renderTargets[j]\n renderTarget.dispose()\n }\n }\n }\n\n function addResolutionDefine(materialShader) {\n materialShader.defines.resolution = 'vec2( ' + sizeX.toFixed(1) + ', ' + sizeY.toFixed(1) + ' )'\n }\n\n this.addResolutionDefine = addResolutionDefine\n\n // The following functions can be used to compute things manually\n\n function createShaderMaterial(computeFragmentShader, uniforms) {\n uniforms = uniforms || {}\n\n const material = new ShaderMaterial({\n uniforms: uniforms,\n vertexShader: getPassThroughVertexShader(),\n fragmentShader: computeFragmentShader,\n })\n\n addResolutionDefine(material)\n\n return material\n }\n\n this.createShaderMaterial = createShaderMaterial\n\n this.createRenderTarget = function (sizeXTexture, sizeYTexture, wrapS, wrapT, minFilter, magFilter) {\n sizeXTexture = sizeXTexture || sizeX\n sizeYTexture = sizeYTexture || sizeY\n\n wrapS = wrapS || ClampToEdgeWrapping\n wrapT = wrapT || ClampToEdgeWrapping\n\n minFilter = minFilter || NearestFilter\n magFilter = magFilter || NearestFilter\n\n const renderTarget = new WebGLRenderTarget(sizeXTexture, sizeYTexture, {\n wrapS: wrapS,\n wrapT: wrapT,\n minFilter: minFilter,\n magFilter: magFilter,\n format: RGBAFormat,\n type: dataType,\n depthBuffer: false,\n })\n\n return renderTarget\n }\n\n this.createTexture = function () {\n const data = new Float32Array(sizeX * sizeY * 4)\n const texture = new DataTexture(data, sizeX, sizeY, RGBAFormat, FloatType)\n texture.needsUpdate = true\n return texture\n }\n\n this.renderTexture = function (input, output) {\n // Takes a texture, and render out in rendertarget\n // input = Texture\n // output = RenderTarget\n\n passThruUniforms.passThruTexture.value = input\n\n this.doRenderTarget(passThruShader, output)\n\n passThruUniforms.passThruTexture.value = null\n }\n\n this.doRenderTarget = function (material, output) {\n const currentRenderTarget = renderer.getRenderTarget()\n\n const currentXrEnabled = renderer.xr.enabled\n const currentShadowAutoUpdate = renderer.shadowMap.autoUpdate\n const currentOutputColorSpace = renderer.outputColorSpace\n const currentToneMapping = renderer.toneMapping\n\n renderer.xr.enabled = false // Avoid camera modification\n renderer.shadowMap.autoUpdate = false // Avoid re-computing shadows\n if ('outputColorSpace' in renderer) renderer.outputColorSpace = 'srgb-linear'\n else renderer.encoding = 3000 // LinearEncoding\n renderer.toneMapping = NoToneMapping\n\n mesh.material = material\n renderer.setRenderTarget(output)\n renderer.render(scene, camera)\n mesh.material = passThruShader\n\n renderer.xr.enabled = currentXrEnabled\n renderer.shadowMap.autoUpdate = currentShadowAutoUpdate\n renderer.outputColorSpace = currentOutputColorSpace\n renderer.toneMapping = currentToneMapping\n\n renderer.setRenderTarget(currentRenderTarget)\n }\n\n // Shaders\n\n function getPassThroughVertexShader() {\n return 'void main()\t{\\n' + '\\n' + '\tgl_Position = vec4( position, 1.0 );\\n' + '\\n' + '}\\n'\n }\n\n function getPassThroughFragmentShader() {\n return (\n 'uniform sampler2D passThruTexture;\\n' +\n '\\n' +\n 'void main() {\\n' +\n '\\n' +\n '\tvec2 uv = gl_FragCoord.xy / resolution.xy;\\n' +\n '\\n' +\n '\tgl_FragColor = texture2D( passThruTexture, uv );\\n' +\n '\\n' +\n '}\\n'\n )\n }\n }\n}\n\nexport { GPUComputationRenderer }\n"],"names":["FloatType","Scene","Camera","Mesh","PlaneGeometry","NearestFilter","ShaderMaterial","ClampToEdgeWrapping","WebGLRenderTarget","RGBAFormat","DataTexture","NoToneMapping"],"mappings":"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"}