diff --git a/src/mol-gl/renderable/schema.ts b/src/mol-gl/renderable/schema.ts index c1f3a4f93338c285e9661f4d9c45f0a6db0b59a6..e6d882b070f291c2b065ba102fab818e0afb1d47 100644 --- a/src/mol-gl/renderable/schema.ts +++ b/src/mol-gl/renderable/schema.ts @@ -83,19 +83,6 @@ export function splitValues(schema: RenderableSchema, values: RenderableValues) return { attributeValues, defineValues, textureValues, uniformValues, materialUniformValues } } -export function splitKeys(schema: RenderableSchema) { - const attributeKeys: string[] = [] - const defineKeys: string[] = [] - const textureKeys: string[] = [] - Object.keys(schema).forEach(k => { - const spec = schema[k] - if (spec.type === 'attribute') attributeKeys.push(k) - if (spec.type === 'define') defineKeys.push(k) - if (spec.type === 'texture') textureKeys.push(k) - }) - return { attributeKeys, defineKeys, textureKeys } -} - export type Versions<T extends RenderableValues> = { [k in keyof T]: number } export function getValueVersions<T extends RenderableValues>(values: T) { const versions: Versions<any> = {} diff --git a/src/mol-gl/renderer.ts b/src/mol-gl/renderer.ts index 60ac75d626075db5d00d4cae31ca30d4519e54d8..7c6831489246a6aebe4c38633518c05a211fe5f4 100644 --- a/src/mol-gl/renderer.ts +++ b/src/mol-gl/renderer.ts @@ -105,6 +105,7 @@ namespace Renderer { uPickingAlphaThreshold: ValueCell.create(pickingAlphaThreshold), } + const globalUniformList = Object.entries(globalUniforms) let globalUniformsNeedUpdate = true const renderObject = (r: Renderable<RenderableValues & BaseValues>, variant: RenderVariant) => { @@ -118,7 +119,7 @@ namespace Renderer { program.use() if (globalUniformsNeedUpdate) { // console.log('globalUniformsNeedUpdate') - program.setUniforms(globalUniforms) + program.setUniforms(globalUniformList) globalUniformsNeedUpdate = false } diff --git a/src/mol-gl/webgl/buffer.ts b/src/mol-gl/webgl/buffer.ts index 0206991a7a026fb37cd271fd6ef153be7f6ea697..e0d35551b61688c8adc6de93fc379ac39ec7951e 100644 --- a/src/mol-gl/webgl/buffer.ts +++ b/src/mol-gl/webgl/buffer.ts @@ -152,7 +152,7 @@ export type AttributeDefs = { [k: string]: { kind: ArrayKind, itemSize: AttributeItemSize, divisor: number } } export type AttributeValues = { [k: string]: ValueCell<ArrayType> } -export type AttributeBuffers = { [k: string]: AttributeBuffer } +export type AttributeBuffers = [string, AttributeBuffer][] export interface AttributeBuffer extends Buffer { bind: (location: number) => void @@ -185,14 +185,14 @@ export function createAttributeBuffer<T extends ArrayType, S extends AttributeIt } export function createAttributeBuffers(ctx: WebGLContext, schema: RenderableSchema, values: AttributeValues) { - const buffers: AttributeBuffers = {} + const buffers: AttributeBuffers = [] Object.keys(schema).forEach(k => { const spec = schema[k] if (spec.type === 'attribute') { - buffers[k] = createAttributeBuffer(ctx, values[k].ref.value, spec.itemSize, spec.divisor) + buffers[buffers.length] = [k, createAttributeBuffer(ctx, values[k].ref.value, spec.itemSize, spec.divisor)] } }) - return buffers as AttributeBuffers + return buffers } // diff --git a/src/mol-gl/webgl/program.ts b/src/mol-gl/webgl/program.ts index f894cc1a328a1bea2bc61f0092a7a8f2117ec2f9..6d9658a6613deaa3e80a4009a8964e42a284e789 100644 --- a/src/mol-gl/webgl/program.ts +++ b/src/mol-gl/webgl/program.ts @@ -1,15 +1,14 @@ /** - * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info. + * Copyright (c) 2018-2019 mol* contributors, licensed under MIT, See LICENSE file for more info. * * @author Alexander Rose <alexander.rose@weirdbyte.de> */ import { ShaderCode, DefineValues, addShaderDefines } from '../shader-code' import { WebGLContext } from './context'; -import { UniformValues, getUniformSetters } from './uniform'; +import { getUniformSetters, UniformsList } from './uniform'; import { AttributeBuffers } from './buffer'; -// import { AttributeBuffers, UniformBuffers, createUniformBuffer } from './buffer'; -import { Textures, TextureId } from './texture'; +import { TextureId, Textures } from './texture'; import { createReferenceCache, ReferenceCache } from 'mol-util/reference-cache'; import { idFactory } from 'mol-util/id-factory'; import { RenderableSchema } from '../renderable/schema'; @@ -21,7 +20,7 @@ export interface Program { readonly id: number use: () => void - setUniforms: (uniformValues: UniformValues) => void + setUniforms: (uniformValues: UniformsList) => void bindAttributes: (attribueBuffers: AttributeBuffers) => void bindTextures: (textures: Textures) => void @@ -88,32 +87,26 @@ export function createProgram(ctx: WebGLContext, props: ProgramProps): Program { ctx.currentProgramId = programId gl.useProgram(program) }, - setUniforms: (uniformValues: UniformValues) => { - const uniformKeys = Object.keys(uniformValues) - for (let i = 0, il = uniformKeys.length; i < il; ++i) { - const k = uniformKeys[i] - const l = locations[k] - const v = uniformValues[k] - if (v) uniformSetters[k](gl, l, v.ref.value) + setUniforms: (uniformValues: UniformsList) => { + for (let i = 0, il = uniformValues.length; i < il; ++i) { + const [k, v] = uniformValues[i] + if (v) uniformSetters[k](gl, locations[k], v.ref.value) } }, bindAttributes: (attribueBuffers: AttributeBuffers) => { - const attributeKeys = Object.keys(attribueBuffers) - for (let i = 0, il = attributeKeys.length; i < il; ++i) { - const k = attributeKeys[i] + for (let i = 0, il = attribueBuffers.length; i < il; ++i) { + const [k, buffer] = attribueBuffers[i] const l = locations[k] - if (l !== -1) attribueBuffers[k].bind(l) + if (l !== -1) buffer.bind(l) } }, bindTextures: (textures: Textures) => { - const textureKeys = Object.keys(textures) - for (let i = 0, il = textureKeys.length; i < il; ++i) { - const k = textureKeys[i] - const l = locations[k] - textures[k].bind(i as TextureId) + for (let i = 0, il = textures.length; i < il; ++i) { + const [k, texture] = textures[i] + texture.bind(i as TextureId) // TODO if the order and count of textures in a material can be made invariant // this needs to be set only when the material changes - uniformSetters[k](gl, l, i as TextureId) + uniformSetters[k](gl, locations[k], i as TextureId) } }, diff --git a/src/mol-gl/webgl/render-item.ts b/src/mol-gl/webgl/render-item.ts index 6809b6c3c5f7427eb4dd204258e6fb6d05537964..5c64e5879f3e119bb658dacb6418cff19e4a5d4f 100644 --- a/src/mol-gl/webgl/render-item.ts +++ b/src/mol-gl/webgl/render-item.ts @@ -9,7 +9,7 @@ import { createTextures } from './texture'; import { WebGLContext } from './context'; import { ShaderCode } from '../shader-code'; import { Program } from './program'; -import { RenderableSchema, RenderableValues, AttributeSpec, getValueVersions, splitValues, Values, splitKeys } from '../renderable/schema'; +import { RenderableSchema, RenderableValues, AttributeSpec, getValueVersions, splitValues, Values } from '../renderable/schema'; import { idFactory } from 'mol-util/id-factory'; import { deleteVertexArray, createVertexArray } from './vertex-array'; import { ValueCell } from 'mol-util'; @@ -58,7 +58,6 @@ interface ValueChanges { defines: boolean elements: boolean textures: boolean - // uniforms: boolean } function createValueChanges() { return { @@ -88,7 +87,11 @@ export function createRenderItem(ctx: WebGLContext, drawMode: DrawMode, shaderCo const { instancedArrays, vertexArrayObject } = ctx.extensions const { attributeValues, defineValues, textureValues, uniformValues, materialUniformValues } = splitValues(schema, values) - const { attributeKeys, defineKeys, textureKeys } = splitKeys(schema) + + const uniformValueEntries = Object.entries(uniformValues) + const materialUniformValueEntries = Object.entries(materialUniformValues) + const defineValueEntries = Object.entries(defineValues) + const versions = getValueVersions(values) const glDrawMode = getDrawMode(ctx, drawMode) @@ -136,10 +139,10 @@ export function createRenderItem(ctx: WebGLContext, drawMode: DrawMode, shaderCo if (drawCount === 0 || instanceCount === 0) return const program = programs[variant].value const vertexArray = vertexArrays[variant] - program.setUniforms(uniformValues) + program.setUniforms(uniformValueEntries) if (materialId === -1 || materialId !== ctx.currentMaterialId) { // console.log('materialId changed or -1', materialId) - program.setUniforms(materialUniformValues) + program.setUniforms(materialUniformValueEntries) ctx.currentMaterialId = materialId } program.bindTextures(textures) @@ -160,9 +163,8 @@ export function createRenderItem(ctx: WebGLContext, drawMode: DrawMode, shaderCo update: () => { resetValueChanges(valueChanges) - for (let i = 0, il = defineKeys.length; i < il; ++i) { - const k = defineKeys[i] - const value = defineValues[k] + for (let i = 0, il = defineValueEntries.length; i < il; ++i) { + const [k, value] = defineValueEntries[i] if (value.ref.version !== versions[k]) { // console.log('define version changed', k) valueChanges.defines = true @@ -198,11 +200,10 @@ export function createRenderItem(ctx: WebGLContext, drawMode: DrawMode, shaderCo versions.instanceCount = values.instanceCount.ref.version } - for (let i = 0, il = attributeKeys.length; i < il; ++i) { - const k = attributeKeys[i] + for (let i = 0, il = attributeBuffers.length; i < il; ++i) { + const [k, buffer] = attributeBuffers[i] const value = attributeValues[k] if (value.ref.version !== versions[k]) { - const buffer = attributeBuffers[k] if (buffer.length >= value.ref.value.length) { // console.log('attribute array large enough to update', k, value.ref.id, value.ref.version) buffer.updateData(value.ref.value) @@ -210,7 +211,7 @@ export function createRenderItem(ctx: WebGLContext, drawMode: DrawMode, shaderCo // console.log('attribute array to small, need to create new attribute', k, value.ref.id, value.ref.version) buffer.destroy() const { itemSize, divisor } = schema[k] as AttributeSpec<ArrayKind> - attributeBuffers[k] = createAttributeBuffer(ctx, value.ref.value, itemSize, divisor) + attributeBuffers[i] = [k, createAttributeBuffer(ctx, value.ref.value, itemSize, divisor)] valueChanges.attributes = true } versions[k] = value.ref.version @@ -247,14 +248,14 @@ export function createRenderItem(ctx: WebGLContext, drawMode: DrawMode, shaderCo } } - for (let i = 0, il = textureKeys.length; i < il; ++i) { - const k = textureKeys[i] + for (let i = 0, il = textures.length; i < il; ++i) { + const [k, texture] = textures[i] const value = textureValues[k] if (value.ref.version !== versions[k]) { // update of textures with kind 'texture' is done externally if (schema[k].kind !== 'texture') { // console.log('texture version changed, uploading image', k) - textures[k].load(value.ref.value as TextureImage<any> | TextureVolume<any>) + texture.load(value.ref.value as TextureImage<any> | TextureVolume<any>) versions[k] = value.ref.version valueChanges.textures = true } @@ -269,13 +270,13 @@ export function createRenderItem(ctx: WebGLContext, drawMode: DrawMode, shaderCo programs[k].free() deleteVertexArray(ctx, vertexArrays[k]) }) - Object.keys(textures).forEach(k => { + textures.forEach(([k, texture]) => { // lifetime of textures with kind 'texture' is defined externally if (schema[k].kind !== 'texture') { - textures[k].destroy() + texture.destroy() } }) - Object.keys(attributeBuffers).forEach(k => attributeBuffers[k].destroy()) + attributeBuffers.forEach(([_, buffer]) => buffer.destroy()) if (elementsBuffer) elementsBuffer.destroy() destroyed = true } diff --git a/src/mol-gl/webgl/texture.ts b/src/mol-gl/webgl/texture.ts index c5128cc4ad2ed9eb3faee3ba3e2bf887ba858adc..5a24bf8bf38fcdf90470cae98e82c2d8b0092b2e 100644 --- a/src/mol-gl/webgl/texture.ts +++ b/src/mol-gl/webgl/texture.ts @@ -1,5 +1,5 @@ /** - * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info. + * Copyright (c) 2018-2019 mol* contributors, licensed under MIT, See LICENSE file for more info. * * @author Alexander Rose <alexander.rose@weirdbyte.de> */ @@ -139,7 +139,7 @@ export interface Texture { export type TextureId = 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 export type TextureValues = { [k: string]: ValueCell<TextureValueType> } -export type Textures = { [k: string]: Texture } +export type Textures = [string, Texture][] export function createTexture(ctx: WebGLContext, kind: TextureKind, _format: TextureFormat, _type: TextureType, _filter: TextureFilter): Texture { const id = getNextTextureId() @@ -244,16 +244,16 @@ export function createTexture(ctx: WebGLContext, kind: TextureKind, _format: Tex } export function createTextures(ctx: WebGLContext, schema: RenderableSchema, values: TextureValues) { - const textures: Textures = {} + const textures: Textures = [] Object.keys(schema).forEach((k, i) => { const spec = schema[k] if (spec.type === 'texture') { if (spec.kind === 'texture') { - textures[k] = values[k].ref.value as Texture + textures[textures.length] = [k, values[k].ref.value as Texture] } else { const texture = createTexture(ctx, spec.kind, spec.format, spec.dataType, spec.filter) texture.load(values[k].ref.value as TextureImage<any> | TextureVolume<any>) - textures[k] = texture + textures[textures.length] = [k, texture] } } }) diff --git a/src/mol-gl/webgl/uniform.ts b/src/mol-gl/webgl/uniform.ts index a979a64fee9228f01f052d39aa94f067a2289807..d7e9a123cabc377ed632b68f53777fcf23f5c0fe 100644 --- a/src/mol-gl/webgl/uniform.ts +++ b/src/mol-gl/webgl/uniform.ts @@ -1,5 +1,5 @@ /** - * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info. + * Copyright (c) 2018-2019 mol* contributors, licensed under MIT, See LICENSE file for more info. * * @author Alexander Rose <alexander.rose@weirdbyte.de> */ @@ -23,6 +23,7 @@ export type UniformKind = keyof UniformKindValue export type UniformType = number | Vec2 | Vec3 | Vec4 | Mat3 | Mat4 export type UniformValues = { [k: string]: ValueCell<UniformType> } +export type UniformsList = [string, ValueCell<UniformType>][] export function setUniform(gl: GLRenderingContext, location: WebGLUniformLocation | null, kind: UniformKind, value: any) { switch (kind) { diff --git a/src/mol-gl/webgl/vertex-array.ts b/src/mol-gl/webgl/vertex-array.ts index f6a2315180e2c1cac18bb253fffe65abbd622599..b6bd48a8bdfef9f3a328f1be4bcf83d3014e944c 100644 --- a/src/mol-gl/webgl/vertex-array.ts +++ b/src/mol-gl/webgl/vertex-array.ts @@ -6,7 +6,7 @@ import { WebGLContext } from './context'; import { Program } from './program'; -import { AttributeBuffers, ElementsBuffer } from './buffer'; +import { ElementsBuffer, AttributeBuffers } from './buffer'; export function createVertexArray(ctx: WebGLContext, program: Program, attributeBuffers: AttributeBuffers, elementsBuffer?: ElementsBuffer) { const { vertexArrayObject } = ctx.extensions