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

basic transparency

parent 82f4e964
Branches
Tags
No related merge requests found
...@@ -40,8 +40,8 @@ export type ColorTheme = keyof typeof ColorTheme ...@@ -40,8 +40,8 @@ export type ColorTheme = keyof typeof ColorTheme
export default class State { export default class State {
viewer: Viewer viewer: Viewer
pdbId = '' pdbId = '5ire'
emdId = '8689' emdId = '8116'
model = new BehaviorSubject<Model | undefined>(undefined) model = new BehaviorSubject<Model | undefined>(undefined)
volume = new BehaviorSubject<Volume | undefined>(undefined) volume = new BehaviorSubject<Volume | undefined>(undefined)
initialized = new BehaviorSubject<boolean>(false) initialized = new BehaviorSubject<boolean>(false)
...@@ -115,7 +115,8 @@ export default class State { ...@@ -115,7 +115,8 @@ export default class State {
const { viewer } = this const { viewer } = this
if (!viewer || !this.model.getValue()) return if (!viewer || !this.model.getValue()) return
viewer.clear() if (this.pointRepr) this.viewer.remove(this.pointRepr)
if (this.spacefillRepr) this.viewer.remove(this.spacefillRepr)
const structure = await this.getStructure() const structure = await this.getStructure()
if (!structure) return if (!structure) return
...@@ -150,7 +151,7 @@ export default class State { ...@@ -150,7 +151,7 @@ export default class State {
const v = this.volume.getValue() const v = this.volume.getValue()
if (!viewer || !v) return if (!viewer || !v) return
viewer.clear() if (this.surfaceRepr) this.viewer.remove(this.surfaceRepr)
this.surfaceRepr = VolumeRepresentation(Surface) this.surfaceRepr = VolumeRepresentation(Surface)
await Run(this.surfaceRepr.create(v.volume, { isoValue: VolumeIsoValue.relative(v.volume.dataStats, 1.5) }), log, 500) await Run(this.surfaceRepr.create(v.volume, { isoValue: VolumeIsoValue.relative(v.volume.dataStats, 1.5) }), log, 500)
...@@ -161,7 +162,8 @@ export default class State { ...@@ -161,7 +162,8 @@ export default class State {
} }
async loadPdbId () { async loadPdbId () {
this.viewer.clear() if (this.pointRepr) this.viewer.remove(this.pointRepr)
if (this.spacefillRepr) this.viewer.remove(this.spacefillRepr)
if (this.pdbId.length !== 4) return if (this.pdbId.length !== 4) return
this.loading.next(true) this.loading.next(true)
this.setModel((await getModelFromPdbId(this.pdbId))[0]) this.setModel((await getModelFromPdbId(this.pdbId))[0])
...@@ -174,7 +176,7 @@ export default class State { ...@@ -174,7 +176,7 @@ export default class State {
} }
async loadEmdId () { async loadEmdId () {
this.viewer.clear() if (this.surfaceRepr) this.viewer.remove(this.surfaceRepr)
if (this.emdId.length !== 4) return if (this.emdId.length !== 4) return
this.loading.next(true) this.loading.next(true)
this.setVolume(await getVolumeFromEmdId(this.emdId)) this.setVolume(await getVolumeFromEmdId(this.emdId))
......
...@@ -19,7 +19,8 @@ import { deepEqual } from 'mol-util'; ...@@ -19,7 +19,8 @@ import { deepEqual } from 'mol-util';
export const DefaultPointProps = { export const DefaultPointProps = {
colorTheme: { name: 'instance-index' } as ColorTheme, colorTheme: { name: 'instance-index' } as ColorTheme,
sizeTheme: { name: 'vdw' } as SizeTheme sizeTheme: { name: 'vdw' } as SizeTheme,
alpha: 1
} }
export type PointProps = Partial<typeof DefaultPointProps> export type PointProps = Partial<typeof DefaultPointProps>
...@@ -59,7 +60,7 @@ export default function Point(): UnitsRepresentation<PointProps> { ...@@ -59,7 +60,7 @@ export default function Point(): UnitsRepresentation<PointProps> {
_units = units _units = units
_elementGroup = elementGroup _elementGroup = elementGroup
const { colorTheme, sizeTheme } = curProps const { colorTheme, sizeTheme, alpha } = curProps
const elementCount = OrderedSet.size(elementGroup.elements) const elementCount = OrderedSet.size(elementGroup.elements)
const unitCount = units.length const unitCount = units.length
...@@ -84,6 +85,7 @@ export default function Point(): UnitsRepresentation<PointProps> { ...@@ -84,6 +85,7 @@ export default function Point(): UnitsRepresentation<PointProps> {
points = createPointRenderObject({ points = createPointRenderObject({
objectId: 0, objectId: 0,
alpha,
position: ValueCell.create(vertices), position: ValueCell.create(vertices),
id: ValueCell.create(fillSerial(new Float32Array(elementCount))), id: ValueCell.create(fillSerial(new Float32Array(elementCount))),
......
...@@ -23,6 +23,7 @@ import { icosahedronVertexCount } from '../../primitive/icosahedron'; ...@@ -23,6 +23,7 @@ import { icosahedronVertexCount } from '../../primitive/icosahedron';
export const DefaultSpacefillProps = { export const DefaultSpacefillProps = {
detail: 0, detail: 0,
colorTheme: { name: 'instance-index' } as ColorTheme, colorTheme: { name: 'instance-index' } as ColorTheme,
alpha: 1
} }
export type SpacefillProps = Partial<typeof DefaultSpacefillProps> export type SpacefillProps = Partial<typeof DefaultSpacefillProps>
...@@ -78,7 +79,7 @@ export default function Spacefill(): UnitsRepresentation<SpacefillProps> { ...@@ -78,7 +79,7 @@ export default function Spacefill(): UnitsRepresentation<SpacefillProps> {
return Task.create('Spacefill.create', async ctx => { return Task.create('Spacefill.create', async ctx => {
renderObjects.length = 0 // clear renderObjects.length = 0 // clear
const { detail, colorTheme } = { ...DefaultSpacefillProps, ...props } const { detail, colorTheme, alpha } = { ...DefaultSpacefillProps, ...props }
await ctx.update('Computing spacefill mesh'); await ctx.update('Computing spacefill mesh');
const mesh = await ctx.runChild(createSpacefillMesh(units[0], elementGroup, detail)) const mesh = await ctx.runChild(createSpacefillMesh(units[0], elementGroup, detail))
...@@ -94,6 +95,7 @@ export default function Spacefill(): UnitsRepresentation<SpacefillProps> { ...@@ -94,6 +95,7 @@ export default function Spacefill(): UnitsRepresentation<SpacefillProps> {
spheres = createMeshRenderObject({ spheres = createMeshRenderObject({
objectId: 0, objectId: 0,
alpha,
position: mesh.vertexBuffer, position: mesh.vertexBuffer,
normal: mesh.normalBuffer as ValueCell<Float32Array>, normal: mesh.normalBuffer as ValueCell<Float32Array>,
......
...@@ -34,7 +34,8 @@ export function computeVolumeSurface(volume: VolumeData, isoValue: VolumeIsoValu ...@@ -34,7 +34,8 @@ export function computeVolumeSurface(volume: VolumeData, isoValue: VolumeIsoValu
} }
export const DefaultSurfaceProps = { export const DefaultSurfaceProps = {
isoValue: VolumeIsoValue.relative({ min: 0, max: 0, mean: 0, sigma: 0 }, 0) isoValue: VolumeIsoValue.relative({ min: 0, max: 0, mean: 0, sigma: 0 }, 0),
alpha: 0.5
} }
export type SurfaceProps = Partial<typeof DefaultSurfaceProps> export type SurfaceProps = Partial<typeof DefaultSurfaceProps>
...@@ -49,11 +50,13 @@ export default function Surface(): VolumeElementRepresentation<SurfaceProps> { ...@@ -49,11 +50,13 @@ export default function Surface(): VolumeElementRepresentation<SurfaceProps> {
return Task.create('Point.create', async ctx => { return Task.create('Point.create', async ctx => {
renderObjects.length = 0 // clear renderObjects.length = 0 // clear
curProps = { ...DefaultSurfaceProps, ...props } curProps = { ...DefaultSurfaceProps, ...props }
const { alpha } = curProps
const mesh = await ctx.runChild(computeVolumeSurface(volume, curProps.isoValue)) const mesh = await ctx.runChild(computeVolumeSurface(volume, curProps.isoValue))
surface = createMeshRenderObject({ surface = createMeshRenderObject({
objectId: 0, objectId: 0,
alpha,
position: mesh.vertexBuffer, position: mesh.vertexBuffer,
normal: mesh.normalBuffer, normal: mesh.normalBuffer,
......
...@@ -50,6 +50,7 @@ function createPoints() { ...@@ -50,6 +50,7 @@ function createPoints() {
return createPointRenderObject({ return createPointRenderObject({
objectId: 0, objectId: 0,
alpha: 1.0,
position, position,
id, id,
......
...@@ -18,6 +18,7 @@ type Mesh = 'mesh' ...@@ -18,6 +18,7 @@ type Mesh = 'mesh'
namespace Mesh { namespace Mesh {
export type Props = { export type Props = {
objectId: number objectId: number
alpha: number
position: ValueCell<Float32Array> position: ValueCell<Float32Array>
normal: ValueCell<Float32Array | undefined> normal: ValueCell<Float32Array | undefined>
......
...@@ -19,6 +19,7 @@ type Point = 'point' ...@@ -19,6 +19,7 @@ type Point = 'point'
namespace Point { namespace Point {
export type Props = { export type Props = {
objectId: number objectId: number
alpha: number
position: ValueCell<Float32Array> position: ValueCell<Float32Array>
id: ValueCell<Float32Array> id: ValueCell<Float32Array>
......
...@@ -65,6 +65,7 @@ interface BaseProps { ...@@ -65,6 +65,7 @@ interface BaseProps {
instanceCount: number, instanceCount: number,
elementCount: number, elementCount: number,
positionCount: number, positionCount: number,
alpha: number,
position: ValueCell<Float32Array> position: ValueCell<Float32Array>
normal?: ValueCell<Float32Array | undefined> normal?: ValueCell<Float32Array | undefined>
...@@ -87,6 +88,7 @@ export function getBaseUniformDefs(props: BaseProps) { ...@@ -87,6 +88,7 @@ export function getBaseUniformDefs(props: BaseProps) {
// light_position: 'v3', // light_position: 'v3',
light_color: 'v3', light_color: 'v3',
light_ambient: 'v3', light_ambient: 'v3',
alpha: 'f',
objectId: 'i', objectId: 'i',
instanceCount: 'i', instanceCount: 'i',
...@@ -107,9 +109,9 @@ export function getBaseUniformDefs(props: BaseProps) { ...@@ -107,9 +109,9 @@ export function getBaseUniformDefs(props: BaseProps) {
} }
export function getBaseUniformValues(props: BaseProps) { export function getBaseUniformValues(props: BaseProps) {
const { objectId, instanceCount, elementCount } = props const { objectId, instanceCount, elementCount, alpha } = props
const uniformValues: UniformValues = { const uniformValues: UniformValues = {
objectId, instanceCount, elementCount objectId, instanceCount, elementCount, alpha
} }
const color = props.color const color = props.color
if (color.type === 'instance' || color.type === 'element' || color.type === 'element-instance') { if (color.type === 'instance' || color.type === 'element' || color.type === 'element-instance') {
......
...@@ -11,6 +11,8 @@ import { Camera } from 'mol-view/camera/base'; ...@@ -11,6 +11,8 @@ import { Camera } from 'mol-view/camera/base';
import Scene, { RenderObject } from './scene'; import Scene, { RenderObject } from './scene';
import { Context } from './webgl/context'; import { Context } from './webgl/context';
import { Mat4, Vec3 } from 'mol-math/linear-algebra'; import { Mat4, Vec3 } from 'mol-math/linear-algebra';
import { Renderable } from './renderable';
import { Color } from 'mol-util/color';
export interface RendererStats { export interface RendererStats {
renderableCount: number renderableCount: number
...@@ -29,6 +31,7 @@ interface Renderer { ...@@ -29,6 +31,7 @@ interface Renderer {
draw: () => void draw: () => void
setViewport: (viewport: Viewport) => void setViewport: (viewport: Viewport) => void
setClearColor: (color: Color) => void
stats: RendererStats stats: RendererStats
dispose: () => void dispose: () => void
...@@ -38,27 +41,34 @@ function getPixelRatio() { ...@@ -38,27 +41,34 @@ function getPixelRatio() {
return (typeof window !== 'undefined') ? window.devicePixelRatio : 1 return (typeof window !== 'undefined') ? window.devicePixelRatio : 1
} }
export const DefaultRendererProps = {
clearColor: 0x000000 as Color,
viewport: Viewport.create(0, 0, 0, 0)
}
export type RendererProps = Partial<typeof DefaultRendererProps>
namespace Renderer { namespace Renderer {
export function create(ctx: Context, camera: Camera): Renderer { export function create(ctx: Context, camera: Camera, props: RendererProps = {}): Renderer {
const { gl } = ctx const { gl } = ctx
let { clearColor, viewport: _viewport } = { ...DefaultRendererProps, ...props }
const scene = Scene.create(ctx) const scene = Scene.create(ctx)
const model = Mat4.identity() const model = Mat4.identity()
const viewport = Viewport.create(0, 0, 0, 0) const viewport = Viewport.clone(_viewport)
const pixelRatio = getPixelRatio() const pixelRatio = getPixelRatio()
// const light_position = Vec3.create(0, 0, -100) // const light_position = Vec3.create(0, 0, -100)
const light_color = Vec3.create(1.0, 1.0, 1.0) const light_color = Vec3.create(1.0, 1.0, 1.0)
const light_ambient = Vec3.create(0.5, 0.5, 0.5) const light_ambient = Vec3.create(0.5, 0.5, 0.5)
const draw = () => { function setClearColor(color: Color) {
// TODO clear color const [ r, g, b ] = Color.toRgbNormalized(color)
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT) gl.clearColor(r, g, b, 1.0)
gl.enable(gl.DEPTH_TEST) }
setClearColor(clearColor)
// TODO painters sort, filter visible, filter picking, visibility culling?
let currentProgramId = -1 let currentProgramId = -1
scene.forEach((r, o) => { const drawObject = (r: Renderable<any>, o: RenderObject) => {
if (o.visible) { if (o.visible) {
if (currentProgramId !== r.program.id) { if (currentProgramId !== r.program.id) {
r.program.use() r.program.use()
...@@ -78,7 +88,22 @@ namespace Renderer { ...@@ -78,7 +88,22 @@ namespace Renderer {
} }
r.draw() r.draw()
} }
}) }
const draw = () => {
currentProgramId = -1
gl.depthMask(true)
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT)
gl.disable(gl.BLEND)
gl.enable(gl.DEPTH_TEST)
scene.eachOpaque(drawObject)
gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA)
gl.enable(gl.BLEND)
gl.depthMask(false)
scene.eachTransparent(drawObject)
} }
return { return {
...@@ -95,10 +120,13 @@ namespace Renderer { ...@@ -95,10 +120,13 @@ namespace Renderer {
scene.clear() scene.clear()
}, },
draw, draw,
setClearColor,
setViewport: (newViewport: Viewport) => { setViewport: (newViewport: Viewport) => {
Viewport.copy(viewport, newViewport) Viewport.copy(viewport, newViewport)
gl.viewport(viewport.x, viewport.y, viewport.width, viewport.height) gl.viewport(viewport.x, viewport.y, viewport.width, viewport.height)
}, },
get stats(): RendererStats { get stats(): RendererStats {
return { return {
renderableCount: scene.count, renderableCount: scene.count,
......
...@@ -16,16 +16,16 @@ function getNextId() { ...@@ -16,16 +16,16 @@ function getNextId() {
export type RenderData = { [k: string]: ValueCell<Helpers.TypedArray> } export type RenderData = { [k: string]: ValueCell<Helpers.TypedArray> }
export interface BaseRenderObject { id: number, type: string, props: {}, visible: boolean } export interface BaseRenderObject { id: number, type: string, props: {}, visible: boolean, transparent: boolean }
export interface MeshRenderObject extends BaseRenderObject { type: 'mesh', props: MeshRenderable.Props } export interface MeshRenderObject extends BaseRenderObject { type: 'mesh', props: MeshRenderable.Props }
export interface PointRenderObject extends BaseRenderObject { type: 'point', props: PointRenderable.Props } export interface PointRenderObject extends BaseRenderObject { type: 'point', props: PointRenderable.Props }
export type RenderObject = MeshRenderObject | PointRenderObject export type RenderObject = MeshRenderObject | PointRenderObject
export function createMeshRenderObject(props: MeshRenderable.Props): MeshRenderObject { export function createMeshRenderObject(props: MeshRenderable.Props): MeshRenderObject {
return { id: getNextId(), type: 'mesh', props, visible: true } return { id: getNextId(), type: 'mesh', props, visible: true, transparent: props.alpha < 1 }
} }
export function createPointRenderObject(props: PointRenderable.Props): PointRenderObject { export function createPointRenderObject(props: PointRenderable.Props): PointRenderObject {
return { id: getNextId(), type: 'point', props, visible: true } return { id: getNextId(), type: 'point', props, visible: true, transparent: props.alpha < 1 }
} }
export function createRenderable(ctx: Context, o: RenderObject) { export function createRenderable(ctx: Context, o: RenderObject) {
...@@ -40,6 +40,8 @@ interface Scene { ...@@ -40,6 +40,8 @@ interface Scene {
remove: (o: RenderObject) => void remove: (o: RenderObject) => void
clear: () => void clear: () => void
forEach: (callbackFn: (value: Renderable<any>, key: RenderObject) => void) => void forEach: (callbackFn: (value: Renderable<any>, key: RenderObject) => void) => void
eachOpaque: (callbackFn: (value: Renderable<any>, key: RenderObject) => void) => void
eachTransparent: (callbackFn: (value: Renderable<any>, key: RenderObject) => void) => void
count: number count: number
} }
...@@ -69,6 +71,16 @@ namespace Scene { ...@@ -69,6 +71,16 @@ namespace Scene {
forEach: (callbackFn: (value: Renderable<any>, key: RenderObject) => void) => { forEach: (callbackFn: (value: Renderable<any>, key: RenderObject) => void) => {
renderableMap.forEach(callbackFn) renderableMap.forEach(callbackFn)
}, },
eachOpaque: (callbackFn: (value: Renderable<any>, key: RenderObject) => void) => {
renderableMap.forEach((r, o) => {
if (!o.transparent) callbackFn(r, o)
})
},
eachTransparent: (callbackFn: (value: Renderable<any>, key: RenderObject) => void) => {
renderableMap.forEach((r, o) => {
if (o.transparent) callbackFn(r, o)
})
},
get count() { get count() {
return renderableMap.size return renderableMap.size
} }
......
...@@ -14,6 +14,7 @@ precision highp float; ...@@ -14,6 +14,7 @@ precision highp float;
uniform vec3 light_color; uniform vec3 light_color;
uniform vec3 light_ambient; uniform vec3 light_ambient;
uniform mat4 view; uniform mat4 view;
uniform float alpha;
#ifndef FLAT_SHADED #ifndef FLAT_SHADED
varying vec3 vNormal; varying vec3 vNormal;
...@@ -47,7 +48,7 @@ void main() { ...@@ -47,7 +48,7 @@ void main() {
#ifdef FLAT_SHADED #ifdef FLAT_SHADED
vec3 fdx = dFdx(vViewPosition); vec3 fdx = dFdx(vViewPosition);
vec3 fdy = dFdy(vViewPosition); vec3 fdy = dFdy(vViewPosition);
vec3 N = -normalize(cross(fdx, fdy)); vec3 N = normalize(cross(fdx, fdy));
#else #else
vec3 N = -normalize(vNormal); vec3 N = -normalize(vNormal);
#ifdef DOUBLE_SIDED #ifdef DOUBLE_SIDED
...@@ -66,5 +67,5 @@ void main() { ...@@ -66,5 +67,5 @@ void main() {
// gl_FragColor.rgb = N; // gl_FragColor.rgb = N;
// gl_FragColor.rgb = vec3(1.0, 0.0, 0.0); // gl_FragColor.rgb = vec3(1.0, 0.0, 0.0);
gl_FragColor.rgb = finalColor; gl_FragColor.rgb = finalColor;
gl_FragColor.a = 1.0; gl_FragColor.a = alpha;
} }
\ No newline at end of file
...@@ -6,9 +6,11 @@ ...@@ -6,9 +6,11 @@
precision highp float; precision highp float;
uniform float alpha;
#pragma glslify: import('./chunks/color-frag-params.glsl') #pragma glslify: import('./chunks/color-frag-params.glsl')
void main(){ void main(){
#pragma glslify: import('./chunks/color-assign-material.glsl') #pragma glslify: import('./chunks/color-assign-material.glsl')
gl_FragColor = vec4(material, 1.0); gl_FragColor = vec4(material, alpha);
} }
\ No newline at end of file
...@@ -64,7 +64,12 @@ namespace Viewer { ...@@ -64,7 +64,12 @@ namespace Viewer {
}) })
const gl = getWebGLContext(canvas) const gl = getWebGLContext(canvas, {
alpha: true,
antialias: true,
depth: true,
preserveDrawingBuffer: true
})
if (gl === null) { if (gl === null) {
throw new Error('Could not create a WebGL rendering context') throw new Error('Could not create a WebGL rendering context')
} }
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment