Axiom.SceneManagers.Bsp.Quake3Shader.CreateAsMaterial C# (CSharp) Method

CreateAsMaterial() public method

Creates this shader as an OGRE material.
Creates a new material based on this shaders settings and registers it with the SceneManager passed in. Material name is in the format of: shader#lightmap.
public CreateAsMaterial ( int lightmapNumber ) : Material
lightmapNumber int Lightmap number
return Axiom.Graphics.Material
		public Material CreateAsMaterial( int lightmapNumber )
		{
			string materialName = String.Format( "{0}#{1}", Name, lightmapNumber );
			string groupName = ResourceGroupManager.Instance.WorldResourceGroupName;

			Material material = (Material)MaterialManager.Instance.Create( materialName, groupName );
			Pass pass = material.GetTechnique( 0 ).GetPass( 0 );

			LogManager.Instance.Write( "Using Q3 shader {0}", Name );

			for ( int p = 0; p < _pass.Count; ++p )
			{
				TextureUnitState t;

				// Create basic texture
				if ( _pass[ p ].textureName == "$lightmap" )
				{
					string lightmapName = String.Format( "@lightmap{0}", lightmapNumber );
					t = pass.CreateTextureUnitState( lightmapName );
				}

				// Animated texture support
				else if ( _pass[ p ].animNumFrames > 0 )
				{
					float sequenceTime = _pass[ p ].animNumFrames / _pass[ p ].animFps;

					/* Pre-load textures
					We need to know if each one was loaded OK since extensions may change for each
					Quake3 can still include alternate extension filenames e.g. jpg instead of tga
					Pain in the arse - have to check for each frame as letters<n>.tga for example
					is different per frame!
					*/
					for ( uint alt = 0; alt < _pass[ p ].animNumFrames; ++alt )
					{
						if ( !ResourceGroupManager.Instance.ResourceExists( groupName, _pass[ p ].frames[ alt ] ) )
						{
							// Try alternate extension
							_pass[ p ].frames[ alt ] = GetAlternateName( _pass[ p ].frames[ alt ] );

							if ( !ResourceGroupManager.Instance.ResourceExists( groupName, _pass[ p ].frames[ alt ] ) )
							{
								// stuffed - no texture
								continue;
							}
						}

					}

					t = pass.CreateTextureUnitState( "" );
					t.SetAnimatedTextureName( _pass[ p ].frames, _pass[ p ].animNumFrames, sequenceTime );

					if ( t.IsBlank )
					{
						for ( int alt = 0; alt < _pass[ p ].animNumFrames; alt++ )
							_pass[ p ].frames[ alt ] = GetAlternateName( _pass[ p ].frames[ alt ] );

						t.SetAnimatedTextureName( _pass[ p ].frames, _pass[ p ].animNumFrames, sequenceTime );
					}
				}
				else
				{
					// Quake3 can still include alternate extension filenames e.g. jpg instead of tga
					// Pain in the arse - have to check for failure
					if ( !ResourceGroupManager.Instance.ResourceExists( groupName, _pass[ p ].textureName ) )
					{
						// Try alternate extension
						_pass[ p ].textureName = GetAlternateName( _pass[ p ].textureName );

						if ( !ResourceGroupManager.Instance.ResourceExists( groupName, _pass[ p ].textureName ) )
						{
							// stuffed - no texture
							continue;
						}
					}

					t = pass.CreateTextureUnitState( _pass[ p ].textureName );
				}

				// Blending
				if ( p == 0 )
				{
					// scene blend
					material.SetSceneBlending( _pass[ p ].blendSrc, _pass[ p ].blendDest );

					if ( material.IsTransparent && ( _pass[ p ].blendSrc != SceneBlendFactor.SourceAlpha ) )
						material.DepthWrite = false;

					t.SetColorOperation( LayerBlendOperation.Replace );

					// Alpha Settings
					pass.SetAlphaRejectSettings( _pass[ p ].alphaFunc, _pass[ p ].alphaVal );
				}
				else
				{
					if ( _pass[ p ].customBlend )
					{
						// Fallback for now
						t.SetColorOperation( LayerBlendOperation.Modulate );
					}
					else
					{
						t.SetColorOperation( _pass[ p ].blend );
					}

					// Alpha mode, prefer 'most alphary'
					CompareFunction currFunc = pass.AlphaRejectFunction;
					int currValue = pass.AlphaRejectValue;
					if ( _pass[ p ].alphaFunc > currFunc
						|| ( _pass[ p ].alphaFunc == currFunc && _pass[ p ].alphaVal < currValue ) )
					{
						pass.SetAlphaRejectSettings( _pass[ p ].alphaFunc, _pass[ p ].alphaVal );
					}
				}

				// Tex coords
				if ( _pass[ p ].texGen == ShaderTextureGen.Base )
					t.TextureCoordSet = 0;
				else if ( _pass[ p ].texGen == ShaderTextureGen.Lightmap )
					t.TextureCoordSet = 1;
				else if ( _pass[ p ].texGen == ShaderTextureGen.Environment )
					t.SetEnvironmentMap( true, EnvironmentMap.Planar );

				// Tex mod
				// Scale
				t.SetTextureScaleU( _pass[ p ].tcModScale[ 0 ] );
				t.SetTextureScaleV( _pass[ p ].tcModScale[ 1 ] );

				// 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 ] );
					}
				}
				// Address mode
                t.SetTextureAddressingMode( _pass[ p ].addressMode );

			}

			// Do farbox (create new material)

			// Do skydome (use this material)
			//if ( _skyDome )
			//{
			//    float halfAngle = 0.5f * ( 0.5f * ( 4.0f * (float)System.Math.Atan( 1.0f ) ) );
			//    float sin = (float)Utility.Sin( halfAngle );

			//    // Quake3 is always aligned with Z upwards
			//    Quaternion q = new Quaternion(
			//        (float)Utility.Cos( halfAngle ),
			//        sin * Vector3.UnitX.x,
			//        sin * Vector3.UnitY.y,
			//        sin * Vector3.UnitX.z
			//        );

			//    // Also draw last, and make close to camera (far clip plane is shorter)
			//    sm.SetSkyDome( true, materialName, 20 - ( _cloudHeight / 256 * 18 ), 12, 2000, false, q );
			//}

			material.CullingMode = Axiom.Graphics.CullingMode.None;
			material.ManualCullingMode = _cullingMode;
			material.Lighting = false;
			material.Load();

			return material;
		}
		#endregion Methods

Usage Example

Beispiel #1
0
        private void CreateShaderMaterials(Quake3Level q3lvl, SceneManager sm)
        {
            // NB this only works for the 'default' shaders for now
            // i.e. those that don't have a .shader script and thus default
            // to just texture + lightmap
            // TODO: pre-parse all .shader files and create lookup for next stage (use ROGL shader_file_t)

            // Material names are shadername#lightmapnumber
            // This is because I like to define materials up front completely
            // rather than combine lightmap and shader dynamically (it's
            // more generic). It results in more materials, but they're small
            // beer anyway. Texture duplication is prevented by infrastructure.
            // To do this I actually need to parse the faces since they have the
            // shader/lightmap combo (lightmap number is not in the shader since
            // it can be used with multiple lightmaps)
            string shaderName;
            int    face = q3lvl.Faces.Length;

            while (face-- > 0)
            {
                // Check to see if existing material
                // Format shader#lightmap
                int shadIdx = q3lvl.Faces[face].shader;

                shaderName = String.Format("{0}#{1}", q3lvl.Shaders[shadIdx].name, q3lvl.Faces[face].lmTexture);
                Material shadMat = sm.GetMaterial(shaderName);

                if (shadMat == null && !bspOptions.useLightmaps)
                {
                    // try the no-lightmap material
                    shaderName = String.Format("{0}#n", q3lvl.Shaders[shadIdx].name);
                    shadMat    = sm.GetMaterial(shaderName);
                }

                if (shadMat == null)
                {
                    // Colour layer
                    // NB no extension in Q3A(doh), have to try shader, .jpg, .tga
                    string tryName = q3lvl.Shaders[shadIdx].name;

                    // Try shader first
                    Quake3Shader shader = (Quake3Shader)Quake3ShaderManager.Instance.GetByName(tryName);

                    if (shader != null)
                    {
                        shadMat = shader.CreateAsMaterial(sm, q3lvl.Faces[face].lmTexture);
                    }
                    else
                    {
                        // No shader script, try default type texture
                        shadMat = sm.CreateMaterial(shaderName);
                        Pass shadPass = shadMat.GetTechnique(0).GetPass(0);

                        // Try jpg
                        TextureUnitState tex = shadPass.CreateTextureUnitState(tryName + ".jpg");
                        tex.Load();

                        if (tex.IsBlank)
                        {
                            // Try tga
                            tex.SetTextureName(tryName + ".tga");
                        }

                        // Set replace on all first layer textures for now
                        tex.SetColorOperation(LayerBlendOperation.Replace);
                        tex.TextureAddressing = TextureAddressing.Wrap;

                        // for ambient lighting
                        tex.ColorBlendMode.source2 = LayerBlendSource.Manual;

                        if (bspOptions.useLightmaps && q3lvl.Faces[face].lmTexture != -1)
                        {
                            // Add lightmap, additive blending
                            tex = shadPass.CreateTextureUnitState(String.Format("@lightmap{0}", q3lvl.Faces[face].lmTexture));

                            // Blend
                            tex.SetColorOperation(LayerBlendOperation.Modulate);

                            // Use 2nd texture co-ordinate set
                            tex.TextureCoordSet = 1;

                            // Clamp
                            tex.TextureAddressing = TextureAddressing.Clamp;
                        }

                        shadMat.CullingMode = CullingMode.None;
                        shadMat.Lighting    = false;
                    }
                }

                shadMat.Load();

                // Copy face data
                BspStaticFaceGroup dest = CopyShaderFaceData(q3lvl, face, shadMat, shadIdx);

                faceGroups[face] = dest;
            }
        }