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;
}
}