Line data Source code
1 : /* Copyright (C) 2022 Wildfire Games.
2 : * This file is part of 0 A.D.
3 : *
4 : * 0 A.D. is free software: you can redistribute it and/or modify
5 : * it under the terms of the GNU General Public License as published by
6 : * the Free Software Foundation, either version 2 of the License, or
7 : * (at your option) any later version.
8 : *
9 : * 0 A.D. is distributed in the hope that it will be useful,
10 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 : * GNU General Public License for more details.
13 : *
14 : * You should have received a copy of the GNU General Public License
15 : * along with 0 A.D. If not, see <http://www.gnu.org/licenses/>.
16 : */
17 :
18 : #include "precompiled.h"
19 :
20 : #include "MaterialManager.h"
21 :
22 : #include "graphics/PreprocessorWrapper.h"
23 : #include "maths/MathUtil.h"
24 : #include "maths/Vector4D.h"
25 : #include "ps/CLogger.h"
26 : #include "ps/ConfigDB.h"
27 : #include "ps/CStrInternStatic.h"
28 : #include "ps/Filesystem.h"
29 : #include "ps/XML/Xeromyces.h"
30 : #include "renderer/RenderingOptions.h"
31 :
32 : #include <sstream>
33 :
34 6 : CMaterialManager::CMaterialManager()
35 : {
36 6 : qualityLevel = 5.0;
37 6 : CFG_GET_VAL("materialmgr.quality", qualityLevel);
38 6 : qualityLevel = Clamp(qualityLevel, 0.0f, 10.0f);
39 :
40 6 : if (VfsDirectoryExists(L"art/materials/") && !CXeromyces::AddValidator(g_VFS, "material", "art/materials/material.rng"))
41 0 : LOGERROR("CMaterialManager: failed to load grammar file 'art/materials/material.rng'");
42 6 : }
43 :
44 0 : CMaterial CMaterialManager::LoadMaterial(const VfsPath& pathname)
45 : {
46 0 : if (pathname.empty())
47 0 : return CMaterial();
48 :
49 0 : std::map<VfsPath, CMaterial>::iterator iter = m_Materials.find(pathname);
50 0 : if (iter != m_Materials.end())
51 0 : return iter->second;
52 :
53 0 : CXeromyces xeroFile;
54 0 : if (xeroFile.Load(g_VFS, pathname, "material") != PSRETURN_OK)
55 0 : return CMaterial();
56 :
57 : #define EL(x) int el_##x = xeroFile.GetElementID(#x)
58 : #define AT(x) int at_##x = xeroFile.GetAttributeID(#x)
59 0 : EL(alpha_blending);
60 0 : EL(alternative);
61 0 : EL(define);
62 0 : EL(shader);
63 0 : EL(uniform);
64 0 : EL(renderquery);
65 0 : EL(required_texture);
66 0 : AT(effect);
67 0 : AT(if);
68 0 : AT(define);
69 0 : AT(quality);
70 0 : AT(material);
71 0 : AT(name);
72 0 : AT(value);
73 : #undef AT
74 : #undef EL
75 :
76 0 : CPreprocessorWrapper preprocessor;
77 0 : CMaterial material;
78 0 : material.AddStaticUniform("qualityLevel", CVector4D(qualityLevel, 0, 0, 0));
79 :
80 0 : XMBElement root = xeroFile.GetRoot();
81 0 : XERO_ITER_EL(root, node)
82 : {
83 0 : int token = node.GetNodeName();
84 0 : XMBAttributeList attrs = node.GetAttributes();
85 0 : if (token == el_alternative)
86 : {
87 0 : CStr cond = attrs.GetNamedItem(at_if);
88 0 : if (cond.empty() || !preprocessor.TestConditional(cond))
89 : {
90 0 : cond = attrs.GetNamedItem(at_quality);
91 0 : if (cond.empty())
92 0 : continue;
93 : else
94 : {
95 0 : if (cond.ToFloat() <= qualityLevel)
96 0 : continue;
97 : }
98 : }
99 :
100 0 : material = LoadMaterial(VfsPath("art/materials") / attrs.GetNamedItem(at_material).FromUTF8());
101 0 : break;
102 : }
103 0 : else if (token == el_alpha_blending)
104 : {
105 0 : material.SetUsesAlphaBlending(true);
106 : }
107 0 : else if (token == el_shader)
108 : {
109 0 : material.SetShaderEffect(attrs.GetNamedItem(at_effect));
110 : }
111 0 : else if (token == el_define)
112 : {
113 0 : material.AddShaderDefine(CStrIntern(attrs.GetNamedItem(at_name)), CStrIntern(attrs.GetNamedItem(at_value)));
114 : }
115 0 : else if (token == el_uniform)
116 : {
117 0 : std::stringstream str(attrs.GetNamedItem(at_value));
118 0 : CVector4D vec;
119 0 : str >> vec.X >> vec.Y >> vec.Z >> vec.W;
120 0 : material.AddStaticUniform(attrs.GetNamedItem(at_name).c_str(), vec);
121 : }
122 0 : else if (token == el_renderquery)
123 : {
124 0 : material.AddRenderQuery(attrs.GetNamedItem(at_name).c_str());
125 : }
126 0 : else if (token == el_required_texture)
127 : {
128 0 : material.AddRequiredSampler(attrs.GetNamedItem(at_name));
129 0 : if (!attrs.GetNamedItem(at_define).empty())
130 0 : material.AddShaderDefine(CStrIntern(attrs.GetNamedItem(at_define)), str_1);
131 : }
132 : }
133 :
134 0 : m_Materials[pathname] = material;
135 0 : return material;
136 3 : }
|