public void BuildMaterialPasses(PageDecalInfo pageInfo) { Technique t = FindPageTechnique(pageInfo.Coord); if (t != null) { float pageX = pageInfo.Coord.X * TerrainManager.Instance.PageSize * TerrainManager.oneMeter; float pageZ = pageInfo.Coord.Z * TerrainManager.Instance.PageSize * TerrainManager.oneMeter; int availableTexUnits = 0; int curTexUnit = 0; int texUnitsPerPass = 8; Pass p = null; foreach (DecalElement element in pageInfo.Decals) { // if there are no texture units available, allocate a new pass if (availableTexUnits == 0) { p = t.CreatePass(); pageInfo.Passes.Add(p); p.SetSceneBlending(SceneBlendType.TransparentAlpha); // TODO: Unclear what should happen here. The new Ogre interface // supports SetDepthBias(constantBias, slopeBias), but the units are // different. Ask Jeff. p.DepthBias = 1; curTexUnit = 0; availableTexUnits = texUnitsPerPass; } TextureUnitState texUnit = p.CreateTextureUnitState(element.ImageName, 0); if (curTexUnit == 0) { texUnit.SetColorOperation(LayerBlendOperation.Replace); texUnit.SetAlphaOperation(LayerBlendOperationEx.Source1, LayerBlendSource.Texture, LayerBlendSource.Current, 0, 0, 0); } else { texUnit.SetColorOperation(LayerBlendOperation.AlphaBlend); texUnit.SetAlphaOperation(LayerBlendOperationEx.AddSmooth, LayerBlendSource.Texture, LayerBlendSource.Current, 0, 0, 0); } texUnit.TextureAddressing = TextureAddressing.Border; texUnit.TextureBorderColor = new ColorEx(0, 0, 0, 0); element.UpdateTextureTransform(texUnit, pageX, pageZ); // bump the counts curTexUnit++; availableTexUnits--; } } }
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; } }