From 22416b2ffc721cb5467195cb90bab6025eeed72e Mon Sep 17 00:00:00 2001 From: Alexander Rose <alexander.rose@weirdbyte.de> Date: Tue, 16 Apr 2019 10:58:10 -0700 Subject: [PATCH] wip --- src/mol-gl/shader/gaussian-density.frag | 45 ++++---------- src/mol-gl/shader/gaussian-density.vert | 15 +++-- src/mol-math/geometry/gaussian-density/gpu.ts | 60 +++++++++++-------- src/tests/browser/marching-cubes.ts | 6 +- 4 files changed, 57 insertions(+), 69 deletions(-) diff --git a/src/mol-gl/shader/gaussian-density.frag b/src/mol-gl/shader/gaussian-density.frag index 2e7c82d3a..74f6539de 100644 --- a/src/mol-gl/shader/gaussian-density.frag +++ b/src/mol-gl/shader/gaussian-density.frag @@ -1,5 +1,5 @@ /** - * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info. + * Copyright (c) 2018-2019 mol* contributors, licensed under MIT, See LICENSE file for more info. * * @author Alexander Rose <alexander.rose@weirdbyte.de> * @author Michael Krone <michael.krone@uni-tuebingen.de> @@ -8,16 +8,11 @@ precision highp float; varying vec3 vPosition; -varying float vRadius; +varying float vRadiusSqInv; #if defined(dCalcType_groupId) - #if defined(dGridTexType_2d) - precision mediump sampler2D; - uniform sampler2D tMinDistanceTex; - uniform vec3 uGridTexDim; - #elif defined(dGridTexType_3d) - precision highp sampler3D; - uniform sampler3D tMinDistanceTex; - #endif + precision highp sampler2D; + uniform sampler2D tMinDistanceTex; + uniform vec3 uGridTexDim; varying float vGroup; #endif @@ -25,45 +20,29 @@ varying float vRadius; // #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 -uniform vec3 uBboxSize; uniform vec3 uGridDim; +uniform vec2 uGridTexScale; uniform float uCurrentSlice; uniform float uCurrentX; uniform float uCurrentY; uniform float uAlpha; - -#if defined(dCalcType_groupId) - #if defined(dGridTexType_2d) - vec4 textureMinDist(vec3 pos) { - return texture3dFrom2dNearest(tMinDistanceTex, pos, uGridDim, uGridTexDim.xy); - } - #elif defined(dGridTexType_3d) - vec4 textureMinDist(vec3 pos) { - return texture(tMinDistanceTex, pos); - } - #endif -#endif +uniform float uResolution; void main() { vec2 v = gl_FragCoord.xy - vec2(uCurrentX, uCurrentY) - 0.5; - vec3 fragPos = vec3(v.x, v.y, uCurrentSlice) / uGridDim; - float dist = distance(fragPos * uBboxSize, vPosition * uBboxSize); + vec3 fragPos = vec3(v.x, v.y, uCurrentSlice); + float dist = distance(fragPos, vPosition) * uResolution; #if defined(dCalcType_density) - float radiusSq = vRadius * vRadius; - float density = exp(-uAlpha * ((dist * dist) / radiusSq)); + float density = exp(-uAlpha * ((dist * dist) * vRadiusSqInv)); gl_FragColor.a = density; #elif defined(dCalcType_minDistance) gl_FragColor.a = 10000.0 - dist; // gl_FragColor.a = 1.0 - encodeFloatLog(dist); #elif defined(dCalcType_groupId) - float minDistance = 10000.0 - textureMinDist(fragPos).a; - // float minDistance = decodeFloatLog(1.0 - textureMinDist(fragPos).a); - // TODO verify `length(uBboxSize / uGridDim) * 2.0` - // on some machines `* 2.0` is needed while on others `* 0.5` works - if (dist > minDistance + length(uBboxSize / uGridDim) * 0.5) + float minDistance = 10000.0 - texture2D(tMinDistanceTex, (gl_FragCoord.xy) / (uGridTexDim.xy / uGridTexScale)).a; + if (dist > minDistance + uResolution * 0.05) discard; gl_FragColor.rgb = encodeFloatRGB(vGroup); #endif diff --git a/src/mol-gl/shader/gaussian-density.vert b/src/mol-gl/shader/gaussian-density.vert index 6db1ff7c8..104828502 100644 --- a/src/mol-gl/shader/gaussian-density.vert +++ b/src/mol-gl/shader/gaussian-density.vert @@ -1,5 +1,5 @@ /** - * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info. + * Copyright (c) 2018-2019 mol* contributors, licensed under MIT, See LICENSE file for more info. * * @author Alexander Rose <alexander.rose@weirdbyte.de> * @author Michael Krone <michael.krone@uni-tuebingen.de> @@ -11,7 +11,7 @@ attribute vec3 aPosition; attribute float aRadius; varying vec3 vPosition; -varying float vRadius; +varying float vRadiusSqInv; #if defined(dCalcType_groupId) attribute float aGroup; @@ -20,16 +20,15 @@ varying float vRadius; uniform vec3 uBboxSize; uniform vec3 uBboxMin; -uniform vec3 uGridDim; uniform float uCurrentSlice; +uniform float uResolution; void main() { - vRadius = aRadius; + vRadiusSqInv = 1.0 / (aRadius * aRadius); #if defined(dCalcType_groupId) vGroup = aGroup; #endif - float scale = max(uBboxSize.x, uBboxSize.y); - gl_PointSize = (vRadius / scale) * max(uGridDim.x, uGridDim.y) * 6.0; - vPosition = (aPosition - uBboxMin) / uBboxSize; - gl_Position = vec4(vPosition * 2.0 - 1.0, 1.0); + gl_PointSize = floor(((aRadius * 4.0) / uResolution) + 0.5); + vPosition = (aPosition - uBboxMin) / uResolution; + gl_Position = vec4(((aPosition - uBboxMin) / uBboxSize) * 2.0 - 1.0, 1.0); } \ No newline at end of file diff --git a/src/mol-math/geometry/gaussian-density/gpu.ts b/src/mol-math/geometry/gaussian-density/gpu.ts index 94d461240..80f6314a5 100644 --- a/src/mol-math/geometry/gaussian-density/gpu.ts +++ b/src/mol-math/geometry/gaussian-density/gpu.ts @@ -34,7 +34,9 @@ export const GaussianDensitySchema = { uBboxSize: UniformSpec('v3', true), uGridDim: UniformSpec('v3', true), uGridTexDim: UniformSpec('v3', true), + uGridTexScale: UniformSpec('v2', true), uAlpha: UniformSpec('f', true), + uResolution: UniformSpec('f', true), tMinDistanceTex: TextureSpec('texture', 'rgba', 'float', 'nearest'), dGridTexType: DefineSpec('string', ['2d', '3d']), @@ -54,10 +56,10 @@ export function GaussianDensityGPU(position: PositionData, box: Box3D, radius: ( // always use texture2d when the gaussian density needs to be downloaded from the GPU, // it's faster than texture3d // console.time('GaussianDensityTexture2d') - const { scale, bbox, texture, gridDim: dim } = calcGaussianDensityTexture2d(webgl, position, box, radius, props) + const { scale, bbox, texture, gridDim, gridTexDim } = calcGaussianDensityTexture2d(webgl, position, box, radius, props) // webgl.waitForGpuCommandsCompleteSync() // console.timeEnd('GaussianDensityTexture2d') - const { field, idField } = fieldFromTexture2d(webgl, texture, dim) + const { field, idField } = fieldFromTexture2d(webgl, texture, gridDim, gridTexDim) return { field, idField, transform: getTransform(scale, bbox) } } @@ -101,18 +103,17 @@ type GaussianDensityTextureData = { function calcGaussianDensityTexture2d(webgl: WebGLContext, position: PositionData, box: Box3D, radius: (index: number) => number, props: GaussianDensityGPUProps, texture?: Texture): GaussianDensityTextureData { const { smoothness } = props - const { drawCount, positions, radii, groups, delta, expandedBox, dim } = prepareGaussianDensityData(position, box, radius, props) + const { drawCount, positions, radii, groups, scale, expandedBox, dim } = prepareGaussianDensityData(position, box, radius, props) const [ dx, dy, dz ] = dim const { texDimX, texDimY, texCols, powerOfTwoSize } = getTexture2dSize(dim) - // console.log({ texDimX, texDimY, texCols, powerOfTwoSize }) - // const gridTexDim = Vec3.create(powerOfTwoSize, powerOfTwoSize, 0) + // console.log({ texDimX, texDimY, texCols, powerOfTwoSize, dim }) const gridTexDim = Vec3.create(texDimX, texDimY, 0) const gridTexScale = Vec2.create(texDimX / powerOfTwoSize, texDimY / powerOfTwoSize) const minDistanceTexture = createTexture(webgl, 'image-float32', 'rgba', 'float', 'nearest') minDistanceTexture.define(powerOfTwoSize, powerOfTwoSize) - const renderable = getGaussianDensityRenderable(webgl, drawCount, positions, radii, groups, minDistanceTexture, expandedBox, dim, gridTexDim, smoothness) + const renderable = getGaussianDensityRenderable(webgl, drawCount, positions, radii, groups, minDistanceTexture, expandedBox, dim, gridTexDim, gridTexScale, smoothness, props.resolution) // @@ -123,8 +124,12 @@ function calcGaussianDensityTexture2d(webgl: WebGLContext, position: PositionDat framebuffer.bind() setRenderingDefaults(webgl) - if (!texture) texture = createTexture(webgl, 'image-float32', 'rgba', 'float', 'nearest') - texture.define(powerOfTwoSize, powerOfTwoSize) + if (!texture) { + texture = createTexture(webgl, 'image-float32', 'rgba', 'float', 'nearest') + texture.define(powerOfTwoSize, powerOfTwoSize) + } else if (texture.width !== powerOfTwoSize || texture.height !== powerOfTwoSize) { + texture.define(powerOfTwoSize, powerOfTwoSize) + } // console.log(renderable) @@ -150,6 +155,7 @@ function calcGaussianDensityTexture2d(webgl: WebGLContext, position: PositionDat ++currCol currX += dx } + gl.finish() } setupDensityRendering(webgl, renderable) @@ -157,27 +163,26 @@ function calcGaussianDensityTexture2d(webgl: WebGLContext, position: PositionDat setupMinDistanceRendering(webgl, renderable) render(minDistanceTexture, true) - gl.finish() setupGroupIdRendering(webgl, renderable) render(texture, false) // printTexture(webgl, texture, 1) - gl.finish() - - return { texture, scale: Vec3.inverse(Vec3.zero(), delta), bbox: expandedBox, gridDim: dim, gridTexDim, gridTexScale } + return { texture, scale, bbox: expandedBox, gridDim: dim, gridTexDim, gridTexScale } } function calcGaussianDensityTexture3d(webgl: WebGLContext, position: PositionData, box: Box3D, radius: (index: number) => number, props: GaussianDensityGPUProps, texture?: Texture): GaussianDensityTextureData { const { smoothness } = props - const { drawCount, positions, radii, groups, delta, expandedBox, dim } = prepareGaussianDensityData(position, box, radius, props) + const { drawCount, positions, radii, groups, scale, expandedBox, dim } = prepareGaussianDensityData(position, box, radius, props) const [ dx, dy, dz ] = dim const minDistanceTexture = createTexture(webgl, 'volume-float32', 'rgba', 'float', 'nearest') minDistanceTexture.define(dx, dy, dz) - const renderable = getGaussianDensityRenderable(webgl, drawCount, positions, radii, groups, minDistanceTexture, expandedBox, dim, dim, smoothness) + const gridTexScale = Vec2.create(1, 1) + + const renderable = getGaussianDensityRenderable(webgl, drawCount, positions, radii, groups, minDistanceTexture, expandedBox, dim, dim, gridTexScale, smoothness, props.resolution) // @@ -209,13 +214,14 @@ function calcGaussianDensityTexture3d(webgl: WebGLContext, position: PositionDat setupGroupIdRendering(webgl, renderable) render(texture) - return { texture, scale: Vec3.inverse(Vec3.zero(), delta), bbox: expandedBox, gridDim: dim, gridTexDim: dim, gridTexScale: Vec2() } + return { texture, scale, bbox: expandedBox, gridDim: dim, gridTexDim: dim, gridTexScale } } // function prepareGaussianDensityData(position: PositionData, box: Box3D, radius: (index: number) => number, props: GaussianDensityGPUProps) { const { resolution, radiusOffset } = props + const scaleFactor = 1 / resolution const { indices, x, y, z } = position const n = OrderedSet.size(indices) @@ -238,19 +244,18 @@ function prepareGaussianDensityData(position: PositionData, box: Box3D, radius: groups[i] = i } - const pad = maxRadius * 2 + resolution + const pad = maxRadius * 2 + resolution * 4 const expandedBox = Box3D.expand(Box3D(), box, Vec3.create(pad, pad, pad)); - const expandedDim = Box3D.size(Vec3(), expandedBox) - - const scaledBox = Box3D.scale(Box3D(), expandedBox, 1 / resolution) + const scaledBox = Box3D.scale(Box3D(), expandedBox, scaleFactor) const dim = Box3D.size(Vec3(), scaledBox) Vec3.ceil(dim, dim) - const delta = Vec3.div(Vec3(), dim, expandedDim) - return { drawCount: n, positions, radii, groups, delta, expandedBox, dim } + const scale = Vec3.create(resolution, resolution, resolution) + + return { drawCount: n, positions, radii, groups, scale, expandedBox, dim } } -function getGaussianDensityRenderable(webgl: WebGLContext, drawCount: number, positions: Float32Array, radii: Float32Array, groups: Float32Array, minDistanceTexture: Texture, box: Box3D, gridDim: Vec3, gridTexDim: Vec3, smoothness: number) { +function getGaussianDensityRenderable(webgl: WebGLContext, drawCount: number, positions: Float32Array, radii: Float32Array, groups: Float32Array, minDistanceTexture: Texture, box: Box3D, gridDim: Vec3, gridTexDim: Vec3, gridTexScale: Vec2, smoothness: number, resolution: number) { const extent = Vec3.sub(Vec3.zero(), box.max, box.min) const values: Values<typeof GaussianDensitySchema> = { @@ -268,7 +273,9 @@ function getGaussianDensityRenderable(webgl: WebGLContext, drawCount: number, po uBboxSize: ValueCell.create(extent), uGridDim: ValueCell.create(gridDim), uGridTexDim: ValueCell.create(gridTexDim), + uGridTexScale: ValueCell.create(gridTexScale), uAlpha: ValueCell.create(smoothness), + uResolution: ValueCell.create(resolution), tMinDistanceTex: ValueCell.create(minDistanceTexture), dGridTexType: ValueCell.create(minDistanceTexture.depth > 0 ? '3d' : '2d'), @@ -308,6 +315,8 @@ function setupDensityRendering(webgl: WebGLContext, renderable: ComputeRenderabl renderable.update() state.colorMask(false, false, false, true) state.blendFunc(gl.ONE, gl.ONE) + // state.colorMask(true, true, true, true) + // state.blendFuncSeparate(gl.ONE, gl.ZERO, gl.ONE, gl.ONE) state.blendEquation(gl.FUNC_ADD) } @@ -338,14 +347,15 @@ function getTexture2dSize(gridDim: Vec3) { } else { texDimX = gridDim[0] * gridDim[2] } - return { texDimX, texDimY, texRows, texCols, powerOfTwoSize } + return { texDimX, texDimY, texRows, texCols, powerOfTwoSize: texDimY < powerOfTwoSize ? powerOfTwoSize : powerOfTwoSize * 2 } } -export function fieldFromTexture2d(ctx: WebGLContext, texture: Texture, dim: Vec3) { +export function fieldFromTexture2d(ctx: WebGLContext, texture: Texture, dim: Vec3, texDim: Vec3) { // console.time('fieldFromTexture2d') const { framebufferCache } = ctx const [ dx, dy, dz ] = dim - const { width, height } = texture + // const { width, height } = texture + const [ width, height ] = texDim const fboTexCols = Math.floor(width / dx) const space = Tensor.Space(dim, [2, 1, 0], Float32Array) diff --git a/src/tests/browser/marching-cubes.ts b/src/tests/browser/marching-cubes.ts index 6d2199749..2aa507cc0 100644 --- a/src/tests/browser/marching-cubes.ts +++ b/src/tests/browser/marching-cubes.ts @@ -50,7 +50,7 @@ async function init() { const box = Box3D.create(Vec3.create(0, 0, 0), Vec3.create(2, 2, 2)) const radius = () => 1.8 const props = { - resolution: 0.3, + resolution: 0.1, radiusOffset: 0, smoothness: 1.5 } @@ -119,9 +119,9 @@ async function init() { // console.time('cpu gaussian') - const densityData = await computeGaussianDensity(position, box, radius, { ...props, useGpu: true }, webgl).run() + const densityData = await computeGaussianDensity(position, box, radius, { ...props, useGpu: false }, webgl).run() console.timeEnd('cpu gaussian') - // console.log({ densityData }) + console.log({ densityData }) const params = { isoLevel: isoValue, -- GitLab