172 lines
4.5 KiB
C++
172 lines
4.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"
|
|
|
|
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 <char> 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 <char> 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> 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;
|
|
}
|