123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200 |
- /**
- * Copyright (c) 2019 mol* contributors, licensed under MIT, See LICENSE file for more info.
- *
- * @author Alexander Rose <alexander.rose@weirdbyte.de>
- */
- import { createComputeRenderable } from '../../renderable'
- import { WebGLContext } from '../../webgl/context';
- import { createComputeRenderItem } from '../../webgl/render-item';
- import { Values, TextureSpec, UniformSpec } from '../../renderable/schema';
- import { Texture, createTexture } from 'mol-gl/webgl/texture';
- import { ShaderCode } from 'mol-gl/shader-code';
- import { ValueCell } from 'mol-util';
- import { Vec3, Vec2, Mat4 } from 'mol-math/linear-algebra';
- import { QuadSchema, QuadValues } from '../util';
- import { HistogramPyramid } from '../histogram-pyramid/reduction';
- import { getTriIndices } from './tables';
- import quad_vert from 'mol-gl/shader/quad.vert'
- import isosurface_frag from 'mol-gl/shader/marching-cubes/isosurface.frag'
- /** name for shared framebuffer used for gpu marching cubes operations */
- const FramebufferName = 'marching-cubes-isosurface'
- const IsosurfaceSchema = {
- ...QuadSchema,
- tTriIndices: TextureSpec('image-uint8', 'alpha', 'ubyte', 'nearest'),
- tActiveVoxelsPyramid: TextureSpec('texture', 'rgba', 'float', 'nearest'),
- tActiveVoxelsBase: TextureSpec('texture', 'rgba', 'float', 'nearest'),
- tVolumeData: TextureSpec('texture', 'rgba', 'ubyte', 'nearest'),
- uIsoValue: UniformSpec('f'),
- uSize: UniformSpec('f'),
- uLevels: UniformSpec('f'),
- uCount: UniformSpec('f'),
- uGridDim: UniformSpec('v3'),
- uGridTexDim: UniformSpec('v3'),
- uGridTransform: UniformSpec('m4'),
- uScale: UniformSpec('v2'),
- }
- function getIsosurfaceRenderable(ctx: WebGLContext, activeVoxelsPyramid: Texture, activeVoxelsBase: Texture, volumeData: Texture, gridDim: Vec3, gridTexDim: Vec3, transform: Mat4, isoValue: number, levels: number, scale: Vec2, count: number, height: number) {
- // console.log('uSize', Math.pow(2, levels))
- const values: Values<typeof IsosurfaceSchema> = {
- ...QuadValues,
- uQuadScale: ValueCell.create(Vec2.create(1, height / Math.pow(2, levels))),
- tTriIndices: ValueCell.create(getTriIndices()),
- tActiveVoxelsPyramid: ValueCell.create(activeVoxelsPyramid),
- tActiveVoxelsBase: ValueCell.create(activeVoxelsBase),
- tVolumeData: ValueCell.create(volumeData),
- uIsoValue: ValueCell.create(isoValue),
- uSize: ValueCell.create(Math.pow(2, levels)),
- uLevels: ValueCell.create(levels),
- uCount: ValueCell.create(count),
- uGridDim: ValueCell.create(gridDim),
- uGridTexDim: ValueCell.create(gridTexDim),
- uGridTransform: ValueCell.create(transform),
- uScale: ValueCell.create(scale),
- }
- const schema = { ...IsosurfaceSchema }
- const shaderCode = ShaderCode(quad_vert, isosurface_frag, { drawBuffers: true })
- const renderItem = createComputeRenderItem(ctx, 'triangles', shaderCode, schema, values)
- return createComputeRenderable(renderItem, values);
- }
- function setRenderingDefaults(ctx: WebGLContext) {
- const { gl, state } = ctx
- state.disable(gl.CULL_FACE)
- state.disable(gl.BLEND)
- state.disable(gl.DEPTH_TEST)
- state.disable(gl.SCISSOR_TEST)
- state.depthMask(false)
- state.colorMask(true, true, true, true)
- 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, vertexGroupTexture?: Texture, normalTexture?: Texture) {
- const { gl, framebufferCache } = ctx
- const { pyramidTex, height, levels, scale, count } = histogramPyramid
- // console.log('iso', 'gridDim', gridDim, 'scale', scale, 'gridTexDim', gridTexDim)
- // console.log('iso volumeData', volumeData)
- const framebuffer = framebufferCache.get(FramebufferName).value
- let needsClear = false
- if (!vertexGroupTexture) {
- vertexGroupTexture = createTexture(ctx, 'image-float32', 'rgba', 'float', 'nearest')
- vertexGroupTexture.define(pyramidTex.width, pyramidTex.height)
- } else if (vertexGroupTexture.width !== pyramidTex.width || vertexGroupTexture.height !== pyramidTex.height) {
- vertexGroupTexture.define(pyramidTex.width, pyramidTex.height)
- } else {
- needsClear = true
- }
- if (!normalTexture) {
- normalTexture = createTexture(ctx, 'image-float32', 'rgba', 'float', 'nearest')
- normalTexture.define(pyramidTex.width, pyramidTex.height)
- } else if (normalTexture.width !== pyramidTex.width || normalTexture.height !== pyramidTex.height) {
- normalTexture.define(pyramidTex.width, pyramidTex.height)
- } else {
- needsClear = true
- }
- // const infoTex = createTexture(ctx, 'image-float32', 'rgba', 'float', 'nearest')
- // infoTex.define(pyramidTex.width, pyramidTex.height)
- // const pointTexA = createTexture(ctx, 'image-float32', 'rgba', 'float', 'nearest')
- // pointTexA.define(pyramidTex.width, pyramidTex.height)
- // const pointTexB = createTexture(ctx, 'image-float32', 'rgba', 'float', 'nearest')
- // pointTexB.define(pyramidTex.width, pyramidTex.height)
- // const coordTex = createTexture(ctx, 'image-float32', 'rgba', 'float', 'nearest')
- // coordTex.define(pyramidTex.width, pyramidTex.height)
- // const indexTex = createTexture(ctx, 'image-float32', 'rgba', 'float', 'nearest')
- // indexTex.define(pyramidTex.width, pyramidTex.height)
- const renderable = getIsosurfaceRenderable(ctx, pyramidTex, activeVoxelsBase, volumeData, gridDim, gridTexDim, transform, isoValue, levels, scale, count, height)
- ctx.state.currentRenderItemId = -1
- vertexGroupTexture.attachFramebuffer(framebuffer, 0)
- normalTexture.attachFramebuffer(framebuffer, 1)
- // infoTex.attachFramebuffer(framebuffer, 1)
- // pointTexA.attachFramebuffer(framebuffer, 2)
- // pointTexB.attachFramebuffer(framebuffer, 3)
- // coordTex.attachFramebuffer(framebuffer, 4)
- // indexTex.attachFramebuffer(framebuffer, 5)
- const { drawBuffers } = ctx.extensions
- if (!drawBuffers) throw new Error('need WebGL draw buffers')
- drawBuffers.drawBuffers([
- drawBuffers.COLOR_ATTACHMENT0,
- drawBuffers.COLOR_ATTACHMENT1,
- // drawBuffers.COLOR_ATTACHMENT2,
- // drawBuffers.COLOR_ATTACHMENT3,
- // drawBuffers.COLOR_ATTACHMENT4,
- // drawBuffers.COLOR_ATTACHMENT5
- ])
- setRenderingDefaults(ctx)
- gl.viewport(0, 0, pyramidTex.width, pyramidTex.height)
- if (needsClear) gl.clear(gl.COLOR_BUFFER_BIT)
- renderable.render()
- gl.finish()
- // const vgt = readTexture(ctx, vertexGroupTexture, pyramidTex.width, height)
- // console.log('vertexGroupTexture', vgt.array.subarray(0, 4 * count))
- // const vt = readTexture(ctx, verticesTex, pyramidTex.width, height)
- // console.log('vt', vt)
- // const vertices = new Float32Array(3 * compacted.count)
- // for (let i = 0; i < compacted.count; ++i) {
- // vertices[i * 3] = vt.array[i * 4]
- // vertices[i * 3 + 1] = vt.array[i * 4 + 1]
- // vertices[i * 3 + 2] = vt.array[i * 4 + 2]
- // }
- // console.log('vertices', vertices)
- // const it = readTexture(ctx, infoTex, pyramidTex.width, height)
- // console.log('info', it.array.subarray(0, 4 * compacted.count))
- // const pat = readTexture(ctx, pointTexA, pyramidTex.width, height)
- // console.log('point a', pat.array.subarray(0, 4 * compacted.count))
- // const pbt = readTexture(ctx, pointTexB, pyramidTex.width, height)
- // console.log('point b', pbt.array.subarray(0, 4 * compacted.count))
- // const ct = readTexture(ctx, coordTex, pyramidTex.width, height)
- // console.log('coord', ct.array.subarray(0, 4 * compacted.count))
- // const idxt = readTexture(ctx, indexTex, pyramidTex.width, height)
- // console.log('index', idxt.array.subarray(0, 4 * compacted.count))
- // const { field, idField } = await fieldFromTexture2d(ctx, volumeData, gridDimensions)
- // console.log({ field, idField })
- // const valuesA = new Float32Array(compacted.count)
- // const valuesB = new Float32Array(compacted.count)
- // for (let i = 0; i < compacted.count; ++i) {
- // valuesA[i] = field.space.get(field.data, pat.array[i * 4], pat.array[i * 4 + 1], pat.array[i * 4 + 2])
- // valuesB[i] = field.space.get(field.data, pbt.array[i * 4], pbt.array[i * 4 + 1], pbt.array[i * 4 + 2])
- // }
- // console.log('valuesA', valuesA)
- // console.log('valuesB', valuesB)
- return { vertexGroupTexture, normalTexture, vertexCount: count }
- }
|