Skip to content
Snippets Groups Projects
Commit af769160 authored by Alexander Rose's avatar Alexander Rose
Browse files

refactored float packing on cpu/gpu

parent 346ffa33
No related branches found
No related tags found
No related merge requests found
Showing
with 80 additions and 66 deletions
...@@ -21,13 +21,14 @@ import { Representation } from 'mol-repr/representation'; ...@@ -21,13 +21,14 @@ import { Representation } from 'mol-repr/representation';
import { createRenderTarget } from 'mol-gl/webgl/render-target'; import { createRenderTarget } from 'mol-gl/webgl/render-target';
import Scene from 'mol-gl/scene'; import Scene from 'mol-gl/scene';
import { RenderVariant } from 'mol-gl/webgl/render-item'; import { RenderVariant } from 'mol-gl/webgl/render-item';
import { PickingId, decodeIdRGB } from 'mol-geo/geometry/picking'; import { PickingId } from 'mol-geo/geometry/picking';
import { MarkerAction } from 'mol-geo/geometry/marker-data'; import { MarkerAction } from 'mol-geo/geometry/marker-data';
import { Loci, EmptyLoci, isEmptyLoci } from 'mol-model/loci'; import { Loci, EmptyLoci, isEmptyLoci } from 'mol-model/loci';
import { Color } from 'mol-util/color'; import { Color } from 'mol-util/color';
import { Camera } from './camera'; import { Camera } from './camera';
import { ParamDefinition as PD } from 'mol-util/param-definition'; import { ParamDefinition as PD } from 'mol-util/param-definition';
import { BoundingSphereHelper, DebugHelperParams } from './helper/bounding-sphere-helper'; import { BoundingSphereHelper, DebugHelperParams } from './helper/bounding-sphere-helper';
import { decodeFloatRGB } from 'mol-util/float-packing';
export const Canvas3DParams = { export const Canvas3DParams = {
// TODO: FPS cap? // TODO: FPS cap?
...@@ -276,19 +277,19 @@ namespace Canvas3D { ...@@ -276,19 +277,19 @@ namespace Canvas3D {
// TODO slow in Chrome, ok in FF; doesn't play well with gpu surface calc // TODO slow in Chrome, ok in FF; doesn't play well with gpu surface calc
// await webgl.readPixelsAsync(xp, yp, 1, 1, buffer) // await webgl.readPixelsAsync(xp, yp, 1, 1, buffer)
webgl.readPixels(xp, yp, 1, 1, buffer) webgl.readPixels(xp, yp, 1, 1, buffer)
const objectId = decodeIdRGB(buffer[0], buffer[1], buffer[2]) const objectId = decodeFloatRGB(buffer[0], buffer[1], buffer[2])
if (objectId === -1) { isIdentifying = false; return; } if (objectId === -1) { isIdentifying = false; return; }
instancePickTarget.bind() instancePickTarget.bind()
// await webgl.readPixelsAsync(xp, yp, 1, 1, buffer) // await webgl.readPixelsAsync(xp, yp, 1, 1, buffer)
webgl.readPixels(xp, yp, 1, 1, buffer) webgl.readPixels(xp, yp, 1, 1, buffer)
const instanceId = decodeIdRGB(buffer[0], buffer[1], buffer[2]) const instanceId = decodeFloatRGB(buffer[0], buffer[1], buffer[2])
if (instanceId === -1) { isIdentifying = false; return; } if (instanceId === -1) { isIdentifying = false; return; }
groupPickTarget.bind() groupPickTarget.bind()
// await webgl.readPixelsAsync(xp, yp, 1, 1, buffer) // await webgl.readPixelsAsync(xp, yp, 1, 1, buffer)
webgl.readPixels(xp, yp, 1, 1, buffer) webgl.readPixels(xp, yp, 1, 1, buffer)
const groupId = decodeIdRGB(buffer[0], buffer[1], buffer[2]) const groupId = decodeFloatRGB(buffer[0], buffer[1], buffer[2])
if (groupId === -1) { isIdentifying = false; return; } if (groupId === -1) { isIdentifying = false; return; }
isIdentifying = false isIdentifying = false
......
...@@ -4,17 +4,6 @@ ...@@ -4,17 +4,6 @@
* @author Alexander Rose <alexander.rose@weirdbyte.de> * @author Alexander Rose <alexander.rose@weirdbyte.de>
*/ */
function decodeFloatRGBA(r: number, g: number, b: number) {
r = Math.floor(r)
g = Math.floor(g)
b = Math.floor(b)
return r * 256 * 256 + g * 256 + b
}
export function decodeIdRGB(r: number, g: number, b: number) {
return decodeFloatRGBA(r, g, b) - 1
}
export interface PickingId { export interface PickingId {
objectId: number objectId: number
instanceId: number instanceId: number
......
...@@ -7,9 +7,9 @@ ...@@ -7,9 +7,9 @@
#elif defined(dColorType_groupInstance) #elif defined(dColorType_groupInstance)
vColor.rgb = readFromTexture(tColor, aInstance * float(uGroupCount) + aGroup, uColorTexDim).rgb; vColor.rgb = readFromTexture(tColor, aInstance * float(uGroupCount) + aGroup, uColorTexDim).rgb;
#elif defined(dColorType_objectPicking) #elif defined(dColorType_objectPicking)
vColor = vec4(encodeIdRGB(float(uObjectId)), 1.0); vColor = vec4(encodeFloatRGB(float(uObjectId)), 1.0);
#elif defined(dColorType_instancePicking) #elif defined(dColorType_instancePicking)
vColor = vec4(encodeIdRGB(aInstance), 1.0); vColor = vec4(encodeFloatRGB(aInstance), 1.0);
#elif defined(dColorType_groupPicking) #elif defined(dColorType_groupPicking)
vColor = vec4(encodeIdRGB(aGroup), 1.0); vColor = vec4(encodeFloatRGB(aGroup), 1.0);
#endif #endif
\ No newline at end of file
...@@ -9,5 +9,5 @@ ...@@ -9,5 +9,5 @@
uniform sampler2D tColor; uniform sampler2D tColor;
#elif defined(dColorType_objectPicking) || defined(dColorType_instancePicking) || defined(dColorType_groupPicking) #elif defined(dColorType_objectPicking) || defined(dColorType_instancePicking) || defined(dColorType_groupPicking)
varying vec4 vColor; varying vec4 vColor;
#pragma glslify: encodeIdRGB = require(../utils/encode-id-rgb.glsl) #pragma glslify: encodeFloatRGB = require(../utils/encode-float-rgb.glsl)
#endif #endif
\ No newline at end of file
...@@ -47,8 +47,8 @@ uniform int uPickable; ...@@ -47,8 +47,8 @@ uniform int uPickable;
#pragma glslify: import('./chunks/common.glsl') #pragma glslify: import('./chunks/common.glsl')
#pragma glslify: readFromTexture = require(./utils/read-from-texture.glsl, intMod=intMod, intDiv=intDiv, foo=foo) // foo=foo is a workaround for a bug in glslify #pragma glslify: readFromTexture = require(./utils/read-from-texture.glsl, intMod=intMod, intDiv=intDiv, foo=foo) // foo=foo is a workaround for a bug in glslify
#pragma glslify: encodeIdRGB = require(./utils/encode-id-rgb.glsl) #pragma glslify: encodeFloatRGB = require(./utils/encode-float-rgb.glsl)
#pragma glslify: decodeIdRGB = require(./utils/decode-id-rgb.glsl) #pragma glslify: decodeFloatRGB = require(./utils/decode-float-rgb.glsl)
#pragma glslify: texture3dFrom2dNearest = require(./utils/texture3d-from-2d-nearest.glsl, intMod=intMod, intDiv=intDiv, foo=foo) // foo=foo is a workaround for a bug in glslify #pragma glslify: texture3dFrom2dNearest = require(./utils/texture3d-from-2d-nearest.glsl, intMod=intMod, intDiv=intDiv, foo=foo) // foo=foo is a workaround for a bug in glslify
#pragma glslify: texture3dFrom2dLinear = require(./utils/texture3d-from-2d-linear.glsl, intMod=intMod, intDiv=intDiv, foo=foo) // foo=foo is a workaround for a bug in glslify #pragma glslify: texture3dFrom2dLinear = require(./utils/texture3d-from-2d-linear.glsl, intMod=intMod, intDiv=intDiv, foo=foo) // foo=foo is a workaround for a bug in glslify
...@@ -135,12 +135,12 @@ vec4 raymarch(vec3 startLoc, vec3 step, vec3 viewDir) { ...@@ -135,12 +135,12 @@ vec4 raymarch(vec3 startLoc, vec3 step, vec3 viewDir) {
#endif #endif
#if defined(dColorType_objectPicking) #if defined(dColorType_objectPicking)
return vec4(encodeIdRGB(float(uObjectId)), 1.0); return vec4(encodeFloatRGB(float(uObjectId)), 1.0);
#elif defined(dColorType_instancePicking) #elif defined(dColorType_instancePicking)
return vec4(encodeIdRGB(instance), 1.0); return vec4(encodeFloatRGB(instance), 1.0);
#elif defined(dColorType_groupPicking) #elif defined(dColorType_groupPicking)
float group = floor(decodeIdRGB(textureGroup(isoPos).rgb) + 0.5); float group = floor(decodeFloatRGB(textureGroup(isoPos).rgb) + 0.5);
return vec4(encodeIdRGB(group), 1.0); return vec4(encodeFloatRGB(group), 1.0);
#else #else
// compute gradient by central differences // compute gradient by central differences
gradient.x = textureVal(isoPos - dx).a - textureVal(isoPos + dx).a; gradient.x = textureVal(isoPos - dx).a - textureVal(isoPos + dx).a;
...@@ -150,7 +150,7 @@ vec4 raymarch(vec3 startLoc, vec3 step, vec3 viewDir) { ...@@ -150,7 +150,7 @@ vec4 raymarch(vec3 startLoc, vec3 step, vec3 viewDir) {
float d = float(dot(gradient, viewDir) > 0.0); float d = float(dot(gradient, viewDir) > 0.0);
gradient = (2.0 * d - 1.0) * gradient; gradient = (2.0 * d - 1.0) * gradient;
float group = floor(decodeIdRGB(textureGroup(isoPos).rgb) + 0.5); float group = floor(decodeFloatRGB(textureGroup(isoPos).rgb) + 0.5);
#if defined(dColorType_instance) #if defined(dColorType_instance)
color = readFromTexture(tColor, instance, uColorTexDim).rgb; color = readFromTexture(tColor, instance, uColorTexDim).rgb;
......
...@@ -22,7 +22,9 @@ varying float vRadius; ...@@ -22,7 +22,9 @@ varying float vRadius;
#endif #endif
#pragma glslify: import('./chunks/common.glsl') #pragma glslify: import('./chunks/common.glsl')
#pragma glslify: encodeIdRGB = require(./utils/encode-id-rgb.glsl) #pragma glslify: encodeFloatLog = require(./utils/encode-float-log.glsl)
#pragma glslify: decodeFloatLog = require(./utils/decode-float-log.glsl)
#pragma glslify: encodeFloatRGB = require(./utils/encode-float-rgb.glsl)
#pragma glslify: texture3dFrom2dNearest = require(./utils/texture3d-from-2d-nearest.glsl, intMod=intMod, intDiv=intDiv, foo=foo) // foo=foo is a workaround for a bug in glslify #pragma glslify: texture3dFrom2dNearest = require(./utils/texture3d-from-2d-nearest.glsl, intMod=intMod, intDiv=intDiv, foo=foo) // foo=foo is a workaround for a bug in glslify
uniform vec3 uBboxSize; uniform vec3 uBboxSize;
...@@ -46,12 +48,6 @@ uniform float uAlpha; ...@@ -46,12 +48,6 @@ uniform float uAlpha;
#endif #endif
#endif #endif
// encode distance logarithmically with given maxDistance
const float maxDistance = 10000.0;
const float distLogFactor = log(maxDistance + 1.0);
float encodeDistLog(float dist) { return log(dist + 1.0) / distLogFactor; }
float decodeDistLog(float logDist) { return exp(logDist * distLogFactor) - 1.0; }
void main() { void main() {
vec2 v = gl_FragCoord.xy - vec2(uCurrentX, uCurrentY) - 0.5; vec2 v = gl_FragCoord.xy - vec2(uCurrentX, uCurrentY) - 0.5;
vec3 fragPos = vec3(v.x, v.y, uCurrentSlice) / uGridDim; vec3 fragPos = vec3(v.x, v.y, uCurrentSlice) / uGridDim;
...@@ -62,13 +58,13 @@ void main() { ...@@ -62,13 +58,13 @@ void main() {
float density = exp(-uAlpha * ((dist * dist) / radiusSq)); float density = exp(-uAlpha * ((dist * dist) / radiusSq));
gl_FragColor = vec4(density); gl_FragColor = vec4(density);
#elif defined(dCalcType_minDistance) #elif defined(dCalcType_minDistance)
gl_FragColor.a = 1.0 - encodeDistLog(dist); gl_FragColor.a = 1.0 - encodeFloatLog(dist);
#elif defined(dCalcType_groupId) #elif defined(dCalcType_groupId)
float minDistance = decodeDistLog(1.0 - textureMinDist(fragPos).a); float minDistance = decodeFloatLog(1.0 - textureMinDist(fragPos).a);
// TODO verify `length(uBboxSize / uGridDim) * 2.0` // TODO verify `length(uBboxSize / uGridDim) * 2.0`
// on some machines `* 2.0` is needed while on others `* 0.5` works // on some machines `* 2.0` is needed while on others `* 0.5` works
if (dist > minDistance + length(uBboxSize / uGridDim) * 0.5) if (dist > minDistance + length(uBboxSize / uGridDim) * 0.5)
discard; discard;
gl_FragColor.rgb = encodeIdRGB(vGroup); gl_FragColor.rgb = encodeFloatRGB(vGroup);
#endif #endif
} }
\ No newline at end of file
/**
* Copyright (c) 2019 mol* contributors, licensed under MIT, See LICENSE file for more info.
*
* @author Alexander Rose <alexander.rose@weirdbyte.de>
*/
const float maxFloat = 10000.0; // NOTE constant also set in in encodeFloatLog and in TypeScript
const float floatLogFactor = log(maxFloat + 1.0);
float decodeFloatLog(in float value) { return exp(value * floatLogFactor) - 1.0; }
#pragma glslify: export(decodeFloatLog)
\ No newline at end of file
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
*/ */
float decodeFloatRGB(const in vec3 rgb) { float decodeFloatRGB(const in vec3 rgb) {
return rgb.r * 256.0 * 256.0 * 255.0 + rgb.g * 256.0 * 255.0 + rgb.b * 255.0; return (rgb.r * 256.0 * 256.0 * 255.0 + rgb.g * 256.0 * 255.0 + rgb.b * 255.0) - 1.0;
} }
#pragma glslify: export(decodeFloatRGB) #pragma glslify: export(decodeFloatRGB)
\ No newline at end of file
/**
* Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info.
*
* @author Alexander Rose <alexander.rose@weirdbyte.de>
*/
#pragma glslify: decodeFloatRGB = require(../utils/decode-float-rgb.glsl)
float decodeIdRGB(const in vec3 v) {
return decodeFloatRGB(v) - 1.0;
}
#pragma glslify: export(decodeIdRGB)
\ No newline at end of file
/**
* Copyright (c) 2019 mol* contributors, licensed under MIT, See LICENSE file for more info.
*
* @author Alexander Rose <alexander.rose@weirdbyte.de>
*/
const float maxFloat = 10000.0; // NOTE constant also set in in decodeFloatLog and in TypeScript
const float floatLogFactor = log(maxFloat + 1.0);
float encodeFloatLog(in float value) { return log(value + 1.0) / floatLogFactor; }
#pragma glslify: export(encodeFloatLog)
\ No newline at end of file
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
*/ */
vec3 encodeFloatRGB(in float value) { vec3 encodeFloatRGB(in float value) {
value = clamp(value, 0.0, 16777216.0); value = clamp(value, 0.0, 16777216.0 - 1.0) + 1.0;
vec3 c = vec3(0.0); vec3 c = vec3(0.0);
c.b = mod(value, 256.0); c.b = mod(value, 256.0);
value = floor(value / 256.0); value = floor(value / 256.0);
......
/**
* Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info.
*
* @author Alexander Rose <alexander.rose@weirdbyte.de>
*/
#pragma glslify: encodeFloatRGB = require(../utils/encode-float-rgb.glsl)
vec3 encodeIdRGB(const in float v) {
return encodeFloatRGB(v + 1.0);
}
#pragma glslify: export(encodeIdRGB)
\ No newline at end of file
...@@ -18,7 +18,7 @@ import { createRenderable, createGaussianDensityRenderObject } from 'mol-gl/rend ...@@ -18,7 +18,7 @@ import { createRenderable, createGaussianDensityRenderObject } from 'mol-gl/rend
import { WebGLContext } from 'mol-gl/webgl/context'; import { WebGLContext } from 'mol-gl/webgl/context';
import { createTexture, Texture } from 'mol-gl/webgl/texture'; import { createTexture, Texture } from 'mol-gl/webgl/texture';
import { GLRenderingContext } from 'mol-gl/webgl/compat'; import { GLRenderingContext } from 'mol-gl/webgl/compat';
import { decodeIdRGB } from 'mol-geo/geometry/picking'; import { decodeFloatRGB } from 'mol-util/float-packing';
/** name for shared framebuffer used for gpu gaussian surface operations */ /** name for shared framebuffer used for gpu gaussian surface operations */
const FramebufferName = 'gaussian-density-gpu' const FramebufferName = 'gaussian-density-gpu'
...@@ -329,7 +329,7 @@ async function fieldFromTexture2d(ctx: WebGLContext, texture: Texture, dim: Vec3 ...@@ -329,7 +329,7 @@ async function fieldFromTexture2d(ctx: WebGLContext, texture: Texture, dim: Vec3
for (let ix = 0; ix < dx; ++ix) { for (let ix = 0; ix < dx; ++ix) {
const idx = 4 * (tmpCol * dx + (iy + tmpRow) * width + ix) const idx = 4 * (tmpCol * dx + (iy + tmpRow) * width + ix)
data[j] = image[idx + 3] / 255 data[j] = image[idx + 3] / 255
idData[j] = decodeIdRGB(image[idx], image[idx + 1], image[idx + 2]) idData[j] = decodeFloatRGB(image[idx], image[idx + 1], image[idx + 2])
j++ j++
} }
} }
......
/**
* Copyright (c) 2019 mol* contributors, licensed under MIT, See LICENSE file for more info.
*
* @author Alexander Rose <alexander.rose@weirdbyte.de>
*/
import { clamp } from 'mol-math/interpolate';
const maxFloat = 10000.0; // NOTE same constant is set in shaders
const floatLogFactor = Math.log(maxFloat + 1.0);
/** encode float logarithmically */
export function encodeFloatLog(value: number) { return Math.log(value + 1.0) / floatLogFactor }
/** decode logarithmically encoded float */
export function decodeFloatLog(value: number) { return Math.exp(value * floatLogFactor) - 1.0 }
/** encode float as 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]
}
/** decode float encoded as rgb triplet */
export function decodeFloatRGB(r: number, g: number, b: number) {
return (Math.floor(r) * 256 * 256 + Math.floor(g) * 256 + Math.floor(b)) - 1
}
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment