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

wip, refactoring uniform handling

parent 203e7152
No related branches found
No related tags found
No related merge requests found
...@@ -6,9 +6,9 @@ ...@@ -6,9 +6,9 @@
import { ShaderCode, DefineValues, addShaderDefines } from '../shader-code' import { ShaderCode, DefineValues, addShaderDefines } from '../shader-code'
import { WebGLContext } from './context'; import { WebGLContext } from './context';
import { getUniformUpdaters, getTextureUniformUpdaters, UniformValues, UniformUpdater } from './uniform'; import { UniformValues, getUniformSetters } from './uniform';
import { AttributeBuffers } from './buffer'; import { AttributeBuffers } from './buffer';
import { TextureId, Textures } from './texture'; import { Textures, TextureId } from './texture';
import { createReferenceCache, ReferenceCache } from 'mol-util/reference-cache'; import { createReferenceCache, ReferenceCache } from 'mol-util/reference-cache';
import { idFactory } from 'mol-util/id-factory'; import { idFactory } from 'mol-util/id-factory';
import { RenderableSchema } from '../renderable/schema'; import { RenderableSchema } from '../renderable/schema';
...@@ -27,20 +27,21 @@ export interface Program { ...@@ -27,20 +27,21 @@ export interface Program {
destroy: () => void destroy: () => void
} }
type AttributeLocations = { [k: string]: number } type Locations = { [k: string]: number }
function getAttributeLocations(ctx: WebGLContext, program: WebGLProgram, schema: RenderableSchema) { function getLocations(ctx: WebGLContext, program: WebGLProgram, schema: RenderableSchema) {
const { gl } = ctx const { gl } = ctx
const locations: AttributeLocations = {} const locations: Locations = {}
gl.useProgram(program)
Object.keys(schema).forEach(k => { Object.keys(schema).forEach(k => {
const spec = schema[k] const spec = schema[k]
if (spec.type === 'attribute') { if (spec.type === 'attribute') {
const loc = gl.getAttribLocation(program, k) const loc = gl.getAttribLocation(program, k)
// if (loc === -1) { // if (loc === -1) console.info(`Could not get attribute location for '${k}'`)
// console.info(`Could not get attribute location for '${k}'`)
// }
locations[k] = loc locations[k] = loc
} else if (spec.type === 'uniform' || spec.type === 'texture') {
const loc = gl.getUniformLocation(program, k)
// if (loc === null) console.info(`Could not get uniform location for '${k}'`)
locations[k] = loc as number
} }
}) })
return locations return locations
...@@ -69,18 +70,12 @@ export function createProgram(ctx: WebGLContext, props: ProgramProps): Program { ...@@ -69,18 +70,12 @@ export function createProgram(ctx: WebGLContext, props: ProgramProps): Program {
vertShaderRef.value.attach(program) vertShaderRef.value.attach(program)
fragShaderRef.value.attach(program) fragShaderRef.value.attach(program)
gl.linkProgram(program) gl.linkProgram(program)
if (!gl.getProgramParameter(program, gl.LINK_STATUS)){ if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
throw new Error(`Could not compile WebGL program. \n\n${gl.getProgramInfoLog(program)}`); throw new Error(`Could not compile WebGL program. \n\n${gl.getProgramInfoLog(program)}`);
} }
const uniformUpdaters = getUniformUpdaters(ctx, program, schema) const locations = getLocations(ctx, program, schema)
const attributeLocations = getAttributeLocations(ctx, program, schema) const uniformSetters = getUniformSetters(schema)
const textureUniformUpdaters = getTextureUniformUpdaters(ctx, program, schema)
const _uniformUpdaters: [string, UniformUpdater][] = []
Object.keys(uniformUpdaters).forEach(k => {
_uniformUpdaters.push([k, uniformUpdaters[k]])
})
let destroyed = false let destroyed = false
...@@ -93,23 +88,30 @@ export function createProgram(ctx: WebGLContext, props: ProgramProps): Program { ...@@ -93,23 +88,30 @@ export function createProgram(ctx: WebGLContext, props: ProgramProps): Program {
gl.useProgram(program) gl.useProgram(program)
}, },
setUniforms: (uniformValues: UniformValues) => { setUniforms: (uniformValues: UniformValues) => {
for (let i = 0, il = _uniformUpdaters.length; i < il; ++i) { const uniformKeys = Object.keys(uniformValues)
const [k, uu] = _uniformUpdaters[i] for (let i = 0, il = uniformKeys.length; i < il; ++i) {
const uv = uniformValues[k] const k = uniformKeys[i]
if (uv !== undefined) uu.set(uv.ref.value) const l = locations[k]
const v = uniformValues[k]
if (v) uniformSetters[k](gl, l, v.ref.value)
} }
}, },
bindAttributes: (attribueBuffers: AttributeBuffers) => { bindAttributes: (attribueBuffers: AttributeBuffers) => {
Object.keys(attribueBuffers).forEach(k => { const attributeKeys = Object.keys(attribueBuffers)
const loc = attributeLocations[k] for (let i = 0, il = attributeKeys.length; i < il; ++i) {
if (loc !== -1) attribueBuffers[k].bind(loc) const k = attributeKeys[i]
}) const l = locations[k]
if (l !== -1) attribueBuffers[k].bind(l)
}
}, },
bindTextures: (textures: Textures) => { bindTextures: (textures: Textures) => {
Object.keys(textures).forEach((k, i) => { 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) textures[k].bind(i as TextureId)
textureUniformUpdaters[k].set(i) uniformSetters[k](gl, l, i as TextureId)
}) }
}, },
destroy: () => { destroy: () => {
......
...@@ -5,9 +5,9 @@ ...@@ -5,9 +5,9 @@
*/ */
import { Mat3, Mat4, Vec2, Vec3, Vec4 } from 'mol-math/linear-algebra' import { Mat3, Mat4, Vec2, Vec3, Vec4 } from 'mol-math/linear-algebra'
import { WebGLContext } from './context'; import { ValueCell } from 'mol-util';
import { ValueCell, arrayEqual } from 'mol-util'; import { GLRenderingContext } from './compat';
import { RenderableSchema } from '../renderable/schema'; import { RenderableSchema } from 'mol-gl/renderable/schema';
export type UniformKindValue = { export type UniformKindValue = {
'f': number 'f': number
...@@ -21,63 +21,55 @@ export type UniformKindValue = { ...@@ -21,63 +21,55 @@ export type UniformKindValue = {
} }
export type UniformKind = keyof UniformKindValue export type UniformKind = keyof UniformKindValue
export type UniformType = number | Vec2 | Vec3 | Vec4 | Mat3 | Mat4 export type UniformType = number | Vec2 | Vec3 | Vec4 | Mat3 | Mat4
export interface UniformUpdater {
set: (value: UniformType) => void,
clear: () => void
}
export type UniformValues = { [k: string]: ValueCell<UniformType> } export type UniformValues = { [k: string]: ValueCell<UniformType> }
export type UniformUpdaters = { [k: string]: UniformUpdater }
function createUniformSetter(ctx: WebGLContext, program: WebGLProgram, name: string, kind: UniformKind): (value: any) => void { export function setUniform(gl: GLRenderingContext, location: WebGLUniformLocation | null, kind: UniformKind, value: any) {
const { gl } = ctx
const location = gl.getUniformLocation(program, name)
if (location === null) {
// console.info(`Could not get WebGL uniform location for '${name}'`)
}
switch (kind) { switch (kind) {
case 'f': return (value: number) => gl.uniform1f(location, value) case 'f': gl.uniform1f(location, value); break
case 'i': case 't': return (value: number) => gl.uniform1i(location, value) case 'i': case 't': gl.uniform1i(location, value); break
case 'v2': return (value: Vec2) => (gl as WebGLRenderingContext).uniform2fv(location, value) // TODO remove cast when webgl2 types are fixed case 'v2': gl.uniform2fv(location, value); break
case 'v3': return (value: Vec3) => (gl as WebGLRenderingContext).uniform3fv(location, value) case 'v3': gl.uniform3fv(location, value); break
case 'v4': return (value: Vec4) => (gl as WebGLRenderingContext).uniform4fv(location, value) case 'v4': gl.uniform4fv(location, value); break
case 'm3': return (value: Mat3) => (gl as WebGLRenderingContext).uniformMatrix3fv(location, false, value) case 'm3': gl.uniformMatrix3fv(location, false, value); break
case 'm4': return (value: Mat4) => (gl as WebGLRenderingContext).uniformMatrix4fv(location, false, value) case 'm4': gl.uniformMatrix4fv(location, false, value); break
default: console.error(`unknown uniform kind '${kind}'`)
} }
} }
function createUniformUpdater(ctx: WebGLContext, program: WebGLProgram, name: string, kind: UniformKind): UniformUpdater { export type UniformSetter = (gl: GLRenderingContext, location: number, value: any) => void
const setter = createUniformSetter(ctx, program, name, kind) export type UniformSetters = { [k: string]: UniformSetter }
let _value: UniformType | undefined = undefined
return { function uniform1f (gl: GLRenderingContext, location: number, value: any) { gl.uniform1f(location, value) }
set: value => { function uniform1i (gl: GLRenderingContext, location: number, value: any) { gl.uniform1i(location, value) }
if (_value !== value || (Array.isArray(_value) && Array.isArray(value) && arrayEqual(_value, value))) { function uniform2fv (gl: GLRenderingContext, location: number, value: any) { gl.uniform2fv(location, value) }
setter(value) function uniform3fv (gl: GLRenderingContext, location: number, value: any) { gl.uniform3fv(location, value) }
_value = value function uniform4fv (gl: GLRenderingContext, location: number, value: any) { gl.uniform4fv(location, value) }
} function uniformMatrix3fv (gl: GLRenderingContext, location: number, value: any) { gl.uniformMatrix3fv(location, false, value) }
}, function uniformMatrix4fv (gl: GLRenderingContext, location: number, value: any) { gl.uniformMatrix4fv(location, false, value) }
clear: () => { _value = undefined }
function getUniformSetter(kind: UniformKind) {
switch (kind) {
case 'f': return uniform1f
case 'i': case 't': return uniform1i
case 'v2': return uniform2fv
case 'v3': return uniform3fv
case 'v4': return uniform4fv
case 'm3': return uniformMatrix3fv
case 'm4': return uniformMatrix4fv
} }
throw new Error(`unknown uniform kind '${kind}'`)
} }
export function getUniformUpdaters(ctx: WebGLContext, program: WebGLProgram, schema: RenderableSchema) { export function getUniformSetters(schema: RenderableSchema) {
const updaters: UniformUpdaters = {} const setters: UniformSetters = {}
Object.keys(schema).forEach(k => { Object.keys(schema).forEach(k => {
const spec = schema[k] const spec = schema[k]
if (spec.type === 'uniform') { if (spec.type === 'uniform') {
updaters[k] = createUniformUpdater(ctx, program, k, spec.kind) setters[k] = getUniformSetter(spec.kind as UniformKind)
} } else if (spec.type === 'texture') {
}) setters[k] = getUniformSetter('t')
return updaters
}
export function getTextureUniformUpdaters(ctx: WebGLContext, program: WebGLProgram, schema: RenderableSchema) {
const updaters: UniformUpdaters = {}
Object.keys(schema).forEach(k => {
const spec = schema[k]
if (spec.type === 'texture') {
updaters[k] = createUniformUpdater(ctx, program, k, 't')
} }
}) })
return updaters return setters
} }
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment