fogBlock.ts 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  1. import { NodeMaterialBlock } from '../../nodeMaterialBlock';
  2. import { NodeMaterialBlockConnectionPointTypes } from '../../nodeMaterialBlockConnectionPointTypes';
  3. import { NodeMaterialBuildState } from '../../nodeMaterialBuildState';
  4. import { NodeMaterialWellKnownValues } from '../../nodeMaterialWellKnownValues';
  5. import { NodeMaterialBlockTargets } from '../../nodeMaterialBlockTargets';
  6. import { Mesh } from '../../../../Meshes/mesh';
  7. import { Effect } from '../../../effect';
  8. import { NodeMaterialConnectionPoint } from '../../nodeMaterialBlockConnectionPoint';
  9. import { MaterialDefines } from '../../../materialDefines';
  10. import { AbstractMesh } from '../../../../Meshes/abstractMesh';
  11. import { MaterialHelper } from '../../../materialHelper';
  12. import { NodeMaterial } from '../../nodeMaterial';
  13. /**
  14. * Block used to add support for scene fog
  15. */
  16. export class FogBlock extends NodeMaterialBlock {
  17. /**
  18. * Create a new FogBlock
  19. * @param name defines the block name
  20. */
  21. public constructor(name: string) {
  22. super(name, NodeMaterialBlockTargets.VertexAndFragment, true);
  23. // Vertex
  24. this.registerInput("worldPosition", NodeMaterialBlockConnectionPointTypes.Vector4, false, NodeMaterialBlockTargets.Vertex);
  25. this.registerInput("view", NodeMaterialBlockConnectionPointTypes.Matrix, false, NodeMaterialBlockTargets.Vertex);
  26. this.registerOutput("vFogDistance", NodeMaterialBlockConnectionPointTypes.Vector3, NodeMaterialBlockTargets.Vertex);
  27. // Fragment
  28. this.registerInput("color", NodeMaterialBlockConnectionPointTypes.Color3OrColor4, false, NodeMaterialBlockTargets.Fragment);
  29. this.registerInput("fogColor", NodeMaterialBlockConnectionPointTypes.Color3, false, NodeMaterialBlockTargets.Fragment);
  30. this.registerInput("fogParameters", NodeMaterialBlockConnectionPointTypes.Vector4, false, NodeMaterialBlockTargets.Fragment);
  31. this.registerOutput("output", NodeMaterialBlockConnectionPointTypes.Color3, NodeMaterialBlockTargets.Fragment);
  32. // Auto configuration
  33. this._inputs[1].setAsWellKnownValue(NodeMaterialWellKnownValues.View);
  34. this._inputs[3].setAsWellKnownValue(NodeMaterialWellKnownValues.FogColor);
  35. this._inputs[4].setAsWellKnownValue(NodeMaterialWellKnownValues.FogParameters);
  36. this._outputs[0].isVarying = true;
  37. }
  38. /**
  39. * Gets the current class name
  40. * @returns the class name
  41. */
  42. public getClassName() {
  43. return "FogBlock";
  44. }
  45. /**
  46. * Gets the world position input component
  47. */
  48. public get worldPosition(): NodeMaterialConnectionPoint {
  49. return this._inputs[0];
  50. }
  51. /**
  52. * Gets the view input component
  53. */
  54. public get view(): NodeMaterialConnectionPoint {
  55. return this._inputs[1];
  56. }
  57. /**
  58. * Gets the color input component
  59. */
  60. public get color(): NodeMaterialConnectionPoint {
  61. return this._inputs[2];
  62. }
  63. /**
  64. * Gets the fog color input component
  65. */
  66. public get fogColor(): NodeMaterialConnectionPoint {
  67. return this._inputs[3];
  68. }
  69. /**
  70. * Gets the for parameter input component
  71. */
  72. public get fogParameters(): NodeMaterialConnectionPoint {
  73. return this._inputs[4];
  74. }
  75. public prepareDefines(mesh: AbstractMesh, nodeMaterial: NodeMaterial, defines: MaterialDefines) {
  76. let scene = mesh.getScene();
  77. defines["FOG"] = nodeMaterial.fogEnabled && MaterialHelper.GetFogState(mesh, scene);
  78. }
  79. public bind(effect: Effect, mesh?: Mesh) {
  80. if (!mesh) {
  81. return;
  82. }
  83. const scene = mesh.getScene();
  84. effect.setColor3("fogColor", scene.fogColor);
  85. effect.setFloat4("fogParameters", scene.fogMode, scene.fogStart, scene.fogEnd, scene.fogDensity);
  86. }
  87. protected _buildBlock(state: NodeMaterialBuildState) {
  88. super._buildBlock(state);
  89. state.sharedData.blocksWithDefines.push(this);
  90. if (state.target === NodeMaterialBlockTargets.Fragment) {
  91. state._emitFunctionFromInclude("CalcFogFactor", "fogFragmentDeclaration", {
  92. removeUniforms: true,
  93. removeVaryings: true,
  94. removeifDef: false,
  95. replaceStrings: [{ search: /float CalcFogFactor\(\)/, replace: "float CalcFogFactor(vec3 vFogDistance, vec4 vFogInfos)" }]
  96. });
  97. let tempFogVariablename = state._getFreeVariableName("fog");
  98. let color = this.color;
  99. let fogColor = this.fogColor;
  100. let fogParameters = this.fogParameters;
  101. let output = this._outputs[1];
  102. let vFogDistance = this._outputs[0];
  103. state.compilationString += `#ifdef FOG\r\n`;
  104. state.compilationString += `float ${tempFogVariablename} = CalcFogFactor(${vFogDistance.associatedVariableName}, ${fogParameters.associatedVariableName});\r\n`;
  105. state.compilationString += this._declareOutput(output, state) + ` = ${tempFogVariablename} * ${color.associatedVariableName}.rgb + (1.0 - ${tempFogVariablename}) * ${fogColor.associatedVariableName};\r\n`;
  106. state.compilationString += `#else\r\n${this._declareOutput(output, state)} = ${color.associatedVariableName}.rgb;\r\n`;
  107. state.compilationString += `#endif\r\n`;
  108. } else {
  109. let worldPos = this.worldPosition;
  110. let view = this.view;
  111. let vFogDistance = this._outputs[0];
  112. state.compilationString += this._declareOutput(vFogDistance, state) + ` = (${view.associatedVariableName} * ${worldPos.associatedVariableName}).xyz;\r\n`;
  113. }
  114. return this;
  115. }
  116. }