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

wip, instances: transform, color texture, ...

parent ea08b46f
No related branches found
No related tags found
No related merge requests found
File suppressed by a .gitattributes entry, the file's encoding is unsupported, or the file size exceeds the limit.
......@@ -13,7 +13,7 @@
"scripts": {
"lint": "tslint src/**/*.ts",
"build": "tsc",
"postbuild": "copyfiles --up 1 src/mol-gl/shader/*.vert src/mol-gl/shader/*.frag build/node_modules/",
"postbuild": "copyfiles --up 1 src/mol-gl/shader/*.vert src/mol-gl/shader/*.frag src/mol-gl/shader/*.glsl build/node_modules/",
"watch": "tsc -watch",
"test": "jest",
"script": "node build/node_modules/script.js",
......@@ -44,6 +44,11 @@
},
"testRegex": "\\.spec\\.ts$"
},
"glslify": {
"transform": [
"glslify-import"
]
},
"author": "",
"license": "MIT",
"devDependencies": {
......@@ -57,6 +62,7 @@
"@types/react-dom": "^16.0.4",
"benchmark": "^2.1.4",
"copyfiles": "^2.0.0",
"glslify-import": "^3.1.0",
"glslify-loader": "^1.0.2",
"jest": "^22.4.2",
"raw-loader": "^0.5.1",
......
......@@ -8,10 +8,11 @@ import REGL = require('regl');
import * as glContext from 'mol-gl/context'
import { Camera } from 'mol-gl/camera'
import { Vec3, Mat4 } from 'mol-math/linear-algebra'
import PointRenderable from 'mol-gl/renderable/point'
import MeshRenderable from 'mol-gl/renderable/mesh'
import { PointRenderable, MeshRenderable } from 'mol-gl/renderable'
import Attribute from 'mol-gl/attribute';
import Model from 'mol-gl/model';
import { createTransformAttributes } from 'mol-gl/renderable/util';
import { calculateTextureInfo } from 'mol-gl/util';
// import { positionFromModel } from 'mol-geo/shape/point'
export default class State {
......@@ -42,28 +43,54 @@ export default class State {
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 position = Attribute.create(regl, new Float32Array([0, -1, 0, -1, 0, 0, 1, 1, 0]), { size: 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.toArray(m4, transformArray1, 0)
Mat4.toArray(m4, transformArray2, 0)
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
const colorTexInfo = calculateTextureInfo(3, 3)
const color = new Uint8Array(colorTexInfo.length)
color.set([
0, 0, 255,
0, 255, 0,
255, 0, 0
])
console.log(color, colorTexInfo)
const colorTex = regl.texture({
width: colorTexInfo.width,
height: colorTexInfo.height,
format: 'rgb',
type: 'uint8',
wrapS: 'clamp',
wrapT: 'clamp',
data: color
})
// position.update((array: Float32Array) => {
// positionFromModel({}, array, 0)
// })
const points = PointRenderable.create(regl, { position, transform: transform1 })
const mesh = MeshRenderable.create(regl, { position, transform: transform2 })
const points = PointRenderable.create(regl, {
position,
...createTransformAttributes(regl, transformArray1)
})
const mesh = MeshRenderable.create(regl,
{
position,
...createTransformAttributes(regl, transformArray2)
},
{
colorTex,
colorTexSize: [ colorTexInfo.width, colorTexInfo.height ]
}
)
const baseContext = regl({
context: {
......@@ -80,11 +107,12 @@ export default class State {
camera.update((state: any) => {
if (!camera.isDirty()) return
baseContext(() => {
console.log(ctx)
// 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()
points.draw()
model1({}, ({ transform }) => {
points.draw()
})
......
......@@ -10,4 +10,5 @@ declare module Helpers {
-readonly [P in keyof T]: T[P]
}
export type TypedArray = Int8Array | Uint8Array | Int16Array | Uint16Array | Int32Array | Uint32Array | Uint8ClampedArray | Float32Array | Float64Array
export type NumberArray = TypedArray | number[]
}
\ No newline at end of file
......@@ -48,19 +48,25 @@ interface Attribute<T extends Helpers.TypedArray> {
reload(): void
}
interface AttributeProps {
size: 1 | 2 | 3 | 4,
divisor?: number,
offset?: number,
stride?: number
}
namespace Attribute {
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> {
export function create<T extends Helpers.TypedArray>(regl: REGL.Regl, array: T, props: AttributeProps): Attribute<T> {
const itemSize = props.size
let _array = array
let _count = _array.length / itemSize
if (props.stride) _count = _array.length / (props.stride / _array.BYTES_PER_ELEMENT)
console.log(_array.length, props.stride)
const buffer = regl.buffer(_array)
const attribute: REGL.AttributeConfig = {
size: itemSize,
buffer,
divisor
}
const attribute: REGL.AttributeConfig = { ...props, buffer }
const growIfNeeded = function(count: number) {
if (count * itemSize > _array.length) {
const newArray: T = new (_array as any).constructor(count * itemSize)
......
......@@ -6,7 +6,8 @@
import REGL = require('regl');
import Attribute from './attribute'
import Point from './renderable/point'
import PointRenderable from './renderable/point'
import MeshRenderable from './renderable/mesh'
export type AttributesMutator<T extends AttributesData> = (data: T) => (boolean | void)
export type AttributesData = { [k: string]: Helpers.TypedArray }
......@@ -17,4 +18,4 @@ export interface Renderable<T extends AttributesData> {
draw(): void
}
export { Point }
\ No newline at end of file
export { PointRenderable, MeshRenderable }
\ No newline at end of file
......@@ -18,24 +18,48 @@ interface Elements {
}
type Uniforms = { [k: string]: REGL.Uniform | REGL.Texture }
export function fillSerial<T extends Helpers.NumberArray> (array: T) {
const n = array.length
for (let i = 0; i < n; ++i) array[ i ] = i
return array
}
namespace Mesh {
export type DataType = {
position: { type: Float32Array, itemSize: 3 }
offset: { type: Float32Array, itemSize: 3 }
transformColumn0: { type: Float32Array, itemSize: 4 }
transformColumn1: { type: Float32Array, itemSize: 4 }
transformColumn2: { type: Float32Array, itemSize: 4 }
transformColumn3: { type: Float32Array, itemSize: 4 }
}
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> {
export function create(regl: REGL.Regl, attributes: Attributes, uniforms: Uniforms, elements?: Elements): Renderable<Data> {
console.log('mesh', {
count: attributes.position.getCount(),
instances: attributes.transform.getCount(),
instances: attributes.transformColumn0.getCount(),
attributes,
uniforms
})
const instanceCount = attributes.transformColumn0.getCount()
const instanceId = fillSerial(new Float32Array(instanceCount))
console.log(instanceId)
const command = regl({
...MeshShaders,
attributes: getBuffers(attributes),
uniforms: {
objectId: uniforms.objectId || 0,
instanceCount,
...uniforms
},
attributes: getBuffers({
instanceId: Attribute.create(regl, instanceId, { size: 1, divisor: 1 }),
...attributes
}),
count: attributes.position.getCount(),
instances: attributes.transform.getCount(),
instances: instanceCount,
primitive: 'triangles'
})
return {
......
......@@ -15,7 +15,10 @@ type Point = 'point'
namespace Point {
export type DataType = {
position: { type: Float32Array, itemSize: 3 }
transform: { type: Float32Array, itemSize: 16 }
transformColumn0: { type: Float32Array, itemSize: 4 }
transformColumn1: { type: Float32Array, itemSize: 4 }
transformColumn2: { type: Float32Array, itemSize: 4 }
transformColumn3: { type: Float32Array, itemSize: 4 }
}
export type Data = { [K in keyof DataType]: DataType[K]['type'] }
export type Attributes = { [K in keyof Data]: Attribute<Data[K]> }
......@@ -23,13 +26,13 @@ namespace Point {
export function create(regl: REGL.Regl, attributes: Attributes): Renderable<Data> {
console.log('point', {
count: attributes.position.getCount(),
instances: attributes.transform.getCount(),
instances: attributes.transformColumn0.getCount(),
}, attributes)
const command = regl({
...PointShaders,
attributes: getBuffers(attributes),
count: attributes.position.getCount(),
instances: attributes.transform.getCount(),
instances: attributes.transformColumn0.getCount(),
primitive: 'points'
})
return {
......
......@@ -4,7 +4,22 @@
* @author Alexander Rose <alexander.rose@weirdbyte.de>
*/
import REGL = require('regl');
import { Attributes, AttributesData, AttributesBuffers } from '../renderable'
import Attribute from '../attribute'
export function createTransformAttributes (regl: REGL.Regl, transform: Float32Array) {
const size = 4
const divisor = 1
const bpe = transform.BYTES_PER_ELEMENT
const stride = 16 * bpe
return {
transformColumn0: Attribute.create(regl, transform, { size, divisor, offset: 0, stride }),
transformColumn1: Attribute.create(regl, transform, { size, divisor, offset: 4 * bpe, stride }),
transformColumn2: Attribute.create(regl, transform, { size, divisor, offset: 8 * bpe, stride }),
transformColumn3: Attribute.create(regl, transform, { size, divisor, offset: 12 * bpe, stride })
}
}
export function getBuffers<T extends AttributesData>(attributes: Attributes<T>): AttributesBuffers<T> {
const buffers: AttributesBuffers<any> = {}
......
......@@ -4,6 +4,10 @@
* @author Alexander Rose <alexander.rose@weirdbyte.de>
*/
precision mediump float;
varying vec3 vColor;
void main(){
gl_FragColor = vec4(0, 1, 0, 1);
gl_FragColor = vec4(vColor, 1);
}
\ No newline at end of file
......@@ -4,16 +4,42 @@
* @author Alexander Rose <alexander.rose@weirdbyte.de>
*/
#define INSTANCE_COLOR
precision mediump float;
uniform mat4 projection, model, view;
uniform int objectId;
uniform int instanceCount;
#if defined( ATTRIBUTE_COLOR )
attribute vec3 color;
#elif defined( INSTANCE_COLOR ) || defined( ELEMENT_COLOR )
uniform vec2 colorTexSize;
uniform sampler2D colorTex;
#endif
attribute vec3 position;
attribute vec4 transformColumn0, transformColumn1, transformColumn2, transformColumn3;
attribute float instanceId;
// attribute int elementId;
// instanced
// attribute mat4 transform;
uniform mat4 transform;
varying vec3 vColor;
varying vec3 vPosition;
#pragma glslify: read_vec3 = require(./read-vec3.glsl)
void main(){
mat4 transform = mat4(transformColumn0, transformColumn1, transformColumn2, transformColumn3);
#if defined( ATTRIBUTE_COLOR )
vColor = color;
#elif defined( INSTANCE_COLOR )
vColor = read_vec3(colorTex, instanceId, colorTexSize);
// #elif defined( ELEMENT_COLOR )
// vColor = read_vec3(colorTex, instanceId * instanceCount + elementId, colorTexSize);
#else
vColor = vec3(0.0, 1.0, 0.0);
#endif
gl_Position = projection * view * model * transform * vec4(position, 1.0);
}
\ No newline at end of file
......@@ -5,16 +5,22 @@
*/
precision mediump float;
uniform mat4 projection, model, view;
attribute vec3 position;
attribute vec3 position; //, color;
attribute vec4 transformColumn0, transformColumn1, transformColumn2, transformColumn3;
// attribute int instanceId;
// instanced
// attribute mat4 transform;
uniform mat4 transform;
// uniform mat4 transform;
varying vec3 vPosition;
// varying vec3 vColor;
void main(){
mat4 transform = mat4(transformColumn0, transformColumn1, transformColumn2, transformColumn3);
// vColor = color;
gl_PointSize = 20.0;
gl_Position = projection * view * model * transform * vec4(position, 1.0);
}
\ No newline at end of file
/**
* Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info.
*
* @author Alexander Rose <alexander.rose@weirdbyte.de>
*/
vec3 read_vec3 (sampler2D tex, float i, vec2 size) {
float x = mod(i, size.x);
float y = floor(i / size.x);
vec2 uv = (vec2(x, y) + 0.5) / size;
return texture2D(tex, uv).rgb;
}
#pragma glslify: export(read_vec3)
\ No newline at end of file
/**
* Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info.
*
* @author Alexander Rose <alexander.rose@weirdbyte.de>
*/
export function calculateTextureInfo (n: number, itemSize: number) {
const sqN = Math.sqrt(n * itemSize)
let width = Math.ceil(sqN)
width = width + (itemSize - (width % itemSize)) % itemSize
const height = width > 0 ? Math.ceil(n * itemSize / width) : 0
return { width, height, length: width * height * itemSize }
}
\ No newline at end of file
......@@ -155,6 +155,45 @@ export namespace Mat4 {
return Mat4.copy(Mat4.zero(), a);
}
export function transpose(out: Mat4, a: Mat4) {
// If we are transposing ourselves we can skip a few steps but have to cache some values
if (out === a) {
const a01 = a[1], a02 = a[2], a03 = a[3];
const a12 = a[6], a13 = a[7];
const a23 = a[11];
out[1] = a[4];
out[2] = a[8];
out[3] = a[12];
out[4] = a01;
out[6] = a[9];
out[7] = a[13];
out[8] = a02;
out[9] = a12;
out[11] = a[14];
out[12] = a03;
out[13] = a13;
out[14] = a23;
} else {
out[0] = a[0];
out[1] = a[4];
out[2] = a[8];
out[3] = a[12];
out[4] = a[1];
out[5] = a[5];
out[6] = a[9];
out[7] = a[13];
out[8] = a[2];
out[9] = a[6];
out[10] = a[10];
out[11] = a[14];
out[12] = a[3];
out[13] = a[7];
out[14] = a[11];
out[15] = a[15];
}
return out;
}
export function invert(out: Mat4, a: Mat4) {
const a00 = a[0], a01 = a[1], a02 = a[2], a03 = a[3],
a10 = a[4], a11 = a[5], a12 = a[6], a13 = a[7],
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment