molstar
Version:
A comprehensive macromolecular library.
429 lines (428 loc) • 24.4 kB
JavaScript
"use strict";
/**
* Copyright (c) 2024-2025 mol* contributors, licensed under MIT, See LICENSE file for more info.
*
* @author Alexander Rose <alexander.rose@weirdbyte.de>
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.TracingPass = exports.TracingParams = void 0;
const util_1 = require("../../mol-gl/compute/util");
const schema_1 = require("../../mol-gl/renderable/schema");
const mol_util_1 = require("../../mol-util");
const debug_1 = require("../../mol-util/debug");
const shader_code_1 = require("../../mol-gl/shader-code");
const quad_vert_1 = require("../../mol-gl/shader/quad.vert");
const renderable_1 = require("../../mol-gl/renderable");
const trace_frag_1 = require("../../mol-gl/shader/illumination/trace.frag");
const vec2_1 = require("../../mol-math/linear-algebra/3d/vec2");
const render_item_1 = require("../../mol-gl/webgl/render-item");
const mat4_1 = require("../../mol-math/linear-algebra/3d/mat4");
const vec4_1 = require("../../mol-math/linear-algebra/3d/vec4");
const vec3_1 = require("../../mol-math/linear-algebra/3d/vec3");
const param_definition_1 = require("../../mol-util/param-definition");
const color_1 = require("../../mol-util/color/color");
const accumulate_frag_1 = require("../../mol-gl/shader/illumination/accumulate.frag");
const now_1 = require("../../mol-util/now");
const interpolate_1 = require("../../mol-math/interpolate");
exports.TracingParams = {
rendersPerFrame: param_definition_1.ParamDefinition.Interval([1, 16], { min: 1, max: 64, step: 1 }, { description: 'Number of rays per pixel each frame. May be adjusted to reach targetFps but will stay within given interval.' }),
targetFps: param_definition_1.ParamDefinition.Numeric(30, { min: 0, max: 120, step: 0.1 }, { description: 'Target FPS per frame. If observed FPS is lower or higher, some parameters may get adjusted.' }),
steps: param_definition_1.ParamDefinition.Numeric(32, { min: 1, max: 1024, step: 1 }),
firstStepSize: param_definition_1.ParamDefinition.Numeric(0.01, { min: 0.001, max: 1, step: 0.001 }),
refineSteps: param_definition_1.ParamDefinition.Numeric(4, { min: 0, max: 8, step: 1 }, { description: 'Number of refine steps per ray hit. May be lower to reach targetFps.' }),
rayDistance: param_definition_1.ParamDefinition.Numeric(256, { min: 1, max: 8192, step: 1 }, { description: 'Maximum distance a ray can travel (in world units).' }),
thicknessMode: param_definition_1.ParamDefinition.Select('auto', param_definition_1.ParamDefinition.arrayToOptions(['auto', 'fixed'])),
minThickness: param_definition_1.ParamDefinition.Numeric(0.5, { min: 0.1, max: 16, step: 0.1 }, { hideIf: p => p.thicknessMode === 'fixed' }),
thicknessFactor: param_definition_1.ParamDefinition.Numeric(1, { min: 0.1, max: 2, step: 0.05 }, { hideIf: p => p.thicknessMode === 'fixed' }),
thickness: param_definition_1.ParamDefinition.Numeric(4, { min: 0.1, max: 512, step: 0.1 }, { hideIf: p => p.thicknessMode === 'auto' }),
bounces: param_definition_1.ParamDefinition.Numeric(4, { min: 1, max: 32, step: 1 }, { description: 'Number of bounces for each ray.' }),
glow: param_definition_1.ParamDefinition.Boolean(true, { description: 'Bounced rays always get the full light. This produces a slight glowing effect.' }),
shadowEnable: param_definition_1.ParamDefinition.Boolean(false),
shadowSoftness: param_definition_1.ParamDefinition.Numeric(0.1, { min: 0.01, max: 1.0, step: 0.01 }),
shadowThickness: param_definition_1.ParamDefinition.Numeric(0.5, { min: 0.1, max: 32, step: 0.1 }),
};
class TracingPass {
constructor(webgl, drawPass) {
this.webgl = webgl;
this.drawPass = drawPass;
this.clearAdjustedProps = true;
this.prevTime = 0;
this.currTime = 0;
this.rendersPerFrame = 1;
this.refineSteps = 1;
this.steps = 16;
const { extensions: { drawBuffers, colorBufferHalfFloat, textureHalfFloat }, resources, isWebGL2 } = webgl;
const { depthTextureOpaque } = drawPass;
const width = depthTextureOpaque.getWidth();
const height = depthTextureOpaque.getHeight();
if (isWebGL2) {
this.shadedTextureOpaque = resources.texture('image-uint8', 'rgba', 'ubyte', 'nearest');
this.shadedTextureOpaque.define(width, height);
this.normalTextureOpaque = colorBufferHalfFloat && textureHalfFloat
? resources.texture('image-float16', 'rgba', 'fp16', 'nearest')
: resources.texture('image-float32', 'rgba', 'float', 'nearest');
this.normalTextureOpaque.define(width, height);
this.colorTextureOpaque = resources.texture('image-uint8', 'rgba', 'ubyte', 'nearest');
this.colorTextureOpaque.define(width, height);
}
else {
// webgl1 requires consistent bit plane counts
this.shadedTextureOpaque = resources.texture('image-float32', 'rgba', 'float', 'nearest');
this.shadedTextureOpaque.define(width, height);
this.normalTextureOpaque = resources.texture('image-float32', 'rgba', 'float', 'nearest');
this.normalTextureOpaque.define(width, height);
this.colorTextureOpaque = resources.texture('image-float32', 'rgba', 'float', 'nearest');
this.colorTextureOpaque.define(width, height);
}
this.framebuffer = resources.framebuffer();
this.framebuffer.bind();
drawBuffers.drawBuffers([
drawBuffers.COLOR_ATTACHMENT0,
drawBuffers.COLOR_ATTACHMENT1,
drawBuffers.COLOR_ATTACHMENT2,
]);
this.shadedTextureOpaque.attachFramebuffer(this.framebuffer, 'color0');
this.normalTextureOpaque.attachFramebuffer(this.framebuffer, 'color1');
this.colorTextureOpaque.attachFramebuffer(this.framebuffer, 'color2');
this.thicknessTarget = webgl.createRenderTarget(width, height, true, 'uint8', 'nearest');
this.holdTarget = webgl.createRenderTarget(width, height, false, 'float32');
this.accumulateTarget = webgl.createRenderTarget(width, height, false, 'float32');
this.composeTarget = webgl.createRenderTarget(width, height, false, 'uint8', 'linear');
this.traceRenderable = getTraceRenderable(webgl, this.colorTextureOpaque, this.normalTextureOpaque, this.shadedTextureOpaque, this.thicknessTarget.texture, this.accumulateTarget.texture, this.drawPass.depthTextureOpaque);
this.accumulateRenderable = getAccumulateRenderable(webgl, this.holdTarget.texture);
}
renderInput(renderer, camera, scene, props) {
if (debug_1.isTimingMode)
this.webgl.timer.mark('TracePass.renderInput');
const { gl, state } = this.webgl;
this.framebuffer.bind();
this.drawPass.depthTextureOpaque.attachFramebuffer(this.framebuffer, 'depth');
renderer.clear(true);
renderer.renderTracing(scene.primitives, camera);
//
if (props.thicknessMode === 'auto') {
this.thicknessTarget.bind();
state.clearColor(0, 0, 0, 0);
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
renderer.renderDepthOpaqueBack(scene.primitives, camera);
}
if (debug_1.isTimingMode)
this.webgl.timer.markEnd('TracePass.renderInput');
}
setSize(width, height) {
const w = this.composeTarget.getWidth();
const h = this.composeTarget.getHeight();
if (width !== w || height !== h) {
this.thicknessTarget.setSize(width, height);
this.holdTarget.setSize(width, height);
this.accumulateTarget.setSize(width, height);
this.composeTarget.setSize(width, height);
this.colorTextureOpaque.define(width, height);
this.normalTextureOpaque.define(width, height);
this.shadedTextureOpaque.define(width, height);
mol_util_1.ValueCell.update(this.traceRenderable.values.uTexSize, vec2_1.Vec2.set(this.traceRenderable.values.uTexSize.ref.value, width, height));
mol_util_1.ValueCell.update(this.accumulateRenderable.values.uTexSize, vec2_1.Vec2.set(this.accumulateRenderable.values.uTexSize.ref.value, width, height));
}
}
reset() {
const { drawBuffers } = this.webgl.extensions;
this.framebuffer.bind();
drawBuffers.drawBuffers([
drawBuffers.COLOR_ATTACHMENT0,
drawBuffers.COLOR_ATTACHMENT1,
drawBuffers.COLOR_ATTACHMENT2,
]);
this.shadedTextureOpaque.attachFramebuffer(this.framebuffer, 'color0');
this.normalTextureOpaque.attachFramebuffer(this.framebuffer, 'color1');
this.colorTextureOpaque.attachFramebuffer(this.framebuffer, 'color2');
this.restart(true);
}
restart(clearAdjustedProps = false) {
const { gl, state } = this.webgl;
this.accumulateTarget.bind();
state.clearColor(0, 0, 0, 0);
gl.clear(gl.COLOR_BUFFER_BIT);
this.composeTarget.bind();
state.clearColor(0, 0, 0, 0);
gl.clear(gl.COLOR_BUFFER_BIT);
if (clearAdjustedProps) {
this.prevTime = 0;
this.currTime = 0;
this.clearAdjustedProps = true;
}
}
increaseAdjustedProps(props) {
this.steps += 1;
if (this.steps > props.steps) {
this.refineSteps += 1;
}
if (this.refineSteps > props.refineSteps) {
this.rendersPerFrame += 1;
}
}
decreaseAdjustedProps(props) {
const minRefineSteps = Math.min(1, props.refineSteps);
this.rendersPerFrame -= 1;
if (this.rendersPerFrame < 1) {
this.refineSteps -= 1;
}
if (this.refineSteps < minRefineSteps) {
this.steps -= 1;
}
}
getAdjustedProps(props, iteration) {
this.currTime = (0, now_1.now)();
const minRefineSteps = Math.min(1, props.refineSteps);
const minSteps = Math.round(props.steps / 2);
if (this.clearAdjustedProps) {
this.rendersPerFrame = props.rendersPerFrame[0];
this.refineSteps = minRefineSteps;
this.steps = minSteps;
this.clearAdjustedProps = false;
}
if (iteration > 0) {
const targetTimeMs = 1000 / props.targetFps;
const deltaTime = this.currTime - this.prevTime;
let f = Math.round(deltaTime / targetTimeMs);
if (f >= 2) {
while (f > 0) {
this.decreaseAdjustedProps(props);
f -= 1;
}
}
else if (deltaTime < targetTimeMs) {
this.increaseAdjustedProps(props);
}
else if (deltaTime > targetTimeMs + 0.5) {
this.decreaseAdjustedProps(props);
}
}
this.prevTime = this.currTime;
this.rendersPerFrame = (0, interpolate_1.clamp)(this.rendersPerFrame, props.rendersPerFrame[0], props.rendersPerFrame[1]);
this.refineSteps = (0, interpolate_1.clamp)(this.refineSteps, minRefineSteps, props.refineSteps);
this.steps = (0, interpolate_1.clamp)(this.steps, minSteps, props.steps);
return {
rendersPerFrame: iteration === 0 ? Math.ceil(this.rendersPerFrame / 2) : this.rendersPerFrame,
refineSteps: iteration === 0 ? minRefineSteps : this.refineSteps,
steps: iteration === 0 ? minSteps : this.steps,
};
}
render(ctx, transparentBackground, props, iteration, forceRenderInput) {
const { rendersPerFrame, refineSteps, steps } = this.getAdjustedProps(props, iteration);
if (debug_1.isTimingMode) {
this.webgl.timer.mark('TracePass.render', {
note: `${rendersPerFrame} rendersPerFrame, ${refineSteps} refineSteps, ${steps} steps`
});
}
const { renderer, camera, scene } = ctx;
const { gl, state } = this.webgl;
const { x, y, width, height } = camera.viewport;
if (iteration === 0 || forceRenderInput) {
// render color & depth
renderer.setTransparentBackground(transparentBackground);
renderer.setDrawingBufferSize(this.composeTarget.getWidth(), this.composeTarget.getHeight());
renderer.setPixelRatio(this.webgl.pixelRatio);
renderer.setViewport(x, y, width, height);
renderer.update(camera, scene);
this.renderInput(renderer, camera, scene, props);
}
state.disable(gl.BLEND);
state.disable(gl.DEPTH_TEST);
state.disable(gl.CULL_FACE);
state.depthMask(false);
state.viewport(x, y, width, height);
state.scissor(x, y, width, height);
const invProjection = mat4_1.Mat4.identity();
mat4_1.Mat4.invert(invProjection, camera.projection);
const orthographic = camera.state.mode === 'orthographic' ? 1 : 0;
const [w, h] = this.traceRenderable.values.uTexSize.ref.value;
const v = camera.viewport;
const ambientColor = (0, vec3_1.Vec3)();
vec3_1.Vec3.scale(ambientColor, color_1.Color.toArrayNormalized(renderer.props.ambientColor, ambientColor, 0), renderer.props.ambientIntensity);
const lightStrength = vec3_1.Vec3.clone(ambientColor);
for (let i = 0, il = renderer.light.count; i < il; ++i) {
const light = vec3_1.Vec3.fromArray((0, vec3_1.Vec3)(), renderer.light.color, i * 3);
vec3_1.Vec3.add(lightStrength, lightStrength, light);
}
// trace
this.holdTarget.bind();
let needsUpdateTrace = false;
mol_util_1.ValueCell.update(this.traceRenderable.values.uFrameNo, iteration);
if (this.traceRenderable.values.dRendersPerFrame.ref.value !== rendersPerFrame) {
mol_util_1.ValueCell.update(this.traceRenderable.values.dRendersPerFrame, rendersPerFrame);
needsUpdateTrace = true;
}
mol_util_1.ValueCell.update(this.traceRenderable.values.uProjection, camera.projection);
mol_util_1.ValueCell.update(this.traceRenderable.values.uInvProjection, invProjection);
vec4_1.Vec4.set(this.traceRenderable.values.uBounds.ref.value, v.x / w, v.y / h, (v.x + v.width) / w, (v.y + v.height) / h);
mol_util_1.ValueCell.update(this.traceRenderable.values.uBounds, this.traceRenderable.values.uBounds.ref.value);
mol_util_1.ValueCell.updateIfChanged(this.traceRenderable.values.uNear, camera.near);
mol_util_1.ValueCell.updateIfChanged(this.traceRenderable.values.uFar, camera.far);
mol_util_1.ValueCell.updateIfChanged(this.traceRenderable.values.uFogFar, camera.fogFar);
mol_util_1.ValueCell.updateIfChanged(this.traceRenderable.values.uFogNear, camera.fogNear);
mol_util_1.ValueCell.update(this.traceRenderable.values.uFogColor, color_1.Color.toVec3Normalized(this.traceRenderable.values.uFogColor.ref.value, renderer.props.backgroundColor));
if (this.traceRenderable.values.dOrthographic.ref.value !== orthographic) {
mol_util_1.ValueCell.update(this.traceRenderable.values.dOrthographic, orthographic);
needsUpdateTrace = true;
}
mol_util_1.ValueCell.update(this.traceRenderable.values.uLightDirection, renderer.light.direction);
mol_util_1.ValueCell.update(this.traceRenderable.values.uLightColor, renderer.light.color);
if (this.traceRenderable.values.dLightCount.ref.value !== renderer.light.count) {
mol_util_1.ValueCell.update(this.traceRenderable.values.dLightCount, renderer.light.count);
needsUpdateTrace = true;
}
mol_util_1.ValueCell.update(this.traceRenderable.values.uAmbientColor, ambientColor);
mol_util_1.ValueCell.update(this.traceRenderable.values.uLightStrength, lightStrength);
if (this.traceRenderable.values.dGlow.ref.value !== props.glow) {
mol_util_1.ValueCell.update(this.traceRenderable.values.dGlow, props.glow);
needsUpdateTrace = true;
}
if (this.traceRenderable.values.dBounces.ref.value !== props.bounces) {
mol_util_1.ValueCell.update(this.traceRenderable.values.dBounces, props.bounces);
needsUpdateTrace = true;
}
if (this.traceRenderable.values.dSteps.ref.value !== steps) {
mol_util_1.ValueCell.update(this.traceRenderable.values.dSteps, steps);
needsUpdateTrace = true;
}
if (this.traceRenderable.values.dFirstStepSize.ref.value !== props.firstStepSize) {
mol_util_1.ValueCell.update(this.traceRenderable.values.dFirstStepSize, props.firstStepSize);
needsUpdateTrace = true;
}
if (this.traceRenderable.values.dRefineSteps.ref.value !== refineSteps) {
mol_util_1.ValueCell.update(this.traceRenderable.values.dRefineSteps, refineSteps);
needsUpdateTrace = true;
}
mol_util_1.ValueCell.updateIfChanged(this.traceRenderable.values.uRayDistance, props.rayDistance);
if (this.traceRenderable.values.dThicknessMode.ref.value !== props.thicknessMode) {
mol_util_1.ValueCell.update(this.traceRenderable.values.dThicknessMode, props.thicknessMode);
needsUpdateTrace = true;
}
mol_util_1.ValueCell.updateIfChanged(this.traceRenderable.values.uMinThickness, props.minThickness);
mol_util_1.ValueCell.updateIfChanged(this.traceRenderable.values.uThicknessFactor, props.thicknessFactor);
mol_util_1.ValueCell.updateIfChanged(this.traceRenderable.values.uThickness, props.thickness);
if (this.traceRenderable.values.dShadowEnable.ref.value !== props.shadowEnable) {
mol_util_1.ValueCell.update(this.traceRenderable.values.dShadowEnable, props.shadowEnable);
needsUpdateTrace = true;
}
mol_util_1.ValueCell.updateIfChanged(this.traceRenderable.values.uShadowSoftness, props.shadowSoftness);
mol_util_1.ValueCell.updateIfChanged(this.traceRenderable.values.uShadowThickness, props.shadowThickness);
if (needsUpdateTrace)
this.traceRenderable.update();
if (debug_1.isTimingMode)
this.webgl.timer.mark('TracePass.renderTrace');
this.traceRenderable.render();
if (debug_1.isTimingMode)
this.webgl.timer.markEnd('TracePass.renderTrace');
// accumulate
this.accumulateTarget.bind();
this.accumulateRenderable.render();
if (debug_1.isTimingMode)
this.webgl.timer.markEnd('TracePass.render');
}
}
exports.TracingPass = TracingPass;
//
const TraceSchema = {
...util_1.QuadSchema,
tColor: (0, schema_1.TextureSpec)('texture', 'rgba', 'ubyte', 'nearest'),
tNormal: (0, schema_1.TextureSpec)('texture', 'rgba', 'ubyte', 'nearest'),
tShaded: (0, schema_1.TextureSpec)('texture', 'rgba', 'ubyte', 'nearest'),
tThickness: (0, schema_1.TextureSpec)('texture', 'rgba', 'ubyte', 'nearest'),
tAccumulate: (0, schema_1.TextureSpec)('texture', 'rgba', 'ubyte', 'nearest'),
tDepth: (0, schema_1.TextureSpec)('texture', 'rgba', 'ubyte', 'nearest'),
uTexSize: (0, schema_1.UniformSpec)('v2'),
dOrthographic: (0, schema_1.DefineSpec)('number'),
uNear: (0, schema_1.UniformSpec)('f'),
uFar: (0, schema_1.UniformSpec)('f'),
uFogNear: (0, schema_1.UniformSpec)('f'),
uFogFar: (0, schema_1.UniformSpec)('f'),
uFogColor: (0, schema_1.UniformSpec)('v3'),
uProjection: (0, schema_1.UniformSpec)('m4'),
uInvProjection: (0, schema_1.UniformSpec)('m4'),
uBounds: (0, schema_1.UniformSpec)('v4'),
uLightDirection: (0, schema_1.UniformSpec)('v3[]'),
uLightColor: (0, schema_1.UniformSpec)('v3[]'),
dLightCount: (0, schema_1.DefineSpec)('number'),
uAmbientColor: (0, schema_1.UniformSpec)('v3'),
uLightStrength: (0, schema_1.UniformSpec)('v3'),
uFrameNo: (0, schema_1.UniformSpec)('i'),
dRendersPerFrame: (0, schema_1.DefineSpec)('number'),
dGlow: (0, schema_1.DefineSpec)('boolean'),
dBounces: (0, schema_1.DefineSpec)('number'),
dSteps: (0, schema_1.DefineSpec)('number'),
dFirstStepSize: (0, schema_1.DefineSpec)('number'),
dRefineSteps: (0, schema_1.DefineSpec)('number'),
uRayDistance: (0, schema_1.UniformSpec)('f'),
dThicknessMode: (0, schema_1.DefineSpec)('string'),
uMinThickness: (0, schema_1.UniformSpec)('f'),
uThicknessFactor: (0, schema_1.UniformSpec)('f'),
uThickness: (0, schema_1.UniformSpec)('f'),
dShadowEnable: (0, schema_1.DefineSpec)('boolean'),
uShadowSoftness: (0, schema_1.UniformSpec)('f'),
uShadowThickness: (0, schema_1.UniformSpec)('f'),
};
const TraceShaderCode = (0, shader_code_1.ShaderCode)('trace', quad_vert_1.quad_vert, trace_frag_1.trace_frag);
function getTraceRenderable(ctx, colorTexture, normalTexture, shadedTexture, thicknessTexture, accumulateTexture, depthTexture) {
const values = {
...util_1.QuadValues,
tColor: mol_util_1.ValueCell.create(colorTexture),
tNormal: mol_util_1.ValueCell.create(normalTexture),
tShaded: mol_util_1.ValueCell.create(shadedTexture),
tThickness: mol_util_1.ValueCell.create(thicknessTexture),
tAccumulate: mol_util_1.ValueCell.create(accumulateTexture),
tDepth: mol_util_1.ValueCell.create(depthTexture),
uTexSize: mol_util_1.ValueCell.create(vec2_1.Vec2.create(colorTexture.getWidth(), colorTexture.getHeight())),
dOrthographic: mol_util_1.ValueCell.create(0),
uNear: mol_util_1.ValueCell.create(1),
uFar: mol_util_1.ValueCell.create(10000),
uFogNear: mol_util_1.ValueCell.create(10000),
uFogFar: mol_util_1.ValueCell.create(10000),
uFogColor: mol_util_1.ValueCell.create(vec3_1.Vec3.create(1, 1, 1)),
uProjection: mol_util_1.ValueCell.create(mat4_1.Mat4.identity()),
uInvProjection: mol_util_1.ValueCell.create(mat4_1.Mat4.identity()),
uBounds: mol_util_1.ValueCell.create((0, vec4_1.Vec4)()),
uLightDirection: mol_util_1.ValueCell.create([]),
uLightColor: mol_util_1.ValueCell.create([]),
dLightCount: mol_util_1.ValueCell.create(0),
uAmbientColor: mol_util_1.ValueCell.create((0, vec3_1.Vec3)()),
uLightStrength: mol_util_1.ValueCell.create(vec3_1.Vec3.create(1, 1, 1)),
uFrameNo: mol_util_1.ValueCell.create(0),
dRendersPerFrame: mol_util_1.ValueCell.create(1),
dGlow: mol_util_1.ValueCell.create(true),
dBounces: mol_util_1.ValueCell.create(4),
dSteps: mol_util_1.ValueCell.create(32),
dFirstStepSize: mol_util_1.ValueCell.create(0.01),
dRefineSteps: mol_util_1.ValueCell.create(4),
uRayDistance: mol_util_1.ValueCell.create(256),
dThicknessMode: mol_util_1.ValueCell.create('auto'),
uMinThickness: mol_util_1.ValueCell.create(0.5),
uThicknessFactor: mol_util_1.ValueCell.create(1),
uThickness: mol_util_1.ValueCell.create(4),
dShadowEnable: mol_util_1.ValueCell.create(false),
uShadowSoftness: mol_util_1.ValueCell.create(0.1),
uShadowThickness: mol_util_1.ValueCell.create(0.1),
};
const schema = { ...TraceSchema };
const renderItem = (0, render_item_1.createComputeRenderItem)(ctx, 'triangles', TraceShaderCode, schema, values);
return (0, renderable_1.createComputeRenderable)(renderItem, values);
}
//
const AccumulateSchema = {
...util_1.QuadSchema,
tColor: (0, schema_1.TextureSpec)('texture', 'rgba', 'ubyte', 'nearest'),
uTexSize: (0, schema_1.UniformSpec)('v2'),
uWeight: (0, schema_1.UniformSpec)('f'),
};
const AccumulateShaderCode = (0, shader_code_1.ShaderCode)('accumulate', quad_vert_1.quad_vert, accumulate_frag_1.accumulate_frag);
function getAccumulateRenderable(ctx, colorTexture) {
const values = {
...util_1.QuadValues,
tColor: mol_util_1.ValueCell.create(colorTexture),
uTexSize: mol_util_1.ValueCell.create(vec2_1.Vec2.create(colorTexture.getWidth(), colorTexture.getHeight())),
uWeight: mol_util_1.ValueCell.create(1.0),
};
const schema = { ...AccumulateSchema };
const renderItem = (0, render_item_1.createComputeRenderItem)(ctx, 'triangles', AccumulateShaderCode, schema, values);
return (0, renderable_1.createComputeRenderable)(renderItem, values);
}