/src/away3d/materials/methods/TerrainDiffuseMethod.as

http://github.com/away3d/away3d-core-fp11 · ActionScript · 164 lines · 114 code · 24 blank · 26 comment · 12 complexity · 526ea7aca7eb3da5883275e28e810ca3 MD5 · raw file

  1. package away3d.materials.methods
  2. {
  3. import away3d.arcane;
  4. import away3d.core.managers.Stage3DProxy;
  5. import away3d.materials.compilation.ShaderRegisterCache;
  6. import away3d.materials.compilation.ShaderRegisterElement;
  7. import away3d.textures.Texture2DBase;
  8. import away3d.textures.TextureProxyBase;
  9. import flash.display3D.Context3D;
  10. use namespace arcane;
  11. /**
  12. * TerrainDiffuseMethod provides a diffuse method that uses different tiled textures with alpha masks to create a
  13. * large surface with high detail and less apparent tiling.
  14. */
  15. public class TerrainDiffuseMethod extends BasicDiffuseMethod
  16. {
  17. private var _blendingTexture:Texture2DBase;
  18. private var _splats:Vector.<Texture2DBase>;
  19. private var _numSplattingLayers:uint;
  20. private var _tileData:Array;
  21. /**
  22. * Creates a new TerrainDiffuseMethod.
  23. * @param splatTextures An array of Texture2DProxyBase containing the detailed textures to be tiled.
  24. * @param blendingTexture The texture containing the blending data. The red, green, and blue channels contain the blending values for each of the textures in splatTextures, respectively.
  25. * @param tileData The amount of times each splat texture needs to be tiled. The first entry in the array applies to the base texture, the others to the splats. If omitted, the default value of 50 is assumed for each.
  26. */
  27. public function TerrainDiffuseMethod(splatTextures:Array, blendingTexture:Texture2DBase, tileData:Array)
  28. {
  29. super();
  30. _splats = Vector.<Texture2DBase>(splatTextures);
  31. _tileData = tileData;
  32. _blendingTexture = blendingTexture;
  33. _numSplattingLayers = _splats.length;
  34. if (_numSplattingLayers > 4)
  35. throw new Error("More than 4 splatting layers is not supported!");
  36. }
  37. /**
  38. * @inheritDoc
  39. */
  40. override arcane function initConstants(vo:MethodVO):void
  41. {
  42. var data:Vector.<Number> = vo.fragmentData;
  43. var index:int = vo.fragmentConstantsIndex;
  44. data[index] = _tileData? _tileData[0] : 1;
  45. for (var i:int = 0; i < _numSplattingLayers; ++i) {
  46. if (i < 3)
  47. data[uint(index + i + 1)] = _tileData? _tileData[i + 1] : 50;
  48. else
  49. data[uint(index + i - 4)] = _tileData? _tileData[i + 1] : 50;
  50. }
  51. }
  52. /**
  53. * @inheritDoc
  54. */
  55. arcane override function getFragmentPostLightingCode(vo:MethodVO, regCache:ShaderRegisterCache, targetReg:ShaderRegisterElement):String
  56. {
  57. var code:String = "";
  58. var albedo:ShaderRegisterElement;
  59. var scaleRegister:ShaderRegisterElement;
  60. var scaleRegister2:ShaderRegisterElement;
  61. // incorporate input from ambient
  62. if (vo.numLights > 0) {
  63. if (_shadowRegister)
  64. code += "mul " + _totalLightColorReg + ".xyz, " + _totalLightColorReg + ".xyz, " + _shadowRegister + ".w\n";
  65. code += "add " + targetReg + ".xyz, " + _totalLightColorReg + ".xyz, " + targetReg + ".xyz\n" +
  66. "sat " + targetReg + ".xyz, " + targetReg + ".xyz\n";
  67. regCache.removeFragmentTempUsage(_totalLightColorReg);
  68. albedo = regCache.getFreeFragmentVectorTemp();
  69. regCache.addFragmentTempUsages(albedo, 1);
  70. } else
  71. albedo = targetReg;
  72. if (!_useTexture)
  73. throw new Error("TerrainDiffuseMethod requires a diffuse texture!");
  74. _diffuseInputRegister = regCache.getFreeTextureReg();
  75. vo.texturesIndex = _diffuseInputRegister.index;
  76. var blendTexReg:ShaderRegisterElement = regCache.getFreeTextureReg();
  77. scaleRegister = regCache.getFreeFragmentConstant();
  78. if (_numSplattingLayers == 4)
  79. scaleRegister2 = regCache.getFreeFragmentConstant();
  80. var uv:ShaderRegisterElement = regCache.getFreeFragmentVectorTemp();
  81. regCache.addFragmentTempUsages(uv, 1);
  82. var uvReg:ShaderRegisterElement = _sharedRegisters.uvVarying;
  83. code += "mul " + uv + ", " + uvReg + ", " + scaleRegister + ".x\n" +
  84. getSplatSampleCode(vo, albedo, _diffuseInputRegister, texture, uv);
  85. var blendValues:ShaderRegisterElement = regCache.getFreeFragmentVectorTemp();
  86. regCache.addFragmentTempUsages(blendValues, 1);
  87. code += getTex2DSampleCode(vo, blendValues, blendTexReg, _blendingTexture, uvReg, "clamp");
  88. var splatTexReg:ShaderRegisterElement;
  89. vo.fragmentConstantsIndex = scaleRegister.index*4;
  90. var comps:Vector.<String> = Vector.<String>([ ".x", ".y", ".z", ".w" ]);
  91. for (var i:int = 0; i < _numSplattingLayers; ++i) {
  92. var scaleRegName:String = i < 3? scaleRegister + comps[i + 1] : scaleRegister2 + comps[i - 3];
  93. splatTexReg = regCache.getFreeTextureReg();
  94. code += "mul " + uv + ", " + uvReg + ", " + scaleRegName + "\n" +
  95. getSplatSampleCode(vo, uv, splatTexReg, _splats[i], uv);
  96. code += "sub " + uv + ", " + uv + ", " + albedo + "\n" +
  97. "mul " + uv + ", " + uv + ", " + blendValues + comps[i] + "\n" +
  98. "add " + albedo + ", " + albedo + ", " + uv + "\n";
  99. }
  100. regCache.removeFragmentTempUsage(uv);
  101. regCache.removeFragmentTempUsage(blendValues);
  102. if (vo.numLights > 0) {
  103. code += "mul " + targetReg + ".xyz, " + albedo + ".xyz, " + targetReg + ".xyz\n" +
  104. "mov " + targetReg + ".w, " + albedo + ".w\n";
  105. regCache.removeFragmentTempUsage(albedo);
  106. }
  107. return code;
  108. }
  109. /**
  110. * @inheritDoc
  111. */
  112. arcane override function activate(vo:MethodVO, stage3DProxy:Stage3DProxy):void
  113. {
  114. var context:Context3D = stage3DProxy._context3D;
  115. var i:int;
  116. var texIndex:int = vo.texturesIndex;
  117. super.activate(vo, stage3DProxy);
  118. context.setTextureAt(texIndex + 1, _blendingTexture.getTextureForStage3D(stage3DProxy));
  119. texIndex += 2;
  120. for (i = 0; i < _numSplattingLayers; ++i)
  121. context.setTextureAt(i + texIndex, _splats[i].getTextureForStage3D(stage3DProxy));
  122. }
  123. /**
  124. * @inheritDoc
  125. */
  126. override public function set alphaThreshold(value:Number):void
  127. {
  128. if (value > 0)
  129. throw new Error("Alpha threshold not supported for TerrainDiffuseMethod");
  130. }
  131. /**
  132. * Gets the sample code for a single splat.
  133. */
  134. protected function getSplatSampleCode(vo:MethodVO, targetReg:ShaderRegisterElement, inputReg:ShaderRegisterElement, texture:TextureProxyBase, uvReg:ShaderRegisterElement = null):String
  135. {
  136. uvReg ||= _sharedRegisters.uvVarying;
  137. return getTex2DSampleCode(vo, targetReg, inputReg, texture, uvReg, "wrap");
  138. }
  139. }
  140. }