Ver Fonte

Merge branch 'master' into lookup3d

giagitom há 2 anos atrás
pai
commit
813c4f845a

+ 0 - 1
.vscode/extensions.json

@@ -6,7 +6,6 @@
 	"recommendations": [
 		"dbaeumer.vscode-eslint",
 		"firsttris.vscode-jest-runner",
-		"msjsdiag.debugger-for-chrome",
 		"slevesque.shader",
 		"stpn.vscode-graphql",
 		"wayou.vscode-todo-highlight"

+ 10 - 0
CHANGELOG.md

@@ -6,6 +6,16 @@ Note that since we don't clearly distinguish between a public and private interf
 
 ## [Unreleased]
 
+- Add mipmap-based blur for skybox backgrounds
+
+## [v3.19.0] - 2022-10-01
+
+- Fix "empty textures" error on empty canvas
+- Optimize BinaryCIF integer packing encoder
+- Fix dual depth peeling when post-processing is off or when rendering direct-volumes
+- Add ``cameraClipping.minNear`` parameter
+- Fix black artifacts on specular highlights with transparent background
+
 ## [v3.18.0] - 2022-09-17
 
 - Integration of Dual depth peeling - OIT method

Diff do ficheiro suprimidas por serem muito extensas
+ 267 - 270
package-lock.json


+ 15 - 15
package.json

@@ -1,6 +1,6 @@
 {
   "name": "molstar",
-  "version": "3.18.0",
+  "version": "3.19.0",
   "description": "A comprehensive macromolecular library.",
   "homepage": "https://github.com/molstar/molstar#readme",
   "repository": {
@@ -97,43 +97,43 @@
   "license": "MIT",
   "devDependencies": {
     "@graphql-codegen/add": "^3.2.1",
-    "@graphql-codegen/cli": "^2.12.0",
+    "@graphql-codegen/cli": "^2.13.1",
     "@graphql-codegen/time": "^3.2.1",
     "@graphql-codegen/typescript": "^2.7.3",
     "@graphql-codegen/typescript-graphql-files-modules": "^2.2.1",
-    "@graphql-codegen/typescript-graphql-request": "^4.5.4",
+    "@graphql-codegen/typescript-graphql-request": "^4.5.5",
     "@graphql-codegen/typescript-operations": "^2.5.3",
     "@types/cors": "^2.8.12",
     "@types/gl": "^4.1.1",
-    "@types/jest": "^29.0.3",
-    "@types/react": "^18.0.20",
+    "@types/jest": "^29.1.1",
+    "@types/react": "^18.0.21",
     "@types/react-dom": "^18.0.6",
-    "@typescript-eslint/eslint-plugin": "^5.37.0",
-    "@typescript-eslint/parser": "^5.37.0",
+    "@typescript-eslint/eslint-plugin": "^5.38.1",
+    "@typescript-eslint/parser": "^5.38.1",
     "benchmark": "^2.1.4",
     "concurrently": "^7.4.0",
     "cpx2": "^4.2.0",
     "crypto-browserify": "^3.12.0",
     "css-loader": "^6.7.1",
-    "eslint": "^8.23.1",
+    "eslint": "^8.24.0",
     "extra-watch-webpack-plugin": "^1.0.3",
     "file-loader": "^6.2.0",
     "fs-extra": "^10.1.0",
     "graphql": "^16.6.0",
     "http-server": "^14.1.1",
-    "jest": "^29.0.3",
+    "jest": "^29.1.2",
     "mini-css-extract-plugin": "^2.6.1",
     "path-browserify": "^1.0.1",
     "raw-loader": "^4.0.2",
     "react": "^18.2.0",
     "react-dom": "^18.2.0",
-    "sass": "^1.54.9",
+    "sass": "^1.55.0",
     "sass-loader": "^13.0.2",
     "simple-git": "^3.14.1",
     "stream-browserify": "^3.0.0",
     "style-loader": "^3.3.1",
-    "ts-jest": "^29.0.1",
-    "typescript": "^4.8.3",
+    "ts-jest": "^29.0.3",
+    "typescript": "^4.8.4",
     "webpack": "^5.74.0",
     "webpack-cli": "^4.10.0"
   },
@@ -142,7 +142,7 @@
     "@types/benchmark": "^2.1.2",
     "@types/compression": "1.7.2",
     "@types/express": "^4.17.14",
-    "@types/node": "^16.11.59",
+    "@types/node": "^16.11.62",
     "@types/node-fetch": "^2.6.2",
     "@types/swagger-ui-dist": "3.30.1",
     "argparse": "^2.0.1",
@@ -154,8 +154,8 @@
     "immer": "^9.0.15",
     "immutable": "^4.1.0",
     "node-fetch": "^2.6.7",
-    "rxjs": "^7.5.6",
-    "swagger-ui-dist": "^4.14.0",
+    "rxjs": "^7.5.7",
+    "swagger-ui-dist": "^4.14.2",
     "tslib": "^2.4.0",
     "util.promisify": "^1.1.1",
     "xhr2": "^0.2.1"

+ 1 - 0
src/extensions/backgrounds/index.ts

@@ -72,6 +72,7 @@ export const Backgrounds = PluginBehavior.create<{ }>({
                             lightness: 0,
                             saturation: 0,
                             opacity: 1,
+                            blur: 0.3,
                         }
                     }
                 }, 'Purple Nebula Skybox'],

+ 11 - 7
src/mol-canvas3d/camera.ts

@@ -1,5 +1,5 @@
 /**
- * Copyright (c) 2018-2021 mol* contributors, licensed under MIT, See LICENSE file for more info.
+ * Copyright (c) 2018-2022 mol* contributors, licensed under MIT, See LICENSE file for more info.
  *
  * @author David Sehnal <david.sehnal@gmail.com>
  * @author Alexander Rose <alexander.rose@weirdbyte.de>
@@ -260,7 +260,8 @@ namespace Camera {
             radius: 0,
             radiusMax: 10,
             fog: 50,
-            clipFar: true
+            clipFar: true,
+            minNear: 5,
         };
     }
 
@@ -276,6 +277,7 @@ namespace Camera {
         radiusMax: number
         fog: number
         clipFar: boolean
+        minNear: number
     }
 
     export function copySnapshot(out: Snapshot, source?: Partial<Snapshot>) {
@@ -292,6 +294,7 @@ namespace Camera {
         if (typeof source.radiusMax !== 'undefined') out.radiusMax = source.radiusMax;
         if (typeof source.fog !== 'undefined') out.fog = source.fog;
         if (typeof source.clipFar !== 'undefined') out.clipFar = source.clipFar;
+        if (typeof source.minNear !== 'undefined') out.minNear = source.minNear;
 
         return out;
     }
@@ -303,6 +306,7 @@ namespace Camera {
             && a.radiusMax === b.radiusMax
             && a.fog === b.fog
             && a.clipFar === b.clipFar
+            && a.minNear === b.minNear
             && Vec3.exactEquals(a.position, b.position)
             && Vec3.exactEquals(a.up, b.up)
             && Vec3.exactEquals(a.target, b.target);
@@ -370,7 +374,7 @@ function updatePers(camera: Camera) {
 }
 
 function updateClip(camera: Camera) {
-    let { radius, radiusMax, mode, fog, clipFar } = camera.state;
+    let { radius, radiusMax, mode, fog, clipFar, minNear } = camera.state;
     if (radius < 0.01) radius = 0.01;
 
     const normalizedFar = clipFar ? radius : radiusMax;
@@ -384,12 +388,12 @@ function updateClip(camera: Camera) {
 
     if (mode === 'perspective') {
         // set at least to 5 to avoid slow sphere impostor rendering
-        near = Math.max(Math.min(radiusMax, 5), near);
-        far = Math.max(5, far);
+        near = Math.max(Math.min(radiusMax, minNear), near);
+        far = Math.max(minNear, far);
     } else {
         // not too close to 0 as it causes issues with outline rendering
-        near = Math.max(Math.min(radiusMax, 5), near);
-        far = Math.max(5, far);
+        near = Math.max(Math.min(radiusMax, minNear), near);
+        far = Math.max(minNear, far);
     }
 
     if (near === far) {

+ 6 - 1
src/mol-canvas3d/canvas3d.ts

@@ -65,6 +65,7 @@ export const Canvas3DParams = {
     cameraClipping: PD.Group({
         radius: PD.Numeric(100, { min: 0, max: 99, step: 1 }, { label: 'Clipping', description: 'How much of the scene to show.' }),
         far: PD.Boolean(true, { description: 'Hide scene in the distance' }),
+        minNear: PD.Numeric(5, { min: 0.1, max: 10, step: 0.1 }, { description: 'Note, may cause performance issues rendering impostors when set too small and cause issues with outline rendering when too close to 0.' }),
     }, { pivot: 'radius' }),
     viewport: PD.MappedStatic('canvas', {
         canvas: PD.Group({}),
@@ -322,6 +323,7 @@ namespace Canvas3D {
             mode: p.camera.mode,
             fog: p.cameraFog.name === 'on' ? p.cameraFog.params.intensity : 0,
             clipFar: p.cameraClipping.far,
+            minNear: p.cameraClipping.minNear,
             fov: degToRad(p.camera.fov),
         }, { x, y, width, height }, { pixelScale: attribs.pixelScale });
         const stereoCamera = new StereoCamera(camera, p.camera.stereo.params);
@@ -687,7 +689,7 @@ namespace Canvas3D {
                 cameraFog: camera.state.fog > 0
                     ? { name: 'on' as const, params: { intensity: camera.state.fog } }
                     : { name: 'off' as const, params: {} },
-                cameraClipping: { far: camera.state.clipFar, radius },
+                cameraClipping: { far: camera.state.clipFar, radius, minNear: camera.state.minNear },
                 cameraResetDurationMs: p.cameraResetDurationMs,
                 sceneRadiusFactor: p.sceneRadiusFactor,
                 transparentBackground: p.transparentBackground,
@@ -814,6 +816,9 @@ namespace Canvas3D {
                     if (props.cameraClipping.far !== undefined && props.cameraClipping.far !== camera.state.clipFar) {
                         cameraState.clipFar = props.cameraClipping.far;
                     }
+                    if (props.cameraClipping.minNear !== undefined && props.cameraClipping.minNear !== camera.state.minNear) {
+                        cameraState.minNear = props.cameraClipping.minNear;
+                    }
                     if (props.cameraClipping.radius !== undefined) {
                         const radius = (getSceneRadius() / 100) * (100 - props.cameraClipping.radius);
                         if (radius > 0 && radius !== cameraState.radius) {

+ 8 - 2
src/mol-canvas3d/passes/background.ts

@@ -49,6 +49,7 @@ const SkyboxParams = {
             pz: PD.File({ label: 'Positive Z / Front', accept: 'image/*' }),
         }, { isExpanded: true, label: 'Files' }),
     }),
+    blur: PD.Numeric(0, { min: 0.0, max: 1.0, step: 0.01 }, { description: 'Note, this only works in WebGL2 or when "EXT_shader_texture_lod" is available.' }),
     ...SharedParams,
 };
 type SkyboxProps = PD.Values<typeof SkyboxParams>
@@ -170,6 +171,7 @@ export class BackgroundPass {
         Mat4.invert(m, m);
         ValueCell.update(this.renderable.values.uViewDirectionProjectionInverse, m);
 
+        ValueCell.updateIfChanged(this.renderable.values.uBlur, props.blur);
         ValueCell.updateIfChanged(this.renderable.values.uOpacity, props.opacity);
         ValueCell.updateIfChanged(this.renderable.values.uSaturation, props.saturation);
         ValueCell.updateIfChanged(this.renderable.values.uLightness, props.lightness);
@@ -367,7 +369,7 @@ function getSkyboxTexture(ctx: WebGLContext, assetManager: AssetManager, faces:
     const cubeAssets = getCubeAssets(assetManager, faces);
     const cubeFaces = getCubeFaces(assetManager, cubeAssets);
     const assets = [cubeAssets.nx, cubeAssets.ny, cubeAssets.nz, cubeAssets.px, cubeAssets.py, cubeAssets.pz];
-    const texture = ctx.resources.cubeTexture(cubeFaces, false, onload);
+    const texture = ctx.resources.cubeTexture(cubeFaces, true, onload);
     return { texture, assets };
 }
 
@@ -424,12 +426,15 @@ const BackgroundSchema = {
     uGradientColorA: UniformSpec('v3'),
     uGradientColorB: UniformSpec('v3'),
     uGradientRatio: UniformSpec('f'),
+    uBlur: UniformSpec('f'),
     uOpacity: UniformSpec('f'),
     uSaturation: UniformSpec('f'),
     uLightness: UniformSpec('f'),
     dVariant: DefineSpec('string', ['skybox', 'image', 'verticalGradient', 'horizontalGradient', 'radialGradient']),
 };
-const SkyboxShaderCode = ShaderCode('background', background_vert, background_frag);
+const SkyboxShaderCode = ShaderCode('background', background_vert, background_frag, {
+    shaderTextureLod: 'optional'
+});
 type BackgroundRenderable = ComputeRenderable<Values<typeof BackgroundSchema>>
 
 function getBackgroundRenderable(ctx: WebGLContext, width: number, height: number): BackgroundRenderable {
@@ -448,6 +453,7 @@ function getBackgroundRenderable(ctx: WebGLContext, width: number, height: numbe
         uGradientColorA: ValueCell.create(Vec3()),
         uGradientColorB: ValueCell.create(Vec3()),
         uGradientRatio: ValueCell.create(0.5),
+        uBlur: ValueCell.create(0),
         uOpacity: ValueCell.create(1),
         uSaturation: ValueCell.create(0),
         uLightness: ValueCell.create(0),

+ 2 - 0
src/mol-canvas3d/passes/draw.ts

@@ -153,6 +153,8 @@ export class DrawPass {
             this.postprocessing.render(camera, false, transparentBackground, renderer.props.backgroundColor, postprocessingProps);
         }
 
+        this.depthTextureOpaque.detachFramebuffer(this.colorTarget.framebuffer, 'depth');
+
         // render transparent primitives
         if (scene.opacityAverage < 1) {
             const target = PostprocessingPass.isEnabled(postprocessingProps)

+ 4 - 1
src/mol-canvas3d/passes/passes.ts

@@ -24,7 +24,10 @@ export class Passes {
 
     updateSize() {
         const { gl } = this.webgl;
-        this.draw.setSize(gl.drawingBufferWidth, gl.drawingBufferHeight);
+        // Avoid setting dimensions to 0x0 because it causes "empty textures are not allowed" error.
+        const width = Math.max(gl.drawingBufferWidth, 2);
+        const height = Math.max(gl.drawingBufferHeight, 2);
+        this.draw.setSize(width, height);
         this.pick.syncSize();
         this.multiSample.syncSize();
     }

+ 5 - 4
src/mol-canvas3d/passes/smaa.ts

@@ -1,5 +1,5 @@
 /**
- * Copyright (c) 2020 mol* contributors, licensed under MIT, See LICENSE file for more info.
+ * Copyright (c) 2020-2022 mol* contributors, licensed under MIT, See LICENSE file for more info.
  *
  * @author Alexander Rose <alexander.rose@weirdbyte.de>
  */
@@ -11,7 +11,7 @@ import { ShaderCode } from '../../mol-gl/shader-code';
 import { WebGLContext } from '../../mol-gl/webgl/context';
 import { createComputeRenderItem } from '../../mol-gl/webgl/render-item';
 import { RenderTarget } from '../../mol-gl/webgl/render-target';
-import { createTexture, loadImageTexture, Texture } from '../../mol-gl/webgl/texture';
+import { loadImageTexture, Texture } from '../../mol-gl/webgl/texture';
 import { Vec2, Vec4 } from '../../mol-math/linear-algebra';
 import { ValueCell } from '../../mol-util';
 import { ParamDefinition as PD } from '../../mol-util/param-definition';
@@ -74,6 +74,7 @@ export class SmaaPass {
         state.viewport(x, y, width, height);
         state.scissor(x, y, width, height);
 
+        state.colorMask(true, true, true, true);
         state.clearColor(0, 0, 0, 1);
         gl.clear(gl.COLOR_BUFFER_BIT);
 
@@ -191,8 +192,8 @@ function getWeightsRenderable(ctx: WebGLContext, edgesTexture: Texture): Weights
     const width = edgesTexture.getWidth();
     const height = edgesTexture.getHeight();
 
-    const areaTexture = createTexture(ctx.gl, ctx.extensions, 'image-uint8', 'rgb', 'ubyte', 'linear');
-    const searchTexture = createTexture(ctx.gl, ctx.extensions, 'image-uint8', 'rgba', 'ubyte', 'nearest');
+    const areaTexture = ctx.resources.texture('image-uint8', 'rgb', 'ubyte', 'linear');
+    const searchTexture = ctx.resources.texture('image-uint8', 'rgba', 'ubyte', 'nearest');
 
     const values: Values<typeof WeightsSchema> = {
         ...QuadValues,

+ 2 - 2
src/mol-geo/geometry/text/font-atlas.ts

@@ -1,5 +1,5 @@
 /**
- * Copyright (c) 2019 mol* contributors, licensed under MIT, See LICENSE file for more info.
+ * Copyright (c) 2019-2022 mol* contributors, licensed under MIT, See LICENSE file for more info.
  *
  * @author Alexander Rose <alexander.rose@weirdbyte.de>
  */
@@ -88,7 +88,7 @@ export class FontAtlas {
         this.scratchCanvas.width = this.maxWidth;
         this.scratchCanvas.height = this.lineHeight;
 
-        this.scratchContext = this.scratchCanvas.getContext('2d')!;
+        this.scratchContext = this.scratchCanvas.getContext('2d', { willReadFrequently: true })!;
         this.scratchContext.font = `${p.fontStyle} ${p.fontVariant} ${p.fontWeight} ${fontSize}px ${p.fontFamily}`;
         this.scratchContext.fillStyle = 'black';
         this.scratchContext.textBaseline = 'middle';

+ 2 - 0
src/mol-geo/geometry/texture-mesh/color-smoothing.ts

@@ -387,6 +387,8 @@ export function calcTextureMeshColorSmoothing(input: ColorSmoothingInput, resolu
     const type = isInstanceType ? 'volumeInstance' : 'volume';
     if (isTimingMode) webgl.timer.markEnd('calcTextureMeshColorSmoothing');
 
+    // printTextureImage(readTexture(webgl, texture), { scale: 0.75 });
+
     return { texture, gridDim, gridTexDim: Vec2.create(width, height), gridTransform, type };
 }
 

+ 1 - 1
src/mol-gl/compute/histogram-pyramid/reduction.ts

@@ -197,7 +197,7 @@ export function createHistogramPyramid(ctx: WebGLContext, inputTexture: Texture,
     gl.finish();
     if (isTimingMode) ctx.timer.markEnd('createHistogramPyramid');
 
-    // printTexture(ctx, pyramidTex, 2)
+    // printTextureImage(readTexture(ctx, pyramidTex), { scale: 0.75 });
 
     //
 

+ 1 - 0
src/mol-gl/compute/marching-cubes/active-voxels.ts

@@ -115,6 +115,7 @@ export function calcActiveVoxels(ctx: WebGLContext, volumeData: Texture, gridDim
     // console.log('gridScale', gridScale, 'gridTexDim', gridTexDim, 'gridDim', gridDim);
     // console.log('volumeData', volumeData);
     // console.log('at', readTexture(ctx, activeVoxelsTex));
+    // printTextureImage(readTexture(ctx, activeVoxelsTex), { scale: 0.75 });
 
     gl.finish();
     if (isTimingMode) ctx.timer.markEnd('calcActiveVoxels');

+ 4 - 0
src/mol-gl/compute/marching-cubes/isosurface.ts

@@ -199,6 +199,10 @@ export function createIsosurfaceBuffers(ctx: WebGLContext, activeVoxelsBase: Tex
     gl.finish();
     if (isTimingMode) ctx.timer.markEnd('createIsosurfaceBuffers');
 
+    // printTextureImage(readTexture(ctx, vertexTexture, new Float32Array(width * height * 4)), { scale: 0.75 });
+    // printTextureImage(readTexture(ctx, groupTexture, new Uint8Array(width * height * 4)), { scale: 0.75 });
+    // printTextureImage(readTexture(ctx, normalTexture, new Float32Array(width * height * 4)), { scale: 0.75 });
+
     return { vertexTexture, groupTexture, normalTexture, vertexCount: count };
 }
 

+ 3 - 3
src/mol-gl/compute/util.ts

@@ -75,9 +75,9 @@ export function getSharedCopyRenderable(ctx: WebGLContext, texture: Texture) {
 const ReadTextureName = 'read-texture';
 const ReadAlphaTextureName = 'read-alpha-texture';
 
-export function readTexture(ctx: WebGLContext, texture: Texture) {
+export function readTexture<T extends Uint8Array | Float32Array | Int32Array = Uint8Array>(ctx: WebGLContext, texture: Texture, array?: T) {
     const { gl, resources } = ctx;
-    if (texture.type !== gl.UNSIGNED_BYTE) throw new Error('unsupported texture type');
+    if (!array && texture.type !== gl.UNSIGNED_BYTE) throw new Error('unsupported texture type');
 
     if (!ctx.namedFramebuffers[ReadTextureName]) {
         ctx.namedFramebuffers[ReadTextureName] = resources.framebuffer();
@@ -86,7 +86,7 @@ export function readTexture(ctx: WebGLContext, texture: Texture) {
 
     const width = texture.getWidth();
     const height = texture.getHeight();
-    const array = new Uint8Array(width * height * 4);
+    if (!array) array = new Uint8Array(width * height * 4) as T;
     framebuffer.bind();
     texture.attachFramebuffer(framebuffer, 0);
     ctx.readPixels(0, 0, width, height, array);

+ 15 - 3
src/mol-gl/renderable/util.ts

@@ -1,5 +1,5 @@
 /**
- * Copyright (c) 2018-2020 mol* contributors, licensed under MIT, See LICENSE file for more info.
+ * Copyright (c) 2018-2022 mol* contributors, licensed under MIT, See LICENSE file for more info.
  *
  * @author Alexander Rose <alexander.rose@weirdbyte.de>
  */
@@ -8,6 +8,7 @@ import { Sphere3D } from '../../mol-math/geometry';
 import { Vec3, Mat4 } from '../../mol-math/linear-algebra';
 import { BoundaryHelper } from '../../mol-math/geometry/boundary-helper';
 import { TextureFilter } from '../webgl/texture';
+import { arrayMinMax } from '../../mol-util/array';
 
 export function calculateTextureInfo(n: number, itemSize: number) {
     n = Math.max(n, 2); // observed issues with 1 pixel textures
@@ -42,7 +43,8 @@ export function createTextureImage<T extends Uint8Array | Float32Array>(n: numbe
 const DefaultPrintImageOptions = {
     scale: 1,
     pixelated: false,
-    id: 'molstar.debug.image'
+    id: 'molstar.debug.image',
+    normalize: false,
 };
 export type PrintImageOptions = typeof DefaultPrintImageOptions
 
@@ -58,7 +60,17 @@ export function printTextureImage(textureImage: TextureImage<any>, options: Part
             }
         }
     } else if (itemSize === 4) {
-        data.set(array);
+        if (options.normalize) {
+            const [min, max] = arrayMinMax(array);
+            for (let i = 0, il = width * height * 4; i < il; i += 4) {
+                data[i] = ((array[i] - min) / (max - min)) * 255;
+                data[i + 1] = ((array[i + 1] - min) / (max - min)) * 255;
+                data[i + 2] = ((array[i + 2] - min) / (max - min)) * 255;
+                data[i + 3] = 255;
+            }
+        } else {
+            data.set(array);
+        }
     } else {
         console.warn(`itemSize '${itemSize}' not supported`);
     }

+ 6 - 1
src/mol-gl/shader/background.frag.ts

@@ -6,6 +6,7 @@ precision mediump sampler2D;
 #if defined(dVariant_skybox)
     uniform samplerCube tSkybox;
     uniform mat4 uViewDirectionProjectionInverse;
+    uniform float uBlur;
     uniform float uOpacity;
     uniform float uSaturation;
     uniform float uLightness;
@@ -49,7 +50,11 @@ vec3 lightenColor(vec3 c, float amount) {
 void main() {
     #if defined(dVariant_skybox)
         vec4 t = uViewDirectionProjectionInverse * vPosition;
-        gl_FragColor = textureCube(tSkybox, normalize(t.xyz / t.w));
+        #ifdef enabledShaderTextureLod
+            gl_FragColor = textureCubeLodEXT(tSkybox, normalize(t.xyz / t.w), uBlur * 8.0);
+        #else
+            gl_FragColor = textureCube(tSkybox, normalize(t.xyz / t.w));
+        #endif
         gl_FragColor.a = uOpacity;
         gl_FragColor.rgb = lightenColor(saturateColor(gl_FragColor.rgb, uSaturation), uLightness);
     #elif defined(dVariant_image)

+ 1 - 0
src/mol-gl/shader/chunks/apply-light-color.glsl.ts

@@ -57,6 +57,7 @@ export const apply_light_color = `
     RE_IndirectSpecular_Physical(radiance, iblIrradiance, clearcoatRadiance, geometry, physicalMaterial, reflectedLight);
 
     vec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + reflectedLight.directSpecular + reflectedLight.indirectSpecular;
+    outgoingLight = clamp(outgoingLight, 0.0, 1.0); // prevents black artifacts on specular highlight with transparent background
 
     gl_FragColor = vec4(outgoingLight, color.a);
 #endif

+ 1 - 1
src/mol-gl/shader/chunks/dpoit-write.glsl.ts

@@ -37,7 +37,7 @@ export const dpoit_write = `
             // back color is separately blend afterwards each pass
             gl_FragData[1] = vec4(0.0);
 
-            float nearestDepth = - lastDepth.x;
+            float nearestDepth = -lastDepth.x;
             float furthestDepth = lastDepth.y;
             float alphaMultiplier = 1.0 - lastFrontColor.a;
 

+ 17 - 10
src/mol-io/common/binary-cif/array-encoder.ts

@@ -264,28 +264,35 @@ export namespace ArrayEncoding {
         return false;
     }
 
-    function packingSize(data: Int32Array, upperLimit: number) {
+    function packingSizeUnsigned(data: Int32Array, upperLimit: number) {
+        let size = 0;
+        for (let i = 0, n = data.length; i < n; i++) {
+            size += (data[i] / upperLimit) | 0;
+        }
+        size += data.length;
+        return size;
+    }
+
+
+    function packingSizeSigned(data: Int32Array, upperLimit: number) {
         const lowerLimit = -upperLimit - 1;
         let size = 0;
         for (let i = 0, n = data.length; i < n; i++) {
             const value = data[i];
-            if (value === 0) {
-                size += 1;
-            } else if (value > 0) {
-                size += Math.ceil(value / upperLimit);
-                if (value % upperLimit === 0) size += 1;
+            if (value >= 0) {
+                size += (value / upperLimit) | 0;
             } else {
-                size += Math.ceil(value / lowerLimit);
-                if (value % lowerLimit === 0) size += 1;
+                size += (value / lowerLimit) | 0;
             }
         }
+        size += data.length;
         return size;
     }
 
     function determinePacking(data: Int32Array): { isSigned: boolean, size: number, bytesPerElement: number } {
         const signed = isSigned(data);
-        const size8 = signed ? packingSize(data, 0x7F) : packingSize(data, 0xFF);
-        const size16 = signed ? packingSize(data, 0x7FFF) : packingSize(data, 0xFFFF);
+        const size8 = signed ? packingSizeSigned(data, 0x7F) : packingSizeUnsigned(data, 0xFF);
+        const size16 = signed ? packingSizeSigned(data, 0x7FFF) : packingSizeUnsigned(data, 0xFFFF);
 
         if (data.length * 4 < size16 * 2) {
             // 4 byte packing is the most effective

+ 1 - 1
src/mol-math/geometry/gaussian-density/gpu.ts

@@ -204,7 +204,7 @@ function calcGaussianDensityTexture2d(webgl: WebGLContext, position: PositionDat
         render(texture, false);
     }
 
-    // printTexture(webgl, minDistTex, 0.75);
+    // printTextureImage(readTexture(webgl, minDistTex), { scale: 0.75 });
 
     return { texture, scale, bbox: expandedBox, gridDim: dim, gridTexDim, gridTexScale, radiusFactor, resolution, maxRadius };
 }

+ 1 - 0
src/mol-plugin-ui/viewport/simple-settings.tsx

@@ -135,6 +135,7 @@ const SimpleSettingsMapping = ParamMapping({
         canvas.cameraClipping = {
             radius: s.clipping.radius,
             far: s.clipping.far,
+            minNear: s.clipping.minNear,
         };
 
         props.layout = s.layout;

Alguns ficheiros não foram mostrados porque muitos ficheiros mudaram neste diff