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