uniform.ts 3.0 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586
  1. /**
  2. * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info.
  3. *
  4. * @author Alexander Rose <alexander.rose@weirdbyte.de>
  5. */
  6. import { Mat3, Mat4, Vec2, Vec3, Vec4 } from 'mol-math/linear-algebra'
  7. import { Context } from './context';
  8. import { TextureImage } from '../renderable/util';
  9. import { ValueCell } from 'mol-util';
  10. import { RenderableSchema } from '../renderable/schema';
  11. export type UniformKindValue = {
  12. 'f': number
  13. 'i': number
  14. 'v2': Vec2
  15. 'v3': Vec3
  16. 'v4': Vec4
  17. 'm3': Mat3
  18. 'm4': Mat4
  19. 't2': number
  20. }
  21. export type UniformKind = keyof UniformKindValue
  22. export type UniformType = number | Vec2 | Vec3 | Vec4 | Mat3 | Mat4 | TextureImage
  23. export interface UniformUpdater {
  24. set: (value: UniformType) => void,
  25. clear: () => void
  26. }
  27. export type UniformValues = { [k: string]: ValueCell<UniformType> }
  28. export type UniformUpdaters = { [k: string]: UniformUpdater }
  29. function createUniformSetter(ctx: Context, program: WebGLProgram, name: string, kind: UniformKind): (value: any) => void {
  30. const { gl } = ctx
  31. const location = gl.getUniformLocation(program, name)
  32. if (location === null) {
  33. // console.info(`Could not get WebGL uniform location for '${name}'`)
  34. }
  35. switch (kind) {
  36. case 'f': return (value: number) => gl.uniform1f(location, value)
  37. case 'i': case 't2': return (value: number) => gl.uniform1i(location, value)
  38. case 'v2': return (value: Vec2) => gl.uniform2fv(location, value)
  39. case 'v3': return (value: Vec3) => gl.uniform3fv(location, value)
  40. case 'v4': return (value: Vec4) => gl.uniform4fv(location, value)
  41. case 'm3': return (value: Mat3) => gl.uniformMatrix3fv(location, false, value)
  42. case 'm4': return (value: Mat4) => gl.uniformMatrix4fv(location, false, value)
  43. }
  44. }
  45. function createUniformUpdater(ctx: Context, program: WebGLProgram, name: string, kind: UniformKind): UniformUpdater {
  46. const setter = createUniformSetter(ctx, program, name, kind)
  47. let _value: UniformType | undefined = undefined
  48. return {
  49. set: value => {
  50. if (_value !== value) {
  51. setter(value)
  52. _value = value
  53. }
  54. },
  55. clear: () => {
  56. _value = undefined
  57. }
  58. }
  59. }
  60. export function getUniformUpdaters(ctx: Context, program: WebGLProgram, schema: RenderableSchema) {
  61. const updaters: UniformUpdaters = {}
  62. Object.keys(schema).forEach(k => {
  63. const spec = schema[k]
  64. if (spec.type === 'uniform') {
  65. updaters[k] = createUniformUpdater(ctx, program, k, spec.kind)
  66. }
  67. })
  68. return updaters
  69. }
  70. export function getTextureUniformUpdaters(ctx: Context, program: WebGLProgram, schema: RenderableSchema) {
  71. const updaters: UniformUpdaters = {}
  72. Object.keys(schema).forEach(k => {
  73. const spec = schema[k]
  74. if (spec.type === 'texture') {
  75. updaters[k] = createUniformUpdater(ctx, program, k, 't2')
  76. }
  77. })
  78. return updaters
  79. }