|
@@ -7,9 +7,35 @@
|
|
|
import REGL = require('regl');
|
|
|
import { ValueCell } from 'mol-util/value-cell'
|
|
|
|
|
|
-import { ColorTexture } from '../util';
|
|
|
import { Attributes, AttributesData, AttributesBuffers } from '../renderable'
|
|
|
import Attribute from '../attribute'
|
|
|
+import { ColorData } from 'mol-geo/color';
|
|
|
+import { ShaderDefines } from '../shaders';
|
|
|
+
|
|
|
+export type ReglUniforms = { [k: string]: REGL.Uniform | REGL.Texture }
|
|
|
+export type ReglAttributes = { [k: string]: REGL.AttributeConfig }
|
|
|
+
|
|
|
+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 }
|
|
|
+}
|
|
|
+
|
|
|
+export interface ColorTexture extends Uint8Array {
|
|
|
+ width: number,
|
|
|
+ height: number
|
|
|
+}
|
|
|
+
|
|
|
+export function createColorTexture (n: number): ColorTexture {
|
|
|
+ const colorTexInfo = calculateTextureInfo(n, 3)
|
|
|
+ const colorTexture = new Uint8Array(colorTexInfo.length)
|
|
|
+ return Object.assign(colorTexture, {
|
|
|
+ width: colorTexInfo.width,
|
|
|
+ height: colorTexInfo.height
|
|
|
+ })
|
|
|
+}
|
|
|
|
|
|
export function createTransformAttributes (regl: REGL.Regl, transform: ValueCell<Float32Array>, count: number) {
|
|
|
const size = 4
|
|
@@ -40,6 +66,18 @@ export function createColorUniforms (regl: REGL.Regl, color: ValueCell<ColorText
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+export function getColorDefines(color: ColorData) {
|
|
|
+ const defines: ShaderDefines = {}
|
|
|
+ switch (color.type) {
|
|
|
+ case 'uniform': defines.UNIFORM_COLOR = ''; break;
|
|
|
+ case 'attribute': defines.ATTRIBUTE_COLOR = ''; break;
|
|
|
+ case 'element': defines.ELEMENT_COLOR = ''; break;
|
|
|
+ case 'instance': defines.INSTANCE_COLOR = ''; break;
|
|
|
+ case 'element-instance': defines.ELEMENT_INSTANCE_COLOR = ''; break;
|
|
|
+ }
|
|
|
+ return defines
|
|
|
+}
|
|
|
+
|
|
|
export function getBuffers<T extends AttributesData>(attributes: Attributes<T>): AttributesBuffers<T> {
|
|
|
const buffers: AttributesBuffers<any> = {}
|
|
|
for (const k of Object.keys(attributes)) {
|
|
@@ -52,4 +90,72 @@ 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
|
|
|
+}
|
|
|
+
|
|
|
+interface BaseProps {
|
|
|
+ objectId: number,
|
|
|
+ instanceCount: number,
|
|
|
+ elementCount: number,
|
|
|
+ positionCount: number,
|
|
|
+
|
|
|
+ position: ValueCell<Float32Array>
|
|
|
+ normal?: ValueCell<Float32Array>
|
|
|
+ size?: ValueCell<Float32Array>
|
|
|
+ id: ValueCell<Float32Array>
|
|
|
+ transform: ValueCell<Float32Array>
|
|
|
+ color: ColorData
|
|
|
+}
|
|
|
+
|
|
|
+export function createBaseUniforms(regl: REGL.Regl, props: BaseProps): ReglUniforms {
|
|
|
+ const { objectId, instanceCount, elementCount, color } = props
|
|
|
+ const uniforms = { objectId, instanceCount, elementCount }
|
|
|
+ if (color.type === 'instance' || color.type === 'element' || color.type === 'element-instance') {
|
|
|
+ Object.assign(uniforms, createColorUniforms(regl, color.value))
|
|
|
+ } else if (color.type === 'uniform') {
|
|
|
+ Object.assign(uniforms, { color: color.value })
|
|
|
+ }
|
|
|
+ return uniforms
|
|
|
+}
|
|
|
+
|
|
|
+export function createBaseAttributes(regl: REGL.Regl, props: BaseProps): ReglAttributes {
|
|
|
+ const { instanceCount, positionCount, position, color, id, normal, size, transform } = props
|
|
|
+ const instanceId = ValueCell.create(fillSerial(new Float32Array(instanceCount)))
|
|
|
+ const attributes = getBuffers({
|
|
|
+ instanceId: Attribute.create(regl, instanceId, instanceCount, { size: 1, divisor: 1 }),
|
|
|
+ position: Attribute.create(regl, position, positionCount, { size: 3 }),
|
|
|
+ elementId: Attribute.create(regl, id, positionCount, { size: 1 }),
|
|
|
+ ...createTransformAttributes(regl, transform, instanceCount)
|
|
|
+ })
|
|
|
+ if (color.type === 'attribute') {
|
|
|
+ attributes.color = Attribute.create(regl, color.value, positionCount, { size: 3 }).buffer
|
|
|
+ }
|
|
|
+ if (normal) {
|
|
|
+ attributes.normal = Attribute.create(regl, normal as any, positionCount, { size: 3 }).buffer
|
|
|
+ }
|
|
|
+ if (size) {
|
|
|
+ attributes.size = Attribute.create(regl, size, positionCount, { size: 1 }).buffer
|
|
|
+ }
|
|
|
+ return attributes
|
|
|
+}
|
|
|
+
|
|
|
+export function createBaseDefines(regl: REGL.Regl, props: BaseProps) {
|
|
|
+ return getColorDefines(props.color)
|
|
|
+}
|
|
|
+
|
|
|
+export function destroyAttributes(attributes: ReglAttributes) {
|
|
|
+ for (const k in attributes) {
|
|
|
+ const buffer = attributes[k].buffer
|
|
|
+ if (buffer) {
|
|
|
+ buffer.destroy()
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+export function destroyUniforms(uniforms: ReglUniforms) {
|
|
|
+ for (const k in uniforms) {
|
|
|
+ const uniform = uniforms[k]
|
|
|
+ if ((uniform as any).destroy) {
|
|
|
+ (uniform as any).destroy()
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|