public SetSceneBlending ( SceneBlendFactor src, SceneBlendFactor dest ) : void | ||
src | SceneBlendFactor | The source factor in the above calculation, i.e. multiplied by the texture color components. |
dest | SceneBlendFactor | The destination factor in the above calculation, i.e. multiplied by the pixel color components. |
리턴 | void |
/// <summary> /// Internal method for splitting the passes into illumination passes. /// </summary> public void CompileIlluminationPasses() { ClearIlluminationPasses(); // don't need to split transparent passes since they are rendered seperately if ( this.IsTransparent ) { return; } // start off with ambient passes IlluminationStage stage = IlluminationStage.Ambient; bool hasAmbient = false; for ( int i = 0; i < _passes.Count; /* increment in logic */) { Pass pass = (Pass)_passes[ i ]; IlluminationPass iPass; switch ( stage ) { case IlluminationStage.Ambient: // keep looking for ambient only if ( pass.IsAmbientOnly ) { iPass = new IlluminationPass(); iPass.OriginalPass = pass; iPass.Pass = pass; iPass.Stage = stage; _illuminationPasses.Add( iPass ); hasAmbient = true; // progress to the next pass i++; } else { // split off any ambient part if ( pass.Ambient.CompareTo( ColorEx.Black ) != 0 || pass.Emissive.CompareTo( ColorEx.Black ) != 0 ) { Pass newPass = new Pass( this, pass.Index ); pass.CopyTo( newPass ); // remove any texture units newPass.RemoveAllTextureUnitStates(); // also remove any fragment program if ( newPass.HasFragmentProgram ) { newPass.SetFragmentProgram( "" ); } // We have to leave vertex program alone (if any) and // just trust that the author is using light bindings, which // we will ensure there are none in the ambient pass newPass.Diffuse = ColorEx.Black; newPass.Specular = ColorEx.Black; // if ambient and emissive are zero, then color write isn't needed if ( newPass.Ambient.CompareTo( ColorEx.Black ) == 0 && newPass.Emissive.CompareTo( ColorEx.Black ) == 0 ) { newPass.ColorWriteEnabled = false; } iPass = new IlluminationPass(); iPass.DestroyOnShutdown = true; iPass.OriginalPass = pass; iPass.Pass = newPass; iPass.Stage = stage; _illuminationPasses.Add( iPass ); hasAmbient = true; } if ( !hasAmbient ) { // make up a new basic pass Pass newPass = new Pass( this, pass.Index ); pass.CopyTo( newPass ); newPass.Ambient = ColorEx.Black; newPass.Diffuse = ColorEx.Black; iPass = new IlluminationPass(); iPass.DestroyOnShutdown = true; iPass.OriginalPass = pass; iPass.Pass = newPass; iPass.Stage = stage; _illuminationPasses.Add( iPass ); hasAmbient = true; } // this means we are done with ambients, progress to per-light stage = IlluminationStage.PerLight; } break; case IlluminationStage.PerLight: if ( pass.IteratePerLight ) { // if this is per-light already, use it directly iPass = new IlluminationPass(); iPass.DestroyOnShutdown = false; iPass.OriginalPass = pass; iPass.Pass = pass; iPass.Stage = stage; _illuminationPasses.Add( iPass ); // progress to the next pass i++; } else { // split off per-light details (can only be done for one) if ( pass.LightingEnabled && ( pass.Diffuse.CompareTo( ColorEx.Black ) != 0 || pass.Specular.CompareTo( ColorEx.Black ) != 0 ) ) { // copy existing pass Pass newPass = new Pass( this, pass.Index ); pass.CopyTo( newPass ); newPass.RemoveAllTextureUnitStates(); // also remove any fragment program if ( newPass.HasFragmentProgram ) { newPass.SetFragmentProgram( "" ); } // Cannot remove vertex program, have to assume that // it will process diffuse lights, ambient will be turned off newPass.Ambient = ColorEx.Black; newPass.Emissive = ColorEx.Black; // must be additive newPass.SetSceneBlending( SceneBlendFactor.One, SceneBlendFactor.One ); iPass = new IlluminationPass(); iPass.DestroyOnShutdown = true; iPass.OriginalPass = pass; iPass.Pass = newPass; iPass.Stage = stage; _illuminationPasses.Add( iPass ); } // This means the end of per-light passes stage = IlluminationStage.Decal; } break; case IlluminationStage.Decal: // We just want a 'lighting off' pass to finish off // and only if there are texture units if ( pass.TextureUnitStageCount > 0 ) { if ( !pass.LightingEnabled ) { // we assume this pass already combines as required with the scene iPass = new IlluminationPass(); iPass.DestroyOnShutdown = false; iPass.OriginalPass = pass; iPass.Pass = pass; iPass.Stage = stage; _illuminationPasses.Add( iPass ); } else { // Copy the pass and tweak away the lighting parts Pass newPass = new Pass( this, pass.Index ); pass.CopyTo( newPass ); newPass.Ambient = ColorEx.Black; newPass.Diffuse = ColorEx.Black; newPass.Specular = ColorEx.Black; newPass.Emissive = ColorEx.Black; newPass.LightingEnabled = false; // modulate newPass.SetSceneBlending( SceneBlendFactor.DestColor, SceneBlendFactor.Zero ); // there is nothing we can do about vertex & fragment // programs here, so people will just have to make their // programs friendly-like if they want to use this technique iPass = new IlluminationPass(); iPass.DestroyOnShutdown = true; iPass.OriginalPass = pass; iPass.Pass = newPass; iPass.Stage = stage; _illuminationPasses.Add( iPass ); } } // always increment on decal, since nothing more to do with this pass i++; break; } } _compiledIlluminationPasses = true; }
/// <see cref="Translator.Translate"/> public override void Translate( ScriptCompiler compiler, AbstractNode node ) { ObjectAbstractNode obj = (ObjectAbstractNode)node; Technique technique = (Technique)obj.Parent.Context; _pass = technique.CreatePass(); obj.Context = _pass; // Get the name of the technique if ( !string.IsNullOrEmpty( obj.Name ) ) _pass.Name = obj.Name; // Set the properties for the material foreach ( AbstractNode i in obj.Children ) { if ( i is PropertyAbstractNode ) { PropertyAbstractNode prop = (PropertyAbstractNode)i; switch ( (Keywords)prop.Id ) { #region ID_AMBIENT case Keywords.ID_AMBIENT: if ( prop.Values.Count == 0 ) { compiler.AddError( CompileErrorCode.NumberExpected, prop.File, prop.Line ); } else if ( prop.Values.Count > 4 ) { compiler.AddError( CompileErrorCode.FewerParametersExpected, prop.File, prop.Line, "ambient must have at most 4 parameters" ); } else { if ( prop.Values[ 0 ] is AtomAbstractNode && ( (AtomAbstractNode)prop.Values[ 0 ] ).Id == (uint)Keywords.ID_VERTEX_COLOUR ) { _pass.VertexColorTracking = _pass.VertexColorTracking | TrackVertexColor.Ambient; } else { ColorEx val = ColorEx.White; if ( getColor( prop.Values, 0, out val ) ) _pass.Ambient = val; else compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, "ambient requires 3 or 4 colour arguments, or a \"vertexcolour\" directive" ); } } break; #endregion ID_AMBIENT #region ID_DIFFUSE case Keywords.ID_DIFFUSE: if ( prop.Values.Count == 0 ) { compiler.AddError( CompileErrorCode.NumberExpected, prop.File, prop.Line ); } else if ( prop.Values.Count > 4 ) { compiler.AddError( CompileErrorCode.FewerParametersExpected, prop.File, prop.Line, "diffuse must have at most 4 arguments" ); } else { if ( prop.Values[ 0 ] is AtomAbstractNode && ( (AtomAbstractNode)prop.Values[ 0 ] ).Id == (uint)Keywords.ID_VERTEX_COLOUR ) { _pass.VertexColorTracking = _pass.VertexColorTracking | TrackVertexColor.Diffuse; } else { ColorEx val; if ( getColor( prop.Values, 0, out val ) ) _pass.Diffuse = val; else compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, "diffuse requires 3 or 4 colour arguments, or a \"vertexcolour\" directive" ); } } break; #endregion ID_DIFFUSE #region ID_SPECULAR case Keywords.ID_SPECULAR: if ( prop.Values.Count == 0 ) { compiler.AddError( CompileErrorCode.NumberExpected, prop.File, prop.Line ); } else if ( prop.Values.Count > 5 ) { compiler.AddError( CompileErrorCode.FewerParametersExpected, prop.File, prop.Line, "specular must have at most 5 arguments" ); } else { if ( prop.Values[ 0 ] is AtomAbstractNode && ( (AtomAbstractNode)prop.Values[ 0 ] ).Id == (uint)Keywords.ID_VERTEX_COLOUR ) { _pass.VertexColorTracking = _pass.VertexColorTracking | TrackVertexColor.Specular; if ( prop.Values.Count >= 2 ) { Real val = 0; if ( getReal( prop.Values[ prop.Values.Count - 1 ], out val ) ) _pass.Shininess = val; else { compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, "specular does not support \"" + prop.Values[ prop.Values.Count - 1 ].Value + "\" as its second argument" ); } } } else { if ( prop.Values.Count < 4 ) { compiler.AddError( CompileErrorCode.NumberExpected, prop.File, prop.Line, "specular expects at least 4 arguments" ); } else { AbstractNode i0 = getNodeAt( prop.Values, 0 ), i1 = getNodeAt( prop.Values, 1 ), i2 = getNodeAt( prop.Values, 2 ); ColorEx val = new ColorEx( 0, 0, 0, 0 ); if ( getFloat( i0, out val.r ) && getFloat( i1, out val.g ) && getFloat( i2, out val.b ) ) { if ( prop.Values.Count == 4 ) { _pass.Specular = val; AbstractNode i3 = getNodeAt( prop.Values, 3 ); Real shininess = 0.0f; if ( getReal( i3, out shininess ) ) _pass.Shininess = shininess; else compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, "specular fourth argument must be a valid number for shininess attribute" ); } else { AbstractNode i3 = getNodeAt( prop.Values, 3 ); if ( !getFloat( i3, out val.a ) ) { compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, "specular fourth argument must be a valid color component value" ); } else _pass.Specular = val; AbstractNode i4 = getNodeAt( prop.Values, 4 ); Real shininess = 0.0f; if ( getReal( i4, out shininess ) ) _pass.Shininess = shininess; else { compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, "specular fourth argument must be a valid number for shininess attribute" ); } } } else { compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, "specular must have first 3 arguments be a valid colour" ); } } } } break; #endregion ID_SPECULAR #region ID_EMISSIVE case Keywords.ID_EMISSIVE: if ( prop.Values.Count == 0 ) { compiler.AddError( CompileErrorCode.NumberExpected, prop.File, prop.Line ); } else if ( prop.Values.Count > 4 ) { compiler.AddError( CompileErrorCode.FewerParametersExpected, prop.File, prop.Line, "emissive must have at most 4 arguments" ); } else { if ( prop.Values[ 0 ] is AtomAbstractNode && ( (AtomAbstractNode)prop.Values[ 0 ] ).Id == (uint)Keywords.ID_VERTEX_COLOUR ) { _pass.VertexColorTracking = _pass.VertexColorTracking | TrackVertexColor.Emissive; } else { ColorEx val; if ( getColor( prop.Values, 0, out val ) ) _pass.SelfIllumination = val; else compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, "emissive requires 3 or 4 colour arguments, or a \"vertexcolour\" directive" ); } } break; #endregion ID_EMISSIVE #region ID_SCENE_BLEND case Keywords.ID_SCENE_BLEND: if ( prop.Values.Count == 0 ) { compiler.AddError( CompileErrorCode.StringExpected, prop.File, prop.Line ); } else if ( prop.Values.Count > 2 ) { compiler.AddError( CompileErrorCode.FewerParametersExpected, prop.File, prop.Line, "scene_blend supports at most 2 arguments" ); } else if ( prop.Values.Count == 1 ) { if ( prop.Values[ 0 ] is AtomAbstractNode ) { AtomAbstractNode atom = (AtomAbstractNode)prop.Values[ 0 ]; switch ( (Keywords)atom.Id ) { case Keywords.ID_ADD: _pass.SetSceneBlending( SceneBlendType.Add ); break; case Keywords.ID_MODULATE: _pass.SetSceneBlending( SceneBlendType.Modulate ); break; case Keywords.ID_COLOUR_BLEND: _pass.SetSceneBlending( SceneBlendType.TransparentColor ); break; case Keywords.ID_ALPHA_BLEND: _pass.SetSceneBlending( SceneBlendType.TransparentAlpha ); break; default: compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, "scene_blend does not support \"" + prop.Values[ 0 ].Value + "\" for argument 1" ); break; } } else { compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, "scene_blend does not support \"" + prop.Values[ 0 ].Value + "\" for argument 1" ); } } else { AbstractNode i0 = getNodeAt( prop.Values, 0 ), i1 = getNodeAt( prop.Values, 1 ); SceneBlendFactor sbf0, sbf1; if ( getEnumeration<SceneBlendFactor>( i0, compiler, out sbf0 ) && getEnumeration<SceneBlendFactor>( i1, compiler, out sbf1 ) ) { _pass.SetSceneBlending( sbf0, sbf1 ); } else { compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, "scene_blend does not support \"" + i0.Value + "\" and \"" + i1.Value + "\" as arguments" ); } } break; #endregion ID_SCENE_BLEND #region ID_SEPARATE_SCENE_BLEND case Keywords.ID_SEPARATE_SCENE_BLEND: if ( prop.Values.Count == 0 ) { compiler.AddError( CompileErrorCode.StringExpected, prop.File, prop.Line ); } else if ( prop.Values.Count == 3 ) { compiler.AddError( CompileErrorCode.FewerParametersExpected, prop.File, prop.Line, "separate_scene_blend must have 2 or 4 arguments" ); } else if ( prop.Values.Count > 4 ) { compiler.AddError( CompileErrorCode.FewerParametersExpected, prop.File, prop.Line, "separate_scene_blend must have 2 or 4 arguments" ); } else if ( prop.Values.Count == 2 ) { AbstractNode i0 = getNodeAt( prop.Values, 0 ), i1 = getNodeAt( prop.Values, 1 ); if ( i0 is AtomAbstractNode && i1 is AtomAbstractNode ) { AtomAbstractNode atom0 = (AtomAbstractNode)i0, atom1 = (AtomAbstractNode)i1; SceneBlendType sbt0, sbt1; switch ( (Keywords)atom0.Id ) { case Keywords.ID_ADD: sbt0 = SceneBlendType.Add; break; case Keywords.ID_MODULATE: sbt0 = SceneBlendType.Modulate; break; case Keywords.ID_COLOUR_BLEND: sbt0 = SceneBlendType.TransparentColor; break; case Keywords.ID_ALPHA_BLEND: sbt0 = SceneBlendType.TransparentAlpha; break; default: compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, "separate_scene_blend does not support \"" + atom0.Value + "\" as argument 1" ); return; } switch ( (Keywords)atom1.Id ) { case Keywords.ID_ADD: sbt1 = SceneBlendType.Add; break; case Keywords.ID_MODULATE: sbt1 = SceneBlendType.Modulate; break; case Keywords.ID_COLOUR_BLEND: sbt1 = SceneBlendType.TransparentColor; break; case Keywords.ID_ALPHA_BLEND: sbt1 = SceneBlendType.TransparentAlpha; break; default: compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, "separate_scene_blend does not support \"" + atom1.Value + "\" as argument 2" ); return; } throw new NotImplementedException( string.Format("SetSeparateSceneBlending({0}, {1})", sbt0, sbt1)); //TODO //mPass->setSeparateSceneBlending(sbt0, sbt1); } else { compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, "separate_scene_blend does not support \"" + i0.Value + "\" as argument 1" ); } } else { AbstractNode i0 = getNodeAt( prop.Values, 0 ), i1 = getNodeAt( prop.Values, 1 ), i2 = getNodeAt( prop.Values, 2 ), i3 = getNodeAt( prop.Values, 3 ); if ( i0 is AtomAbstractNode && i1 is AtomAbstractNode && i2 is AtomAbstractNode && i3 is AtomAbstractNode ) { SceneBlendFactor sbf0, sbf1, sbf2, sbf3; if ( getEnumeration<SceneBlendFactor>( i0, compiler, out sbf0 ) && getEnumeration<SceneBlendFactor>( i1, compiler, out sbf1 ) && getEnumeration<SceneBlendFactor>( i2, compiler, out sbf2 ) && getEnumeration<SceneBlendFactor>( i3, compiler, out sbf3 ) ) { //TODO //mPass->setSeparateSceneBlending(sbf0, sbf1, sbf2, sbf3); } else { compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, "one of the arguments to separate_scene_blend is not a valid scene blend factor directive" ); } } else { compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, "one of the arguments to separate_scene_blend is not a valid scene blend factor directive" ); } } break; #endregion ID_SEPARATE_SCENE_BLEND #region ID_SCENE_BLEND_OP case Keywords.ID_SCENE_BLEND_OP: if ( prop.Values.Count == 0 ) { compiler.AddError( CompileErrorCode.StringExpected, prop.File, prop.Line ); } else if ( prop.Values.Count > 1 ) { compiler.AddError( CompileErrorCode.FewerParametersExpected, prop.File, prop.Line, "scene_blend_op must have 1 argument" ); } else { if ( prop.Values[ 0 ] is AtomAbstractNode ) { AtomAbstractNode atom = (AtomAbstractNode)prop.Values[ 0 ]; switch ( (Keywords)atom.Id ) { case Keywords.ID_ADD: //TODO //mPass->setSceneBlendingOperation(SBO_ADD); break; case Keywords.ID_SUBTRACT: //TODO //mPass->setSceneBlendingOperation(SBO_SUBTRACT); break; case Keywords.ID_REVERSE_SUBTRACT: //TODO //mPass->setSceneBlendingOperation(SBO_REVERSE_SUBTRACT); break; case Keywords.ID_MIN: //TODO //mPass->setSceneBlendingOperation(SBO_MIN); break; case Keywords.ID_MAX: //TODO //mPass->setSceneBlendingOperation(SBO_MAX); break; default: compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, atom.Value + ": unrecognized argument" ); break; } } else { compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, prop.Values[ 0 ].Value + ": unrecognized argument" ); } } break; #endregion ID_SCENE_BLEND_OP #region ID_SEPARATE_SCENE_BLEND_OP case Keywords.ID_SEPARATE_SCENE_BLEND_OP: if ( prop.Values.Count == 0 ) { compiler.AddError( CompileErrorCode.StringExpected, prop.File, prop.Line ); } else if ( prop.Values.Count != 2 ) { compiler.AddError( CompileErrorCode.FewerParametersExpected, prop.File, prop.Line, "separate_scene_blend_op must have 2 arguments" ); } else { AbstractNode i0 = getNodeAt( prop.Values, 0 ), i1 = getNodeAt( prop.Values, 1 ); if ( i0 is AtomAbstractNode && i1 is AtomAbstractNode ) { AtomAbstractNode atom0 = (AtomAbstractNode)i0, atom1 = (AtomAbstractNode)i1; //TODO //SceneBlendOperation op = SBO_ADD, alphaOp = SBO_ADD; switch ( (Keywords)atom0.Id ) { case Keywords.ID_ADD: //TODO //op = SBO_ADD; break; case Keywords.ID_SUBTRACT: //TODO //op = SBO_SUBTRACT; break; case Keywords.ID_REVERSE_SUBTRACT: //TODO //op = SBO_REVERSE_SUBTRACT; break; case Keywords.ID_MIN: //TODO //op = SBO_MIN; break; case Keywords.ID_MAX: //TODO //op = SBO_MAX; break; default: compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, atom0.Value + ": unrecognized first argument" ); break; } switch ( (Keywords)atom1.Id ) { case Keywords.ID_ADD: //TODO //alphaOp = SBO_ADD; break; case Keywords.ID_SUBTRACT: //TODO //alphaOp = SBO_SUBTRACT; break; case Keywords.ID_REVERSE_SUBTRACT: //TODO //alphaOp = SBO_REVERSE_SUBTRACT; break; case Keywords.ID_MIN: //TODO //alphaOp = SBO_MIN; break; case Keywords.ID_MAX: //TODO //alphaOp = SBO_MAX; break; default: compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, atom1.Value + ": unrecognized second argument" ); break; } //TODO //mPass->setSeparateSceneBlendingOperation(op, alphaOp); } else { compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, prop.Values[ 0 ].Value + ": unrecognized argument" ); } } break; #endregion ID_SEPARATE_SCENE_BLEND_OP #region ID_DEPTH_CHECK case Keywords.ID_DEPTH_CHECK: if ( prop.Values.Count == 0 ) { compiler.AddError( CompileErrorCode.StringExpected, prop.File, prop.Line ); } else if ( prop.Values.Count > 1 ) { compiler.AddError( CompileErrorCode.FewerParametersExpected, prop.File, prop.Line, "depth_check must have 1 argument" ); } else { bool val = true; if ( getBoolean( prop.Values[ 0 ], out val ) ) _pass.DepthCheck = val; else compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, "depth_check third argument must be \"true\", \"false\", \"yes\", \"no\", \"on\", or \"off\"" ); } break; #endregion ID_DEPTH_CHECK #region ID_DEPTH_WRITE case Keywords.ID_DEPTH_WRITE: if ( prop.Values.Count == 0 ) { compiler.AddError( CompileErrorCode.StringExpected, prop.File, prop.Line ); } else if ( prop.Values.Count > 1 ) { compiler.AddError( CompileErrorCode.FewerParametersExpected, prop.File, prop.Line, "depth_write must have 1 argument" ); } else { bool val = true; if ( getBoolean( prop.Values[ 0 ], out val ) ) _pass.DepthWrite = val; else compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, "depth_write third argument must be \"true\", \"false\", \"yes\", \"no\", \"on\", or \"off\"" ); } break; #endregion ID_DEPTH_WRITE #region ID_DEPTH_BIAS case Keywords.ID_DEPTH_BIAS: if ( prop.Values.Count == 0 ) { compiler.AddError( CompileErrorCode.StringExpected, prop.File, prop.Line ); } else if ( prop.Values.Count > 2 ) { compiler.AddError( CompileErrorCode.FewerParametersExpected, prop.File, prop.Line, "depth_bias must have at most 2 arguments" ); } else { AbstractNode i0 = getNodeAt( prop.Values, 0 ), i1 = getNodeAt( prop.Values, 1 ); float val0, val1 = 0.0f; if ( getFloat( i0, out val0 ) ) { if ( i1 != null ) getFloat( i1, out val1 ); _pass.SetDepthBias( val0, val1 ); } else { compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, "depth_bias does not support \"" + i0.Value + "\" for argument 1" ); } } break; #endregion ID_DEPTH_BIAS #region ID_DEPTH_FUNC case Keywords.ID_DEPTH_FUNC: if ( prop.Values.Count == 0 ) { compiler.AddError( CompileErrorCode.StringExpected, prop.File, prop.Line ); } else if ( prop.Values.Count > 1 ) { compiler.AddError( CompileErrorCode.FewerParametersExpected, prop.File, prop.Line, "depth_func must have 1 argument" ); } else { CompareFunction func; if ( getEnumeration<CompareFunction>( prop.Values[ 0 ], compiler, out func ) ) _pass.DepthFunction = func; else compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, prop.Values[ 0 ].Value + " is not a valid CompareFunction" ); } break; #endregion ID_DEPTH_FUNC #region ID_ITERATION_DEPTH_BIAS case Keywords.ID_ITERATION_DEPTH_BIAS: if ( prop.Values.Count == 0 ) { compiler.AddError( CompileErrorCode.StringExpected, prop.File, prop.Line ); } else if ( prop.Values.Count > 1 ) { compiler.AddError( CompileErrorCode.FewerParametersExpected, prop.File, prop.Line, "iteration_depth_bias must have 1 argument" ); } else { float val = 0.0f; if ( getFloat( prop.Values[ 0 ], out val ) ) { //TODO /*mPass->setIterationDepthBias(val);*/ } else compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, prop.Values[ 0 ].Value + " is not a valid float value" ); } break; #endregion ID_ITERATION_DEPTH_BIAS #region ID_ALPHA_REJECTION case Keywords.ID_ALPHA_REJECTION: if ( prop.Values.Count == 0 ) { compiler.AddError( CompileErrorCode.StringExpected, prop.File, prop.Line ); } else if ( prop.Values.Count > 2 ) { compiler.AddError( CompileErrorCode.FewerParametersExpected, prop.File, prop.Line, "alpha_rejection must have at most 2 arguments" ); } else { AbstractNode i0 = getNodeAt( prop.Values, 0 ), i1 = getNodeAt( prop.Values, 1 ); CompareFunction func; if ( getEnumeration<CompareFunction>( i0, compiler, out func ) ) { if ( i1 != null ) { int val = 0; if ( getInt( i1, out val ) ) _pass.SetAlphaRejectSettings( func, val ); else compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, i1.Value + " is not a valid integer" ); } else _pass.AlphaRejectFunction = func; } else compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, i0.Value + " is not a valid CompareFunction" ); } break; #endregion ID_ALPHA_REJECTION #region ID_ALPHA_TO_COVERAGE case Keywords.ID_ALPHA_TO_COVERAGE: if ( prop.Values.Count == 0 ) { compiler.AddError( CompileErrorCode.StringExpected, prop.File, prop.Line ); } else if ( prop.Values.Count > 1 ) { compiler.AddError( CompileErrorCode.FewerParametersExpected, prop.File, prop.Line, "alpha_to_coverage must have 1 argument" ); } else { bool val = true; if ( getBoolean( prop.Values[ 0 ], out val ) ) _pass.IsAlphaToCoverageEnabled = val; else compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, "alpha_to_coverage argument must be \"true\", \"false\", \"yes\", \"no\", \"on\", or \"off\"" ); } break; #endregion ID_ALPHA_TO_COVERAGE #region ID_LIGHT_SCISSOR case Keywords.ID_LIGHT_SCISSOR: if ( prop.Values.Count == 0 ) { compiler.AddError( CompileErrorCode.StringExpected, prop.File, prop.Line ); } else if ( prop.Values.Count > 1 ) { compiler.AddError( CompileErrorCode.FewerParametersExpected, prop.File, prop.Line, "light_scissor must have only 1 argument" ); } else { bool val = false; if ( getBoolean( prop.Values[ 0 ], out val ) ) { //TODO /*mPass->setLightScissoringEnabled(val);*/ } else compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, prop.Values[ 0 ].Value + " is not a valid boolean" ); } break; #endregion ID_LIGHT_SCISSOR #region ID_LIGHT_CLIP_PLANES case Keywords.ID_LIGHT_CLIP_PLANES: if ( prop.Values.Count == 0 ) { compiler.AddError( CompileErrorCode.StringExpected, prop.File, prop.Line ); } else if ( prop.Values.Count > 1 ) { compiler.AddError( CompileErrorCode.FewerParametersExpected, prop.File, prop.Line, "light_clip_planes must have at most 1 argument" ); } else { bool val = false; if ( getBoolean( prop.Values[ 0 ], out val ) ) { //TODO /*mPass->setLightClipPlanesEnabled(val);*/ } else compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, prop.Values[ 0 ].Value + " is not a valid boolean" ); } break; #endregion ID_LIGHT_CLIP_PLANES #region ID_TRANSPARENT_SORTING case Keywords.ID_TRANSPARENT_SORTING: if ( prop.Values.Count == 0 ) { compiler.AddError( CompileErrorCode.StringExpected, prop.File, prop.Line ); } else if ( prop.Values.Count > 1 ) { compiler.AddError( CompileErrorCode.FewerParametersExpected, prop.File, prop.Line, "transparent_sorting must have at most 1 argument" ); } else { bool val = true; if ( getBoolean( prop.Values[ 0 ], out val ) ) { //TODO //mPass->setTransparentSortingEnabled(val); //mPass->setTransparentSortingForced(false); } else { string val2; if ( getString( prop.Values[ 0 ], out val2 ) && val2 == "force" ) { //TODO //mPass->setTransparentSortingEnabled(true); //mPass->setTransparentSortingForced(true); } else { compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, prop.Values[ 0 ].Value + " must be boolean or force" ); } } } break; #endregion ID_TRANSPARENT_SORTING #region ID_ILLUMINATION_STAGE case Keywords.ID_ILLUMINATION_STAGE: if ( prop.Values.Count == 0 ) { compiler.AddError( CompileErrorCode.StringExpected, prop.File, prop.Line ); } else if ( prop.Values.Count > 1 ) { compiler.AddError( CompileErrorCode.FewerParametersExpected, prop.File, prop.Line, "illumination_stage must have at most 1 argument" ); } else { if ( prop.Values[ 0 ] is AtomAbstractNode ) { AtomAbstractNode atom = (AtomAbstractNode)prop.Values[ 0 ]; switch ( (Keywords)atom.Id ) { case Keywords.ID_AMBIENT: //TODO //mPass->setIlluminationStage(IS_AMBIENT); break; case Keywords.ID_PER_LIGHT: //TODO //mPass->setIlluminationStage(IS_PER_LIGHT); break; case Keywords.ID_DECAL: //TODO //mPass->setIlluminationStage(IS_DECAL); break; default: compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, prop.Values[ 0 ].Value + " is not a valid IlluminationStage" ); break; } } else { compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, prop.Values[ 0 ].Value + " is not a valid IlluminationStage" ); } } break; #endregion ID_ILLUMINATION_STAGE #region ID_CULL_HARDWARE case Keywords.ID_CULL_HARDWARE: if ( prop.Values.Count == 0 ) { compiler.AddError( CompileErrorCode.StringExpected, prop.File, prop.Line ); } else if ( prop.Values.Count > 1 ) { compiler.AddError( CompileErrorCode.FewerParametersExpected, prop.File, prop.Line, "cull_hardware must have at most 1 argument" ); } else { if ( prop.Values[ 0 ] is AtomAbstractNode ) { AtomAbstractNode atom = (AtomAbstractNode)prop.Values[ 0 ]; switch ( (Keywords)atom.Id ) { case Keywords.ID_CLOCKWISE: _pass.CullingMode = CullingMode.Clockwise; break; case Keywords.ID_ANTICLOCKWISE: _pass.CullingMode = CullingMode.CounterClockwise; break; case Keywords.ID_NONE: _pass.CullingMode = CullingMode.None; break; default: compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, prop.Values[ 0 ].Value + " is not a valid CullingMode" ); break; } } else { compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, prop.Values[ 0 ].Value + " is not a valid CullingMode" ); } } break; #endregion ID_CULL_HARDWARE #region ID_CULL_SOFTWARE case Keywords.ID_CULL_SOFTWARE: if ( prop.Values.Count == 0 ) { compiler.AddError( CompileErrorCode.StringExpected, prop.File, prop.Line ); } else if ( prop.Values.Count > 1 ) { compiler.AddError( CompileErrorCode.FewerParametersExpected, prop.File, prop.Line, "cull_software must have at most 1 argument" ); } else { if ( prop.Values[ 0 ] is AtomAbstractNode ) { AtomAbstractNode atom = (AtomAbstractNode)prop.Values[ 0 ]; switch ( (Keywords)atom.Id ) { case Keywords.ID_FRONT: _pass.ManualCullingMode = ManualCullingMode.Front; break; case Keywords.ID_BACK: _pass.ManualCullingMode = ManualCullingMode.Back; break; case Keywords.ID_NONE: _pass.ManualCullingMode = ManualCullingMode.None; break; default: compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, prop.Values[ 0 ].Value + " is not a valid ManualCullingMode" ); break; } } else { compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, prop.Values[ 0 ].Value + " is not a valid ManualCullingMode" ); } } break; #endregion ID_CULL_SOFTWARE #region ID_NORMALISE_NORMALS case Keywords.ID_NORMALISE_NORMALS: if ( prop.Values.Count == 0 ) { compiler.AddError( CompileErrorCode.StringExpected, prop.File, prop.Line ); } else if ( prop.Values.Count > 1 ) { compiler.AddError( CompileErrorCode.FewerParametersExpected, prop.File, prop.Line, "normalise_normals must have at most 1 argument" ); } else { bool val = false; if ( getBoolean( prop.Values[ 0 ], out val ) ) { //TODO /*mPass->setNormaliseNormals(val);*/ } else compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, prop.Values[ 0 ].Value + " is not a valid boolean" ); } break; #endregion ID_NORMALISE_NORMALS #region ID_LIGHTING case Keywords.ID_LIGHTING: if ( prop.Values.Count == 0 ) { compiler.AddError( CompileErrorCode.StringExpected, prop.File, prop.Line ); } else if ( prop.Values.Count > 1 ) { compiler.AddError( CompileErrorCode.FewerParametersExpected, prop.File, prop.Line, "lighting must have at most 1 argument" ); } else { bool val = false; if ( getBoolean( prop.Values[ 0 ], out val ) ) _pass.LightingEnabled = val; else compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, prop.Values[ 0 ].Value + " is not a valid boolean" ); } break; #endregion ID_LIGHTING #region ID_SHADING case Keywords.ID_SHADING: if ( prop.Values.Count == 0 ) { compiler.AddError( CompileErrorCode.StringExpected, prop.File, prop.Line ); } else if ( prop.Values.Count > 1 ) { compiler.AddError( CompileErrorCode.FewerParametersExpected, prop.File, prop.Line, "shading must have at most 1 argument" ); } else { if ( prop.Values[ 0 ] is AtomAbstractNode ) { AtomAbstractNode atom = (AtomAbstractNode)prop.Values[ 0 ]; switch ( (Keywords)atom.Id ) { case Keywords.ID_FLAT: _pass.ShadingMode = Shading.Flat; break; case Keywords.ID_GOURAUD: _pass.ShadingMode = Shading.Gouraud; break; case Keywords.ID_PHONG: _pass.ShadingMode = Shading.Phong; break; default: compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, prop.Values[ 0 ].Value + " is not a valid shading mode (flat, gouraud, or phong)" ); break; } } else { compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, prop.Values[ 0 ].Value + " is not a valid shading mode (flat, gouraud, or phong)" ); } } break; #endregion ID_SHADING #region ID_POLYGON_MODE case Keywords.ID_POLYGON_MODE: if ( prop.Values.Count == 0 ) { compiler.AddError( CompileErrorCode.StringExpected, prop.File, prop.Line ); } else if ( prop.Values.Count > 1 ) { compiler.AddError( CompileErrorCode.FewerParametersExpected, prop.File, prop.Line, "polygon_mode must have at most 1 argument" ); } else { if ( prop.Values[ 0 ] is AtomAbstractNode ) { AtomAbstractNode atom = (AtomAbstractNode)prop.Values[ 0 ]; switch ( (Keywords)atom.Id ) { case Keywords.ID_SOLID: _pass.PolygonMode = PolygonMode.Solid; break; case Keywords.ID_POINTS: _pass.PolygonMode = PolygonMode.Points; break; case Keywords.ID_WIREFRAME: _pass.PolygonMode = PolygonMode.Wireframe; break; default: compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, prop.Values[ 0 ].Value + " is not a valid polygon mode (solid, points, or wireframe)" ); break; } } else { compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, prop.Values[ 0 ].Value + " is not a valid polygon mode (solid, points, or wireframe)" ); } } break; #endregion ID_POLYGON_MODE #region ID_POLYGON_MODE_OVERRIDEABLE case Keywords.ID_POLYGON_MODE_OVERRIDEABLE: if ( prop.Values.Count == 0 ) { compiler.AddError( CompileErrorCode.StringExpected, prop.File, prop.Line ); } else if ( prop.Values.Count > 1 ) { compiler.AddError( CompileErrorCode.FewerParametersExpected, prop.File, prop.Line, "polygon_mode_overrideable must have at most 1 argument" ); } else { bool val = false; if ( getBoolean( prop.Values[ 0 ], out val ) ) { //TODO /*mPass->setPolygonModeOverrideable(val);*/ } else compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, prop.Values[ 0 ].Value + " is not a valid boolean" ); } break; #endregion ID_POLYGON_MODE_OVERRIDEABLE #region ID_FOG_OVERRIDE case Keywords.ID_FOG_OVERRIDE: if ( prop.Values.Count == 0 ) { compiler.AddError( CompileErrorCode.StringExpected, prop.File, prop.Line ); } else if ( prop.Values.Count > 8 ) { compiler.AddError( CompileErrorCode.FewerParametersExpected, prop.File, prop.Line, "fog_override must have at most 8 arguments" ); } else { AbstractNode i0 = getNodeAt( prop.Values, 0 ), i1 = getNodeAt( prop.Values, 1 ), i2 = getNodeAt( prop.Values, 2 ); bool val = false; if ( getBoolean( prop.Values[ 0 ], out val ) ) { FogMode mode = FogMode.None; ColorEx clr = ColorEx.White; Real dens = 0.001, start = 0.0f, end = 1.0f; if ( i1 != null ) { if ( i1 is AtomAbstractNode ) { AtomAbstractNode atom = (AtomAbstractNode)i1; switch ( (Keywords)atom.Id ) { case Keywords.ID_NONE: mode = FogMode.None; break; case Keywords.ID_LINEAR: mode = FogMode.Linear; break; case Keywords.ID_EXP: mode = FogMode.Exp; break; case Keywords.ID_EXP2: mode = FogMode.Exp2; break; default: compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, i1.Value + " is not a valid FogMode" ); break; } } else { compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, i1.Value + " is not a valid FogMode" ); break; } } if ( i2 != null ) { // following line code was if(!getColour(i2, prop->values.end(), &clr, 3)) if ( !getColor( prop.Values, 2, out clr, 3 ) ) { compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, i2.Value + " is not a valid colour" ); break; } i2 = getNodeAt( prop.Values, 5 ); } if ( i2 != null ) { if ( !getReal( i2, out dens ) ) { compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, i2.Value + " is not a valid number" ); break; } //++i2; i2 = getNodeAt( prop.Values, 6 ); } if ( i2 != null ) { if ( !getReal( i2, out start ) ) { compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, i2.Value + " is not a valid number" ); return; } //++i2; i2 = getNodeAt( prop.Values, 7 ); } if ( i2 != null ) { if ( !getReal( i2, out end ) ) { compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, i2.Value + " is not a valid number" ); return; } //++i2; i2 = getNodeAt( prop.Values, 8 ); } _pass.SetFog( val, mode, clr, dens, start, end ); } else compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, prop.Values[ 0 ].Value + " is not a valid boolean" ); } break; #endregion ID_FOG_OVERRIDE #region ID_COLOUR_WRITE case Keywords.ID_COLOUR_WRITE: if ( prop.Values.Count == 0 ) { compiler.AddError( CompileErrorCode.StringExpected, prop.File, prop.Line ); } else if ( prop.Values.Count > 1 ) { compiler.AddError( CompileErrorCode.FewerParametersExpected, prop.File, prop.Line, "colour_write must have at most 1 argument" ); } else { bool val = false; if ( getBoolean( prop.Values[ 0 ], out val ) ) _pass.ColorWriteEnabled = val; else compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, prop.Values[ 0 ].Value + " is not a valid boolean" ); } break; #endregion ID_COLOUR_WRITE #region ID_MAX_LIGHTS case Keywords.ID_MAX_LIGHTS: if ( prop.Values.Count == 0 ) { compiler.AddError( CompileErrorCode.StringExpected, prop.File, prop.Line ); } else if ( prop.Values.Count > 1 ) { compiler.AddError( CompileErrorCode.FewerParametersExpected, prop.File, prop.Line, "max_lights must have at most 1 argument" ); } else { int val = 0; if ( getInt( prop.Values[ 0 ], out val ) ) _pass.MaxSimultaneousLights = val; else compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, prop.Values[ 0 ].Value + " is not a valid integer" ); } break; #endregion ID_MAX_LIGHTS #region ID_START_LIGHT case Keywords.ID_START_LIGHT: if ( prop.Values.Count == 0 ) { compiler.AddError( CompileErrorCode.StringExpected, prop.File, prop.Line ); } else if ( prop.Values.Count > 1 ) { compiler.AddError( CompileErrorCode.FewerParametersExpected, prop.File, prop.Line, "start_light must have at most 1 argument" ); } else { uint val = 0; if ( getUInt( prop.Values[ 0 ], out val ) ) { //TODO /*mPass->setStartLight(static_cast<unsigned short>(val));*/ } else compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, prop.Values[ 0 ].Value + " is not a valid integer" ); } break; #endregion ID_START_LIGHT #region ID_ITERATION case Keywords.ID_ITERATION: if ( prop.Values.Count == 0 ) { compiler.AddError( CompileErrorCode.StringExpected, prop.File, prop.Line ); } else { AbstractNode i0 = getNodeAt( prop.Values, 0 ); if ( i0 is AtomAbstractNode ) { AtomAbstractNode atom = (AtomAbstractNode)i0; if ( atom.Id == (uint)Keywords.ID_ONCE ) { _pass.IteratePerLight = false; } else if ( atom.Id == (uint)Keywords.ID_ONCE_PER_LIGHT ) { AbstractNode i1 = getNodeAt( prop.Values, 1 ); if ( i1 != null && i1 is AtomAbstractNode ) { atom = (AtomAbstractNode)i1; switch ( (Keywords)atom.Id ) { case Keywords.ID_POINT: _pass.IteratePerLight = true; break; case Keywords.ID_DIRECTIONAL: //TODO //_pass.SetIteratePerLight(true, true, LightType.Directional ); break; case Keywords.ID_SPOT: //TODO //_pass.SetIteratePerLight(true, true, LightType.Spotlight ); break; default: compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, prop.Values[ 0 ].Value + " is not a valid light type (point, directional, or spot)" ); break; } } else { //TODO //_pass.SetIteratePerLight(true, false); } } else if ( atom.IsNumber ) { //TODO _pass.IterationCount = Int32.Parse( atom.Value ); AbstractNode i1 = getNodeAt( prop.Values, 1 ); if ( i1 != null && i1 is AtomAbstractNode ) { atom = (AtomAbstractNode)i1; if ( atom.Id == (uint)Keywords.ID_PER_LIGHT ) { AbstractNode i2 = getNodeAt( prop.Values, 2 ); if ( i2 != null && i2 is AtomAbstractNode ) { atom = (AtomAbstractNode)i2; switch ( (Keywords)atom.Id ) { case Keywords.ID_POINT: _pass.IteratePerLight = true; break; case Keywords.ID_DIRECTIONAL: //TODO //mPass->setIteratePerLight(true, true, Light::LT_DIRECTIONAL); break; case Keywords.ID_SPOT: //TODO //mPass->setIteratePerLight(true, true, Light::LT_SPOTLIGHT); break; default: compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, i2.Value + " is not a valid light type (point, directional, or spot)" ); break; } } else { //TODO //mPass->setIteratePerLight(true, false); } } else if ( atom.Id == (uint)Keywords.ID_PER_N_LIGHTS ) { AbstractNode i2 = getNodeAt( prop.Values, 2 ); if ( i2 != null && i2 is AtomAbstractNode ) { atom = (AtomAbstractNode)i2; if ( atom.IsNumber ) { //TODO //mPass->setLightCountPerIteration( // static_cast<unsigned short>(StringConverter::parseInt(atom->value))); AbstractNode i3 = getNodeAt( prop.Values, 3 ); if ( i3 != null && i3 is AtomAbstractNode ) { atom = (AtomAbstractNode)i3; switch ( (Keywords)atom.Id ) { case Keywords.ID_POINT: _pass.IteratePerLight = true; break; case Keywords.ID_DIRECTIONAL: //TODO //mPass->setIteratePerLight(true, true, Light::LT_DIRECTIONAL); break; case Keywords.ID_SPOT: //TODO //mPass->setIteratePerLight(true, true, Light::LT_SPOTLIGHT); break; default: compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, i3.Value + " is not a valid light type (point, directional, or spot)" ); break; } } else { //TODO //mPass->setIteratePerLight(true, false); } } else { compiler.AddError( CompileErrorCode.NumberExpected, prop.File, prop.Line, i2.Value + " is not a valid number" ); } } else { compiler.AddError( CompileErrorCode.NumberExpected, prop.File, prop.Line, prop.Values[ 0 ].Value + " is not a valid number" ); } } } } else { compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line ); } } else { compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line ); } } break; #endregion ID_ITERATION #region ID_POINT_SIZE case Keywords.ID_POINT_SIZE: if ( prop.Values.Count == 0 ) { compiler.AddError( CompileErrorCode.StringExpected, prop.File, prop.Line ); } else if ( prop.Values.Count > 1 ) { compiler.AddError( CompileErrorCode.FewerParametersExpected, prop.File, prop.Line, "point_size must have at most 1 argument" ); } else { Real val = 0.0f; if ( getReal( prop.Values[ 0 ], out val ) ) _pass.PointSize = val; else compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, prop.Values[ 0 ].Value + " is not a valid number" ); } break; #endregion ID_POINT_SIZE #region ID_POINT_SPRITES case Keywords.ID_POINT_SPRITES: if ( prop.Values.Count == 0 ) { compiler.AddError( CompileErrorCode.StringExpected, prop.File, prop.Line ); } else if ( prop.Values.Count > 1 ) { compiler.AddError( CompileErrorCode.FewerParametersExpected, prop.File, prop.Line, "point_sprites must have at most 1 argument" ); } else { bool val = false; if ( getBoolean( prop.Values[ 0 ], out val ) ) _pass.PointSpritesEnabled = val; else compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, prop.Values[ 0 ].Value + " is not a valid boolean" ); } break; #endregion ID_POINT_SPRITES #region ID_POINT_SIZE_ATTENUATION case Keywords.ID_POINT_SIZE_ATTENUATION: if ( prop.Values.Count == 0 ) { compiler.AddError( CompileErrorCode.StringExpected, prop.File, prop.Line ); } else if ( prop.Values.Count > 4 ) { compiler.AddError( CompileErrorCode.FewerParametersExpected, prop.File, prop.Line, "point_size_attenuation must have at most 4 arguments" ); } else { bool val = false; if ( getBoolean( prop.Values[ 0 ], out val ) ) { if ( val ) { AbstractNode i1 = getNodeAt( prop.Values, 1 ), i2 = getNodeAt( prop.Values, 2 ), i3 = getNodeAt( prop.Values, 3 ); if ( prop.Values.Count > 1 ) { Real constant = 0.0f, linear = 1.0f, quadratic = 0.0f; if ( i1 != null && i1 is AtomAbstractNode ) { AtomAbstractNode atom = (AtomAbstractNode)i1; if ( atom.IsNumber ) constant = atom.Number; else compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line ); } else { compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, i1.Value + " is not a valid number" ); } if ( i2 != null && i2 is AtomAbstractNode ) { AtomAbstractNode atom = (AtomAbstractNode)i2; if ( atom.IsNumber ) linear = atom.Number; else compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line ); } else { compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, i2.Value + " is not a valid number" ); } if ( i3 != null && i3 is AtomAbstractNode ) { AtomAbstractNode atom = (AtomAbstractNode)i3; if ( atom.IsNumber ) quadratic = atom.Number; else compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line ); } else { compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, i3.Value + " is not a valid number" ); } //TODO //mPass->setPointAttenuation(true, constant, linear, quadratic); } else { //TODO //mPass->setPointAttenuation(true); } } else { //TODO //mPass->setPointAttenuation(false); } } else compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, prop.Values[ 0 ].Value + " is not a valid boolean" ); } break; #endregion ID_POINT_SIZE_ATTENUATION #region ID_POINT_SIZE_MIN case Keywords.ID_POINT_SIZE_MIN: if ( prop.Values.Count == 0 ) { compiler.AddError( CompileErrorCode.StringExpected, prop.File, prop.Line ); } else if ( prop.Values.Count > 1 ) { compiler.AddError( CompileErrorCode.FewerParametersExpected, prop.File, prop.Line, "point_size_min must have at most 1 argument" ); } else { Real val = 0.0f; if ( getReal( prop.Values[ 0 ], out val ) ) _pass.PointMinSize = val; else compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, prop.Values[ 0 ].Value + " is not a valid number" ); } break; #endregion ID_POINT_SIZE_MIN #region ID_POINT_SIZE_MAX case Keywords.ID_POINT_SIZE_MAX: if ( prop.Values.Count == 0 ) { compiler.AddError( CompileErrorCode.StringExpected, prop.File, prop.Line ); } else if ( prop.Values.Count > 1 ) { compiler.AddError( CompileErrorCode.FewerParametersExpected, prop.File, prop.Line, "point_size_max must have at most 1 argument" ); } else { Real val = 0.0f; if ( getReal( prop.Values[ 0 ], out val ) ) _pass.PointMaxSize = val; else compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, prop.Values[ 0 ].Value + " is not a valid number" ); } break; #endregion ID_POINT_SIZE_MAX default: compiler.AddError( CompileErrorCode.UnexpectedToken, prop.File, prop.Line, "token \"" + prop.Name + "\" is not recognized" ); break; } // end of switch statement } // end of if ( i is PropertyAbstractNode ) else if ( i is ObjectAbstractNode ) { ObjectAbstractNode child = (ObjectAbstractNode)i; switch ( (Keywords)child.Id ) { case Keywords.ID_FRAGMENT_PROGRAM_REF: _translateFragmentProgramRef( compiler, child ); break; case Keywords.ID_VERTEX_PROGRAM_REF: _translateVertexProgramRef( compiler, child ); break; case Keywords.ID_GEOMETRY_PROGRAM_REF: _translateGeometryProgramRef( compiler, child ); break; case Keywords.ID_SHADOW_CASTER_VERTEX_PROGRAM_REF: _translateShadowCasterVertexProgramRef( compiler, child ); break; case Keywords.ID_SHADOW_RECEIVER_VERTEX_PROGRAM_REF: _translateShadowReceiverVertexProgramRef( compiler, child ); break; case Keywords.ID_SHADOW_RECEIVER_FRAGMENT_PROGRAM_REF: _translateShadowReceiverFragmentProgramRef( compiler, child ); break; default: _processNode( compiler, i ); break; } } } }
protected void InitTextureLighting() { if ( targetRenderSystem.Capabilities.TextureUnitCount < 2 ) LogManager.Instance.Write( "--WARNING--At least 2 available texture units are required for BSP dynamic lighting!" ); Texture texLight = TextureLight.CreateTexture(); textureLightMaterial = (Material)MaterialManager.Instance.GetByName( "Axiom/BspTextureLightMaterial" ); if ( textureLightMaterial == null ) { textureLightMaterial = (Material)MaterialManager.Instance.Create( "Axiom/BspTextureLightMaterial", ResourceGroupManager.DefaultResourceGroupName ); textureLightPass = textureLightMaterial.GetTechnique( 0 ).GetPass( 0 ); // the texture light TextureUnitState tex = textureLightPass.CreateTextureUnitState( texLight.Name ); tex.SetColorOperation( LayerBlendOperation.Modulate ); tex.ColorBlendMode.source2 = LayerBlendSource.Diffuse; tex.SetAlphaOperation( LayerBlendOperationEx.Modulate ); tex.AlphaBlendMode.source2 = LayerBlendSource.Diffuse; tex.TextureCoordSet = 2; tex.SetTextureAddressingMode( TextureAddressing.Clamp ); // The geometry texture without lightmap. Use the light texture on this // pass, the appropriate texture will be rendered at RenderTextureLighting tex = textureLightPass.CreateTextureUnitState( texLight.Name ); tex.SetColorOperation( LayerBlendOperation.Modulate ); tex.SetAlphaOperation( LayerBlendOperationEx.Modulate ); tex.SetTextureAddressingMode( TextureAddressing.Wrap ); textureLightPass.SetSceneBlending( SceneBlendType.TransparentAlpha ); textureLightMaterial.CullingMode = CullingMode.None; textureLightMaterial.Lighting = false; } else { textureLightPass = textureLightMaterial.GetTechnique( 0 ).GetPass( 0 ); } }
private void InitShadowReceiverPass() { Material matShadRec = MaterialManager.Instance.GetByName(TEXTURE_SHADOW_RECEIVER_MATERIAL); if (matShadRec == null) { matShadRec = (Material) MaterialManager.Instance.Create(TEXTURE_SHADOW_RECEIVER_MATERIAL); shadowReceiverPass = matShadRec.GetTechnique(0).GetPass(0); shadowReceiverPass.SetSceneBlending(SceneBlendFactor.DestColor, SceneBlendFactor.Zero); // No lighting, one texture unit // everything else will be bound as needed during the receiver pass shadowReceiverPass.LightingEnabled = false; TextureUnitState t = shadowReceiverPass.CreateTextureUnitState(); t.TextureAddressing = TextureAddressing.Clamp; shadowReceiverPass.DepthBias = 1; } else { shadowReceiverPass = matShadRec.GetTechnique(0).GetPass(0); } }
private void InitShadowModulativePass() { Material matModStencil = MaterialManager.Instance.GetByName(STENCIL_SHADOW_MODULATIVE_MATERIAL); if(matModStencil == null) { // Create matModStencil = (Material)MaterialManager.Instance.Create(STENCIL_SHADOW_MODULATIVE_MATERIAL); shadowModulativePass = matModStencil.GetTechnique(0).GetPass(0); shadowModulativePass.SetSceneBlending(SceneBlendFactor.DestColor, SceneBlendFactor.Zero); shadowModulativePass.LightingEnabled = false; shadowModulativePass.DepthWrite = false; shadowModulativePass.DepthCheck = false; TextureUnitState t = shadowModulativePass.CreateTextureUnitState(); t.SetColorOperationEx( LayerBlendOperationEx.Modulate, LayerBlendSource.Manual, LayerBlendSource.Current, shadowColor); } else { shadowModulativePass = matModStencil.GetTechnique(0).GetPass(0); } }
private void InitShadowDebugPass() { Material matDebug = MaterialManager.Instance.GetByName(SHADOW_VOLUMES_MATERIAL); if(matDebug == null) { // Create matDebug = (Material)MaterialManager.Instance.Create(SHADOW_VOLUMES_MATERIAL); shadowDebugPass = matDebug.GetTechnique(0).GetPass(0); shadowDebugPass.SetSceneBlending(SceneBlendType.Add); shadowDebugPass.LightingEnabled = false; shadowDebugPass.DepthWrite = false; TextureUnitState t = shadowDebugPass.CreateTextureUnitState(); t.SetColorOperationEx( LayerBlendOperationEx.Modulate, LayerBlendSource.Manual, LayerBlendSource.Current, new ColorEx(0.7f, 0.0f, 0.2f)); shadowDebugPass.CullMode = CullingMode.None; if(targetRenderSystem.Caps.CheckCap(Capabilities.VertexPrograms)) { ShadowVolumeExtrudeProgram.Initialize(); // Enable the (infinite) point light extruder for now, just to get some params shadowDebugPass.SetVertexProgram( ShadowVolumeExtrudeProgram.GetProgramName(ShadowVolumeExtrudeProgram.Programs.PointLight)); infiniteExtrusionParams = shadowDebugPass.VertexProgramParameters; infiniteExtrusionParams.SetAutoConstant(0, AutoConstants.WorldViewProjMatrix); infiniteExtrusionParams.SetAutoConstant(4, AutoConstants.LightPositionObjectSpace); } matDebug.Compile(); } else { shadowDebugPass = matDebug.GetTechnique(0).GetPass(0); } }
/// <summary> /// Internal method for splitting the passes into illumination passes. /// </summary> public void CompileIlluminationPasses() { ClearIlluminationPasses(); // don't need to split transparent passes since they are rendered seperately if(this.IsTransparent) { return; } // start off with ambient passes IlluminationStage stage = IlluminationStage.Ambient; bool hasAmbient = false; for(int i = 0; i < passes.Count; /* increment in logic */) { Pass pass = (Pass)passes[i]; IlluminationPass iPass; switch(stage) { case IlluminationStage.Ambient: // keep looking for ambient only if(pass.IsAmbientOnly) { iPass = new IlluminationPass(); iPass.OriginalPass = pass; iPass.Pass = pass; iPass.Stage = stage; illuminationPasses.Add(iPass); hasAmbient = true; // progress to the next pass i++; } else { // split off any ambient part if(pass.Ambient.CompareTo(ColorEx.Black) != 0 || pass.Emissive.CompareTo(ColorEx.Black) != 0 || pass.AlphaRejectFunction != CompareFunction.AlwaysPass) { Pass newPass = new Pass(this, pass.Index); pass.CopyTo(newPass); if (newPass.AlphaRejectFunction != CompareFunction.AlwaysPass) { // Alpha rejection passes must retain their transparency, so // we allow the texture units, but override the colour functions for (int tindex = 0; tindex < newPass.NumTextureUnitStages; tindex++) { TextureUnitState tus = newPass.GetTextureUnitState(tindex); tus.SetColorOperationEx(LayerBlendOperationEx.Source1, LayerBlendSource.Current, LayerBlendSource.Current); } } else // remove any texture units newPass.RemoveAllTextureUnitStates(); // also remove any fragment program if(newPass.HasFragmentProgram) { newPass.SetFragmentProgram(""); } // We have to leave vertex program alone (if any) and // just trust that the author is using light bindings, which // we will ensure there are none in the ambient pass newPass.Diffuse = new ColorEx(newPass.Diffuse.a, 0f, 0f, 0f); // Preserving alpha newPass.Specular = ColorEx.Black; // Calculate hash value for new pass, because we are compiling // illumination passes on demand, which will loss hash calculate // before it add to render queue first time. newPass.RecalculateHash(); iPass = new IlluminationPass(); iPass.DestroyOnShutdown = true; iPass.OriginalPass = pass; iPass.Pass = newPass; iPass.Stage = stage; illuminationPasses.Add(iPass); hasAmbient = true; } if(!hasAmbient) { // make up a new basic pass Pass newPass = new Pass(this, pass.Index); pass.CopyTo(newPass); newPass.Ambient = ColorEx.Black; newPass.Diffuse = ColorEx.Black; // Calculate hash value for new pass, because we are compiling // illumination passes on demand, which will loss hash calculate // before it add to render queue first time. newPass.RecalculateHash(); iPass = new IlluminationPass(); iPass.DestroyOnShutdown = true; iPass.OriginalPass = pass; iPass.Pass = newPass; iPass.Stage = stage; illuminationPasses.Add(iPass); hasAmbient = true; } // this means we are done with ambients, progress to per-light stage = IlluminationStage.PerLight; } break; case IlluminationStage.PerLight: if(pass.RunOncePerLight) { // if this is per-light already, use it directly iPass = new IlluminationPass(); iPass.DestroyOnShutdown = false; iPass.OriginalPass = pass; iPass.Pass = pass; iPass.Stage = stage; illuminationPasses.Add(iPass); // progress to the next pass i++; } else { // split off per-light details (can only be done for one) if(pass.LightingEnabled && (pass.Diffuse.CompareTo(ColorEx.Black) != 0 || pass.Specular.CompareTo(ColorEx.Black) != 0)) { // copy existing pass Pass newPass = new Pass(this, pass.Index); pass.CopyTo(newPass); if (newPass.AlphaRejectFunction != CompareFunction.AlwaysPass) { // Alpha rejection passes must retain their transparency, so // we allow the texture units, but override the colour functions for (int tindex = 0; tindex < newPass.NumTextureUnitStages; tindex++) { TextureUnitState tus = newPass.GetTextureUnitState(tindex); tus.SetColorOperationEx(LayerBlendOperationEx.Source1, LayerBlendSource.Current, LayerBlendSource.Current); } } else // remove any texture units newPass.RemoveAllTextureUnitStates(); // also remove any fragment program if(newPass.HasFragmentProgram) { newPass.SetFragmentProgram(""); } // Cannot remove vertex program, have to assume that // it will process diffuse lights, ambient will be turned off newPass.Ambient = ColorEx.Black; newPass.Emissive = ColorEx.Black; // must be additive newPass.SetSceneBlending(SceneBlendFactor.One, SceneBlendFactor.One); iPass = new IlluminationPass(); iPass.DestroyOnShutdown = true; iPass.OriginalPass = pass; iPass.Pass = newPass; iPass.Stage = stage; illuminationPasses.Add(iPass); } // This means the end of per-light passes stage = IlluminationStage.Decal; } break; case IlluminationStage.Decal: // We just want a 'lighting off' pass to finish off // and only if there are texture units if(pass.NumTextureUnitStages > 0) { if(!pass.LightingEnabled) { // we assume this pass already combines as required with the scene iPass = new IlluminationPass(); iPass.DestroyOnShutdown = false; iPass.OriginalPass = pass; iPass.Pass = pass; iPass.Stage = stage; illuminationPasses.Add(iPass); } else { // Copy the pass and tweak away the lighting parts Pass newPass = new Pass(this, pass.Index); pass.CopyTo(newPass); newPass.Ambient = ColorEx.Black; newPass.Diffuse = new ColorEx(newPass.Diffuse.a, 0f, 0f, 0f); // Preserving alpha newPass.Specular = ColorEx.Black; newPass.Emissive = ColorEx.Black; newPass.LightingEnabled = false; // modulate newPass.SetSceneBlending(SceneBlendFactor.DestColor, SceneBlendFactor.Zero); // Calculate hash value for new pass, because we are compiling // illumination passes on demand, which will loss hash calculate // before it add to render queue first time. newPass.RecalculateHash(); // there is nothing we can do about vertex & fragment // programs here, so people will just have to make their // programs friendly-like if they want to use this technique iPass = new IlluminationPass(); iPass.DestroyOnShutdown = true; iPass.OriginalPass = pass; iPass.Pass = newPass; iPass.Stage = stage; illuminationPasses.Add(iPass); } } // always increment on decal, since nothing more to do with this pass i++; break; } } }