Merge pull request #1761 from molstar/fix-color-smoothing

This commit is contained in:
Alexander Rose
2026-01-25 22:26:35 -08:00
committed by GitHub
7 changed files with 95 additions and 62 deletions

View File

@@ -4,6 +4,10 @@ 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]
- Color smoothing fixes (#1747)
- Use correct instance for non instance-type
- Never transform for non instance-type
- Add extra radius to gaussian surface boundingsphere
## [v5.6.1] - 2026-01-23
- Disable occlusion culling in `ImagePass` (#1758)

View File

@@ -1,5 +1,5 @@
/**
* Copyright (c) 2021-2025 mol* contributors, licensed under MIT, See LICENSE file for more info.
* Copyright (c) 2021-2026 mol* contributors, licensed under MIT, See LICENSE file for more info.
*
* @author Alexander Rose <alexander.rose@weirdbyte.de>
*/
@@ -29,8 +29,14 @@ interface ColorSmoothingInput {
itemSize: 4 | 3 | 1
}
export function calcMeshColorSmoothing(input: ColorSmoothingInput, resolution: number, stride: number, webgl?: WebGLContext, texture?: Texture) {
export type ColorSmoothingOptions = {
resolution: number,
stride: number
};
export function calcMeshColorSmoothing(input: ColorSmoothingInput, options: ColorSmoothingOptions, webgl?: WebGLContext, texture?: Texture) {
const { colorType, vertexCount, groupCount, positionBuffer, instanceBuffer, transformBuffer, groupBuffer, itemSize } = input;
const { resolution, stride } = options;
const isInstanceType = colorType.endsWith('Instance');
const box = Box3D.fromSphere3D(Box3D(), isInstanceType ? input.boundingSphere : input.invariantBoundingSphere);
@@ -70,7 +76,7 @@ export function calcMeshColorSmoothing(input: ColorSmoothingInput, resolution: n
for (let i = 0; i < instanceCount; ++i) {
// - use reordered index for access from GPU
// - use serial index for access from CPU
const instanceIndex = webgl ? instanceBuffer[i] : i;
const instanceIndex = (webgl && isInstanceType) ? instanceBuffer[i] : i;
for (let j = 0; j < vertexCount; j += stride) {
Vec3.fromArray(v, positionBuffer, j * 3);
if (isInstanceType) Vec3.transformMat4Offset(v, v, transformBuffer, 0, 0, i * 16);
@@ -262,7 +268,7 @@ function isSupportedColorType(x: string): x is 'group' | 'groupInstance' {
return x === 'group' || x === 'groupInstance';
}
export function applyMeshColorSmoothing(values: MeshValues, resolution: number, stride: number, webgl?: WebGLContext, colorTexture?: Texture) {
export function applyMeshColorSmoothing(values: MeshValues, options: ColorSmoothingOptions, webgl?: WebGLContext, colorTexture?: Texture) {
if (!isSupportedColorType(values.dColorType.ref.value)) return;
const smoothingData = calcMeshColorSmoothing({
@@ -278,7 +284,7 @@ export function applyMeshColorSmoothing(values: MeshValues, resolution: number,
boundingSphere: values.boundingSphere.ref.value,
invariantBoundingSphere: values.invariantBoundingSphere.ref.value,
itemSize: 3
}, resolution, stride, webgl, colorTexture);
}, options, webgl, colorTexture);
if (smoothingData.kind === 'volume') {
ValueCell.updateIfChanged(values.dColorType, smoothingData.type);
@@ -297,7 +303,7 @@ function isSupportedOverpaintType(x: string): x is 'groupInstance' {
return x === 'groupInstance';
}
export function applyMeshOverpaintSmoothing(values: MeshValues, resolution: number, stride: number, webgl?: WebGLContext, colorTexture?: Texture) {
export function applyMeshOverpaintSmoothing(values: MeshValues, options: ColorSmoothingOptions, webgl?: WebGLContext, colorTexture?: Texture) {
if (!isSupportedOverpaintType(values.dOverpaintType.ref.value)) return;
const smoothingData = calcMeshColorSmoothing({
@@ -313,7 +319,7 @@ export function applyMeshOverpaintSmoothing(values: MeshValues, resolution: numb
boundingSphere: values.boundingSphere.ref.value,
invariantBoundingSphere: values.invariantBoundingSphere.ref.value,
itemSize: 4
}, resolution, stride, webgl, colorTexture);
}, options, webgl, colorTexture);
if (smoothingData.kind === 'volume') {
ValueCell.updateIfChanged(values.dOverpaintType, smoothingData.type);
ValueCell.update(values.tOverpaintGrid, smoothingData.texture);
@@ -331,7 +337,7 @@ function isSupportedTransparencyType(x: string): x is 'groupInstance' {
return x === 'groupInstance';
}
export function applyMeshTransparencySmoothing(values: MeshValues, resolution: number, stride: number, webgl?: WebGLContext, colorTexture?: Texture) {
export function applyMeshTransparencySmoothing(values: MeshValues, options: ColorSmoothingOptions, webgl?: WebGLContext, colorTexture?: Texture) {
if (!isSupportedTransparencyType(values.dTransparencyType.ref.value)) return;
const smoothingData = calcMeshColorSmoothing({
@@ -347,7 +353,7 @@ export function applyMeshTransparencySmoothing(values: MeshValues, resolution: n
boundingSphere: values.boundingSphere.ref.value,
invariantBoundingSphere: values.invariantBoundingSphere.ref.value,
itemSize: 1
}, resolution, stride, webgl, colorTexture);
}, options, webgl, colorTexture);
if (smoothingData.kind === 'volume') {
ValueCell.updateIfChanged(values.dTransparencyType, smoothingData.type);
ValueCell.update(values.tTransparencyGrid, smoothingData.texture);
@@ -365,7 +371,7 @@ function isSupportedEmissiveType(x: string): x is 'groupInstance' {
return x === 'groupInstance';
}
export function applyMeshEmissiveSmoothing(values: MeshValues, resolution: number, stride: number, webgl?: WebGLContext, colorTexture?: Texture) {
export function applyMeshEmissiveSmoothing(values: MeshValues, options: ColorSmoothingOptions, webgl?: WebGLContext, colorTexture?: Texture) {
if (!isSupportedEmissiveType(values.dEmissiveType.ref.value)) return;
const smoothingData = calcMeshColorSmoothing({
@@ -381,7 +387,7 @@ export function applyMeshEmissiveSmoothing(values: MeshValues, resolution: numbe
boundingSphere: values.boundingSphere.ref.value,
invariantBoundingSphere: values.invariantBoundingSphere.ref.value,
itemSize: 1
}, resolution, stride, webgl, colorTexture);
}, options, webgl, colorTexture);
if (smoothingData.kind === 'volume') {
ValueCell.updateIfChanged(values.dEmissiveType, smoothingData.type);
ValueCell.update(values.tEmissiveGrid, smoothingData.texture);
@@ -399,7 +405,7 @@ function isSupportedSubstanceType(x: string): x is 'groupInstance' {
return x === 'groupInstance';
}
export function applyMeshSubstanceSmoothing(values: MeshValues, resolution: number, stride: number, webgl?: WebGLContext, colorTexture?: Texture) {
export function applyMeshSubstanceSmoothing(values: MeshValues, options: ColorSmoothingOptions, webgl?: WebGLContext, colorTexture?: Texture) {
if (!isSupportedSubstanceType(values.dSubstanceType.ref.value)) return;
const smoothingData = calcMeshColorSmoothing({
@@ -415,7 +421,7 @@ export function applyMeshSubstanceSmoothing(values: MeshValues, resolution: numb
boundingSphere: values.boundingSphere.ref.value,
invariantBoundingSphere: values.invariantBoundingSphere.ref.value,
itemSize: 4
}, resolution, stride, webgl, colorTexture);
}, options, webgl, colorTexture);
if (smoothingData.kind === 'volume') {
ValueCell.updateIfChanged(values.dSubstanceType, smoothingData.type);
ValueCell.update(values.tSubstanceGrid, smoothingData.texture);

View File

@@ -1,5 +1,5 @@
/**
* Copyright (c) 2021-2024 mol* contributors, licensed under MIT, See LICENSE file for more info.
* Copyright (c) 2021-2026 mol* contributors, licensed under MIT, See LICENSE file for more info.
*
* @author Alexander Rose <alexander.rose@weirdbyte.de>
*/
@@ -14,7 +14,7 @@ import { ValueSpec, AttributeSpec, UniformSpec, TextureSpec, Values, DefineSpec
import { quad_vert } from '../../../mol-gl/shader/quad.vert';
import { normalize_frag } from '../../../mol-gl/shader/compute/color-smoothing/normalize.frag';
import { QuadSchema, QuadValues } from '../../../mol-gl/compute/util';
import { Vec2, Vec3, Vec4 } from '../../../mol-math/linear-algebra';
import { Mat4, Vec2, Vec3, Vec4 } from '../../../mol-math/linear-algebra';
import { Box3D, Sphere3D } from '../../../mol-math/geometry';
import { accumulate_frag } from '../../../mol-gl/shader/compute/color-smoothing/accumulate.frag';
import { accumulate_vert } from '../../../mol-gl/shader/compute/color-smoothing/accumulate.vert';
@@ -246,18 +246,30 @@ interface ColorSmoothingInput extends AccumulateInput {
invariantBoundingSphere: Sphere3D
}
export function calcTextureMeshColorSmoothing(input: ColorSmoothingInput, resolution: number, stride: number, webgl: WebGLContext, texture?: Texture) {
export type ColorSmoothingOptions = {
resolution: number,
stride: number
};
export function calcTextureMeshColorSmoothing(input: ColorSmoothingInput, options: ColorSmoothingOptions, webgl: WebGLContext, texture?: Texture) {
const { drawBuffers } = webgl.extensions;
if (!drawBuffers) throw new Error('need WebGL draw buffers');
if (isTimingMode) webgl.timer.mark('calcTextureMeshColorSmoothing');
const { gl, resources, state, extensions: { colorBufferHalfFloat, textureHalfFloat } } = webgl;
const { resolution, stride } = options;
const isInstanceType = input.colorType.endsWith('Instance');
const box = Box3D.fromSphere3D(Box3D(), isInstanceType ? input.boundingSphere : input.invariantBoundingSphere);
const pad = 1 + resolution;
const expandedBox = Box3D.expand(Box3D(), box, Vec3.create(pad, pad, pad));
if (!isInstanceType) {
input.instanceCount = 1;
input.instanceBuffer = new Float32Array([0]);
input.transformBuffer = new Float32Array(Mat4.id);
}
const scaleFactor = 1 / resolution;
const scaledBox = Box3D.scale(Box3D(), expandedBox, scaleFactor);
const gridDim = Box3D.size(Vec3(), scaledBox);
@@ -389,7 +401,7 @@ export function calcTextureMeshColorSmoothing(input: ColorSmoothingInput, resolu
const type = isInstanceType ? 'volumeInstance' : 'volume';
if (isTimingMode) webgl.timer.markEnd('calcTextureMeshColorSmoothing');
// printTextureImage(readTexture(webgl, texture), { scale: 0.75 });
// printTextureImage(readTexture(webgl, texture), { scale: 0.75, id: `${texture.id}` });
return { texture, gridDim, gridTexDim: Vec2.create(width, height), gridTransform, type };
}
@@ -404,10 +416,10 @@ function isSupportedColorType(x: string): x is 'group' | 'groupInstance' {
return x === 'group' || x === 'groupInstance';
}
export function applyTextureMeshColorSmoothing(values: TextureMeshValues, resolution: number, stride: number, webgl: WebGLContext, colorTexture?: Texture) {
export function applyTextureMeshColorSmoothing(values: TextureMeshValues, options: ColorSmoothingOptions, webgl: WebGLContext, colorTexture?: Texture) {
if (!isSupportedColorType(values.dColorType.ref.value)) return;
stride *= 3; // triple because TextureMesh is never indexed (no elements buffer)
options = { ...options, stride: options.stride * 3 }; // triple because TextureMesh is never indexed (no elements buffer)
if (!webgl.namedTextures[ColorSmoothingRgbName]) {
webgl.namedTextures[ColorSmoothingRgbName] = webgl.resources.texture('image-uint8', 'rgb', 'ubyte', 'nearest');
@@ -427,7 +439,7 @@ export function applyTextureMeshColorSmoothing(values: TextureMeshValues, resolu
colorType: values.dColorType.ref.value,
boundingSphere: values.boundingSphere.ref.value,
invariantBoundingSphere: values.invariantBoundingSphere.ref.value,
}, resolution, stride, webgl, colorTexture);
}, options, webgl, colorTexture);
ValueCell.updateIfChanged(values.dColorType, smoothingData.type);
ValueCell.update(values.tColorGrid, smoothingData.texture);
@@ -440,10 +452,10 @@ function isSupportedOverpaintType(x: string): x is 'groupInstance' {
return x === 'groupInstance';
}
export function applyTextureMeshOverpaintSmoothing(values: TextureMeshValues, resolution: number, stride: number, webgl: WebGLContext, colorTexture?: Texture) {
export function applyTextureMeshOverpaintSmoothing(values: TextureMeshValues, options: ColorSmoothingOptions, webgl: WebGLContext, colorTexture?: Texture) {
if (!isSupportedOverpaintType(values.dOverpaintType.ref.value)) return;
stride *= 3; // triple because TextureMesh is never indexed (no elements buffer)
options = { ...options, stride: options.stride * 3 }; // triple because TextureMesh is never indexed (no elements buffer)
if (!webgl.namedTextures[ColorSmoothingRgbaName]) {
webgl.namedTextures[ColorSmoothingRgbaName] = webgl.resources.texture('image-uint8', 'rgba', 'ubyte', 'nearest');
@@ -463,7 +475,7 @@ export function applyTextureMeshOverpaintSmoothing(values: TextureMeshValues, re
colorType: values.dOverpaintType.ref.value,
boundingSphere: values.boundingSphere.ref.value,
invariantBoundingSphere: values.invariantBoundingSphere.ref.value,
}, resolution, stride, webgl, colorTexture);
}, options, webgl, colorTexture);
ValueCell.updateIfChanged(values.dOverpaintType, smoothingData.type);
ValueCell.update(values.tOverpaintGrid, smoothingData.texture);
@@ -476,10 +488,10 @@ function isSupportedTransparencyType(x: string): x is 'groupInstance' {
return x === 'groupInstance';
}
export function applyTextureMeshTransparencySmoothing(values: TextureMeshValues, resolution: number, stride: number, webgl: WebGLContext, colorTexture?: Texture) {
export function applyTextureMeshTransparencySmoothing(values: TextureMeshValues, options: ColorSmoothingOptions, webgl: WebGLContext, colorTexture?: Texture) {
if (!isSupportedTransparencyType(values.dTransparencyType.ref.value)) return;
stride *= 3; // triple because TextureMesh is never indexed (no elements buffer)
options = { ...options, stride: options.stride * 3 }; // triple because TextureMesh is never indexed (no elements buffer)
if (!webgl.namedTextures[ColorSmoothingAlphaName]) {
webgl.namedTextures[ColorSmoothingAlphaName] = webgl.resources.texture('image-uint8', 'alpha', 'ubyte', 'nearest');
@@ -499,7 +511,7 @@ export function applyTextureMeshTransparencySmoothing(values: TextureMeshValues,
colorType: values.dTransparencyType.ref.value,
boundingSphere: values.boundingSphere.ref.value,
invariantBoundingSphere: values.invariantBoundingSphere.ref.value,
}, resolution, stride, webgl, colorTexture);
}, options, webgl, colorTexture);
ValueCell.updateIfChanged(values.dTransparencyType, smoothingData.type);
ValueCell.update(values.tTransparencyGrid, smoothingData.texture);
@@ -512,10 +524,10 @@ function isSupportedEmissiveType(x: string): x is 'groupInstance' {
return x === 'groupInstance';
}
export function applyTextureMeshEmissiveSmoothing(values: TextureMeshValues, resolution: number, stride: number, webgl: WebGLContext, colorTexture?: Texture) {
export function applyTextureMeshEmissiveSmoothing(values: TextureMeshValues, options: ColorSmoothingOptions, webgl: WebGLContext, colorTexture?: Texture) {
if (!isSupportedEmissiveType(values.dEmissiveType.ref.value)) return;
stride *= 3; // triple because TextureMesh is never indexed (no elements buffer)
options = { ...options, stride: options.stride * 3 }; // triple because TextureMesh is never indexed (no elements buffer)
if (!webgl.namedTextures[ColorSmoothingAlphaName]) {
webgl.namedTextures[ColorSmoothingAlphaName] = webgl.resources.texture('image-uint8', 'alpha', 'ubyte', 'nearest');
@@ -535,7 +547,7 @@ export function applyTextureMeshEmissiveSmoothing(values: TextureMeshValues, res
colorType: values.dEmissiveType.ref.value,
boundingSphere: values.boundingSphere.ref.value,
invariantBoundingSphere: values.invariantBoundingSphere.ref.value,
}, resolution, stride, webgl, colorTexture);
}, options, webgl, colorTexture);
ValueCell.updateIfChanged(values.dEmissiveType, smoothingData.type);
ValueCell.update(values.tEmissiveGrid, smoothingData.texture);
@@ -548,10 +560,10 @@ function isSupportedSubstanceType(x: string): x is 'groupInstance' {
return x === 'groupInstance';
}
export function applyTextureMeshSubstanceSmoothing(values: TextureMeshValues, resolution: number, stride: number, webgl: WebGLContext, colorTexture?: Texture) {
export function applyTextureMeshSubstanceSmoothing(values: TextureMeshValues, options: ColorSmoothingOptions, webgl: WebGLContext, colorTexture?: Texture) {
if (!isSupportedSubstanceType(values.dSubstanceType.ref.value)) return;
stride *= 3; // triple because TextureMesh is never indexed (no elements buffer)
options = { ...options, stride: options.stride * 3 }; // triple because TextureMesh is never indexed (no elements buffer)
if (!webgl.namedTextures[ColorSmoothingRgbaName]) {
webgl.namedTextures[ColorSmoothingRgbaName] = webgl.resources.texture('image-uint8', 'rgba', 'ubyte', 'nearest');
@@ -571,7 +583,7 @@ export function applyTextureMeshSubstanceSmoothing(values: TextureMeshValues, re
colorType: values.dSubstanceType.ref.value,
boundingSphere: values.boundingSphere.ref.value,
invariantBoundingSphere: values.invariantBoundingSphere.ref.value,
}, resolution, stride, webgl, colorTexture);
}, options, webgl, colorTexture);
ValueCell.updateIfChanged(values.dSubstanceType, smoothingData.type);
ValueCell.update(values.tSubstanceGrid, smoothingData.texture);

View File

@@ -1,5 +1,5 @@
/**
* Copyright (c) 2018-2025 mol* contributors, licensed under MIT, See LICENSE file for more info.
* Copyright (c) 2018-2026 mol* contributors, licensed under MIT, See LICENSE file for more info.
*
* @author Alexander Rose <alexander.rose@weirdbyte.de>
*/
@@ -82,6 +82,13 @@ export function printTextureImage(textureImage: TextureImage<any>, options: Part
} else {
data.set(array);
}
} else if (itemSize === 3) {
for (let i = 0, il = width * height; i < il; ++i) {
data[i * 4] = array[i * 3];
data[i * 4 + 1] = array[i * 3 + 1];
data[i * 4 + 2] = array[i * 3 + 2];
data[i * 4 + 3] = 255;
}
} else {
console.warn(`itemSize '${itemSize}' not supported`);
}

View File

@@ -1,5 +1,5 @@
/**
* Copyright (c) 2018-2025 mol* contributors, licensed under MIT, See LICENSE file for more info.
* Copyright (c) 2018-2026 mol* contributors, licensed under MIT, See LICENSE file for more info.
*
* @author Alexander Rose <alexander.rose@weirdbyte.de>
*/
@@ -88,20 +88,20 @@ type GaussianSurfaceMeta = {
//
async function createGaussianSurfaceMesh(ctx: VisualContext, unit: Unit, structure: Structure, theme: Theme, props: GaussianDensityProps, mesh?: Mesh): Promise<Mesh> {
const { smoothness } = props;
const { smoothness, floodfill, includeParent, radiusOffset } = props;
const { transform, field, idField, radiusFactor, resolution, maxRadius } = await computeUnitGaussianDensity(structure, unit, theme.size, props).runInContext(ctx.runtime);
const isoLevel = Math.exp(-smoothness) / radiusFactor;
const params = {
isoLevel,
scalarField: props.floodfill !== 'off' ? Tensor.createFloodfilled(field, isoLevel, props.floodfill) : field,
scalarField: floodfill !== 'off' ? Tensor.createFloodfilled(field, isoLevel, floodfill) : field,
idField
};
const surface = await computeMarchingCubesMesh(params, mesh).runAsChild(ctx.runtime);
(surface.meta.resolution as GaussianSurfaceMeta['resolution']) = resolution;
if (props.includeParent) {
const iterations = Math.ceil(2 / props.resolution);
if (includeParent) {
const iterations = Math.ceil(2 / resolution);
Mesh.smoothEdges(surface, { iterations, maxNewEdgeLength: Math.sqrt(2) });
}
@@ -113,7 +113,8 @@ async function createGaussianSurfaceMesh(ctx: VisualContext, unit: Unit, structu
ValueCell.updateIfChanged(surface.varyingGroup, true);
}
const sphere = Sphere3D.expand(Sphere3D(), unit.boundary.sphere, maxRadius);
const extraRadius = radiusOffset * (1 + Math.exp(-smoothness));
const sphere = Sphere3D.expand(Sphere3D(), unit.boundary.sphere, maxRadius + extraRadius);
surface.setBoundingSphere(sphere);
return surface;
@@ -152,7 +153,7 @@ export function GaussianSurfaceMeshVisual(materialId: number): UnitsVisual<Gauss
const { resolution, colorTexture } = geometry.meta as GaussianSurfaceMeta;
const csp = getColorSmoothingProps(props.smoothColors, theme.color.preferSmoothing, resolution);
if (csp) {
applyMeshColorSmoothing(values, csp.resolution, csp.stride, webgl, colorTexture);
applyMeshColorSmoothing(values, csp, webgl, colorTexture);
(geometry.meta.colorTexture as GaussianSurfaceMeta['colorTexture']) = values.tColorGrid.ref.value;
}
},
@@ -165,20 +166,20 @@ export function GaussianSurfaceMeshVisual(materialId: number): UnitsVisual<Gauss
//
async function createStructureGaussianSurfaceMesh(ctx: VisualContext, structure: Structure, theme: Theme, props: GaussianDensityProps, mesh?: Mesh): Promise<Mesh> {
const { smoothness } = props;
const { smoothness, floodfill, includeParent, radiusOffset } = props;
const { transform, field, idField, radiusFactor, resolution, maxRadius } = await computeStructureGaussianDensity(structure, theme.size, props).runInContext(ctx.runtime);
const isoLevel = Math.exp(-smoothness) / radiusFactor;
const params = {
isoLevel,
scalarField: props.floodfill !== 'off' ? Tensor.createFloodfilled(field, isoLevel, props.floodfill) : field,
scalarField: floodfill !== 'off' ? Tensor.createFloodfilled(field, isoLevel, floodfill) : field,
idField
};
const surface = await computeMarchingCubesMesh(params, mesh).runAsChild(ctx.runtime);
(surface.meta.resolution as GaussianSurfaceMeta['resolution']) = resolution;
if (props.includeParent) {
const iterations = Math.ceil(2 / props.resolution);
if (includeParent) {
const iterations = Math.ceil(2 / resolution);
Mesh.smoothEdges(surface, { iterations, maxNewEdgeLength: Math.sqrt(2) });
}
@@ -190,7 +191,8 @@ async function createStructureGaussianSurfaceMesh(ctx: VisualContext, structure:
ValueCell.updateIfChanged(surface.varyingGroup, true);
}
const sphere = Sphere3D.expand(Sphere3D(), structure.boundary.sphere, maxRadius);
const extraRadius = radiusOffset * (1 + Math.exp(-smoothness));
const sphere = Sphere3D.expand(Sphere3D(), structure.boundary.sphere, maxRadius + extraRadius);
surface.setBoundingSphere(sphere);
return surface;
@@ -229,7 +231,7 @@ export function StructureGaussianSurfaceMeshVisual(materialId: number): ComplexV
const { resolution, colorTexture } = geometry.meta as GaussianSurfaceMeta;
const csp = getColorSmoothingProps(props.smoothColors, theme.color.preferSmoothing, resolution);
if (csp) {
applyMeshColorSmoothing(values, csp.resolution, csp.stride, webgl, colorTexture);
applyMeshColorSmoothing(values, csp, webgl, colorTexture);
(geometry.meta.colorTexture as GaussianSurfaceMeta['colorTexture']) = values.tColorGrid.ref.value;
}
},
@@ -268,7 +270,8 @@ function createGaussianSurfaceTextureMesh(ctx: VisualContext, unit: Unit, struct
const gv = extractIsosurface(webgl, densityTextureData.texture, densityTextureData.gridDim, densityTextureData.gridTexDim, densityTextureData.gridDataDim, densityTextureData.gridTexScale, densityTextureData.transform, isoLevel, false, true, axisOrder, true, buffer?.vertex, buffer?.group, buffer?.normal);
if (isTimingMode) webgl.timer.markEnd('createGaussianSurfaceTextureMesh');
const boundingSphere = Sphere3D.expand(Sphere3D(), unit.boundary.sphere, densityTextureData.maxRadius);
const extraRadius = props.radiusOffset * (1 + Math.exp(-props.smoothness));
const boundingSphere = Sphere3D.expand(Sphere3D(), unit.boundary.sphere, densityTextureData.maxRadius + extraRadius);
const surface = TextureMesh.create(gv.vertexCount, groupCount, gv.vertexTexture, gv.groupTexture, gv.normalTexture, boundingSphere, textureMesh);
(surface.meta as GaussianSurfaceMeta).resolution = densityTextureData.resolution;
return surface;
@@ -314,7 +317,7 @@ export function GaussianSurfaceTextureMeshVisual(materialId: number): UnitsVisua
const { resolution, colorTexture } = geometry.meta as GaussianSurfaceMeta;
const csp = getColorSmoothingProps(props.smoothColors, theme.color.preferSmoothing, resolution);
if (csp && webgl) {
applyTextureMeshColorSmoothing(values, csp.resolution, csp.stride, webgl, colorTexture);
applyTextureMeshColorSmoothing(values, csp, webgl, colorTexture);
(geometry.meta as GaussianSurfaceMeta).colorTexture = values.tColorGrid.ref.value;
}
},
@@ -356,7 +359,8 @@ function createStructureGaussianSurfaceTextureMesh(ctx: VisualContext, structure
const gv = extractIsosurface(webgl, densityTextureData.texture, densityTextureData.gridDim, densityTextureData.gridTexDim, densityTextureData.gridDataDim, densityTextureData.gridTexScale, densityTextureData.transform, isoLevel, false, true, axisOrder, true, buffer?.vertex, buffer?.group, buffer?.normal);
if (isTimingMode) webgl.timer.markEnd('createStructureGaussianSurfaceTextureMesh');
const boundingSphere = Sphere3D.expand(Sphere3D(), structure.boundary.sphere, densityTextureData.maxRadius);
const extraRadius = props.radiusOffset * (1 + Math.exp(-props.smoothness));
const boundingSphere = Sphere3D.expand(Sphere3D(), structure.boundary.sphere, densityTextureData.maxRadius + extraRadius);
const surface = TextureMesh.create(gv.vertexCount, groupCount, gv.vertexTexture, gv.groupTexture, gv.normalTexture, boundingSphere, textureMesh);
(surface.meta as GaussianSurfaceMeta).resolution = densityTextureData.resolution;
return surface;
@@ -402,7 +406,7 @@ export function StructureGaussianSurfaceTextureMeshVisual(materialId: number): C
const { resolution, colorTexture } = geometry.meta as GaussianSurfaceMeta;
const csp = getColorSmoothingProps(props.smoothColors, theme.color.preferSmoothing, resolution);
if (csp && webgl) {
applyTextureMeshColorSmoothing(values, csp.resolution, csp.stride, webgl, colorTexture);
applyTextureMeshColorSmoothing(values, csp, webgl, colorTexture);
(geometry.meta as GaussianSurfaceMeta).colorTexture = values.tColorGrid.ref.value;
}
},

View File

@@ -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>
*/
@@ -101,7 +101,7 @@ export function MolecularSurfaceMeshVisual(materialId: number): UnitsVisual<Mole
const { resolution, colorTexture } = geometry.meta as MolecularSurfaceMeta;
const csp = getColorSmoothingProps(props.smoothColors, theme.color.preferSmoothing, resolution);
if (csp) {
applyMeshColorSmoothing(values, csp.resolution, csp.stride, webgl, colorTexture);
applyMeshColorSmoothing(values, csp, webgl, colorTexture);
(geometry.meta as MolecularSurfaceMeta).colorTexture = values.tColorGrid.ref.value;
}
},
@@ -173,7 +173,7 @@ export function StructureMolecularSurfaceMeshVisual(materialId: number): Complex
const { resolution, colorTexture } = geometry.meta as MolecularSurfaceMeta;
const csp = getColorSmoothingProps(props.smoothColors, theme.color.preferSmoothing, resolution);
if (csp) {
applyMeshColorSmoothing(values, csp.resolution, csp.stride, webgl, colorTexture);
applyMeshColorSmoothing(values, csp, webgl, colorTexture);
(geometry.meta as MolecularSurfaceMeta).colorTexture = values.tColorGrid.ref.value;
}
},

View File

@@ -1,5 +1,5 @@
/**
* Copyright (c) 2018-2024 mol* contributors, licensed under MIT, See LICENSE file for more info.
* Copyright (c) 2018-2026 mol* contributors, licensed under MIT, See LICENSE file for more info.
*
* @author Alexander Rose <alexander.rose@weirdbyte.de>
*/
@@ -204,14 +204,14 @@ namespace Visual {
const { resolution, overpaintTexture } = geometry.meta as SurfaceMeta;
const csp = getColorSmoothingProps(props.smoothColors, true, resolution);
if (csp) {
applyMeshOverpaintSmoothing(renderObject.values as any, csp.resolution, csp.stride, webgl, overpaintTexture);
applyMeshOverpaintSmoothing(renderObject.values as any, csp, webgl, overpaintTexture);
(geometry.meta as SurfaceMeta).overpaintTexture = renderObject.values.tOverpaintGrid.ref.value;
}
} else if (webgl && geometry.kind === 'texture-mesh') {
const { resolution, overpaintTexture } = geometry.meta as SurfaceMeta;
const csp = getColorSmoothingProps(props.smoothColors, true, resolution);
if (csp) {
applyTextureMeshOverpaintSmoothing(renderObject.values as any, csp.resolution, csp.stride, webgl, overpaintTexture);
applyTextureMeshOverpaintSmoothing(renderObject.values as any, csp, webgl, overpaintTexture);
(geometry.meta as SurfaceMeta).overpaintTexture = renderObject.values.tOverpaintGrid.ref.value;
}
}
@@ -258,14 +258,14 @@ namespace Visual {
const { resolution, transparencyTexture } = geometry.meta as SurfaceMeta;
const csp = getColorSmoothingProps(props.smoothColors, true, resolution);
if (csp) {
applyMeshTransparencySmoothing(renderObject.values as any, csp.resolution, csp.stride, webgl, transparencyTexture);
applyMeshTransparencySmoothing(renderObject.values as any, csp, webgl, transparencyTexture);
(geometry.meta as SurfaceMeta).transparencyTexture = renderObject.values.tTransparencyGrid.ref.value;
}
} else if (webgl && geometry.kind === 'texture-mesh') {
const { resolution, transparencyTexture } = geometry.meta as SurfaceMeta;
const csp = getColorSmoothingProps(props.smoothColors, true, resolution);
if (csp) {
applyTextureMeshTransparencySmoothing(renderObject.values as any, csp.resolution, csp.stride, webgl, transparencyTexture);
applyTextureMeshTransparencySmoothing(renderObject.values as any, csp, webgl, transparencyTexture);
(geometry.meta as SurfaceMeta).transparencyTexture = renderObject.values.tTransparencyGrid.ref.value;
}
}
@@ -311,14 +311,14 @@ namespace Visual {
const { resolution, emissiveTexture } = geometry.meta as SurfaceMeta;
const csp = getColorSmoothingProps(props.smoothColors, true, resolution);
if (csp) {
applyMeshEmissiveSmoothing(renderObject.values as any, csp.resolution, csp.stride, webgl, emissiveTexture);
applyMeshEmissiveSmoothing(renderObject.values as any, csp, webgl, emissiveTexture);
(geometry.meta as SurfaceMeta).emissiveTexture = renderObject.values.tEmissiveGrid.ref.value;
}
} else if (webgl && geometry.kind === 'texture-mesh') {
const { resolution, emissiveTexture } = geometry.meta as SurfaceMeta;
const csp = getColorSmoothingProps(props.smoothColors, true, resolution);
if (csp) {
applyTextureMeshEmissiveSmoothing(renderObject.values as any, csp.resolution, csp.stride, webgl, emissiveTexture);
applyTextureMeshEmissiveSmoothing(renderObject.values as any, csp, webgl, emissiveTexture);
(geometry.meta as SurfaceMeta).emissiveTexture = renderObject.values.tEmissiveGrid.ref.value;
}
}
@@ -365,14 +365,14 @@ namespace Visual {
const { resolution, substanceTexture } = geometry.meta as SurfaceMeta;
const csp = getColorSmoothingProps(props.smoothColors, true, resolution);
if (csp) {
applyMeshSubstanceSmoothing(renderObject.values as any, csp.resolution, csp.stride, webgl, substanceTexture);
applyMeshSubstanceSmoothing(renderObject.values as any, csp, webgl, substanceTexture);
(geometry.meta as SurfaceMeta).substanceTexture = renderObject.values.tSubstanceGrid.ref.value;
}
} else if (webgl && geometry.kind === 'texture-mesh') {
const { resolution, substanceTexture } = geometry.meta as SurfaceMeta;
const csp = getColorSmoothingProps(props.smoothColors, true, resolution);
if (csp) {
applyTextureMeshSubstanceSmoothing(renderObject.values as any, csp.resolution, csp.stride, webgl, substanceTexture);
applyTextureMeshSubstanceSmoothing(renderObject.values as any, csp, webgl, substanceTexture);
(geometry.meta as SurfaceMeta).substanceTexture = renderObject.values.tSubstanceGrid.ref.value;
}
}