Buckets:
ktongue/docker_container / simsite /frontend /node_modules /three-stdlib /misc /GPUComputationRenderer.js
| import { Scene, Camera, Mesh, PlaneGeometry, ShaderMaterial, WebGLRenderTarget, RGBAFormat, DataTexture, FloatType, NoToneMapping, NearestFilter, ClampToEdgeWrapping } from "three"; | |
| class GPUComputationRenderer { | |
| constructor(sizeX, sizeY, renderer) { | |
| this.variables = []; | |
| this.currentTextureIndex = 0; | |
| let dataType = FloatType; | |
| const scene = new Scene(); | |
| const camera = new Camera(); | |
| camera.position.z = 1; | |
| const passThruUniforms = { | |
| passThruTexture: { value: null } | |
| }; | |
| const passThruShader = createShaderMaterial(getPassThroughFragmentShader(), passThruUniforms); | |
| const mesh = new Mesh(new PlaneGeometry(2, 2), passThruShader); | |
| scene.add(mesh); | |
| this.setDataType = function(type) { | |
| dataType = type; | |
| return this; | |
| }; | |
| this.addVariable = function(variableName, computeFragmentShader, initialValueTexture) { | |
| const material = this.createShaderMaterial(computeFragmentShader); | |
| const variable = { | |
| name: variableName, | |
| initialValueTexture, | |
| material, | |
| dependencies: null, | |
| renderTargets: [], | |
| wrapS: null, | |
| wrapT: null, | |
| minFilter: NearestFilter, | |
| magFilter: NearestFilter | |
| }; | |
| this.variables.push(variable); | |
| return variable; | |
| }; | |
| this.setVariableDependencies = function(variable, dependencies) { | |
| variable.dependencies = dependencies; | |
| }; | |
| this.init = function() { | |
| if (renderer.capabilities.isWebGL2 === false && renderer.extensions.has("OES_texture_float") === false) { | |
| return "No OES_texture_float support for float textures."; | |
| } | |
| if (renderer.capabilities.maxVertexTextures === 0) { | |
| return "No support for vertex shader textures."; | |
| } | |
| for (let i = 0; i < this.variables.length; i++) { | |
| const variable = this.variables[i]; | |
| variable.renderTargets[0] = this.createRenderTarget( | |
| sizeX, | |
| sizeY, | |
| variable.wrapS, | |
| variable.wrapT, | |
| variable.minFilter, | |
| variable.magFilter | |
| ); | |
| variable.renderTargets[1] = this.createRenderTarget( | |
| sizeX, | |
| sizeY, | |
| variable.wrapS, | |
| variable.wrapT, | |
| variable.minFilter, | |
| variable.magFilter | |
| ); | |
| this.renderTexture(variable.initialValueTexture, variable.renderTargets[0]); | |
| this.renderTexture(variable.initialValueTexture, variable.renderTargets[1]); | |
| const material = variable.material; | |
| const uniforms = material.uniforms; | |
| if (variable.dependencies !== null) { | |
| for (let d = 0; d < variable.dependencies.length; d++) { | |
| const depVar = variable.dependencies[d]; | |
| if (depVar.name !== variable.name) { | |
| let found = false; | |
| for (let j = 0; j < this.variables.length; j++) { | |
| if (depVar.name === this.variables[j].name) { | |
| found = true; | |
| break; | |
| } | |
| } | |
| if (!found) { | |
| return "Variable dependency not found. Variable=" + variable.name + ", dependency=" + depVar.name; | |
| } | |
| } | |
| uniforms[depVar.name] = { value: null }; | |
| material.fragmentShader = "\nuniform sampler2D " + depVar.name + ";\n" + material.fragmentShader; | |
| } | |
| } | |
| } | |
| this.currentTextureIndex = 0; | |
| return null; | |
| }; | |
| this.compute = function() { | |
| const currentTextureIndex = this.currentTextureIndex; | |
| const nextTextureIndex = this.currentTextureIndex === 0 ? 1 : 0; | |
| for (let i = 0, il = this.variables.length; i < il; i++) { | |
| const variable = this.variables[i]; | |
| if (variable.dependencies !== null) { | |
| const uniforms = variable.material.uniforms; | |
| for (let d = 0, dl = variable.dependencies.length; d < dl; d++) { | |
| const depVar = variable.dependencies[d]; | |
| uniforms[depVar.name].value = depVar.renderTargets[currentTextureIndex].texture; | |
| } | |
| } | |
| this.doRenderTarget(variable.material, variable.renderTargets[nextTextureIndex]); | |
| } | |
| this.currentTextureIndex = nextTextureIndex; | |
| }; | |
| this.getCurrentRenderTarget = function(variable) { | |
| return variable.renderTargets[this.currentTextureIndex]; | |
| }; | |
| this.getAlternateRenderTarget = function(variable) { | |
| return variable.renderTargets[this.currentTextureIndex === 0 ? 1 : 0]; | |
| }; | |
| this.dispose = function() { | |
| mesh.geometry.dispose(); | |
| mesh.material.dispose(); | |
| const variables = this.variables; | |
| for (let i = 0; i < variables.length; i++) { | |
| const variable = variables[i]; | |
| if (variable.initialValueTexture) | |
| variable.initialValueTexture.dispose(); | |
| const renderTargets = variable.renderTargets; | |
| for (let j = 0; j < renderTargets.length; j++) { | |
| const renderTarget = renderTargets[j]; | |
| renderTarget.dispose(); | |
| } | |
| } | |
| }; | |
| function addResolutionDefine(materialShader) { | |
| materialShader.defines.resolution = "vec2( " + sizeX.toFixed(1) + ", " + sizeY.toFixed(1) + " )"; | |
| } | |
| this.addResolutionDefine = addResolutionDefine; | |
| function createShaderMaterial(computeFragmentShader, uniforms) { | |
| uniforms = uniforms || {}; | |
| const material = new ShaderMaterial({ | |
| uniforms, | |
| vertexShader: getPassThroughVertexShader(), | |
| fragmentShader: computeFragmentShader | |
| }); | |
| addResolutionDefine(material); | |
| return material; | |
| } | |
| this.createShaderMaterial = createShaderMaterial; | |
| this.createRenderTarget = function(sizeXTexture, sizeYTexture, wrapS, wrapT, minFilter, magFilter) { | |
| sizeXTexture = sizeXTexture || sizeX; | |
| sizeYTexture = sizeYTexture || sizeY; | |
| wrapS = wrapS || ClampToEdgeWrapping; | |
| wrapT = wrapT || ClampToEdgeWrapping; | |
| minFilter = minFilter || NearestFilter; | |
| magFilter = magFilter || NearestFilter; | |
| const renderTarget = new WebGLRenderTarget(sizeXTexture, sizeYTexture, { | |
| wrapS, | |
| wrapT, | |
| minFilter, | |
| magFilter, | |
| format: RGBAFormat, | |
| type: dataType, | |
| depthBuffer: false | |
| }); | |
| return renderTarget; | |
| }; | |
| this.createTexture = function() { | |
| const data = new Float32Array(sizeX * sizeY * 4); | |
| const texture = new DataTexture(data, sizeX, sizeY, RGBAFormat, FloatType); | |
| texture.needsUpdate = true; | |
| return texture; | |
| }; | |
| this.renderTexture = function(input, output) { | |
| passThruUniforms.passThruTexture.value = input; | |
| this.doRenderTarget(passThruShader, output); | |
| passThruUniforms.passThruTexture.value = null; | |
| }; | |
| this.doRenderTarget = function(material, output) { | |
| const currentRenderTarget = renderer.getRenderTarget(); | |
| const currentXrEnabled = renderer.xr.enabled; | |
| const currentShadowAutoUpdate = renderer.shadowMap.autoUpdate; | |
| const currentOutputColorSpace = renderer.outputColorSpace; | |
| const currentToneMapping = renderer.toneMapping; | |
| renderer.xr.enabled = false; | |
| renderer.shadowMap.autoUpdate = false; | |
| if ("outputColorSpace" in renderer) | |
| renderer.outputColorSpace = "srgb-linear"; | |
| else | |
| renderer.encoding = 3e3; | |
| renderer.toneMapping = NoToneMapping; | |
| mesh.material = material; | |
| renderer.setRenderTarget(output); | |
| renderer.render(scene, camera); | |
| mesh.material = passThruShader; | |
| renderer.xr.enabled = currentXrEnabled; | |
| renderer.shadowMap.autoUpdate = currentShadowAutoUpdate; | |
| renderer.outputColorSpace = currentOutputColorSpace; | |
| renderer.toneMapping = currentToneMapping; | |
| renderer.setRenderTarget(currentRenderTarget); | |
| }; | |
| function getPassThroughVertexShader() { | |
| return "void main() {\n\n gl_Position = vec4( position, 1.0 );\n\n}\n"; | |
| } | |
| function getPassThroughFragmentShader() { | |
| return "uniform sampler2D passThruTexture;\n\nvoid main() {\n\n vec2 uv = gl_FragCoord.xy / resolution.xy;\n\n gl_FragColor = texture2D( passThruTexture, uv );\n\n}\n"; | |
| } | |
| } | |
| } | |
| export { | |
| GPUComputationRenderer | |
| }; | |
| //# sourceMappingURL=GPUComputationRenderer.js.map | |
Xet Storage Details
- Size:
- 8.21 kB
- Xet hash:
- e41e0ce8db9b974f6908df7862e8fdb53c8fe2896f609d5cf0830eb97478307f
·
Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.