Browse Source

wip, geo data from texture, mc normals

Alexander Rose 6 years ago
parent
commit
a71f192a8a

+ 17 - 18
src/mol-geo/geometry/isosurface/isosurface.ts

@@ -31,27 +31,24 @@ export interface Isosurface {
     /** Number of groups in the isosurface */
     readonly groupCount: ValueCell<number>,
 
+    readonly geoTextureDim: ValueCell<Vec2>,
     readonly vertexTexture: ValueCell<Texture>,
-    readonly vertexTextureDim: ValueCell<Vec2>,
-
-    /** Normal buffer as array of xyz values for each vertex wrapped in a value cell */
-    readonly normalBuffer: ValueCell<Float32Array>,
-    /** Group buffer as array of group ids for each vertex wrapped in a value cell */
-    readonly groupBuffer: ValueCell<Float32Array>,
+    readonly normalTexture: ValueCell<Texture>,
+    readonly groupTexture: ValueCell<Texture>,
 
     readonly boundingSphere: ValueCell<Sphere3D>,
 }
 
 export namespace Isosurface {
-    export function create(vertexCount: number, groupCount: number, vertexTexture: Texture, normalBuffer: Float32Array, groupBuffer: Float32Array, boundingSphere: Sphere3D, isosurface?: Isosurface): Isosurface {
+    export function create(vertexCount: number, groupCount: number, vertexTexture: Texture, normalTexture: Texture, groupTexture: Texture, boundingSphere: Sphere3D, isosurface?: Isosurface): Isosurface {
         const { width, height } = vertexTexture
         if (isosurface) {
             ValueCell.update(isosurface.vertexCount, vertexCount)
             ValueCell.update(isosurface.groupCount, groupCount)
+            ValueCell.update(isosurface.geoTextureDim, Vec2.set(isosurface.geoTextureDim.ref.value, width, height))
             ValueCell.update(isosurface.vertexTexture, vertexTexture)
-            ValueCell.update(isosurface.vertexTextureDim, Vec2.set(isosurface.vertexTextureDim.ref.value, width, height))
-            ValueCell.update(isosurface.normalBuffer, normalBuffer)
-            ValueCell.update(isosurface.groupBuffer, groupBuffer)
+            ValueCell.update(isosurface.normalTexture, normalTexture)
+            ValueCell.update(isosurface.groupTexture, groupTexture)
             ValueCell.update(isosurface.boundingSphere, boundingSphere)
             return isosurface
         } else {
@@ -59,10 +56,10 @@ export namespace Isosurface {
                 kind: 'isosurface',
                 vertexCount: ValueCell.create(vertexCount),
                 groupCount: ValueCell.create(groupCount),
+                geoTextureDim: ValueCell.create(Vec2.create(width, height)),
                 vertexTexture: ValueCell.create(vertexTexture),
-                vertexTextureDim: ValueCell.create(Vec2.create(width, height)),
-                normalBuffer: ValueCell.create(normalBuffer),
-                groupBuffer: ValueCell.create(groupBuffer),
+                normalTexture: ValueCell.create(normalTexture),
+                groupTexture: ValueCell.create(groupTexture),
                 boundingSphere: ValueCell.create(boundingSphere),
             }
         }
@@ -103,11 +100,13 @@ export namespace Isosurface {
         const transformBoundingSphere = calculateTransformBoundingSphere(isosurface.boundingSphere.ref.value, transform.aTransform.ref.value, transform.instanceCount.ref.value)
 
         return {
+            uGeoTexDim: isosurface.geoTextureDim,
             tPosition: isosurface.vertexTexture,
-            uPositionTexDim: isosurface.vertexTextureDim,
-            aIndex: ValueCell.create(fillSerial(new Float32Array(isosurface.vertexCount.ref.value))),
-            aNormal: isosurface.normalBuffer,
-            aGroup: isosurface.groupBuffer,
+            tNormal: isosurface.normalTexture,
+            tGroup: isosurface.groupTexture,
+
+            // aGroup is used as a triangle index here and the group id is retirieved from the tGroup texture
+            aGroup: ValueCell.create(fillSerial(new Float32Array(isosurface.vertexCount.ref.value))),
             boundingSphere: ValueCell.create(transformBoundingSphere),
             invariantBoundingSphere: isosurface.boundingSphere,
 
@@ -121,7 +120,7 @@ export namespace Isosurface {
             dDoubleSided: ValueCell.create(props.doubleSided),
             dFlatShaded: ValueCell.create(props.flatShaded),
             dFlipSided: ValueCell.create(props.flipSided),
-            dPositionTexture: ValueCell.create(true),
+            dGeoTexture: ValueCell.create(true),
         }
     }
 

+ 1 - 1
src/mol-gl/compute/histogram-pyramid/reduction.ts

@@ -134,7 +134,7 @@ export function createHistogramPyramid(ctx: WebGLContext, inputTexture: Texture)
         offset += size;
     }
 
-    printTexture(ctx, pyramidTexture, 3)
+    // printTexture(ctx, pyramidTexture, 3)
 
     //
 

+ 21 - 18
src/mol-gl/compute/marching-cubes/isosurface.ts

@@ -87,8 +87,14 @@ export function createIsosurfaceBuffers(ctx: WebGLContext, activeVoxelsBase: Tex
     const framebuffer = framebufferCache.get(FramebufferName).value
     framebuffer.bind()
 
-    const verticesTex = createTexture(ctx, 'image-float32', 'rgba', 'float', 'nearest')
-    verticesTex.define(pyramidTex.width, pyramidTex.height)
+    const vertexTexture = createTexture(ctx, 'image-float32', 'rgba', 'float', 'nearest')
+    vertexTexture.define(pyramidTex.width, pyramidTex.height)
+
+    const normalTexture = createTexture(ctx, 'image-float32', 'rgba', 'float', 'nearest')
+    normalTexture.define(pyramidTex.width, pyramidTex.height)
+
+    const groupTexture = createTexture(ctx, 'image-float32', 'rgba', 'float', 'nearest')
+    groupTexture.define(pyramidTex.width, pyramidTex.height)
 
     // const infoTex = createTexture(ctx, 'image-float32', 'rgba', 'float', 'nearest')
     // infoTex.define(pyramidTex.width, pyramidTex.height)
@@ -109,24 +115,25 @@ export function createIsosurfaceBuffers(ctx: WebGLContext, activeVoxelsBase: Tex
     pr.update()
     pr.use()
 
-    verticesTex.attachFramebuffer(framebuffer, 0)
+    vertexTexture.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 draw buffers')
+    const { drawBuffers } = ctx.extensions
+    if (!drawBuffers) throw new Error('need draw buffers')
 
-    // drawBuffers.drawBuffers([
-    //     drawBuffers.COLOR_ATTACHMENT0,
-    //     drawBuffers.COLOR_ATTACHMENT1,
-    //     drawBuffers.COLOR_ATTACHMENT2,
-    //     drawBuffers.COLOR_ATTACHMENT3,
-    //     drawBuffers.COLOR_ATTACHMENT4,
-    //     drawBuffers.COLOR_ATTACHMENT5
-    // ])
+    drawBuffers.drawBuffers([
+        drawBuffers.COLOR_ATTACHMENT0,
+        drawBuffers.COLOR_ATTACHMENT1,
+        // drawBuffers.COLOR_ATTACHMENT2,
+        // drawBuffers.COLOR_ATTACHMENT3,
+        // drawBuffers.COLOR_ATTACHMENT4,
+        // drawBuffers.COLOR_ATTACHMENT5
+    ])
 
     setRenderingDefaults(gl)
     gl.viewport(0, 0, pyramidTex.width, pyramidTex.height)
@@ -171,9 +178,5 @@ export function createIsosurfaceBuffers(ctx: WebGLContext, activeVoxelsBase: Tex
     // console.log('valuesA', valuesA)
     // console.log('valuesB', valuesB)
 
-    const vertexTexture = verticesTex
-    const normalBuffer = new Float32Array(count * 3)
-    const groupBuffer = new Float32Array(count)
-
-    return { vertexTexture, normalBuffer, groupBuffer, vertexCount: count }
+    return { vertexTexture, normalTexture, groupTexture, vertexCount: count }
 }

+ 5 - 6
src/mol-gl/renderable/isosurface.ts

@@ -7,23 +7,22 @@
 import { Renderable, RenderableState, createRenderable } from '../renderable'
 import { WebGLContext } from '../webgl/context';
 import { createGraphicsRenderItem } from '../webgl/render-item';
-import { GlobalUniformSchema, BaseSchema, AttributeSpec, DefineSpec, Values, InternalSchema, InternalValues, UniformSpec, TextureSpec } from './schema';
+import { GlobalUniformSchema, BaseSchema, DefineSpec, Values, InternalSchema, InternalValues, UniformSpec, TextureSpec } from './schema';
 import { MeshShaderCode } from '../shader-code';
 import { ValueCell } from 'mol-util';
 
 export const IsosurfaceSchema = {
     ...BaseSchema,
 
-    aIndex: AttributeSpec('float32', 1, 0),
-    aNormal: AttributeSpec('float32', 3, 0),
-
-    uPositionTexDim: UniformSpec('v2'),
+    uGeoTexDim: UniformSpec('v2'),
     tPosition: TextureSpec('texture', 'rgba', 'float', 'nearest'),
+    tNormal: TextureSpec('texture', 'rgba', 'float', 'nearest'),
+    tGroup: TextureSpec('texture', 'rgba', 'float', 'nearest'),
 
     dFlatShaded: DefineSpec('boolean'),
     dDoubleSided: DefineSpec('boolean'),
     dFlipSided: DefineSpec('boolean'),
-    dPositionTexture: DefineSpec('boolean'),
+    dGeoTexture: DefineSpec('boolean'),
 }
 export type IsosurfaceSchema = typeof IsosurfaceSchema
 export type IsosurfaceValues = Values<IsosurfaceSchema>

+ 6 - 6
src/mol-gl/shader/chunks/assign-color-varying.glsl

@@ -3,22 +3,22 @@
 #elif defined(dColorType_instance)
     vColor.rgb = readFromTexture(tColor, aInstance, uColorTexDim).rgb;
 #elif defined(dColorType_group)
-    vColor.rgb = readFromTexture(tColor, aGroup, uColorTexDim).rgb;
+    vColor.rgb = readFromTexture(tColor, group, uColorTexDim).rgb;
 #elif defined(dColorType_groupInstance)
-    vColor.rgb = readFromTexture(tColor, aInstance * float(uGroupCount) + aGroup, uColorTexDim).rgb;
+    vColor.rgb = readFromTexture(tColor, aInstance * float(uGroupCount) + group, uColorTexDim).rgb;
 #elif defined(dColorType_objectPicking)
     vColor = vec4(encodeFloatRGB(float(uObjectId)), 1.0);
 #elif defined(dColorType_instancePicking)
     vColor = vec4(encodeFloatRGB(aInstance), 1.0);
 #elif defined(dColorType_groupPicking)
-    vColor = vec4(encodeFloatRGB(aGroup), 1.0);
+    vColor = vec4(encodeFloatRGB(group), 1.0);
 #endif
 
 #ifdef dOverpaint
-    vOverpaint = readFromTexture(tOverpaint, aInstance * float(uGroupCount) + aGroup, uOverpaintTexDim);
+    vOverpaint = readFromTexture(tOverpaint, aInstance * float(uGroupCount) + group, uOverpaintTexDim);
 #endif
 
 #ifdef dTransparency
-    vGroup = aGroup;
-    vTransparency = readFromTexture(tTransparency, aInstance * float(uGroupCount) + aGroup, uTransparencyTexDim).a;
+    vGroup = group;
+    vTransparency = readFromTexture(tTransparency, aInstance * float(uGroupCount) + group, uTransparencyTexDim).a;
 #endif

+ 6 - 0
src/mol-gl/shader/chunks/assign-group.glsl

@@ -0,0 +1,6 @@
+#ifdef dGeoTexture
+    // aGroup is used as a triangle index here and the group id is retirieved from the tGroup texture
+    float group = readFromTexture(tGroup, aGroup, uGeoTexDim).a;
+#else
+    float group = aGroup;
+#endif

+ 1 - 1
src/mol-gl/shader/chunks/assign-marker-varying.glsl

@@ -1 +1 @@
-vMarker = readFromTexture(tMarker, aInstance * float(uGroupCount) + aGroup, uMarkerTexDim).a;
+vMarker = readFromTexture(tMarker, aInstance * float(uGroupCount) + group, uMarkerTexDim).a;

+ 2 - 2
src/mol-gl/shader/chunks/assign-position.glsl

@@ -1,6 +1,6 @@
 mat4 modelView = uView * uModel * aTransform;
-#ifdef dPositionTexture
-    vec3 position = readFromTexture(tPosition, aIndex, uPositionTexDim).xyz;
+#ifdef dGeoTexture
+    vec3 position = readFromTexture(tPosition, aGroup, uGeoTexDim).xyz;
 #else
     vec3 position = aPosition;
 #endif

+ 2 - 2
src/mol-gl/shader/chunks/assign-size.glsl

@@ -5,9 +5,9 @@
 #elif defined(dSizeType_instance)
     float size = readFromTexture(tSize, aInstance, uSizeTexDim).a;
 #elif defined(dSizeType_group)
-    float size = readFromTexture(tSize, aGroup, uSizeTexDim).a;
+    float size = readFromTexture(tSize, group, uSizeTexDim).a;
 #elif defined(dSizeType_groupInstance)
-    float size = readFromTexture(tSize, aInstance * float(uGroupCount) + aGroup, uSizeTexDim).a;
+    float size = readFromTexture(tSize, aInstance * float(uGroupCount) + group, uSizeTexDim).a;
 #endif
 
 #if defined(dSizeType_instance) || defined(dSizeType_group) || defined(dSizeType_groupInstance)

+ 1 - 0
src/mol-gl/shader/lines.vert

@@ -36,6 +36,7 @@ void trimSegment(const in vec4 start, inout vec4 end) {
 }
 
 void main(){
+    #pragma glslify: import('./chunks/assign-group.glsl')
     #pragma glslify: import('./chunks/assign-color-varying.glsl')
     #pragma glslify: import('./chunks/assign-marker-varying.glsl')
     #pragma glslify: import('./chunks/assign-size.glsl')

+ 2 - 1
src/mol-gl/shader/marching-cubes/active-voxels.frag

@@ -37,7 +37,8 @@ vec4 texture3dFrom2dNearest(sampler2D tex, vec3 pos, vec3 gridDim, vec2 texDim)
     float column = intMod(zSlice * gridDim.x, texDim.x) / gridDim.x;
     float row = floor(intDiv(zSlice * gridDim.x, texDim.x));
     vec2 coord = (vec2(column * gridDim.x, row * gridDim.y) + (pos.xy * gridDim.xy)) / texDim;
-    return texture2D(tex, coord + 0.5 / texDim);
+    // return texture2D(tex, coord + 0.5 / texDim);
+    return texture2D(tex, coord);
 }
 
 vec4 voxel(vec3 pos) {

+ 21 - 3
src/mol-gl/shader/marching-cubes/isosurface.frag

@@ -30,6 +30,8 @@ const vec3 c5 = vec3(1., 0., 1.);
 const vec3 c6 = vec3(1., 1., 1.);
 const vec3 c7 = vec3(0., 1., 1.);
 
+const float EPS = 0.00001;
+
 vec3 index3dFrom2d(vec2 coord) {
     vec2 gridTexPos = coord * uGridTexDim.xy;
     vec2 columnRow = floor(gridTexPos / uGridDim.xy);
@@ -174,10 +176,26 @@ void main(void) {
     // b0 = floor(b0 + 0.5);
     // b1 = floor(b1 + 0.5);
 
-    float v0 = voxel(b0 / uGridDim).a;
-    float v1 = voxel(b1 / uGridDim).a;
+    float d0 = voxel(b0 / uGridDim);
+    float d1 = voxel(b1 / uGridDim);
+
+    float v0 = d0.a;
+    float v1 = d1.a;
 
     float t = (uIsoValue - v0) / (v0 - v1);
-    t = -0.5;
+    // t = -0.5;
     gl_FragColor.xyz = b0 + t * (b0 - b1);
+
+    // normals from gradients
+    vec3 n0 = -normalize(vec3(
+        v0 - voxel((b0 + c1) / uGridDim).a,
+        v0 - voxel((b0 + c3) / uGridDim).a,
+        v0 - voxel((b0 + c4) / uGridDim).a
+    ));
+    vec3 n1 = -normalize(vec3(
+        v1 - voxel((b1 + c1) / uGridDim).a,
+        v1 - voxel((b1 + c3) / uGridDim).a,
+        v1 - voxel((b1 + c4) / uGridDim).a
+    ));
+    gl_FragData[1].xyz = -normalize((v0 * n0 + v1 * n1) / max(v0 + v1, EPS));
 }

+ 15 - 5
src/mol-gl/shader/mesh.vert

@@ -10,10 +10,10 @@ precision highp int;
 #pragma glslify: import('./chunks/common-vert-params.glsl')
 #pragma glslify: import('./chunks/color-vert-params.glsl')
 
-#ifdef dPositionTexture
-    attribute float aIndex;
-    uniform vec2 uPositionTexDim;
+#ifdef dGeoTexture
+    uniform vec2 uGeoTexDim;
     uniform sampler2D tPosition;
+    uniform sampler2D tGroup;
 #else
     attribute vec3 aPosition;
 #endif
@@ -22,18 +22,28 @@ attribute float aInstance;
 attribute float aGroup;
 
 #ifndef dFlatShaded
-    attribute vec3 aNormal;
+    #ifdef dGeoTexture
+        uniform sampler2D tNormal;
+    #else
+        attribute vec3 aNormal;
+    #endif
     varying vec3 vNormal;
 #endif
 
 void main(){
+    #pragma glslify: import('./chunks/assign-group.glsl')
     #pragma glslify: import('./chunks/assign-color-varying.glsl')
     #pragma glslify: import('./chunks/assign-marker-varying.glsl')
     #pragma glslify: import('./chunks/assign-position.glsl')
 
     #ifndef dFlatShaded
+        #ifdef dGeoTexture
+            vec3 normal = readFromTexture(tNormal, aGroup, uGeoTexDim).xyz;
+        #else
+            vec3 normal = aNormal;
+        #endif
         mat3 normalMatrix = transpose(inverse(mat3(modelView)));
-        vec3 transformedNormal = normalize(normalMatrix * normalize(aNormal));
+        vec3 transformedNormal = normalize(normalMatrix * normalize(normal));
         #if defined(dFlipSided) && !defined(dDoubleSided) // TODO checking dDoubleSided should not be required, ASR
             transformedNormal = -transformedNormal;
         #endif

+ 1 - 0
src/mol-gl/shader/points.vert

@@ -20,6 +20,7 @@ attribute float aInstance;
 attribute float aGroup;
 
 void main(){
+    #pragma glslify: import('./chunks/assign-group.glsl')
     #pragma glslify: import('./chunks/assign-color-varying.glsl')
     #pragma glslify: import('./chunks/assign-marker-varying.glsl')
     #pragma glslify: import('./chunks/assign-position.glsl')

+ 1 - 0
src/mol-gl/shader/spheres.vert

@@ -86,6 +86,7 @@ void quadraticProjection(const in float radius, const in vec3 position){
 
 
 void main(void){
+    #pragma glslify: import('./chunks/assign-group.glsl')
     #pragma glslify: import('./chunks/assign-color-varying.glsl')
     #pragma glslify: import('./chunks/assign-marker-varying.glsl')
     #pragma glslify: import('./chunks/assign-size.glsl')

+ 1 - 0
src/mol-gl/shader/text.vert

@@ -34,6 +34,7 @@ varying vec2 vTexCoord;
 #pragma glslify: matrixScale = require(./utils/matrix-scale.glsl)
 
 void main(void){
+    #pragma glslify: import('./chunks/assign-group.glsl')
     #pragma glslify: import('./chunks/assign-color-varying.glsl')
     #pragma glslify: import('./chunks/assign-marker-varying.glsl')
     #pragma glslify: import('./chunks/assign-size.glsl')

+ 6 - 5
src/tests/browser/marching-cubes.ts

@@ -61,8 +61,6 @@ async function init() {
     }
     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()
@@ -109,8 +107,11 @@ async function init() {
 
     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 mcBoundingSphere = Sphere3D.zero()
+    Sphere3D.addVec3(mcBoundingSphere, mcBoundingSphere, densityTextureData.gridDimension)
+    console.log('mcBoundingSphere', mcBoundingSphere, densityTextureData.gridDimension)
+    const mcIsosurface = Isosurface.create(gv.vertexCount, 1, gv.vertexTexture, gv.normalTexture, gv.groupTexture, mcBoundingSphere)
+    const mcIsoSurfaceProps = { doubleSided: true, flatShaded: false, alpha: 1.0 }
     const mcIsoSurfaceValues = Isosurface.Utils.createValuesSimple(mcIsosurface, mcIsoSurfaceProps, Color(0x112299), 1)
     // console.log('mcIsoSurfaceValues', mcIsoSurfaceValues)
     const mcIsoSurfaceState = Isosurface.Utils.createRenderableState(mcIsoSurfaceProps)
@@ -138,7 +139,7 @@ async function init() {
     console.timeEnd('cpu mc')
     // console.log('surface', surface)
     Mesh.computeNormalsImmediate(surface)
-    const meshProps = { doubleSided: true, flatShaded: true, alpha: 0.1 }
+    const meshProps = { doubleSided: true, flatShaded: false, 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)