threepipe
Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.

NormalBufferPlugin.ts 5.0KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  1. import {
  2. BufferGeometry,
  3. Camera,
  4. Color,
  5. FrontSide,
  6. HalfFloatType,
  7. IUniform,
  8. LinearSRGBColorSpace,
  9. MeshNormalMaterial,
  10. NearestFilter,
  11. NoBlending,
  12. Object3D,
  13. Scene,
  14. TangentSpaceNormalMap,
  15. Texture,
  16. TextureDataType,
  17. WebGLRenderer,
  18. WebGLRenderTarget,
  19. } from 'three'
  20. import {GBufferRenderPass} from '../../postprocessing'
  21. import {ThreeViewer} from '../../viewer'
  22. import {IShaderPropertiesUpdater} from '../../materials'
  23. import {PipelinePassPlugin} from '../base/PipelinePassPlugin'
  24. import type {IMaterial, PhysicalMaterial} from '../../core'
  25. import {uiFolderContainer, uiImage} from 'uiconfig.js'
  26. export type NormalBufferPluginEventTypes = ''
  27. // type NormalBufferPluginTarget = WebGLMultipleRenderTargets | WebGLRenderTarget
  28. export type NormalBufferPluginTarget = WebGLRenderTarget
  29. export type NormalBufferPluginPass = GBufferRenderPass<'normal', NormalBufferPluginTarget>
  30. @uiFolderContainer('Normal Buffer Plugin')
  31. export class NormalBufferPlugin
  32. extends PipelinePassPlugin<NormalBufferPluginPass, 'normal', NormalBufferPluginEventTypes>
  33. implements IShaderPropertiesUpdater {
  34. readonly passId = 'normal'
  35. public static readonly PluginType = 'NormalBufferPlugin'
  36. target?: NormalBufferPluginTarget
  37. @uiImage('Normal Buffer' /* {readOnly: true}*/) texture?: Texture
  38. readonly material: MeshNormalMaterial = new MeshNormalMaterial2({
  39. blending: NoBlending,
  40. })
  41. // private _gbufferPass?: IFilter<GBufferRenderPass<WebGLMultipleRenderTargets>
  42. createPass(v: ThreeViewer) {
  43. if (!this.target) this.target = v.renderManager.createTarget<NormalBufferPluginTarget>(
  44. {
  45. depthBuffer: true,
  46. // samples: v.renderManager.composerTarget.samples || 0,
  47. samples: 0,
  48. type: this.bufferType,
  49. magFilter: NearestFilter,
  50. minFilter: NearestFilter,
  51. generateMipmaps: false,
  52. colorSpace: LinearSRGBColorSpace,
  53. })
  54. this.texture = this.target.texture
  55. this.texture.name = 'normalBuffer'
  56. this.material.userData.isGBufferMaterial = true
  57. const pass = new GBufferRenderPass('normal', this.target, this.material, new Color(0, 0, 0), 1)
  58. const preprocessMaterial = pass.preprocessMaterial
  59. pass.preprocessMaterial = (m) => preprocessMaterial(m, true)
  60. pass.before = ['render']
  61. pass.after = []
  62. pass.required = ['render']
  63. return pass
  64. }
  65. constructor(
  66. public readonly bufferType: TextureDataType = HalfFloatType,
  67. enabled = true,
  68. ) {
  69. super()
  70. this.enabled = enabled
  71. }
  72. onRemove(viewer: ThreeViewer): void {
  73. if (this.target) {
  74. viewer.renderManager.disposeTarget(this.target)
  75. this.target = undefined
  76. }
  77. return super.onRemove(viewer)
  78. }
  79. updateShaderProperties(material: {defines: Record<string, string | number | undefined>; uniforms: {[p: string]: IUniform}}): this {
  80. if (material.uniforms.tNormal) material.uniforms.tNormal.value = this.texture ?? undefined
  81. else this._viewer?.console.warn('BaseRenderer: no uniform: tNormal')
  82. return this
  83. }
  84. }
  85. class MeshNormalMaterial2 extends MeshNormalMaterial {
  86. onBeforeRender(renderer: WebGLRenderer, scene: Scene, camera: Camera, geometry: BufferGeometry, object: Object3D) {
  87. super.onBeforeRender(renderer, scene, camera, geometry, object)
  88. if (!(object as any).material) return
  89. const material = (object as any).material as IMaterial & Partial<PhysicalMaterial>
  90. if (material.bumpMap !== undefined) this.bumpMap = material.bumpMap
  91. if (material.bumpScale !== undefined) this.bumpScale = material.bumpScale
  92. if (material.normalMap !== undefined) this.normalMap = material.normalMap
  93. if (material.normalMapType !== undefined) this.normalMapType = material.normalMapType
  94. if (material.normalScale !== undefined) this.normalScale.copy(material.normalScale)
  95. if (material.displacementMap !== undefined) this.displacementMap = material.displacementMap
  96. if (material.displacementScale !== undefined) this.displacementScale = material.displacementScale
  97. if (material.displacementBias !== undefined) this.displacementBias = material.displacementBias
  98. if (material.flatShading !== undefined) this.flatShading = material.flatShading
  99. if (material.side !== undefined) this.side = material.side
  100. }
  101. onAfterRender(renderer: WebGLRenderer, scene: Scene, camera: Camera, geometry: BufferGeometry, object: Object3D) {
  102. super.onAfterRender(renderer, scene, camera, geometry, object)
  103. this.bumpMap = null
  104. this.bumpScale = 1
  105. this.normalMap = null
  106. this.normalMapType = TangentSpaceNormalMap
  107. this.displacementMap = null
  108. this.displacementScale = 1
  109. this.displacementBias = 0
  110. this.flatShading = false
  111. this.side = FrontSide
  112. }
  113. }