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

NormalBufferPlugin.ts 5.7KB

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