mirror of
https://github.com/molstar/molstar.git
synced 2026-06-04 13:30:24 +08:00
Merge branch 'master' of https://github.com/molstar/molstar into cam-anim-params
This commit is contained in:
@@ -4,6 +4,8 @@ All notable changes to this project will be documented in this file, following t
|
||||
Note that since we don't clearly distinguish between a public and private interfaces there will be changes in non-major versions that are potentially breaking. If we make breaking changes to less used interfaces we will highlight it in here.
|
||||
|
||||
## [Unreleased]
|
||||
- Fix exported image artifacts on transparent background with emissive, bloom, or antialiasing
|
||||
- Fix cel-shaded ambient color being stripped to luminance (now uses full RGB, matching the classic lighting path)
|
||||
- Fix empty transforms default in `ShapeFromPly`
|
||||
- Use morton order for spheres in dot visual with lod-levels
|
||||
- Add `Camera.changed` event and rotation/translation setter/getter
|
||||
@@ -12,8 +14,10 @@ Note that since we don't clearly distinguish between a public and private interf
|
||||
- Add mesoscale representation preset
|
||||
- Add presets option to `ObjectList` param definition
|
||||
- Fix memory leak in `State.dispose()` not invoking transformer `dispose` callbacks for live cells
|
||||
- Fix bugs in ModelServer surroundingLigands endpoint, resulting in omitWater not honored
|
||||
- Fix `Volume` and `Isosurface` getBoundingSphere ignoring instances
|
||||
- Add axis param to camera spin/rock animation
|
||||
- Fix SSAO half/quarter resolution textures for multi-scale
|
||||
|
||||
## [v5.9.0] - 2026-05-03
|
||||
- Fix edge case when `PluginSpec.animations` is empty
|
||||
|
||||
@@ -98,7 +98,6 @@ export const Canvas3DParams = {
|
||||
transparentBackground: PD.Boolean(false),
|
||||
checkeredTransparentBackground: PD.Boolean(false),
|
||||
dpoitIterations: PD.Numeric(2, { min: 1, max: 10, step: 1 }),
|
||||
enableAnimation: PD.Boolean(true, { description: 'Enable GPU time-based animations (wiggle/tumble).' }),
|
||||
pickPadding: PD.Numeric(3, { min: 0, max: 10, step: 1 }, { description: 'Extra pixels to around target to check in case target is empty.' }),
|
||||
userInteractionReleaseMs: PD.Numeric(250, { min: 0, max: 1000, step: 1 }, { description: 'The time before the user is not considered interacting anymore.' }),
|
||||
|
||||
@@ -480,7 +479,6 @@ namespace Canvas3D {
|
||||
const hiZ = new HiZPass(webgl, passes.draw, canvas, p.hiZ);
|
||||
|
||||
const renderer = Renderer.create(webgl, p.renderer);
|
||||
renderer.setProps({ enableAnimation: p.enableAnimation });
|
||||
renderer.setOcclusionTest(hiZ.isOccluded);
|
||||
|
||||
const shaderManager = new ShaderManager(webgl, scene);
|
||||
@@ -677,7 +675,7 @@ namespace Canvas3D {
|
||||
const xrChanged = xrManager.update(xrFrame);
|
||||
if (!xrChanged && xrFrame) return false;
|
||||
|
||||
const activeAnimation = p.enableAnimation && scene.hasAnimation;
|
||||
const activeAnimation = renderer.props.enableAnimation && scene.hasAnimation;
|
||||
const shouldRender = force || cameraChanged || resized || forceNextRender || xrChanged || activeAnimation;
|
||||
forceNextRender = false;
|
||||
|
||||
@@ -1071,7 +1069,6 @@ namespace Canvas3D {
|
||||
transparentBackground: p.transparentBackground,
|
||||
checkeredTransparentBackground: p.checkeredTransparentBackground,
|
||||
dpoitIterations: p.dpoitIterations,
|
||||
enableAnimation: p.enableAnimation,
|
||||
pickPadding: p.pickPadding,
|
||||
userInteractionReleaseMs: p.userInteractionReleaseMs,
|
||||
viewport: p.viewport,
|
||||
@@ -1317,10 +1314,6 @@ namespace Canvas3D {
|
||||
if (props.transparentBackground !== undefined) p.transparentBackground = props.transparentBackground;
|
||||
if (props.checkeredTransparentBackground !== undefined) p.checkeredTransparentBackground = props.checkeredTransparentBackground;
|
||||
if (props.dpoitIterations !== undefined) p.dpoitIterations = props.dpoitIterations;
|
||||
if (props.enableAnimation !== undefined) {
|
||||
p.enableAnimation = props.enableAnimation;
|
||||
renderer.setProps({ enableAnimation: p.enableAnimation });
|
||||
}
|
||||
if (props.pickPadding !== undefined) {
|
||||
p.pickPadding = props.pickPadding;
|
||||
pickHelper.setPickPadding(p.pickPadding);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Copyright (c) 2019-2025 mol* contributors, licensed under MIT, See LICENSE file for more info.
|
||||
* Copyright (c) 2019-2026 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>
|
||||
@@ -484,27 +484,45 @@ export class SsaoPass {
|
||||
if (isTimingMode) this.webgl.timer.markEnd('SSAO.downsample');
|
||||
}
|
||||
|
||||
if (isTimingMode) this.webgl.timer.mark('SSAO.half');
|
||||
if (multiScale) {
|
||||
// half-resolution viewport (matches dimensions of depthHalfTarget*)
|
||||
const hsx = Math.floor(sx * 0.5);
|
||||
const hsy = Math.floor(sy * 0.5);
|
||||
const hsw = Math.ceil(sw * 0.5);
|
||||
const hsh = Math.ceil(sh * 0.5);
|
||||
state.viewport(hsx, hsy, hsw, hsh);
|
||||
state.scissor(hsx, hsy, hsw, hsh);
|
||||
|
||||
if (isTimingMode) this.webgl.timer.mark('SSAO.half');
|
||||
this.depthHalfTargetOpaque.bind();
|
||||
this.depthHalfRenderableOpaque.render();
|
||||
}
|
||||
if (multiScale && includeTransparent) {
|
||||
this.depthHalfTargetTransparent.bind();
|
||||
this.depthHalfRenderableTransparent.render();
|
||||
}
|
||||
if (isTimingMode) this.webgl.timer.markEnd('SSAO.half');
|
||||
if (includeTransparent) {
|
||||
this.depthHalfTargetTransparent.bind();
|
||||
this.depthHalfRenderableTransparent.render();
|
||||
}
|
||||
if (isTimingMode) this.webgl.timer.markEnd('SSAO.half');
|
||||
|
||||
if (isTimingMode) this.webgl.timer.mark('SSAO.quarter');
|
||||
if (multiScale) {
|
||||
// quarter-resolution viewport (matches dimensions of depthQuarterTarget*)
|
||||
const qsx = Math.floor(sx * 0.25);
|
||||
const qsy = Math.floor(sy * 0.25);
|
||||
const qsw = Math.ceil(sw * 0.25);
|
||||
const qsh = Math.ceil(sh * 0.25);
|
||||
state.viewport(qsx, qsy, qsw, qsh);
|
||||
state.scissor(qsx, qsy, qsw, qsh);
|
||||
|
||||
if (isTimingMode) this.webgl.timer.mark('SSAO.quarter');
|
||||
this.depthQuarterTargetOpaque.bind();
|
||||
this.depthQuarterRenderableOpaque.render();
|
||||
if (includeTransparent) {
|
||||
this.depthQuarterTargetTransparent.bind();
|
||||
this.depthQuarterRenderableTransparent.render();
|
||||
}
|
||||
if (isTimingMode) this.webgl.timer.markEnd('SSAO.quarter');
|
||||
|
||||
// restore full-scale viewport for SSAO + blur passes
|
||||
state.viewport(sx, sy, sw, sh);
|
||||
state.scissor(sx, sy, sw, sh);
|
||||
}
|
||||
if (multiScale && includeTransparent) {
|
||||
this.depthQuarterTargetTransparent.bind();
|
||||
this.depthQuarterRenderableTransparent.render();
|
||||
}
|
||||
if (isTimingMode) this.webgl.timer.markEnd('SSAO.quarter');
|
||||
|
||||
if (isTimingMode) this.webgl.timer.mark('SSAO.opaque');
|
||||
this.ssaoDepthTexture.attachFramebuffer(this.framebuffer, 'color0');
|
||||
|
||||
@@ -78,7 +78,7 @@ export const apply_light_color = `
|
||||
}
|
||||
#pragma unroll_loop_end
|
||||
|
||||
outgoingLight += physicalMaterial.diffuseColor * luminance(uAmbientColor);
|
||||
outgoingLight += physicalMaterial.diffuseColor * uAmbientColor;
|
||||
#else
|
||||
ReflectedLight reflectedLight = ReflectedLight(vec3(0.0), vec3(0.0), vec3(0.0), vec3(0.0));
|
||||
|
||||
|
||||
@@ -545,6 +545,12 @@ export function surroundingLigands({ query, radius, includeWater }: SurroundingL
|
||||
continue;
|
||||
}
|
||||
|
||||
// Water is handled exclusively by the `includeWater` 3D-lookup branch below.
|
||||
// A single water pulled in via a struct_conn metalc/covale edge would
|
||||
// otherwise match every other water in the chain (all share label_seq_id
|
||||
// and label_comp_id) and leak the entire chain.
|
||||
if (StructureProperties.entity.type(l) === 'water') continue;
|
||||
|
||||
residuesIt.setSegment(chainSegment);
|
||||
while (residuesIt.hasNext) {
|
||||
const residueSegment = residuesIt.move();
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
* Copyright (c) 2019-2021 mol* contributors, licensed under MIT, See LICENSE file for more info.
|
||||
*
|
||||
* @author Alexander Rose <alexander.rose@weirdbyte.de>
|
||||
* @author Gianluca Tomasello <giagitom@gmail.com>
|
||||
*/
|
||||
|
||||
export { PixelData };
|
||||
@@ -37,12 +38,14 @@ namespace PixelData {
|
||||
/** to undo pre-multiplied alpha */
|
||||
export function divideByAlpha(pixelData: PixelData): PixelData {
|
||||
const { array } = pixelData;
|
||||
const factor = (array instanceof Uint8Array) ? 255 : 1;
|
||||
// clamp: emissive, bloom and antialiasing can lift premul RGB above alpha; without it Uint8Array silently wraps.
|
||||
const max = (array instanceof Uint8Array) ? 255 : 1;
|
||||
for (let i = 0, il = array.length; i < il; i += 4) {
|
||||
const a = array[i + 3] / factor;
|
||||
array[i] /= a;
|
||||
array[i + 1] /= a;
|
||||
array[i + 2] /= a;
|
||||
const a = array[i + 3] / max;
|
||||
if (a === 0) continue;
|
||||
array[i] = Math.min(max, array[i] / a);
|
||||
array[i + 1] = Math.min(max, array[i + 1] / a);
|
||||
array[i + 2] = Math.min(max, array[i + 2] / a);
|
||||
}
|
||||
return pixelData;
|
||||
}
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
# 0.9.13
|
||||
* /surroundingLigands: honor `omit_water=true|false` for REST GET requests (boolean parser previously coerced both to `false`)
|
||||
* /surroundingLigands: stop leaking the asymmetric unit's water chain into the result when `omit_water=true` (water residues pulled in via struct_conn covale/metalc edges no longer match every other water in the chain)
|
||||
|
||||
# 0.9.12
|
||||
* add `health-check` endpoint + `healthCheckPath` config prop to report service health
|
||||
|
||||
|
||||
@@ -295,7 +295,7 @@ function _normalizeQueryParams(params: { [p: string]: string }, paramList: Query
|
||||
case QueryParamType.String: el = value; break;
|
||||
case QueryParamType.Integer: el = parseInt(value); break;
|
||||
case QueryParamType.Float: el = parseFloat(value); break;
|
||||
case QueryParamType.Boolean: el = Boolean(+value); break;
|
||||
case QueryParamType.Boolean: el = isTrue(value); break;
|
||||
}
|
||||
|
||||
if (p.validation) p.validation(el);
|
||||
|
||||
@@ -4,4 +4,4 @@
|
||||
* @author David Sehnal <david.sehnal@gmail.com>
|
||||
*/
|
||||
|
||||
export const VERSION = '0.9.12';
|
||||
export const VERSION = '0.9.13';
|
||||
Reference in New Issue
Block a user