commit x64 compilation from lulu cause the other branch dont seems to compile properly at home
This commit is contained in:
429
include/engine/gpu/gpu_material_shader.cpp
Normal file
429
include/engine/gpu/gpu_material_shader.cpp
Normal file
@ -0,0 +1,429 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#include "gpu/gpu_material_shader.h"
|
||||
#include "gpu/gpu_material.h"
|
||||
#include "gpu/gpu_renderer.h"
|
||||
#include "log/log.h"
|
||||
|
||||
using namespace GS;
|
||||
using namespace GS::GPU;
|
||||
using GS::NML::Tag;
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
bool MaterialShader::SetUserUniformValue(const char *name, const Vector4 &v)
|
||||
{
|
||||
uint match_count = 0;
|
||||
for (uint n = 0; n < variants.GetCount(); ++n)
|
||||
if (Shader *shader = variants[n].c_ptr())
|
||||
if (ShaderInput *input = shader->GetInput(name))
|
||||
{
|
||||
input->parm_v = v;
|
||||
++match_count;
|
||||
}
|
||||
|
||||
return match_count > 0;
|
||||
}
|
||||
bool MaterialShader::SetUserUniformValue(const char *name, Render::Texture *t)
|
||||
{
|
||||
uint match_count = 0;
|
||||
for (uint n = 0; n < variants.GetCount(); ++n)
|
||||
if (Shader *shader = variants[n].c_ptr())
|
||||
if (ShaderInput *input = shader->GetInput(name))
|
||||
{
|
||||
input->parm_t = t;
|
||||
++match_count;
|
||||
}
|
||||
|
||||
return match_count > 0;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void MaterialShader::CompileForwardPointLight(Core::Shader &shader, bool shadow)
|
||||
{
|
||||
shader.Define("_POINT_LIGHT", Core::ShaderInput::Pixel);
|
||||
CompileShaderSection("OutputForwardLightModel", shader);
|
||||
|
||||
if (shadow)
|
||||
{
|
||||
shader.Define("_CAST_SHADOW", Core::ShaderInput::Pixel);
|
||||
|
||||
shader.DeclareInput("psm", Core::ShaderInput::DataTextureShadow, Core::ShaderInput::LightShadowMap0, Core::ShaderInput::Uniform, Core::ShaderInput::Pixel);
|
||||
for (int n = 0; n < 6; ++n)
|
||||
shader.DeclareInput(String::Format("psm_%d_projection_matrix", n), Core::ShaderInput::Matrix4, Core::ShaderInput::Semantic(Core::ShaderInput::LightShadowMatrix0 + n), Core::ShaderInput::Uniform, Core::ShaderInput::Pixel);
|
||||
shader.DeclareInput("u_iss", Core::ShaderInput::Float, Core::ShaderInput::InverseShadowMapSize, Core::ShaderInput::Uniform, Core::ShaderInput::Pixel);
|
||||
shader.DeclareInput("u_lsb", Core::ShaderInput::Float, Core::ShaderInput::LightShadowBias, Core::ShaderInput::Uniform, Core::ShaderInput::Pixel);
|
||||
shader.DeclareInput("u_vtl", Core::ShaderInput::Matrix4, Core::ShaderInput::ViewToLightMatrix, Core::ShaderInput::Uniform, Core::ShaderInput::Pixel);
|
||||
shader.DeclareInput("u_noise", Core::ShaderInput::DataTexture2D, Core::ShaderInput::NoiseMap, Core::ShaderInput::Uniform, Core::ShaderInput::Pixel);
|
||||
|
||||
if (Tag *t = renderer.GetPCFShaderTag())
|
||||
shader.pixel_decl += t->GetString();
|
||||
if (Tag *t = renderer.GetPSMShaderTag())
|
||||
shader.pixel.Replace("%psm_pcf_evaluation%", t->GetString());
|
||||
}
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void MaterialShader::CompileForwardSpotLight(Core::Shader &shader, bool shadow, bool projection_map)
|
||||
{
|
||||
shader.Define("_SPOT_LIGHT", Core::ShaderInput::Pixel);
|
||||
CompileShaderSection("OutputForwardLightModel", shader);
|
||||
|
||||
if (shadow)
|
||||
{
|
||||
shader.Define("_CAST_SHADOW", Core::ShaderInput::Pixel);
|
||||
|
||||
shader.DeclareInput("u_ssm", Core::ShaderInput::DataTextureShadow, Core::ShaderInput::Semantic(Core::ShaderInput::LightShadowMap0), Core::ShaderInput::Uniform, Core::ShaderInput::Pixel);
|
||||
shader.DeclareInput("u_ssm_projection", Core::ShaderInput::Matrix4, Core::ShaderInput::Semantic(Core::ShaderInput::LightShadowMatrix0), Core::ShaderInput::Uniform, Core::ShaderInput::Pixel);
|
||||
shader.DeclareInput("u_iss", Core::ShaderInput::Float, Core::ShaderInput::InverseShadowMapSize, Core::ShaderInput::Uniform, Core::ShaderInput::Pixel);
|
||||
shader.DeclareInput("u_lsb", Core::ShaderInput::Float, Core::ShaderInput::LightShadowBias, Core::ShaderInput::Uniform, Core::ShaderInput::Pixel);
|
||||
shader.DeclareInput("u_noise", Core::ShaderInput::DataTexture2D, Core::ShaderInput::NoiseMap, Core::ShaderInput::Uniform, Core::ShaderInput::Pixel);
|
||||
|
||||
if (Tag *t = renderer.GetPCFShaderTag())
|
||||
shader.pixel_decl += t->GetString();
|
||||
}
|
||||
|
||||
if (projection_map)
|
||||
{
|
||||
shader.Define("_PROJECTION_MAP", Core::ShaderInput::Pixel);
|
||||
shader.DeclareInput("u_pjm", Core::ShaderInput::DataTexture2D, Core::ShaderInput::Semantic(Core::ShaderInput::LightProjectionMap), Core::ShaderInput::Uniform, Core::ShaderInput::Pixel);
|
||||
shader.DeclareInput("u_pjm_projection", Core::ShaderInput::Matrix4, Core::ShaderInput::Semantic(Core::ShaderInput::LightShadowMatrix0), Core::ShaderInput::Uniform, Core::ShaderInput::Pixel);
|
||||
}
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void MaterialShader::CompileForwardLinearLight(Core::Shader &shader, bool shadow)
|
||||
{
|
||||
shader.Define("_LINEAR_LIGHT", Core::ShaderInput::Pixel);
|
||||
CompileShaderSection("OutputForwardLightModel", shader);
|
||||
|
||||
if (shadow)
|
||||
{
|
||||
shader.Define("_CAST_SHADOW", Core::ShaderInput::Pixel);
|
||||
|
||||
shader.DeclareInput("pssm", Core::ShaderInput::DataTextureShadow, Core::ShaderInput::LightShadowMap0, Core::ShaderInput::Uniform, Core::ShaderInput::Pixel);
|
||||
for (int n = 0; n < renderer.registry.GetInteger("ShadowMapping:PSSM:Split", 3); ++n)
|
||||
{
|
||||
shader.DeclareInput(String::Format("pssm_%d_slice_distance", n), Core::ShaderInput::Float, Core::ShaderInput::Semantic(Core::ShaderInput::LightPSSMSliceDistance0 + n), Core::ShaderInput::Uniform, Core::ShaderInput::Pixel);
|
||||
shader.DeclareInput(String::Format("pssm_%d_projection_matrix", n), Core::ShaderInput::Matrix4, Core::ShaderInput::Semantic(Core::ShaderInput::LightShadowMatrix0 + n), Core::ShaderInput::Uniform, Core::ShaderInput::Pixel);
|
||||
}
|
||||
shader.DeclareInput("u_noise", Core::ShaderInput::DataTexture2D, Core::ShaderInput::NoiseMap, Core::ShaderInput::Uniform, Core::ShaderInput::Pixel);
|
||||
shader.DeclareInput("u_iss", Core::ShaderInput::Float, Core::ShaderInput::InverseShadowMapSize, Core::ShaderInput::Uniform, Core::ShaderInput::Pixel);
|
||||
shader.DeclareInput("u_lsb", Core::ShaderInput::Float, Core::ShaderInput::LightShadowBias, Core::ShaderInput::Uniform, Core::ShaderInput::Pixel);
|
||||
|
||||
if (Tag *t = renderer.GetPCFShaderTag())
|
||||
shader.pixel_decl += t->GetString();
|
||||
|
||||
if (Tag *t = renderer.GetPSSMShaderTag())
|
||||
shader.pixel.Replace("%pssm_pcf_evaluation%", t->GetString());
|
||||
}
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
bool MaterialShader::CompileShaderSection(const char *id, Core::Shader &shader)
|
||||
{
|
||||
Tag *shader_tag = renderer.GetMaterialDict().GetTag(id);
|
||||
if (!shader_tag)
|
||||
__ERR__(__LOG_E__ << "Missing shader section '" << id << "'.\n", false)
|
||||
|
||||
if (Tag *tag = shader_tag->GetTag("Input;"))
|
||||
shader.ParseInputTag(tag);
|
||||
if (Tag *tag = shader_tag->GetTag("Varying;"))
|
||||
shader.ParseVaryingTag(tag);
|
||||
if (Tag *tag = shader_tag->GetTag("Vertex;"))
|
||||
shader.vertex += tag->GetString();
|
||||
if (Tag *tag = shader_tag->GetTag("Fragment;"))
|
||||
shader.pixel += tag->GetString();
|
||||
|
||||
return true;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
bool MaterialShader::SetupMaterialProgram(Variant p, Core::Shader &shader)
|
||||
{
|
||||
if (parm.use_alpha_test)
|
||||
{
|
||||
shader.DeclareInput("u_alpha_threshold", Core::ShaderInput::Float, Core::ShaderInput::MaterialAlphaThreshold, Core::ShaderInput::Uniform, Core::ShaderInput::Pixel);
|
||||
shader.pixel += "if (%opacity% < u_alpha_threshold) discard;\n";
|
||||
}
|
||||
|
||||
if (parm.use_depth_bias)
|
||||
shader.DeclareInput("u_depth_bias", Core::ShaderInput::Float, Core::ShaderInput::MaterialDepthBias, Core::ShaderInput::Uniform, Core::ShaderInput::Pixel);
|
||||
|
||||
if (parm.use_skinning)
|
||||
{
|
||||
shader.Define("_SKINNED", (Core::ShaderInput::Scope)(Core::ShaderInput::Vertex | Core::ShaderInput::Pixel));
|
||||
shader.DeclareInput("bone_mtx", Core::ShaderInput::Matrix4, Core::ShaderInput::BoneMatrix, Core::ShaderInput::Uniform, Core::ShaderInput::Vertex, __PL_BONE_LIMIT__);
|
||||
shader.DeclareInput("bone_idx", Core::ShaderInput::Vector4, Core::ShaderInput::BoneIndex, Core::ShaderInput::Attribute, Core::ShaderInput::Vertex);
|
||||
shader.DeclareInput("bone_w", Core::ShaderInput::Vector4, Core::ShaderInput::BoneWeight, Core::ShaderInput::Attribute, Core::ShaderInput::Vertex);
|
||||
shader.DeclareVarying("v_skin_mtx", "mat4");
|
||||
}
|
||||
|
||||
CompileShaderSection("InputPosition;", shader);
|
||||
|
||||
// Assemble program shader.
|
||||
switch (p)
|
||||
{
|
||||
case Depth:
|
||||
CompileShaderSection("OutputDepth;", shader);
|
||||
break;
|
||||
|
||||
case FS_Constant:
|
||||
CompileShaderSection("OutputForwardConstant;", shader);
|
||||
break;
|
||||
|
||||
case FS_PointLight:
|
||||
case FS_PointLightShadowMapping:
|
||||
CompileForwardPointLight(shader, p == FS_PointLightShadowMapping);
|
||||
break;
|
||||
|
||||
case FS_SpotLight:
|
||||
case FS_SpotLightShadowMapping:
|
||||
case FS_SpotLightProjection:
|
||||
case FS_SpotLightProjectionShadowMapping:
|
||||
CompileForwardSpotLight(shader, (p == FS_SpotLightShadowMapping) || (p == FS_SpotLightProjectionShadowMapping), (p == FS_SpotLightProjection) || (p == FS_SpotLightProjectionShadowMapping));
|
||||
break;
|
||||
|
||||
case FS_LinearLight:
|
||||
case FS_LinearLightShadowMapping:
|
||||
CompileForwardLinearLight(shader, p == FS_LinearLightShadowMapping);
|
||||
break;
|
||||
|
||||
case DS_GBufferMRT4:
|
||||
CompileShaderSection("OutputDeferred;", shader);
|
||||
break;
|
||||
|
||||
case PP_NormalDepth:
|
||||
CompileShaderSection("OutputNormalDepth;", shader);
|
||||
break;
|
||||
|
||||
case PP_Velocity:
|
||||
if (parm.use_skinning)
|
||||
shader.DeclareInput("previous_bone_mtx", Core::ShaderInput::Matrix4, Core::ShaderInput::PreviousBoneMatrix, Core::ShaderInput::Uniform, Core::ShaderInput::Vertex, __PL_BONE_LIMIT__);
|
||||
CompileShaderSection("OutputVelocity;", shader);
|
||||
break;
|
||||
|
||||
case Last:
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
static bool FindVarAssignation(const String &src, const char *var) // TODO fix with proper regex, this is proof of concept code at best...
|
||||
{
|
||||
if (src.FindString(String::Format("%s =", var)))
|
||||
return true;
|
||||
if (src.FindString(String::Format("%s\t=", var)))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
static void DeclareVertexPosition(Core::Shader &shader, bool declare_varying)
|
||||
{
|
||||
String decl = "vec4 %position%;\n";
|
||||
|
||||
if (!asbool(FindVarAssignation(shader.vertex, "%position%")))
|
||||
{
|
||||
Core::ShaderInput *input = shader.DeclareInput("a_position", Core::ShaderInput::Vector3, Core::ShaderInput::Position, Core::ShaderInput::Attribute, Core::ShaderInput::Vertex);
|
||||
// Core::ShaderInput *input = shader.GetInput(Core::ShaderInput::Position);
|
||||
decl << "%position% = vec4(" << input->name << ", 1.0);\n";
|
||||
}
|
||||
shader.vertex = decl + shader.vertex;
|
||||
}
|
||||
static void DeclareVertexNormal(Core::Shader &shader)
|
||||
{
|
||||
String decl = "vec3 %normal%;\n";
|
||||
|
||||
if (!asbool(FindVarAssignation(shader.vertex, "%normal%")))
|
||||
{
|
||||
Core::ShaderInput *input = shader.DeclareInput("a_normal", Core::ShaderInput::Vector3, Core::ShaderInput::Normal, Core::ShaderInput::Attribute, Core::ShaderInput::Vertex);
|
||||
// Core::ShaderInput *input = shader.GetInput(Core::ShaderInput::Normal);
|
||||
decl << "%normal% = " << input->name << ";\n";
|
||||
}
|
||||
shader.vertex = decl + shader.vertex;
|
||||
}
|
||||
static void InitializeShader(Core::Shader &shader)
|
||||
{
|
||||
// Position
|
||||
{
|
||||
bool pixel_consumes = asbool(shader.pixel.FindString("%in.position%"));
|
||||
DeclareVertexPosition(shader, pixel_consumes);
|
||||
}
|
||||
|
||||
// Normal
|
||||
{
|
||||
bool pixel_consumes = asbool(shader.pixel.FindString("%in.normal%"));
|
||||
bool pixel_provides = FindVarAssignation(shader.pixel, "%normal%");
|
||||
|
||||
if (pixel_consumes || !pixel_provides)
|
||||
DeclareVertexNormal(shader);
|
||||
|
||||
if (!pixel_provides)
|
||||
shader.pixel << "%normal% = %in.normal%;\n";
|
||||
|
||||
shader.pixel = String("vec3 %normal%;\n") + shader.pixel;
|
||||
}
|
||||
|
||||
{
|
||||
struct ShaderDefault
|
||||
{
|
||||
const char *type, *name, *var;
|
||||
Core::ShaderInput::DataType data_type;
|
||||
Core::ShaderInput::Semantic semantic;
|
||||
};
|
||||
|
||||
static ShaderDefault ps_ic[] =
|
||||
{
|
||||
{ "vec4", "%diffuse%", "_u_mat_diff", Core::ShaderInput::Vector4, Core::ShaderInput::MaterialDiffuse },
|
||||
{ "vec4", "%specular%", "_u_mat_spec", Core::ShaderInput::Vector4, Core::ShaderInput::MaterialSpecular },
|
||||
{ "float", "%glossiness%", "_u_mat_glos", Core::ShaderInput::Float, Core::ShaderInput::MaterialGlossiness },
|
||||
{ "vec4", "%constant%", "_u_mat_const", Core::ShaderInput::Vector4, Core::ShaderInput::MaterialSelf },
|
||||
{ "float", "%opacity%", "_u_mat_opac", Core::ShaderInput::Float, Core::ShaderInput::MaterialOpacity },
|
||||
{ NULL, NULL, NULL }
|
||||
};
|
||||
|
||||
// Declare mandatory outputs and set default value for unprovided entries.
|
||||
String decl;
|
||||
for (uint n = 0; ps_ic[n].type; ++n)
|
||||
{
|
||||
decl << ps_ic[n].type << " " << ps_ic[n].name << ";\n";
|
||||
|
||||
if (!FindVarAssignation(shader.pixel, ps_ic[n].name))
|
||||
{
|
||||
Core::ShaderInput *input = shader.DeclareInput(ps_ic[n].var, ps_ic[n].data_type, ps_ic[n].semantic, Core::ShaderInput::Uniform, Core::ShaderInput::Pixel);
|
||||
decl << ps_ic[n].name << " = " << input->name << ";\n";
|
||||
}
|
||||
}
|
||||
shader.pixel = decl + shader.pixel;
|
||||
}
|
||||
}
|
||||
static void FinalizeShader(Core::Shader &shader)
|
||||
{
|
||||
if (asbool(shader.pixel.FindString("%in.position%")))
|
||||
{
|
||||
shader.DeclareVarying("_v_position", "vec4");
|
||||
shader.vertex << "_v_position = %position%;\n";
|
||||
}
|
||||
if (asbool(shader.pixel.FindString("%in.normal%")))
|
||||
{
|
||||
shader.DeclareVarying("_v_normal", "vec3");
|
||||
shader.vertex << "_v_normal = %normal%;\n";
|
||||
}
|
||||
|
||||
shader.pixel.ReplaceAll("%in.position%", "_v_position", true);
|
||||
shader.pixel.ReplaceAll("%in.normal%", "_v_normal", true);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
static const char *GetShaderVariantName(MaterialShader::Variant v)
|
||||
{
|
||||
switch (v)
|
||||
{
|
||||
case MaterialShader::Depth: return "Depth";
|
||||
|
||||
case MaterialShader::DS_GBufferMRT4: return "DS_GBufferMRT4";
|
||||
case MaterialShader::FS_Constant: return "FS_Constant";
|
||||
|
||||
case MaterialShader::FS_PointLight: return "FS_PointLight";
|
||||
case MaterialShader::FS_PointLightShadowMapping: return "FS_PointLightShadowMapping";
|
||||
|
||||
case MaterialShader::FS_LinearLight: return "FS_LinearLight";
|
||||
case MaterialShader::FS_LinearLightShadowMapping: return "FS_LinearLightShadowMapping";
|
||||
|
||||
case MaterialShader::FS_SpotLight: return "FS_SpotLight";
|
||||
case MaterialShader::FS_SpotLightShadowMapping: return "FS_SpotLightShadowMapping";
|
||||
case MaterialShader::FS_SpotLightProjection: return "FS_SpotLightProjection";
|
||||
case MaterialShader::FS_SpotLightProjectionShadowMapping: return "FS_SpotLightProjectionShadowMapping";
|
||||
|
||||
case MaterialShader::PP_NormalDepth: return "PP_NormalDepth";
|
||||
case MaterialShader::PP_Velocity: return "PP_Velocity";
|
||||
|
||||
case MaterialShader::Last:
|
||||
break;
|
||||
}
|
||||
return "UnknownVariant";
|
||||
}
|
||||
bool MaterialShader::Create(Render::ResourceFactory &rf, const Core::Shader &shader, const MaterialShaderStaticParm &static_parm)
|
||||
{
|
||||
__LOG_V__ << "Creating material shader '" << shader.name << "' variants.\n";
|
||||
|
||||
name = shader.name;
|
||||
parm = static_parm;
|
||||
|
||||
// Build variants.
|
||||
if (!variants.Allocate(Last))
|
||||
return false;
|
||||
|
||||
for (int n = 0; n < Last; ++n)
|
||||
{
|
||||
if (renderer.render_technique == Renderer::TechniqueDeferred)
|
||||
if ((n >= FS_Constant) && (n <= FS_SpotLightProjectionShadowMapping))
|
||||
continue; // no forward
|
||||
|
||||
if (renderer.render_technique == Renderer::TechniqueForward)
|
||||
if (n == DS_GBufferMRT4)
|
||||
continue; // no deferred
|
||||
|
||||
if (!renderer.gpu_config.enable_shadow)
|
||||
if (
|
||||
(n == Depth) ||
|
||||
(n == FS_PointLightShadowMapping) ||
|
||||
(n == FS_LinearLightShadowMapping) ||
|
||||
(n == FS_SpotLightShadowMapping) ||
|
||||
(n == FS_SpotLightProjectionShadowMapping)
|
||||
)
|
||||
continue; // no shadow-mapping
|
||||
|
||||
if (!renderer.gpu_config.use_rtt)
|
||||
if (
|
||||
(n == PP_Velocity) ||
|
||||
(n == PP_NormalDepth)
|
||||
)
|
||||
continue; // no post-processes
|
||||
|
||||
if (parm.no_lighting)
|
||||
if ((n > FS_Constant) && (n <= FS_SpotLightProjectionShadowMapping)) // keep constant!
|
||||
continue; // no lighting pass
|
||||
|
||||
// Specialize shader for this program.
|
||||
Core::Shader shader_variant;
|
||||
if (!shader.Clone(shader_variant))
|
||||
return false;
|
||||
|
||||
InitializeShader(shader_variant);
|
||||
if (!SetupMaterialProgram((Variant)n, shader_variant))
|
||||
return false;
|
||||
FinalizeShader(shader_variant);
|
||||
|
||||
shader_variant.name << "_" << GetShaderVariantName((MaterialShader::Variant)n);
|
||||
|
||||
// Compile it.
|
||||
if ((variants[n] = (Shader *)renderer.NewShader()) != NULL)
|
||||
if (!variants[n]->Create(rf, shader_variant))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
MaterialShader::MaterialShader(Renderer &r) : renderer(r)
|
||||
{ renderer.material_shaders.Add(this); }
|
||||
MaterialShader::~MaterialShader()
|
||||
{ renderer.material_shaders.Remove(this); }
|
||||
//------------------------------------------------------------------------------
|
||||
Reference in New Issue
Block a user