lightInformationBlock.ts 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161
  1. import { NodeMaterialBlock } from '../../nodeMaterialBlock';
  2. import { NodeMaterialBlockConnectionPointTypes } from '../../Enums/nodeMaterialBlockConnectionPointTypes';
  3. import { NodeMaterialBuildState } from '../../nodeMaterialBuildState';
  4. import { NodeMaterialConnectionPoint } from '../../nodeMaterialBlockConnectionPoint';
  5. import { NodeMaterialBlockTargets } from '../../Enums/nodeMaterialBlockTargets';
  6. import { _TypeStore } from '../../../../Misc/typeStore';
  7. import { Nullable } from '../../../../types';
  8. import { Scene } from '../../../../scene';
  9. import { Effect } from '../../../effect';
  10. import { NodeMaterial, NodeMaterialDefines } from '../../nodeMaterial';
  11. import { Mesh } from '../../../../Meshes/mesh';
  12. import { Light } from '../../../../Lights/light';
  13. import { PointLight } from '../../../../Lights/pointLight';
  14. import { AbstractMesh } from '../../../../Meshes/abstractMesh';
  15. /**
  16. * Block used to get data information from a light
  17. */
  18. export class LightInformationBlock extends NodeMaterialBlock {
  19. private _lightDataUniformName: string;
  20. private _lightColorUniformName: string;
  21. private _lightTypeDefineName: string;
  22. /**
  23. * Gets or sets the light associated with this block
  24. */
  25. public light: Nullable<Light>;
  26. /**
  27. * Creates a new LightInformationBlock
  28. * @param name defines the block name
  29. */
  30. public constructor(name: string) {
  31. super(name, NodeMaterialBlockTargets.Vertex);
  32. this.registerInput("worldPosition", NodeMaterialBlockConnectionPointTypes.Vector4, false, NodeMaterialBlockTargets.Vertex);
  33. this.registerOutput("direction", NodeMaterialBlockConnectionPointTypes.Vector3);
  34. this.registerOutput("color", NodeMaterialBlockConnectionPointTypes.Color3);
  35. this.registerOutput("intensity", NodeMaterialBlockConnectionPointTypes.Float);
  36. }
  37. /**
  38. * Gets the current class name
  39. * @returns the class name
  40. */
  41. public getClassName() {
  42. return "LightInformationBlock";
  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 direction output component
  52. */
  53. public get direction(): NodeMaterialConnectionPoint {
  54. return this._outputs[0];
  55. }
  56. /**
  57. * Gets the direction output component
  58. */
  59. public get color(): NodeMaterialConnectionPoint {
  60. return this._outputs[1];
  61. }
  62. /**
  63. * Gets the direction output component
  64. */
  65. public get intensity(): NodeMaterialConnectionPoint {
  66. return this._outputs[2];
  67. }
  68. public bind(effect: Effect, nodeMaterial: NodeMaterial, mesh?: Mesh) {
  69. if (!mesh) {
  70. return;
  71. }
  72. if (this.light && this.light.isDisposed) {
  73. this.light = null;
  74. }
  75. let light = this.light;
  76. let scene = nodeMaterial.getScene();
  77. if (!light && scene.lights.length) {
  78. light = scene.lights[0];
  79. }
  80. if (!light || !light.isEnabled) {
  81. effect.setFloat3(this._lightDataUniformName, 0, 0, 0);
  82. effect.setFloat4(this._lightColorUniformName, 0, 0, 0, 0);
  83. return;
  84. }
  85. light.transferToNodeMaterialEffect(effect, this._lightDataUniformName);
  86. effect.setColor4(this._lightColorUniformName, light.diffuse, light.intensity);
  87. }
  88. public prepareDefines(mesh: AbstractMesh, nodeMaterial: NodeMaterial, defines: NodeMaterialDefines) {
  89. if (!defines._areLightsDirty) {
  90. return;
  91. }
  92. let light = this.light;
  93. defines.setValue(this._lightTypeDefineName, light && light instanceof PointLight ? true : false);
  94. }
  95. protected _buildBlock(state: NodeMaterialBuildState) {
  96. super._buildBlock(state);
  97. state.sharedData.bindableBlocks.push(this);
  98. state.sharedData.blocksWithDefines.push(this);
  99. let direction = this.direction;
  100. let color = this.color;
  101. let intensity = this.intensity;
  102. this._lightDataUniformName = state._getFreeVariableName("lightData");
  103. this._lightColorUniformName = state._getFreeVariableName("lightColor");
  104. this._lightTypeDefineName = state._getFreeDefineName("LIGHTPOINTTYPE");
  105. state._emitUniformFromString(this._lightDataUniformName, "vec3");
  106. state._emitUniformFromString(this._lightColorUniformName, "vec4");
  107. state.compilationString += `#if ${this._lightTypeDefineName}\r\n`;
  108. state.compilationString += this._declareOutput(direction, state) + ` = normalize(${this._lightDataUniformName} - ${this.worldPosition.associatedVariableName}.xyz);\r\n`;
  109. state.compilationString += `#else\r\n`;
  110. state.compilationString += this._declareOutput(direction, state) + ` = ${this._lightDataUniformName};\r\n`;
  111. state.compilationString += `#endif\r\n`;
  112. state.compilationString += this._declareOutput(color, state) + ` = ${this._lightColorUniformName}.rgb;\r\n`;
  113. state.compilationString += this._declareOutput(intensity, state) + ` = ${this._lightColorUniformName}.a;\r\n`;
  114. return this;
  115. }
  116. public serialize(): any {
  117. let serializationObject = super.serialize();
  118. if (this.light) {
  119. serializationObject.lightId = this.light.id;
  120. }
  121. return serializationObject;
  122. }
  123. public _deserialize(serializationObject: any, scene: Scene, rootUrl: string) {
  124. super._deserialize(serializationObject, scene, rootUrl);
  125. if (serializationObject.lightId) {
  126. this.light = scene.getLightByID(serializationObject.lightId);
  127. }
  128. }
  129. }
  130. _TypeStore.RegisteredTypes["BABYLON.LightInformationBlock"] = LightInformationBlock;