Alexander Rose 7 роки тому
батько
коміт
5148690ae1

+ 1 - 1
.vscode/settings.json

@@ -1,3 +1,3 @@
 {
-    "typescript.tsdk": "node_modules\\typescript\\lib"
+    "typescript.tsdk": "node_modules/typescript/lib"
 }

+ 2 - 1
package.json

@@ -17,7 +17,8 @@
     "watch": "tsc -watch",
     "test": "jest",
     "script": "node build/node_modules/script.js",
-    "app-render-test": "webpack build/node_modules/apps/render-test/index.js --mode development -o web/render-test/index.js"
+    "app-render-test": "webpack build/node_modules/apps/render-test/index.js --mode development -o web/render-test/index.js",
+    "app-render-test-watch": "webpack build/node_modules/apps/render-test/index.js -w --mode development -o web/render-test/index.js"
   },
   "jest": {
     "moduleFileExtensions": [

+ 5 - 12
src/apps/render-test/state.ts

@@ -8,9 +8,7 @@ import REGL = require('regl');
 import * as glContext from 'mol-gl/context'
 import { Camera } from 'mol-gl/camera'
 import { Vec3 } from 'mol-math/linear-algebra'
-
-const pointVert = require('mol-gl/shader/point.vert')
-const pointFrag = require('mol-gl/shader/point.frag')
+import Point from 'mol-gl/renderable/point'
 
 export default class State {
     regl: REGL.Regl
@@ -31,21 +29,16 @@ export default class State {
             center: Vec3.create(0, 0, 0)
         })
 
-        const drawPoints = regl({
-            vert: pointVert,
-            frag: pointFrag,
-            attributes: {
-                position: [[0, -1, 0], [-1, 0, 0], [1, 1, 0]]
-            },
-            count: 3,
-            primitive: 'points'
+        const points = Point.create(regl, {
+            position: new Float32Array([0, -1, 0, -1, 0, 0, 1, 1, 0])
         })
 
         regl.frame(() => {
             camera.update((state: any) => {
                 if (!camera.isDirty()) return
                 regl.clear({color: [0, 0, 0, 1]})
-                drawPoints()
+                points.update(a => { a.position[0] = Math.random() })
+                points.draw()
             }, undefined)
         })
 

+ 13 - 0
src/helpers.d.ts

@@ -0,0 +1,13 @@
+/**
+ * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info.
+ *
+ * @author Alexander Rose <alexander.rose@weirdbyte.de>
+ * @author David Sehnal <david.sehnal@gmail.com>
+ */
+
+declare module Helpers {
+    export type Mutable<T> = {
+        -readonly [P in keyof T]: T[P]
+    }
+    export type TypedArray = Int8Array | Uint8Array | Int16Array | Uint16Array | Int32Array | Uint32Array | Uint8ClampedArray | Float32Array | Float64Array
+}

+ 56 - 0
src/mol-gl/attribute.ts

@@ -0,0 +1,56 @@
+/**
+ * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info.
+ *
+ * @author Alexander Rose <alexander.rose@weirdbyte.de>
+ */
+
+import REGL = require('regl');
+
+interface Attribute<T extends Helpers.TypedArray> {
+    readonly buffer: REGL.Buffer
+    readonly length: number
+    readonly data: T
+    set(value: number, index: number): void
+    growIfNeeded(size: number): void
+    update(mutator: Attribute.Mutator<T>): void
+    reload(): void
+}
+
+namespace Attribute {
+    export type Mutator<T extends Helpers.TypedArray> = (data: T) => (boolean | void)
+
+    export function create<T extends Helpers.TypedArray>(regl: REGL.Regl, data: T): Attribute<T> {
+        let _data = data
+        let _length = _data.length
+        const buffer = regl.buffer(_data)
+        const growIfNeeded = function(length: number) {
+            if (length > _data.length) {
+                _data = new (_data as any).constructor(_data)
+                _length = _data.length
+                buffer(_data)
+            }
+        }
+        return {
+            buffer,
+            get length() { return _length },
+            get data() { return _data },
+            set: (value: number, index: number) => {
+                growIfNeeded(index)
+                _data[index] = value
+                buffer.subdata([value], index * data.BYTES_PER_ELEMENT)
+            },
+            growIfNeeded(size: number) {
+                growIfNeeded(size)
+            },
+            update: (mutator: Mutator<T>) => {
+                mutator(_data)
+                buffer(_data)
+            },
+            reload: () => {
+                buffer(_data)
+            }
+        }
+    }
+}
+
+export default Attribute

+ 21 - 0
src/mol-gl/renderable.ts

@@ -0,0 +1,21 @@
+/**
+ * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info.
+ *
+ * @author Alexander Rose <alexander.rose@weirdbyte.de>
+ */
+
+import REGL = require('regl');
+import Attribute from './attribute'
+import Point from './renderable/point'
+
+export type AttributesMutator<T extends AttributesData> = (data: T) => (boolean | void)
+export type AttributesData = { [k: string]: Helpers.TypedArray }
+export type Attributes<T extends AttributesData> = { [K in keyof T]: Attribute<T[K]> }
+export type AttributesBuffers<T extends AttributesData> = { [K in keyof T]: REGL.Buffer }
+
+export interface Renderable<T extends AttributesData> {
+    draw(): void,
+    update(mutator: AttributesMutator<T>): void
+}
+
+export { Point }

+ 41 - 0
src/mol-gl/renderable/point.ts

@@ -0,0 +1,41 @@
+/**
+ * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info.
+ *
+ * @author Alexander Rose <alexander.rose@weirdbyte.de>
+ */
+
+import REGL = require('regl');
+import { Renderable, AttributesMutator, AttributesData } from '../renderable'
+import { createAttributes, getBuffers, getData } from './util'
+
+const pointVert = require('mol-gl/shader/point.vert')
+const pointFrag = require('mol-gl/shader/point.frag')
+
+type Point = 'point'
+
+namespace Point {
+    export interface Data extends AttributesData {
+        position: Float32Array
+    }
+    export function create(regl: REGL.Regl, data: Data): Renderable<Data> {
+        const attributes = createAttributes(regl, data)
+        const command = regl({
+            vert: pointVert,
+            frag: pointFrag,
+            attributes: getBuffers(attributes),
+            count: data.position.length / 3,
+            primitive: 'points'
+        })
+        return {
+            draw: () => command(),
+            update: (mutator: AttributesMutator<Data>) => {
+                mutator(getData(attributes))
+                for (const k of Object.keys(attributes)) {
+                    attributes[k].reload()
+                }
+            }
+        }
+    }
+}
+
+export default Point

+ 34 - 0
src/mol-gl/renderable/util.ts

@@ -0,0 +1,34 @@
+/**
+ * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info.
+ *
+ * @author Alexander Rose <alexander.rose@weirdbyte.de>
+ */
+
+import REGL = require('regl');
+
+import Attribute from '../attribute'
+import { Attributes, AttributesData, AttributesBuffers } from '../renderable'
+
+export function getData<T extends AttributesData>(attributes: Attributes<T>): T {
+    const data: AttributesData = {}
+    for (const k of Object.keys(attributes)) {
+        data[k] = attributes[k].data
+    }
+    return data as T
+}
+
+export function getBuffers<T extends AttributesData>(attributes: Attributes<T>): AttributesBuffers<T> {
+    const buffers: AttributesBuffers<any> = {}
+    for (const k of Object.keys(attributes)) {
+        buffers[k] = attributes[k].buffer
+    }
+    return buffers as AttributesBuffers<T>
+}
+
+export function createAttributes<T extends AttributesData>(regl: REGL.Regl, data: T): Attributes<T> {
+    const attributes: Attributes<any> = {}
+    for (const k of Object.keys(data)) {
+        attributes[k] = Attribute.create(regl, data[k])
+    }
+    return attributes as Attributes<T>
+}