|
@@ -4,123 +4,36 @@
|
|
|
* @author Alexander Rose <alexander.rose@weirdbyte.de>
|
|
|
*/
|
|
|
|
|
|
-import REGL = require('regl');
|
|
|
-import * as glContext from './context'
|
|
|
-import { PerspectiveCamera } from './camera/perspective'
|
|
|
-import { PointRenderable, MeshRenderable, Renderable } from './renderable'
|
|
|
-import Stats from './stats'
|
|
|
-
|
|
|
import { Vec3, Mat4 } from 'mol-math/linear-algebra'
|
|
|
-import { ValueCell } from 'mol-util';
|
|
|
-import TrackballControls from './controls/trackball';
|
|
|
-import { Viewport } from './camera/util';
|
|
|
-
|
|
|
-let _renderObjectId = 0;
|
|
|
-function getNextId() {
|
|
|
- return _renderObjectId++ % 0x7FFFFFFF;
|
|
|
-}
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-export interface RenderUpdateInfo {
|
|
|
-
|
|
|
-}
|
|
|
-
|
|
|
-export type RenderData = { [k: string]: ValueCell<Helpers.TypedArray> }
|
|
|
-
|
|
|
-export interface RenderObject {
|
|
|
- id: number
|
|
|
- type: 'mesh' | 'point'
|
|
|
- data: PointRenderable.Data | MeshRenderable.Data
|
|
|
- uniforms: { [k: string]: REGL.Uniform }
|
|
|
-}
|
|
|
+import { Viewport } from 'mol-view/camera/util';
|
|
|
+import { Camera } from 'mol-view/camera/base';
|
|
|
|
|
|
-export function createRenderObject(type: 'mesh' | 'point', data: PointRenderable.Data | MeshRenderable.Data, uniforms: { [k: string]: REGL.Uniform }) {
|
|
|
- return { id: getNextId(), type, data, uniforms }
|
|
|
-}
|
|
|
-
|
|
|
-export function createRenderable(regl: REGL.Regl, o: RenderObject) {
|
|
|
- switch (o.type) {
|
|
|
- case 'mesh': return MeshRenderable.create(regl, o.data as MeshRenderable.Data, o.uniforms || {})
|
|
|
- case 'point': return PointRenderable.create(regl, o.data as PointRenderable.Data)
|
|
|
- }
|
|
|
-}
|
|
|
+import * as glContext from './context'
|
|
|
+import Scene, { RenderObject } from './scene';
|
|
|
|
|
|
interface Renderer {
|
|
|
- camera: PerspectiveCamera
|
|
|
- controls: any // OrbitControls
|
|
|
-
|
|
|
add: (o: RenderObject) => void
|
|
|
remove: (o: RenderObject) => void
|
|
|
clear: () => void
|
|
|
draw: () => void
|
|
|
- frame: () => void
|
|
|
- handleResize: () => void
|
|
|
-}
|
|
|
-
|
|
|
-function resizeCanvas (canvas: HTMLCanvasElement, element: HTMLElement) {
|
|
|
- let w = window.innerWidth
|
|
|
- let h = window.innerHeight
|
|
|
- if (element !== document.body) {
|
|
|
- let bounds = element.getBoundingClientRect()
|
|
|
- w = bounds.right - bounds.left
|
|
|
- h = bounds.bottom - bounds.top
|
|
|
- }
|
|
|
- canvas.width = window.devicePixelRatio * w
|
|
|
- canvas.height = window.devicePixelRatio * h
|
|
|
- Object.assign(canvas.style, { width: `${w}px`, height: `${h}px` })
|
|
|
-}
|
|
|
-
|
|
|
-namespace Renderer {
|
|
|
- export function fromElement(element: HTMLElement, contexAttributes?: WebGLContextAttributes) {
|
|
|
- const canvas = document.createElement('canvas')
|
|
|
- Object.assign(canvas.style, { border: 0, margin: 0, padding: 0, top: 0, left: 0 })
|
|
|
- element.appendChild(canvas)
|
|
|
-
|
|
|
- if (element === document.body) {
|
|
|
- canvas.style.position = 'absolute'
|
|
|
- Object.assign(element.style, { margin: 0, padding: 0 })
|
|
|
- }
|
|
|
-
|
|
|
- function resize () {
|
|
|
- resizeCanvas(canvas, element)
|
|
|
- }
|
|
|
-
|
|
|
- window.addEventListener('resize', resize, false)
|
|
|
|
|
|
- // function onDestroy () {
|
|
|
- // window.removeEventListener('resize', resize)
|
|
|
- // element.removeChild(canvas)
|
|
|
- // }
|
|
|
+ setViewport: (viewport: Viewport) => void
|
|
|
|
|
|
- resize()
|
|
|
-
|
|
|
- return create(canvas)
|
|
|
- }
|
|
|
-
|
|
|
- export function create(canvas: HTMLCanvasElement): Renderer {
|
|
|
- const renderableList: Renderable[] = []
|
|
|
- const objectIdRenderableMap: { [k: number]: Renderable } = {}
|
|
|
+ dispose: () => void
|
|
|
+}
|
|
|
|
|
|
- const extensions = [
|
|
|
- 'OES_element_index_uint',
|
|
|
- 'ANGLE_instanced_arrays'
|
|
|
- ]
|
|
|
- const optionalExtensions = [
|
|
|
- 'EXT_disjoint_timer_query'
|
|
|
- ]
|
|
|
+const extensions = [
|
|
|
+ 'OES_element_index_uint',
|
|
|
+ 'ANGLE_instanced_arrays'
|
|
|
+]
|
|
|
+const optionalExtensions = [
|
|
|
+ 'EXT_disjoint_timer_query'
|
|
|
+]
|
|
|
|
|
|
+namespace Renderer {
|
|
|
+ export function create(canvas: HTMLCanvasElement, camera: Camera): Renderer {
|
|
|
const regl = glContext.create({ canvas, extensions, optionalExtensions, profile: true })
|
|
|
-
|
|
|
- const camera = PerspectiveCamera.create({
|
|
|
- near: 0.01,
|
|
|
- far: 10000,
|
|
|
- position: Vec3.create(0, 0, 50)
|
|
|
- })
|
|
|
-
|
|
|
- const controls = TrackballControls.create(canvas, camera, {
|
|
|
-
|
|
|
- })
|
|
|
+ const scene = Scene.create(regl)
|
|
|
|
|
|
const baseContext = regl({
|
|
|
context: {
|
|
@@ -142,68 +55,39 @@ namespace Renderer {
|
|
|
}
|
|
|
})
|
|
|
|
|
|
- const stats = Stats([])
|
|
|
- let prevTime = regl.now()
|
|
|
-
|
|
|
const draw = () => {
|
|
|
- controls.update()
|
|
|
- // controls.copyInto(camera.position, camera.direction, camera.up)
|
|
|
+ regl.poll() // updates timers and viewport
|
|
|
camera.update()
|
|
|
baseContext(state => {
|
|
|
regl.clear({ color: [0, 0, 0, 1] })
|
|
|
// TODO painters sort, filter visible, filter picking, visibility culling?
|
|
|
- renderableList.forEach(r => {
|
|
|
+ scene.forEach(r => {
|
|
|
r.draw()
|
|
|
})
|
|
|
- stats.update(state.time - prevTime)
|
|
|
- prevTime = state.time
|
|
|
})
|
|
|
}
|
|
|
|
|
|
- window.addEventListener('resize', handleResize, false)
|
|
|
- handleResize()
|
|
|
-
|
|
|
// TODO animate, draw, requestDraw
|
|
|
return {
|
|
|
- camera,
|
|
|
- controls,
|
|
|
-
|
|
|
add: (o: RenderObject) => {
|
|
|
- const renderable = createRenderable(regl, o)
|
|
|
- renderableList.push(renderable)
|
|
|
- objectIdRenderableMap[o.id] = renderable
|
|
|
- stats.add(renderable)
|
|
|
+ scene.add(o)
|
|
|
draw()
|
|
|
},
|
|
|
remove: (o: RenderObject) => {
|
|
|
- if (o.id in objectIdRenderableMap) {
|
|
|
- // TODO
|
|
|
- // objectIdRenderableMap[o.id].destroy()
|
|
|
- delete objectIdRenderableMap[o.id]
|
|
|
- draw()
|
|
|
- }
|
|
|
+ scene.remove(o)
|
|
|
+ draw()
|
|
|
},
|
|
|
clear: () => {
|
|
|
- for (const id in objectIdRenderableMap) {
|
|
|
- // TODO
|
|
|
- // objectIdRenderableMap[id].destroy()
|
|
|
- delete objectIdRenderableMap[id]
|
|
|
- }
|
|
|
- renderableList.length = 0
|
|
|
+ scene.clear()
|
|
|
draw()
|
|
|
},
|
|
|
draw,
|
|
|
- frame: () => {
|
|
|
- regl.frame((ctx) => draw())
|
|
|
+ setViewport: (viewport: Viewport) => {
|
|
|
+ regl({ viewport })
|
|
|
},
|
|
|
- handleResize
|
|
|
- }
|
|
|
-
|
|
|
- function handleResize() {
|
|
|
- const viewport = { x: 0, y: 0, width: canvas.width, height: canvas.height }
|
|
|
- regl({ viewport })
|
|
|
- Viewport.copy(camera.viewport, viewport)
|
|
|
- Viewport.copy(controls.viewport, viewport)
|
|
|
+ dispose: () => {
|
|
|
+ regl.destroy()
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
}
|