PageRenderTime 50ms CodeModel.GetById 23ms app.highlight 20ms RepoModel.GetById 1ms app.codeStats 1ms

/src/away3d/materials/methods/CelDiffuseMethod.as

http://github.com/away3d/away3d-core-fp11
ActionScript | 134 lines | 81 code | 16 blank | 37 comment | 0 complexity | 5b4e00545e626df0b69a90b69f5635b5 MD5 | raw file
  1package 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.ShaderRegisterData;
  7	import away3d.materials.compilation.ShaderRegisterElement;
  8	
  9	use namespace arcane;
 10	
 11	/**
 12	 * CelDiffuseMethod provides a shading method to add diffuse cel (cartoon) shading.
 13	 */
 14	public class CelDiffuseMethod extends CompositeDiffuseMethod
 15	{
 16		private var _levels:uint;
 17		private var _dataReg:ShaderRegisterElement;
 18		private var _smoothness:Number = .1;
 19		
 20		/**
 21		 * Creates a new CelDiffuseMethod object.
 22		 * @param levels The amount of shadow gradations.
 23		 * @param baseDiffuseMethod An optional diffuse method on which the cartoon shading is based. If omitted, BasicDiffuseMethod is used.
 24		 */
 25		public function CelDiffuseMethod(levels:uint = 3, baseDiffuseMethod:BasicDiffuseMethod = null)
 26		{
 27			super(clampDiffuse, baseDiffuseMethod);
 28			
 29			_levels = levels;
 30		}
 31
 32		/**
 33		 * @inheritDoc
 34		 */
 35		override arcane function initConstants(vo:MethodVO):void
 36		{
 37			var data:Vector.<Number> = vo.fragmentData;
 38			var index:int = vo.secondaryFragmentConstantsIndex;
 39			super.initConstants(vo);
 40			data[index + 1] = 1;
 41			data[index + 2] = 0;
 42		}
 43
 44		/**
 45		 * The amount of shadow gradations.
 46		 */
 47		public function get levels():uint
 48		{
 49			return _levels;
 50		}
 51		
 52		public function set levels(value:uint):void
 53		{
 54			_levels = value;
 55		}
 56		
 57		/**
 58		 * The smoothness of the edge between 2 shading levels.
 59		 */
 60		public function get smoothness():Number
 61		{
 62			return _smoothness;
 63		}
 64		
 65		public function set smoothness(value:Number):void
 66		{
 67			_smoothness = value;
 68		}
 69		
 70		/**
 71		 * @inheritDoc
 72		 */
 73		arcane override function cleanCompilationData():void
 74		{
 75			super.cleanCompilationData();
 76			_dataReg = null;
 77		}
 78		
 79		/**
 80		 * @inheritDoc
 81		 */
 82		override arcane function getFragmentPreLightingCode(vo:MethodVO, regCache:ShaderRegisterCache):String
 83		{
 84			_dataReg = regCache.getFreeFragmentConstant();
 85			vo.secondaryFragmentConstantsIndex = _dataReg.index*4;
 86			return super.getFragmentPreLightingCode(vo, regCache);
 87		}
 88		
 89		/**
 90		 * @inheritDoc
 91		 */
 92		override arcane function activate(vo:MethodVO, stage3DProxy:Stage3DProxy):void
 93		{
 94			super.activate(vo, stage3DProxy);
 95			var data:Vector.<Number> = vo.fragmentData;
 96			var index:int = vo.secondaryFragmentConstantsIndex;
 97			data[index] = _levels;
 98			data[index + 3] = _smoothness;
 99		}
100		
101		/**
102		 * Snaps the diffuse shading of the wrapped method to one of the levels.
103		 * @param vo The MethodVO used to compile the current shader.
104		 * @param t The register containing the diffuse strength in the "w" component.
105		 * @param regCache The register cache used for the shader compilation.
106		 * @param sharedRegisters The shared register data for this shader.
107		 * @return The AGAL fragment code for the method.
108		 */
109		private function clampDiffuse(vo:MethodVO, t:ShaderRegisterElement, regCache:ShaderRegisterCache, sharedRegisters:ShaderRegisterData):String
110		{
111			return "mul " + t + ".w, " + t + ".w, " + _dataReg + ".x\n" +
112				"frc " + t + ".z, " + t + ".w\n" +
113				"sub " + t + ".y, " + t + ".w, " + t + ".z\n" +
114				"mov " + t + ".x, " + _dataReg + ".x\n" +
115				"sub " + t + ".x, " + t + ".x, " + _dataReg + ".y\n" +
116				"rcp " + t + ".x," + t + ".x\n" +
117				"mul " + t + ".w, " + t + ".y, " + t + ".x\n" +
118				
119				// previous clamped strength
120				"sub " + t + ".y, " + t + ".w, " + t + ".x\n" +
121				
122				// fract/epsilon (so 0 - epsilon will become 0 - 1)
123				"div " + t + ".z, " + t + ".z, " + _dataReg + ".w\n" +
124				"sat " + t + ".z, " + t + ".z\n" +
125				
126				"mul " + t + ".w, " + t + ".w, " + t + ".z\n" +
127				// 1-z
128				"sub " + t + ".z, " + _dataReg + ".y, " + t + ".z\n" +
129				"mul " + t + ".y, " + t + ".y, " + t + ".z\n" +
130				"add " + t + ".w, " + t + ".w, " + t + ".y\n" +
131				"sat " + t + ".w, " + t + ".w\n";
132		}
133	}
134}