/src/away3d/materials/methods/ProjectiveTextureMethod.as

http://github.com/away3d/away3d-core-fp11 · ActionScript · 167 lines · 106 code · 19 blank · 42 comment · 10 complexity · 76d2332a25d3bc0b8c299142444ee271 MD5 · raw file

  1. package away3d.materials.methods
  2. {
  3. import away3d.arcane;
  4. import away3d.cameras.Camera3D;
  5. import away3d.core.base.IRenderable;
  6. import away3d.core.managers.Stage3DProxy;
  7. import away3d.entities.TextureProjector;
  8. import away3d.materials.compilation.ShaderRegisterCache;
  9. import away3d.materials.compilation.ShaderRegisterElement;
  10. import flash.geom.Matrix3D;
  11. use namespace arcane;
  12. /**
  13. * ProjectiveTextureMethod is a material method used to project a texture unto the surface of an object.
  14. * This can be used for various effects apart from acting like a normal projector, such as projecting fake shadows
  15. * unto a surface, the impact of light coming through a stained glass window, ...
  16. */
  17. public class ProjectiveTextureMethod extends EffectMethodBase
  18. {
  19. public static const MULTIPLY:String = "multiply";
  20. public static const ADD:String = "add";
  21. public static const MIX:String = "mix";
  22. private var _projector:TextureProjector;
  23. private var _uvVarying:ShaderRegisterElement;
  24. private var _projMatrix:Matrix3D = new Matrix3D();
  25. private var _mode:String;
  26. /**
  27. * Creates a new ProjectiveTextureMethod object.
  28. *
  29. * @param projector The TextureProjector object that defines the projection properties as well as the texture.
  30. * @param mode The blend mode with which the texture is blended unto the surface.
  31. *
  32. * @see away3d.entities.TextureProjector
  33. */
  34. public function ProjectiveTextureMethod(projector:TextureProjector, mode:String = "multiply")
  35. {
  36. super();
  37. _projector = projector;
  38. _mode = mode;
  39. }
  40. /**
  41. * @inheritDoc
  42. */
  43. override arcane function initConstants(vo:MethodVO):void
  44. {
  45. var index:int = vo.fragmentConstantsIndex;
  46. var data:Vector.<Number> = vo.fragmentData;
  47. data[index] = .5;
  48. data[index + 1] = -.5;
  49. data[index + 2] = 1.0;
  50. data[index + 3] = 1.0;
  51. }
  52. /**
  53. * @inheritDoc
  54. */
  55. arcane override function cleanCompilationData():void
  56. {
  57. super.cleanCompilationData();
  58. _uvVarying = null;
  59. }
  60. /**
  61. * The blend mode with which the texture is blended unto the object.
  62. * ProjectiveTextureMethod.MULTIPLY can be used to project shadows. To prevent clamping, the texture's alpha should be white!
  63. * ProjectiveTextureMethod.ADD can be used to project light, such as a slide projector or light coming through stained glass. To prevent clamping, the texture's alpha should be black!
  64. * ProjectiveTextureMethod.MIX provides normal alpha blending. To prevent clamping, the texture's alpha should be transparent!
  65. */
  66. public function get mode():String
  67. {
  68. return _mode;
  69. }
  70. public function set mode(value:String):void
  71. {
  72. if (_mode == value)
  73. return;
  74. _mode = value;
  75. invalidateShaderProgram();
  76. }
  77. /**
  78. * The TextureProjector object that defines the projection properties as well as the texture.
  79. *
  80. * @see away3d.entities.TextureProjector
  81. */
  82. public function get projector():TextureProjector
  83. {
  84. return _projector;
  85. }
  86. public function set projector(value:TextureProjector):void
  87. {
  88. _projector = value;
  89. }
  90. /**
  91. * @inheritDoc
  92. */
  93. arcane override function getVertexCode(vo:MethodVO, regCache:ShaderRegisterCache):String
  94. {
  95. var projReg:ShaderRegisterElement = regCache.getFreeVertexConstant();
  96. regCache.getFreeVertexConstant();
  97. regCache.getFreeVertexConstant();
  98. regCache.getFreeVertexConstant();
  99. regCache.getFreeVertexVectorTemp();
  100. vo.vertexConstantsIndex = projReg.index*4;
  101. _uvVarying = regCache.getFreeVarying();
  102. return "m44 " + _uvVarying + ", vt0, " + projReg + "\n";
  103. }
  104. /**
  105. * @inheritDoc
  106. */
  107. override arcane function getFragmentCode(vo:MethodVO, regCache:ShaderRegisterCache, targetReg:ShaderRegisterElement):String
  108. {
  109. var code:String = "";
  110. var mapRegister:ShaderRegisterElement = regCache.getFreeTextureReg();
  111. var col:ShaderRegisterElement = regCache.getFreeFragmentVectorTemp();
  112. var toTexReg:ShaderRegisterElement = regCache.getFreeFragmentConstant();
  113. vo.fragmentConstantsIndex = toTexReg.index*4;
  114. vo.texturesIndex = mapRegister.index;
  115. code += "div " + col + ", " + _uvVarying + ", " + _uvVarying + ".w \n" +
  116. "mul " + col + ".xy, " + col + ".xy, " + toTexReg + ".xy \n" +
  117. "add " + col + ".xy, " + col + ".xy, " + toTexReg + ".xx \n";
  118. code += getTex2DSampleCode(vo, col, mapRegister, _projector.texture, col, "clamp");
  119. if (_mode == MULTIPLY)
  120. code += "mul " + targetReg + ".xyz, " + targetReg + ".xyz, " + col + ".xyz \n";
  121. else if (_mode == ADD)
  122. code += "add " + targetReg + ".xyz, " + targetReg + ".xyz, " + col + ".xyz \n";
  123. else if (_mode == MIX) {
  124. code += "sub " + col + ".xyz, " + col + ".xyz, " + targetReg + ".xyz \n" +
  125. "mul " + col + ".xyz, " + col + ".xyz, " + col + ".w \n" +
  126. "add " + targetReg + ".xyz, " + targetReg + ".xyz, " + col + ".xyz \n";
  127. } else
  128. throw new Error("Unknown mode \"" + _mode + "\"");
  129. return code;
  130. }
  131. /**
  132. * @inheritDoc
  133. */
  134. arcane override function setRenderState(vo:MethodVO, renderable:IRenderable, stage3DProxy:Stage3DProxy, camera:Camera3D):void
  135. {
  136. _projMatrix.copyFrom(_projector.viewProjection);
  137. _projMatrix.prepend(renderable.getRenderSceneTransform(camera));
  138. _projMatrix.copyRawDataTo(vo.vertexData, vo.vertexConstantsIndex, true);
  139. }
  140. /**
  141. * @inheritDoc
  142. */
  143. override arcane function activate(vo:MethodVO, stage3DProxy:Stage3DProxy):void
  144. {
  145. stage3DProxy._context3D.setTextureAt(vo.texturesIndex, _projector.texture.getTextureForStage3D(stage3DProxy));
  146. }
  147. }
  148. }