123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394 |
- package h3d.mat;
- import h3d.mat.Data;
- @:allow(h3d.mat.BaseMaterial)
- #if !macro
- @:build(hxd.impl.BitsBuilder.build())
- #end
- class Pass {
- public var name(default, null) : String;
- var flags : Int;
- var passId : Int;
- var bits : Int = 0;
- var parentPass : Pass;
- var parentShaders : hxsl.ShaderList;
- var selfShaders(default, null) : hxsl.ShaderList;
- var selfShadersChanged(default, null) : Bool;
- var selfShadersCache : hxsl.ShaderList;
- var shaders : hxsl.ShaderList;
- var nextPass : Pass;
- var rendererFlags : Int = 0;
- @:bits(flags) public var enableLights : Bool;
- /**
- Inform the pass system that the parameters will be modified in object draw() command,
- so they will be manually uploaded by calling RenderContext.uploadParams.
- **/
- @:bits(flags) public var dynamicParameters : Bool;
- /**
- Mark the pass as static, this will allow some renderers or shadows to filter it
- when rendering static/dynamic parts.
- **/
- @:bits(flags) public var isStatic : Bool;
- @:bits(flags) var batchMode : Bool; // for MeshBatch
- @:bits(bits) public var culling : Face;
- @:bits(bits) public var depthWrite : Bool;
- @:bits(bits) public var depthTest : Compare;
- @:bits(bits) public var blendSrc : Blend;
- @:bits(bits) public var blendDst : Blend;
- @:bits(bits) public var blendAlphaSrc : Blend;
- @:bits(bits) public var blendAlphaDst : Blend;
- @:bits(bits) public var blendOp : Operation;
- @:bits(bits) public var blendAlphaOp : Operation;
- @:bits(bits) public var wireframe : Bool;
- @:bits(bits) public var culled : Bool;
- public var colorMask : Int;
- public var layer : Int = 0;
- public var stencil : Stencil;
- // one bit for internal engine usage
- @:bits(bits) @:noCompletion var reserved : Bool;
- public function new(name, ?shaders, ?parent) {
- this.parentPass = parent;
- this.shaders = shaders;
- setPassName(name);
- culling = Back;
- blend(One, Zero);
- depth(true, Less);
- blendOp = blendAlphaOp = Add;
- colorMask = 15;
- }
- public function load( p : Pass ) {
- name = p.name;
- passId = p.passId;
- bits = p.bits;
- enableLights = p.enableLights;
- dynamicParameters = p.dynamicParameters;
- culling = p.culling;
- depthWrite = p.depthWrite;
- depthTest = p.depthTest;
- blendSrc = p.blendSrc;
- blendDst = p.blendDst;
- blendOp = p.blendOp;
- blendAlphaSrc = p.blendAlphaSrc;
- blendAlphaDst = p.blendAlphaDst;
- blendAlphaOp = p.blendAlphaOp;
- colorMask = p.colorMask;
- if (p.stencil != null) {
- if (stencil == null) stencil = new Stencil();
- stencil.load(p.stencil);
- }
- }
- public function setPassName( name : String ) {
- this.name = name;
- passId = hxsl.Globals.allocID(name);
- }
- public inline function blend( src, dst ) {
- this.blendSrc = src;
- this.blendAlphaSrc = src;
- this.blendDst = dst;
- this.blendAlphaDst = dst;
- }
- public function setBlendMode( b : BlendMode ) {
- blendOp = Add;
- blendAlphaOp = Add;
- switch( b ) {
- case None: // Out = 1 * Src + 0 * Dst
- blend(One, Zero);
- case Alpha: // Out = SrcA * Src + (1 - SrcA) * Dst
- blend(SrcAlpha, OneMinusSrcAlpha);
- blendAlphaSrc = One;
- case Add: // Out = SrcA * Src + 1 * Dst
- blend(SrcAlpha, One);
- blendAlphaSrc = One;
- case AlphaAdd: // Out = Src + (1 - SrcA) * Dst
- blend(One, OneMinusSrcAlpha);
- case SoftAdd: // Out = (1 - Dst) * Src + 1 * Dst
- blend(OneMinusDstColor, One);
- blendAlphaSrc = One;
- case Multiply: // Out = Dst * Src + 0 * Dst
- blend(DstColor, Zero);
- blendAlphaSrc = One;
- case AlphaMultiply: // Out = Dst * Src + (1 - SrcA) * Dst
- blend(DstColor, OneMinusSrcAlpha);
- case Erase: // Out = 0 * Src + (1 - Srb) * Dst
- blend(Zero, OneMinusSrcColor);
- case Screen: // Out = 1 * Src + (1 - Srb) * Dst
- blend(One, OneMinusSrcColor);
- case Sub: // Out = 1 * Dst - SrcA * Src
- blend(SrcAlpha, One);
- blendOp = ReverseSub;
- blendAlphaOp = ReverseSub;
- case Max: // Out = MAX( Src, Dst )
- blend(One, One);
- blendAlphaOp = Max;
- blendOp = Max;
- case Min: // Out = MIN( Src, Dst )
- blend(One, One);
- blendAlphaOp = Min;
- blendOp = Min;
- }
- }
- public function depth( write, test ) {
- this.depthWrite = write;
- this.depthTest = test;
- }
- public function setColorMask(r, g, b, a) {
- this.colorMask = (r?1:0) | (g?2:0) | (b?4:0) | (a?8:0);
- }
- public function setColorChannel( c : hxsl.Channel) {
- switch( c ) {
- case R: setColorMask(true, false, false, false);
- case G: setColorMask(false, true, false, false);
- case B: setColorMask(false, false, true, false);
- case A: setColorMask(false, false, false, true);
- default: throw "Unsupported channel "+c;
- }
- }
- public function setColorMaski(r, g, b, a, i) {
- if ( i > 8 )
- throw "Color mask i supports 8 Render target";
- var mask = (r?1:0) | (g?2:0) | (b?4:0) | (a?8:0);
- mask = mask << (i * 4);
- this.colorMask = this.colorMask | mask;
- }
- function resetRendererFlags() {
- rendererFlags = 0;
- }
- public function addShader<T:hxsl.Shader>(s:T) : T {
- // throwing an exception will require NG GameServer review
- if( s == null ) return null;
- shaders = hxsl.ShaderList.addSort(s, shaders);
- resetRendererFlags();
- return s;
- }
- function addSelfShader<T:hxsl.Shader>(s:T) : T {
- if ( s == null ) return null;
- selfShadersChanged = true;
- selfShaders = hxsl.ShaderList.addSort(s, selfShaders);
- resetRendererFlags();
- return s;
- }
- /**
- Can be used for internal usage
- **/
- function addShaderAtIndex<T:hxsl.Shader>(s:T, index:Int) : T {
- var prev = null;
- var cur = shaders;
- while( index > 0 && cur != parentShaders ) {
- prev = cur;
- cur = cur.next;
- index--;
- }
- if( prev == null )
- shaders = new hxsl.ShaderList(s, cur);
- else
- prev.next = new hxsl.ShaderList(s, cur);
- return s;
- }
- function getShaderIndex(s:hxsl.Shader) : Int {
- var index = 0;
- var cur = shaders;
- while( cur != parentShaders ) {
- if( cur.s == s ) return index;
- cur = cur.next;
- index++;
- }
- return -1;
- }
- public function removeShader(s) {
- var sl = shaders, prev = null;
- var shaderFound = false;
- while( sl != null ) {
- if( sl.s == s ) {
- resetRendererFlags();
- if ( selfShadersCache == sl )
- selfShadersCache = selfShadersCache.next;
- if( prev == null )
- shaders = sl.next;
- else
- prev.next = sl.next;
- shaderFound = true;
- break;
- }
- prev = sl;
- sl = sl.next;
- }
- sl = selfShaders;
- prev = null;
- while ( sl != null ) {
- if ( sl.s == s ) {
- resetRendererFlags();
- if ( selfShadersCache == sl )
- selfShadersCache = selfShadersCache.next;
- if ( prev == null )
- selfShaders = sl.next;
- else
- prev.next = sl.next;
- return true;
- }
- prev = sl;
- sl = sl.next;
- }
- return shaderFound;
- }
- public function removeShaders< T:hxsl.Shader >(t:Class<T>) {
- var sl = shaders;
- var prev = null;
- while( sl != null ) {
- if( Std.isOfType(sl.s, t) ) {
- resetRendererFlags();
- if ( selfShadersCache == sl )
- selfShadersCache = selfShadersCache.next;
- if( prev == null )
- shaders = sl.next;
- else
- prev.next = sl.next;
- }
- else
- prev = sl;
- sl = sl.next;
- }
- sl = selfShaders;
- prev = null;
- while( sl != null ) {
- if( Std.isOfType(sl.s, t) ) {
- resetRendererFlags();
- if ( selfShadersCache == sl )
- selfShadersCache = selfShadersCache.next;
- if( prev == null )
- selfShaders = sl.next;
- else
- prev.next = sl.next;
- }
- else
- prev = sl;
- sl = sl.next;
- }
- }
- public function getShader< T:hxsl.Shader >(t:Class<T>) : T {
- var s = _getShader(t, shaders);
- return s != null ? s : _getShader(t, selfShaders);
- }
- function _getShader< T:hxsl.Shader >(t:Class<T>, s : hxsl.ShaderList) : T {
- while( s != null && s != parentShaders ) {
- var sh = Std.downcast(s.s, t);
- if( sh != null )
- return sh;
- s = s.next;
- }
- return null;
- }
- public function getShaderByName( name : String ) : hxsl.Shader {
- var s = _getShaderByName(name, shaders);
- return s != null ? s : _getShaderByName(name, selfShaders);
- }
- function _getShaderByName( name : String, sl : hxsl.ShaderList ) : hxsl.Shader {
- while( sl != null && sl != parentShaders ) {
- if( @:privateAccess sl.s.shader.data.name == name )
- return sl.s;
- sl = sl.next;
- }
- return null;
- }
- public inline function getShaders() {
- return shaders.iterateTo(parentShaders);
- }
- function checkInfiniteLoop() {
- var shaderList = [];
- var s = selfShaders;
- while ( s != null ) {
- for ( already in shaderList )
- if ( already == s )
- throw "infinite loop";
- shaderList.push(s);
- s = s.next;
- }
- }
- function selfShadersRec(rebuild : Bool) {
- if ( selfShaders == null )
- return shaders;
- if ( !selfShadersChanged && !rebuild && shaders == selfShadersCache )
- return selfShaders;
- var sl = selfShaders, prev = null;
- while ( sl != null && sl != selfShadersCache ) {
- prev = sl;
- sl = sl.next;
- }
- selfShadersCache = shaders;
- if ( prev != null )
- prev.next = selfShadersCache;
- else
- selfShaders = shaders;
- return selfShaders;
- }
- function getShadersRec() {
- if( parentPass == null || parentShaders == parentPass.shaders ) {
- return selfShadersRec(false);
- }
- // relink to our parent shader list
- var s = shaders, prev = null;
- while( s != null && s != parentShaders ) {
- prev = s;
- s = s.next;
- }
- if ( s != parentShaders )
- prev = null;
- parentShaders = parentPass.shaders;
- if( prev == null )
- shaders = parentShaders;
- else
- prev.next = parentShaders;
- return selfShadersRec(true);
- }
- function reverseDepthTest() {
- depthTest = switch( depthTest ) {
- case Greater: Less;
- case GreaterEqual: LessEqual;
- case Less: Greater;
- case LessEqual: GreaterEqual;
- default: depthTest;
- };
- }
- public function clone() {
- var p = new Pass(name, shaders.clone());
- p.selfShaders = selfShaders;
- p.bits = bits;
- p.enableLights = enableLights;
- if (stencil != null) p.stencil = stencil.clone();
- return p;
- }
- }
|