molstar
Version:
A comprehensive macromolecular library.
132 lines (131 loc) • 6.96 kB
JavaScript
"use strict";
/**
* Copyright (c) 2019-2024 mol* contributors, licensed under MIT, See LICENSE file for more info.
*
* @author Alexander Rose <alexander.rose@weirdbyte.de>
* @author Áron Samuel Kovács <aron.kovacs@mail.muni.cz>
* @author Ludovic Autin <ludovic.autin@gmail.com>
* @author Gianluca Tomasello <giagitom@gmail.com>
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.ShadowPass = exports.ShadowParams = void 0;
const util_1 = require("../../mol-gl/compute/util");
const schema_1 = require("../../mol-gl/renderable/schema");
const shader_code_1 = require("../../mol-gl/shader-code");
const mol_util_1 = require("../../mol-util");
const render_item_1 = require("../../mol-gl/webgl/render-item");
const renderable_1 = require("../../mol-gl/renderable");
const linear_algebra_1 = require("../../mol-math/linear-algebra");
const param_definition_1 = require("../../mol-util/param-definition");
const quad_vert_1 = require("../../mol-gl/shader/quad.vert");
const debug_1 = require("../../mol-util/debug");
const shadows_frag_1 = require("../../mol-gl/shader/shadows.frag");
exports.ShadowParams = {
steps: param_definition_1.ParamDefinition.Numeric(1, { min: 1, max: 64, step: 1 }),
maxDistance: param_definition_1.ParamDefinition.Numeric(3, { min: 0, max: 256, step: 1 }),
tolerance: param_definition_1.ParamDefinition.Numeric(1.0, { min: 0.0, max: 10.0, step: 0.1 }),
};
class ShadowPass {
static isEnabled(props) {
return props.shadow.name !== 'off';
}
constructor(webgl, width, height, depthTextureOpaque) {
this.webgl = webgl;
this.target = webgl.createRenderTarget(width, height, false);
this.renderable = getShadowsRenderable(webgl, depthTextureOpaque);
}
setSize(width, height) {
const [w, h] = this.renderable.values.uTexSize.ref.value;
if (width !== w || height !== h) {
this.target.setSize(width, height);
mol_util_1.ValueCell.update(this.renderable.values.uTexSize, linear_algebra_1.Vec2.set(this.renderable.values.uTexSize.ref.value, width, height));
}
}
update(camera, light, ambientColor, props) {
let needsUpdateShadows = false;
const orthographic = camera.state.mode === 'orthographic' ? 1 : 0;
const invProjection = linear_algebra_1.Mat4.identity();
linear_algebra_1.Mat4.invert(invProjection, camera.projection);
const [w, h] = this.renderable.values.uTexSize.ref.value;
const v = camera.viewport;
mol_util_1.ValueCell.update(this.renderable.values.uProjection, camera.projection);
mol_util_1.ValueCell.update(this.renderable.values.uInvProjection, invProjection);
linear_algebra_1.Vec4.set(this.renderable.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.renderable.values.uBounds, this.renderable.values.uBounds.ref.value);
mol_util_1.ValueCell.updateIfChanged(this.renderable.values.uNear, camera.near);
mol_util_1.ValueCell.updateIfChanged(this.renderable.values.uFar, camera.far);
if (this.renderable.values.dOrthographic.ref.value !== orthographic) {
mol_util_1.ValueCell.update(this.renderable.values.dOrthographic, orthographic);
needsUpdateShadows = true;
}
mol_util_1.ValueCell.updateIfChanged(this.renderable.values.uMaxDistance, props.maxDistance);
mol_util_1.ValueCell.updateIfChanged(this.renderable.values.uTolerance, props.tolerance);
if (this.renderable.values.dSteps.ref.value !== props.steps) {
mol_util_1.ValueCell.update(this.renderable.values.dSteps, props.steps);
needsUpdateShadows = true;
}
mol_util_1.ValueCell.update(this.renderable.values.uLightDirection, light.direction);
mol_util_1.ValueCell.update(this.renderable.values.uLightColor, light.color);
if (this.renderable.values.dLightCount.ref.value !== light.count) {
mol_util_1.ValueCell.update(this.renderable.values.dLightCount, light.count);
needsUpdateShadows = true;
}
mol_util_1.ValueCell.update(this.renderable.values.uAmbientColor, ambientColor);
if (needsUpdateShadows) {
this.renderable.update();
}
}
render() {
if (debug_1.isTimingMode)
this.webgl.timer.mark('ShadowPass.render');
this.target.bind();
this.renderable.render();
if (debug_1.isTimingMode)
this.webgl.timer.markEnd('ShadowPass.render');
}
}
exports.ShadowPass = ShadowPass;
const ShadowsSchema = {
...util_1.QuadSchema,
tDepth: (0, schema_1.TextureSpec)('texture', 'rgba', 'ubyte', 'nearest'),
uTexSize: (0, schema_1.UniformSpec)('v2'),
uProjection: (0, schema_1.UniformSpec)('m4'),
uInvProjection: (0, schema_1.UniformSpec)('m4'),
uBounds: (0, schema_1.UniformSpec)('v4'),
dOrthographic: (0, schema_1.DefineSpec)('number'),
uNear: (0, schema_1.UniformSpec)('f'),
uFar: (0, schema_1.UniformSpec)('f'),
dSteps: (0, schema_1.DefineSpec)('number'),
uMaxDistance: (0, schema_1.UniformSpec)('f'),
uTolerance: (0, schema_1.UniformSpec)('f'),
uLightDirection: (0, schema_1.UniformSpec)('v3[]'),
uLightColor: (0, schema_1.UniformSpec)('v3[]'),
dLightCount: (0, schema_1.DefineSpec)('number'),
uAmbientColor: (0, schema_1.UniformSpec)('v3'),
};
function getShadowsRenderable(ctx, depthTexture) {
const width = depthTexture.getWidth();
const height = depthTexture.getHeight();
const values = {
...util_1.QuadValues,
tDepth: mol_util_1.ValueCell.create(depthTexture),
uTexSize: mol_util_1.ValueCell.create(linear_algebra_1.Vec2.create(width, height)),
uProjection: mol_util_1.ValueCell.create(linear_algebra_1.Mat4.identity()),
uInvProjection: mol_util_1.ValueCell.create(linear_algebra_1.Mat4.identity()),
uBounds: mol_util_1.ValueCell.create((0, linear_algebra_1.Vec4)()),
dOrthographic: mol_util_1.ValueCell.create(0),
uNear: mol_util_1.ValueCell.create(1),
uFar: mol_util_1.ValueCell.create(10000),
dSteps: mol_util_1.ValueCell.create(1),
uMaxDistance: mol_util_1.ValueCell.create(3.0),
uTolerance: mol_util_1.ValueCell.create(1.0),
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, linear_algebra_1.Vec3)()),
};
const schema = { ...ShadowsSchema };
const shaderCode = (0, shader_code_1.ShaderCode)('shadows', quad_vert_1.quad_vert, shadows_frag_1.shadows_frag);
const renderItem = (0, render_item_1.createComputeRenderItem)(ctx, 'triangles', shaderCode, schema, values);
return (0, renderable_1.createComputeRenderable)(renderItem, values);
}