|
@@ -14,6 +14,42 @@ import { Camera } from '../camera';
|
|
import { CameraHelper, CameraHelperParams } from '../helper/camera-helper';
|
|
import { CameraHelper, CameraHelperParams } from '../helper/camera-helper';
|
|
import { ParamDefinition as PD } from '../../mol-util/param-definition';
|
|
import { ParamDefinition as PD } from '../../mol-util/param-definition';
|
|
import { HandleHelper } from '../helper/handle-helper';
|
|
import { HandleHelper } from '../helper/handle-helper';
|
|
|
|
+import { QuadSchema, QuadValues } from '../../mol-gl/compute/util';
|
|
|
|
+import { DefineSpec, TextureSpec, UniformSpec, Values } from '../../mol-gl/renderable/schema';
|
|
|
|
+import { ComputeRenderable, createComputeRenderable } from '../../mol-gl/renderable';
|
|
|
|
+import { ShaderCode } from '../../mol-gl/shader-code';
|
|
|
|
+import { createComputeRenderItem } from '../../mol-gl/webgl/render-item';
|
|
|
|
+import { ValueCell } from '../../mol-util';
|
|
|
|
+import { Vec2 } from '../../mol-math/linear-algebra';
|
|
|
|
+
|
|
|
|
+import quad_vert from '../../mol-gl/shader/quad.vert';
|
|
|
|
+import depthMerge_frag from '../../mol-gl/shader/depth-merge.frag';
|
|
|
|
+
|
|
|
|
+const DepthMergeSchema = {
|
|
|
|
+ ...QuadSchema,
|
|
|
|
+ tDepthPrimitives: TextureSpec('texture', 'depth', 'ushort', 'nearest'),
|
|
|
|
+ tDepthVolumes: TextureSpec('texture', 'depth', 'ushort', 'nearest'),
|
|
|
|
+ uTexSize: UniformSpec('v2'),
|
|
|
|
+ dPackedDepth: DefineSpec('boolean'),
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+type DepthMergeRenderable = ComputeRenderable<Values<typeof DepthMergeSchema>>
|
|
|
|
+
|
|
|
|
+function getDepthMergeRenderable(ctx: WebGLContext, depthTexturePrimitives: Texture, depthTextureVolumes: Texture, packedDepth: boolean): DepthMergeRenderable {
|
|
|
|
+ const values: Values<typeof DepthMergeSchema> = {
|
|
|
|
+ ...QuadValues,
|
|
|
|
+ tDepthPrimitives: ValueCell.create(depthTexturePrimitives),
|
|
|
|
+ tDepthVolumes: ValueCell.create(depthTextureVolumes),
|
|
|
|
+ uTexSize: ValueCell.create(Vec2.create(depthTexturePrimitives.getWidth(), depthTexturePrimitives.getHeight())),
|
|
|
|
+ dPackedDepth: ValueCell.create(packedDepth),
|
|
|
|
+ };
|
|
|
|
+
|
|
|
|
+ const schema = { ...DepthMergeSchema };
|
|
|
|
+ const shaderCode = ShaderCode('depth-merge', quad_vert, depthMerge_frag);
|
|
|
|
+ const renderItem = createComputeRenderItem(ctx, 'triangles', shaderCode, schema, values);
|
|
|
|
+
|
|
|
|
+ return createComputeRenderable(renderItem, values);
|
|
|
|
+}
|
|
|
|
|
|
export const DrawPassParams = {
|
|
export const DrawPassParams = {
|
|
cameraHelper: PD.Group(CameraHelperParams)
|
|
cameraHelper: PD.Group(CameraHelperParams)
|
|
@@ -28,7 +64,12 @@ export class DrawPass {
|
|
|
|
|
|
cameraHelper: CameraHelper
|
|
cameraHelper: CameraHelper
|
|
|
|
|
|
- private depthTarget: RenderTarget | null
|
|
|
|
|
|
+ private depthTarget: RenderTarget
|
|
|
|
+ private depthTargetPrimitives: RenderTarget | null
|
|
|
|
+ private depthTargetVolumes: RenderTarget | null
|
|
|
|
+ private depthTexturePrimitives: Texture
|
|
|
|
+ private depthTextureVolumes: Texture
|
|
|
|
+ private depthMerge: DepthMergeRenderable
|
|
|
|
|
|
constructor(private webgl: WebGLContext, private renderer: Renderer, private scene: Scene, private camera: Camera, private debugHelper: BoundingSphereHelper, private handleHelper: HandleHelper, props: Partial<DrawPassProps> = {}) {
|
|
constructor(private webgl: WebGLContext, private renderer: Renderer, private scene: Scene, private camera: Camera, private debugHelper: BoundingSphereHelper, private handleHelper: HandleHelper, props: Partial<DrawPassProps> = {}) {
|
|
const { gl, extensions, resources } = webgl;
|
|
const { gl, extensions, resources } = webgl;
|
|
@@ -36,12 +77,20 @@ export class DrawPass {
|
|
const height = gl.drawingBufferHeight;
|
|
const height = gl.drawingBufferHeight;
|
|
this.colorTarget = webgl.createRenderTarget(width, height);
|
|
this.colorTarget = webgl.createRenderTarget(width, height);
|
|
this.packedDepth = !extensions.depthTexture;
|
|
this.packedDepth = !extensions.depthTexture;
|
|
- this.depthTarget = this.packedDepth ? webgl.createRenderTarget(width, height) : null;
|
|
|
|
- this.depthTexture = this.depthTarget ? this.depthTarget.texture : resources.texture('image-depth', 'depth', 'ushort', 'nearest');
|
|
|
|
|
|
+
|
|
|
|
+ this.depthTarget = webgl.createRenderTarget(width, height);
|
|
|
|
+ this.depthTexture = this.depthTarget.texture;
|
|
|
|
+
|
|
|
|
+ this.depthTargetPrimitives = this.packedDepth ? webgl.createRenderTarget(width, height) : null;
|
|
|
|
+ this.depthTargetVolumes = this.packedDepth ? webgl.createRenderTarget(width, height) : null;
|
|
|
|
+
|
|
|
|
+ this.depthTexturePrimitives = this.depthTargetPrimitives ? this.depthTargetPrimitives.texture : resources.texture('image-depth', 'depth', 'ushort', 'nearest');
|
|
|
|
+ this.depthTextureVolumes = this.depthTargetVolumes ? this.depthTargetVolumes.texture : resources.texture('image-depth', 'depth', 'ushort', 'nearest');
|
|
if (!this.packedDepth) {
|
|
if (!this.packedDepth) {
|
|
- this.depthTexture.define(width, height);
|
|
|
|
- this.depthTexture.attachFramebuffer(this.colorTarget.framebuffer, 'depth');
|
|
|
|
|
|
+ this.depthTexturePrimitives.define(width, height);
|
|
|
|
+ this.depthTextureVolumes.define(width, height);
|
|
}
|
|
}
|
|
|
|
+ this.depthMerge = getDepthMergeRenderable(webgl, this.depthTexturePrimitives, this.depthTextureVolumes, this.packedDepth);
|
|
|
|
|
|
const p = { ...DefaultDrawPassProps, ...props };
|
|
const p = { ...DefaultDrawPassProps, ...props };
|
|
this.cameraHelper = new CameraHelper(webgl, p.cameraHelper);
|
|
this.cameraHelper = new CameraHelper(webgl, p.cameraHelper);
|
|
@@ -49,11 +98,21 @@ export class DrawPass {
|
|
|
|
|
|
setSize(width: number, height: number) {
|
|
setSize(width: number, height: number) {
|
|
this.colorTarget.setSize(width, height);
|
|
this.colorTarget.setSize(width, height);
|
|
- if (this.depthTarget) {
|
|
|
|
- this.depthTarget.setSize(width, height);
|
|
|
|
|
|
+ this.depthTarget.setSize(width, height);
|
|
|
|
+
|
|
|
|
+ if (this.depthTargetPrimitives) {
|
|
|
|
+ this.depthTargetPrimitives.setSize(width, height);
|
|
|
|
+ } else {
|
|
|
|
+ this.depthTexturePrimitives.define(width, height);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (this.depthTargetVolumes) {
|
|
|
|
+ this.depthTargetVolumes.setSize(width, height);
|
|
} else {
|
|
} else {
|
|
- this.depthTexture.define(width, height);
|
|
|
|
|
|
+ this.depthTextureVolumes.define(width, height);
|
|
}
|
|
}
|
|
|
|
+
|
|
|
|
+ ValueCell.update(this.depthMerge.values.uTexSize, Vec2.set(this.depthMerge.values.uTexSize.ref.value, width, height));
|
|
}
|
|
}
|
|
|
|
|
|
setProps(props: Partial<DrawPassProps>) {
|
|
setProps(props: Partial<DrawPassProps>) {
|
|
@@ -67,41 +126,67 @@ export class DrawPass {
|
|
}
|
|
}
|
|
|
|
|
|
render(toDrawingBuffer: boolean, transparentBackground: boolean) {
|
|
render(toDrawingBuffer: boolean, transparentBackground: boolean) {
|
|
- const { webgl, renderer, colorTarget, depthTarget } = this;
|
|
|
|
if (toDrawingBuffer) {
|
|
if (toDrawingBuffer) {
|
|
- webgl.unbindFramebuffer();
|
|
|
|
|
|
+ this.webgl.unbindFramebuffer();
|
|
} else {
|
|
} else {
|
|
- colorTarget.bind();
|
|
|
|
|
|
+ this.colorTarget.bind();
|
|
if (!this.packedDepth) {
|
|
if (!this.packedDepth) {
|
|
- // TODO unlcear why it is not enough to call `attachFramebuffer` in `Texture.reset`
|
|
|
|
- this.depthTexture.attachFramebuffer(this.colorTarget.framebuffer, 'depth');
|
|
|
|
|
|
+ this.depthTexturePrimitives.attachFramebuffer(this.colorTarget.framebuffer, 'depth');
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
- renderer.setViewport(0, 0, colorTarget.getWidth(), colorTarget.getHeight());
|
|
|
|
- this.renderInternal('color', transparentBackground);
|
|
|
|
|
|
+ this.renderer.setViewport(0, 0, this.colorTarget.getWidth(), this.colorTarget.getHeight());
|
|
|
|
+ this.renderer.render(this.scene.primitives, this.camera, 'color', true, transparentBackground, null);
|
|
|
|
|
|
// do a depth pass if not rendering to drawing buffer and
|
|
// do a depth pass if not rendering to drawing buffer and
|
|
// extensions.depthTexture is unsupported (i.e. depthTarget is set)
|
|
// extensions.depthTexture is unsupported (i.e. depthTarget is set)
|
|
- if (!toDrawingBuffer && depthTarget) {
|
|
|
|
- depthTarget.bind();
|
|
|
|
- this.renderInternal('depth', transparentBackground);
|
|
|
|
|
|
+ if (!toDrawingBuffer && this.depthTargetPrimitives) {
|
|
|
|
+ this.depthTargetPrimitives.bind();
|
|
|
|
+ this.renderer.render(this.scene.primitives, this.camera, 'depth', true, transparentBackground, null);
|
|
|
|
+ this.colorTarget.bind();
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // do direct-volume rendering
|
|
|
|
+ if (!toDrawingBuffer && this.scene.volumes.renderables.length > 0) {
|
|
|
|
+ if (!this.packedDepth) {
|
|
|
|
+ this.depthTextureVolumes.attachFramebuffer(this.colorTarget.framebuffer, 'depth');
|
|
|
|
+ this.webgl.state.depthMask(true);
|
|
|
|
+ this.webgl.gl.clear(this.webgl.gl.DEPTH_BUFFER_BIT);
|
|
|
|
+ }
|
|
|
|
+ this.renderer.render(this.scene.volumes, this.camera, 'color', false, transparentBackground, this.depthTexturePrimitives);
|
|
|
|
+
|
|
|
|
+ // do volume depth pass if extensions.depthTexture is unsupported (i.e. depthTarget is set)
|
|
|
|
+ if (this.depthTargetVolumes) {
|
|
|
|
+ this.depthTargetVolumes.bind();
|
|
|
|
+ this.renderer.render(this.scene.volumes, this.camera, 'depth', false, transparentBackground, this.depthTexturePrimitives);
|
|
|
|
+ this.colorTarget.bind();
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // merge depths from primitive and volume rendering
|
|
|
|
+ if (!toDrawingBuffer) {
|
|
|
|
+ this.depthMerge.update();
|
|
|
|
+ this.depthTarget.bind();
|
|
|
|
+ this.webgl.state.disable(this.webgl.gl.SCISSOR_TEST);
|
|
|
|
+ this.webgl.state.disable(this.webgl.gl.BLEND);
|
|
|
|
+ this.webgl.state.disable(this.webgl.gl.DEPTH_TEST);
|
|
|
|
+ this.webgl.state.depthMask(false);
|
|
|
|
+ this.webgl.state.clearColor(1, 1, 1, 1);
|
|
|
|
+ this.webgl.gl.clear(this.webgl.gl.COLOR_BUFFER_BIT);
|
|
|
|
+ this.depthMerge.render();
|
|
|
|
+ this.colorTarget.bind();
|
|
}
|
|
}
|
|
- }
|
|
|
|
|
|
|
|
- private renderInternal(variant: 'color' | 'depth', transparentBackground: boolean) {
|
|
|
|
- const { renderer, scene, camera, debugHelper, cameraHelper, handleHelper } = this;
|
|
|
|
- renderer.render(scene, camera, variant, true, transparentBackground);
|
|
|
|
- if (debugHelper.isEnabled) {
|
|
|
|
- debugHelper.syncVisibility();
|
|
|
|
- renderer.render(debugHelper.scene, camera, variant, false, transparentBackground);
|
|
|
|
|
|
+ if (this.debugHelper.isEnabled) {
|
|
|
|
+ this.debugHelper.syncVisibility();
|
|
|
|
+ this.renderer.render(this.debugHelper.scene, this.camera, 'color', false, transparentBackground, null);
|
|
}
|
|
}
|
|
- if (handleHelper.isEnabled) {
|
|
|
|
- renderer.render(handleHelper.scene, camera, variant, false, transparentBackground);
|
|
|
|
|
|
+ if (this.handleHelper.isEnabled) {
|
|
|
|
+ this.renderer.render(this.handleHelper.scene, this.camera, 'color', false, transparentBackground, null);
|
|
}
|
|
}
|
|
- if (cameraHelper.isEnabled) {
|
|
|
|
- cameraHelper.update(camera);
|
|
|
|
- renderer.render(cameraHelper.scene, cameraHelper.camera, variant, false, transparentBackground);
|
|
|
|
|
|
+ if (this.cameraHelper.isEnabled) {
|
|
|
|
+ this.cameraHelper.update(this.camera);
|
|
|
|
+ this.renderer.render(this.cameraHelper.scene, this.cameraHelper.camera, 'color', false, transparentBackground, null);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|