threepipe
Du kannst nicht mehr als 25 Themen auswählen Themen müssen mit entweder einem Buchstaben oder einer Ziffer beginnen. Sie können Bindestriche („-“) enthalten und bis zu 35 Zeichen lang sein.

NormalBufferPlugin.ts 6.0KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171
  1. import {
  2. BufferGeometry,
  3. Camera,
  4. Color,
  5. DoubleSide,
  6. HalfFloatType,
  7. LinearSRGBColorSpace,
  8. MeshNormalMaterial,
  9. MeshNormalMaterialParameters,
  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 {PipelinePassPlugin} from '../base/PipelinePassPlugin'
  23. import type {IMaterial, PhysicalMaterial} from '../../core'
  24. import {uiFolderContainer, uiImage} from 'uiconfig.js'
  25. export type NormalBufferPluginEventTypes = ''
  26. // type NormalBufferPluginTarget = WebGLMultipleRenderTargets | WebGLRenderTarget
  27. export type NormalBufferPluginTarget = WebGLRenderTarget
  28. export type NormalBufferPluginPass = GBufferRenderPass<'normal', NormalBufferPluginTarget>
  29. /**
  30. * Normal Buffer Plugin
  31. *
  32. * Adds a pre-render pass to render the normal buffer to a render target that can be used for postprocessing.
  33. * @category Plugins
  34. */
  35. @uiFolderContainer('Normal Buffer Plugin')
  36. export class NormalBufferPlugin
  37. extends PipelinePassPlugin<NormalBufferPluginPass, 'normal', NormalBufferPluginEventTypes> {
  38. readonly passId = 'normal'
  39. public static readonly PluginType = 'NormalBufferPlugin'
  40. target?: NormalBufferPluginTarget
  41. @uiImage('Normal Buffer' /* {readOnly: true}*/) texture?: Texture
  42. readonly material: MeshNormalMaterial = new MeshNormalMaterialOverride({
  43. blending: NoBlending,
  44. })
  45. // @onChange2(NormalBufferPlugin.prototype._createTarget)
  46. // @uiDropdown('Buffer Type', threeConstMappings.TextureDataType.uiConfig)
  47. readonly bufferType: TextureDataType // cannot be changed after creation (for now)
  48. protected _createTarget(recreate = true) {
  49. if (!this._viewer) return
  50. if (recreate) this._disposeTarget()
  51. if (!this.target) this.target = this._viewer.renderManager.createTarget<NormalBufferPluginTarget>(
  52. {
  53. depthBuffer: true,
  54. // samples: v.renderManager.composerTarget.samples || 0,
  55. samples: 0,
  56. type: this.bufferType,
  57. magFilter: NearestFilter,
  58. minFilter: NearestFilter,
  59. generateMipmaps: false,
  60. colorSpace: LinearSRGBColorSpace,
  61. })
  62. this.texture = this.target.texture
  63. this.texture.name = 'normalBuffer'
  64. if (this._pass) this._pass.target = this.target
  65. }
  66. protected _disposeTarget() {
  67. if (!this._viewer) return
  68. if (this.target) {
  69. this._viewer.renderManager.disposeTarget(this.target)
  70. this.target = undefined
  71. }
  72. this.texture = undefined
  73. }
  74. protected _createPass() {
  75. this._createTarget(true)
  76. if (!this.target) throw new Error('NormalBufferPlugin: target not created')
  77. this.material.userData.isGBufferMaterial = true
  78. const pass = new GBufferRenderPass(this.passId, this.target, this.material, new Color(0, 0, 0), 1)
  79. const preprocessMaterial = pass.preprocessMaterial
  80. pass.preprocessMaterial = (m) => preprocessMaterial(m, true)
  81. pass.before = ['render']
  82. pass.after = []
  83. pass.required = ['render']
  84. return pass
  85. }
  86. constructor(
  87. bufferType: TextureDataType = HalfFloatType,
  88. enabled = true,
  89. ) {
  90. super()
  91. this.enabled = enabled
  92. this.bufferType = bufferType
  93. }
  94. onRemove(viewer: ThreeViewer): void {
  95. this._disposeTarget()
  96. return super.onRemove(viewer)
  97. }
  98. }
  99. class MeshNormalMaterialOverride extends MeshNormalMaterial {
  100. constructor(parameters: MeshNormalMaterialParameters) {
  101. super(parameters)
  102. this.reset()
  103. }
  104. onBeforeRender(renderer: WebGLRenderer, scene: Scene, camera: Camera, geometry: BufferGeometry, object: Object3D) {
  105. super.onBeforeRender(renderer, scene, camera, geometry, object)
  106. if (!(object as any).material) return
  107. const material = (object as any).material as IMaterial & Partial<PhysicalMaterial>
  108. if (material.bumpMap !== undefined) this.bumpMap = material.bumpMap
  109. if (material.bumpScale !== undefined) this.bumpScale = material.bumpScale
  110. // if (material.alphaMap !== undefined) this.alphaMap = material.alphaMap
  111. if (material.alphaTest !== undefined) this.alphaTest = material.alphaTest
  112. if (material.normalMap !== undefined) this.normalMap = material.normalMap
  113. if (material.normalMapType !== undefined) this.normalMapType = material.normalMapType
  114. if (material.normalScale !== undefined) this.normalScale.copy(material.normalScale)
  115. if (material.displacementMap !== undefined) this.displacementMap = material.displacementMap
  116. if (material.displacementScale !== undefined) this.displacementScale = material.displacementScale
  117. if (material.displacementBias !== undefined) this.displacementBias = material.displacementBias
  118. if (material.flatShading !== undefined) this.flatShading = material.flatShading
  119. if (material.side !== undefined) this.side = material.side
  120. if (material.wireframe !== undefined) this.wireframe = material.wireframe
  121. if (material.wireframeLinewidth !== undefined) this.wireframeLinewidth = material.wireframeLinewidth
  122. }
  123. onAfterRender(renderer: WebGLRenderer, scene: Scene, camera: Camera, geometry: BufferGeometry, object: Object3D) {
  124. super.onAfterRender(renderer, scene, camera, geometry, object)
  125. this.reset()
  126. }
  127. reset() {
  128. this.bumpMap = null
  129. this.bumpScale = 1
  130. // this.alphaMap = null
  131. this.alphaTest = 0
  132. this.normalMap = null
  133. this.normalMapType = TangentSpaceNormalMap
  134. this.displacementMap = null
  135. this.displacementScale = 1
  136. this.displacementBias = 0
  137. this.flatShading = false
  138. this.side = DoubleSide
  139. this.wireframe = false
  140. this.wireframeLinewidth = 1
  141. }
  142. }