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

wip, marchin cubes

parent db640554
Branches
Tags
No related merge requests found
...@@ -22,8 +22,8 @@ varying float vRadius; ...@@ -22,8 +22,8 @@ varying float vRadius;
#endif #endif
#pragma glslify: import('./chunks/common.glsl') #pragma glslify: import('./chunks/common.glsl')
#pragma glslify: encodeFloatLog = require(./utils/encode-float-log.glsl) // #pragma glslify: encodeFloatLog = require(./utils/encode-float-log.glsl)
#pragma glslify: decodeFloatLog = require(./utils/decode-float-log.glsl) // #pragma glslify: decodeFloatLog = require(./utils/decode-float-log.glsl)
#pragma glslify: encodeFloatRGB = require(./utils/encode-float-rgb.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
...@@ -58,9 +58,11 @@ void main() { ...@@ -58,9 +58,11 @@ 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 - encodeFloatLog(dist); gl_FragColor.a = 10000.0 - dist;
// gl_FragColor.a = 1.0 - encodeFloatLog(dist);
#elif defined(dCalcType_groupId) #elif defined(dCalcType_groupId)
float minDistance = decodeFloatLog(1.0 - textureMinDist(fragPos).a); float minDistance = 10000.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)
......
...@@ -115,7 +115,7 @@ async function calcGaussianDensityTexture2d(ctx: RuntimeContext, webgl: WebGLCon ...@@ -115,7 +115,7 @@ async function calcGaussianDensityTexture2d(ctx: RuntimeContext, webgl: WebGLCon
framebuffer.bind() framebuffer.bind()
setRenderingDefaults(gl) setRenderingDefaults(gl)
if (!texture) texture = createTexture(webgl, 'image-uint8', 'rgba', 'ubyte', 'linear') if (!texture) texture = createTexture(webgl, 'image-float32', 'rgba', 'float', 'nearest')
texture.define(texDimX, texDimY) texture.define(texDimX, texDimY)
function render(fbTex: Texture) { function render(fbTex: Texture) {
...@@ -173,7 +173,7 @@ async function calcGaussianDensityTexture3d(ctx: RuntimeContext, webgl: WebGLCon ...@@ -173,7 +173,7 @@ async function calcGaussianDensityTexture3d(ctx: RuntimeContext, webgl: WebGLCon
setRenderingDefaults(gl) setRenderingDefaults(gl)
gl.viewport(0, 0, dx, dy) gl.viewport(0, 0, dx, dy)
if (!texture) texture = createTexture(webgl, 'volume-uint8', 'rgba', 'ubyte', 'linear') if (!texture) texture = createTexture(webgl, 'volume-float32', 'rgba', 'float', 'nearest')
texture.define(dx, dy, dz) texture.define(dx, dy, dz)
function render(fbTex: Texture) { function render(fbTex: Texture) {
...@@ -330,7 +330,7 @@ function getTexture2dSize(gridDim: Vec3) { ...@@ -330,7 +330,7 @@ function getTexture2dSize(gridDim: Vec3) {
return { texDimX, texDimY, texRows, texCols } return { texDimX, texDimY, texRows, texCols }
} }
async function fieldFromTexture2d(ctx: WebGLContext, texture: Texture, dim: Vec3) { export async function fieldFromTexture2d(ctx: WebGLContext, texture: Texture, dim: Vec3) {
// console.time('fieldFromTexture2d') // console.time('fieldFromTexture2d')
const { framebufferCache } = ctx const { framebufferCache } = ctx
const [ dx, dy, dz ] = dim const [ dx, dy, dz ] = dim
...@@ -343,7 +343,8 @@ async function fieldFromTexture2d(ctx: WebGLContext, texture: Texture, dim: Vec3 ...@@ -343,7 +343,8 @@ async function fieldFromTexture2d(ctx: WebGLContext, texture: Texture, dim: Vec3
const idData = space.create() const idData = space.create()
const idField = Tensor.create(space, idData) const idField = Tensor.create(space, idData)
const image = new Uint8Array(width * height * 4) // const image = new Uint8Array(width * height * 4)
const image = new Float32Array(width * height * 4)
const framebuffer = framebufferCache.get(FramebufferName).value const framebuffer = framebufferCache.get(FramebufferName).value
framebuffer.bind() framebuffer.bind()
...@@ -365,8 +366,8 @@ async function fieldFromTexture2d(ctx: WebGLContext, texture: Texture, dim: Vec3 ...@@ -365,8 +366,8 @@ async function fieldFromTexture2d(ctx: WebGLContext, texture: Texture, dim: Vec3
for (let iy = 0; iy < dy; ++iy) { for (let iy = 0; iy < dy; ++iy) {
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] = decodeFloatRGB(image[idx], image[idx + 1], image[idx + 2]) idData[j] = decodeFloatRGB(image[idx] * 255, image[idx + 1] * 255, image[idx + 2] * 255)
j++ j++
} }
} }
......
/**
* Copyright (c) 2019 mol* contributors, licensed under MIT, See LICENSE file for more info.
*
* @author Alexander Rose <alexander.rose@weirdbyte.de>
*/
import './index.html'
import { Canvas3D } from 'mol-canvas3d/canvas3d';
import { Representation } from 'mol-repr/representation';
import { Color } from 'mol-util/color';
import { createRenderObject } from 'mol-gl/render-object';
import { computeGaussianDensity, computeGaussianDensityTexture2d } from 'mol-math/geometry/gaussian-density';
import { PositionData, Box3D, Sphere3D } from 'mol-math/geometry';
import { OrderedSet } from 'mol-data/int';
import { Vec3 } from 'mol-math/linear-algebra';
import { computeMarchingCubesMesh } from 'mol-geo/util/marching-cubes/algorithm';
import { Mesh } from 'mol-geo/geometry/mesh/mesh';
import { ColorNames } from 'mol-util/color/tables';
import { Isosurface } from 'mol-geo/geometry/isosurface/isosurface';
import { calcActiveVoxels } from 'mol-gl/compute/marching-cubes/active-voxels';
import { createHistogramPyramid } from 'mol-gl/compute/histogram-pyramid/reduction';
import { createIsosurfaceBuffers } from 'mol-gl/compute/marching-cubes/isosurface';
const parent = document.getElementById('app')!
parent.style.width = '100%'
parent.style.height = '100%'
const canvas = document.createElement('canvas')
canvas.style.width = '100%'
canvas.style.height = '100%'
parent.appendChild(canvas)
const canvas3d = Canvas3D.create(canvas, parent, {
backgroundColor: ColorNames.white,
cameraMode: 'orthographic'
})
canvas3d.animate()
async function init() {
const { webgl } = canvas3d
const position: PositionData = {
x: [0, 2],
y: [0, 2],
z: [0, 2],
indices: OrderedSet.ofSortedArray([0, 1]),
}
const box = Box3D.create(Vec3.create(-1, -1, -1), Vec3.create(3, 3, 3))
// const position: PositionData = {
// x: [0],
// y: [0],
// z: [0],
// indices: OrderedSet.ofSortedArray([0]),
// }
// const box = Box3D.create(Vec3.create(-1, -1, -1), Vec3.create(1, 1, 1))
const radius = () => 1.6
const props = {
resolution: 0.1,
radiusOffset: 0,
smoothness: 1.5
}
const isoValue = Math.exp(-props.smoothness)
// console.log('bbox', densityTextureData.bbox)
// console.time('gpu gaussian2')
// const densityTextureData2 = await computeGaussianDensityTexture2d(position, box, radius, props, webgl).run()
// webgl.waitForGpuCommandsCompleteSync()
// console.timeEnd('gpu gaussian2')
// console.time('gpu mc2')
// console.time('gpu mc active2')
// const activeVoxelsTex2 = calcActiveVoxels(webgl, densityTextureData2.texture, densityTextureData2.gridDimension, isoValue)
// webgl.waitForGpuCommandsCompleteSync()
// console.timeEnd('gpu mc active2')
// console.time('gpu mc pyramid2')
// const compacted2 = createHistogramPyramid(webgl, activeVoxelsTex2)
// webgl.waitForGpuCommandsCompleteSync()
// console.timeEnd('gpu mc pyramid2')
// console.time('gpu mc vert2')
// const gv2 = createIsosurfaceBuffers(webgl, activeVoxelsTex2, densityTextureData2.texture, compacted2, densityTextureData2.gridDimension, densityTextureData2.transform, isoValue)
// webgl.waitForGpuCommandsCompleteSync()
// console.timeEnd('gpu mc vert2')
// console.timeEnd('gpu mc2')
console.time('gpu gaussian')
const densityTextureData = await computeGaussianDensityTexture2d(position, box, radius, props, webgl).run()
webgl.waitForGpuCommandsCompleteSync()
console.timeEnd('gpu gaussian')
console.time('gpu mc')
console.time('gpu mc active')
const activeVoxelsTex = calcActiveVoxels(webgl, densityTextureData.texture, densityTextureData.gridDimension, isoValue)
webgl.waitForGpuCommandsCompleteSync()
console.timeEnd('gpu mc active')
console.time('gpu mc pyramid')
const compacted = createHistogramPyramid(webgl, activeVoxelsTex)
webgl.waitForGpuCommandsCompleteSync()
console.timeEnd('gpu mc pyramid')
console.time('gpu mc vert')
const gv = createIsosurfaceBuffers(webgl, activeVoxelsTex, densityTextureData.texture, compacted, densityTextureData.gridDimension, densityTextureData.transform, isoValue)
webgl.waitForGpuCommandsCompleteSync()
console.timeEnd('gpu mc vert')
console.timeEnd('gpu mc')
console.log({ ...webgl.stats, programCount: webgl.programCache.count, shaderCount: webgl.shaderCache.count })
const mcIsosurface = Isosurface.create(gv.vertexCount, 1, gv.vertexTexture, gv.normalBuffer, gv.groupBuffer, Sphere3D.fromBox3D(Sphere3D.zero(), densityTextureData.bbox))
const mcIsoSurfaceProps = { doubleSided: true, flatShaded: true, alpha: 1.0 }
const mcIsoSurfaceValues = Isosurface.Utils.createValuesSimple(mcIsosurface, mcIsoSurfaceProps, Color(0x112299), 1)
// console.log('mcIsoSurfaceValues', mcIsoSurfaceValues)
const mcIsoSurfaceState = Isosurface.Utils.createRenderableState(mcIsoSurfaceProps)
const mcIsoSurfaceRenderObject = createRenderObject('isosurface', mcIsoSurfaceValues, mcIsoSurfaceState, -1)
const mcIsoSurfaceRepr = Representation.fromRenderObject('isosurface', mcIsoSurfaceRenderObject)
canvas3d.add(mcIsoSurfaceRepr)
canvas3d.resetCamera()
//
console.time('cpu gaussian')
const densityData = await computeGaussianDensity(position, box, radius, { ...props, useGpu: false }, webgl).run()
console.timeEnd('cpu gaussian')
// console.log({ densityData })
const params = {
isoLevel: isoValue,
scalarField: densityData.field,
idField: densityData.idField
}
console.time('cpu mc')
const surface = await computeMarchingCubesMesh(params).run()
console.timeEnd('cpu mc')
// console.log('surface', surface)
Mesh.computeNormalsImmediate(surface)
const meshProps = { doubleSided: true, flatShaded: true, alpha: 1.0 }
const meshValues = Mesh.Utils.createValuesSimple(surface, meshProps, Color(0x995511), 1)
const meshState = Mesh.Utils.createRenderableState(meshProps)
const meshRenderObject = createRenderObject('mesh', meshValues, meshState, -1)
const meshRepr = Representation.fromRenderObject('mesh', meshRenderObject)
canvas3d.add(meshRepr)
canvas3d.resetCamera()
}
init()
\ No newline at end of file
...@@ -102,6 +102,7 @@ module.exports = [ ...@@ -102,6 +102,7 @@ module.exports = [
createApp('model-server-query'), createApp('model-server-query'),
createBrowserTest('font-atlas'), createBrowserTest('font-atlas'),
createBrowserTest('marching-cubes'),
createBrowserTest('render-lines'), createBrowserTest('render-lines'),
createBrowserTest('render-mesh'), createBrowserTest('render-mesh'),
createBrowserTest('render-shape'), createBrowserTest('render-shape'),
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment