uniform.ts 3.1 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485
  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 { WebGLContext } from './context';
  8. import { ValueCell } from 'mol-util';
  9. import { RenderableSchema } from '../renderable/schema';
  10. export type UniformKindValue = {
  11. 'f': number
  12. 'i': number
  13. 'v2': Vec2
  14. 'v3': Vec3
  15. 'v4': Vec4
  16. 'm3': Mat3
  17. 'm4': Mat4
  18. 't': number
  19. }
  20. export type UniformKind = keyof UniformKindValue
  21. export type UniformType = number | Vec2 | Vec3 | Vec4 | Mat3 | Mat4
  22. export interface UniformUpdater {
  23. set: (value: UniformType) => void,
  24. clear: () => void
  25. }
  26. export type UniformValues = { [k: string]: ValueCell<UniformType> }
  27. export type UniformUpdaters = { [k: string]: UniformUpdater }
  28. function createUniformSetter(ctx: WebGLContext, program: WebGLProgram, name: string, kind: UniformKind): (value: any) => void {
  29. const { gl } = ctx
  30. const location = gl.getUniformLocation(program, name)
  31. if (location === null) {
  32. // console.info(`Could not get WebGL uniform location for '${name}'`)
  33. }
  34. switch (kind) {
  35. case 'f': return (value: number) => gl.uniform1f(location, value)
  36. case 'i': case 't': return (value: number) => gl.uniform1i(location, value)
  37. case 'v2': return (value: Vec2) => (gl as WebGLRenderingContext).uniform2fv(location, value) // TODO remove cast when webgl2 types are fixed
  38. case 'v3': return (value: Vec3) => (gl as WebGLRenderingContext).uniform3fv(location, value)
  39. case 'v4': return (value: Vec4) => (gl as WebGLRenderingContext).uniform4fv(location, value)
  40. case 'm3': return (value: Mat3) => (gl as WebGLRenderingContext).uniformMatrix3fv(location, false, value)
  41. case 'm4': return (value: Mat4) => (gl as WebGLRenderingContext).uniformMatrix4fv(location, false, value)
  42. }
  43. }
  44. function createUniformUpdater(ctx: WebGLContext, program: WebGLProgram, name: string, kind: UniformKind): UniformUpdater {
  45. const setter = createUniformSetter(ctx, program, name, kind)
  46. let _value: UniformType | undefined = undefined
  47. return {
  48. set: value => {
  49. if (_value !== value) {
  50. setter(value)
  51. _value = value
  52. }
  53. },
  54. clear: () => {
  55. _value = undefined
  56. }
  57. }
  58. }
  59. export function getUniformUpdaters(ctx: WebGLContext, program: WebGLProgram, schema: RenderableSchema) {
  60. const updaters: UniformUpdaters = {}
  61. Object.keys(schema).forEach(k => {
  62. const spec = schema[k]
  63. if (spec.type === 'uniform') {
  64. updaters[k] = createUniformUpdater(ctx, program, k, spec.kind)
  65. }
  66. })
  67. return updaters
  68. }
  69. export function getTextureUniformUpdaters(ctx: WebGLContext, program: WebGLProgram, schema: RenderableSchema) {
  70. const updaters: UniformUpdaters = {}
  71. Object.keys(schema).forEach(k => {
  72. const spec = schema[k]
  73. if (spec.type === 'texture') {
  74. updaters[k] = createUniformUpdater(ctx, program, k, 't')
  75. }
  76. })
  77. return updaters
  78. }