173 lines
5.5 KiB
C++
173 lines
5.5 KiB
C++
/* -----------------------------------------------------------------------------
|
|
GSFramework
|
|
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
|
----------------------------------------------------------------------------- */
|
|
|
|
|
|
#include "gpu/gpu_material.h"
|
|
#include "gpu/gpu_renderer.h"
|
|
#include "core/material_to_shader_tree.h"
|
|
#include "core/shader_tree_convert_static_texture_block_to_dynamic.h"
|
|
#include "core/shader_tree_to_shader.h"
|
|
#include "core/shader_tree.h"
|
|
#include "log/log.h"
|
|
|
|
using namespace GS;
|
|
using namespace GPU;
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
bool Material::ShouldReloadOnDependencyChange(const char *n) const
|
|
{ return (name == n) || (shader->GetName() == n); }
|
|
//------------------------------------------------------------------------------
|
|
|
|
//------------------------------------------------------------------------------
|
|
bool Material::LoadTextureTable(Render::ResourceFactory &rf, const Core::Material &m)
|
|
{
|
|
bool r = true;
|
|
for (uint n = 0; n < Core::Material::max_texture_stage; ++n)
|
|
{
|
|
texture_table[n] = rf.LoadTexture(m.texstage[n].t);
|
|
if (texture_table[n].IsNull())
|
|
r = false;
|
|
}
|
|
return r;
|
|
}
|
|
static bool LoadCoreShader(Render::ResourceFactory &rf, const Core::Material &m, Core::Shader &core_shader, const char *name)
|
|
{
|
|
using namespace Core;
|
|
|
|
if (name == NULL)
|
|
{
|
|
// TODO convert material to shader directly (avoid creating an AST).
|
|
ShaderTree shader_tree;
|
|
if (!MaterialToShaderTree::Convert(m, shader_tree) || !ConvertShaderTreeToShader(shader_tree, core_shader))
|
|
return false;
|
|
}
|
|
else
|
|
{
|
|
using namespace NML;
|
|
|
|
// Load shader/shader tree.
|
|
File file;
|
|
if (!Parser::Load(name, file))
|
|
return false;
|
|
|
|
if (Tag *tag = file.GetTag("Shader"))
|
|
{
|
|
if (!core_shader.FromMetaTag(*tag))
|
|
return false;
|
|
core_shader.name = m.shader;
|
|
}
|
|
else if (Tag *tag = file.GetTag("ShaderMap"))
|
|
{
|
|
ShaderTree shader_tree;
|
|
if (!shader_tree.FromMetaTag(*tag))
|
|
return false;
|
|
|
|
ConvertStaticToDynamicTextureBlocks(shader_tree, m);
|
|
|
|
if (!ConvertShaderTreeToShader(shader_tree, core_shader))
|
|
return false;
|
|
}
|
|
else
|
|
__ERR__(__LOG_E__ << "No shader or shader tree definition found in '" << m.shader << "'.\n", false)
|
|
}
|
|
return true;
|
|
}
|
|
bool Material::Create(Render::ResourceFactory &rf, const Core::Material &m)
|
|
{
|
|
__LOG_H__ << "Load render material '" << m.name << "'.\n";
|
|
name = m.name;
|
|
|
|
using namespace Core;
|
|
|
|
// Transfer basic material informations to the render data.
|
|
*((BasicMaterial *)this) = ((BasicMaterial &)m);
|
|
|
|
// Load texture table.
|
|
LoadTextureTable(rf, m);
|
|
|
|
// Load core shader.
|
|
MaterialShaderStaticParm parm;
|
|
|
|
parm.no_lighting = asbool(m.renderword & Core::Material::Render_Unlit);
|
|
parm.use_skinning = asbool(m.renderword & Core::Material::Render_Skinned);
|
|
parm.use_alpha_test = asbool(m.renderword & Core::Material::Render_AlphaTest);
|
|
parm.use_depth_bias = asbool(m.depth_bias);
|
|
|
|
Core::Shader core_shader;
|
|
bool load_core_shader = LoadCoreShader(rf, m, core_shader, m.shader);
|
|
|
|
// Drop current material shader.
|
|
shader = NULL;
|
|
|
|
// Look for a compatible material shader in cache.
|
|
if (load_core_shader)
|
|
ListForeachPtr(MaterialShader *, s, renderer.material_shaders)
|
|
if ((s->GetName() == core_shader.name) && (s->GetStaticParm() == parm))
|
|
{
|
|
__LOG_V__ << "Reusing cached material shader for material '" << m.name << "'.\n";
|
|
|
|
shader = s;
|
|
return true;
|
|
}
|
|
|
|
// Build a new one otherwise.
|
|
shader = new MaterialShader(renderer);
|
|
if (shader.IsNull())
|
|
return false;
|
|
|
|
if (!load_core_shader || !shader->Create(rf, core_shader, parm))
|
|
{
|
|
if (!LoadCoreShader(rf, m, core_shader, "@core/builtin/shader/shader_error.nsa"))
|
|
return false;
|
|
if (!shader->Create(rf, core_shader, parm))
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
//------------------------------------------------------------------------------
|
|
|
|
//------------------------------------------------------------------------------
|
|
Render::Material *Material::Clone() const
|
|
{
|
|
Material *cloned = new Material(renderer);
|
|
|
|
// __LOG_W__ << "[MaterialClone] Step 1c: 'new' returned successfully!\n";
|
|
if (!cloned)
|
|
{
|
|
__LOG_E__ << "[MaterialClone] ERROR: Failed to allocate memory for cloned material!\n";
|
|
return NULL;
|
|
}
|
|
// __LOG_W__ << "[MaterialClone] Step 1: Material instance created at " << (void*)cloned << "\n";
|
|
|
|
// Copy name (with "_clone" suffix to distinguish it)
|
|
// __LOG_W__ << "[MaterialClone] Step 2: Copying name...\n";
|
|
cloned->name = name + "_clone";
|
|
// __LOG_W__ << "[MaterialClone] Step 2: Name copied: '" << cloned->name << "'\n";
|
|
|
|
// Copy basic material properties (diffuse, specular, self, ambient, glossiness, etc.)
|
|
// __LOG_W__ << "[MaterialClone] Step 3: Copying BasicMaterial properties...\n";
|
|
*((Core::BasicMaterial *)cloned) = *((Core::BasicMaterial *)this);
|
|
// __LOG_W__ << "[MaterialClone] Step 3: BasicMaterial properties copied.\n";
|
|
|
|
// Copy shader reference
|
|
// __LOG_W__ << "[MaterialClone] Step 4: Copying shader reference...\n";
|
|
cloned->shader = shader;
|
|
// __LOG_W__ << "[MaterialClone] Step 4: Shader reference copied.\n";
|
|
|
|
// Copy texture table (smart pointers, so textures are shared, not duplicated)
|
|
// __LOG_W__ << "[MaterialClone] Step 5: Copying texture table...\n";
|
|
for (uint n = 0; n < Core::Material::max_texture_stage; ++n)
|
|
{
|
|
cloned->texture_table[n] = texture_table[n];
|
|
}
|
|
// __LOG_W__ << "[MaterialClone] Step 5: Texture table copied.\n";
|
|
|
|
// __LOG_W__ << "[MaterialClone] SUCCESS: Material cloned successfully as '" << cloned->name << "'.\n";
|
|
|
|
return cloned;
|
|
}
|
|
//------------------------------------------------------------------------------
|