virtual void Reload() { Unload(); CVFSFile vertexFile; if (vertexFile.Load(g_VFS, m_VertexFile) != PSRETURN_OK) return; CVFSFile fragmentFile; if (fragmentFile.Load(g_VFS, m_FragmentFile) != PSRETURN_OK) return; CPreprocessorWrapper preprocessor; preprocessor.AddDefines(m_Defines); #if CONFIG2_GLES // GLES defines the macro "GL_ES" in its GLSL preprocessor, // but since we run our own preprocessor first, we need to explicitly // define it here preprocessor.AddDefine("GL_ES", "1"); #endif CStr vertexCode = preprocessor.Preprocess(vertexFile.GetAsString()); CStr fragmentCode = preprocessor.Preprocess(fragmentFile.GetAsString()); #if CONFIG2_GLES // Ugly hack to replace desktop GLSL 1.10/1.20 with GLSL ES 1.00, // and also to set default float precision for fragment shaders vertexCode.Replace("#version 110\n", "#version 100\n"); vertexCode.Replace("#version 110\r\n", "#version 100\n"); vertexCode.Replace("#version 120\n", "#version 100\n"); vertexCode.Replace("#version 120\r\n", "#version 100\n"); fragmentCode.Replace("#version 110\n", "#version 100\nprecision mediump float;\n"); fragmentCode.Replace("#version 110\r\n", "#version 100\nprecision mediump float;\n"); fragmentCode.Replace("#version 120\n", "#version 100\nprecision mediump float;\n"); fragmentCode.Replace("#version 120\r\n", "#version 100\nprecision mediump float;\n"); #endif if (!Compile(m_VertexShader, m_VertexFile, vertexCode)) return; if (!Compile(m_FragmentShader, m_FragmentFile, fragmentCode)) return; if (!Link()) return; m_IsValid = true; }
CMaterial CMaterialManager::LoadMaterial(const VfsPath& pathname) { if (pathname.empty()) return CMaterial(); std::map<VfsPath, CMaterial>::iterator iter = m_Materials.find(pathname); if (iter != m_Materials.end()) return iter->second; CXeromyces xeroFile; if (xeroFile.Load(g_VFS, pathname, "material") != PSRETURN_OK) return CMaterial(); #define EL(x) int el_##x = xeroFile.GetElementID(#x) #define AT(x) int at_##x = xeroFile.GetAttributeID(#x) EL(alpha_blending); EL(alternative); EL(define); EL(shader); EL(uniform); EL(renderquery); EL(required_texture); EL(conditional_define); AT(effect); AT(if); AT(define); AT(quality); AT(material); AT(name); AT(value); AT(type); AT(min); AT(max); AT(conf); #undef AT #undef EL CMaterial material; XMBElement root = xeroFile.GetRoot(); CPreprocessorWrapper preprocessor; preprocessor.AddDefine("CFG_FORCE_ALPHATEST", g_Renderer.m_Options.m_ForceAlphaTest ? "1" : "0"); CVector4D vec(qualityLevel,0,0,0); material.AddStaticUniform("qualityLevel", vec); XERO_ITER_EL(root, node) { int token = node.GetNodeName(); XMBAttributeList attrs = node.GetAttributes(); if (token == el_alternative) { CStr cond = attrs.GetNamedItem(at_if); if (cond.empty() || !preprocessor.TestConditional(cond)) { cond = attrs.GetNamedItem(at_quality); if (cond.empty()) continue; else { if (cond.ToFloat() <= qualityLevel) continue; } } material = LoadMaterial(VfsPath("art/materials") / attrs.GetNamedItem(at_material).FromUTF8()); break; } else if (token == el_alpha_blending) { material.SetUsesAlphaBlending(true); } else if (token == el_shader) { material.SetShaderEffect(attrs.GetNamedItem(at_effect)); } else if (token == el_define) { material.AddShaderDefine(CStrIntern(attrs.GetNamedItem(at_name)), CStrIntern(attrs.GetNamedItem(at_value))); } else if (token == el_conditional_define) { std::vector<float> args; CStr type = attrs.GetNamedItem(at_type).c_str(); int typeID = -1; if (type == CStr("draw_range")) { typeID = DCOND_DISTANCE; float valmin = -1.0f; float valmax = -1.0f; CStr conf = attrs.GetNamedItem(at_conf); if (!conf.empty()) { CFG_GET_VAL("materialmgr." + conf + ".min", valmin); CFG_GET_VAL("materialmgr." + conf + ".max", valmax); } else { CStr dmin = attrs.GetNamedItem(at_min); if (!dmin.empty()) valmin = attrs.GetNamedItem(at_min).ToFloat(); CStr dmax = attrs.GetNamedItem(at_max); if (!dmax.empty()) valmax = attrs.GetNamedItem(at_max).ToFloat(); } args.push_back(valmin); args.push_back(valmax); if (valmin >= 0.0f) { std::stringstream sstr; sstr << valmin; material.AddShaderDefine(CStrIntern(conf + "_MIN"), CStrIntern(sstr.str())); } if (valmax >= 0.0f) { std::stringstream sstr; sstr << valmax; material.AddShaderDefine(CStrIntern(conf + "_MAX"), CStrIntern(sstr.str())); } } material.AddConditionalDefine(attrs.GetNamedItem(at_name).c_str(), attrs.GetNamedItem(at_value).c_str(), typeID, args); } else if (token == el_uniform) { std::stringstream str(attrs.GetNamedItem(at_value)); CVector4D vec; str >> vec.X >> vec.Y >> vec.Z >> vec.W; material.AddStaticUniform(attrs.GetNamedItem(at_name).c_str(), vec); }