示例#1
0
bool CShaderManager::NewProgram(const char* name, const CShaderDefines& baseDefines, CShaderProgramPtr& program)
{
    PROFILE2("loading shader");
    PROFILE2_ATTR("name: %s", name);

    if (strncmp(name, "fixed:", 6) == 0)
    {
        program = CShaderProgramPtr(CShaderProgram::ConstructFFP(name+6, baseDefines));
        if (!program)
            return false;
        program->Reload();
        return true;
    }

    VfsPath xmlFilename = L"shaders/" + wstring_from_utf8(name) + L".xml";

    CXeromyces XeroFile;
    PSRETURN ret = XeroFile.Load(g_VFS, xmlFilename);
    if (ret != PSRETURN_OK)
        return false;

#if USE_SHADER_XML_VALIDATION
    {
        TIMER_ACCRUE(tc_ShaderValidation);

        // Serialize the XMB data and pass it to the validator
        XML_Start();
        XML_SetPrettyPrint(false);
        XML_WriteXMB(XeroFile);
        bool ok = m_Validator.ValidateEncoded(wstring_from_utf8(name), XML_GetOutput());
        if (!ok)
            return false;
    }
#endif

    // Define all the elements and attributes used in the XML file
#define EL(x) int el_##x = XeroFile.GetElementID(#x)
#define AT(x) int at_##x = XeroFile.GetAttributeID(#x)
    EL(attrib);
    EL(define);
    EL(fragment);
    EL(stream);
    EL(uniform);
    EL(vertex);
    AT(file);
    AT(if);
    AT(loc);
    AT(name);
    AT(semantics);
    AT(type);
    AT(value);
#undef AT
#undef EL

    CPreprocessorWrapper preprocessor;
    preprocessor.AddDefines(baseDefines);

    XMBElement Root = XeroFile.GetRoot();

    bool isGLSL = (Root.GetAttributes().GetNamedItem(at_type) == "glsl");
    VfsPath vertexFile;
    VfsPath fragmentFile;
    CShaderDefines defines = baseDefines;
    std::map<CStrIntern, int> vertexUniforms;
    std::map<CStrIntern, CShaderProgram::frag_index_pair_t> fragmentUniforms;
    std::map<CStrIntern, int> vertexAttribs;
    int streamFlags = 0;

    XERO_ITER_EL(Root, Child)
    {
        if (Child.GetNodeName() == el_define)
        {
            defines.Add(CStrIntern(Child.GetAttributes().GetNamedItem(at_name)), CStrIntern(Child.GetAttributes().GetNamedItem(at_value)));
        }
        else if (Child.GetNodeName() == el_vertex)
        {
            vertexFile = L"shaders/" + Child.GetAttributes().GetNamedItem(at_file).FromUTF8();

            XERO_ITER_EL(Child, Param)
            {
                XMBAttributeList Attrs = Param.GetAttributes();

                CStr cond = Attrs.GetNamedItem(at_if);
                if (!cond.empty() && !preprocessor.TestConditional(cond))
                    continue;

                if (Param.GetNodeName() == el_uniform)
                {
                    vertexUniforms[CStrIntern(Attrs.GetNamedItem(at_name))] = Attrs.GetNamedItem(at_loc).ToInt();
                }
                else if (Param.GetNodeName() == el_stream)
                {
                    CStr StreamName = Attrs.GetNamedItem(at_name);
                    if (StreamName == "pos")
                        streamFlags |= STREAM_POS;
                    else if (StreamName == "normal")
                        streamFlags |= STREAM_NORMAL;
                    else if (StreamName == "color")
                        streamFlags |= STREAM_COLOR;
                    else if (StreamName == "uv0")
                        streamFlags |= STREAM_UV0;
                    else if (StreamName == "uv1")
                        streamFlags |= STREAM_UV1;
                    else if (StreamName == "uv2")
                        streamFlags |= STREAM_UV2;
                    else if (StreamName == "uv3")
                        streamFlags |= STREAM_UV3;
                }
                else if (Param.GetNodeName() == el_attrib)
                {
                    int attribLoc = ParseAttribSemantics(Attrs.GetNamedItem(at_semantics));
                    vertexAttribs[CStrIntern(Attrs.GetNamedItem(at_name))] = attribLoc;
                }
            }
        }
示例#2
0
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);
		}