31 template<
typename EnumType>
39 template<
int Num,
typename EnumType>
40 struct EnumeratorShortcut
46 const Enumerator<StdMeshMaterialShaderParameter::Auto> ShaderParameterAutoEnumerators[] =
51 const Enumerator<StdMeshMaterialTextureUnit::TexAddressModeType> TexAddressModeEnumerators[] =
60 const Enumerator<StdMeshMaterialTextureUnit::FilteringType> FilteringEnumerators[] =
69 const EnumeratorShortcut<3, StdMeshMaterialTextureUnit::FilteringType> FilteringShortcuts[] =
78 const Enumerator<StdMeshMaterialTextureUnit::BlendOpType> BlendOpEnumerators[] =
87 const Enumerator<StdMeshMaterialTextureUnit::BlendOpExType> BlendOpExEnumerators[] =
107 const Enumerator<StdMeshMaterialTextureUnit::BlendOpSourceType> BlendOpSourceEnumerators[] =
119 const Enumerator<StdMeshMaterialTextureUnit::Transformation::XFormType> XFormTypeEnumerators[] =
129 const Enumerator<StdMeshMaterialTextureUnit::Transformation::WaveType> WaveTypeEnumerators[] =
139 const Enumerator<StdMeshMaterialPass::CullHardwareType> CullHardwareEnumerators[] =
147 const Enumerator<StdMeshMaterialPass::SceneBlendType> SceneBlendEnumerators[] =
162 const EnumeratorShortcut<2, StdMeshMaterialPass::SceneBlendType> SceneBlendShortcuts[] =
171 const Enumerator<StdMeshMaterialPass::DepthFunctionType> DepthFunctionEnumerators[] =
216 template<
typename EnumType> EnumType
AdvanceEnum(
const Enumerator<EnumType>* enumerators);
217 template<
int Num,
typename EnumType>
void AdvanceEnums(
const Enumerator<EnumType>* enumerators, EnumType enums[Num]);
218 template<
int Num,
typename EnumType>
void AdvanceEnums(
const Enumerator<EnumType>* enumerators,
const EnumeratorShortcut<Num, EnumType>* shortcuts, EnumType enums[Num]);
239 unsigned int CurIndex{0u};
243 Line(1), Script(mat_script), Manager(manager), FileName(filename), Loader(loader)
283 const char* before =
Script;
311 const char* begin =
Script;
339 if (token != expect1 && token != expect2)
351 i = g_ascii_strtoll(buf.
getData(), &end, 10);
354 if (!(std::istringstream(buf.
getData()) >> i))
382 f = g_ascii_strtod(buf.
getData(), &end);
385 if (!(std::istringstream(buf.
getData()) >> f))
417 if (buf ==
"on")
return true;
418 if (buf ==
"off")
return false;
423 template<
typename EnumType>
429 for (
const Enumerator<EnumType>* cur = enumerators; cur->Name; ++cur)
430 if (buf == cur->Name)
437 template<
int Num,
typename EnumType>
440 for (
int i = 0; i < Num; ++i)
444 template<
int Num,
typename EnumType>
450 const Enumerator<EnumType>* cenum;
451 const EnumeratorShortcut<Num, EnumType>* cshort;
453 for (cenum = enumerators; cenum->Name; ++cenum)
454 if (buf == cenum->Name)
456 for (cshort = shortcuts; cshort->Name; ++cshort)
457 if (buf == cshort->Name)
460 if (!cenum->Name && !cshort->Name)
464 else if (!cenum->Name && cshort->Name)
466 for (
int i = 0; i < Num; ++i)
467 enums[i] = cshort->Values[i];
469 else if (cenum->Name && (!cshort->Name || Num == 1))
471 enums[0] = cenum->Value;
472 for (
int i = 1; i < Num; ++i)
478 const Enumerator<EnumType>* cenum2 =
nullptr;
482 for (cenum2 = enumerators; cenum2->Name; ++cenum2)
483 if (buf == cenum2->Name)
487 if (cenum2 && cenum2->Name)
490 enums[0] = cenum->Value;
491 for (
int i = 1; i < Num; ++i)
497 for (
int i = 0; i < Num; ++i)
498 enums[i] = cshort->Values[i];
520 template<
typename SubT>
523 std::vector<unsigned int> indices;
530 indices.push_back(CurIndex);
531 assert(CurIndex <= vec.size());
532 if(CurIndex == vec.size())
534 vec.push_back(SubT());
535 vec.back().Name.Format(
"%u", CurIndex);
542 unsigned int size_before = indices.size();
543 for(
unsigned int i = 0; i < vec.size(); ++i)
545 indices.push_back(i);
548 if(indices.size() == size_before)
550 if(std::strchr(token_name.
getData(),
'*') ==
nullptr && std::strchr(token_name.
getData(),
'?') ==
nullptr)
552 indices.push_back(vec.size());
553 vec.push_back(SubT());
554 vec.back().Name = token_name;
571 for(
unsigned int i = 0; i < indices.size()-1; ++i)
573 unsigned int old_line = ctx.
Line;
574 const char* old_pos = ctx.
Script;
575 vec[indices[i]].Load(ctx);
580 vec[indices.back()].Load(ctx);
596 if(token_name ==
"source")
603 else if(token_name ==
"syntax")
625 matrix =
new float[16];
635 Move(std::move(other));
646 if(
this == &other)
return *
this;
657 if(
this == &other)
return *
this;
662 Move(std::move(other));
669 Move(std::move(other));
695 matrix = other.matrix;
709 matrix =
new float[16];
710 for(
int i = 0; i < 16; ++i)
711 matrix[i] = other.matrix[i];
727 if(type_name ==
"int")
733 else if(type_name ==
"float")
739 else if(type_name ==
"float2")
746 else if(type_name ==
"float3")
754 else if(type_name ==
"float4")
773 param.GetAuto() = ctx.
AdvanceEnum(ShaderParameterAutoEnumerators);
785 if(token_name ==
"param_named")
791 else if(token_name ==
"param_named_auto")
814 Name(name), FragmentShader(fragment_shader), VertexShader(vertex_shader), GeometryShader(geometry_shader)
816 assert(FragmentShader !=
nullptr);
817 assert(VertexShader !=
nullptr);
827 const std::vector<StdCopyStrBuf>::const_iterator iter = std::find(ParameterNames.begin(), ParameterNames.end(), NamedParameter.first);
828 if (iter == ParameterNames.end())
830 ParameterNames.push_back(NamedParameter.first);
846 std::vector<const char*> uniformNames;
847 std::vector<const char*> attributeNames;
849 uniformNames.resize(
C4SSU_Count + ParameterNames.size() + 1);
873 for (
unsigned int i = 0; i < ParameterNames.size(); ++i)
874 uniformNames[
C4SSU_Count + i] = ParameterNames[i].getData();
875 uniformNames[
C4SSU_Count + ParameterNames.size()] =
nullptr;
890 if (ssc != 0) name.Append(
":");
891 if (ssc & C4SSC_LIGHT) name.Append(
"Light");
892 if (ssc & C4SSC_MOD2) name.Append(
"Mod2");
894 return shader.
Init(name.getData(), &uniformNames[0], &attributeNames[0]);
900 if (!CompileShader(loader, Shader, 0))
return false;
901 if (!CompileShader(loader, ShaderMod2, C4SSC_MOD2))
return false;
902 if (!CompileShader(loader, ShaderLight, C4SSC_LIGHT))
return false;
903 if (!CompileShader(loader, ShaderLightMod2, C4SSC_LIGHT | C4SSC_MOD2))
return false;
919 if(ssc & C4SSC_MOD2) index += 1;
920 if(ssc & C4SSC_LIGHT) index += 2;
923 return shaders[index];
932 std::vector<StdCopyStrBuf>::const_iterator iter = std::find(ParameterNames.begin(), ParameterNames.end(), name);
933 if(iter == ParameterNames.end())
return -1;
934 return C4SSU_Count + std::distance(ParameterNames.begin(), iter);
943 const double val = fmod(WaveXForm.Frequency * t + WaveXForm.Phase, 1.0);
944 switch (WaveXForm.Wave)
946 case W_SINE:
return WaveXForm.Base + WaveXForm.Amplitude*0.5*(1.0 + sin(val * 2.0 * M_PI));
947 case W_TRIANGLE:
if (val < 0.5)
return WaveXForm.Base + WaveXForm.Amplitude*2.0*val;
else return WaveXForm.Base + WaveXForm.Amplitude*2.0*(1.0 - val);
948 case W_SQUARE:
if (val < 0.5)
return WaveXForm.Base;
else return WaveXForm.Base + WaveXForm.Amplitude;
949 case W_SAWTOOTH:
return WaveXForm.Base + WaveXForm.Amplitude*val;
951 default: assert(
false);
return 0.0;
956 : RefCount(1), Surf(Surface), Texture(*Surface->texture)
962 assert(RefCount == 0);
967 : pTex(new
Tex(Surface))
979 if(!--pTex->RefCount)
985 if(&other ==
this)
return *
this;
987 if(!--pTex->RefCount)
1012 if (surface->Wdt != surface->Hgt)
1015 Textures.emplace_back(surface.release());
1024 if (token_name ==
"texture")
1030 else if (token_name ==
"anim_texture")
1040 const char* data = base_name.
getData();
1041 const char* sep = strrchr(data,
'.');
1042 for (
int i = 0; i < num_frames; ++i)
1046 buf.
Format(
"%.*s_%d.%s", (
int)(sep - data), data, i, sep+1);
1048 buf.
Format(
"%s_%d", data, i);
1065 else if (token_name ==
"tex_address_mode")
1069 else if (token_name ==
"tex_border_colour")
1073 else if (token_name ==
"filtering")
1081 else if (token_name ==
"colour_op")
1103 else if (token_name ==
"colour_op_ex")
1112 else if (token_name ==
"alpha_op_ex")
1121 else if (token_name ==
"scroll")
1129 else if (token_name ==
"scroll_anim")
1137 else if (token_name ==
"rotate")
1144 else if (token_name ==
"rotate_anim")
1151 else if (token_name ==
"scale")
1159 else if (token_name ==
"transform")
1163 for (
float & i : trans.Transform.M)
1167 else if (token_name ==
"wave_xform")
1171 trans.WaveXForm.XForm = ctx.
AdvanceEnum(XFormTypeEnumerators);
1172 trans.WaveXForm.Wave = ctx.
AdvanceEnum(WaveTypeEnumerators);
1196 LoadParameterRefs(fragment_instance);
1197 LoadParameterRefs(vertex_instance);
1198 LoadParameterRefs(geometry_instance);
1201 void StdMeshMaterialPass::ProgramInstance::LoadParameterRefs(
const ShaderInstance* instance)
1205 const int index =
Program->GetParameterIndex(NamedParameter.first.getData());
1206 assert(index != -1);
1208 const std::vector<ParameterRef>::const_iterator parameter_iter =
1209 std::find_if(Parameters.begin(), Parameters.end(), [index](
const ParameterRef& ref) { return ref.UniformIndex == index; });
1210 if(parameter_iter != Parameters.end())
1218 ref.Parameter = &NamedParameter.second;
1219 ref.UniformIndex = index;
1220 Parameters.push_back(ref);
1243 ShaderInstance* cur_shader;
1245 const char* shader_type_name;
1252 shader_type_name =
"fragment";
1257 shader_type_name =
"vertex";
1262 shader_type_name =
"geometry";
1269 if(cur_shader->Shader !=
nullptr)
1270 ctx.
Error(
FormatString(
"There is already a %s shader in this pass", shader_type_name));
1274 cur_shader->Shader = shader;
1275 cur_shader->Parameters.Load(ctx);
1285 if (token_name ==
"texture_unit")
1289 else if (token_name ==
"ambient")
1293 else if (token_name ==
"diffuse")
1297 else if (token_name ==
"specular")
1317 else if (token_name ==
"emissive")
1321 else if (token_name ==
"depth_check")
1325 else if (token_name ==
"depth_write")
1329 else if (token_name ==
"cull_hardware")
1333 else if (token_name ==
"scene_blend")
1337 else if (token_name ==
"scene_blend_op")
1343 else if (token_name ==
"alpha_rejection")
1349 else if (token_name ==
"alpha_to_coverage")
1353 else if (token_name ==
"colour_write")
1358 else if (token_name ==
"depth_func")
1364 else if (token_name ==
"illumination_stage")
1368 else if (token_name ==
"light_clip_planes")
1373 else if (token_name ==
"light_scissor")
1378 else if (token_name ==
"lighting")
1383 else if (token_name ==
"normalise_normals" || token_name ==
"normalize_normals")
1388 else if (token_name ==
"polygon_mode")
1394 else if (token_name ==
"shading")
1400 else if (token_name ==
"transparent_sorting")
1405 else if (token_name ==
"vertex_program_ref")
1409 else if (token_name ==
"fragment_program_ref")
1413 else if (token_name ==
"geometry_program_ref")
1434 if (token_name ==
"pass")
1436 pass_loader.
Load(ctx, Passes);
1452 for(
const auto & Pass : Passes)
1467 if (token_name ==
"technique")
1469 technique_loader.
Load(ctx, Techniques);
1471 else if (token_name ==
"receive_shadows")
1488 FragmentShaders.clear();
1489 VertexShaders.clear();
1490 GeometryShaders.clear();
1500 std::set<StdCopyStrBuf> loaded_materials;
1504 if (token_name ==
"material")
1511 std::map<StdCopyStrBuf, StdMeshMaterial>::iterator iter = Materials.find(material_name);
1512 if (iter != Materials.end())
1513 ctx.
Error(
FormatString(
"Material with name '%s' is already defined in %s:%u", material_name.
getData(), iter->second.FileName.getData(), iter->second.Line));
1529 iter = Materials.find(parent_name);
1530 if (iter == Materials.end())
1531 ctx.
Error(
StdCopyStrBuf(
"Parent material '") + parent_name +
"' does not exist (or is not yet loaded)");
1532 parent = &iter->second;
1540 mat.
Name = material_name;
1546 Materials[material_name] = mat;
1552 Materials.erase(material_name);
1553 ctx.
Error(
StdCopyStrBuf(
"No working technique for material '") + material_name +
"'");
1556 loaded_materials.insert(material_name);
1558 else if (token_name ==
"vertex_program")
1562 else if (token_name ==
"fragment_program")
1566 else if (token_name ==
"geometry_program")
1577 return loaded_materials;
1582 std::map<StdCopyStrBuf, StdMeshMaterial>::const_iterator iter = Materials.find(
StdCopyStrBuf(material_name));
1583 if (iter == Materials.end())
return nullptr;
1584 return &iter->second;
1589 if(update) update->Add(&*iter);
1592 Materials.erase(iter.iter_);
1599 if (it == Materials.end())
1601 if (update) update->Add(&it->second);
1602 Materials.erase(it);
1607 ShaderMap::const_iterator iter = FragmentShaders.find(
StdCopyStrBuf(name));
1608 if(iter == FragmentShaders.end())
return nullptr;
1609 return iter->second.get();
1614 ShaderMap::const_iterator iter = VertexShaders.find(
StdCopyStrBuf(name));
1615 if(iter == VertexShaders.end())
return nullptr;
1616 return iter->second.get();
1621 ShaderMap::const_iterator iter = GeometryShaders.find(
StdCopyStrBuf(name));
1622 if(iter == GeometryShaders.end())
return nullptr;
1623 return iter->second.get();
1628 ShaderMap* map =
nullptr;
1632 map = &FragmentShaders;
1635 map = &VertexShaders;
1638 map = &GeometryShaders;
1643 ShaderMap::iterator iter = map->find(name_buf);
1645 if(iter != map->end())
1648 if ((load_flags & SMM_ForceReload) == SMM_ForceReload)
1650 else if ((load_flags & SMM_AcceptExisting) == SMM_AcceptExisting)
1651 return iter->second.get();
1657 std::pair<ShaderMap::iterator, bool> inserted = map->insert(std::make_pair(name_buf, std::move(shader)));
1658 assert(inserted.second ==
true);
1659 iter = inserted.first;
1661 return iter->second.get();
1666 std::tuple<const StdMeshMaterialShader*, const StdMeshMaterialShader*, const StdMeshMaterialShader*> key = std::make_tuple(fragment_shader.
Shader, vertex_shader.
Shader, geometry_shader.
Shader);
1667 ProgramMap::iterator iter = Programs.find(key);
1668 if(iter == Programs.end())
1671 iter = Programs.insert(std::make_pair(key, std::move(program))).first;
1682 if(!inserted_program.
IsCompiled() || fragment_added || vertex_added || geometry_added)
1683 if(!inserted_program.
Compile(loader))
1686 return &inserted_program;
@ C4SSU_AmbientBrightness
@ C4SSU_MaterialShininess
bool DebugLogF(const char *strMessage ...)
bool SWildcardMatchEx(const char *szString, const char *szWildcard)
StdStrBuf FormatString(const char *szFmt,...)
StdMeshMatManager MeshMaterialManager
void LoadShader(StdMeshMaterialParserCtx &ctx, StdMeshMaterialShaderType type)
StdMeshMaterialShaderType
virtual bool PrepareMaterial(StdMeshMatManager &mat_manager, StdMeshMaterialLoader &loader, StdMeshMaterial &mat)=0
void AddVertexSlices(const char *szWhat, const char *szText, const char *szSource="", int iFileTime=0)
bool Init(const char *szWhat, const char **szUniforms, const char **szAttributes)
void AddFragmentSlices(const char *szWhat, const char *szText, const char *szSource="", int iFileTime=0)
void Remove(const StdStrBuf &name, class StdMeshMaterialUpdate *update)
const StdMeshMaterialShader * GetGeometryShader(const char *name) const
std::set< StdCopyStrBuf > Parse(const char *mat_script, const char *filename, StdMeshMaterialLoader &loader)
const StdMeshMaterialShader * GetVertexShader(const char *name) const
const StdMeshMaterialProgram * AddProgram(const char *name, StdMeshMaterialLoader &loader, const StdMeshMaterialPass::ShaderInstance &fragment_shader, const StdMeshMaterialPass::ShaderInstance &vertex_shader, const StdMeshMaterialPass::ShaderInstance &geometry_shader)
const StdMeshMaterial * GetMaterial(const char *material_name) const
const StdMeshMaterialShader * GetFragmentShader(const char *name) const
const StdMeshMaterialShader * AddShader(const char *filename, const char *name, const char *language, StdMeshMaterialShaderType type, const char *text, uint32_t load_flags)
StdMeshMaterialError(const StdStrBuf &message, const char *file, unsigned int line)
void Load(StdMeshMaterialParserCtx &ctx)
virtual void AddShaderSlices(C4Shader &shader, int ssc)=0
virtual StdStrBuf LoadShaderCode(const char *filename)=0
virtual C4Surface * LoadTexture(const char *filename)=0
Token AdvanceRequired(StdStrBuf &name, Token expect)
bool AdvanceIntOptional(int &value)
void Error(const StdStrBuf &message)
StdMeshMaterialLoader & Loader
void ErrorUnexpectedIdentifier(const StdStrBuf &identifier)
bool AdvanceFloatOptional(float &value)
void AdvanceColor(bool with_alpha, float Color[4])
Token AdvanceNonEOF(StdStrBuf &name)
void AdvanceEnums(const Enumerator< EnumType > *enumerators, EnumType enums[Num])
StdMeshMatManager & Manager
StdMeshMaterialParserCtx(StdMeshMatManager &manager, const char *mat_script, const char *filename, StdMeshMaterialLoader &loader)
Token Peek(StdStrBuf &name)
Token Advance(StdStrBuf &name)
void WarningNotSupported(const char *identifier)
EnumType AdvanceEnum(const Enumerator< EnumType > *enumerators)
const StdMeshMaterialProgram *const Program
ProgramInstance(const StdMeshMaterialProgram *program, const ShaderInstance *fragment_instance, const ShaderInstance *vertex_instance, const ShaderInstance *geometry_instance)
const StdMeshMaterialShader * Shader
void Load(StdMeshMaterialParserCtx &ctx)
DepthFunctionType AlphaRejectionFunction
SceneBlendType SceneBlendFactors[2]
std::shared_ptr< ProgramInstance > Program
CullHardwareType CullHardware
StdMeshMaterialShaderParameters Parameters
ShaderInstance GeometryShader
ShaderInstance FragmentShader
std::vector< StdMeshMaterialTextureUnit > TextureUnits
ShaderInstance VertexShader
float AlphaRejectionValue
StdMeshMaterialProgram(const char *name, const StdMeshMaterialShader *fragment_shader, const StdMeshMaterialShader *vertex_shader, const StdMeshMaterialShader *geometry_shader)
const C4Shader * GetShader(int ssc) const
bool Compile(StdMeshMaterialLoader &loader)
bool AddParameterNames(const StdMeshMaterialShaderParameters ¶meters)
int GetParameterIndex(const char *name) const
const StdMeshMaterialShader * GetVertexShader() const
const StdMeshMaterialShader * GetFragmentShader() const
const StdMeshMaterialShader * GetGeometryShader() const
const char * GetCode() const
const char * GetFilename() const
StdMeshMaterialShaderParameter()
StdMeshMaterialShaderParameter & operator=(const StdMeshMaterialShaderParameter &other)
~StdMeshMaterialShaderParameter()
StdMeshMaterialShaderParameter & AddParameter(const char *name, StdMeshMaterialShaderParameter::Type type)
StdMeshMaterialShaderParameters()
std::vector< std::pair< StdCopyStrBuf, StdMeshMaterialShaderParameter > > NamedParameters
void Load(StdMeshMaterialParserCtx &ctx)
StdMeshMaterialSubLoader()
void Load(StdMeshMaterialParserCtx &ctx, std::vector< SubT > &vec)
StdMeshMaterialTechnique()
void Load(StdMeshMaterialParserCtx &ctx)
TexPtr(C4Surface *Surface)
TexPtr & operator=(const TexPtr &other)
float ColorOpManualColor2[3]
BlendOpSourceType ColorOpSources[2]
float AlphaOpManualFactor
float AlphaOpManualAlpha1
void LoadTexture(StdMeshMaterialParserCtx &ctx, const char *texname)
float ColorOpManualFactor
float AlphaOpManualAlpha2
TexAddressModeType TexAddressMode
float ColorOpManualColor1[3]
FilteringType Filtering[3]
StdMeshMaterialTextureUnit()
BlendOpSourceType AlphaOpSources[2]
void Load(StdMeshMaterialParserCtx &ctx)
std::vector< Transformation > Transformations
const char * getData() const
void Format(const char *szFmt,...) GNUC_FORMAT_ATTRIBUTE_O
double GetWaveXForm(double t) const