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

fix gpu isosurface group id

- was wrong for axis order other than 012
- fixes #331
parent 7f698336
No related branches found
No related tags found
No related merge requests found
...@@ -39,13 +39,14 @@ const IsosurfaceSchema = { ...@@ -39,13 +39,14 @@ const IsosurfaceSchema = {
uGridTransform: UniformSpec('m4'), uGridTransform: UniformSpec('m4'),
uScale: UniformSpec('v2'), uScale: UniformSpec('v2'),
dPackedGroup: DefineSpec('boolean') dPackedGroup: DefineSpec('boolean'),
dAxisOrder: DefineSpec('string', ['012', '021', '102', '120', '201', '210']),
}; };
type IsosurfaceValues = Values<typeof IsosurfaceSchema> type IsosurfaceValues = Values<typeof IsosurfaceSchema>
const IsosurfaceName = 'isosurface'; 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): 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): ComputeRenderable<IsosurfaceValues> {
if (ctx.namedComputeRenderables[IsosurfaceName]) { if (ctx.namedComputeRenderables[IsosurfaceName]) {
const v = ctx.namedComputeRenderables[IsosurfaceName].values as IsosurfaceValues; const v = ctx.namedComputeRenderables[IsosurfaceName].values as IsosurfaceValues;
...@@ -65,15 +66,16 @@ function getIsosurfaceRenderable(ctx: WebGLContext, activeVoxelsPyramid: Texture ...@@ -65,15 +66,16 @@ function getIsosurfaceRenderable(ctx: WebGLContext, activeVoxelsPyramid: Texture
ValueCell.update(v.uScale, scale); ValueCell.update(v.uScale, scale);
ValueCell.update(v.dPackedGroup, packedGroup); ValueCell.update(v.dPackedGroup, packedGroup);
ValueCell.updateIfChanged(v.dAxisOrder, axisOrder.join(''));
ctx.namedComputeRenderables[IsosurfaceName].update(); ctx.namedComputeRenderables[IsosurfaceName].update();
} else { } else {
ctx.namedComputeRenderables[IsosurfaceName] = createIsosurfaceRenderable(ctx, activeVoxelsPyramid, activeVoxelsBase, volumeData, gridDim, gridTexDim, transform, isoValue, levels, scale, count, invert, packedGroup); ctx.namedComputeRenderables[IsosurfaceName] = createIsosurfaceRenderable(ctx, activeVoxelsPyramid, activeVoxelsBase, volumeData, gridDim, gridTexDim, transform, isoValue, levels, scale, count, invert, packedGroup, axisOrder);
} }
return ctx.namedComputeRenderables[IsosurfaceName]; 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) { 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) {
// console.log('uSize', Math.pow(2, levels)) // console.log('uSize', Math.pow(2, levels))
const values: IsosurfaceValues = { const values: IsosurfaceValues = {
...QuadValues, ...QuadValues,
...@@ -94,7 +96,8 @@ function createIsosurfaceRenderable(ctx: WebGLContext, activeVoxelsPyramid: Text ...@@ -94,7 +96,8 @@ function createIsosurfaceRenderable(ctx: WebGLContext, activeVoxelsPyramid: Text
uGridTransform: ValueCell.create(transform), uGridTransform: ValueCell.create(transform),
uScale: ValueCell.create(scale), uScale: ValueCell.create(scale),
dPackedGroup: ValueCell.create(packedGroup) dPackedGroup: ValueCell.create(packedGroup),
dAxisOrder: ValueCell.create(axisOrder.join('')),
}; };
const schema = { ...IsosurfaceSchema }; const schema = { ...IsosurfaceSchema };
...@@ -115,7 +118,7 @@ function setRenderingDefaults(ctx: WebGLContext) { ...@@ -115,7 +118,7 @@ function setRenderingDefaults(ctx: WebGLContext) {
state.clearColor(0, 0, 0, 0); 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, 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, vertexTexture?: Texture, groupTexture?: Texture, normalTexture?: Texture) {
const { drawBuffers } = ctx.extensions; const { drawBuffers } = ctx.extensions;
if (!drawBuffers) throw new Error('need WebGL draw buffers'); if (!drawBuffers) throw new Error('need WebGL draw buffers');
...@@ -173,7 +176,7 @@ export function createIsosurfaceBuffers(ctx: WebGLContext, activeVoxelsBase: Tex ...@@ -173,7 +176,7 @@ export function createIsosurfaceBuffers(ctx: WebGLContext, activeVoxelsBase: Tex
groupTexture.attachFramebuffer(framebuffer, 1); groupTexture.attachFramebuffer(framebuffer, 1);
normalTexture.attachFramebuffer(framebuffer, 2); normalTexture.attachFramebuffer(framebuffer, 2);
const renderable = getIsosurfaceRenderable(ctx, pyramidTex, activeVoxelsBase, volumeData, gridDim, gridTexDim, transform, isoValue, levels, scale, count, invert, packedGroup); const renderable = getIsosurfaceRenderable(ctx, pyramidTex, activeVoxelsBase, volumeData, gridDim, gridTexDim, transform, isoValue, levels, scale, count, invert, packedGroup, axisOrder);
ctx.state.currentRenderItemId = -1; ctx.state.currentRenderItemId = -1;
framebuffer.bind(); framebuffer.bind();
...@@ -204,7 +207,7 @@ export function createIsosurfaceBuffers(ctx: WebGLContext, activeVoxelsBase: Tex ...@@ -204,7 +207,7 @@ export function createIsosurfaceBuffers(ctx: WebGLContext, activeVoxelsBase: Tex
* *
* Implementation based on http://www.miaumiau.cat/2016/10/stream-compaction-in-webgl/ * 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, 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, vertexTexture?: Texture, groupTexture?: Texture, normalTexture?: Texture) {
// console.time('calcActiveVoxels'); // console.time('calcActiveVoxels');
const activeVoxelsTex = calcActiveVoxels(ctx, volumeData, gridDim, gridTexDim, isoValue, gridTexScale); const activeVoxelsTex = calcActiveVoxels(ctx, volumeData, gridDim, gridTexDim, isoValue, gridTexScale);
// ctx.waitForGpuCommandsCompleteSync(); // ctx.waitForGpuCommandsCompleteSync();
...@@ -216,7 +219,7 @@ export function extractIsosurface(ctx: WebGLContext, volumeData: Texture, gridDi ...@@ -216,7 +219,7 @@ export function extractIsosurface(ctx: WebGLContext, volumeData: Texture, gridDi
// console.timeEnd('createHistogramPyramid'); // console.timeEnd('createHistogramPyramid');
// console.time('createIsosurfaceBuffers'); // console.time('createIsosurfaceBuffers');
const gv = createIsosurfaceBuffers(ctx, activeVoxelsTex, volumeData, compacted, gridDim, gridTexDim, transform, isoValue, invert, packedGroup, vertexTexture, groupTexture, normalTexture); const gv = createIsosurfaceBuffers(ctx, activeVoxelsTex, volumeData, compacted, gridDim, gridTexDim, transform, isoValue, invert, packedGroup, axisOrder, vertexTexture, groupTexture, normalTexture);
// ctx.waitForGpuCommandsCompleteSync(); // ctx.waitForGpuCommandsCompleteSync();
// console.timeEnd('createIsosurfaceBuffers'); // console.timeEnd('createIsosurfaceBuffers');
......
...@@ -256,7 +256,20 @@ void main(void) { ...@@ -256,7 +256,20 @@ void main(void) {
gl_FragData[1] = vec4(voxel(coord3d).rgb, 1.0); gl_FragData[1] = vec4(voxel(coord3d).rgb, 1.0);
#else #else
vec3 gridDim = uGridDim - vec3(1.0, 1.0, 0.0); // remove xy padding vec3 gridDim = uGridDim - vec3(1.0, 1.0, 0.0); // remove xy padding
float group = coord3d.z + coord3d.y * gridDim.z + coord3d.x * gridDim.z * gridDim.y; // note that we swap x and z because the texture is flipped around y
#if defined(dAxisOrder_012)
float group = coord3d.z + coord3d.y * gridDim.z + coord3d.x * gridDim.z * gridDim.y; // 210
#elif defined(dAxisOrder_021)
float group = coord3d.y + coord3d.z * gridDim.y + coord3d.x * gridDim.y * gridDim.z; // 120
#elif defined(dAxisOrder_102)
float group = coord3d.z + coord3d.x * gridDim.z + coord3d.y * gridDim.z * gridDim.x; // 201
#elif defined(dAxisOrder_120)
float group = coord3d.x + coord3d.z * gridDim.x + coord3d.y * gridDim.x * gridDim.z; // 021
#elif defined(dAxisOrder_201)
float group = coord3d.y + coord3d.x * gridDim.y + coord3d.z * gridDim.y * gridDim.x; // 102
#elif defined(dAxisOrder_210)
float group = coord3d.x + coord3d.y * gridDim.x + coord3d.z * gridDim.x * gridDim.y; // 012
#endif
gl_FragData[1] = vec4(group > 16777215.5 ? vec3(1.0) : encodeFloatRGB(group), 1.0); gl_FragData[1] = vec4(group > 16777215.5 ? vec3(1.0) : encodeFloatRGB(group), 1.0);
#endif #endif
#else #else
...@@ -265,7 +278,20 @@ void main(void) { ...@@ -265,7 +278,20 @@ void main(void) {
#else #else
vec3 b = t < 0.5 ? b0 : b1; vec3 b = t < 0.5 ? b0 : b1;
vec3 gridDim = uGridDim - vec3(1.0, 1.0, 0.0); // remove xy padding vec3 gridDim = uGridDim - vec3(1.0, 1.0, 0.0); // remove xy padding
float group = b.z + b.y * gridDim.z + b.x * gridDim.z * gridDim.y; // note that we swap x and z because the texture is flipped around y
#if defined(dAxisOrder_012)
float group = b.z + b.y * gridDim.z + b.x * gridDim.z * gridDim.y; // 210
#elif defined(dAxisOrder_021)
float group = b.y + b.z * gridDim.y + b.x * gridDim.y * gridDim.z; // 120
#elif defined(dAxisOrder_102)
float group = b.z + b.x * gridDim.z + b.y * gridDim.z * gridDim.x; // 201
#elif defined(dAxisOrder_120)
float group = b.x + b.z * gridDim.x + b.y * gridDim.x * gridDim.z; // 021
#elif defined(dAxisOrder_201)
float group = b.y + b.x * gridDim.y + b.z * gridDim.y * gridDim.x; // 102
#elif defined(dAxisOrder_210)
float group = b.x + b.y * gridDim.x + b.z * gridDim.x * gridDim.y; // 012
#endif
gl_FragData[1] = vec4(group > 16777215.5 ? vec3(1.0) : encodeFloatRGB(group), 1.0); gl_FragData[1] = vec4(group > 16777215.5 ? vec3(1.0) : encodeFloatRGB(group), 1.0);
#endif #endif
#endif #endif
......
...@@ -26,6 +26,7 @@ import { Texture } from '../../../mol-gl/webgl/texture'; ...@@ -26,6 +26,7 @@ import { Texture } from '../../../mol-gl/webgl/texture';
import { applyMeshColorSmoothing } from '../../../mol-geo/geometry/mesh/color-smoothing'; import { applyMeshColorSmoothing } from '../../../mol-geo/geometry/mesh/color-smoothing';
import { applyTextureMeshColorSmoothing } from '../../../mol-geo/geometry/texture-mesh/color-smoothing'; import { applyTextureMeshColorSmoothing } from '../../../mol-geo/geometry/texture-mesh/color-smoothing';
import { ColorSmoothingParams, getColorSmoothingProps } from '../../../mol-geo/geometry/base'; import { ColorSmoothingParams, getColorSmoothingProps } from '../../../mol-geo/geometry/base';
import { Vec3 } from '../../../mol-math/linear-algebra';
const SharedParams = { const SharedParams = {
...GaussianDensityParams, ...GaussianDensityParams,
...@@ -230,8 +231,9 @@ async function createGaussianSurfaceTextureMesh(ctx: VisualContext, unit: Unit, ...@@ -230,8 +231,9 @@ async function createGaussianSurfaceTextureMesh(ctx: VisualContext, unit: Unit,
const isoLevel = Math.exp(-props.smoothness) / densityTextureData.radiusFactor; const isoLevel = Math.exp(-props.smoothness) / densityTextureData.radiusFactor;
const axisOrder = Vec3.create(0, 1, 2);
const buffer = textureMesh?.doubleBuffer.get(); const buffer = textureMesh?.doubleBuffer.get();
const gv = extractIsosurface(ctx.webgl, densityTextureData.texture, densityTextureData.gridDim, densityTextureData.gridTexDim, densityTextureData.gridTexScale, densityTextureData.transform, isoLevel, false, true, 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, buffer?.vertex, buffer?.group, buffer?.normal);
const boundingSphere = Sphere3D.expand(Sphere3D(), unit.boundary.sphere, props.radiusOffset + getStructureExtraRadius(structure)); const boundingSphere = Sphere3D.expand(Sphere3D(), unit.boundary.sphere, props.radiusOffset + getStructureExtraRadius(structure));
const surface = TextureMesh.create(gv.vertexCount, 1, gv.vertexTexture, gv.groupTexture, gv.normalTexture, boundingSphere, textureMesh); const surface = TextureMesh.create(gv.vertexCount, 1, gv.vertexTexture, gv.groupTexture, gv.normalTexture, boundingSphere, textureMesh);
...@@ -306,8 +308,9 @@ async function createStructureGaussianSurfaceTextureMesh(ctx: VisualContext, str ...@@ -306,8 +308,9 @@ async function createStructureGaussianSurfaceTextureMesh(ctx: VisualContext, str
const isoLevel = Math.exp(-props.smoothness) / densityTextureData.radiusFactor; const isoLevel = Math.exp(-props.smoothness) / densityTextureData.radiusFactor;
const axisOrder = Vec3.create(0, 1, 2);
const buffer = textureMesh?.doubleBuffer.get(); const buffer = textureMesh?.doubleBuffer.get();
const gv = extractIsosurface(ctx.webgl, densityTextureData.texture, densityTextureData.gridDim, densityTextureData.gridTexDim, densityTextureData.gridTexScale, densityTextureData.transform, isoLevel, false, true, 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, buffer?.vertex, buffer?.group, buffer?.normal);
const boundingSphere = Sphere3D.expand(Sphere3D(), structure.boundary.sphere, props.radiusOffset + getStructureExtraRadius(structure)); const boundingSphere = Sphere3D.expand(Sphere3D(), structure.boundary.sphere, props.radiusOffset + getStructureExtraRadius(structure));
const surface = TextureMesh.create(gv.vertexCount, 1, gv.vertexTexture, gv.groupTexture, gv.normalTexture, boundingSphere, textureMesh); const surface = TextureMesh.create(gv.vertexCount, 1, gv.vertexTexture, gv.groupTexture, gv.normalTexture, boundingSphere, textureMesh);
......
...@@ -183,8 +183,9 @@ async function createVolumeIsosurfaceTextureMesh(ctx: VisualContext, volume: Vol ...@@ -183,8 +183,9 @@ async function createVolumeIsosurfaceTextureMesh(ctx: VisualContext, volume: Vol
const { texture, gridDimension, gridTexDim, gridTexScale, transform } = VolumeIsosurfaceTexture.get(volume, ctx.webgl); const { texture, gridDimension, gridTexDim, gridTexScale, transform } = VolumeIsosurfaceTexture.get(volume, ctx.webgl);
const axisOrder = volume.grid.cells.space.axisOrderSlowToFast as Vec3;
const buffer = textureMesh?.doubleBuffer.get(); const buffer = textureMesh?.doubleBuffer.get();
const gv = extractIsosurface(ctx.webgl, texture, gridDimension, gridTexDim, gridTexScale, transform, isoLevel, value < 0, false, buffer?.vertex, buffer?.group, buffer?.normal); const gv = extractIsosurface(ctx.webgl, texture, gridDimension, gridTexDim, gridTexScale, transform, isoLevel, value < 0, false, axisOrder, buffer?.vertex, buffer?.group, buffer?.normal);
const surface = TextureMesh.create(gv.vertexCount, 1, gv.vertexTexture, gv.groupTexture, gv.normalTexture, Volume.getBoundingSphere(volume), textureMesh); const surface = TextureMesh.create(gv.vertexCount, 1, gv.vertexTexture, gv.groupTexture, gv.normalTexture, Volume.getBoundingSphere(volume), textureMesh);
......
...@@ -73,7 +73,7 @@ async function init() { ...@@ -73,7 +73,7 @@ async function init() {
console.timeEnd('gpu mc pyramid2'); console.timeEnd('gpu mc pyramid2');
console.time('gpu mc vert2'); console.time('gpu mc vert2');
createIsosurfaceBuffers(webgl, activeVoxelsTex2, densityTextureData2.texture, compacted2, densityTextureData2.gridDim, densityTextureData2.gridTexDim, densityTextureData2.transform, isoValue, false, true); createIsosurfaceBuffers(webgl, activeVoxelsTex2, densityTextureData2.texture, compacted2, densityTextureData2.gridDim, densityTextureData2.gridTexDim, densityTextureData2.transform, isoValue, false, true, Vec3.create(0, 1, 2));
webgl.waitForGpuCommandsCompleteSync(); webgl.waitForGpuCommandsCompleteSync();
console.timeEnd('gpu mc vert2'); console.timeEnd('gpu mc vert2');
console.timeEnd('gpu mc2'); console.timeEnd('gpu mc2');
...@@ -96,7 +96,7 @@ async function init() { ...@@ -96,7 +96,7 @@ async function init() {
console.timeEnd('gpu mc pyramid'); console.timeEnd('gpu mc pyramid');
console.time('gpu mc vert'); console.time('gpu mc vert');
const gv = createIsosurfaceBuffers(webgl, activeVoxelsTex, densityTextureData.texture, compacted, densityTextureData.gridDim, densityTextureData.gridTexDim, densityTextureData.transform, isoValue, false, true); const gv = createIsosurfaceBuffers(webgl, activeVoxelsTex, densityTextureData.texture, compacted, densityTextureData.gridDim, densityTextureData.gridTexDim, densityTextureData.transform, isoValue, false, true, Vec3.create(0, 1, 2));
webgl.waitForGpuCommandsCompleteSync(); webgl.waitForGpuCommandsCompleteSync();
console.timeEnd('gpu mc vert'); console.timeEnd('gpu mc vert');
console.timeEnd('gpu mc'); console.timeEnd('gpu mc');
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment