Reflection shader support

This commit is contained in:
Jack Andersen 2017-03-25 19:51:58 -10:00
parent d92ba13405
commit b860d962ae
10 changed files with 251 additions and 76 deletions

View File

@ -325,6 +325,17 @@ def recursive_alpha_trace(mat_obj, mesh_obj, tex_list, node, socket=None):
raise RuntimeError("HMDL is unable to process '{0}' shader nodes in '{1}'".format(node.type, mat_obj.name))
# Trace indirect node structure
def indirect_trace(mat_obj, mesh_obj, tex_list, node):
if node.type == 'OUTPUT':
if node.inputs['Color'].is_linked:
tex_node = node.inputs['Color'].links[0].from_node
if tex_node.type != 'TEXTURE':
raise RuntimeError("HMDL *requires* that an indirect output node is directly connected to TEXTURE")
if not tex_node.texture or not hasattr(tex_node.texture, 'name'):
raise RuntimeError("HMDL texture nodes must specify a texture object")
get_texmap_idx(tex_list, tex_node.texture.name)
def shader(mat_obj, mesh_obj):
@ -342,6 +353,11 @@ def shader(mat_obj, mesh_obj):
color_trace_result = recursive_color_trace(mat_obj, mesh_obj, tex_list, output_node)
alpha_trace_result = recursive_alpha_trace(mat_obj, mesh_obj, tex_list, output_node)
# Trace indirect reflection texture
if 'IndirectOutput' in mat_obj.node_tree.nodes:
ind_out_node = mat_obj.node_tree.nodes['IndirectOutput']
indirect_trace(mat_obj, mesh_obj, tex_list, ind_out_node)
# Resolve texture paths
tex_paths = [get_texture_path(name) for name in tex_list]

View File

@ -55,6 +55,13 @@ struct TextureInfo
bool normalize;
};
enum class ReflectionType
{
None,
Simple,
Indirect
};
class IBackend
{
public:

View File

@ -16,19 +16,21 @@ struct GLSL : ProgrammableCommon
void reset(const IR& ir, Diagnostics& diag);
std::string makeVert(const char* glslVer, unsigned col, unsigned uv, unsigned w,
unsigned skinSlots, unsigned texMtxs, size_t extTexCount,
const TextureInfo* extTexs) const;
std::string makeFrag(const char* glslVer, bool alphaTest,
const TextureInfo* extTexs, ReflectionType reflectionType) const;
std::string makeFrag(const char* glslVer, bool alphaTest, ReflectionType reflectionType,
const ShaderFunction& lighting=ShaderFunction()) const;
std::string makeFrag(const char* glslVer, bool alphaTest,
ReflectionType reflectionType,
const ShaderFunction& lighting,
const ShaderFunction& post,
size_t extTexCount, const TextureInfo* extTexs) const;
private:
std::string GenerateVertInStruct(unsigned col, unsigned uv, unsigned w) const;
std::string GenerateVertToFragStruct(size_t extTexCount) const;
std::string GenerateVertUniformStruct(unsigned skinSlots, unsigned texMtxs) const;
std::string GenerateVertToFragStruct(size_t extTexCount, bool reflectionCoords) const;
std::string GenerateVertUniformStruct(unsigned skinSlots, unsigned texMtxs, bool reflectionCoords) const;
std::string GenerateAlphaTest() const;
std::string GenerateReflectionExpr(ReflectionType type) const;
std::string EmitVec3(const atVec4f& vec) const
{

View File

@ -13,17 +13,20 @@ struct HLSL : ProgrammableCommon
void reset(const IR& ir, Diagnostics& diag);
std::string makeVert(unsigned col, unsigned uv, unsigned w,
unsigned skinSlots, unsigned texMtxs, size_t extTexCount,
const TextureInfo* extTexs) const;
std::string makeFrag(bool alphaTest, const ShaderFunction& lighting=ShaderFunction()) const;
const TextureInfo* extTexs, ReflectionType reflectionType) const;
std::string makeFrag(bool alphaTest, ReflectionType reflectionType,
const ShaderFunction& lighting=ShaderFunction()) const;
std::string makeFrag(bool alphaTest, const ShaderFunction& lighting,
ReflectionType reflectionType,
const ShaderFunction& post, size_t extTexCount,
const TextureInfo* extTexs) const;
private:
std::string GenerateVertInStruct(unsigned col, unsigned uv, unsigned w) const;
std::string GenerateVertToFragStruct(size_t extTexCount) const;
std::string GenerateVertUniformStruct(unsigned skinSlots, unsigned texMtxs) const;
std::string GenerateVertToFragStruct(size_t extTexCount, ReflectionType reflectionType) const;
std::string GenerateVertUniformStruct(unsigned skinSlots, unsigned texMtxs, ReflectionType reflectionType) const;
std::string GenerateAlphaTest() const;
std::string GenerateReflectionExpr(ReflectionType type) const;
std::string EmitVec3(const atVec4f& vec) const
{

View File

@ -15,20 +15,22 @@ struct Metal : ProgrammableCommon
void reset(const IR& ir, Diagnostics& diag);
std::string makeVert(unsigned col, unsigned uv, unsigned w,
unsigned skinSlots, unsigned texMtxs, size_t extTexCount,
const TextureInfo* extTexs) const;
const TextureInfo* extTexs, ReflectionType reflectionType) const;
std::string makeFrag(size_t blockCount, const char** blockNames, bool alphaTest,
ReflectionType reflectionType,
const ShaderFunction& lighting=ShaderFunction()) const;
std::string makeFrag(size_t blockCount, const char** blockNames, bool alphaTest,
const ShaderFunction& lighting,
ReflectionType reflectionType, const ShaderFunction& lighting,
const ShaderFunction& post, size_t extTexCount,
const TextureInfo* extTexs) const;
private:
std::string GenerateVertInStruct(unsigned col, unsigned uv, unsigned w) const;
std::string GenerateVertToFragStruct(size_t extTexCount) const;
std::string GenerateVertToFragStruct(size_t extTexCount, bool reflectionCoords) const;
std::string GenerateVertUniformStruct(unsigned skinSlots) const;
std::string GenerateFragOutStruct() const;
std::string GenerateAlphaTest() const;
std::string GenerateReflectionExpr(ReflectionType type) const;
std::string EmitVec3(const atVec4f& vec) const
{

View File

@ -49,6 +49,7 @@ class ShaderTag : public Hash
uint8_t m_skinSlotCount;
uint8_t m_texMtxCount;
uint8_t m_primitiveType;
uint8_t m_reflectionType;
bool m_depthTest:1;
bool m_depthWrite:1;
bool m_backfaceCulling:1;
@ -57,19 +58,22 @@ class ShaderTag : public Hash
public:
ShaderTag() = default;
ShaderTag(const std::string& source, uint8_t c, uint8_t u, uint8_t w, uint8_t s, uint8_t t, boo::Primitive pt,
bool depthTest, bool depthWrite, bool backfaceCulling)
Backend::ReflectionType reflectionType, bool depthTest, bool depthWrite, bool backfaceCulling)
: Hash(source), m_colorCount(c), m_uvCount(u), m_weightCount(w), m_skinSlotCount(s), m_texMtxCount(t),
m_primitiveType(uint8_t(pt)), m_depthTest(depthTest), m_depthWrite(depthWrite), m_backfaceCulling(backfaceCulling)
m_primitiveType(uint8_t(pt)), m_reflectionType(uint8_t(reflectionType)),
m_depthTest(depthTest), m_depthWrite(depthWrite), m_backfaceCulling(backfaceCulling)
{hash ^= m_meta;}
ShaderTag(const hecl::Frontend::IR& ir, uint8_t c, uint8_t u, uint8_t w, uint8_t s, uint8_t t, boo::Primitive pt,
bool depthTest, bool depthWrite, bool backfaceCulling)
Backend::ReflectionType reflectionType, bool depthTest, bool depthWrite, bool backfaceCulling)
: Hash(ir.m_hash), m_colorCount(c), m_uvCount(u), m_weightCount(w), m_skinSlotCount(s), m_texMtxCount(t),
m_primitiveType(uint8_t(pt)), m_depthTest(depthTest), m_depthWrite(depthWrite), m_backfaceCulling(backfaceCulling)
m_primitiveType(uint8_t(pt)), m_reflectionType(uint8_t(reflectionType)),
m_depthTest(depthTest), m_depthWrite(depthWrite), m_backfaceCulling(backfaceCulling)
{hash ^= m_meta;}
ShaderTag(uint64_t hashin, uint8_t c, uint8_t u, uint8_t w, uint8_t s, uint8_t t, boo::Primitive pt,
bool depthTest, bool depthWrite, bool backfaceCulling)
Backend::ReflectionType reflectionType, bool depthTest, bool depthWrite, bool backfaceCulling)
: Hash(hashin), m_colorCount(c), m_uvCount(u), m_weightCount(w), m_skinSlotCount(s), m_texMtxCount(t),
m_primitiveType(uint8_t(pt)), m_depthTest(depthTest), m_depthWrite(depthWrite), m_backfaceCulling(backfaceCulling)
m_primitiveType(uint8_t(pt)), m_reflectionType(uint8_t(reflectionType)),
m_depthTest(depthTest), m_depthWrite(depthWrite), m_backfaceCulling(backfaceCulling)
{hash ^= m_meta;}
ShaderTag(uint64_t comphashin, uint64_t meta)
: Hash(comphashin), m_meta(meta) {}
@ -80,6 +84,7 @@ public:
uint8_t getSkinSlotCount() const {return m_skinSlotCount;}
uint8_t getTexMtxCount() const {return m_texMtxCount;}
boo::Primitive getPrimType() const {return boo::Primitive(m_primitiveType);}
Backend::ReflectionType getReflectionType() const {return Backend::ReflectionType(m_reflectionType);}
bool getDepthTest() const {return m_depthTest;}
bool getDepthWrite() const {return m_depthWrite;}
bool getBackfaceCulling() const {return m_backfaceCulling;}

View File

@ -69,7 +69,7 @@ std::string GLSL::GenerateVertInStruct(unsigned col, unsigned uv, unsigned w) co
return retval;
}
std::string GLSL::GenerateVertToFragStruct(size_t extTexCount) const
std::string GLSL::GenerateVertToFragStruct(size_t extTexCount, bool reflectionCoords) const
{
std::string retval =
"struct VertToFrag\n"
@ -82,10 +82,14 @@ std::string GLSL::GenerateVertToFragStruct(size_t extTexCount) const
if (extTexCount)
retval += hecl::Format(" vec2 extTcgs[%u];\n", unsigned(extTexCount));
if (reflectionCoords)
retval += " vec2 reflectTcgs[2];\n"
" float reflectAlpha;\n";
return retval + "};\n";
}
std::string GLSL::GenerateVertUniformStruct(unsigned skinSlots, unsigned texMtxs) const
std::string GLSL::GenerateVertUniformStruct(unsigned skinSlots, unsigned texMtxs, bool reflectionCoords) const
{
if (skinSlots == 0)
skinSlots = 1;
@ -97,7 +101,6 @@ std::string GLSL::GenerateVertUniformStruct(unsigned skinSlots, unsigned texMtxs
"};\n",
skinSlots, skinSlots);
if (texMtxs)
{
retval += hecl::Format("struct HECLTCGMatrix\n"
"{\n"
" mat4 mtx;\n"
@ -107,7 +110,15 @@ std::string GLSL::GenerateVertUniformStruct(unsigned skinSlots, unsigned texMtxs
"{\n"
" HECLTCGMatrix texMtxs[%u];\n"
"};\n", texMtxs);
}
if (reflectionCoords)
retval += "UBINDING3 uniform HECLReflectMtx\n"
"{\n"
" mat4 indMtx;\n"
" mat4 reflectMtx;\n"
" float reflectAlpha;\n"
"};\n"
"\n";
return retval;
}
@ -120,6 +131,20 @@ std::string GLSL::GenerateAlphaTest() const
" }\n";
}
std::string GLSL::GenerateReflectionExpr(ReflectionType type) const
{
switch (type)
{
case ReflectionType::None:
return "vec3(0.0, 0.0, 0.0);\n";
case ReflectionType::Simple:
return "texture(reflectionTex, vtf.reflectTcgs[1]).rgb * vtf.reflectAlpha;\n";
case ReflectionType::Indirect:
return "texture(reflectionTex, (texture(reflectionIndTex, vtf.reflectTcgs[0]).rg - "
"vec2(0.5, 0.5)) * vec2(0.5, 0.5) + vtf.reflectTcgs[1]).rgb * vtf.reflectAlpha;\n";
}
}
void GLSL::reset(const IR& ir, Diagnostics& diag)
{
/* Common programmable interpretation */
@ -128,13 +153,13 @@ void GLSL::reset(const IR& ir, Diagnostics& diag)
std::string GLSL::makeVert(const char* glslVer, unsigned col, unsigned uv, unsigned w,
unsigned s, unsigned tm, size_t extTexCount,
const TextureInfo* extTexs) const
const TextureInfo* extTexs, ReflectionType reflectionType) const
{
extTexCount = std::min(int(extTexCount), BOO_GLSL_MAX_TEXTURE_COUNT - int(m_tcgs.size()));
std::string retval = std::string(glslVer) + "\n" BOO_GLSL_BINDING_HEAD +
GenerateVertInStruct(col, uv, w) + "\n" +
GenerateVertToFragStruct(extTexCount) + "\n" +
GenerateVertUniformStruct(s, tm) +
GenerateVertToFragStruct(extTexCount, reflectionType != ReflectionType::None) + "\n" +
GenerateVertUniformStruct(s, tm, reflectionType != ReflectionType::None) +
"SBINDING(0) out VertToFrag vtf;\n\n"
"void main()\n{\n";
@ -185,11 +210,16 @@ std::string GLSL::makeVert(const char* glslVer, unsigned col, unsigned uv, unsig
extTex.mtxIdx, EmitTexGenSource4(extTex.src, extTex.uvIdx).c_str());
}
if (reflectionType != ReflectionType::None)
retval += " vtf.reflectTcgs[0] = normalize((indMtx * vec4(v.posIn, 1.0)).xz) * vec2(0.5, 0.5) + vec2(0.5, 0.5);\n"
" vtf.reflectTcgs[1] = (reflectMtx * vec4(v.posIn, 1.0)).xy;\n"
" vtf.reflectAlpha = reflectAlpha;\n";
return retval + "}\n";
}
std::string GLSL::makeFrag(const char* glslVer, bool alphaTest,
const ShaderFunction& lighting) const
ReflectionType reflectionType, const ShaderFunction& lighting) const
{
std::string lightingSrc;
if (lighting.m_source)
@ -204,10 +234,17 @@ std::string GLSL::makeFrag(const char* glslVer, bool alphaTest,
std::string texMapDecl;
for (unsigned i=0 ; i<m_texMapEnd ; ++i)
texMapDecl += hecl::Format("TBINDING%u uniform sampler2D tex%u;\n", i, i);
if (reflectionType == ReflectionType::Indirect)
texMapDecl += hecl::Format("TBINDING%u uniform sampler2D reflectionIndTex;\n"
"TBINDING%u uniform sampler2D reflectionTex;\n",
m_texMapEnd, m_texMapEnd+1);
else if (reflectionType == ReflectionType::Simple)
texMapDecl += hecl::Format("TBINDING%u uniform sampler2D reflectionTex;\n",
m_texMapEnd);
std::string retval = std::string(glslVer) +
"\n#extension GL_ARB_shader_image_load_store: enable\n" BOO_GLSL_BINDING_HEAD +
GenerateVertToFragStruct(0) +
GenerateVertToFragStruct(0, reflectionType != ReflectionType::None) +
(!alphaTest ?
"#ifdef GL_ARB_shader_image_load_store\n"
"layout(early_fragment_tests) in;\n"
@ -232,15 +269,18 @@ std::string GLSL::makeFrag(const char* glslVer, bool alphaTest,
retval += hecl::Format(" vec4 sampling%u = texture(tex%u, vtf.tcgs[%u]);\n",
sampIdx++, sampling.mapIdx, sampling.tcgIdx);
std::string reflectionExpr = GenerateReflectionExpr(reflectionType);
if (m_alphaExpr.size())
retval += " colorOut = vec4(" + m_colorExpr + ", " + m_alphaExpr + ") * mulColor;\n";
retval += " colorOut = vec4(" + m_colorExpr + " + " + reflectionExpr + ", " + m_alphaExpr + ") * mulColor;\n";
else
retval += " colorOut = vec4(" + m_colorExpr + ", 1.0) * mulColor;\n";
retval += " colorOut = vec4(" + m_colorExpr + " + " + reflectionExpr + ", 1.0) * mulColor;\n";
return retval + (alphaTest ? GenerateAlphaTest() : "") + "}\n";
}
std::string GLSL::makeFrag(const char* glslVer, bool alphaTest,
ReflectionType reflectionType,
const ShaderFunction& lighting,
const ShaderFunction& post,
size_t extTexCount, const TextureInfo* extTexs) const
@ -266,6 +306,13 @@ std::string GLSL::makeFrag(const char* glslVer, bool alphaTest,
std::string texMapDecl;
for (unsigned i=0 ; i<m_texMapEnd ; ++i)
texMapDecl += hecl::Format("TBINDING%u uniform sampler2D tex%u;\n", i, i);
if (reflectionType == ReflectionType::Indirect)
texMapDecl += hecl::Format("TBINDING%u uniform sampler2D reflectionIndTex;\n"
"TBINDING%u uniform sampler2D reflectionTex;\n",
m_texMapEnd, m_texMapEnd+1);
else if (reflectionType == ReflectionType::Simple)
texMapDecl += hecl::Format("TBINDING%u uniform sampler2D reflectionTex;\n",
m_texMapEnd);
for (int i=0 ; i<extTexCount ; ++i)
{
@ -276,7 +323,7 @@ std::string GLSL::makeFrag(const char* glslVer, bool alphaTest,
std::string retval = std::string(glslVer) +
"\n#extension GL_ARB_shader_image_load_store: enable\n" BOO_GLSL_BINDING_HEAD +
GenerateVertToFragStruct(extTexCount) +
GenerateVertToFragStruct(extTexCount, reflectionType != ReflectionType::None) +
(!alphaTest ?
"\n#ifdef GL_ARB_shader_image_load_store\n"
"layout(early_fragment_tests) in;\n"
@ -301,10 +348,12 @@ std::string GLSL::makeFrag(const char* glslVer, bool alphaTest,
retval += hecl::Format(" vec4 sampling%u = texture(tex%u, vtf.tcgs[%u]);\n",
sampIdx++, sampling.mapIdx, sampling.tcgIdx);
std::string reflectionExpr = GenerateReflectionExpr(reflectionType);
if (m_alphaExpr.size())
retval += " colorOut = " + postEntry + "(vec4(" + m_colorExpr + ", " + m_alphaExpr + ")) * mulColor;\n";
retval += " colorOut = " + postEntry + "(vec4(" + m_colorExpr + " + " + reflectionExpr + ", " + m_alphaExpr + ")) * mulColor;\n";
else
retval += " colorOut = " + postEntry + "(vec4(" + m_colorExpr + ", 1.0)) * mulColor;\n";
retval += " colorOut = " + postEntry + "(vec4(" + m_colorExpr + " + " + reflectionExpr + ", 1.0)) * mulColor;\n";
return retval + (alphaTest ? GenerateAlphaTest() : "") + "}\n";
}
@ -344,11 +393,12 @@ struct GLSLBackendFactory : IShaderBackendFactory
std::string vertSource =
m_backend.makeVert("#version 330",
tag.getColorCount(), tag.getUvCount(), tag.getWeightCount(),
tag.getSkinSlotCount(), tag.getTexMtxCount(), 0, nullptr);
tag.getSkinSlotCount(), tag.getTexMtxCount(), 0, nullptr, tag.getReflectionType());
cachedSz += vertSource.size() + 1;
std::string fragSource = m_backend.makeFrag("#version 330",
tag.getDepthWrite() && m_backend.m_blendDst == hecl::Backend::BlendFactor::InvSrcAlpha);
tag.getDepthWrite() && m_backend.m_blendDst == hecl::Backend::BlendFactor::InvSrcAlpha,
tag.getReflectionType());
cachedSz += fragSource.size() + 1;
if (m_backend.m_texMapEnd > 8)
@ -437,10 +487,10 @@ struct GLSLBackendFactory : IShaderBackendFactory
sources.emplace_back(m_backend.makeVert("#version 330",
tag.getColorCount(), tag.getUvCount(), tag.getWeightCount(),
tag.getSkinSlotCount(), tag.getTexMtxCount(), slot.texCount,
slot.texs),
slot.texs, tag.getReflectionType()),
m_backend.makeFrag("#version 330",
tag.getDepthWrite() && m_backend.m_blendDst == hecl::Backend::BlendFactor::InvSrcAlpha,
slot.lighting, slot.post, slot.texCount, slot.texs));
tag.getReflectionType(), slot.lighting, slot.post, slot.texCount, slot.texs));
cachedSz += sources.back().first.size() + 1;
cachedSz += sources.back().second.size() + 1;

View File

@ -61,7 +61,7 @@ std::string HLSL::GenerateVertInStruct(unsigned col, unsigned uv, unsigned w) co
return retval + "};\n";
}
std::string HLSL::GenerateVertToFragStruct(size_t extTexCount) const
std::string HLSL::GenerateVertToFragStruct(size_t extTexCount, ReflectionType reflectionType) const
{
std::string retval =
"struct VertToFrag\n"
@ -75,10 +75,14 @@ std::string HLSL::GenerateVertToFragStruct(size_t extTexCount) const
if (extTexCount)
retval += hecl::Format(" float2 extTcgs[%u] : EXTUV;\n", unsigned(extTexCount));
if (reflectionCoords)
retval += " float2 reflectTcgs[2] : REFLECTUV;\n"
" float reflectAlpha;\n";
return retval + "};\n";
}
std::string HLSL::GenerateVertUniformStruct(unsigned skinSlots, unsigned texMtxs) const
std::string HLSL::GenerateVertUniformStruct(unsigned skinSlots, unsigned texMtxs, ReflectionType reflectionType) const
{
if (skinSlots == 0)
skinSlots = 1;
@ -90,7 +94,6 @@ std::string HLSL::GenerateVertUniformStruct(unsigned skinSlots, unsigned texMtxs
"};\n",
skinSlots, skinSlots);
if (texMtxs)
{
retval += hecl::Format("struct TCGMtx\n"
"{\n"
" float4x4 mtx;\n"
@ -100,7 +103,16 @@ std::string HLSL::GenerateVertUniformStruct(unsigned skinSlots, unsigned texMtxs
"{\n"
" TCGMtx texMtxs[%u];\n"
"};\n", texMtxs);
}
if (reflectionCoords)
retval += "cbuffer HECLReflectMtx : register(b3)\n"
"{\n"
" float4x4 indMtx;\n"
" float4x4 reflectMtx;\n"
" float reflectAlpha;\n"
"};\n"
"\n";
return retval;
}
@ -112,6 +124,20 @@ std::string HLSL::GenerateAlphaTest() const
" }\n";
}
std::string HLSL::GenerateReflectionExpr(ReflectionType type) const
{
switch (type)
{
case ReflectionType::None:
return "float3(0.0, 0.0, 0.0);\n";
case ReflectionType::Simple:
return "reflectionTex.Sample(samp, vtf.reflectTcgs[1]).rgb * vtf.reflectAlpha;\n";
case ReflectionType::Indirect:
return "reflectionTex.Sample(samp, (reflectionIndTex.Sample(samp, vtf.reflectTcgs[0]).rg - "
"float2(0.5, 0.5)) * float2(0.5, 0.5) + vtf.reflectTcgs[1]).rgb * vtf.reflectAlpha;\n";
}
}
void HLSL::reset(const IR& ir, Diagnostics& diag)
{
/* Common programmable interpretation */
@ -120,12 +146,12 @@ void HLSL::reset(const IR& ir, Diagnostics& diag)
std::string HLSL::makeVert(unsigned col, unsigned uv, unsigned w,
unsigned s, unsigned tm, size_t extTexCount,
const TextureInfo* extTexs) const
const TextureInfo* extTexs, ReflectionType reflectionType) const
{
std::string retval =
GenerateVertInStruct(col, uv, w) + "\n" +
GenerateVertToFragStruct(extTexCount) + "\n" +
GenerateVertUniformStruct(s, tm) + "\n" +
GenerateVertToFragStruct(extTexCount, reflectionType != ReflectionType::None) + "\n" +
GenerateVertUniformStruct(s, tm, reflectionType != ReflectionType::None) + "\n" +
"VertToFrag main(in VertData v)\n"
"{\n"
" VertToFrag vtf;\n";
@ -176,11 +202,17 @@ std::string HLSL::makeVert(unsigned col, unsigned uv, unsigned w,
extTex.mtxIdx, EmitTexGenSource4(extTex.src, extTex.uvIdx).c_str());
}
if (reflectionCoords)
retval += " vtf.reflectTcgs[0] = normalize(mul(indMtx, float4(v.posIn, 1.0)).xz) * float2(0.5, 0.5) + float2(0.5, 0.5);\n"
" vtf.reflectTcgs[1] = mul(reflectMtx, float4(v.posIn, 1.0)).xy;\n"
" vtf.reflectAlpha = reflectAlpha;\n";
return retval + " return vtf;\n"
"}\n";
}
std::string HLSL::makeFrag(bool alphaTest, const ShaderFunction& lighting) const
std::string HLSL::makeFrag(bool alphaTest, ReflectionType reflectionType,
const ShaderFunction& lighting) const
{
std::string lightingSrc;
if (lighting.m_source)
@ -194,10 +226,16 @@ std::string HLSL::makeFrag(bool alphaTest, const ShaderFunction& lighting) const
std::string texMapDecl;
if (m_texMapEnd)
texMapDecl = hecl::Format("Texture2D texs[%u] : register(t0);\n", m_texMapEnd);
if (reflectionType == ReflectionType::Indirect)
texMapDecl += hecl::Format("Texture2D reflectionIndTex : register(t%u);\n"
"Texture2D reflectionTex : register(t%u);\n",
m_texMapEnd, m_texMapEnd+1);
else if (reflectionType == ReflectionType::Simple)
texMapDecl += hecl::Format("Texture2D reflectionTex : register(t%u);\n",
m_texMapEnd);
std::string retval =
"SamplerState samp : register(s0);\n" +
GenerateVertToFragStruct(0) +
GenerateVertToFragStruct(0, reflectionType != ReflectionType::None) +
texMapDecl + "\n" +
lightingSrc + "\n" +
(!alphaTest ? "\n[earlydepthstencil]\n" : "\n") +
@ -217,16 +255,19 @@ std::string HLSL::makeFrag(bool alphaTest, const ShaderFunction& lighting) const
retval += hecl::Format(" float4 sampling%u = texs[%u].Sample(samp, vtf.tcgs[%u]);\n",
sampIdx++, sampling.mapIdx, sampling.tcgIdx);
std::string reflectionExpr = GenerateReflectionExpr(reflectionType);
retval += " float4 colorOut;\n";
if (m_alphaExpr.size())
retval += " colorOut = float4(" + m_colorExpr + ", " + m_alphaExpr + ") * mulColor;\n";
retval += " colorOut = float4(" + m_colorExpr + " + " + reflectionExpr + ", " + m_alphaExpr + ") * mulColor;\n";
else
retval += " colorOut = float4(" + m_colorExpr + ", 1.0) * mulColor;\n";
retval += " colorOut = float4(" + m_colorExpr + " + " + reflectionExpr + ", 1.0) * mulColor;\n";
return retval + (alphaTest ? GenerateAlphaTest() : "") + " return colorOut;\n}\n";
}
std::string HLSL::makeFrag(bool alphaTest, const ShaderFunction& lighting,
std::string HLSL::makeFrag(bool alphaTest, ReflectionType reflectionType,
const ShaderFunction& lighting,
const ShaderFunction& post, size_t extTexCount,
const TextureInfo* extTexs) const
{
@ -250,6 +291,13 @@ std::string HLSL::makeFrag(bool alphaTest, const ShaderFunction& lighting,
std::string texMapDecl;
if (m_texMapEnd)
texMapDecl = hecl::Format("Texture2D texs[%u] : register(t0);\n", m_texMapEnd);
if (reflectionType == ReflectionType::Indirect)
texMapDecl += hecl::Format("Texture2D reflectionIndTex : register(t%u);\n"
"Texture2D reflectionTex : register(t%u);\n",
m_texMapEnd, m_texMapEnd+1);
else if (reflectionType == ReflectionType::Simple)
texMapDecl += hecl::Format("Texture2D reflectionTex : register(t%u);\n",
m_texMapEnd);
for (int i=0 ; i<extTexCount ; ++i)
{
@ -260,7 +308,7 @@ std::string HLSL::makeFrag(bool alphaTest, const ShaderFunction& lighting,
std::string retval =
"SamplerState samp : register(s0);\n" +
GenerateVertToFragStruct(extTexCount) +
GenerateVertToFragStruct(extTexCount, reflectionType != ReflectionType::None) +
texMapDecl + "\n" +
lightingSrc + "\n" +
postSrc +
@ -281,11 +329,13 @@ std::string HLSL::makeFrag(bool alphaTest, const ShaderFunction& lighting,
retval += hecl::Format(" float4 sampling%u = texs[%u].Sample(samp, vtf.tcgs[%u]);\n",
sampIdx++, sampling.mapIdx, sampling.tcgIdx);
std::string reflectionExpr = GenerateReflectionExpr(reflectionType);
retval += " float4 colorOut;\n";
if (m_alphaExpr.size())
retval += " colorOut = " + postEntry + "(" + (postEntry.size() ? "vtf, " : "") + "float4(" + m_colorExpr + ", " + m_alphaExpr + ")) * mulColor;\n";
retval += " colorOut = " + postEntry + "(" + (postEntry.size() ? "vtf, " : "") + "float4(" + m_colorExpr + " + " + reflectionExpr + ", " + m_alphaExpr + ")) * mulColor;\n";
else
retval += " colorOut = " + postEntry + "(" + (postEntry.size() ? "vtf, " : "") + "float4(" + m_colorExpr + ", 1.0)) * mulColor;\n";
retval += " colorOut = " + postEntry + "(" + (postEntry.size() ? "vtf, " : "") + "float4(" + m_colorExpr + " + " + reflectionExpr + ", 1.0)) * mulColor;\n";
return retval + (alphaTest ? GenerateAlphaTest() : "") + " return colorOut;\n}\n";
}

View File

@ -72,7 +72,7 @@ std::string Metal::GenerateVertInStruct(unsigned col, unsigned uv, unsigned w) c
return retval + "};\n";
}
std::string Metal::GenerateVertToFragStruct(size_t extTexCount) const
std::string Metal::GenerateVertToFragStruct(size_t extTexCount, bool reflectionCoords) const
{
std::string retval =
"struct VertToFrag\n"
@ -82,15 +82,16 @@ std::string Metal::GenerateVertToFragStruct(size_t extTexCount) const
" float4 mvNorm;\n";
if (m_tcgs.size())
{
for (size_t i=0 ; i<m_tcgs.size() ; ++i)
retval += hecl::Format(" float2 tcgs%" PRISize ";\n", i);
}
if (extTexCount)
{
for (size_t i=0 ; i<extTexCount ; ++i)
retval += hecl::Format(" float2 extTcgs%" PRISize ";\n", i);
}
if (reflectionCoords)
retval += " float2 reflectTcgs0;\n"
" float2 reflectTcgs1;\n"
" float reflectAlpha;\n";
return retval + "};\n";
}
@ -105,7 +106,8 @@ std::string Metal::GenerateVertUniformStruct(unsigned skinSlots) const
" float4x4 mvInv[%u];\n"
" float4x4 proj;\n"
"};\n"
"struct TexMtxs {float4x4 mtx; float4x4 postMtx;};\n",
"struct TexMtxs {float4x4 mtx; float4x4 postMtx;};\n"
"struct ReflectTexMtxs {float4x4 indMtx; float4x4 reflectMtx; float reflectAlpha;};\n",
skinSlots, skinSlots);
return retval;
}
@ -127,6 +129,20 @@ std::string Metal::GenerateAlphaTest() const
" }\n";
}
std::string Metal::GenerateReflectionExpr(ReflectionType type) const
{
switch (type)
{
case ReflectionType::None:
return "float3(0.0, 0.0, 0.0);\n";
case ReflectionType::Simple:
return "reflectionTex.sample(samp, vtf.reflectTcgs1).rgb * vtf.reflectAlpha;\n";
case ReflectionType::Indirect:
return "reflectionTex.sample(samp, (reflectionIndTex.sample(samp, vtf.reflectTcgs0).rg - "
"float2(0.5, 0.5)) * float2(0.5, 0.5) + vtf.reflectTcgs1).rgb * vtf.reflectAlpha;\n";
}
}
void Metal::reset(const IR& ir, Diagnostics& diag)
{
/* Common programmable interpretation */
@ -135,14 +151,16 @@ void Metal::reset(const IR& ir, Diagnostics& diag)
std::string Metal::makeVert(unsigned col, unsigned uv, unsigned w,
unsigned s, unsigned tm, size_t extTexCount,
const TextureInfo* extTexs) const
const TextureInfo* extTexs, ReflectionType reflectionType) const
{
std::string tmStr;
if (tm)
tmStr = hecl::Format(",\nconstant TexMtxs* texMtxs [[ buffer(3) ]]");
if (reflectionType != ReflectionType::None)
tmStr += ",\nconstant ReflectTexMtxs& reflectMtxs [[ buffer(5) ]]";
std::string retval = "#include <metal_stdlib>\nusing namespace metal;\n" +
GenerateVertInStruct(col, uv, w) + "\n" +
GenerateVertToFragStruct(extTexCount) + "\n" +
GenerateVertToFragStruct(extTexCount, reflectionType != ReflectionType::None) + "\n" +
GenerateVertUniformStruct(s) +
"\nvertex VertToFrag vmain(VertData v [[ stage_in ]],\n"
" constant HECLVertUniform& vu [[ buffer(2) ]]" + tmStr + ")\n"
@ -194,11 +212,16 @@ std::string Metal::makeVert(unsigned col, unsigned uv, unsigned w,
extTex.normalize ? "normalize" : "", extTex.mtxIdx, EmitTexGenSource4(extTex.src, extTex.uvIdx).c_str());
}
if (reflectionType != ReflectionType::None)
retval += " vtf.reflectTcgs0 = normalize((reflectMtxs.indMtx * float4(v.posIn, 1.0)).xz) * float2(0.5, 0.5) + float2(0.5, 0.5);\n"
" vtf.reflectTcgs1 = (reflectMtxs.reflectMtx * float4(v.posIn, 1.0)).xy;\n"
" vtf.reflectAlpha = reflectMtxs.reflectAlpha;\n";
return retval + " return vtf;\n}\n";
}
std::string Metal::makeFrag(size_t blockCount, const char** blockNames, bool alphaTest,
const ShaderFunction& lighting) const
ReflectionType reflectionType, const ShaderFunction& lighting) const
{
std::string lightingSrc;
if (lighting.m_source)
@ -206,10 +229,15 @@ std::string Metal::makeFrag(size_t blockCount, const char** blockNames, bool alp
std::string texMapDecl;
if (m_texMapEnd)
{
for (int i=0 ; i<m_texMapEnd ; ++i)
texMapDecl += hecl::Format(",\ntexture2d<float> tex%u [[ texture(%u) ]]", i, i);
}
if (reflectionType == ReflectionType::Indirect)
texMapDecl += hecl::Format(",\ntexture2d<float> reflectionIndTex [[ texture(%u) ]]\n"
",\ntexture2d<float> reflectionTex [[ texture(%u) ]]\n",
m_texMapEnd, m_texMapEnd+1);
else if (reflectionType == ReflectionType::Simple)
texMapDecl += hecl::Format(",\ntexture2d<float> reflectionTex [[ texture(%u) ]]\n",
m_texMapEnd);
std::string blockCall;
for (size_t i=0 ; i<blockCount ; ++i)
@ -222,7 +250,7 @@ std::string Metal::makeFrag(size_t blockCount, const char** blockNames, bool alp
std::string retval = "#include <metal_stdlib>\nusing namespace metal;\n"
"constexpr sampler samp(address::repeat, filter::linear, mip_filter::linear);\n" +
GenerateVertToFragStruct(0) + "\n" +
GenerateVertToFragStruct(0, reflectionType != ReflectionType::None) + "\n" +
GenerateFragOutStruct() + "\n" +
lightingSrc + "\n" +
"fragment FragOut fmain(VertToFrag vtf [[ stage_in ]]" + texMapDecl + ")\n"
@ -257,10 +285,12 @@ std::string Metal::makeFrag(size_t blockCount, const char** blockNames, bool alp
retval += hecl::Format(" float4 sampling%u = tex%u.sample(samp, vtf.tcgs%u);\n",
sampIdx++, sampling.mapIdx, sampling.tcgIdx);
std::string reflectionExpr = GenerateReflectionExpr(reflectionType);
if (m_alphaExpr.size())
retval += " out.color = float4(" + m_colorExpr + ", " + m_alphaExpr + ") * mulColor;\n";
retval += " out.color = float4(" + m_colorExpr + " + " + reflectionExpr + ", " + m_alphaExpr + ") * mulColor;\n";
else
retval += " out.color = float4(" + m_colorExpr + ", 1.0) * mulColor;\n";
retval += " out.color = float4(" + m_colorExpr + " + " + reflectionExpr + ", 1.0) * mulColor;\n";
return retval + (alphaTest ? GenerateAlphaTest() : "") +
" //out.depth = 1.0 - float(int((1.0 - vtf.mvpPos.z) * 16777216.0)) / 16777216.0;\n"
@ -269,7 +299,7 @@ std::string Metal::makeFrag(size_t blockCount, const char** blockNames, bool alp
}
std::string Metal::makeFrag(size_t blockCount, const char** blockNames, bool alphaTest,
const ShaderFunction& lighting,
ReflectionType reflectionType, const ShaderFunction& lighting,
const ShaderFunction& post, size_t extTexCount,
const TextureInfo* extTexs) const
{
@ -294,11 +324,16 @@ std::string Metal::makeFrag(size_t blockCount, const char** blockNames, bool alp
std::string texMapDecl;
if (m_texMapEnd)
{
for (int i=0 ; i<m_texMapEnd ; ++i)
if (!(extTexBits & (1 << i)))
texMapDecl += hecl::Format(",\ntexture2d<float> tex%u [[ texture(%u) ]]", i, i);
}
if (reflectionType == ReflectionType::Indirect)
texMapDecl += hecl::Format(",\ntexture2d<float> reflectionIndTex [[ texture(%u) ]]\n"
",\ntexture2d<float> reflectionTex [[ texture(%u) ]]\n",
m_texMapEnd, m_texMapEnd+1);
else if (reflectionType == ReflectionType::Simple)
texMapDecl += hecl::Format(",\ntexture2d<float> reflectionTex [[ texture(%u) ]]\n",
m_texMapEnd);
std::string extTexCall;
for (int i=0 ; i<extTexCount ; ++i)
@ -322,7 +357,7 @@ std::string Metal::makeFrag(size_t blockCount, const char** blockNames, bool alp
std::string retval = "#include <metal_stdlib>\nusing namespace metal;\n"
"constexpr sampler samp(address::repeat, filter::linear, mip_filter::linear);\n" +
GenerateVertToFragStruct(extTexCount) + "\n" +
GenerateVertToFragStruct(extTexCount, reflectionType != ReflectionType::None) + "\n" +
GenerateFragOutStruct() + "\n" +
lightingSrc + "\n" +
postSrc + "\n" +
@ -358,12 +393,14 @@ std::string Metal::makeFrag(size_t blockCount, const char** blockNames, bool alp
retval += hecl::Format(" float4 sampling%u = tex%u.sample(samp, vtf.tcgs%u);\n",
sampIdx++, sampling.mapIdx, sampling.tcgIdx);
std::string reflectionExpr = GenerateReflectionExpr(reflectionType);
if (m_alphaExpr.size())
retval += " out.color = " + postEntry + "(" + (postEntry.size() ? ("vtf, " + (blockCall.size() ? (blockCall + ", ") : "") + (extTexCall.size() ? (extTexCall + ", ") : "")) : "") +
"float4(" + m_colorExpr + ", " + m_alphaExpr + ")) * mulColor;\n";
"float4(" + m_colorExpr + " + " + reflectionExpr + ", " + m_alphaExpr + ")) * mulColor;\n";
else
retval += " out.color = " + postEntry + "(" + (postEntry.size() ? ("vtf, " + (blockCall.size() ? (blockCall + ", ") : "") + (extTexCall.size() ? (extTexCall + ", ") : "")) : "") +
"float4(" + m_colorExpr + ", 1.0)) * mulColor;\n";
"float4(" + m_colorExpr + " + " + reflectionExpr + ", 1.0)) * mulColor;\n";
return retval + (alphaTest ? GenerateAlphaTest() : "") +
" //out.depth = 1.0 - float(int((1.0 - vtf.mvpPos.z) * 16777216.0)) / 16777216.0;\n"
@ -394,11 +431,12 @@ struct MetalBackendFactory : IShaderBackendFactory
std::string vertSource =
m_backend.makeVert(tag.getColorCount(), tag.getUvCount(), tag.getWeightCount(),
tag.getSkinSlotCount(), tag.getTexMtxCount(), 0, nullptr);
tag.getSkinSlotCount(), tag.getTexMtxCount(), 0, nullptr, tag.getReflectionType());
cachedSz += vertSource.size() + 1;
std::string fragSource = m_backend.makeFrag(0, nullptr,
tag.getDepthWrite() && m_backend.m_blendDst == hecl::Backend::BlendFactor::InvSrcAlpha);
tag.getDepthWrite() && m_backend.m_blendDst == hecl::Backend::BlendFactor::InvSrcAlpha,
tag.getReflectionType());
cachedSz += fragSource.size() + 1;
objOut =
static_cast<boo::MetalDataFactory::Context&>(ctx).
@ -470,10 +508,11 @@ struct MetalBackendFactory : IShaderBackendFactory
for (const ShaderCacheExtensions::ExtensionSlot& slot : extensionSlots)
{
sources.emplace_back(m_backend.makeVert(tag.getColorCount(), tag.getUvCount(), tag.getWeightCount(),
tag.getSkinSlotCount(), tag.getTexMtxCount(), slot.texCount, slot.texs),
tag.getSkinSlotCount(), tag.getTexMtxCount(), slot.texCount, slot.texs,
tag.getReflectionType()),
m_backend.makeFrag(slot.blockCount, slot.blockNames,
tag.getDepthWrite() && m_backend.m_blendDst == hecl::Backend::BlendFactor::InvSrcAlpha,
slot.lighting, slot.post, slot.texCount, slot.texs));
tag.getReflectionType(), slot.lighting, slot.post, slot.texCount, slot.texs));
cachedSz += sources.back().first.size() + 1;
cachedSz += sources.back().second.size() + 1;

View File

@ -89,7 +89,8 @@ struct HECLApplicationCallback : boo::IApplicationCallback
/* Compile HECL shader */
static std::string testShader = "HECLOpaque(Texture(0, UV(0)))";
//static std::string testShader = "HECLOpaque(vec4(1.0,1.0,1.0,1.0))";
hecl::Runtime::ShaderTag testShaderTag(testShader, 0, 1, 0, 0, 0, boo::Primitive::TriStrips, false, false, false);
hecl::Runtime::ShaderTag testShaderTag(testShader, 0, 1, 0, 0, 0, boo::Primitive::TriStrips,
hecl::Backend::ReflectionType::None, false, false, false);
std::shared_ptr<hecl::Runtime::ShaderPipelines> testShaderObj =
shaderMgr.buildShader(testShaderTag, testShader, "testShader", *gfxF);