Browse Source

wip, not working

Alexander Rose 7 years ago
parent
commit
ea08b46ff2

+ 65 - 9
src/apps/render-test/state.ts

@@ -7,8 +7,12 @@
 import REGL = require('regl');
 import * as glContext from 'mol-gl/context'
 import { Camera } from 'mol-gl/camera'
-import { Vec3 } from 'mol-math/linear-algebra'
-import Point from 'mol-gl/renderable/point'
+import { Vec3, Mat4 } from 'mol-math/linear-algebra'
+import PointRenderable from 'mol-gl/renderable/point'
+import MeshRenderable from 'mol-gl/renderable/mesh'
+import Attribute from 'mol-gl/attribute';
+import Model from 'mol-gl/model';
+// import { positionFromModel } from 'mol-geo/shape/point'
 
 export default class State {
     regl: REGL.Regl
@@ -19,8 +23,10 @@ export default class State {
             extensions: [
                 'OES_texture_float',
                 'OES_texture_float_linear',
+                'OES_element_index_uint',
                 // 'ext_disjoint_timer_query',
-                'EXT_blend_minmax'
+                'EXT_blend_minmax',
+                'ANGLE_instanced_arrays'
             ],
             // profile: true
         })
@@ -29,16 +35,66 @@ export default class State {
             center: Vec3.create(0, 0, 0)
         })
 
-        const points = Point.create(regl, {
-            position: new Float32Array([0, -1, 0, -1, 0, 0, 1, 1, 0])
+        const p1 = Vec3.create(0, 4, 0)
+        const p2 = Vec3.create(-3, 0, 0)
+
+        const model1 = Model(regl)
+        const model2 = Model(regl, { position: p1 })
+        const model3 = Model(regl, { position: p2 })
+
+        const position = Attribute.create(regl, new Float32Array([0, -1, 0, -1, 0, 0, 1, 1, 0]), 3)
+
+        const transformArray1 = new Float32Array(16)
+        const transformArray2 = new Float32Array(16 * 3)
+        const m4 = Mat4.identity()
+        Mat4.toArray(m4, transformArray1)
+        Mat4.toArray(m4, transformArray2)
+        Mat4.setTranslation(m4, p1)
+        Mat4.toArray(m4, transformArray2, 16)
+        Mat4.setTranslation(m4, p2)
+        Mat4.toArray(m4, transformArray2, 32)
+        const transform1 = Attribute.create(regl, transformArray1, 16, 1)
+        const transform2 = Attribute.create(regl, transformArray2, 16, 1)
+
+        // TODO use https://github.com/substack/glsl-matrix-texture
+
+        // position.update((array: Float32Array) => {
+        //     positionFromModel({}, array, 0)
+        // })
+
+        const points = PointRenderable.create(regl, { position, transform: transform1 })
+        const mesh = MeshRenderable.create(regl, { position, transform: transform2 })
+
+        const baseContext = regl({
+            context: {
+                model: Mat4.identity(),
+                transform: Mat4.setTranslation(Mat4.identity(), Vec3.create(6, 0, 0))
+            },
+            uniforms: {
+                model: regl.context('model' as any),
+                transform: regl.context('transform' as any),
+            }
         })
 
-        regl.frame(() => {
+        regl.frame((ctx) => {
             camera.update((state: any) => {
                 if (!camera.isDirty()) return
-                regl.clear({color: [0, 0, 0, 1]})
-                points.update(a => { a.position[0] = Math.random() })
-                points.draw()
+                baseContext(() => {
+                    console.log(ctx)
+                    regl.clear({color: [0, 0, 0, 1]})
+                    position.update(array => { array[0] = Math.random() })
+                    // points.update(a => { a.position[0] = Math.random() })
+                    mesh.draw()
+                    model1({}, ({ transform }) => {
+                        points.draw()
+                    })
+                    model2({}, ({ transform }) => {
+                        points.draw()
+                        model3({ transform }, () => {
+                            points.draw()
+                        })
+                    })
+                })
             }, undefined)
         })
 

+ 17 - 0
src/mol-geo/shape/point.ts

@@ -0,0 +1,17 @@
+/**
+ * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info.
+ *
+ * @author Alexander Rose <alexander.rose@weirdbyte.de>
+ */
+
+
+export function countFromModel(model: any) {}
+export function positionFromModel(model: any, array: Float32Array, offset: number) {
+
+}
+export function colorFromModel(model: any, params: any, array: Float32Array, offset: number) {
+
+}
+export function sizeFromModel(model: any, params: any, array: Float32Array, offset: number) {
+
+}

+ 5 - 0
src/mol-geo/shape/sphere.ts

@@ -0,0 +1,5 @@
+/**
+ * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info.
+ *
+ * @author Alexander Rose <alexander.rose@weirdbyte.de>
+ */

+ 71 - 31
src/mol-gl/attribute.ts

@@ -6,49 +6,89 @@
 
 import REGL = require('regl');
 
+// export type AttributeGroupMutator<T extends AttributesData> = (data: T) => (boolean | void)
+// export type AttributeGroupData = { [k: string]: Helpers.TypedArray }
+// export type AttributesBuffers<T extends AttributesData> = { [K in keyof T]: REGL.Buffer }
+
+// interface AttributeGroup<T extends AttributeGroup.Data> {
+//     readonly buffer: REGL.Buffer
+//     readonly length: number
+//     readonly data: T
+//     setCount(size: number): void
+//     update(mutator: AttributeGroup.Mutator<T>): void
+// }
+
+// namespace AttributeGroup {
+//     export type Data = { [k: string]: Helpers.TypedArray }
+//     export type Mutator<T extends Data> = (data: T) => (UpdateInfo<T> | void)
+//     export type UpdateInfo<T extends Data> = boolean | { [k in keyof T]: Attribute.UpdateInfo }
+//     export type Attributes<T extends Data> = { [K in keyof T]: Attribute<T[K]> }
+
+//     export function create<T extends Data>(regl: REGL.Regl, data: T): AttributeGroup<T> {
+//         const attributes: Attributes<any> = {}
+//         for (const k of Object.keys(data)) {
+//             attributes[k] = Attribute.create(regl, data[k])
+//         }
+//         return {
+//             update: (mutator: Mutator<T>) => {
+
+//             }
+//         }
+//     }
+// }
+
+
 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
+    readonly buffer: REGL.AttributeConfig
+    getCount(): number
+    setCount(count: number): void
+    getArray(): T
+    set(index: number, ...values: 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)
+    export type Mutator<T extends Helpers.TypedArray> = (data: T) => (UpdateInfo | void)
+    export type UpdateInfo = boolean | { offset: number, count: number }
+
+    export function create<T extends Helpers.TypedArray>(regl: REGL.Regl, array: T, itemSize: number, divisor = 0): Attribute<T> {
+        let _array = array
+        let _count = _array.length / itemSize
+        const buffer = regl.buffer(_array)
+        const attribute: REGL.AttributeConfig = {
+            size: itemSize,
+            buffer,
+            divisor
+        }
+        const growIfNeeded = function(count: number) {
+            if (count * itemSize > _array.length) {
+                const newArray: T = new (_array as any).constructor(count * itemSize)
+                newArray.set(_array)
+                _array = newArray
+                buffer(_array)
             }
+            _count = count
         }
         return {
-            buffer,
-            get length() { return _length },
-            get data() { return _data },
-            set: (value: number, index: number) => {
+            buffer: attribute,
+            getCount: () =>  _count,
+            setCount: (count: number) => growIfNeeded(count),
+            getArray: () => _array,
+            set: (index: number, ...values: number[]) => {
+                if (values.length !== itemSize) throw new Error('wrong number of values given')
                 growIfNeeded(index)
-                _data[index] = value
-                buffer.subdata([value], index * data.BYTES_PER_ELEMENT)
-            },
-            growIfNeeded(size: number) {
-                growIfNeeded(size)
+                for (let i = 0; i < itemSize; ++i) {
+                    _array[index * itemSize + i] = values[i]
+                }
+                buffer.subdata(values, index * itemSize * _array.BYTES_PER_ELEMENT)
             },
-            update: (mutator: Mutator<T>) => {
-                mutator(_data)
-                buffer(_data)
+            update: (mutator: Mutator<T>, offset?: number, count?: number) => {
+                if (offset && count) growIfNeeded(offset + count)
+                mutator(_array)
+                buffer(_array)
             },
-            reload: () => {
-                buffer(_data)
-            }
+            reload: () => buffer(_array)
         }
     }
 }

+ 2 - 3
src/mol-gl/renderable.ts

@@ -11,11 +11,10 @@ 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 type AttributesBuffers<T extends AttributesData> = { [K in keyof T]: REGL.AttributeConfig }
 
 export interface Renderable<T extends AttributesData> {
-    draw(): void,
-    update(mutator: AttributesMutator<T>): void
+    draw(): void
 }
 
 export { Point }

+ 5 - 0
src/mol-gl/renderable/line.ts

@@ -0,0 +1,5 @@
+/**
+ * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info.
+ *
+ * @author Alexander Rose <alexander.rose@weirdbyte.de>
+ */

+ 47 - 0
src/mol-gl/renderable/mesh.ts

@@ -0,0 +1,47 @@
+/**
+ * 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 } from '../renderable'
+import { getBuffers } from './util'
+import Attribute from '../attribute';
+
+import { MeshShaders } from '../shaders'
+
+type Mesh = 'mesh'
+
+// TODO
+interface Elements {
+
+}
+
+namespace Mesh {
+    export type DataType = {
+        position: { type: Float32Array, itemSize: 3 }
+        offset: { type: Float32Array, itemSize: 3 }
+    }
+    export type Data = { [K in keyof DataType]: DataType[K]['type'] }
+    export type Attributes = { [K in keyof Data]: Attribute<Data[K]> }
+
+    export function create(regl: REGL.Regl, attributes: Attributes, elements?: Elements): Renderable<Data> {
+        console.log('mesh', {
+            count: attributes.position.getCount(),
+            instances: attributes.transform.getCount(),
+        })
+        const command = regl({
+            ...MeshShaders,
+            attributes: getBuffers(attributes),
+            count: attributes.position.getCount(),
+            instances: attributes.transform.getCount(),
+            primitive: 'triangles'
+        })
+        return {
+            draw: () => command(),
+        }
+    }
+}
+
+export default Mesh

+ 60 - 19
src/mol-gl/renderable/point.ts

@@ -5,37 +5,78 @@
  */
 
 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')
+import { Renderable } from '../renderable'
+import { getBuffers } from './util'
+import Attribute from '../attribute';
+import { PointShaders } from '../shaders'
 
 type Point = 'point'
 
 namespace Point {
-    export interface Data extends AttributesData {
-        position: Float32Array
+    export type DataType = {
+        position: { type: Float32Array, itemSize: 3 }
+        transform: { type: Float32Array, itemSize: 16 }
     }
-    export function create(regl: REGL.Regl, data: Data): Renderable<Data> {
-        const attributes = createAttributes(regl, data)
+    export type Data = { [K in keyof DataType]: DataType[K]['type'] }
+    export type Attributes = { [K in keyof Data]: Attribute<Data[K]> }
+
+    export function create(regl: REGL.Regl, attributes: Attributes): Renderable<Data> {
+        console.log('point', {
+            count: attributes.position.getCount(),
+            instances: attributes.transform.getCount(),
+        }, attributes)
         const command = regl({
-            vert: pointVert,
-            frag: pointFrag,
+            ...PointShaders,
             attributes: getBuffers(attributes),
-            count: data.position.length / 3,
+            count: attributes.position.getCount(),
+            instances: attributes.transform.getCount(),
             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
+export default Point
+
+// namespace Point {
+//     export type DataType = {
+//         position: { type: Float32Array, itemSize: 3 }
+//     }
+//     export type Data = { [K in keyof DataType]: DataType[K]['type'] }
+//     export type Attributes = { [K in keyof Data]: Attribute<Data[K]> }
+
+//     export function create(regl: REGL.Regl, dataOrCount: Data | number): Renderable<Data> {
+//         let count: number
+//         let data: Data
+//         if (typeof dataOrCount === 'number') {
+//             count = dataOrCount
+//             data = {
+//                 position: new Float32Array(count * 3)
+//             }
+//         } else {
+//             count = dataOrCount.position.length / 3
+//             data = dataOrCount
+//         }
+//         const attributes = createAttributes(regl, data)
+//         const command = regl({
+//             vert: pointVert,
+//             frag: pointFrag,
+//             attributes: getBuffers(attributes),
+//             count,
+//             primitive: 'points'
+//         })
+//         return {
+//             draw: () => command(),
+//             setCount: (newCount: number) => {
+//                 for (const k of Object.keys(data)) {
+//                     attributes[k as keyof Data].setCount(newCount)
+//                 }
+//                 count = newCount
+//             },
+//             getCount: () => count,
+//             attributes
+//         }
+//     }
+// }

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

@@ -4,19 +4,8 @@
  * @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)) {
@@ -24,11 +13,3 @@ export function getBuffers<T extends AttributesData>(attributes: Attributes<T>):
     }
     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>
-}

+ 9 - 0
src/mol-gl/shader/mesh.frag

@@ -0,0 +1,9 @@
+/**
+ * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info.
+ *
+ * @author Alexander Rose <alexander.rose@weirdbyte.de>
+ */
+
+void main(){
+    gl_FragColor = vec4(0, 1, 0, 1);
+}

+ 19 - 0
src/mol-gl/shader/mesh.vert

@@ -0,0 +1,19 @@
+/**
+ * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info.
+ *
+ * @author Alexander Rose <alexander.rose@weirdbyte.de>
+ */
+
+precision mediump float;
+uniform mat4 projection, model, view;
+attribute vec3 position;
+
+// instanced
+// attribute mat4 transform;
+uniform mat4 transform;
+
+varying vec3 vPosition;
+
+void main(){
+    gl_Position = projection * view * model * transform * vec4(position, 1.0);
+}

+ 6 - 0
src/mol-gl/shader/point.frag

@@ -1,3 +1,9 @@
+/**
+ * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info.
+ *
+ * @author Alexander Rose <alexander.rose@weirdbyte.de>
+ */
+
 void main(){
     gl_FragColor = vec4(1, 0, 0, 1);
 }

+ 12 - 2
src/mol-gl/shader/point.vert

@@ -1,10 +1,20 @@
+/**
+ * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info.
+ *
+ * @author Alexander Rose <alexander.rose@weirdbyte.de>
+ */
+
 precision mediump float;
-uniform mat4 projection, view;
+uniform mat4 projection, model, view;
 attribute vec3 position;
 
+// instanced
+// attribute mat4 transform;
+uniform mat4 transform;
+
 varying vec3 vPosition;
 
 void main(){
     gl_PointSize = 20.0;
-    gl_Position = projection * view * vec4(position, 1.0);
+    gl_Position = projection * view * model * transform * vec4(position, 1.0);
 }

+ 12 - 0
src/mol-gl/shaders.ts

@@ -0,0 +1,12 @@
+
+const PointShaders = {
+    vert: require('mol-gl/shader/point.vert'),
+    frag: require('mol-gl/shader/point.frag')
+}
+
+const MeshShaders = {
+    vert: require('mol-gl/shader/mesh.vert'),
+    frag: require('mol-gl/shader/mesh.frag')
+}
+
+export { PointShaders, MeshShaders }

+ 19 - 0
src/mol-math/linear-algebra/3d.ts

@@ -112,6 +112,25 @@ export namespace Mat4 {
         a[4 * j + i] = value;
     }
 
+    export function toArray(a: Mat4, out: number[]|Helpers.TypedArray, offset = 0) {
+        out[offset + 0] = a[0];
+        out[offset + 1] = a[1];
+        out[offset + 2] = a[2];
+        out[offset + 3] = a[3];
+        out[offset + 4] = a[4];
+        out[offset + 5] = a[5];
+        out[offset + 6] = a[6];
+        out[offset + 7] = a[7];
+        out[offset + 8] = a[8];
+        out[offset + 9] = a[9];
+        out[offset + 10] = a[10];
+        out[offset + 11] = a[11];
+        out[offset + 12] = a[12];
+        out[offset + 13] = a[13];
+        out[offset + 14] = a[14];
+        out[offset + 15] = a[15];
+    }
+
     export function copy(out: Mat4, a: Mat4) {
         out[0] = a[0];
         out[1] = a[1];