Forráskód Böngészése

more precise sphere shader sizes

Alexander Rose 4 éve
szülő
commit
361dce2b96

+ 15 - 13
src/mol-geo/geometry/size-data.ts

@@ -1,5 +1,5 @@
 /**
- * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info.
+ * Copyright (c) 2018-2020 mol* contributors, licensed under MIT, See LICENSE file for more info.
  *
  * @author Alexander Rose <alexander.rose@weirdbyte.de>
  */
@@ -11,7 +11,7 @@ import { LocationIterator } from '../util/location-iterator';
 import { Location, NullLocation } from '../../mol-model/location';
 import { SizeTheme } from '../../mol-theme/size';
 import { Geometry } from './geometry';
-import { encodeFloatLog, decodeFloatLog } from '../../mol-util/float-packing';
+import { decodeFloatRGB, encodeFloatRGBtoArray } from '../../mol-util/float-packing';
 
 export type SizeType = 'uniform' | 'instance' | 'group' | 'groupInstance'
 
@@ -31,6 +31,8 @@ export function createSizes(locationIt: LocationIterator, sizeTheme: SizeTheme<a
     }
 }
 
+const sizeFactor = 100; // NOTE same factor is set in shaders
+
 export function getMaxSize(sizeData: SizeData): number {
     const type = sizeData.dSizeType.ref.value as SizeType;
     switch (type) {
@@ -41,17 +43,17 @@ export function getMaxSize(sizeData: SizeData): number {
         case 'groupInstance':
             let maxSize = 0;
             const array = sizeData.tSize.ref.value.array;
-            for (let i = 0, il = array.length; i < il; ++i) {
-                const value = decodeFloatLog(array[i] / 255);
+            for (let i = 0, il = array.length; i < il; i += 3) {
+                const value = decodeFloatRGB(array[i], array[i + 1], array[i + 2]);
                 if (maxSize < value) maxSize = value;
             }
-            return maxSize;
+            return maxSize / sizeFactor;
     }
 }
 
 export type LocationSize = (location: Location) => number
 
-const emptySizeTexture = { array: new Uint8Array(1), width: 1, height: 1 };
+const emptySizeTexture = { array: new Uint8Array(3), width: 1, height: 1 };
 function createEmptySizeTexture() {
     return {
         tSize: ValueCell.create(emptySizeTexture),
@@ -101,11 +103,11 @@ export function createTextureSize(sizes: TextureImage<Uint8Array>, type: SizeTyp
 /** Creates size texture with size for each instance/unit */
 export function createInstanceSize(locationIt: LocationIterator, sizeFn: LocationSize, sizeData?: SizeData): SizeData {
     const { instanceCount} = locationIt;
-    const sizes = createTextureImage(Math.max(1, instanceCount), 1, Uint8Array, sizeData && sizeData.tSize.ref.value.array);
+    const sizes = createTextureImage(Math.max(1, instanceCount), 3, Uint8Array, sizeData && sizeData.tSize.ref.value.array);
     locationIt.reset();
     while (locationIt.hasNext && !locationIt.isNextNewInstance) {
         const v = locationIt.move();
-        sizes.array[v.instanceIndex] = encodeFloatLog(sizeFn(v.location)) * 255;
+        encodeFloatRGBtoArray(sizeFn(v.location) * sizeFactor, sizes.array, v.instanceIndex * 3);
         locationIt.skipInstance();
     }
     return createTextureSize(sizes, 'instance', sizeData);
@@ -114,11 +116,11 @@ export function createInstanceSize(locationIt: LocationIterator, sizeFn: Locatio
 /** Creates size texture with size for each group (i.e. shared across instances/units) */
 export function createGroupSize(locationIt: LocationIterator, sizeFn: LocationSize, sizeData?: SizeData): SizeData {
     const { groupCount } = locationIt;
-    const sizes = createTextureImage(Math.max(1, groupCount), 1, Uint8Array, sizeData && sizeData.tSize.ref.value.array);
+    const sizes = createTextureImage(Math.max(1, groupCount), 3, Uint8Array, sizeData && sizeData.tSize.ref.value.array);
     locationIt.reset();
     while (locationIt.hasNext && !locationIt.isNextNewInstance) {
         const v = locationIt.move();
-        sizes.array[v.groupIndex] = encodeFloatLog(sizeFn(v.location)) * 255;
+        encodeFloatRGBtoArray(sizeFn(v.location) * sizeFactor, sizes.array, v.groupIndex * 3);
     }
     return createTextureSize(sizes, 'group', sizeData);
 }
@@ -127,11 +129,11 @@ export function createGroupSize(locationIt: LocationIterator, sizeFn: LocationSi
 export function createGroupInstanceSize(locationIt: LocationIterator, sizeFn: LocationSize, sizeData?: SizeData): SizeData {
     const { groupCount, instanceCount } = locationIt;
     const count = instanceCount * groupCount;
-    const sizes = createTextureImage(Math.max(1, count), 1, Uint8Array, sizeData && sizeData.tSize.ref.value.array);
+    const sizes = createTextureImage(Math.max(1, count), 3, Uint8Array, sizeData && sizeData.tSize.ref.value.array);
     locationIt.reset();
-    while (locationIt.hasNext && !locationIt.isNextNewInstance) {
+    while (locationIt.hasNext) {
         const v = locationIt.move();
-        sizes.array[v.index] = encodeFloatLog(sizeFn(v.location)) * 255;
+        encodeFloatRGBtoArray(sizeFn(v.location) * sizeFactor, sizes.array, v.index * 3);
     }
     return createTextureSize(sizes, 'groupInstance', sizeData);
 }

+ 1 - 1
src/mol-gl/renderable/schema.ts

@@ -176,7 +176,7 @@ export const SizeSchema = {
     // aSize: AttributeSpec('float32', 1, 0), // TODO
     uSize: UniformSpec('f', true),
     uSizeTexDim: UniformSpec('v2'),
-    tSize: TextureSpec('image-uint8', 'alpha', 'ubyte', 'nearest'),
+    tSize: TextureSpec('image-uint8', 'rgb', 'ubyte', 'nearest'),
     dSizeType: DefineSpec('string', ['uniform', 'attribute', 'instance', 'group', 'group_instance']),
     uSizeFactor: UniformSpec('f'),
 } as const;

+ 1 - 1
src/mol-gl/renderable/util.ts

@@ -82,7 +82,7 @@ export function printImageData(imageData: ImageData, scale = 1, pixelated = fals
 
 //
 
-const v = Vec3.zero();
+const v = Vec3();
 const boundaryHelperCoarse = new BoundaryHelper('14');
 const boundaryHelperFine = new BoundaryHelper('98');
 

+ 4 - 4
src/mol-gl/shader/chunks/assign-size.glsl.ts

@@ -4,15 +4,15 @@ export default `
 #elif defined(dSizeType_attribute)
     float size = aSize;
 #elif defined(dSizeType_instance)
-    float size = readFromTexture(tSize, aInstance, uSizeTexDim).a;
+    float size = decodeFloatRGB(readFromTexture(tSize, aInstance, uSizeTexDim).rgb);
 #elif defined(dSizeType_group)
-    float size = readFromTexture(tSize, group, uSizeTexDim).a;
+    float size = decodeFloatRGB(readFromTexture(tSize, group, uSizeTexDim).rgb);
 #elif defined(dSizeType_groupInstance)
-    float size = readFromTexture(tSize, aInstance * float(uGroupCount) + group, uSizeTexDim).a;
+    float size = decodeFloatRGB(readFromTexture(tSize, aInstance * float(uGroupCount) + group, uSizeTexDim).rgb);
 #endif
 
 #if defined(dSizeType_instance) || defined(dSizeType_group) || defined(dSizeType_groupInstance)
-    size = decodeFloatLog(size);
+    size /= 100.0; // NOTE factor also set in TypeScript
 #endif
 
 size *= uSizeFactor;

+ 14 - 13
src/mol-util/float-packing.ts

@@ -7,25 +7,26 @@
 import { clamp } from '../mol-math/interpolate';
 import { fasterExp, fasterLog } from '../mol-math/approx';
 import { Vec3, Vec4 } from '../mol-math/linear-algebra';
+import { NumberArray } from './type-helpers';
 
 const maxFloat = 10000.0; // NOTE same constant is set in shaders
-const floatLogFactor = fasterLog(maxFloat + 1.0);
+const floatLogFactor = fasterLog(maxFloat + 1);
 
 /** encode float logarithmically */
-export function encodeFloatLog(value: number) { return fasterLog(value + 1.0) / floatLogFactor; }
+export function encodeFloatLog(value: number) { return fasterLog(value + 1) / floatLogFactor; }
 
 /** decode logarithmically encoded float */
-export function decodeFloatLog(value: number) { return fasterExp(value * floatLogFactor) - 1.0; }
-
-/** encode float as normalized rgb triplet */
-export function encodeFloatRGB(value: number) {
-    value = clamp(value, 0.0, 16777216.0 - 1.0) + 1.0;
-    const b = (value % 256) / 255.0;
-    value = Math.floor(value / 256.0);
-    const g = (value % 256) / 255.0;
-    value = Math.floor(value / 256.0);
-    const r = (value % 256) / 255.0;
-    return [r, g, b];
+export function decodeFloatLog(value: number) { return fasterExp(value * floatLogFactor) - 1; }
+
+/** encode float as rgb triplet into array at offset */
+export function encodeFloatRGBtoArray(value: number, array: NumberArray, offset: number) {
+    value = clamp(value, 0, 16777216 - 1) + 1;
+    array[offset + 2] = value % 256;
+    value = Math.floor(value / 256);
+    array[offset + 1] = value % 256;
+    value = Math.floor(value / 256);
+    array[offset] = value % 256;
+    return array;
 }
 
 /** decode float encoded as rgb triplet */