schema.ts 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265
  1. /**
  2. * Copyright (c) 2018-2020 mol* contributors, licensed under MIT, See LICENSE file for more info.
  3. *
  4. * @author Alexander Rose <alexander.rose@weirdbyte.de>
  5. */
  6. import { ValueCell } from '../../mol-util';
  7. import { AttributeItemSize, ElementsKind, AttributeValues, AttributeKind, DataTypeArrayType } from '../webgl/buffer';
  8. import { UniformKind, UniformValues, UniformKindValue } from '../webgl/uniform';
  9. import { DefineKind, DefineValues } from '../shader-code';
  10. import { Mat4 } from '../../mol-math/linear-algebra';
  11. import { TextureValues, TextureType, TextureFormat, TextureFilter, TextureKind, TextureKindValue } from '../webgl/texture';
  12. import { Sphere3D } from '../../mol-math/geometry';
  13. export type ValueKindType = {
  14. 'number': number
  15. 'string': string
  16. 'boolean': boolean
  17. 'any': any
  18. 'm4': Mat4,
  19. 'float32': Float32Array
  20. 'sphere': Sphere3D
  21. }
  22. export type ValueKind = keyof ValueKindType
  23. //
  24. export type KindValue = UniformKindValue & DataTypeArrayType & TextureKindValue & ValueKindType
  25. export type Values<S extends RenderableSchema> = { readonly [k in keyof S]: ValueCell<KindValue[S[k]['kind']]> }
  26. export function splitValues(schema: RenderableSchema, values: RenderableValues) {
  27. const attributeValues: AttributeValues = {};
  28. const defineValues: DefineValues = {};
  29. const textureValues: TextureValues = {};
  30. const uniformValues: UniformValues = {};
  31. const materialUniformValues: UniformValues = {};
  32. Object.keys(schema).forEach(k => {
  33. const spec = schema[k];
  34. if (spec.type === 'attribute') attributeValues[k] = values[k];
  35. if (spec.type === 'define') defineValues[k] = values[k];
  36. if (spec.type === 'texture') textureValues[k] = values[k];
  37. // check if k exists in values so that global uniforms are excluded here
  38. if (spec.type === 'uniform' && values[k] !== undefined) {
  39. if (spec.isMaterial) materialUniformValues[k] = values[k];
  40. else uniformValues[k] = values[k];
  41. }
  42. });
  43. return { attributeValues, defineValues, textureValues, uniformValues, materialUniformValues };
  44. }
  45. export type Versions<T extends RenderableValues> = { [k in keyof T]: number }
  46. export function getValueVersions<T extends RenderableValues>(values: T) {
  47. const versions: Versions<any> = {};
  48. Object.keys(values).forEach(k => {
  49. versions[k] = values[k].ref.version;
  50. });
  51. return versions as Versions<T>;
  52. }
  53. //
  54. export type AttributeSpec<K extends AttributeKind> = { type: 'attribute', kind: K, itemSize: AttributeItemSize, divisor: number }
  55. export function AttributeSpec<K extends AttributeKind>(kind: K, itemSize: AttributeItemSize, divisor: number): AttributeSpec<K> {
  56. return { type: 'attribute', kind, itemSize, divisor };
  57. }
  58. export type UniformSpec<K extends UniformKind> = { type: 'uniform', kind: K, isMaterial: boolean }
  59. export function UniformSpec<K extends UniformKind>(kind: K, isMaterial = false): UniformSpec<K> {
  60. return { type: 'uniform', kind, isMaterial };
  61. }
  62. export type TextureSpec<K extends TextureKind> = { type: 'texture', kind: K, format: TextureFormat, dataType: TextureType, filter: TextureFilter }
  63. export function TextureSpec<K extends TextureKind>(kind: K, format: TextureFormat, dataType: TextureType, filter: TextureFilter): TextureSpec<K> {
  64. return { type: 'texture', kind, format, dataType, filter };
  65. }
  66. export type ElementsSpec<K extends ElementsKind> = { type: 'elements', kind: K }
  67. export function ElementsSpec<K extends ElementsKind>(kind: K): ElementsSpec<K> {
  68. return { type: 'elements', kind };
  69. }
  70. export type DefineSpec<K extends DefineKind> = { type: 'define', kind: K, options?: string[] }
  71. export function DefineSpec<K extends DefineKind>(kind: K, options?: string[]): DefineSpec<K> {
  72. return { type: 'define', kind, options };
  73. }
  74. export type ValueSpec<K extends ValueKind> = { type: 'value', kind: K }
  75. export function ValueSpec<K extends ValueKind>(kind: K): ValueSpec<K> {
  76. return { type: 'value', kind };
  77. }
  78. //
  79. export type RenderableSchema = {
  80. readonly [k: string]: (
  81. AttributeSpec<AttributeKind> | UniformSpec<UniformKind> | TextureSpec<TextureKind> |
  82. ValueSpec<ValueKind> | DefineSpec<DefineKind> | ElementsSpec<ElementsKind>
  83. )
  84. }
  85. export type RenderableValues = { readonly [k: string]: ValueCell<any> }
  86. //
  87. export const GlobalUniformSchema = {
  88. uModel: UniformSpec('m4'),
  89. uView: UniformSpec('m4'),
  90. uInvView: UniformSpec('m4'),
  91. uModelView: UniformSpec('m4'),
  92. uInvModelView: UniformSpec('m4'),
  93. uProjection: UniformSpec('m4'),
  94. uInvProjection: UniformSpec('m4'),
  95. uModelViewProjection: UniformSpec('m4'),
  96. uInvModelViewProjection: UniformSpec('m4'),
  97. uIsOrtho: UniformSpec('f'),
  98. uPixelRatio: UniformSpec('f'),
  99. uViewportHeight: UniformSpec('f'),
  100. uViewport: UniformSpec('v4'),
  101. uViewOffset: UniformSpec('v2'),
  102. uCameraPosition: UniformSpec('v3'),
  103. uNear: UniformSpec('f'),
  104. uFar: UniformSpec('f'),
  105. uFogNear: UniformSpec('f'),
  106. uFogFar: UniformSpec('f'),
  107. uFogColor: UniformSpec('v3'),
  108. uTransparentBackground: UniformSpec('i'),
  109. uClipObjectType: UniformSpec('i[]'),
  110. uClipObjectPosition: UniformSpec('v3[]'),
  111. uClipObjectRotation: UniformSpec('v4[]'),
  112. uClipObjectScale: UniformSpec('v3[]'),
  113. // all the following could in principle be per object
  114. // as a kind of 'material' parameter set
  115. // would need to test performance implications
  116. uLightIntensity: UniformSpec('f'),
  117. uAmbientIntensity: UniformSpec('f'),
  118. uMetalness: UniformSpec('f'),
  119. uRoughness: UniformSpec('f'),
  120. uReflectivity: UniformSpec('f'),
  121. uPickingAlphaThreshold: UniformSpec('f'),
  122. uInteriorDarkening: UniformSpec('f'),
  123. uInteriorColorFlag: UniformSpec('i'),
  124. uInteriorColor: UniformSpec('v3'),
  125. uHighlightColor: UniformSpec('v3'),
  126. uSelectColor: UniformSpec('v3'),
  127. } as const;
  128. export type GlobalUniformSchema = typeof GlobalUniformSchema
  129. export type GlobalUniformValues = Values<GlobalUniformSchema> // { [k in keyof GlobalUniformSchema]: ValueCell<any> }
  130. export const InternalSchema = {
  131. uObjectId: UniformSpec('i'),
  132. } as const;
  133. export type InternalSchema = typeof InternalSchema
  134. export type InternalValues = { [k in keyof InternalSchema]: ValueCell<any> }
  135. export const ColorSchema = {
  136. // aColor: AttributeSpec('float32', 3, 0), // TODO
  137. uColor: UniformSpec('v3', true),
  138. uColorTexDim: UniformSpec('v2'),
  139. tColor: TextureSpec('image-uint8', 'rgb', 'ubyte', 'nearest'),
  140. dColorType: DefineSpec('string', ['uniform', 'attribute', 'instance', 'group', 'group_instance']),
  141. } as const;
  142. export type ColorSchema = typeof ColorSchema
  143. export type ColorValues = Values<ColorSchema>
  144. export const SizeSchema = {
  145. // aSize: AttributeSpec('float32', 1, 0), // TODO
  146. uSize: UniformSpec('f', true),
  147. uSizeTexDim: UniformSpec('v2'),
  148. tSize: TextureSpec('image-uint8', 'rgb', 'ubyte', 'nearest'),
  149. dSizeType: DefineSpec('string', ['uniform', 'attribute', 'instance', 'group', 'group_instance']),
  150. uSizeFactor: UniformSpec('f'),
  151. } as const;
  152. export type SizeSchema = typeof SizeSchema
  153. export type SizeValues = Values<SizeSchema>
  154. export const MarkerSchema = {
  155. uMarkerTexDim: UniformSpec('v2'),
  156. tMarker: TextureSpec('image-uint8', 'alpha', 'ubyte', 'nearest'),
  157. } as const;
  158. export type MarkerSchema = typeof MarkerSchema
  159. export type MarkerValues = Values<MarkerSchema>
  160. export const OverpaintSchema = {
  161. uOverpaintTexDim: UniformSpec('v2'),
  162. tOverpaint: TextureSpec('image-uint8', 'rgba', 'ubyte', 'nearest'),
  163. dOverpaint: DefineSpec('boolean'),
  164. } as const;
  165. export type OverpaintSchema = typeof OverpaintSchema
  166. export type OverpaintValues = Values<OverpaintSchema>
  167. export const TransparencySchema = {
  168. uTransparencyTexDim: UniformSpec('v2'),
  169. tTransparency: TextureSpec('image-uint8', 'alpha', 'ubyte', 'nearest'),
  170. dTransparency: DefineSpec('boolean'),
  171. dTransparencyVariant: DefineSpec('string', ['single', 'multi']),
  172. } as const;
  173. export type TransparencySchema = typeof TransparencySchema
  174. export type TransparencyValues = Values<TransparencySchema>
  175. export const ClippingSchema = {
  176. dClipObjectCount: DefineSpec('number'),
  177. dClipVariant: DefineSpec('string', ['instance', 'pixel']),
  178. uClippingTexDim: UniformSpec('v2'),
  179. tClipping: TextureSpec('image-uint8', 'alpha', 'ubyte', 'nearest'),
  180. dClipping: DefineSpec('boolean'),
  181. } as const;
  182. export type ClippingSchema = typeof ClippingSchema
  183. export type ClippingValues = Values<ClippingSchema>
  184. export const BaseSchema = {
  185. ...ColorSchema,
  186. ...MarkerSchema,
  187. ...OverpaintSchema,
  188. ...TransparencySchema,
  189. ...ClippingSchema,
  190. aInstance: AttributeSpec('float32', 1, 1),
  191. aGroup: AttributeSpec('float32', 1, 0),
  192. /**
  193. * final per-instance transform calculated for instance `i` as
  194. * `aTransform[i] = matrix * transform[i] * extraTransform[i]`
  195. */
  196. aTransform: AttributeSpec('float32', 16, 1),
  197. /**
  198. * final alpha, calculated as `values.alpha * state.alpha`
  199. */
  200. uAlpha: UniformSpec('f', true),
  201. uInstanceCount: UniformSpec('i'),
  202. uGroupCount: UniformSpec('i'),
  203. uInvariantBoundingSphere: UniformSpec('v4'),
  204. drawCount: ValueSpec('number'),
  205. instanceCount: ValueSpec('number'),
  206. /** base alpha, see uAlpha */
  207. alpha: ValueSpec('number'),
  208. /** global transform, see aTransform */
  209. matrix: ValueSpec('m4'),
  210. /** base per-instance transform, see aTransform */
  211. transform: ValueSpec('float32'),
  212. /** additional per-instance transform, see aTransform */
  213. extraTransform: ValueSpec('float32'),
  214. /** denotes reflection in transform */
  215. hasReflection: ValueSpec('boolean'),
  216. /** bounding sphere taking aTransform into account and encompases all instances */
  217. boundingSphere: ValueSpec('sphere'),
  218. /** bounding sphere NOT taking aTransform into account */
  219. invariantBoundingSphere: ValueSpec('sphere'),
  220. } as const;
  221. export type BaseSchema = typeof BaseSchema
  222. export type BaseValues = Values<BaseSchema>