fogBlock.ts 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162
  1. import { NodeMaterialBlock } from '../../nodeMaterialBlock';
  2. import { NodeMaterialBlockConnectionPointTypes } from '../../Enums/nodeMaterialBlockConnectionPointTypes';
  3. import { NodeMaterialBuildState } from '../../nodeMaterialBuildState';
  4. import { NodeMaterialSystemValues } from '../../Enums/nodeMaterialSystemValues';
  5. import { NodeMaterialBlockTargets } from '../../Enums/nodeMaterialBlockTargets';
  6. import { Mesh } from '../../../../Meshes/mesh';
  7. import { Effect } from '../../../effect';
  8. import { NodeMaterialConnectionPoint } from '../../nodeMaterialBlockConnectionPoint';
  9. import { AbstractMesh } from '../../../../Meshes/abstractMesh';
  10. import { MaterialHelper } from '../../../materialHelper';
  11. import { NodeMaterial, NodeMaterialDefines } from '../../nodeMaterial';
  12. import { InputBlock } from '../Input/inputBlock';
  13. import { _TypeStore } from '../../../../Misc/typeStore';
  14. import "../../../../Shaders/ShadersInclude/fogFragmentDeclaration";
  15. /**
  16. * Block used to add support for scene fog
  17. */
  18. export class FogBlock extends NodeMaterialBlock {
  19. private _fogDistanceName: string;
  20. private _fogParameters: string;
  21. /**
  22. * Create a new FogBlock
  23. * @param name defines the block name
  24. */
  25. public constructor(name: string) {
  26. super(name, NodeMaterialBlockTargets.VertexAndFragment, true);
  27. // Vertex
  28. this.registerInput("worldPosition", NodeMaterialBlockConnectionPointTypes.Vector4, false, NodeMaterialBlockTargets.Vertex);
  29. this.registerInput("view", NodeMaterialBlockConnectionPointTypes.Matrix, false, NodeMaterialBlockTargets.Vertex);
  30. // Fragment
  31. this.registerInput("input", NodeMaterialBlockConnectionPointTypes.Color3, false, NodeMaterialBlockTargets.Fragment);
  32. this.registerInput("fogColor", NodeMaterialBlockConnectionPointTypes.Color3, false, NodeMaterialBlockTargets.Fragment);
  33. this.registerOutput("output", NodeMaterialBlockConnectionPointTypes.Color3, NodeMaterialBlockTargets.Fragment);
  34. this.input.acceptedConnectionPointTypes.push(NodeMaterialBlockConnectionPointTypes.Color4);
  35. this.fogColor.acceptedConnectionPointTypes.push(NodeMaterialBlockConnectionPointTypes.Color4);
  36. }
  37. /**
  38. * Gets the current class name
  39. * @returns the class name
  40. */
  41. public getClassName() {
  42. return "FogBlock";
  43. }
  44. /**
  45. * Gets the world position input component
  46. */
  47. public get worldPosition(): NodeMaterialConnectionPoint {
  48. return this._inputs[0];
  49. }
  50. /**
  51. * Gets the view input component
  52. */
  53. public get view(): NodeMaterialConnectionPoint {
  54. return this._inputs[1];
  55. }
  56. /**
  57. * Gets the color input component
  58. */
  59. public get input(): NodeMaterialConnectionPoint {
  60. return this._inputs[2];
  61. }
  62. /**
  63. * Gets the fog color input component
  64. */
  65. public get fogColor(): NodeMaterialConnectionPoint {
  66. return this._inputs[3];
  67. }
  68. /**
  69. * Gets the output component
  70. */
  71. public get output(): NodeMaterialConnectionPoint {
  72. return this._outputs[0];
  73. }
  74. public autoConfigure(material: NodeMaterial) {
  75. if (!this.view.isConnected) {
  76. let viewInput = material.getInputBlockByPredicate((b) => b.systemValue === NodeMaterialSystemValues.View);
  77. if (!viewInput) {
  78. viewInput = new InputBlock("view");
  79. viewInput.setAsSystemValue(NodeMaterialSystemValues.View);
  80. }
  81. viewInput.output.connectTo(this.view);
  82. }
  83. if (!this.fogColor.isConnected) {
  84. let fogColorInput = material.getInputBlockByPredicate((b) => b.systemValue === NodeMaterialSystemValues.FogColor);
  85. if (!fogColorInput) {
  86. fogColorInput = new InputBlock("fogColor", undefined, NodeMaterialBlockConnectionPointTypes.Color3);
  87. fogColorInput.setAsSystemValue(NodeMaterialSystemValues.FogColor);
  88. }
  89. fogColorInput.output.connectTo(this.fogColor);
  90. }
  91. }
  92. public prepareDefines(mesh: AbstractMesh, nodeMaterial: NodeMaterial, defines: NodeMaterialDefines) {
  93. let scene = mesh.getScene();
  94. defines.setValue("FOG", nodeMaterial.fogEnabled && MaterialHelper.GetFogState(mesh, scene));
  95. }
  96. public bind(effect: Effect, nodeMaterial: NodeMaterial, mesh?: Mesh) {
  97. if (!mesh) {
  98. return;
  99. }
  100. const scene = mesh.getScene();
  101. effect.setFloat4(this._fogParameters, scene.fogMode, scene.fogStart, scene.fogEnd, scene.fogDensity);
  102. }
  103. protected _buildBlock(state: NodeMaterialBuildState) {
  104. super._buildBlock(state);
  105. if (state.target === NodeMaterialBlockTargets.Fragment) {
  106. state.sharedData.blocksWithDefines.push(this);
  107. state.sharedData.bindableBlocks.push(this);
  108. state._emitFunctionFromInclude("fogFragmentDeclaration", `//${this.name}`, {
  109. removeUniforms: true,
  110. removeVaryings: true,
  111. removeIfDef: false,
  112. replaceStrings: [{ search: /float CalcFogFactor\(\)/, replace: "float CalcFogFactor(vec3 vFogDistance, vec4 vFogInfos)" }]
  113. });
  114. let tempFogVariablename = state._getFreeVariableName("fog");
  115. let color = this.input;
  116. let fogColor = this.fogColor;
  117. this._fogParameters = state._getFreeVariableName("fogParameters");
  118. let output = this._outputs[0];
  119. state._emitUniformFromString(this._fogParameters, "vec4");
  120. state.compilationString += `#ifdef FOG\r\n`;
  121. state.compilationString += `float ${tempFogVariablename} = CalcFogFactor(${this._fogDistanceName}, ${this._fogParameters});\r\n`;
  122. state.compilationString += this._declareOutput(output, state) + ` = ${tempFogVariablename} * ${color.associatedVariableName}.rgb + (1.0 - ${tempFogVariablename}) * ${fogColor.associatedVariableName}.rgb;\r\n`;
  123. state.compilationString += `#else\r\n${this._declareOutput(output, state)} = ${color.associatedVariableName}.rgb;\r\n`;
  124. state.compilationString += `#endif\r\n`;
  125. } else {
  126. let worldPos = this.worldPosition;
  127. let view = this.view;
  128. this._fogDistanceName = state._getFreeVariableName("vFogDistance");
  129. state._emitVaryingFromString(this._fogDistanceName, "vec3");
  130. state.compilationString += `${this._fogDistanceName} = (${view.associatedVariableName} * ${worldPos.associatedVariableName}).xyz;\r\n`;
  131. }
  132. return this;
  133. }
  134. }
  135. _TypeStore.RegisteredTypes["BABYLON.FogBlock"] = FogBlock;