public virtual SubRenderState CreateInstance( ScriptCompiler compiler, PropertyAbstractNode prop, TextureUnitState texState, SGScriptTranslator translator ) { return null; }
/// <summary> /// Inserts a new TextureUnitState object into the Pass. /// </summary> /// <remarks> /// This unit is is added on top of all previous texture units. /// <p/> /// Applies to both fixed-function and programmable passes. /// </remarks> /// <param name="textureName">The basic name of the texture (i.e. brickwall.jpg)</param> /// <param name="texCoordSet">The index of the texture coordinate set to use.</param> /// <returns></returns> public TextureUnitState CreateTextureUnitState( string textureName, int texCoordSet ) { TextureUnitState state = new TextureUnitState( this ); state.SetTextureName( textureName ); state.TextureCoordSet = texCoordSet; textureUnitStates.Add( state ); // needs recompilation _parent.NotifyNeedsRecompile(); DirtyHash(); return state; }
public TextureUnitTranslator() : base() { _textureunit = null; }
/// <summary> /// /// </summary> protected void Initialize() { // Create geometry int nvertices = this.slices*4; // n+1 planes int elemsize = 3*3; int dsize = elemsize*nvertices; int x; var indexData = new IndexData(); var vertexData = new VertexData(); var vertices = new float[dsize]; var coords = new float[4,2] { { 0.0f, 0.0f }, { 0.0f, 1.0f }, { 1.0f, 0.0f }, { 1.0f, 1.0f } }; for ( x = 0; x < this.slices; x++ ) { for ( int y = 0; y < 4; y++ ) { float xcoord = coords[ y, 0 ] - 0.5f; float ycoord = coords[ y, 1 ] - 0.5f; float zcoord = -( (float)x/(float)( this.slices - 1 ) - 0.5f ); // 1.0f .. a/(a+1) // coordinate vertices[ x*4*elemsize + y*elemsize + 0 ] = xcoord*( this.size/2.0f ); vertices[ x*4*elemsize + y*elemsize + 1 ] = ycoord*( this.size/2.0f ); vertices[ x*4*elemsize + y*elemsize + 2 ] = zcoord*( this.size/2.0f ); // normal vertices[ x*4*elemsize + y*elemsize + 3 ] = 0.0f; vertices[ x*4*elemsize + y*elemsize + 4 ] = 0.0f; vertices[ x*4*elemsize + y*elemsize + 5 ] = 1.0f; // tex vertices[ x*4*elemsize + y*elemsize + 6 ] = xcoord*Utility.Sqrt( 3.0f ); vertices[ x*4*elemsize + y*elemsize + 7 ] = ycoord*Utility.Sqrt( 3.0f ); vertices[ x*4*elemsize + y*elemsize + 8 ] = zcoord*Utility.Sqrt( 3.0f ); } } var faces = new short[this.slices*6]; for ( x = 0; x < this.slices; x++ ) { faces[ x*6 + 0 ] = (short)( x*4 + 0 ); faces[ x*6 + 1 ] = (short)( x*4 + 1 ); faces[ x*6 + 2 ] = (short)( x*4 + 2 ); faces[ x*6 + 3 ] = (short)( x*4 + 1 ); faces[ x*6 + 4 ] = (short)( x*4 + 2 ); faces[ x*6 + 5 ] = (short)( x*4 + 3 ); } //setup buffers vertexData.vertexStart = 0; vertexData.vertexCount = nvertices; VertexDeclaration decl = vertexData.vertexDeclaration; VertexBufferBinding bind = vertexData.vertexBufferBinding; int offset = 0; offset += decl.AddElement( 0, 0, VertexElementType.Float3, VertexElementSemantic.Position ).Size; offset += decl.AddElement( 0, offset, VertexElementType.Float3, VertexElementSemantic.Normal ).Size; offset += decl.AddElement( 0, offset, VertexElementType.Float3, VertexElementSemantic.TexCoords ).Size; HardwareVertexBuffer vertexBuffer = HardwareBufferManager.Instance.CreateVertexBuffer( decl, nvertices, BufferUsage.StaticWriteOnly ); bind.SetBinding( 0, vertexBuffer ); HardwareIndexBuffer indexBuffer = HardwareBufferManager.Instance.CreateIndexBuffer( IndexType.Size16, this.slices*6, BufferUsage.StaticWriteOnly ); indexData.indexBuffer = indexBuffer; indexData.indexCount = this.slices*6; indexData.indexStart = 0; indexBuffer.WriteData( 0, indexBuffer.Size, faces, true ); vertexBuffer.WriteData( 0, vertexBuffer.Size, vertices ); vertices = null; faces = null; // Now make the render operation renderOperation.operationType = OperationType.TriangleList; renderOperation.indexData = indexData; renderOperation.vertexData = vertexData; renderOperation.useIndices = true; // Create a brand new private material if ( !ResourceGroupManager.Instance.GetResourceGroups().Contains( "VolumeRendable" ) ) { ResourceGroupManager.Instance.CreateResourceGroup( "VolumeRendable" ); } var material = (Material)MaterialManager.Instance.Create( this.texture, "VolumeRendable" ); // Remove pre-created technique from defaults material.RemoveAllTechniques(); // Create a techinique and a pass and a texture unit Technique technique = material.CreateTechnique(); Pass pass = technique.CreatePass(); TextureUnitState textureUnit = pass.CreateTextureUnitState(); // Set pass parameters pass.SetSceneBlending( SceneBlendType.TransparentAlpha ); pass.DepthWrite = false; pass.CullingMode = CullingMode.None; pass.LightingEnabled = false; textureUnit.SetTextureAddressingMode( TextureAddressing.Clamp ); textureUnit.SetTextureName( this.texture, TextureType.ThreeD ); textureUnit.SetTextureFiltering( TextureFiltering.Trilinear ); this.unit = textureUnit; base.material = material; }
/// <summary> /// Copy the details of this pass to the target pass. /// </summary> /// <param name="target">Destination pass to copy this pass's attributes to.</param> public void CopyTo( Pass target ) { target._name = _name; target._hashCode = _hashCode; // surface target._ambient = _ambient.Clone(); target._diffuse = _diffuse.Clone(); target._specular = _specular.Clone(); target._emissive = _emissive.Clone(); target._shininess = _shininess; target._tracking = _tracking; // fog target._fogOverride = _fogOverride; target._fogMode = _fogMode; target._fogColor = _fogColor.Clone(); target._fogStart = _fogStart; target._fogEnd = _fogEnd; target._fogDensity = _fogDensity; // default blending target._sourceBlendFactor = _sourceBlendFactor; target._destinationBlendFactor = _destinationBlendFactor; target._depthCheck = _depthCheck; target._depthWrite = _depthWrite; target._alphaRejectFunction = _alphaRejectFunction; target._alphaRejectValue = _alphaRejectValue; target._colorWriteEnabled = _colorWriteEnabled; target._depthFunction = _depthFunction; target._depthBiasConstant = _depthBiasConstant; target._depthBiasSlopeScale = _depthBiasSlopeScale; target._cullingMode = _cullingMode; target._manualCullingMode = _manualCullingMode; target._lightingEnabled = _lightingEnabled; target._maxSimultaneousLights = _maxSimultaneousLights; target._iteratePerLight = _iteratePerLight; target._runOnlyForOneLightType = _runOnlyForOneLightType; target._onlyLightType = _onlyLightType; target._shadingMode = _shadingMode; target._polygonMode = _polygonMode; target.IterationCount = IterationCount; // vertex program if ( _vertexProgramUsage != null ) { target._vertexProgramUsage = _vertexProgramUsage.Clone(); } else { target._vertexProgramUsage = null; } // shadow caster vertex program if ( shadowCasterVertexProgramUsage != null ) { target.shadowCasterVertexProgramUsage = shadowCasterVertexProgramUsage.Clone(); } else { target.shadowCasterVertexProgramUsage = null; } // shadow receiver vertex program if ( _shadowReceiverVertexProgramUsage != null ) { target._shadowReceiverVertexProgramUsage = _shadowReceiverVertexProgramUsage.Clone(); } else { target._shadowReceiverVertexProgramUsage = null; } // fragment program if ( _fragmentProgramUsage != null ) { target._fragmentProgramUsage = _fragmentProgramUsage.Clone(); } else { target._fragmentProgramUsage = null; } // shadow caster fragment program if ( _shadowCasterFragmentProgramUsage != null ) { target._shadowCasterFragmentProgramUsage = _shadowCasterFragmentProgramUsage.Clone(); } else { target._shadowCasterFragmentProgramUsage = null; } // shadow receiver fragment program if ( _shadowReceiverFragmentProgramUsage != null ) { target._shadowReceiverFragmentProgramUsage = _shadowReceiverFragmentProgramUsage.Clone(); } else { target._shadowReceiverFragmentProgramUsage = null; } // Clear texture units but doesn't notify need recompilation in the case // we are cloning, The parent material will take care of this. target.textureUnitStates.Clear(); // Copy texture units for ( int i = 0; i < textureUnitStates.Count; i++ ) { TextureUnitState newState = new TextureUnitState( target ); TextureUnitState src = (TextureUnitState)textureUnitStates[ i ]; src.CopyTo( newState ); target.textureUnitStates.Add( newState ); } target.DirtyHash(); }
/// <summary> /// Creates a basic time-based texture coordinate modifier designed for creating rotating textures. /// </summary> /// <remarks> /// This simple method allows you to easily create constant-speed rotating textures. If you want more /// control, look up the ControllerManager.CreateTextureWaveTransformer for more complex wave-based /// scrollers / stretchers / rotaters. /// </remarks> /// <param name="layer">The texture unit to animate.</param> /// <param name="speed">Speed of the rotation, in counter-clockwise revolutions per second.</param> /// <returns>A newly created controller object that will be updated during the main render loop.</returns> public Controller<Real> CreateTextureRotator( TextureUnitState layer, Real speed ) { IControllerValue<Real> val = new TexCoordModifierControllerValue( layer, false, false, false, false, true ); IControllerFunction<Real> func = new MultipyControllerFunction( -speed, true ); return CreateController( val, func ); }
/// <summary> /// Creates a basic time-based texture v coordinate modifier designed for creating scrolling textures. /// </summary> /// <remarks> /// This simple method allows you to easily create constant-speed scrolling textures. If you want more /// control, look up the <see cref="CreateTextureWaveTransformer"/> for more complex wave-based /// scrollers / stretchers / rotaters. /// </remarks> /// <param name="layer">The texture unit to animate.</param> /// <param name="speed">speed, in wraps per second.</param> /// <returns>A newly created controller object that will be updated during the main render loop.</returns> public Controller<Real> CreateTextureVScroller( TextureUnitState layer, Real speed ) { IControllerValue<Real> val = null; IControllerFunction<Real> func = null; Controller<Real> controller = null; // if both u and v speeds are the same, we can use a single controller for it if ( speed != 0 ) { // create the value and function val = new TexCoordModifierControllerValue( layer, false, true ); func = new MultipyControllerFunction( -speed, true ); // create the controller (uses FrameTime for source by default) controller = CreateController( val, func ); } return controller; }
/// <summary> /// Used to clone a texture layer. Mainly used during a call to Clone on a Material or Pass. /// </summary> /// <returns></returns> public TextureUnitState Clone( Pass parent ) { var newState = new TextureUnitState( parent ); CopyTo( newState ); newState.parent.DirtyHash(); return newState; }
/// <summary> /// Adds the passed in TextureUnitState, to the existing Pass. /// </summary> /// <param name="state">TextureUnitState to add to this pass.</param> public void AddTextureUnitState(TextureUnitState state) { Debug.Assert(state != null, "state is null in Pass.AddTextureUnitState()"); if (state != null) { // only attach TUS to pass if TUS does not belong to another pass if ((state.Parent == null) || (state.Parent == this)) { textureUnitStates.Add(state); // Notify state state.Parent = this; // if texture unit state name is empty then give it a default name based on its index if (state.Name == null || state.Name == "") { // its the last entry in the container so its index is size - 1 int idx = textureUnitStates.Count - 1; state.Name = idx.ToString(); // since the name was never set and a default one has been made, clear the alias name // so that when the texture unit name is set by the user, the alias name will be set to // that name state.TextureNameAlias = null; } // needs recompilation parent.NotifyNeedsRecompile(); DirtyHash(); } else throw new AxiomException("TextureUnitState already attached to another pass" + " In Pass.AddTextureUnitState"); contentTypeLookupBuilt = false; } }
private bool NeedsTextureMatrix( TextureUnitState textureUnitState ) { for ( int i = 0; i < textureUnitState.NumEffects; i++ ) { TextureEffect effi = textureUnitState.GetEffect( i ); switch ( effi.type ) { case TextureEffectType.EnvironmentMap: case TextureEffectType.ProjectiveTexture: case TextureEffectType.Rotate: case TextureEffectType.Transform: case TextureEffectType.UScroll: case TextureEffectType.UVScroll: case TextureEffectType.VScroll: return true; } } //TODO var matTexture = new Matrix4(); //textureUnitState.getTextureTransform(); //Resolve texture matrix parameter if ( matTexture != Matrix4.Identity ) { return true; } return false; }
/// <summary> /// Used to clone a texture layer. Mainly used during a call to Clone on a Material. /// </summary> /// <returns></returns> public void CopyTo( TextureUnitState target ) { var props = target.GetType().GetFields( BindingFlags.NonPublic | BindingFlags.Instance ); // save parent from target, since it will be overwritten by the following loop var tmpParent = target.parent; for ( var i = 0; i < props.Length; i++ ) { var prop = props[ i ]; var srcVal = prop.GetValue( this ); prop.SetValue( target, srcVal ); } // restore correct parent target.parent = tmpParent; target.frames = new string[MaxAnimationFrames]; // copy over animation frame texture names for ( var i = 0; i < MaxAnimationFrames; i++ ) { target.frames[ i ] = this.frames[ i ]; } // must clone these references target.colorBlendMode = this.colorBlendMode.Clone(); target.alphaBlendMode = this.alphaBlendMode.Clone(); target.effectList = new TextureEffectList(); // copy effects foreach ( var effect in this.effectList ) { target.effectList.Add( effect.Clone() ); } // dirty the hash of the parent pass target.parent.DirtyHash(); }
private TexCoordCalcMethod GetCalcMethod( TextureUnitState textureUnitState ) { TexCoordCalcMethod texCoordCalcMethod = TexCoordCalcMethod.None; var effectMap = new List<TextureEffect>(); for ( int i = 0; i < textureUnitState.NumEffects; i++ ) { effectMap.Add( textureUnitState.GetEffect( i ) ); } foreach ( var effi in effectMap ) { switch ( effi.type ) { case TextureEffectType.EnvironmentMap: //TODO //if (effi.subtype == Curved) //{ // texCoordCalcMethod = TexCoordCalcMethod.EnvironmentMap; //} //else if (effi.subtype == Planar) //{ // texCoordCalcMethod = TexCoordCalcMethod.EnvironmentMapPlanar; //} //else if (effi.subtype == Reflection) //{ // texCoordCalcMethod = TexCoordCalcMethod.EnvironmentMapReflection; //} //else if (effi.subtype == Normal) //{ // texCoordCalcMethod = TexCoordCalcMethod.EnvironmentMapNormal; //} break; case TextureEffectType.ProjectiveTexture: texCoordCalcMethod = TexCoordCalcMethod.ProjectiveTexture; break; case TextureEffectType.Rotate: case TextureEffectType.Transform: case TextureEffectType.UScroll: case TextureEffectType.UVScroll: case TextureEffectType.VScroll: break; } } return texCoordCalcMethod; }
private void SetTextureUnit( int index, TextureUnitState textureUnitState ) { if ( index >= this.textureUnitParamsList.Count ) { throw new AxiomException( "FFPTexturing unit index out of bounds !!!" ); } if ( textureUnitState.BindingType == TextureBindingType.Vertex ) { throw new AxiomException( "FFP Texture unit does not support vertex texture fetch !!!" ); } TextureUnitParams curParams = this.textureUnitParamsList[ index ]; curParams.TextureSamplerIndex = index; curParams.TextureUnitState = textureUnitState; switch ( curParams.TextureUnitState.TextureType ) { case TextureType.CubeMap: curParams.TextureSamplerType = GpuProgramParameters.GpuConstantType.SamplerCube; curParams.VSInTextureCoordinateType = GpuProgramParameters.GpuConstantType.Float3; break; case TextureType.OneD: curParams.TextureSamplerType = GpuProgramParameters.GpuConstantType.Sampler1D; curParams.VSInTextureCoordinateType = GpuProgramParameters.GpuConstantType.Float1; break; case TextureType.ThreeD: curParams.TextureSamplerType = GpuProgramParameters.GpuConstantType.Sampler3D; curParams.VSInTextureCoordinateType = GpuProgramParameters.GpuConstantType.Float3; break; case TextureType.TwoD: curParams.TextureSamplerType = GpuProgramParameters.GpuConstantType.Sampler2D; curParams.VSInTextureCoordinateType = GpuProgramParameters.GpuConstantType.Float2; break; } curParams.VSOutTextureCoordinateType = curParams.VSInTextureCoordinateType; curParams.TexCoordCalcMethod = GetCalcMethod( curParams.TextureUnitState ); if ( curParams.TexCoordCalcMethod == TexCoordCalcMethod.ProjectiveTexture ) { curParams.VSOutTextureCoordinateType = GpuProgramParameters.GpuConstantType.Float3; } }
protected virtual bool IsProcessingNeeded( TextureUnitState texUnitState ) { return texUnitState.BindingType == TextureBindingType.Fragment; }
private void CreateProceduralTextureMods(int p, TextureUnitState t) { // Procedural mods // Custom - don't use mod if generating environment // Because I do env a different way it look horrible if(pass[p].texGen != ShaderTextureGen.Environment) { if(pass[p].tcModRotate != 0.0f) t.SetRotateAnimation(pass[p].tcModRotate); if((pass[p].tcModScroll[0] != 0.0f) || (pass[p].tcModScroll[1] != 0.0f)) { if(pass[p].tcModTurbOn) { // Turbulent scroll if(pass[p].tcModScroll[0] != 0.0f) { t.SetTransformAnimation(TextureTransform.TranslateU, WaveformType.Sine, pass[p].tcModTurb[0], pass[p].tcModTurb[3], pass[p].tcModTurb[2], pass[p].tcModTurb[1]); } if(pass[p].tcModScroll[1] != 0.0f) { t.SetTransformAnimation(TextureTransform.TranslateV, WaveformType.Sine, pass[p].tcModTurb[0], pass[p].tcModTurb[3], pass[p].tcModTurb[2], pass[p].tcModTurb[1]); } } else { // Constant scroll t.SetScrollAnimation(pass[p].tcModScroll[0], pass[p].tcModScroll[1]); } } if(pass[p].tcModStretchWave != ShaderWaveType.None) { WaveformType wft = WaveformType.Sine; switch(pass[p].tcModStretchWave) { case ShaderWaveType.Sin: wft = WaveformType.Sine; break; case ShaderWaveType.Triangle: wft = WaveformType.Triangle; break; case ShaderWaveType.Square: wft = WaveformType.Square; break; case ShaderWaveType.SawTooth: wft = WaveformType.Sawtooth; break; case ShaderWaveType.InverseSawtooth: wft = WaveformType.InverseSawtooth; break; } // Create wave-based stretcher t.SetTransformAnimation(TextureTransform.ScaleU, wft, pass[p].tcModStretchParams[3], pass[p].tcModStretchParams[0], pass[p].tcModStretchParams[2], pass[p].tcModStretchParams[1]); t.SetTransformAnimation(TextureTransform.ScaleV, wft, pass[p].tcModStretchParams[3], pass[p].tcModStretchParams[0], pass[p].tcModStretchParams[2], pass[p].tcModStretchParams[1]); } } }
/// <summary> /// Copy the details of this pass to the target pass. /// </summary> /// <param name="target">Destination pass to copy this pass's attributes to.</param> public void CopyTo(Pass target) { target.name = name; target.hashCode = hashCode; // surface target.ambient = ambient.Clone(); target.diffuse = diffuse.Clone(); target.specular = specular.Clone(); target.emissive = emissive.Clone(); target.shininess = shininess; target.tracking = tracking; // fog target.fogOverride = fogOverride; target.fogMode = fogMode; target.fogColor = fogColor.Clone(); target.fogStart = fogStart; target.fogEnd = fogEnd; target.fogDensity = fogDensity; // default blending target.sourceBlendFactor = sourceBlendFactor; target.destBlendFactor = destBlendFactor; target.depthCheck = depthCheck; target.depthWrite = depthWrite; target.alphaRejectFunction = alphaRejectFunction; target.alphaRejectValue = alphaRejectValue; target.colorWrite = colorWrite; target.depthFunc = depthFunc; target.depthBiasConstant = depthBiasConstant; target.depthBiasSlopeScale = depthBiasSlopeScale; target.cullMode = cullMode; target.manualCullMode = manualCullMode; target.lightingEnabled = lightingEnabled; target.maxLights = maxLights; target.startLight = startLight; target.runOncePerLight = runOncePerLight; target.lightsPerIteration = lightsPerIteration; target.runOnlyForOneLightType = runOnlyForOneLightType; target.onlyLightType = onlyLightType; target.shadeOptions = shadeOptions; target.sceneDetail = sceneDetail; target.passIterationCount = passIterationCount; target.pointSize = pointSize; target.pointMinSize = pointMinSize; target.pointMaxSize = pointMaxSize; target.pointSpritesEnabled = pointSpritesEnabled; target.pointAttenuationEnabled = pointAttenuationEnabled; target.pointAttenuationConstant = pointAttenuationConstant; target.pointAttenuationLinear = pointAttenuationLinear; target.pointAttenuationQuadratic = pointAttenuationQuadratic; target.contentTypeLookupBuilt = contentTypeLookupBuilt; // vertex program if(vertexProgramUsage != null) { target.vertexProgramUsage = vertexProgramUsage.Clone(); } else { target.vertexProgramUsage = null; } // shadow caster vertex program if (shadowCasterVertexProgramUsage != null) { target.shadowCasterVertexProgramUsage = shadowCasterVertexProgramUsage.Clone(); } else { target.shadowCasterVertexProgramUsage = null; } // shadow receiver vertex program if (shadowReceiverVertexProgramUsage != null) { target.shadowReceiverVertexProgramUsage = shadowReceiverVertexProgramUsage.Clone(); } else { target.shadowReceiverVertexProgramUsage = null; } // fragment program if(fragmentProgramUsage != null) { target.fragmentProgramUsage = fragmentProgramUsage.Clone(); } else { target.fragmentProgramUsage = null; } // shadow caster fragment program if (shadowCasterFragmentProgramUsage != null) { target.shadowCasterFragmentProgramUsage = shadowCasterFragmentProgramUsage.Clone(); } else { target.shadowCasterFragmentProgramUsage = null; } // shadow receiver fragment program if(shadowReceiverFragmentProgramUsage != null) { target.shadowReceiverFragmentProgramUsage = shadowReceiverFragmentProgramUsage.Clone(); } else { target.shadowReceiverFragmentProgramUsage = null; } // texture units target.RemoveAllTextureUnitStates(); for(int i = 0; i < textureUnitStates.Count; i++) { TextureUnitState newState = new TextureUnitState(target); TextureUnitState src = (TextureUnitState)textureUnitStates[i]; src.CopyTo(newState); target.textureUnitStates.Add(newState); } target.DirtyHash(); }
/// <summary> /// Creates a texture layer animator controller. /// </summary> /// <remarks> /// This helper method creates the Controller, IControllerValue and IControllerFunction classes required /// to animate a texture. /// </remarks> /// <param name="texUnit">The texture unit to animate.</param> /// <param name="sequenceTime">Length of the animation (in seconds).</param> /// <returns>A newly created controller object that will be updated during the main render loop.</returns> public Controller<Real> CreateTextureAnimator( TextureUnitState texUnit, Real sequenceTime ) { IControllerValue<Real> val = new TextureFrameControllerValue( texUnit ); IControllerFunction<Real> func = new AnimationControllerFunction( sequenceTime ); return CreateController( val, func ); }
/// <summary> /// Overloaded method. /// </summary> /// <param name="textureName">The basic name of the texture (i.e. brickwall.jpg)</param> /// <returns></returns> public TextureUnitState CreateTextureUnitState() { TextureUnitState state = new TextureUnitState(this); AddTextureUnitState(state); contentTypeLookupBuilt = false; return state; }
/// <summary> /// Creates a basic time-based texture u coordinate modifier designed for creating scrolling textures. /// </summary> /// <remarks> /// This simple method allows you to easily create constant-speed scrolling textures. If you want more /// control, look up the <see cref="CreateTextureWaveTransformer"/> for more complex wave-based /// scrollers / stretchers / rotaters. /// </remarks> /// <param name="layer">The texture unit to animate.</param> /// <param name="speed">speed, in wraps per second.</param> /// <returns>A newly created controller object that will be updated during the main render loop.</returns> public Controller<Real> CreateTextureUScroller( TextureUnitState layer, Real speed ) { IControllerValue<Real> val = null; IControllerFunction<Real> func = null; Controller<Real> controller = null; // Don't create a controller if the speed is zero if ( speed != 0 ) { // create the value and function val = new TexCoordModifierControllerValue( layer, true ); func = new MultipyControllerFunction( -speed, true ); // create the controller (uses FrameTime for source by default) controller = CreateController( val, func ); } return controller; }
/// <summary> /// Inserts a new TextureUnitState object into the Pass. /// </summary> /// <remarks> /// This unit is is added on top of all previous texture units. /// <p/> /// Applies to both fixed-function and programmable passes. /// </remarks> /// <param name="textureName">The basic name of the texture (i.e. brickwall.jpg)</param> /// <param name="texCoordSet">The index of the texture coordinate set to use.</param> /// <returns></returns> public TextureUnitState CreateTextureUnitState(string textureName, int texCoordSet) { TextureUnitState state = new TextureUnitState(this); state.SetTextureName(textureName); state.TextureCoordSet = texCoordSet; AddTextureUnitState(state); contentTypeLookupBuilt = false; return state; }
/// <summary> /// Creates a very flexible time-based texture transformation which can alter the scale, position or /// rotation of a texture based on a wave function. /// </summary> /// <param name="layer">The texture unit to effect.</param> /// <param name="type">The type of transform, either translate (scroll), scale (stretch) or rotate (spin).</param> /// <param name="waveType">The shape of the wave, see WaveformType enum for details.</param> /// <param name="baseVal">The base value of the output.</param> /// <param name="frequency">The speed of the wave in cycles per second.</param> /// <param name="phase">The offset of the start of the wave, e.g. 0.5 to start half-way through the wave.</param> /// <param name="amplitude">Scales the output so that instead of lying within 0..1 it lies within 0..(1 * amplitude) for exaggerated effects</param> /// <returns>A newly created controller object that will be updated during the main render loop.</returns> public Controller<Real> CreateTextureWaveTransformer( TextureUnitState layer, TextureTransform type, WaveformType waveType, Real baseVal, Real frequency, Real phase, Real amplitude ) { IControllerValue<Real> val = null; IControllerFunction<Real> function = null; // determine which type of controller value this layer needs switch ( type ) { case TextureTransform.TranslateU: val = new TexCoordModifierControllerValue( layer, true, false ); break; case TextureTransform.TranslateV: val = new TexCoordModifierControllerValue( layer, false, true ); break; case TextureTransform.ScaleU: val = new TexCoordModifierControllerValue( layer, false, false, true, false, false ); break; case TextureTransform.ScaleV: val = new TexCoordModifierControllerValue( layer, false, false, false, true, false ); break; case TextureTransform.Rotate: val = new TexCoordModifierControllerValue( layer, false, false, false, false, true ); break; } // switch // create a new waveform controller function function = new WaveformControllerFunction( waveType, baseVal, frequency, phase, amplitude, true ); // finally, create the controller using frame time as the source value return CreateController( this.frameTimeController, val, function ); }
/// <summary> /// Retrieve the index of the Texture Unit State in the pass. /// </summary> public int GetTextureUnitStateIndex(TextureUnitState state) { Debug.Assert(state != null, "state is 0 in Pass.AddTextureUnitState()"); // only find index for state attached to this pass if (state.Parent == this) { // iterate through TUS container and find matching pointer to state for (int i=0; i<textureUnitStates.Count; i++) { TextureUnitState t = (TextureUnitState)textureUnitStates[i]; if (t == state) return i; } } else throw new AxiomException("TextureUnitState is not attached to this pass" + " In Pass.GetTextureUnitStateIndex"); return 0; }
/// <summary> /// Adds the passed in TextureUnitState, to the existing Pass. /// </summary> /// <param name="state">TextureUnitState to add to this pass.</param> public void AddTextureUnitState( TextureUnitState state ) { textureUnitStates.Add( state ); if ( state.Name == null ) { // it's the last entry in the container so it's index is count - 1 state.Name = ( textureUnitStates.Count - 1 ).ToString(); // Since the anme was never set and a default one has been made, // clear the alias name so that when the texture unit name is set // by the user, the alias name will be set to that name. state.TextureNameAlias = null; } // needs recompilation _parent.NotifyNeedsRecompile(); DirtyHash(); }
/// <summary> /// Removes the specified TextureUnitState from this pass. /// </summary> /// <param name="state">A reference to the TextureUnitState to remove from this pass.</param> public void RemoveTextureUnitState(TextureUnitState state) { textureUnitStates.Remove(state); if(!queuedForDeletion) { // needs recompilation parent.NotifyNeedsRecompile(); } DirtyHash(); contentTypeLookupBuilt = false; }
/// <summary> /// Overloaded method. /// </summary> /// <returns></returns> public TextureUnitState CreateTextureUnitState() { TextureUnitState state = new TextureUnitState( this ); textureUnitStates.Add( state ); // needs recompilation _parent.NotifyNeedsRecompile(); DirtyHash(); return state; }
/// <summary> /// Utility function for setting all the properties of a texture unit at once. /// This method is also worth using over the individual texture unit settings because it /// only sets those settings which are different from the current settings for this /// unit, thus minimising render state changes. /// </summary> /// <param name="textureUnit">Index of the texture unit to configure</param> /// <param name="layer">Reference to a TextureLayer object which defines all the settings.</param> public virtual void SetTextureUnit(int unit, TextureUnitState unitState, bool fixedFunction) { // This method is only ever called to set a texture unit to valid details // The method _disableTextureUnit is called to turn a unit off // Vertex texture binding? if (caps.CheckCap(Capabilities.VertexTextureFetch) && !caps.CheckCap(Capabilities.VertexTextureFetch)) { if (unitState.BindingType == GpuProgramType.Vertex) { // Bind vertex texture SetVertexTexture(unit, unitState); // bind nothing to fragment unit (hardware isn't shared but fragment // unit can't be using the same index SetTexture(unit, true, string.Empty); } else { // vice versa SetVertexTexture(unit, unitState); SetTexture(unit, true, unitState.TextureName); } } else { // Shared vertex / fragment textures or no vertex texture support // Bind texture (may be blank) SetTexture(unit, true, unitState.TextureName); } // Set texture coordinate set // SetTextureCoordSet(unit, unitState.TextureCoordSet); if (!fixedFunction) // From Direct3D9 error log: // Texture coordinate index in the stage must be equal to the stage index when programmable vertex pipeline is used SetTextureCoordSet(unit, unit); // Texture layer filtering SetTextureUnitFiltering( unit, unitState.GetTextureFiltering(FilterType.Min), unitState.GetTextureFiltering(FilterType.Mag), unitState.GetTextureFiltering(FilterType.Mip)); // Texture layer anistropy SetTextureLayerAnisotropy(unit, unitState.TextureAnisotropy); // Set mipmap biasing SetTextureMipmapBias(unit, unitState.MipmapBias); // Texture addressing mode UVWAddressingMode uvw = unitState.GetTextureAddressingMode(); SetTextureAddressingMode(unit, uvw); // Set texture border colour only if required if (uvw.u == TextureAddressing.Border || uvw.v == TextureAddressing.Border || uvw.w == TextureAddressing.Border) SetTextureBorderColor(unit, unitState.TextureBorderColor); // This stuff only gets done for the fixed function pipeline. It is not needed // if we are using a pixel shader. if (fixedFunction) { // Tex Coord Set SetTextureCoordSet(unit, unitState.TextureCoordSet); // set the texture blending mode SetTextureBlendMode(unit, unitState.ColorBlendMode); // set the texture blending mode SetTextureBlendMode(unit, unitState.AlphaBlendMode); bool anyCalcs = false; for (int i = 0; i < unitState.NumEffects; i++) { TextureEffect effect = unitState.GetEffect(i); switch (effect.type) { case TextureEffectType.EnvironmentMap: if ((EnvironmentMap)effect.subtype == EnvironmentMap.Curved) { SetTextureCoordCalculation(unit, TexCoordCalcMethod.EnvironmentMap); anyCalcs = true; } else if ((EnvironmentMap)effect.subtype == EnvironmentMap.Planar) { SetTextureCoordCalculation(unit, TexCoordCalcMethod.EnvironmentMapPlanar); anyCalcs = true; } else if ((EnvironmentMap)effect.subtype == EnvironmentMap.Reflection) { SetTextureCoordCalculation(unit, TexCoordCalcMethod.EnvironmentMapReflection); anyCalcs = true; } else if ((EnvironmentMap)effect.subtype == EnvironmentMap.Normal) { SetTextureCoordCalculation(unit, TexCoordCalcMethod.EnvironmentMapNormal); anyCalcs = true; } break; case TextureEffectType.Scroll: case TextureEffectType.Rotate: case TextureEffectType.Transform: break; case TextureEffectType.ProjectiveTexture: SetTextureCoordCalculation(unit, TexCoordCalcMethod.ProjectiveTexture, effect.frustum); anyCalcs = true; break; } // switch } // for // Ensure any previous texcoord calc settings are reset if there are now none if (!anyCalcs) { SetTextureCoordCalculation(unit, TexCoordCalcMethod.None); } // set the texture matrix to that of the current layer for any transformations SetTextureMatrix(unit, unitState.TextureMatrix); } }
/// <summary> /// Removes the specified TextureUnitState from this pass. /// </summary> /// <param name="state">A reference to the TextureUnitState to remove from this pass.</param> public void RemoveTextureUnitState( TextureUnitState state ) { textureUnitStates.Remove( state ); if ( !queuedForDeletion ) { // needs recompilation _parent.NotifyNeedsRecompile(); } DirtyHash(); }
/// <summary> /// Binds a texture to a vertex sampler. /// </summary> /// <remarks> /// Not all rendersystems support separate vertex samplers. For those that /// do, you can set a texture for them, separate to the regular texture /// samplers, using this method. For those that don't, you should use the /// regular texture samplers which are shared between the vertex and /// fragment units; calling this method will throw an exception. /// @see RenderSystemCapabilites::getVertexTextureUnitsShared /// </remarks> public void SetVertexTexture(int unit, TextureUnitState unitState) { throw new AxiomException( "This rendersystem does not support separate vertex texture samplers, " + "you should use the regular texture samplers which are shared between " + "the vertex and fragment units." + "In RenderSystem.SetVertexTexture"); }
/// <see cref="Translator.Translate"/> public override void Translate( ScriptCompiler compiler, AbstractNode node ) { ObjectAbstractNode obj = (ObjectAbstractNode)node; Pass pass = (Pass)obj.Parent.Context; _textureunit = pass.CreateTextureUnitState(); obj.Context = _textureunit; // Get the name of the technique if ( !string.IsNullOrEmpty( obj.Name ) ) _textureunit.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_TEXTURE_ALIAS case Keywords.ID_TEXTURE_ALIAS: 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, "texture_alias must have at most 1 argument" ); } else { string val; if ( getString( prop.Values[ 0 ], out val ) ) _textureunit.TextureNameAlias = val; else compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, prop.Values[ 0 ].Value + " is not a valid texture alias" ); } break; #endregion ID_TEXTURE_ALIAS #region ID_TEXTURE case Keywords.ID_TEXTURE: if ( prop.Values.Count == 0 ) { compiler.AddError( CompileErrorCode.StringExpected, prop.File, prop.Line ); } else if ( prop.Values.Count > 5 ) { compiler.AddError( CompileErrorCode.FewerParametersExpected, prop.File, prop.Line, "texture must have at most 5 arguments" ); } else { AbstractNode j = getNodeAt( prop.Values, 0 ); int index = 1; string val; if ( getString( j, out val ) ) { TextureType texType = TextureType.TwoD; bool isAlpha = false; bool sRGBRead = false; PixelFormat format = PixelFormat.Unknown; int mipmaps = -1;//MIP_DEFAULT; while ( j != null ) { if ( j is AtomAbstractNode ) { AtomAbstractNode atom = (AtomAbstractNode)j; switch ( (Keywords)atom.Id ) { case Keywords.ID_1D: texType = TextureType.OneD; break; case Keywords.ID_2D: texType = TextureType.TwoD; break; case Keywords.ID_3D: texType = TextureType.ThreeD; break; case Keywords.ID_CUBIC: texType = TextureType.CubeMap; break; case Keywords.ID_UNLIMITED: mipmaps = 0x7FFFFFFF;//MIP_UNLIMITED; break; case Keywords.ID_ALPHA: isAlpha = true; break; case Keywords.ID_GAMMA: sRGBRead = true; break; default: if ( atom.IsNumber ) mipmaps = (int)atom.Number; else format = PixelUtil.GetFormatFromName( atom.Value, true ); break; } } else { compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, j.Value + " is not a supported argument to the texture property" ); } j = getNodeAt( prop.Values, index++ ); } ScriptCompilerEvent evt = new ProcessResourceNameScriptCompilerEvent( ProcessResourceNameScriptCompilerEvent.ResourceType.Texture, val ); compiler._fireEvent( ref evt ); string textureName = ( (ProcessResourceNameScriptCompilerEvent)evt ).Name; _textureunit.SetTextureName( textureName, texType ); _textureunit.DesiredFormat = format; _textureunit.IsAlpha = isAlpha; _textureunit.MipmapCount = mipmaps; _textureunit.IsHardwareGammaEnabled = sRGBRead; } else compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, j.Value + " is not a valid texture name" ); } break; #endregion ID_TEXTURE #region ID_ANIM_TEXTURE case Keywords.ID_ANIM_TEXTURE: if ( prop.Values.Count < 3 ) { compiler.AddError( CompileErrorCode.StringExpected, prop.File, prop.Line ); } else { AbstractNode i1 = getNodeAt( prop.Values, 1 ); if ( i1 is AtomAbstractNode && ( (AtomAbstractNode)i ).IsNumber ) { // Short form AbstractNode i0 = getNodeAt( prop.Values, 0 ), i2 = getNodeAt( prop.Values, 2 ); if ( i0 is AtomAbstractNode ) { string val0; int val1; Real val2; if ( getString( i0, out val0 ) && getInt( i1, out val1 ) && getReal( i2, out val2 ) ) { ScriptCompilerEvent evt = new ProcessResourceNameScriptCompilerEvent( ProcessResourceNameScriptCompilerEvent.ResourceType.Texture, val0 ); compiler._fireEvent( ref evt ); string evtName = ( (ProcessResourceNameScriptCompilerEvent)evt ).Name; _textureunit.SetAnimatedTextureName( evtName, val1, val2 ); } else { compiler.AddError( CompileErrorCode.NumberExpected, prop.File, prop.Line, "anim_texture short form requires a texture name, number of frames, and animation duration" ); } } else { compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, "anim_texture short form requires a texture name, number of frames, and animation duration" ); } } else { // Long form has n number of frames Real duration = 0; AbstractNode inNode = getNodeAt( prop.Values, prop.Values.Count - 1 ); if ( getReal( inNode, out duration ) ) { string[] names = new string[ prop.Values.Count - 1 ]; int n = 0; AbstractNode j = prop.Values[ 0 ]; int index = 0; while ( j != inNode ) { if ( j is AtomAbstractNode ) { string name = ( (AtomAbstractNode)j ).Value; #warning check this if statement // Run the name through the listener if ( compiler.Listener != null ) { ScriptCompilerEvent evt = new ProcessResourceNameScriptCompilerEvent( ProcessResourceNameScriptCompilerEvent.ResourceType.Texture, name ); compiler._fireEvent( ref evt ); names[ n++ ] = ( (ProcessResourceNameScriptCompilerEvent)evt ).Name; } else { names[ n++ ] = name; } } else compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, j.Value + " is not supported as a texture name" ); ++index; j = prop.Values[ index ]; } _textureunit.SetAnimatedTextureName( names, n, duration ); } else { compiler.AddError( CompileErrorCode.NumberExpected, prop.File, prop.Line, inNode.Value + " is not supported for the duration argument" ); } } } break; #endregion ID_ANIM_TEXTURE #region ID_CUBIC_TEXTURE case Keywords.ID_CUBIC_TEXTURE: if ( prop.Values.Count == 0 ) { compiler.AddError( CompileErrorCode.StringExpected, prop.File, prop.Line ); } 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; ScriptCompilerEvent evt = new ProcessResourceNameScriptCompilerEvent( ProcessResourceNameScriptCompilerEvent.ResourceType.Texture, atom0.Value ); compiler._fireEvent( ref evt ); string evtName = ( (ProcessResourceNameScriptCompilerEvent)evt ).Name; _textureunit.SetCubicTextureName( evtName, atom1.Id == (uint)Keywords.ID_COMBINED_UVW ); } else { compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line ); } } else if ( prop.Values.Count == 7 ) { AbstractNode i0 = getNodeAt( prop.Values, 0 ), i1 = getNodeAt( prop.Values, 1 ), i2 = getNodeAt( prop.Values, 2 ), i3 = getNodeAt( prop.Values, 3 ), i4 = getNodeAt( prop.Values, 4 ), i5 = getNodeAt( prop.Values, 5 ), i6 = getNodeAt( prop.Values, 6 ); if ( i0 is AtomAbstractNode && i1 is AtomAbstractNode && i2 is AtomAbstractNode && i3 is AtomAbstractNode && i4 is AtomAbstractNode && i5 is AtomAbstractNode && i6 is AtomAbstractNode ) { AtomAbstractNode atom0 = (AtomAbstractNode)i0, atom1 = (AtomAbstractNode)i1, atom2 = (AtomAbstractNode)i2, atom3 = (AtomAbstractNode)i3, atom4 = (AtomAbstractNode)i4, atom5 = (AtomAbstractNode)i5, atom6 = (AtomAbstractNode)i6; string[] names = new string[ 6 ]; names[ 0 ] = atom0.Value; names[ 1 ] = atom1.Value; names[ 2 ] = atom2.Value; names[ 3 ] = atom3.Value; names[ 4 ] = atom4.Value; names[ 5 ] = atom5.Value; if ( compiler.Listener != null ) { // Run each name through the listener for ( int j = 0; j < 6; ++j ) { ScriptCompilerEvent evt = new ProcessResourceNameScriptCompilerEvent( ProcessResourceNameScriptCompilerEvent.ResourceType.Texture, names[ j ] ); compiler._fireEvent( ref evt ); names[ j ] = ( (ProcessResourceNameScriptCompilerEvent)evt ).Name; } } _textureunit.SetCubicTextureName( names, atom6.Id == (uint)Keywords.ID_COMBINED_UVW ); } } else { compiler.AddError( CompileErrorCode.FewerParametersExpected, prop.File, prop.Line, "cubic_texture must have at most 7 arguments" ); } break; #endregion ID_CUBIC_TEXTURE #region ID_TEX_COORD_SET case Keywords.ID_TEX_COORD_SET: 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, "tex_coord_set must have at most 1 argument" ); } else { int val = 0; if ( getInt( prop.Values[ 0 ], out val ) ) _textureunit.TextureCoordSet = val; else compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, prop.Values[ 0 ].Value + " is not supported as an integer argument" ); } break; #endregion ID_TEX_COORD_SET #region ID_TEX_ADDRESS_MODE case Keywords.ID_TEX_ADDRESS_MODE: if ( prop.Values.Count == 0 ) { compiler.AddError( CompileErrorCode.StringExpected, prop.File, prop.Line ); } else { AbstractNode i0 = getNodeAt( prop.Values, 0 ), i1 = getNodeAt( prop.Values, 1 ), i2 = getNodeAt( prop.Values, 2 ); UVWAddressing mode = new UVWAddressing( TextureAddressing.Wrap ); if ( i0 != null && i0 is AtomAbstractNode ) { AtomAbstractNode atom = (AtomAbstractNode)i0; switch ( (Keywords)atom.Id ) { case Keywords.ID_WRAP: mode.U = TextureAddressing.Wrap; break; case Keywords.ID_CLAMP: mode.U = TextureAddressing.Clamp; break; case Keywords.ID_MIRROR: mode.U = TextureAddressing.Mirror; break; case Keywords.ID_BORDER: mode.U = TextureAddressing.Border; break; default: compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, i0.Value + " not supported as first argument (must be \"wrap\", \"clamp\", \"mirror\", or \"border\")" ); break; } } mode.V = mode.U; mode.W = mode.U; if ( i1 != null && i1 is AtomAbstractNode ) { AtomAbstractNode atom = (AtomAbstractNode)i1; switch ( (Keywords)atom.Id ) { case Keywords.ID_WRAP: mode.V = TextureAddressing.Wrap; break; case Keywords.ID_CLAMP: mode.V = TextureAddressing.Clamp; break; case Keywords.ID_MIRROR: mode.V = TextureAddressing.Mirror; break; case Keywords.ID_BORDER: mode.V = TextureAddressing.Border; break; default: compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, i0.Value + " not supported as second argument (must be \"wrap\", \"clamp\", \"mirror\", or \"border\")" ); break; } } if ( i2 != null && i2 is AtomAbstractNode ) { AtomAbstractNode atom = (AtomAbstractNode)i2; switch ( (Keywords)atom.Id ) { case Keywords.ID_WRAP: mode.W = TextureAddressing.Wrap; break; case Keywords.ID_CLAMP: mode.W = TextureAddressing.Clamp; break; case Keywords.ID_MIRROR: mode.W = TextureAddressing.Mirror; break; case Keywords.ID_BORDER: mode.W = TextureAddressing.Border; break; default: compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, i0.Value + " not supported as third argument (must be \"wrap\", \"clamp\", \"mirror\", or \"border\")" ); break; } } _textureunit.SetTextureAddressingMode( mode ); } break; #endregion ID_TEX_ADDRESS_MODE #region ID_TEX_BORDER_COLOUR case Keywords.ID_TEX_BORDER_COLOUR: if ( prop.Values.Count == 0 ) { compiler.AddError( CompileErrorCode.NumberExpected, prop.File, prop.Line ); } else { ColorEx val; if ( getColor( prop.Values, 0, out val ) ) _textureunit.TextureBorderColor = val; else compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, "tex_border_colour only accepts a colour argument" ); } break; #endregion ID_TEX_BORDER_COLOUR #region ID_FILTERING case Keywords.ID_FILTERING: if ( prop.Values.Count == 0 ) { compiler.AddError( CompileErrorCode.StringExpected, prop.File, prop.Line ); } 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_NONE: _textureunit.SetTextureFiltering( TextureFiltering.None ); break; case Keywords.ID_BILINEAR: _textureunit.SetTextureFiltering( TextureFiltering.Bilinear ); break; case Keywords.ID_TRILINEAR: _textureunit.SetTextureFiltering( TextureFiltering.Trilinear ); break; case Keywords.ID_ANISOTROPIC: _textureunit.SetTextureFiltering( TextureFiltering.Anisotropic ); break; default: compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, prop.Values[ 0 ].Value + " not supported as first argument (must be \"none\", \"bilinear\", \"trilinear\", or \"anisotropic\")" ); break; } } else { compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, prop.Values[ 0 ].Value + " not supported as first argument (must be \"none\", \"bilinear\", \"trilinear\", or \"anisotropic\")" ); } } else if ( prop.Values.Count == 3 ) { AbstractNode i0 = getNodeAt( prop.Values, 0 ), i1 = getNodeAt( prop.Values, 1 ), i2 = getNodeAt( prop.Values, 2 ); if ( i0 is AtomAbstractNode && i1 is AtomAbstractNode && i2 is AtomAbstractNode ) { AtomAbstractNode atom0 = (AtomAbstractNode)i0, atom1 = (AtomAbstractNode)i1, atom2 = (AtomAbstractNode)i2; FilterOptions tmin = FilterOptions.None, tmax = FilterOptions.None, tmip = FilterOptions.None; switch ( (Keywords)atom0.Id ) { case Keywords.ID_NONE: tmin = FilterOptions.None; break; case Keywords.ID_POINT: tmin = FilterOptions.Point; break; case Keywords.ID_LINEAR: tmin = FilterOptions.Linear; break; case Keywords.ID_ANISOTROPIC: tmin = FilterOptions.Anisotropic; break; default: compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, i0.Value + " not supported as first argument (must be \"none\", \"point\", \"linear\", or \"anisotropic\")" ); break; } switch ( (Keywords)atom1.Id ) { case Keywords.ID_NONE: tmax = FilterOptions.None; break; case Keywords.ID_POINT: tmax = FilterOptions.Point; break; case Keywords.ID_LINEAR: tmax = FilterOptions.Linear; break; case Keywords.ID_ANISOTROPIC: tmax = FilterOptions.Anisotropic; break; default: compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, i0.Value + " not supported as second argument (must be \"none\", \"point\", \"linear\", or \"anisotropic\")" ); break; } switch ( (Keywords)atom2.Id ) { case Keywords.ID_NONE: tmip = FilterOptions.None; break; case Keywords.ID_POINT: tmip = FilterOptions.Point; break; case Keywords.ID_LINEAR: tmip = FilterOptions.Linear; break; case Keywords.ID_ANISOTROPIC: tmip = FilterOptions.Anisotropic; break; default: compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, i0.Value + " not supported as third argument (must be \"none\", \"point\", \"linear\", or \"anisotropic\")" ); break; } _textureunit.SetTextureFiltering( tmin, tmax, tmip ); } else { compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line ); } } else { compiler.AddError( CompileErrorCode.FewerParametersExpected, prop.File, prop.Line, "filtering must have either 1 or 3 arguments" ); } break; #endregion ID_FILTERING #region ID_MAX_ANISOTROPY case Keywords.ID_MAX_ANISOTROPY: if ( prop.Values.Count == 0 ) { compiler.AddError( CompileErrorCode.NumberExpected, prop.File, prop.Line ); } else if ( prop.Values.Count > 1 ) { compiler.AddError( CompileErrorCode.FewerParametersExpected, prop.File, prop.Line, "max_anisotropy must have at most 1 argument" ); } else { int val = 0; if ( getInt( prop.Values[ 0 ], out val ) ) _textureunit.TextureAnisotropy = val; else compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, prop.Values[ 0 ].Value + " is not a valid integer argument" ); } break; #endregion ID_MAX_ANISOTROPY #region ID_MIPMAP_BIAS case Keywords.ID_MIPMAP_BIAS: if ( prop.Values.Count == 0 ) { compiler.AddError( CompileErrorCode.NumberExpected, prop.File, prop.Line ); } else if ( prop.Values.Count > 1 ) { compiler.AddError( CompileErrorCode.FewerParametersExpected, prop.File, prop.Line, "mipmap_bias must have at most 1 argument" ); } else { throw new NotImplementedException(); #if UNREACHABLE_CODE Real val = 0.0f; if ( getReal( prop.Values[ 0 ], out val ) ) { /*mUnit->setTextureMipmapBias(val);*/ } else compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, prop.Values[ 0 ].Value + " is not a valid number argument" ); #endif } break; #endregion ID_MIPMAP_BIAS #region ID_COLOUR_OP case Keywords.ID_COLOUR_OP: if ( prop.Values.Count == 0 ) { compiler.AddError( CompileErrorCode.NumberExpected, prop.File, prop.Line ); } else if ( prop.Values.Count > 1 ) { compiler.AddError( CompileErrorCode.FewerParametersExpected, prop.File, prop.Line, "colour_op 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_REPLACE: _textureunit.ColorOperation = LayerBlendOperation.Replace; break; case Keywords.ID_ADD: _textureunit.ColorOperation = LayerBlendOperation.Add; break; case Keywords.ID_MODULATE: _textureunit.ColorOperation = LayerBlendOperation.Modulate; break; case Keywords.ID_ALPHA_BLEND: _textureunit.ColorOperation = LayerBlendOperation.AlphaBlend; break; default: compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, prop.Values[ 0 ].Value + " is not a valid argument (must be \"replace\", \"add\", \"modulate\", or \"alpha_blend\")" ); break; } } else { compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, prop.Values[ 0 ].Value + " is not a valid argument (must be \"replace\", \"add\", \"modulate\", or \"alpha_blend\")" ); } } break; #endregion ID_COLOUR_OP #region ID_COLOUR_OP_EX case Keywords.ID_COLOUR_OP_EX: if ( prop.Values.Count < 3 ) { compiler.AddError( CompileErrorCode.StringExpected, prop.File, prop.Line, "colour_op_ex must have at least 3 arguments" ); } else if ( prop.Values.Count > 10 ) { compiler.AddError( CompileErrorCode.FewerParametersExpected, prop.File, prop.Line, "colour_op_ex must have at most 10 arguments" ); } else { AbstractNode i0 = getNodeAt( prop.Values, 0 ), i1 = getNodeAt( prop.Values, 1 ), i2 = getNodeAt( prop.Values, 2 ); if ( i0 is AtomAbstractNode && i1 is AtomAbstractNode && i2 is AtomAbstractNode ) { AtomAbstractNode atom0 = (AtomAbstractNode)i0, atom1 = (AtomAbstractNode)i1, atom2 = (AtomAbstractNode)i2; LayerBlendOperationEx op = LayerBlendOperationEx.Add; LayerBlendSource source1 = LayerBlendSource.Current, source2 = LayerBlendSource.Texture; ColorEx arg1 = ColorEx.White, arg2 = ColorEx.White; Real manualBlend = 0.0f; switch ( (Keywords)atom0.Id ) { case Keywords.ID_SOURCE1: op = LayerBlendOperationEx.Source1; break; case Keywords.ID_SOURCE2: op = LayerBlendOperationEx.Source2; break; case Keywords.ID_MODULATE: op = LayerBlendOperationEx.Modulate; break; case Keywords.ID_MODULATE_X2: op = LayerBlendOperationEx.ModulateX2; break; case Keywords.ID_MODULATE_X4: op = LayerBlendOperationEx.ModulateX4; break; case Keywords.ID_ADD: op = LayerBlendOperationEx.Add; break; case Keywords.ID_ADD_SIGNED: op = LayerBlendOperationEx.AddSigned; break; case Keywords.ID_ADD_SMOOTH: op = LayerBlendOperationEx.AddSmooth; break; case Keywords.ID_SUBTRACT: op = LayerBlendOperationEx.Subtract; break; case Keywords.ID_BLEND_DIFFUSE_ALPHA: op = LayerBlendOperationEx.BlendDiffuseAlpha; break; case Keywords.ID_BLEND_TEXTURE_ALPHA: op = LayerBlendOperationEx.BlendTextureAlpha; break; case Keywords.ID_BLEND_CURRENT_ALPHA: op = LayerBlendOperationEx.BlendCurrentAlpha; break; case Keywords.ID_BLEND_MANUAL: op = LayerBlendOperationEx.BlendManual; break; case Keywords.ID_DOT_PRODUCT: op = LayerBlendOperationEx.DotProduct; break; case Keywords.ID_BLEND_DIFFUSE_COLOUR: op = LayerBlendOperationEx.BlendDiffuseColor; break; default: compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, i0.Value + " is not a valid first argument (must be \"source1\", \"source2\", \"modulate\", \"modulate_x2\", \"modulate_x4\", \"add\", \"add_signed\", \"add_smooth\", \"subtract\", \"blend_diffuse_alpha\", \"blend_texture_alpha\", \"blend_current_alpha\", \"blend_manual\", \"dot_product\", or \"blend_diffuse_colour\")" ); break; } switch ( (Keywords)atom1.Id ) { case Keywords.ID_SRC_CURRENT: source1 = LayerBlendSource.Current; break; case Keywords.ID_SRC_TEXTURE: source1 = LayerBlendSource.Texture; break; case Keywords.ID_SRC_DIFFUSE: source1 = LayerBlendSource.Diffuse; break; case Keywords.ID_SRC_SPECULAR: source1 = LayerBlendSource.Specular; break; case Keywords.ID_SRC_MANUAL: source1 = LayerBlendSource.Manual; break; default: compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, i1.Value + " is not a valid second argument (must be \"src_current\", \"src_texture\", \"src_diffuse\", \"src_specular\", or \"src_manual\")" ); break; } switch ( (Keywords)atom2.Id ) { case Keywords.ID_SRC_CURRENT: source2 = LayerBlendSource.Current; break; case Keywords.ID_SRC_TEXTURE: source2 = LayerBlendSource.Texture; break; case Keywords.ID_SRC_DIFFUSE: source2 = LayerBlendSource.Diffuse; break; case Keywords.ID_SRC_SPECULAR: source2 = LayerBlendSource.Specular; break; case Keywords.ID_SRC_MANUAL: source2 = LayerBlendSource.Manual; break; default: compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, i2.Value + " is not a valid third argument (must be \"src_current\", \"src_texture\", \"src_diffuse\", \"src_specular\", or \"src_manual\")" ); break; } if ( op == LayerBlendOperationEx.BlendManual ) { AbstractNode i3 = getNodeAt( prop.Values, 3 ); if ( i3 != null ) { if ( !getReal( i3, out manualBlend ) ) compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, i3.Value + " is not a valid number argument" ); } else { compiler.AddError( CompileErrorCode.NumberExpected, prop.File, prop.Line, "fourth argument expected when blend_manual is used" ); } } AbstractNode j = getNodeAt( prop.Values, 3 ); int index = 3; if ( op == LayerBlendOperationEx.BlendManual ) j = getNodeAt( prop.Values, ++index ); if ( source1 == LayerBlendSource.Manual ) { if ( j != null ) { if ( !getColor( prop.Values, 3, out arg1, 3 ) ) compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, "valid colour expected when src_manual is used" ); } else { compiler.AddError( CompileErrorCode.NumberExpected, prop.File, prop.Line, "valid colour expected when src_manual is used" ); } } if ( source2 == LayerBlendSource.Manual ) { if ( j != null ) { if ( !getColor( prop.Values, 3, out arg2, 3 ) ) compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, "valid colour expected when src_manual is used" ); } else { compiler.AddError( CompileErrorCode.NumberExpected, prop.File, prop.Line, "valid colour expected when src_manual is used" ); } } _textureunit.SetColorOperationEx( op, source1, source2, arg1, arg2, manualBlend ); } else { compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line ); } } break; #endregion ID_COLOUR_OP_EX #region ID_COLOUR_OP_MULTIPASS_FALLBACK case Keywords.ID_COLOUR_OP_MULTIPASS_FALLBACK: 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, "colour_op_multiplass_fallback must have 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: _textureunit.SetColorOpMultipassFallback( SceneBlendFactor.One, SceneBlendFactor.One ); break; case Keywords.ID_MODULATE: _textureunit.SetColorOpMultipassFallback( SceneBlendFactor.DestColor, SceneBlendFactor.Zero ); break; case Keywords.ID_COLOUR_BLEND: _textureunit.SetColorOpMultipassFallback( SceneBlendFactor.SourceColor, SceneBlendFactor.OneMinusSourceColor ); break; case Keywords.ID_ALPHA_BLEND: _textureunit.SetColorOpMultipassFallback( SceneBlendFactor.SourceAlpha, SceneBlendFactor.OneMinusSourceAlpha ); break; case Keywords.ID_REPLACE: _textureunit.SetColorOpMultipassFallback( SceneBlendFactor.One, SceneBlendFactor.Zero ); break; default: compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, "argument must be a valid scene blend type (add, modulate, colour_blend, alpha_blend, or replace)" ); break; } } else { compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, "argument must be a valid scene blend type (add, modulate, colour_blend, alpha_blend, or replace)" ); } } 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 ) ) _textureunit.SetColorOpMultipassFallback( sbf0, sbf1 ); else compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, "arguments must be valid scene blend factors" ); } break; #endregion ID_COLOUR_OP_MULTIPASS_FALLBACK #region ID_ALPHA_OP_EX case Keywords.ID_ALPHA_OP_EX: if ( prop.Values.Count < 3 ) { compiler.AddError( CompileErrorCode.StringExpected, prop.File, prop.Line, "alpha_op_ex must have at least 3 arguments" ); } else if ( prop.Values.Count > 6 ) { compiler.AddError( CompileErrorCode.FewerParametersExpected, prop.File, prop.Line, "alpha_op_ex must have at most 6 arguments" ); } else { AbstractNode i0 = getNodeAt( prop.Values, 0 ), i1 = getNodeAt( prop.Values, 1 ), i2 = getNodeAt( prop.Values, 2 ); if ( i0 is AtomAbstractNode && i1 is AtomAbstractNode && i2 is AtomAbstractNode ) { AtomAbstractNode atom0 = (AtomAbstractNode)i0, atom1 = (AtomAbstractNode)i1, atom2 = (AtomAbstractNode)i2; LayerBlendOperationEx op = LayerBlendOperationEx.Add; LayerBlendSource source1 = LayerBlendSource.Current, source2 = LayerBlendSource.Texture; Real arg1 = 0.0f, arg2 = 0.0f; Real manualBlend = 0.0f; switch ( (Keywords)atom0.Id ) { case Keywords.ID_SOURCE1: op = LayerBlendOperationEx.Source1; break; case Keywords.ID_SOURCE2: op = LayerBlendOperationEx.Source2; break; case Keywords.ID_MODULATE: op = LayerBlendOperationEx.Modulate; break; case Keywords.ID_MODULATE_X2: op = LayerBlendOperationEx.ModulateX2; break; case Keywords.ID_MODULATE_X4: op = LayerBlendOperationEx.ModulateX4; break; case Keywords.ID_ADD: op = LayerBlendOperationEx.Add; break; case Keywords.ID_ADD_SIGNED: op = LayerBlendOperationEx.AddSigned; break; case Keywords.ID_ADD_SMOOTH: op = LayerBlendOperationEx.AddSmooth; break; case Keywords.ID_SUBTRACT: op = LayerBlendOperationEx.Subtract; break; case Keywords.ID_BLEND_DIFFUSE_ALPHA: op = LayerBlendOperationEx.BlendDiffuseAlpha; break; case Keywords.ID_BLEND_TEXTURE_ALPHA: op = LayerBlendOperationEx.BlendTextureAlpha; break; case Keywords.ID_BLEND_CURRENT_ALPHA: op = LayerBlendOperationEx.BlendCurrentAlpha; break; case Keywords.ID_BLEND_MANUAL: op = LayerBlendOperationEx.BlendManual; break; case Keywords.ID_DOT_PRODUCT: op = LayerBlendOperationEx.DotProduct; break; case Keywords.ID_BLEND_DIFFUSE_COLOUR: op = LayerBlendOperationEx.BlendDiffuseColor; break; default: compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, i0.Value + " is not a valid first argument (must be \"source1\", \"source2\", \"modulate\", \"modulate_x2\", \"modulate_x4\", \"add\", \"add_signed\", \"add_smooth\", \"subtract\", \"blend_diffuse_alpha\", \"blend_texture_alpha\", \"blend_current_alpha\", \"blend_manual\", \"dot_product\", or \"blend_diffuse_colour\")" ); break; } switch ( (Keywords)atom1.Id ) { case Keywords.ID_SRC_CURRENT: source1 = LayerBlendSource.Current; break; case Keywords.ID_SRC_TEXTURE: source1 = LayerBlendSource.Texture; break; case Keywords.ID_SRC_DIFFUSE: source1 = LayerBlendSource.Diffuse; break; case Keywords.ID_SRC_SPECULAR: source1 = LayerBlendSource.Specular; break; case Keywords.ID_SRC_MANUAL: source1 = LayerBlendSource.Manual; break; default: compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, i1.Value + " is not a valid second argument (must be \"src_current\", \"src_texture\", \"src_diffuse\", \"src_specular\", or \"src_manual\")" ); break; } switch ( (Keywords)atom2.Id ) { case Keywords.ID_SRC_CURRENT: source2 = LayerBlendSource.Current; break; case Keywords.ID_SRC_TEXTURE: source2 = LayerBlendSource.Texture; break; case Keywords.ID_SRC_DIFFUSE: source2 = LayerBlendSource.Diffuse; break; case Keywords.ID_SRC_SPECULAR: source2 = LayerBlendSource.Specular; break; case Keywords.ID_SRC_MANUAL: source2 = LayerBlendSource.Manual; break; default: compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, i2.Value + " is not a valid third argument (must be \"src_current\", \"src_texture\", \"src_diffuse\", \"src_specular\", or \"src_manual\")" ); break; } if ( op == LayerBlendOperationEx.BlendManual ) { AbstractNode i3 = getNodeAt( prop.Values, 3 ); if ( i3 != null ) { if ( !getReal( i3, out manualBlend ) ) compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, "valid number expected when blend_manual is used" ); } else { compiler.AddError( CompileErrorCode.NumberExpected, prop.File, prop.Line, "valid number expected when blend_manual is used" ); } } AbstractNode j = getNodeAt( prop.Values, 3 ); int index = 3; if ( op == LayerBlendOperationEx.BlendManual ) j = getNodeAt( prop.Values, ++index ); if ( source1 == LayerBlendSource.Manual ) { if ( j != null ) { if ( !getReal( j, out arg1 ) ) compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, "valid colour expected when src_manual is used" ); else j = getNodeAt( prop.Values, ++index ); } else { compiler.AddError( CompileErrorCode.NumberExpected, prop.File, prop.Line, "valid colour expected when src_manual is used" ); } } if ( source2 == LayerBlendSource.Manual ) { if ( j != null ) { if ( !getReal( j, out arg2 ) ) compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, "valid colour expected when src_manual is used" ); } else { compiler.AddError( CompileErrorCode.NumberExpected, prop.File, prop.Line, "valid colour expected when src_manual is used" ); } } _textureunit.SetAlphaOperation( op, source1, source2, arg1, arg2, manualBlend ); } else { compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line ); } } break; #endregion ID_ALPHA_OP_EX #region ID_ENV_MAP case Keywords.ID_ENV_MAP: 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, "env_map must have at most 1 argument" ); } else { if ( prop.Values[ 0 ] is AtomAbstractNode ) { AtomAbstractNode atom = (AtomAbstractNode)prop.Values[ 0 ]; switch ( atom.Id ) { case (uint)BuiltIn.ID_OFF: _textureunit.SetEnvironmentMap( false ); break; case (uint)Keywords.ID_SPHERICAL: _textureunit.SetEnvironmentMap( true, EnvironmentMap.Curved ); break; case (uint)Keywords.ID_PLANAR: _textureunit.SetEnvironmentMap( true, EnvironmentMap.Planar ); break; case (uint)Keywords.ID_CUBIC_REFLECTION: _textureunit.SetEnvironmentMap( true, EnvironmentMap.Reflection ); break; case (uint)Keywords.ID_CUBIC_NORMAL: _textureunit.SetEnvironmentMap( true, EnvironmentMap.Normal ); break; default: compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, prop.Values[ 0 ].Value + " is not a valid argument (must be \"off\", \"spherical\", \"planar\", \"cubic_reflection\", or \"cubic_normal\")" ); break; } } else { compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, prop.Values[ 0 ].Value + " is not a valid argument (must be \"off\", \"spherical\", \"planar\", \"cubic_reflection\", or \"cubic_normal\")" ); } } break; #endregion ID_ENV_MAP #region ID_SCROLL case Keywords.ID_SCROLL: if ( prop.Values.Count == 0 ) { compiler.AddError( CompileErrorCode.NumberExpected, prop.File, prop.Line ); } else if ( prop.Values.Count > 2 ) { compiler.AddError( CompileErrorCode.FewerParametersExpected, prop.File, prop.Line, "scroll must have at most 2 arguments" ); } else { AbstractNode i0 = getNodeAt( prop.Values, 0 ), i1 = getNodeAt( prop.Values, 1 ); Real x, y; if ( getReal( i0, out x ) && getReal( i1, out y ) ) _textureunit.SetTextureScroll( x, y ); else compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, i0.Value + " and/or " + i1.Value + " is invalid; both must be numbers" ); } break; #endregion ID_SCROLL #region ID_SCROLL_ANIM case Keywords.ID_SCROLL_ANIM: if ( prop.Values.Count == 0 ) { compiler.AddError( CompileErrorCode.NumberExpected, prop.File, prop.Line ); } else if ( prop.Values.Count > 2 ) { compiler.AddError( CompileErrorCode.FewerParametersExpected, prop.File, prop.Line, "scroll_anim must have at most 2 arguments" ); } else { AbstractNode i0 = getNodeAt( prop.Values, 0 ), i1 = getNodeAt( prop.Values, 1 ); Real x, y; if ( getReal( i0, out x ) && getReal( i1, out y ) ) _textureunit.SetScrollAnimation( x, y ); else compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, i0.Value + " and/or " + i1.Value + " is invalid; both must be numbers" ); } break; #endregion ID_SCROLL_ANIM #region ID_ROTATE case Keywords.ID_ROTATE: if ( prop.Values.Count == 0 ) { compiler.AddError( CompileErrorCode.NumberExpected, prop.File, prop.Line ); } else if ( prop.Values.Count > 1 ) { compiler.AddError( CompileErrorCode.FewerParametersExpected, prop.File, prop.Line, "rotate must have at most 1 argument" ); } else { Real angle; if ( getReal( prop.Values[ 0 ], out angle ) ) #warning check this statement //mUnit->setTextureRotate(Degree(angle)); _textureunit.SetTextureRotate( angle ); else compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, prop.Values[ 0 ].Value + " is not a valid number value" ); } break; #endregion ID_ROTATE #region ID_ROTATE_ANIM case Keywords.ID_ROTATE_ANIM: if ( prop.Values.Count == 0 ) { compiler.AddError( CompileErrorCode.NumberExpected, prop.File, prop.Line ); } else if ( prop.Values.Count > 1 ) { compiler.AddError( CompileErrorCode.FewerParametersExpected, prop.File, prop.Line, "rotate_anim must have at most 1 argument" ); } else { Real angle; if ( getReal( prop.Values[ 0 ], out angle ) ) _textureunit.SetRotateAnimation( angle ); else compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, prop.Values[ 0 ].Value + " is not a valid number value" ); } break; #endregion ID_ROTATE_ANIM #region ID_SCALE case Keywords.ID_SCALE: if ( prop.Values.Count == 0 ) { compiler.AddError( CompileErrorCode.NumberExpected, prop.File, prop.Line ); } else if ( prop.Values.Count > 2 ) { compiler.AddError( CompileErrorCode.FewerParametersExpected, prop.File, prop.Line, "scale must have at most 2 arguments" ); } else { AbstractNode i0 = getNodeAt( prop.Values, 0 ), i1 = getNodeAt( prop.Values, 1 ); Real x, y; if ( getReal( i0, out x ) && getReal( i1, out y ) ) _textureunit.SetTextureScale( x, y ); else compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, "first and second arguments must both be valid number values (received " + i0.Value + ", " + i1.Value + ")" ); } break; #endregion ID_SCALE #region ID_WAVE_XFORM case Keywords.ID_WAVE_XFORM: if ( prop.Values.Count == 0 ) { compiler.AddError( CompileErrorCode.NumberExpected, prop.File, prop.Line ); } else if ( prop.Values.Count > 6 ) { compiler.AddError( CompileErrorCode.FewerParametersExpected, prop.File, prop.Line, "wave_xform must have at most 6 arguments" ); } else { AbstractNode i0 = getNodeAt( prop.Values, 0 ), i1 = getNodeAt( prop.Values, 1 ), i2 = getNodeAt( prop.Values, 2 ), i3 = getNodeAt( prop.Values, 3 ), i4 = getNodeAt( prop.Values, 4 ), i5 = getNodeAt( prop.Values, 5 ); if ( i0 is AtomAbstractNode && i1 is AtomAbstractNode && i2 is AtomAbstractNode && i3 is AtomAbstractNode && i4 is AtomAbstractNode && i5 is AtomAbstractNode ) { AtomAbstractNode atom0 = (AtomAbstractNode)i0, atom1 = (AtomAbstractNode)i1; TextureTransform type = TextureTransform.Rotate; WaveformType wave = WaveformType.Sine; Real baseVal = 0.0f, freq = 0.0f, phase = 0.0f, amp = 0.0f; switch ( (Keywords)atom0.Id ) { case Keywords.ID_SCROLL_X: type = TextureTransform.TranslateU; break; case Keywords.ID_SCROLL_Y: type = TextureTransform.TranslateV; break; case Keywords.ID_SCALE_X: type = TextureTransform.ScaleU; break; case Keywords.ID_SCALE_Y: type = TextureTransform.ScaleV; break; case Keywords.ID_ROTATE: type = TextureTransform.Rotate; break; default: compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, atom0.Value + " is not a valid transform type (must be \"scroll_x\", \"scroll_y\", \"scale_x\", \"scale_y\", or \"rotate\")" ); break; } switch ( (Keywords)atom1.Id ) { case Keywords.ID_SINE: wave = WaveformType.Sine; break; case Keywords.ID_TRIANGLE: wave = WaveformType.Triangle; break; case Keywords.ID_SQUARE: wave = WaveformType.Square; break; case Keywords.ID_SAWTOOTH: wave = WaveformType.Sawtooth; break; case Keywords.ID_INVERSE_SAWTOOTH: wave = WaveformType.InverseSawtooth; break; default: compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, atom1.Value + " is not a valid waveform type (must be \"sine\", \"triangle\", \"square\", \"sawtooth\", or \"inverse_sawtooth\")" ); break; } if ( !getReal( i2, out baseVal ) || !getReal( i3, out freq ) || !getReal( i4, out phase ) || !getReal( i5, out amp ) ) compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, "arguments 3, 4, 5, and 6 must be valid numbers; received " + i2.Value + ", " + i3.Value + ", " + i4.Value + ", " + i5.Value ); _textureunit.SetTransformAnimation( type, wave, baseVal, freq, phase, amp ); } else { compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line ); } } break; #endregion ID_WAVE_XFORM #region ID_TRANSFORM case Keywords.ID_TRANSFORM: { throw new NotImplementedException(); #if UNREACHABLE_CODE Matrix4 m; if ( getMatrix4( prop.Values, 0, out m ) ) { /*mUnit->setTextureTransform(m);*/ } else compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line ); } break; #else } #endif #endregion ID_TRANSFORM #region ID_BINDING_TYPE case Keywords.ID_BINDING_TYPE: if ( prop.Values.Count == 0 ) { compiler.AddError( CompileErrorCode.NumberExpected, prop.File, prop.Line ); } else if ( prop.Values.Count > 1 ) { compiler.AddError( CompileErrorCode.FewerParametersExpected, prop.File, prop.Line, "binding_type 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_VERTEX: _textureunit.BindingType = TextureBindingType.Vertex; break; case Keywords.ID_FRAGMENT: _textureunit.BindingType = TextureBindingType.Fragment; break; default: compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, atom.Value + " is not a valid binding type (must be \"vertex\" or \"fragment\")" ); break; } } else { compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, prop.Values[ 0 ].Value + " is not a valid binding type" ); } } break; #endregion ID_BINDING_TYPE #region ID_CONTENT_TYPE case Keywords.ID_CONTENT_TYPE: 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, "content_type must have at most 4 arguments" ); } else { if ( prop.Values[ 0 ] is AtomAbstractNode ) { throw new NotImplementedException(); #if UNREACHABLE_CODE AtomAbstractNode atom = (AtomAbstractNode)prop.Values[ 0 ]; switch ( (Keywords)atom.Id ) { case Keywords.ID_NAMED: //mUnit->setContentType(TextureUnitState::CONTENT_NAMED); break; case Keywords.ID_SHADOW: //mUnit->setContentType(TextureUnitState::CONTENT_SHADOW); break; case Keywords.ID_COMPOSITOR: //mUnit->setContentType(TextureUnitState::CONTENT_COMPOSITOR); if ( prop.Values.Count >= 3 ) { string compositorName; getString( getNodeAt( prop.Values, 1 ), out compositorName ); string textureName; getString( getNodeAt( prop.Values, 2 ), out textureName ); if ( prop.Values.Count == 4 ) { uint mrtIndex; getUInt( getNodeAt( prop.Values, 3 ), out mrtIndex ); //mUnit->setCompositorReference(compositorName, textureName, mrtIndex); } else { //mUnit->setCompositorReference(compositorName, textureName); } } else { compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, "content_type compositor must have an additional 2 or 3 parameters" ); } break; default: compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, atom.Value + " is not a valid content type (must be \"named\" or \"shadow\" or \"compositor\")" ); break; } #endif } else { compiler.AddError( CompileErrorCode.InvalidParameters, prop.File, prop.Line, prop.Values[ 0 ].Value + " is not a valid content type" ); } } break;
public virtual void WriteInstance( MaterialSerializer ser, SubRenderState subRenderState, TextureUnitState srcTextureUnit, TextureUnitState dstTextureUnit ) { }