commonShadowLightPropertyGridComponent.tsx 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204
  1. import * as React from "react";
  2. import { Observable } from "babylonjs/Misc/observable";
  3. import { IShadowLight } from "babylonjs/Lights/shadowLight";
  4. import { PropertyChangedEvent } from "../../../../propertyChangedEvent";
  5. import { LineContainerComponent } from "../../../lineContainerComponent";
  6. import { CheckBoxLineComponent } from "../../../../../sharedUiComponents/lines/checkBoxLineComponent";
  7. import { FloatLineComponent } from "../../../../../sharedUiComponents/lines/floatLineComponent";
  8. import { LockObject } from "../../../../../sharedUiComponents/tabs/propertyGrids/lockObject";
  9. import { GlobalState } from '../../../../globalState';
  10. import { OptionsLineComponent } from '../../../../../sharedUiComponents/lines/optionsLineComponent';
  11. import { ShadowGenerator } from 'babylonjs/Lights/Shadows/shadowGenerator';
  12. import { CascadedShadowGenerator } from 'babylonjs/Lights/Shadows/cascadedShadowGenerator';
  13. import { SliderLineComponent } from '../../../../../sharedUiComponents/lines/sliderLineComponent';
  14. import { ButtonLineComponent } from '../../../../../sharedUiComponents/lines/buttonLineComponent';
  15. import { DirectionalLight } from 'babylonjs/Lights/directionalLight';
  16. interface ICommonShadowLightPropertyGridComponentProps {
  17. globalState: GlobalState;
  18. light: IShadowLight;
  19. lockObject: LockObject;
  20. onPropertyChangedObservable?: Observable<PropertyChangedEvent>;
  21. }
  22. export class CommonShadowLightPropertyGridComponent extends React.Component<ICommonShadowLightPropertyGridComponentProps> {
  23. private _internals : { generatorType: number, mapSize: number };
  24. constructor(props: ICommonShadowLightPropertyGridComponentProps) {
  25. super(props);
  26. this._internals = {
  27. generatorType: 0,
  28. mapSize: 1024,
  29. };
  30. }
  31. createShadowGenerator() {
  32. const light = this.props.light;
  33. const scene = light.getScene();
  34. const internals = this._internals;
  35. let generator = internals.generatorType === 0 ? new ShadowGenerator(internals.mapSize, light) : new CascadedShadowGenerator(internals.mapSize, light as DirectionalLight);
  36. scene.meshes.forEach((m) => {
  37. if (m.infiniteDistance) { return; }
  38. generator.addShadowCaster(m);
  39. if (!m.isAnInstance) {
  40. m.receiveShadows = true;
  41. }
  42. });
  43. this.forceUpdate();
  44. }
  45. disposeShadowGenerator() {
  46. const light = this.props.light;
  47. light.getShadowGenerator()?.dispose();
  48. this.forceUpdate();
  49. }
  50. render() {
  51. const light = this.props.light;
  52. const internals = this._internals;
  53. const generator = light.getShadowGenerator() as (ShadowGenerator | CascadedShadowGenerator) || null;
  54. const csmGenerator = generator instanceof CascadedShadowGenerator;
  55. const camera = light.getScene().activeCamera;
  56. var typeGeneratorOptions = [
  57. { label: "Shadow Generator", value: 0 }
  58. ];
  59. if (light instanceof DirectionalLight) {
  60. typeGeneratorOptions.push({ label: "Cascaded Shadow Generator", value: 1 });
  61. }
  62. var mapSizeOptions = [
  63. { label: "2048x2048", value: 2048 },
  64. { label: "1024x1024", value: 1024 },
  65. { label: "512x512", value: 512 },
  66. { label: "256x256", value: 256 },
  67. ];
  68. var blurModeOptions;
  69. if (generator instanceof CascadedShadowGenerator) {
  70. blurModeOptions = [
  71. { label: "None", value: ShadowGenerator.FILTER_NONE },
  72. { label: "PCF", value: ShadowGenerator.FILTER_PCF },
  73. { label: "PCSS", value: ShadowGenerator.FILTER_PCSS },
  74. ];
  75. } else {
  76. blurModeOptions = [
  77. { label: "None", value: ShadowGenerator.FILTER_NONE },
  78. { label: "PCF", value: ShadowGenerator.FILTER_PCF },
  79. { label: "PCSS", value: ShadowGenerator.FILTER_PCSS },
  80. { label: "Poisson", value: ShadowGenerator.FILTER_POISSONSAMPLING },
  81. { label: "Exponential", value: ShadowGenerator.FILTER_EXPONENTIALSHADOWMAP },
  82. { label: "Blurred exponential", value: ShadowGenerator.FILTER_BLUREXPONENTIALSHADOWMAP },
  83. { label: "Close exponential", value: ShadowGenerator.FILTER_CLOSEEXPONENTIALSHADOWMAP },
  84. { label: "Blurred close exponential", value: ShadowGenerator.FILTER_BLURCLOSEEXPONENTIALSHADOWMAP },
  85. ];
  86. }
  87. var filteringQualityOptions = [
  88. { label: "Low", value: ShadowGenerator.QUALITY_LOW },
  89. { label: "Medium", value: ShadowGenerator.QUALITY_MEDIUM },
  90. { label: "High", value: ShadowGenerator.QUALITY_HIGH },
  91. ];
  92. var numCascadesOptions = [
  93. { label: "2", value: 2 },
  94. { label: "3", value: 3 },
  95. { label: "4", value: 4 },
  96. ];
  97. const near = camera ? camera.minZ : 0, far = camera ? camera.maxZ : 0;
  98. let filter = generator ? generator.filter : 0;
  99. return (
  100. <div>
  101. <LineContainerComponent globalState={this.props.globalState} title="SHADOWS">
  102. <CheckBoxLineComponent label="Shadows enabled" target={light} propertyName="shadowEnabled" onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
  103. { !csmGenerator && <>
  104. <FloatLineComponent lockObject={this.props.lockObject} label="Shadows near plane" target={light} propertyName="shadowMinZ" onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
  105. <FloatLineComponent lockObject={this.props.lockObject} label="Shadows far plane" target={light} propertyName="shadowMaxZ" onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
  106. </> }
  107. </LineContainerComponent>
  108. {
  109. generator == null &&
  110. <LineContainerComponent globalState={this.props.globalState} title="SHADOW GENERATOR">
  111. <OptionsLineComponent label="Type" options={typeGeneratorOptions} target={internals} propertyName="generatorType" />
  112. <OptionsLineComponent label="Map size" options={mapSizeOptions} target={internals} propertyName="mapSize" />
  113. <ButtonLineComponent label="Create generator" onClick={() => this.createShadowGenerator()} />
  114. </LineContainerComponent>
  115. }
  116. {
  117. generator !== null &&
  118. <LineContainerComponent globalState={this.props.globalState} title="SHADOW GENERATOR">
  119. <ButtonLineComponent label="Dispose generator" onClick={() => this.disposeShadowGenerator()} />
  120. { csmGenerator && <>
  121. <OptionsLineComponent label="Num cascades" options={numCascadesOptions} target={generator} propertyName="numCascades" onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
  122. <CheckBoxLineComponent label="Debug mode" target={generator} propertyName="debug" onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
  123. <CheckBoxLineComponent label="Stabilize cascades" target={generator} propertyName="stabilizeCascades" onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
  124. <SliderLineComponent label="Lambda" minimum={0} maximum={1.0} step={0.01} target={generator} propertyName="lambda" onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
  125. <SliderLineComponent label="Cascade blend" minimum={0} maximum={1.0} step={0.01} target={generator} propertyName="cascadeBlendPercentage" onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
  126. <CheckBoxLineComponent label="Depth clamp" target={generator} propertyName="depthClamp" onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
  127. <CheckBoxLineComponent label="Auto-Calc depth bounds" target={generator} propertyName="autoCalcDepthBounds" onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
  128. <SliderLineComponent label="Shadow MaxZ" minimum={near} maximum={far} step={0.5} target={generator} propertyName="shadowMaxZ" onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
  129. </> }
  130. <FloatLineComponent lockObject={this.props.lockObject} digits={4} step="0.0001" label="Bias" target={generator} propertyName="bias" onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
  131. <FloatLineComponent lockObject={this.props.lockObject} label="Normal bias" target={generator} propertyName="normalBias" onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
  132. <SliderLineComponent label="Darkness" target={generator} minimum={0} maximum={1} step={0.01} propertyName="darkness" onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
  133. <CheckBoxLineComponent label="Allow transparent shadows" target={generator} propertyName="transparencyShadow" onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
  134. <OptionsLineComponent label="Filter" options={blurModeOptions}
  135. onSelect={() => {
  136. this.forceUpdate();
  137. }}
  138. target={generator} propertyName="filter" onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
  139. {
  140. (filter === ShadowGenerator.FILTER_PCF || filter === ShadowGenerator.FILTER_PCSS) &&
  141. <OptionsLineComponent label="Filtering quality" options={filteringQualityOptions}
  142. onSelect={() => {
  143. this.forceUpdate();
  144. }}
  145. target={generator} propertyName="filteringQuality" onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
  146. }
  147. {
  148. (filter === ShadowGenerator.FILTER_PCSS) &&
  149. <SliderLineComponent label="Penumbra ratio" minimum={0} maximum={0.5} step={0.001} target={generator} propertyName="contactHardeningLightSizeUVRatio" onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
  150. }
  151. {
  152. !csmGenerator && (filter === ShadowGenerator.FILTER_BLUREXPONENTIALSHADOWMAP || filter === ShadowGenerator.FILTER_BLURCLOSEEXPONENTIALSHADOWMAP) &&
  153. <CheckBoxLineComponent label="Use kernel blur" target={generator} propertyName="useKernelBlur"
  154. onValueChanged={() => this.forceUpdate()}
  155. onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
  156. }
  157. {
  158. (generator instanceof ShadowGenerator) && (filter === ShadowGenerator.FILTER_BLUREXPONENTIALSHADOWMAP || filter === ShadowGenerator.FILTER_BLURCLOSEEXPONENTIALSHADOWMAP) &&
  159. !generator.useKernelBlur &&
  160. <SliderLineComponent label="Blur box offset" target={generator} propertyName="blurBoxOffset" minimum={1} maximum={64} step={1} onPropertyChangedObservable={this.props.onPropertyChangedObservable} />}
  161. {
  162. (generator instanceof ShadowGenerator) && (filter === ShadowGenerator.FILTER_BLUREXPONENTIALSHADOWMAP || filter === ShadowGenerator.FILTER_BLURCLOSEEXPONENTIALSHADOWMAP) &&
  163. generator.useKernelBlur &&
  164. <SliderLineComponent label="Blur kernel" target={generator} propertyName="blurKernel" minimum={1} maximum={64} step={1} onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
  165. }
  166. {
  167. (generator instanceof ShadowGenerator) && (filter === ShadowGenerator.FILTER_BLUREXPONENTIALSHADOWMAP || filter === ShadowGenerator.FILTER_EXPONENTIALSHADOWMAP) &&
  168. <FloatLineComponent lockObject={this.props.lockObject} label="Depth scale" target={generator} propertyName="depthScale" onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
  169. }
  170. {
  171. (generator instanceof ShadowGenerator) && (filter === ShadowGenerator.FILTER_BLUREXPONENTIALSHADOWMAP || filter === ShadowGenerator.FILTER_EXPONENTIALSHADOWMAP) &&
  172. <SliderLineComponent label="Blur scale" target={generator} propertyName="blurScale" minimum={1} maximum={4} step={1} onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
  173. }
  174. {
  175. csmGenerator && (filter === ShadowGenerator.FILTER_PCSS) &&
  176. <SliderLineComponent label="Penumbra darkness" minimum={0} maximum={1.0} step={0.01} target={generator} propertyName="penumbraDarkness" onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
  177. }
  178. </LineContainerComponent>
  179. }
  180. </div>
  181. );
  182. }
  183. }