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

wip

parent 65c7c2f4
No related branches found
No related tags found
No related merge requests found
/**
* 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
......
/**
* 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
......@@ -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)
......
......@@ -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,
......
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