From 29fc6c59e9068acc6e264ab88bf21bd313f62dbd Mon Sep 17 00:00:00 2001 From: Alexander Rose <alexander.rose@weirdbyte.de> Date: Sat, 23 Jul 2022 13:18:16 -0700 Subject: [PATCH] support constant group in gpu mc --- .../compute/marching-cubes/isosurface.ts | 19 +++++++++++-------- .../shader/marching-cubes/isosurface.frag.ts | 4 ++-- .../structure/visual/gaussian-surface-mesh.ts | 8 ++------ src/mol-repr/volume/isosurface.ts | 4 +--- src/tests/browser/marching-cubes.ts | 6 +++--- 5 files changed, 19 insertions(+), 22 deletions(-) diff --git a/src/mol-gl/compute/marching-cubes/isosurface.ts b/src/mol-gl/compute/marching-cubes/isosurface.ts index 93263e227..3c628b255 100644 --- a/src/mol-gl/compute/marching-cubes/isosurface.ts +++ b/src/mol-gl/compute/marching-cubes/isosurface.ts @@ -42,12 +42,13 @@ const IsosurfaceSchema = { dPackedGroup: DefineSpec('boolean'), dAxisOrder: DefineSpec('string', ['012', '021', '102', '120', '201', '210']), + dConstantGroup: DefineSpec('boolean'), }; type IsosurfaceValues = Values<typeof IsosurfaceSchema> const IsosurfaceName = 'isosurface'; -function getIsosurfaceRenderable(ctx: WebGLContext, activeVoxelsPyramid: Texture, activeVoxelsBase: Texture, volumeData: Texture, gridDim: Vec3, gridTexDim: Vec3, transform: Mat4, isoValue: number, levels: number, scale: Vec2, count: number, invert: boolean, packedGroup: boolean, axisOrder: Vec3): ComputeRenderable<IsosurfaceValues> { +function getIsosurfaceRenderable(ctx: WebGLContext, activeVoxelsPyramid: Texture, activeVoxelsBase: Texture, volumeData: Texture, gridDim: Vec3, gridTexDim: Vec3, transform: Mat4, isoValue: number, levels: number, scale: Vec2, count: number, invert: boolean, packedGroup: boolean, axisOrder: Vec3, constantGroup: boolean): ComputeRenderable<IsosurfaceValues> { if (ctx.namedComputeRenderables[IsosurfaceName]) { const v = ctx.namedComputeRenderables[IsosurfaceName].values as IsosurfaceValues; @@ -66,17 +67,18 @@ function getIsosurfaceRenderable(ctx: WebGLContext, activeVoxelsPyramid: Texture ValueCell.update(v.uGridTransform, transform); ValueCell.update(v.uScale, scale); - ValueCell.update(v.dPackedGroup, packedGroup); + ValueCell.updateIfChanged(v.dPackedGroup, packedGroup); ValueCell.updateIfChanged(v.dAxisOrder, axisOrder.join('')); + ValueCell.updateIfChanged(v.dConstantGroup, constantGroup); ctx.namedComputeRenderables[IsosurfaceName].update(); } else { - ctx.namedComputeRenderables[IsosurfaceName] = createIsosurfaceRenderable(ctx, activeVoxelsPyramid, activeVoxelsBase, volumeData, gridDim, gridTexDim, transform, isoValue, levels, scale, count, invert, packedGroup, axisOrder); + ctx.namedComputeRenderables[IsosurfaceName] = createIsosurfaceRenderable(ctx, activeVoxelsPyramid, activeVoxelsBase, volumeData, gridDim, gridTexDim, transform, isoValue, levels, scale, count, invert, packedGroup, axisOrder, constantGroup); } return ctx.namedComputeRenderables[IsosurfaceName]; } -function createIsosurfaceRenderable(ctx: WebGLContext, activeVoxelsPyramid: Texture, activeVoxelsBase: Texture, volumeData: Texture, gridDim: Vec3, gridTexDim: Vec3, transform: Mat4, isoValue: number, levels: number, scale: Vec2, count: number, invert: boolean, packedGroup: boolean, axisOrder: Vec3) { +function createIsosurfaceRenderable(ctx: WebGLContext, activeVoxelsPyramid: Texture, activeVoxelsBase: Texture, volumeData: Texture, gridDim: Vec3, gridTexDim: Vec3, transform: Mat4, isoValue: number, levels: number, scale: Vec2, count: number, invert: boolean, packedGroup: boolean, axisOrder: Vec3, constantGroup: boolean) { // console.log('uSize', Math.pow(2, levels)) const values: IsosurfaceValues = { ...QuadValues, @@ -99,6 +101,7 @@ function createIsosurfaceRenderable(ctx: WebGLContext, activeVoxelsPyramid: Text dPackedGroup: ValueCell.create(packedGroup), dAxisOrder: ValueCell.create(axisOrder.join('')), + dConstantGroup: ValueCell.create(constantGroup), }; const schema = { ...IsosurfaceSchema }; @@ -119,7 +122,7 @@ function setRenderingDefaults(ctx: WebGLContext) { state.clearColor(0, 0, 0, 0); } -export function createIsosurfaceBuffers(ctx: WebGLContext, activeVoxelsBase: Texture, volumeData: Texture, histogramPyramid: HistogramPyramid, gridDim: Vec3, gridTexDim: Vec3, transform: Mat4, isoValue: number, invert: boolean, packedGroup: boolean, axisOrder: Vec3, vertexTexture?: Texture, groupTexture?: Texture, normalTexture?: Texture) { +export function createIsosurfaceBuffers(ctx: WebGLContext, activeVoxelsBase: Texture, volumeData: Texture, histogramPyramid: HistogramPyramid, gridDim: Vec3, gridTexDim: Vec3, transform: Mat4, isoValue: number, invert: boolean, packedGroup: boolean, axisOrder: Vec3, constantGroup: boolean, vertexTexture?: Texture, groupTexture?: Texture, normalTexture?: Texture) { const { drawBuffers } = ctx.extensions; if (!drawBuffers) throw new Error('need WebGL draw buffers'); @@ -178,7 +181,7 @@ export function createIsosurfaceBuffers(ctx: WebGLContext, activeVoxelsBase: Tex groupTexture.attachFramebuffer(framebuffer, 1); normalTexture.attachFramebuffer(framebuffer, 2); - const renderable = getIsosurfaceRenderable(ctx, pyramidTex, activeVoxelsBase, volumeData, gridDim, gridTexDim, transform, isoValue, levels, scale, count, invert, packedGroup, axisOrder); + const renderable = getIsosurfaceRenderable(ctx, pyramidTex, activeVoxelsBase, volumeData, gridDim, gridTexDim, transform, isoValue, levels, scale, count, invert, packedGroup, axisOrder, constantGroup); ctx.state.currentRenderItemId = -1; framebuffer.bind(); @@ -210,11 +213,11 @@ export function createIsosurfaceBuffers(ctx: WebGLContext, activeVoxelsBase: Tex * * Implementation based on http://www.miaumiau.cat/2016/10/stream-compaction-in-webgl/ */ -export function extractIsosurface(ctx: WebGLContext, volumeData: Texture, gridDim: Vec3, gridTexDim: Vec3, gridTexScale: Vec2, transform: Mat4, isoValue: number, invert: boolean, packedGroup: boolean, axisOrder: Vec3, vertexTexture?: Texture, groupTexture?: Texture, normalTexture?: Texture) { +export function extractIsosurface(ctx: WebGLContext, volumeData: Texture, gridDim: Vec3, gridTexDim: Vec3, gridTexScale: Vec2, transform: Mat4, isoValue: number, invert: boolean, packedGroup: boolean, axisOrder: Vec3, constantGroup: boolean, vertexTexture?: Texture, groupTexture?: Texture, normalTexture?: Texture) { if (isTimingMode) ctx.timer.mark('extractIsosurface'); const activeVoxelsTex = calcActiveVoxels(ctx, volumeData, gridDim, gridTexDim, isoValue, gridTexScale); const compacted = createHistogramPyramid(ctx, activeVoxelsTex, gridTexScale, gridTexDim); - const gv = createIsosurfaceBuffers(ctx, activeVoxelsTex, volumeData, compacted, gridDim, gridTexDim, transform, isoValue, invert, packedGroup, axisOrder, vertexTexture, groupTexture, normalTexture); + const gv = createIsosurfaceBuffers(ctx, activeVoxelsTex, volumeData, compacted, gridDim, gridTexDim, transform, isoValue, invert, packedGroup, axisOrder, constantGroup, vertexTexture, groupTexture, normalTexture); if (isTimingMode) ctx.timer.markEnd('extractIsosurface'); return gv; diff --git a/src/mol-gl/shader/marching-cubes/isosurface.frag.ts b/src/mol-gl/shader/marching-cubes/isosurface.frag.ts index ac7f0cf3d..964bfdf17 100644 --- a/src/mol-gl/shader/marching-cubes/isosurface.frag.ts +++ b/src/mol-gl/shader/marching-cubes/isosurface.frag.ts @@ -268,9 +268,9 @@ void main(void) { gl_FragData[0].xyz = (uGridTransform * vec4(b0 + t * (b0 - b1), 1.0)).xyz; // group id - #if __VERSION__ == 100 + #if __VERSION__ == 100 || defined(dConstantGroup) // webgl1 does not support 'flat' interpolation (i.e. no interpolation) - // so we ensure a constant group id per triangle here + // ensure a constant group id per triangle as needed #ifdef dPackedGroup gl_FragData[1] = vec4(voxel(coord3d).rgb, 1.0); #else diff --git a/src/mol-repr/structure/visual/gaussian-surface-mesh.ts b/src/mol-repr/structure/visual/gaussian-surface-mesh.ts index bab823704..85da9b606 100644 --- a/src/mol-repr/structure/visual/gaussian-surface-mesh.ts +++ b/src/mol-repr/structure/visual/gaussian-surface-mesh.ts @@ -240,7 +240,7 @@ async function createGaussianSurfaceTextureMesh(ctx: VisualContext, unit: Unit, const axisOrder = Vec3.create(0, 1, 2); const buffer = textureMesh?.doubleBuffer.get(); - const gv = extractIsosurface(ctx.webgl, densityTextureData.texture, densityTextureData.gridDim, densityTextureData.gridTexDim, densityTextureData.gridTexScale, densityTextureData.transform, isoLevel, false, true, axisOrder, buffer?.vertex, buffer?.group, buffer?.normal); + const gv = extractIsosurface(ctx.webgl, densityTextureData.texture, densityTextureData.gridDim, densityTextureData.gridTexDim, densityTextureData.gridTexScale, densityTextureData.transform, isoLevel, false, true, axisOrder, true, buffer?.vertex, buffer?.group, buffer?.normal); if (isTimingMode) ctx.webgl.timer.markEnd('createGaussianSurfaceTextureMesh'); const groupCount = unit.elements.length; @@ -248,8 +248,6 @@ async function createGaussianSurfaceTextureMesh(ctx: VisualContext, unit: Unit, const surface = TextureMesh.create(gv.vertexCount, groupCount, gv.vertexTexture, gv.groupTexture, gv.normalTexture, boundingSphere, textureMesh); (surface.meta as GaussianSurfaceMeta).resolution = densityTextureData.resolution; - ValueCell.updateIfChanged(surface.varyingGroup, ctx.webgl.isWebGL2); - return surface; } @@ -316,7 +314,7 @@ async function createStructureGaussianSurfaceTextureMesh(ctx: VisualContext, str const axisOrder = Vec3.create(0, 1, 2); const buffer = textureMesh?.doubleBuffer.get(); - const gv = extractIsosurface(ctx.webgl, densityTextureData.texture, densityTextureData.gridDim, densityTextureData.gridTexDim, densityTextureData.gridTexScale, densityTextureData.transform, isoLevel, false, true, axisOrder, buffer?.vertex, buffer?.group, buffer?.normal); + const gv = extractIsosurface(ctx.webgl, densityTextureData.texture, densityTextureData.gridDim, densityTextureData.gridTexDim, densityTextureData.gridTexScale, densityTextureData.transform, isoLevel, false, true, axisOrder, true, buffer?.vertex, buffer?.group, buffer?.normal); if (isTimingMode) ctx.webgl.timer.markEnd('createStructureGaussianSurfaceTextureMesh'); const groupCount = structure.elementCount; @@ -324,8 +322,6 @@ async function createStructureGaussianSurfaceTextureMesh(ctx: VisualContext, str const surface = TextureMesh.create(gv.vertexCount, groupCount, gv.vertexTexture, gv.groupTexture, gv.normalTexture, boundingSphere, textureMesh); (surface.meta as GaussianSurfaceMeta).resolution = densityTextureData.resolution; - ValueCell.updateIfChanged(surface.varyingGroup, ctx.webgl.isWebGL2); - return surface; } diff --git a/src/mol-repr/volume/isosurface.ts b/src/mol-repr/volume/isosurface.ts index f6d6b9304..d7b1f068e 100644 --- a/src/mol-repr/volume/isosurface.ts +++ b/src/mol-repr/volume/isosurface.ts @@ -189,13 +189,11 @@ async function createVolumeIsosurfaceTextureMesh(ctx: VisualContext, volume: Vol const axisOrder = volume.grid.cells.space.axisOrderSlowToFast as Vec3; const buffer = textureMesh?.doubleBuffer.get(); - const gv = extractIsosurface(ctx.webgl, texture, gridDimension, gridTexDim, gridTexScale, transform, isoLevel, value < 0, false, axisOrder, buffer?.vertex, buffer?.group, buffer?.normal); + const gv = extractIsosurface(ctx.webgl, texture, gridDimension, gridTexDim, gridTexScale, transform, isoLevel, value < 0, false, axisOrder, true, buffer?.vertex, buffer?.group, buffer?.normal); const groupCount = volume.grid.cells.data.length; const surface = TextureMesh.create(gv.vertexCount, groupCount, gv.vertexTexture, gv.groupTexture, gv.normalTexture, Volume.getBoundingSphere(volume), textureMesh); - ValueCell.updateIfChanged(surface.varyingGroup, ctx.webgl.isWebGL2); - return surface; } diff --git a/src/tests/browser/marching-cubes.ts b/src/tests/browser/marching-cubes.ts index 8c501aa70..5f585b779 100644 --- a/src/tests/browser/marching-cubes.ts +++ b/src/tests/browser/marching-cubes.ts @@ -1,5 +1,5 @@ /** - * Copyright (c) 2019-2021 mol* contributors, licensed under MIT, See LICENSE file for more info. + * Copyright (c) 2019-2022 mol* contributors, licensed under MIT, See LICENSE file for more info. * * @author Alexander Rose <alexander.rose@weirdbyte.de> */ @@ -73,7 +73,7 @@ async function init() { console.timeEnd('gpu mc pyramid2'); console.time('gpu mc vert2'); - createIsosurfaceBuffers(webgl, activeVoxelsTex2, densityTextureData2.texture, compacted2, densityTextureData2.gridDim, densityTextureData2.gridTexDim, densityTextureData2.transform, isoValue, false, true, Vec3.create(0, 1, 2)); + createIsosurfaceBuffers(webgl, activeVoxelsTex2, densityTextureData2.texture, compacted2, densityTextureData2.gridDim, densityTextureData2.gridTexDim, densityTextureData2.transform, isoValue, false, true, Vec3.create(0, 1, 2), true); webgl.waitForGpuCommandsCompleteSync(); console.timeEnd('gpu mc vert2'); console.timeEnd('gpu mc2'); @@ -96,7 +96,7 @@ async function init() { console.timeEnd('gpu mc pyramid'); console.time('gpu mc vert'); - const gv = createIsosurfaceBuffers(webgl, activeVoxelsTex, densityTextureData.texture, compacted, densityTextureData.gridDim, densityTextureData.gridTexDim, densityTextureData.transform, isoValue, false, true, Vec3.create(0, 1, 2)); + const gv = createIsosurfaceBuffers(webgl, activeVoxelsTex, densityTextureData.texture, compacted, densityTextureData.gridDim, densityTextureData.gridTexDim, densityTextureData.transform, isoValue, false, true, Vec3.create(0, 1, 2), true); webgl.waitForGpuCommandsCompleteSync(); console.timeEnd('gpu mc vert'); console.timeEnd('gpu mc'); -- GitLab