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

renderer refactoring (avoid object usage)

parent 8ebd2642
No related branches found
No related tags found
No related merge requests found
......@@ -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> = {}
......
......@@ -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
}
......
......@@ -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
}
//
......
/**
* 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)
}
},
......
......@@ -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
}
......
/**
* 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]
}
}
})
......
/**
* 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) {
......
......@@ -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
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment