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

NormalBufferPlugin.ts 5.1KB

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