Files
Webcam/include/engine/core/shader_nml.cpp

273 lines
7.5 KiB
C++

/* -----------------------------------------------------------------------------
GSFramework
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
----------------------------------------------------------------------------- */
#include "core/shader.h"
#include "metafile/nml.h"
#include "filesystem/filesystem.h"
#include "platform.h"
#include "log/log.h"
using namespace GS::Core;
using GS::NML::Tag;
//------------------------------------------------------------------------------
void Shader::ParseVaryingTag(Tag *tag)
{
if (!tag || tag->name != "Varying")
return;
NMLTagForeach(it, *tag)
if (it->name == "Variable")
{
Tag *t_name = it->GetTypedTag("Name", Variant::VariantString),
*t_type = it->GetTypedTag("Type", Variant::VariantString);
if (t_name && t_type)
DeclareVarying(t_name->GetString(), t_type->GetString());
}
}
void Shader::ParseInputTag(Tag *tag)
{
if (!tag || tag->name != "Input")
return;
NMLTagForeach(it, *tag)
{
ShaderInput::Type type = ShaderInput::None;
uint scope = 0;
// Parse shader input.
if (it->name == "Attribute")
{
type = ShaderInput::Attribute;
scope = ShaderInput::Vertex;
}
else if (it->name == "Uniform")
{
type = ShaderInput::Uniform;
scope = ShaderInput::Pixel;
}
if (type != ShaderInput::None)
{
String input_name;
ShaderInput::DataType data_type = ShaderInput::NoData;
ShaderInput::Semantic semantic = ShaderInput::Constant;
if (Tag *t = it->GetTypedTag("Name", Variant::VariantString))
input_name = t->GetString();
if (Tag *t = it->GetTypedTag("Semantic", Variant::VariantString))
{
String cs(t->GetString());
#if 1 // Legacy semantic support (changed with 1.3.0).
if (cs == "Texture")
cs = "Texture2D";
else if (cs == "NativeTexture")
cs = "Texture2D";
else if (cs == "CubeTexture")
cs = "TextureCube";
else if (cs == "User")
cs = "Constant";
#endif
uint n = 0;
for (; n < ShaderInput::LastSemantic; ++n)
if (cs == ShaderInput::semantic_desc[n].name)
{
semantic = (ShaderInput::Semantic)n;
data_type = ShaderInput::semantic_desc[semantic].data_type;
break;
}
if (n == ShaderInput::LastSemantic)
__LOG_E__ << "Unknown shader input semantic '" << cs << "'.\n";
}
if (Tag *t = it->GetTag("Type"))
{
String type(t->GetString());
if (type == "float") data_type = ShaderInput::Float;
else if (type == "vec2") data_type = ShaderInput::Vector2;
else if (type == "vec3") data_type = ShaderInput::Vector3;
else if (type == "vec4") data_type = ShaderInput::Vector4;
else if (type == "mat3") data_type = ShaderInput::Matrix3;
else if (type == "mat4") data_type = ShaderInput::Matrix4;
else
__LOG_E__ << "Unknown type '" << type << "' for input '" << input_name << "'.\n";
}
if (Tag *t = it->GetTag("Scope"))
{
scope = 0;
if (t->GetTag("Vertex"))
scope |= ShaderInput::Vertex;
if (t->GetTag("Pixel") || t->GetTag("Fragment"))
scope |= ShaderInput::Pixel;
}
ShaderInput *input = NULL;
if (semantic != ShaderInput::LastSemantic)
input = DeclareInput(input_name, data_type, semantic, type, (ShaderInput::Scope)scope);
else
__LOG_W__ << "Unknown shader input semantic in shader '" << name << "'.\n";
if (input)
switch (input->semantic)
{
case ShaderInput::Texture2D:
case ShaderInput::TextureCube:
if (Tag *t = it->GetTypedTag("Texture", Variant::VariantString))
input->parm_t = t->GetString();
break;
case ShaderInput::Constant:
if (Tag *t = it->GetTag("Vector"))
input->parm_v.FromMetaTag(*t);
break;
}
}
}
}
bool Shader::FromMetaTag(Tag &tag)
{
if (tag.name != "Shader")
return false;
Clear();
NMLTagForeach(pt, tag)
{
if (pt->name == "Name")
name = pt->GetString();
else if (pt->name == "Varying")
ParseVaryingTag(pt);
else if (pt->name == "Input")
ParseInputTag(pt);
else if (pt->name == "VertexDeclaration")
vertex_decl = pt->GetString();
else if (pt->name == "PixelDeclaration")
pixel_decl = pt->GetString();
else if (pt->name == "GeometryDeclaration")
geometry_decl = pt->GetString();
else if (pt->name == "VertexSource")
vertex = pt->GetString();
else if ((pt->name == "PixelSource") || (pt->name == "FragmentSource"))
pixel = pt->GetString();
else if (pt->name == "GeometrySource")
geometry = pt->GetString();
else if (pt->name == "Vertex")
{
Array <char> buffer;
if (Platform::Get().io->FileLoad(pt->GetString(), buffer))
vertex.Set(buffer, &buffer[buffer.GetCount()]);
}
else if ((pt->name == "Pixel") || (pt->name == "Fragment"))
{
Array <char> buffer;
if (Platform::Get().io->FileLoad(pt->GetString(), buffer))
pixel.Set(buffer, &buffer[buffer.GetCount()]);
}
else if (pt->name == "Geometry")
{
Array <char> buffer;
if (Platform::Get().io->FileLoad(pt->GetString(), buffer))
geometry.Set(buffer, &buffer[buffer.GetCount()]);
}
else
__LOG_W__ << "Unknown tag '" << pt->name << "' in <Shader>.\n";
}
return true;
}
Tag *Shader::AsMetaTag() const
{
Tag *root = new Tag("Shader");
if (!root)
__ERR__(__LOG_E__ << "Could not serialize shader. Failed to create root tag.\n", NULL)
if (input_list.GetCount())
if (Tag *it = root->AddChild("Input"))
ListForeachPtr(ShaderInput *, input, input_list)
{
Tag *t = NULL;
switch (input->type)
{
case ShaderInput::Attribute: t = new Tag("Attribute"); break;
case ShaderInput::Uniform: t = new Tag("Uniform"); break;
}
if (!t)
continue;
t->AddChild("Name", input->name);
t->AddChild("Semantic", ShaderInput::semantic_desc[input->semantic].name);
if (Tag *st = t->AddChild("Scope"))
{
if (input->scope & ShaderInput::Vertex)
st->AddChild("Vertex");
if (input->scope & ShaderInput::Pixel)
st->AddChild("Pixel");
if (input->scope & ShaderInput::Geometry)
st->AddChild("Geometry");
}
switch (input->semantic)
{
case ShaderInput::Constant:
switch (input->data_type)
{
case ShaderInput::Float: t->AddChild("Type", "float"); break;
case ShaderInput::Vector2: t->AddChild("Type", "vec2"); break;
case ShaderInput::Vector3: t->AddChild("Type", "vec3"); break;
case ShaderInput::Vector4: t->AddChild("Type", "vec4"); break;
case ShaderInput::Matrix3: t->AddChild("Type", "mat3"); break;
case ShaderInput::Matrix4: t->AddChild("Type", "mat4"); break;
}
t->AddChild(input->parm_v.AsMetaTag("Vector"));
break;
}
if (!input->parm_t.IsEmpty())
t->AddChild("Texture", input->parm_t.c_str());
it->AddChild(t);
}
if (varying_list.GetCount())
if (Tag *it = root->AddChild("Varying"))
ListForeachPtr(ShaderVarying *, varying, varying_list)
if (Tag *v = it->AddChild("Variable"))
{
v->AddChild("Name", varying->name);
v->AddChild("Type", varying->type);
}
if (!geometry_decl.IsEmpty())
root->AddChild("GeometryDeclaration", geometry_decl);
if (!vertex_decl.IsEmpty())
root->AddChild("VertexDeclaration", vertex_decl);
if (!pixel_decl.IsEmpty())
root->AddChild("PixelDeclaration", pixel_decl);
if (!geometry.IsEmpty())
root->AddChild("GeometrySource", geometry);
if (!vertex.IsEmpty())
root->AddChild("VertexSource", vertex);
if (!pixel.IsEmpty())
root->AddChild("PixelSource", pixel);
return root;
}
//------------------------------------------------------------------------------