From f0f7060dfdb21c27fa90b13a4c52eb8f65c0b7d9 Mon Sep 17 00:00:00 2001 From: Alexander Rose <alex.rose@rcsb.org> Date: Mon, 15 Oct 2018 12:16:01 -0700 Subject: [PATCH] wip, mrt surface calc --- src/apps/canvas/index.ts | 2 +- src/apps/canvas/structure-view.ts | 2 +- src/mol-gl/shader/gaussian-density.frag | 32 +++-- src/mol-gl/webgl/program.ts | 7 +- src/mol-math/geometry/gaussian-density/gpu.ts | 122 ++++++++++-------- 5 files changed, 98 insertions(+), 67 deletions(-) diff --git a/src/apps/canvas/index.ts b/src/apps/canvas/index.ts index aa7a8ff5d..45b617685 100644 --- a/src/apps/canvas/index.ts +++ b/src/apps/canvas/index.ts @@ -23,4 +23,4 @@ const assemblyId = urlQueryParameter('assembly') const pdbId = urlQueryParameter('pdb') if (pdbId) app.loadPdbIdOrMmcifUrl(pdbId, { assemblyId }) -app.loadCcp4Url('http://localhost:8091/ngl/data/betaGal.mrc') \ No newline at end of file +// app.loadCcp4Url('http://localhost:8091/ngl/data/betaGal.mrc') \ No newline at end of file diff --git a/src/apps/canvas/structure-view.ts b/src/apps/canvas/structure-view.ts index 422487447..d13cae50b 100644 --- a/src/apps/canvas/structure-view.ts +++ b/src/apps/canvas/structure-view.ts @@ -70,7 +70,7 @@ export async function StructureView(app: App, viewer: Viewer, models: ReadonlyAr const active: { [k: string]: boolean } = { cartoon: true, point: false, - surface: false, + surface: true, ballAndStick: false, carbohydrate: false, spacefill: false, diff --git a/src/mol-gl/shader/gaussian-density.frag b/src/mol-gl/shader/gaussian-density.frag index 652b57980..ff0a48371 100644 --- a/src/mol-gl/shader/gaussian-density.frag +++ b/src/mol-gl/shader/gaussian-density.frag @@ -19,16 +19,17 @@ uniform float uCurrentX; uniform float uCurrentY; uniform float uAlpha; -// #if dDrawBuffers == 8 - // layout(location = 0) out vec4 out0; +#if dDrawBuffers >= 4 layout(location = 1) out vec4 out1; layout(location = 2) out vec4 out2; layout(location = 3) out vec4 out3; +#endif +#if dDrawBuffers >= 8 layout(location = 4) out vec4 out4; layout(location = 5) out vec4 out5; layout(location = 6) out vec4 out6; layout(location = 7) out vec4 out7; -// #endif +#endif float calcDensity(float x, float y, float z) { vec3 fragPos = vec3(x, y, z) / uGridDim; @@ -37,15 +38,20 @@ float calcDensity(float x, float y, float z) { return density; } +const vec3 color = vec3(1.0, 1.0, 1.0); + void main() { - vec2 tmpVec = gl_FragCoord.xy - vec2(uCurrentX, uCurrentY) - 0.5; - out_FragColor = vec4(1, 1, 1, calcDensity(tmpVec.x, tmpVec.y, uCurrentSlice + 0.0)); - out1 = vec4(1, 1, 1, calcDensity(tmpVec.x, tmpVec.y, uCurrentSlice + 1.0)); - out2 = vec4(1, 1, 1, calcDensity(tmpVec.x, tmpVec.y, uCurrentSlice + 2.0)); - out3 = vec4(1, 1, 1, calcDensity(tmpVec.x, tmpVec.y, uCurrentSlice + 3.0)); - out4 = vec4(1, 1, 1, calcDensity(tmpVec.x, tmpVec.y, uCurrentSlice + 4.0)); - out5 = vec4(1, 1, 1, calcDensity(tmpVec.x, tmpVec.y, uCurrentSlice + 5.0)); - out6 = vec4(1, 1, 1, calcDensity(tmpVec.x, tmpVec.y, uCurrentSlice + 6.0)); - out7 = vec4(1, 1, 1, calcDensity(tmpVec.x, tmpVec.y, uCurrentSlice + 7.0)); - // gl_FragColor = vec4(1, 1, 1, calcDensity(tmpVec.x, tmpVec.y, uCurrentSlice)); + vec2 v = gl_FragCoord.xy - vec2(uCurrentX, uCurrentY) - 0.5; + gl_FragColor = vec4(color, calcDensity(v.x, v.y, uCurrentSlice)); + #if dDrawBuffers >= 4 + out1 = vec4(color, calcDensity(v.x, v.y, uCurrentSlice + 1.0)); + out2 = vec4(color, calcDensity(v.x, v.y, uCurrentSlice + 2.0)); + out3 = vec4(color, calcDensity(v.x, v.y, uCurrentSlice + 3.0)); + #endif + #if dDrawBuffers >= 8 + out4 = vec4(color, calcDensity(v.x, v.y, uCurrentSlice + 4.0)); + out5 = vec4(color, calcDensity(v.x, v.y, uCurrentSlice + 5.0)); + out6 = vec4(color, calcDensity(v.x, v.y, uCurrentSlice + 6.0)); + out7 = vec4(color, calcDensity(v.x, v.y, uCurrentSlice + 7.0)); + #endif } \ No newline at end of file diff --git a/src/mol-gl/webgl/program.ts b/src/mol-gl/webgl/program.ts index 39a90f7c0..551f42abe 100644 --- a/src/mol-gl/webgl/program.ts +++ b/src/mol-gl/webgl/program.ts @@ -114,13 +114,18 @@ export function createProgram(ctx: Context, props: ProgramProps): Program { export type ProgramCache = ReferenceCache<Program, ProgramProps, Context> +function defineValueHash(v: boolean | number | string): number { + return typeof v === 'boolean' ? (v ? 1 : 0) : + typeof v === 'number' ? v : hashString(v) +} + export function createProgramCache(): ProgramCache { return createReferenceCache( (props: ProgramProps) => { const array = [ props.shaderCode.id ] Object.keys(props.defineValues).forEach(k => { const v = props.defineValues[k].ref.value - array.push(hashString(k), typeof v === 'boolean' ? v ? 1 : 0 : hashString(v)) + array.push(hashString(k), defineValueHash(v)) }) return hashFnv32a(array).toString() }, diff --git a/src/mol-math/geometry/gaussian-density/gpu.ts b/src/mol-math/geometry/gaussian-density/gpu.ts index 036baf03a..e10d12c21 100644 --- a/src/mol-math/geometry/gaussian-density/gpu.ts +++ b/src/mol-math/geometry/gaussian-density/gpu.ts @@ -72,7 +72,7 @@ async function prepareGaussianDensityData(ctx: RuntimeContext, position: Positio } } - + const pad = maxRadius * 2 + resolution const expandedBox = Box3D.expand(Box3D.empty(), box, Vec3.create(pad, pad, pad)); const extent = Vec3.sub(Vec3.zero(), expandedBox.max, expandedBox.min) @@ -85,7 +85,7 @@ async function prepareGaussianDensityData(ctx: RuntimeContext, position: Positio return { drawCount: n, positions, radii, delta, expandedBox, dim } } -function getGaussianDensityRenderObject(drawCount: number, positions: Float32Array, radii: Float32Array, box: Box3D, dimensions: Vec3, smoothness: number) { +function getGaussianDensityRenderObject(webgl: Context, drawCount: number, positions: Float32Array, radii: Float32Array, box: Box3D, dimensions: Vec3, smoothness: number) { const extent = Vec3.sub(Vec3.zero(), box.max, box.min) const values: GaussianDensityValues = { @@ -104,7 +104,7 @@ function getGaussianDensityRenderObject(drawCount: number, positions: Float32Arr uGridDim: ValueCell.create(dimensions), uAlpha: ValueCell.create(smoothness), - dDrawBuffers: ValueCell.create(0), + dDrawBuffers: ValueCell.create(Math.min(8, webgl.maxDrawBuffers)), } const state: RenderableState = { visible: true, @@ -120,7 +120,7 @@ async function GaussianDensitySingleDrawBuffer(ctx: RuntimeContext, webgl: Conte const { readSlices, smoothness } = props const { drawCount, positions, radii, delta, expandedBox, dim } = await prepareGaussianDensityData(ctx, position, box, radius, props) - const renderObject = getGaussianDensityRenderObject(drawCount, positions, radii, expandedBox, dim, smoothness) + const renderObject = getGaussianDensityRenderObject(webgl, drawCount, positions, radii, expandedBox, dim, smoothness) const renderable = createRenderable(webgl, renderObject) // @@ -166,11 +166,6 @@ async function GaussianDensitySingleDrawBuffer(ctx: RuntimeContext, webgl: Conte gl.frontFace(gl.CCW) gl.cullFace(gl.BACK) - gl.depthMask(true) - gl.clearColor(0, 0, 0, 0) - gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT) - gl.depthMask(false) - gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA) gl.blendEquation(gl.FUNC_ADD) gl.enable(gl.BLEND) @@ -245,8 +240,9 @@ async function GaussianDensityMultiDrawBuffer(ctx: RuntimeContext, webgl: Contex const { smoothness } = props const { drawCount, positions, radii, delta, expandedBox, dim } = await prepareGaussianDensityData(ctx, position, box, radius, props) - const renderObject = getGaussianDensityRenderObject(drawCount, positions, radii, expandedBox, dim, smoothness) + const renderObject = getGaussianDensityRenderObject(webgl, drawCount, positions, radii, expandedBox, dim, smoothness) const renderable = createRenderable(webgl, renderObject) + const drawBuffers = Math.min(8, webgl.maxDrawBuffers) // @@ -261,14 +257,9 @@ async function GaussianDensityMultiDrawBuffer(ctx: RuntimeContext, webgl: Contex // - console.log('webgl.maxDrawBuffers', webgl.maxDrawBuffers) - const gl = webgl.gl as WebGL2RenderingContext const { uCurrentSlice } = renderObject.values - const program = renderable.getProgram('draw') - const renderTarget = createRenderTarget(webgl, dx, dy) - const fb = gl.createFramebuffer() gl.bindFramebuffer(gl.FRAMEBUFFER, fb) @@ -278,62 +269,85 @@ async function GaussianDensityMultiDrawBuffer(ctx: RuntimeContext, webgl: Contex gl.texParameteri(gl.TEXTURE_3D, gl.TEXTURE_MAG_FILTER, gl.LINEAR) gl.texImage3D(gl.TEXTURE_3D, 0, gl.RGBA8, dx, dy, dz, 0, gl.RGBA, gl.UNSIGNED_BYTE, null) - gl.drawBuffers([ - gl.COLOR_ATTACHMENT0, - gl.COLOR_ATTACHMENT1, - gl.COLOR_ATTACHMENT2, - gl.COLOR_ATTACHMENT3, - gl.COLOR_ATTACHMENT4, - gl.COLOR_ATTACHMENT5, - gl.COLOR_ATTACHMENT6, - gl.COLOR_ATTACHMENT7, - ]); + if (drawBuffers === 1) { + gl.drawBuffers([ + gl.COLOR_ATTACHMENT0, + ]); + } else if (drawBuffers === 4) { + gl.drawBuffers([ + gl.COLOR_ATTACHMENT0, gl.COLOR_ATTACHMENT1, gl.COLOR_ATTACHMENT2, gl.COLOR_ATTACHMENT3, + ]); + } else if (drawBuffers === 8) { + gl.drawBuffers([ + gl.COLOR_ATTACHMENT0, gl.COLOR_ATTACHMENT1, gl.COLOR_ATTACHMENT2, gl.COLOR_ATTACHMENT3, + gl.COLOR_ATTACHMENT4, gl.COLOR_ATTACHMENT5, gl.COLOR_ATTACHMENT6, gl.COLOR_ATTACHMENT7, + ]); + } - program.use() gl.viewport(0, 0, dx, dy) - // renderTarget.bind() - gl.disable(gl.CULL_FACE) gl.frontFace(gl.CCW) gl.cullFace(gl.BACK) - gl.depthMask(true) - gl.clearColor(0, 0, 0, 0) - gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT) - gl.depthMask(false) - gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA) gl.blendEquation(gl.FUNC_ADD) gl.enable(gl.BLEND) const slice = new Uint8Array(dx * dy * 4) - const dzFactor = Math.floor(dz / webgl.maxDrawBuffers) - const dzFull = dzFactor * webgl.maxDrawBuffers - const dzRest = dz - dzFull - console.log(dz, webgl.maxDrawBuffers, dzFull, dzRest) + // - console.time('gpu gaussian density 3d texture slices') - let j = 0 - for (let i = 0; i < dz; i += 8) { + const dzMulti = Math.floor(dz / drawBuffers) * drawBuffers + + const programMulti = renderable.getProgram('draw') + programMulti.use() + + console.time('gpu gaussian density 3d texture slices multi') + for (let i = 0; i < dzMulti; i += drawBuffers) { ValueCell.update(uCurrentSlice, i) - for (let k = 0; k < webgl.maxDrawBuffers && k + i < dz; ++k) { + for (let k = 0; k < drawBuffers; ++k) { gl.framebufferTextureLayer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0 + k, tex, 0, i + k) } renderable.render('draw') - for (let k = 0; k < webgl.maxDrawBuffers && k + i < dz; ++k) { - gl.readBuffer(gl.COLOR_ATTACHMENT0 + k); - gl.readPixels(0, 0, dx, dy, gl.RGBA, gl.UNSIGNED_BYTE, slice) - for (let iy = 0; iy < dim[1]; ++iy) { - for (let ix = 0; ix < dim[0]; ++ix) { - data[j] = slice[4 * (iy * dim[0] + ix)] / 255 - ++j - } + } + console.timeEnd('gpu gaussian density 3d texture slices multi') + + ValueCell.updateIfChanged(renderable.values.dDrawBuffers, 1) + renderable.update() + const programSingle = renderable.getProgram('draw') + programSingle.use() + + console.time('gpu gaussian density 3d texture slices single') + for (let i = dzMulti; i < dz; ++i) { + ValueCell.update(uCurrentSlice, i) + gl.framebufferTextureLayer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, tex, 0, i) + renderable.render('draw') + } + console.timeEnd('gpu gaussian density 3d texture slices single') + + console.time('gpu gaussian density 3d texture slices read') + // Must unset framebufferTextureLayer attachments before reading + for (let k = 0; k < drawBuffers; ++k) { + gl.framebufferTextureLayer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0 + k, null, 0, 0) + } + + let j = 0 + for (let i = 0; i < dz; ++i) { + gl.framebufferTextureLayer(gl.READ_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, tex, 0, i) + gl.readBuffer(gl.COLOR_ATTACHMENT0) + gl.readPixels(0, 0, dx, dy, gl.RGBA, gl.UNSIGNED_BYTE, slice) + for (let iy = 0; iy < dim[1]; ++iy) { + for (let ix = 0; ix < dim[0]; ++ix) { + data[j] = slice[4 * (iy * dim[0] + ix)] / 255 + ++j } } } - console.timeEnd('gpu gaussian density 3d texture slices') + console.timeEnd('gpu gaussian density 3d texture slices read') + + // clean up + gl.bindFramebuffer(gl.FRAMEBUFFER, null) // @@ -341,5 +355,11 @@ async function GaussianDensityMultiDrawBuffer(ctx: RuntimeContext, webgl: Contex Mat4.fromScaling(transform, Vec3.inverse(Vec3.zero(), delta)) Mat4.setTranslation(transform, expandedBox.min) + // throw new Error('foo') + + const renderTarget = createRenderTarget(webgl, dx, dy) + return { field, idField, transform, renderTarget, bbox: expandedBox, gridDimension: dim } -} \ No newline at end of file +} + +// const wait = (ms: number) => new Promise(r => setTimeout(r, ms)) \ No newline at end of file -- GitLab