/* ----------------------------------------------------------------------------- GSFramework Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. ----------------------------------------------------------------------------- */ #include "core/shader.h" #include "metafile/nml.h" #include "filesystem/filesystem.h" #include "platform.h" using namespace GS; using namespace GS::Core; using namespace GS::NML; //------------------------------------------------------------------------------ bool Shader::AddISLSection(const char *uri) { File isl_file; if (!Parser::Load(uri, isl_file)) return false; // Declare inputs. ParseInputTag(isl_file.GetTag("Shader:Input;")); ParseVaryingTag(isl_file.GetTag("Shader:Varying;")); // Append vertex & fragment programs. bool r = true; if (Tag *t = isl_file.GetTypedTag("Shader:Vertex;", Variant::VariantString)) { Array data; if ((r &= Platform::Get().io->FileLoad(t->GetString(), data)) != false) vertex += String(data.c_ptr(), data.GetSize()); } if (Tag *t = isl_file.GetTypedTag("Shader:Fragment;", Variant::VariantString)) { Array data; if ((r &= Platform::Get().io->FileLoad(t->GetString(), data)) != false) pixel += String(data.c_ptr(), data.GetSize()); } return r; } //------------------------------------------------------------------------------ //------------------------------------------------------------------------------ bool Shader::Clone(Shader &clone) const { // TODO make something faster... please. AutoPtr tag(AsMetaTag()); clone.name = name; return clone.FromMetaTag(*tag); } //------------------------------------------------------------------------------ //------------------------------------------------------------------------------ void Shader::Define(const char *def, ShaderInput::Scope scope) { String directive = String::Format("#define %s\n", def); if (scope & ShaderInput::Vertex) vertex_decl = directive + vertex_decl; if (scope & ShaderInput::Pixel) pixel_decl = directive + pixel_decl; } ShaderVarying *Shader::DeclareVarying(const char *name, const char *type) { ShaderVarying *varying = new ShaderVarying; if (!varying) return NULL; varying_list.Add(varying); varying->name = name; varying->type = type; return varying; } //------------------------------------------------------------------------------ //------------------------------------------------------------------------------ ShaderInput *Shader::GetInput(ShaderInput::Semantic semantic) const { ListForeachPtr(ShaderInput *, input, input_list) if (input->semantic == semantic) return input; return NULL; } //------------------------------------------------------------------------------ //------------------------------------------------------------------------------ ShaderInput *Shader::DeclareInput(const char *name, ShaderInput::DataType data_type, ShaderInput::Semantic semantic, ShaderInput::Type parm_type, ShaderInput::Scope parm_scope, uint array_size) { // Catch duplicates. ShaderInput *input = NULL; switch (semantic) { case ShaderInput::Position: case ShaderInput::Normal: case ShaderInput::UV0: case ShaderInput::UV1: case ShaderInput::UV2: case ShaderInput::Tangent: case ShaderInput::Bitangent: case ShaderInput::BoneIndex: case ShaderInput::BoneWeight: ListForeachPtr(ShaderInput *, p, input_list) if (p->semantic == semantic) { input = p; break; } break; default: ListForeachPtr(ShaderInput *, p, input_list) if ((p->name == name) && (p->semantic == semantic)) { input = p; break; } break; } // Equivalent input found. if (input) { input->scope |= parm_scope; // Merge scopes. return input; } // Create a new input. if ((input = new ShaderInput) == NULL) return NULL; input_list.Add(input); input->name = name; input->semantic = semantic; input->type = parm_type; input->data_type = data_type; input->scope = parm_scope; input->array_size = array_size; input->parm_v.Set(0, 0, 0); return input; } //------------------------------------------------------------------------------ //------------------------------------------------------------------------------ void Shader::Clear() { input_list.Clear(); varying_list.Clear(); geometry_decl.Clear(); vertex_decl.Clear(); pixel_decl.Clear(); geometry.Clear(); vertex.Clear(); pixel.Clear(); } //------------------------------------------------------------------------------ Shader::Shader(const char *n, const char *v, const char *f, const char *g) { name = n; vertex = v; pixel = f; geometry = g; }