diff --git a/CMakeLists.txt b/CMakeLists.txt index 1250bb0fe..14cdce832 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -251,9 +251,13 @@ bintoc(CModelShaders.frag.glsl.cpp Shaders/CModelShaders.frag.glsl CMODELSHADERS bintoc(CModelShaders.common.hlsl.cpp Shaders/CModelShaders.common.hlsl CMODELSHADERS_COMMON_HLSL) bintoc(CModelShaders.vert.hlsl.cpp Shaders/CModelShaders.vert.hlsl CMODELSHADERS_VERT_HLSL) bintoc(CModelShaders.frag.hlsl.cpp Shaders/CModelShaders.frag.hlsl CMODELSHADERS_FRAG_HLSL) +bintoc(CModelShaders.common.metal.cpp Shaders/CModelShaders.common.metal CMODELSHADERS_COMMON_METAL) +bintoc(CModelShaders.vert.metal.cpp Shaders/CModelShaders.vert.metal CMODELSHADERS_VERT_METAL) +bintoc(CModelShaders.frag.metal.cpp Shaders/CModelShaders.frag.metal CMODELSHADERS_FRAG_METAL) add_library(CModelShaders CModelShaders.common.glsl.cpp CModelShaders.vert.glsl.cpp CModelShaders.frag.glsl.cpp - CModelShaders.common.hlsl.cpp CModelShaders.vert.hlsl.cpp CModelShaders.frag.hlsl.cpp) + CModelShaders.common.hlsl.cpp CModelShaders.vert.hlsl.cpp CModelShaders.frag.hlsl.cpp + CModelShaders.common.metal.cpp CModelShaders.vert.metal.cpp CModelShaders.frag.metal.cpp) if(NOT TARGET atdna) # Import native atdna if cross-compiling diff --git a/Shaders/CModelShaders.common.glsl b/Shaders/CModelShaders.common.glsl index 41280f15b..e40749a21 100644 --- a/Shaders/CModelShaders.common.glsl +++ b/Shaders/CModelShaders.common.glsl @@ -1,4 +1,3 @@ -#extension GL_ARB_enhanced_layouts: enable #extension GL_ARB_shader_image_load_store: enable struct VertToFrag { diff --git a/Shaders/CModelShaders.common.metal b/Shaders/CModelShaders.common.metal new file mode 100644 index 000000000..6e9e3cb69 --- /dev/null +++ b/Shaders/CModelShaders.common.metal @@ -0,0 +1,21 @@ +#include +using namespace metal; + +struct VertToFrag { + float4 mvpPos [[ position ]]; + float4 mvPos; + float4 mvNorm; + float2 lightmapUv; + float2 diffuseUv; + float2 emissiveUv; + float2 specularUv; + float2 extendedSpecularUv; + float2 reflectionUv; + float2 alphaUv; + float2 extUvs0; + float2 extUvs1; + float2 extUvs2; + float2 dynReflectionUvs0; + float2 dynReflectionUvs1; + float dynReflectionAlpha; +}; diff --git a/Shaders/CModelShaders.frag.metal b/Shaders/CModelShaders.frag.metal new file mode 100644 index 000000000..034379829 --- /dev/null +++ b/Shaders/CModelShaders.frag.metal @@ -0,0 +1,367 @@ +constant float3 kRGBToYPrime = float3(0.257, 0.504, 0.098); + +/* +#if defined(ALPHA_%s) +#define SampleTexture_%s() %s.sample(samp, vtf.%sUv).aaa +#define SampleTextureAlpha_%s() %s.sample(samp, vtf.%sUv).a +#else +#define SampleTexture_%s() %s.sample(samp, vtf.%sUv).rgb +#define SampleTextureAlpha_%s() dot(%s.sample(samp, vtf.%sUv).rgb, kRGBToYPrime) +#endif + */ + +#if defined(ALPHA_lightmap) +#define SampleTexture_lightmap() lightmap.sample(samp, vtf.lightmapUv).aaa +#define SampleTextureAlpha_lightmap() lightmap.sample(samp, vtf.lightmapUv).a +#else +#define SampleTexture_lightmap() lightmap.sample(samp, vtf.lightmapUv).rgb +#define SampleTextureAlpha_lightmap() dot(lightmap.sample(samp, vtf.lightmapUv).rgb, kRGBToYPrime) +#endif + +#if defined(ALPHA_diffuse) +#define SampleTexture_diffuse() diffuse.sample(samp, vtf.diffuseUv).aaa +#define SampleTextureAlpha_diffuse() diffuse.sample(samp, vtf.diffuseUv).a +#else +#define SampleTexture_diffuse() diffuse.sample(samp, vtf.diffuseUv).rgb +#define SampleTextureAlpha_diffuse() dot(diffuse.sample(samp, vtf.diffuseUv).rgb, kRGBToYPrime) +#endif + +#if defined(ALPHA_emissive) +#define SampleTexture_emissive() emissive.sample(samp, vtf.emissiveUv).aaa +#define SampleTextureAlpha_emissive() emissive.sample(samp, vtf.emissiveUv).a +#else +#define SampleTexture_emissive() emissive.sample(samp, vtf.emissiveUv).rgb +#define SampleTextureAlpha_emissive() dot(emissive.sample(samp, vtf.emissiveUv).rgb, kRGBToYPrime) +#endif + +#if defined(ALPHA_specular) +#define SampleTexture_specular() specular.sample(samp, vtf.specularUv).aaa +#define SampleTextureAlpha_specular() specular.sample(samp, vtf.specularUv).a +#else +#define SampleTexture_specular() specular.sample(samp, vtf.specularUv).rgb +#define SampleTextureAlpha_specular() dot(specular.sample(samp, vtf.specularUv).rgb, kRGBToYPrime) +#endif + +#if defined(ALPHA_extendedSpecular) +#define SampleTexture_extendedSpecular() extendedSpecular.sample(samp, vtf.extendedSpecularUv).aaa +#define SampleTextureAlpha_extendedSpecular() extendedSpecular.sample(samp, vtf.extendedSpecularUv).a +#else +#define SampleTexture_extendedSpecular() extendedSpecular.sample(samp, vtf.extendedSpecularUv).rgb +#define SampleTextureAlpha_extendedSpecular() dot(extendedSpecular.sample(samp, vtf.extendedSpecularUv).rgb, kRGBToYPrime) +#endif + +#if defined(ALPHA_reflection) +#define SampleTexture_reflection() reflection.sample(samp, vtf.reflectionUv).aaa +#define SampleTextureAlpha_reflection() reflection.sample(samp, vtf.reflectionUv).a +#else +#define SampleTexture_reflection() reflection.sample(samp, vtf.reflectionUv).rgb +#define SampleTextureAlpha_reflection() dot(reflection.sample(samp, vtf.reflectionUv).rgb, kRGBToYPrime) +#endif + +#if defined(ALPHA_alpha) +#define SampleTexture_alpha() alpha.sample(samp, vtf.alphaUv).aaa +#define SampleTextureAlpha_alpha() alpha.sample(samp, vtf.alphaUv).a +#else +#define SampleTexture_alpha() alpha.sample(samp, vtf.alphaUv).rgb +#define SampleTextureAlpha_alpha() dot(alpha.sample(samp, vtf.alphaUv).rgb, kRGBToYPrime) +#endif + +#if defined(URDE_LIGHTING) || defined(URDE_LIGHTING_SHADOW) || defined(URDE_DISINTEGRATE) +struct Fog { + float4 color; + float A; + float B; + float C; + int mode; +}; +#endif + +#if defined(URDE_LIGHTING) || defined(URDE_LIGHTING_SHADOW) +struct Light { + float4 pos; + float4 dir; + float4 color; + float4 linAtt; + float4 angAtt; +}; + +struct LightingUniform { + Light lights[URDE_MAX_LIGHTS]; + float4 ambient; + float4 colorReg0; + float4 colorReg1; + float4 colorReg2; + float4 mulColor; + float4 addColor; + Fog fog; +}; +#define colorReg0 lu.colorReg0 +#define colorReg1 lu.colorReg1 +#define colorReg2 lu.colorReg2 +#else +constant float4 colorReg0 = float4(1.0, 1.0, 1.0, 1.0); +constant float4 colorReg1 = float4(1.0, 1.0, 1.0, 1.0); +constant float4 colorReg2 = float4(1.0, 1.0, 1.0, 1.0); +#endif + +#if defined(URDE_LIGHTING) +float3 LightingFunc(thread VertToFrag& vtf, constant LightingUniform& lu, texture2d extTex0, sampler clampSamp) { + float4 ret = lu.ambient; + + for (int i = 0; i < URDE_MAX_LIGHTS; ++i) { + float3 delta = vtf.mvPos.xyz - lu.lights[i].pos.xyz; + float dist = length(delta); + float3 deltaNorm = delta / dist; + float angDot = max(dot(deltaNorm, lu.lights[i].dir.xyz), 0.0); + float att = 1.0 / (lu.lights[i].linAtt[2] * dist * dist + + lu.lights[i].linAtt[1] * dist + + lu.lights[i].linAtt[0]); + float angAtt = lu.lights[i].angAtt[2] * angDot * angDot + + lu.lights[i].angAtt[1] * angDot + + lu.lights[i].angAtt[0]; + ret += lu.lights[i].color * angAtt * att * max(dot(-deltaNorm, vtf.mvNorm.xyz), 0.0); + } + + return saturate(ret.rgb); +} +#endif + +#if defined(URDE_THERMAL_HOT) +struct LightingUniform { + float4 tmulColor; + float4 taddColor; +}; +float3 LightingFunc(thread VertToFrag& vtf, constant LightingUniform& lu, texture2d extTex0, sampler clampSamp) { + return float3(1.0, 1.0, 1.0); +} +#endif + +#if defined(URDE_THERMAL_COLD) +struct LightingUniform {}; +float3 LightingFunc(thread VertToFrag& vtf, constant LightingUniform& lu, texture2d extTex0, sampler clampSamp) { + return float3(1.0, 1.0, 1.0); +} +#endif + +#if defined(URDE_SOLID) +struct LightingUniform { + float4 solidColor; +}; +float3 LightingFunc(thread VertToFrag& vtf, constant LightingUniform& lu, texture2d extTex0, sampler clampSamp) { + return float3(1.0, 1.0, 1.0); +} +#endif + +#if defined(URDE_MB_SHADOW) +struct LightingUniform { + float4 shadowUp; + float shadowId; +}; +float3 LightingFunc(thread VertToFrag& vtf, constant LightingUniform& lu, texture2d extTex0, sampler clampSamp) { + return float3(1.0, 1.0, 1.0); +} +#endif + +#if defined(URDE_LIGHTING_SHADOW) +float3 LightingFunc(thread VertToFrag& vtf, constant LightingUniform& lu, texture2d extTex0, sampler clampSamp) { + float2 shadowUV = vtf.extUvs0; + shadowUV.y = 1.0 - shadowUV.y; + + float4 ret = lu.ambient; + + float3 delta = vtf.mvPos.xyz - lu.lights[0].pos.xyz; + float dist = length(delta); + float3 deltaNorm = delta / dist; + float angDot = max(dot(deltaNorm, lu.lights[0].dir.xyz), 0.0); + float att = 1.0 / (lu.lights[0].linAtt[2] * dist * dist + + lu.lights[0].linAtt[1] * dist + + lu.lights[0].linAtt[0]); + float angAtt = lu.lights[0].angAtt[2] * angDot * angDot + + lu.lights[0].angAtt[1] * angDot + + lu.lights[0].angAtt[0]; + ret += lu.lights[0].color * angAtt * att * max(dot(-deltaNorm, vtf.mvNorm.xyz), 0.0) * + extTex0.sample(clampSamp, shadowUV).r; + + for (int i = 1; i < URDE_MAX_LIGHTS; ++i) { + float3 delta = vtf.mvPos.xyz - lu.lights[i].pos.xyz; + float dist = length(delta); + float3 deltaNorm = delta / dist; + float angDot = max(dot(deltaNorm, lu.lights[i].dir.xyz), 0.0); + float att = 1.0 / (lu.lights[i].linAtt[2] * dist * dist + + lu.lights[i].linAtt[1] * dist + + lu.lights[i].linAtt[0]); + float angAtt = lu.lights[i].angAtt[2] * angDot * angDot + + lu.lights[i].angAtt[1] * angDot + + lu.lights[i].angAtt[0]; + ret += lu.lights[i].color * angAtt * att * max(dot(-deltaNorm, vtf.mvNorm.xyz), 0.0); + } + + return saturate(ret.rgb); +} +#endif + +#if defined(URDE_DISINTEGRATE) +struct LightingUniform { + float4 daddColor; + Fog fog; +}; +float3 LightingFunc(thread VertToFrag& vtf, constant LightingUniform& lu, texture2d extTex0, sampler clampSamp) { + return float3(1.0, 1.0, 1.0); +} +#endif + +#if defined(URDE_LIGHTING) || defined(URDE_LIGHTING_SHADOW) || defined(URDE_DISINTEGRATE) +float4 FogFunc(thread VertToFrag& vtf, constant LightingUniform& lu, float4 colorIn) { + float fogZ; + float fogF = saturate((lu.fog.A / (lu.fog.B - (1.0 - vtf.mvpPos.z))) - lu.fog.C); + switch (lu.fog.mode) { + case 2: + fogZ = fogF; + break; + case 4: + fogZ = 1.0 - exp2(-8.0 * fogF); + break; + case 5: + fogZ = 1.0 - exp2(-8.0 * fogF * fogF); + break; + case 6: + fogZ = exp2(-8.0 * (1.0 - fogF)); + break; + case 7: + fogF = 1.0 - fogF; + fogZ = exp2(-8.0 * fogF * fogF); + break; + default: + fogZ = 0.0; + break; + } +#ifdef BLEND_DST_ONE + return float4(mix(colorIn, float4(0.0, 0.0, 0.0, 0.0), saturate(fogZ)).rgb, colorIn.a); +#else + return float4(mix(colorIn, lu.fog.color, saturate(fogZ)).rgb, colorIn.a); +#endif +} +#endif + +#if defined(URDE_LIGHTING) || defined(URDE_LIGHTING_SHADOW) +float4 PostFunc(thread VertToFrag& vtf, constant LightingUniform& lu, + texture2d extTex0, texture2d extTex1, texture2d extTex2, + sampler samp, float4 colorIn) { + return FogFunc(vtf, lu, colorIn) * lu.mulColor + lu.addColor; +} +#endif + +#if defined(URDE_THERMAL_HOT) +float4 PostFunc(thread VertToFrag& vtf, constant LightingUniform& lu, + texture2d extTex0, texture2d extTex1, texture2d extTex2, + sampler samp, float4 colorIn) { + return extTex0.sample(samp, vtf.extUvs0).rrrr * lu.tmulColor + lu.taddColor; +} +#endif + +#if defined(URDE_THERMAL_COLD) +float4 PostFunc(thread VertToFrag& vtf, constant LightingUniform& lu, + texture2d extTex0, texture2d extTex1, texture2d extTex2, + sampler samp, float4 colorIn) { + return colorIn * float4(0.75, 0.75, 0.75, 0.75); +} +#endif + +#if defined(URDE_SOLID) +float4 PostFunc(thread VertToFrag& vtf, constant LightingUniform& lu, + texture2d extTex0, texture2d extTex1, texture2d extTex2, + sampler samp, float4 colorIn) { + return lu.solidColor; +} +#endif + +#if defined(URDE_MB_SHADOW) +float4 PostFunc(thread VertToFrag& vtf, constant LightingUniform& lu, + texture2d extTex0, texture2d extTex1, texture2d extTex2, + sampler samp, float4 colorIn) { + float idTexel = extTex0.sample(samp, vtf.extUvs0).a; + float sphereTexel = extTex1.sample(samp, vtf.extUvs1).a; + float fadeTexel = extTex2.sample(samp, vtf.extUvs2).a; + float val = ((abs(idTexel - lu.shadowId) < 0.001) ? + (dot(vtf.mvNorm.xyz, lu.shadowUp.xyz) * lu.shadowUp.w) : 0.0) * + sphereTexel * fadeTexel; + return float4(0.0, 0.0, 0.0, val); +} +#endif + +#if defined(URDE_DISINTEGRATE) +float4 PostFunc(thread VertToFrag& vtf, constant LightingUniform& lu, + texture2d extTex0, texture2d extTex1, texture2d extTex2, + sampler samp, float4 colorIn) { + float4 texel0 = extTex0.sample(samp, vtf.extUvs0); + float4 texel1 = extTex0.sample(samp, vtf.extUvs1); + colorIn = mix(float4(0.0, 0.0, 0.0, 0.0), texel1, texel0); + colorIn.rgb += lu.daddColor.rgb; + return FogFunc(vtf, lu, colorIn); +} +#endif + +#if defined(URDE_REFLECTION_SIMPLE) +#define ReflectionFunc() \ + (reflectionTex.sample(reflectSamp, vtf.dynReflectionUvs1).rgb * vtf.dynReflectionAlpha) +#elif defined(URDE_REFLECTION_INDIRECT) +#define ReflectionFunc() \ + (reflectionTex.sample(reflectSamp, (reflectionIndTex.sample(samp, vtf.dynReflectionUvs0).ab - \ + float2(0.5, 0.5)) * float2(0.5, 0.5) + vtf.dynReflectionUvs1).rgb * vtf.dynReflectionAlpha) +#else +#define ReflectionFunc() float3(0.0, 0.0, 0.0) +#endif + +#if !defined(URDE_ALPHA_TEST) +[[ early_fragment_tests ]] +#endif +fragment float4 fmain(VertToFrag vtf [[ stage_in ]], + sampler samp [[ sampler(0) ]], + sampler clampSamp [[ sampler(1) ]], + sampler reflectSamp [[ sampler(2) ]], + texture2d lightmap [[ texture(0) ]], + texture2d diffuse [[ texture(1) ]], + texture2d emissive [[ texture(2) ]], + texture2d specular [[ texture(3) ]], + texture2d extendedSpecular [[ texture(4) ]], + texture2d reflection [[ texture(5) ]], + texture2d alpha [[ texture(6) ]], + texture2d reflectionIndTex [[ texture(7) ]], + texture2d extTex0 [[ texture(8) ]], + texture2d extTex1 [[ texture(9) ]], + texture2d extTex2 [[ texture(10) ]], + texture2d reflectionTex [[ texture(11) ]], + constant LightingUniform& lu [[ buffer(4) ]]) { + float3 lighting = LightingFunc(vtf, lu, extTex0, clampSamp); + float4 tmp; +#if defined(URDE_DIFFUSE_ONLY) + tmp.rgb = SampleTexture_diffuse(); + tmp.a = SampleTextureAlpha_alpha(); +#elif defined(RETRO_SHADER) + tmp.rgb = (SampleTexture_lightmap() * colorReg1.rgb + lighting) * SampleTexture_diffuse() + + SampleTexture_emissive() + (SampleTexture_specular() + SampleTexture_extendedSpecular() * lighting) * + SampleTexture_reflection() + ReflectionFunc(); + tmp.a = SampleTextureAlpha_alpha(); +#elif defined(RETRO_DYNAMIC_SHADER) + tmp.rgb = (SampleTexture_lightmap() * colorReg1.rgb + lighting) * SampleTexture_diffuse() * colorReg1.rgb + + SampleTexture_emissive() * colorReg1.rgb + (SampleTexture_specular() + SampleTexture_extendedSpecular() * lighting) * + SampleTexture_reflection() + ReflectionFunc(); + tmp.a = SampleTextureAlpha_alpha(); +#elif defined(RETRO_DYNAMIC_ALPHA_SHADER) + tmp.rgb = (SampleTexture_lightmap() * colorReg1.rgb + lighting) * SampleTexture_diffuse() * colorReg1.rgb + + SampleTexture_emissive() * colorReg1.rgb + (SampleTexture_specular() + SampleTexture_extendedSpecular() * lighting) * + SampleTexture_reflection() + ReflectionFunc(); + tmp.a = SampleTextureAlpha_alpha() * colorReg1.a; +#elif defined(RETRO_DYNAMIC_CHARACTER_SHADER) + tmp.rgb = (SampleTexture_lightmap() + lighting) * SampleTexture_diffuse() + + SampleTexture_emissive() * colorReg1.rgb + (SampleTexture_specular() + SampleTexture_extendedSpecular() * lighting) * + SampleTexture_reflection() + ReflectionFunc(); + tmp.a = SampleTextureAlpha_alpha(); +#endif + float4 colorOut = PostFunc(vtf, lu, extTex0, extTex1, extTex2, samp, tmp); +#if defined(URDE_ALPHA_TEST) + if (colorOut.a < 0.25) + discard_fragment(); +#endif + return colorOut; +} diff --git a/Shaders/CModelShaders.vert.glsl b/Shaders/CModelShaders.vert.glsl index c4c170cbd..83884b406 100644 --- a/Shaders/CModelShaders.vert.glsl +++ b/Shaders/CModelShaders.vert.glsl @@ -22,17 +22,7 @@ UBINDING3 uniform URDEReflectMtx { float reflectAlpha; }; -layout(location=0) in vec3 posIn; -layout(location=1) in vec3 normIn; -#if URDE_COL_SLOTS -layout(location=2) in vec4 colIn[URDE_COL_SLOTS]; -#endif -#if URDE_UV_SLOTS -layout(location=2 + URDE_COL_SLOTS) in vec2 uvIn[URDE_UV_SLOTS]; -#endif -#if URDE_WEIGHT_SLOTS -layout(location=2 + URDE_COL_SLOTS + URDE_UV_SLOTS) in vec4 weightIn[URDE_WEIGHT_SLOTS]; -#endif +URDE_VERT_DATA_DECL SBINDING(0) out VertToFrag vtf; void main() { diff --git a/Shaders/CModelShaders.vert.metal b/Shaders/CModelShaders.vert.metal new file mode 100644 index 000000000..d97837edb --- /dev/null +++ b/Shaders/CModelShaders.vert.metal @@ -0,0 +1,60 @@ +struct URDEVertUniform { +#if URDE_SKIN_SLOTS + float4x4 objs[URDE_SKIN_SLOTS]; + float4x4 objsInv[URDE_SKIN_SLOTS]; +#endif + float4x4 mv; + float4x4 mvInv; + float4x4 proj; +}; + +struct URDETCGMatrix { + float4x4 mtx; + float4x4 postMtx; +}; +struct URDETexMtxUniform { + URDETCGMatrix texMtxs[8]; +}; + +struct URDEReflectMtx { + float4x4 indMtx; + float4x4 reflectMtx; + float reflectAlpha; +}; + +URDE_VERT_DATA_DECL + +vertex VertToFrag vmain(VertData v [[ stage_in ]], + constant URDEVertUniform& vu [[ buffer(2) ]], + constant URDETexMtxUniform& tu [[ buffer(3) ]], + constant URDEReflectMtx& ru [[ buffer(5) ]]) { + VertToFrag vtf; +#if URDE_SKIN_SLOTS + float4 objPos = float4(0.0, 0.0, 0.0, 0.0); + float4 objNorm = float4(0.0, 0.0, 0.0, 0.0); +URDE_WEIGHTING_EXPR + objPos[3] = 1.0; + objNorm = float4(normalize(objNorm.xyz), 0.0); + vtf.mvPos = vu.mv * objPos; + vtf.mvNorm = float4(normalize((vu.mvInv * objNorm).xyz), 0.0); + vtf.mvpPos = vu.proj * vtf.mvPos; +#else + float4 objPos = float4(v.posIn, 1.0); + float4 objNorm = float4(v.normIn, 0.0); + vtf.mvPos = vu.mv * objPos; + vtf.mvNorm = vu.mvInv * objNorm; + vtf.mvpPos = vu.proj * vtf.mvPos; +#endif + + vtf.lightmapUv = float2(0.0, 0.0); + vtf.diffuseUv = float2(0.0, 0.0); + vtf.emissiveUv = float2(0.0, 0.0); + vtf.specularUv = float2(0.0, 0.0); + vtf.extendedSpecularUv = float2(0.0, 0.0); + vtf.reflectionUv = float2(0.0, 0.0); + vtf.alphaUv = float2(0.0, 0.0); + float4 tmpProj; + URDE_TCG_EXPR + + return vtf; +} diff --git a/Shaders/shader_CModelShaders.hpp b/Shaders/shader_CModelShaders.hpp index 63a0bf496..eef26b673 100644 --- a/Shaders/shader_CModelShaders.hpp +++ b/Shaders/shader_CModelShaders.hpp @@ -18,7 +18,7 @@ struct SModelShadersInfo { const hecl::Backend::ExtensionSlot& extension) : m_material(material), m_tag(tag), m_extension(extension) { m_hash = m_tag.val64(); - hecl::hash_combine_impl(m_hash, std::hash()(m_extension.hash())); + hecl::hash_combine_impl(m_hash, std::hash()(m_extension.hash())); m_vtxFmtData = tag.vertexFormat(); m_vtxFmt = boo::VertexFormatInfo(m_vtxFmtData.size(), m_vtxFmtData.data()); diff --git a/Shaders/shader_CModelShadersGLSL.cpp b/Shaders/shader_CModelShadersGLSL.cpp index 69753fa79..42d010644 100644 --- a/Shaders/shader_CModelShadersGLSL.cpp +++ b/Shaders/shader_CModelShadersGLSL.cpp @@ -84,8 +84,20 @@ static std::string _BuildVS(const SModelShadersInfo& info) { vertOut << "#define URDE_UV_SLOTS "sv << unsigned(info.m_tag.getUvCount()) << '\n'; vertOut << "#define URDE_SKIN_SLOTS "sv << unsigned(info.m_tag.getSkinSlotCount()) << '\n'; vertOut << "#define URDE_WEIGHT_SLOTS "sv << unsigned(info.m_tag.getWeightCount()) << '\n'; - vertOut << "#define URDE_TCG_EXPR "sv; + vertOut << "#define URDE_VERT_DATA_DECL " + "layout(location=0) in vec3 posIn;" + "layout(location=1) in vec3 normIn;"sv; + if (info.m_tag.getColorCount()) + vertOut << "layout(location=2) in vec4 colIn["sv << unsigned(info.m_tag.getColorCount()) << "];"sv; + if (info.m_tag.getUvCount()) + vertOut << "layout(location="sv << 2 + info.m_tag.getColorCount() << + ") in vec2 uvIn["sv << unsigned(info.m_tag.getUvCount()) << "];"sv; + if (info.m_tag.getWeightCount()) + vertOut << "layout(location="sv << 2 + info.m_tag.getColorCount() + info.m_tag.getUvCount() << + ") in vec4 weightIn["sv << unsigned(info.m_tag.getWeightCount()) << "];"sv; + + vertOut << "#define URDE_TCG_EXPR "sv; using UVAnimType = BlendMaterial::UVAnimType; using PassType = BlendMaterial::PassType; int mtxIdx = 0; diff --git a/Shaders/shader_CModelShadersHLSL.cpp b/Shaders/shader_CModelShadersHLSL.cpp index 6bc2693ea..6faf7c05c 100644 --- a/Shaders/shader_CModelShadersHLSL.cpp +++ b/Shaders/shader_CModelShadersHLSL.cpp @@ -84,8 +84,8 @@ static std::string _BuildVS(const SModelShadersInfo& info) { vertOut << "#define URDE_UV_SLOTS "sv << unsigned(info.m_tag.getUvCount()) << '\n'; vertOut << "#define URDE_SKIN_SLOTS "sv << unsigned(info.m_tag.getSkinSlotCount()) << '\n'; vertOut << "#define URDE_WEIGHT_SLOTS "sv << unsigned(info.m_tag.getWeightCount()) << '\n'; - vertOut << "#define URDE_TCG_EXPR "sv; + vertOut << "#define URDE_TCG_EXPR "sv; using UVAnimType = BlendMaterial::UVAnimType; using PassType = BlendMaterial::PassType; int mtxIdx = 0; diff --git a/Shaders/shader_CModelShadersMetal.cpp b/Shaders/shader_CModelShadersMetal.cpp index e69de29bb..a7cb6eeaf 100644 --- a/Shaders/shader_CModelShadersMetal.cpp +++ b/Shaders/shader_CModelShadersMetal.cpp @@ -0,0 +1,218 @@ +#include +#include +#include +#include "shader_CModelShaders.hpp" +#include "Runtime/Graphics/Shaders/CModelShaders.hpp" + +extern "C" const uint8_t CMODELSHADERS_COMMON_METAL[]; +extern "C" size_t CMODELSHADERS_COMMON_METAL_SZ; +static std::string_view CMODELSHADERS_COMMON_METAL_SV((char*)CMODELSHADERS_COMMON_METAL, CMODELSHADERS_COMMON_METAL_SZ); + +extern "C" const uint8_t CMODELSHADERS_VERT_METAL[]; +extern "C" size_t CMODELSHADERS_VERT_METAL_SZ; +static std::string_view CMODELSHADERS_VERT_METAL_SV((char*)CMODELSHADERS_VERT_METAL, CMODELSHADERS_VERT_METAL_SZ); + +extern "C" const uint8_t CMODELSHADERS_FRAG_METAL[]; +extern "C" size_t CMODELSHADERS_FRAG_METAL_SZ; +static std::string_view CMODELSHADERS_FRAG_METAL_SV((char*)CMODELSHADERS_FRAG_METAL, CMODELSHADERS_FRAG_METAL_SZ); + +using BlendMaterial = SModelShadersInfo::Material::BlendMaterial; +using TexCoordSource = BlendMaterial::TexCoordSource; + +static std::string_view EmitTexGenSource2(TexCoordSource src) { + switch (src) { + case TexCoordSource::Position: + return "objPos.xy"sv; + case TexCoordSource::Normal: + return "objNorm.xy"sv; + case TexCoordSource::Tex0: + return "v.uvIn0"sv; + case TexCoordSource::Tex1: + return "v.uvIn1"sv; + case TexCoordSource::Tex2: + return "v.uvIn2"sv; + case TexCoordSource::Tex3: + return "v.uvIn3"sv; + case TexCoordSource::Tex4: + return "v.uvIn4"sv; + case TexCoordSource::Tex5: + return "v.uvIn5"sv; + case TexCoordSource::Tex6: + return "v.uvIn6"sv; + case TexCoordSource::Tex7: + return "v.uvIn7"sv; + default: + assert(false && "Unknown source type"); + break; + } + return {}; +} + +static std::string_view EmitTexGenSource4(TexCoordSource src) { + switch (src) { + case TexCoordSource::Position: + return "float4(objPos.xyz, 1.0)"sv; + case TexCoordSource::Normal: + return "float4(objNorm.xyz, 1.0)"sv; + case TexCoordSource::Tex0: + return "float4(v.uvIn0, 0.0, 1.0)"sv; + case TexCoordSource::Tex1: + return "float4(v.uvIn1, 0.0, 1.0)"sv; + case TexCoordSource::Tex2: + return "float4(v.uvIn2, 0.0, 1.0)"sv; + case TexCoordSource::Tex3: + return "float4(v.uvIn3, 0.0, 1.0)"sv; + case TexCoordSource::Tex4: + return "float4(v.uvIn4, 0.0, 1.0)"sv; + case TexCoordSource::Tex5: + return "float4(v.uvIn5, 0.0, 1.0)"sv; + case TexCoordSource::Tex6: + return "float4(v.uvIn6, 0.0, 1.0)"sv; + case TexCoordSource::Tex7: + return "float4(v.uvIn7, 0.0, 1.0)"sv; + default: + assert(false && "Unknown source type"); + break; + } + return {}; +} + +static std::string _BuildVS(const SModelShadersInfo& info) { + std::stringstream vertOut; + vertOut << CMODELSHADERS_COMMON_METAL_SV; + vertOut << "#define URDE_COL_SLOTS "sv << unsigned(info.m_tag.getColorCount()) << '\n'; + vertOut << "#define URDE_UV_SLOTS "sv << unsigned(info.m_tag.getUvCount()) << '\n'; + vertOut << "#define URDE_SKIN_SLOTS "sv << unsigned(info.m_tag.getSkinSlotCount()) << '\n'; + vertOut << "#define URDE_WEIGHT_SLOTS "sv << unsigned(info.m_tag.getWeightCount()) << '\n'; + + vertOut << "#define URDE_VERT_DATA_DECL struct VertData {" + "float3 posIn [[ attribute(0) ]];" + "float3 normIn [[ attribute(1) ]];"sv; + for (unsigned i = 0; i < unsigned(info.m_tag.getColorCount()); ++i) + vertOut << "float4 colIn"sv << i << " [[ attribute("sv << 2 + i << ") ]];"sv; + for (unsigned i = 0; i < unsigned(info.m_tag.getUvCount()); ++i) + vertOut << "float2 uvIn"sv << i << " [[ attribute("sv << 2 + info.m_tag.getColorCount() + i << ") ]];"sv; + for (unsigned i = 0; i < unsigned(info.m_tag.getWeightCount()); ++i) + vertOut << "float4 weightIn"sv << i << " [[ attribute("sv << + 2 + info.m_tag.getColorCount() + info.m_tag.getUvCount() + i << ") ]];"sv; + vertOut << "};\n"sv; + + if (info.m_tag.getSkinSlotCount()) { + vertOut << "#define URDE_WEIGHTING_EXPR "sv; + for (unsigned i = 0; i < info.m_tag.getSkinSlotCount(); ++i) { + vertOut << "objPos += (vu.objs["sv << i << "] * float4(v.posIn, 1.0)) * v.weightIn"sv << i / 4 << "["sv << i % 4 <<"];"sv; + vertOut << "objNorm += (vu.objsInv["sv << i << "] * float4(v.normIn, 1.0)) * v.weightIn"sv << i / 4 << "["sv << i % 4 <<"];"sv; + } + vertOut << '\n'; + } + + vertOut << "#define URDE_TCG_EXPR "sv; + using UVAnimType = BlendMaterial::UVAnimType; + using PassType = BlendMaterial::PassType; + int mtxIdx = 0; + for (const auto& chunk : info.m_material.chunks) { + if (auto passChunk = chunk.get_if()) { + if (passChunk->type != PassType::IndirectTex) { + std::string_view tpStr = BlendMaterial::PassTypeToString(passChunk->type); + if (passChunk->uvAnimType == UVAnimType::Invalid) { + vertOut << "vtf."sv << tpStr << "Uv = "sv << EmitTexGenSource2(passChunk->source) << ";"sv; + } else { + vertOut << "tmpProj = tu.texMtxs["sv << mtxIdx << "].postMtx * float4("sv << + (passChunk->shouldNormalizeUv() ? "normalize"sv : ""sv) << "((tu.texMtxs["sv << mtxIdx << "].mtx * "sv << + EmitTexGenSource4(passChunk->source) << ").xyz), 1.0);"sv << + "vtf."sv << tpStr << "Uv = (tmpProj / tmpProj.w).xy;"sv; + } + } + } else if (auto clrChunk = chunk.get_if()) { + std::string_view tpStr = BlendMaterial::PassTypeToString(clrChunk->type); + vertOut << "vtf."sv << tpStr << "Uv = float2(0.0,0.0);"sv; + } + } + if (!info.m_extension.noReflection && info.m_tag.getReflectionType() != hecl::Backend::ReflectionType::None) + vertOut << "vtf.dynReflectionUvs0 = normalize((ru.indMtx * float4(objPos.xyz, 1.0)).xz) * float2(0.5, 0.5) + float2(0.5, 0.5);" + "vtf.dynReflectionUvs1 = (ru.reflectMtx * float4(objPos.xyz, 1.0)).xy;" + "vtf.dynReflectionAlpha = ru.reflectAlpha;"; + + for (size_t i = 0; i < info.m_extension.texCount; ++i) { + const auto& extTex = info.m_extension.texs[i]; + if (extTex.mtxIdx == 0xff) + vertOut << "vtf.extUvs"sv << i << " = "sv << EmitTexGenSource2(extTex.src) << ";"sv; + else + vertOut << "tmpProj = tu.texMtxs["sv << unsigned(extTex.mtxIdx) << "].postMtx * float4("sv << + (extTex.normalize ? "normalize"sv : ""sv) << "((tu.texMtxs["sv << unsigned(extTex.mtxIdx) << "].mtx * "sv << + EmitTexGenSource4(extTex.src) << ").xyz), 1.0);"sv << + "vtf.extUvs"sv << i << " = (tmpProj / tmpProj.w).xy;"sv; + } + vertOut << '\n'; + + vertOut << CMODELSHADERS_VERT_METAL_SV; + return vertOut.str(); +} + +static std::string _BuildFS(const SModelShadersInfo& info) { + std::stringstream fragOut; + fragOut << CMODELSHADERS_COMMON_METAL_SV; + fragOut << "#define URDE_MAX_LIGHTS " _XSTR(URDE_MAX_LIGHTS) "\n"; + fragOut << "#define " << info.m_extension.shaderMacro << "\n"; + + using ShaderType = BlendMaterial::ShaderType; + switch (info.m_material.shaderType) { + case ShaderType::RetroShader: + fragOut << "#define RETRO_SHADER\n"; break; + case ShaderType::RetroDynamicShader: + fragOut << "#define RETRO_DYNAMIC_SHADER\n"; break; + case ShaderType::RetroDynamicAlphaShader: + fragOut << "#define RETRO_DYNAMIC_ALPHA_SHADER\n"; break; + case ShaderType::RetroDynamicCharacterShader: + fragOut << "#define RETRO_DYNAMIC_CHARACTER_SHADER\n"; break; + default: + assert(false && "Unknown shader type"); + break; + } + + fragOut << "#define BLEND_SRC_"sv << hecl::Backend::BlendFactorToDefine( + hecl::Backend::BlendFactor(info.m_additionalInfo.srcFac), hecl::Backend::BlendFactor::One) << '\n'; + fragOut << "#define BLEND_DST_"sv << hecl::Backend::BlendFactorToDefine( + hecl::Backend::BlendFactor(info.m_additionalInfo.dstFac), hecl::Backend::BlendFactor::Zero) << '\n'; + + using PassType = BlendMaterial::PassType; + for (const auto& chunk : info.m_material.chunks) { + if (auto passChunk = chunk.get_if()) { + if (passChunk->alpha) { + std::string_view tpStr = BlendMaterial::PassTypeToString(passChunk->type); + fragOut << "#define ALPHA_" << tpStr << '\n'; + } + } else if (auto clrChunk = chunk.get_if()) { + if (clrChunk->type == PassType::Alpha) + fragOut << "#define ALPHA_alpha\n"; + } + } + + if (info.m_tag.getAlphaTest() || info.m_extension.forceAlphaTest) + fragOut << "#define URDE_ALPHA_TEST\n"; + + if (info.m_extension.diffuseOnly) + fragOut << "#define URDE_DIFFUSE_ONLY\n"; + + if (!info.m_extension.noReflection) { + if (info.m_tag.getReflectionType() == hecl::Backend::ReflectionType::Indirect) + fragOut << "#define URDE_REFLECTION_INDIRECT\n"sv; + else if (info.m_tag.getReflectionType() == hecl::Backend::ReflectionType::Simple) + fragOut << "#define URDE_REFLECTION_SIMPLE\n"sv; + } + + fragOut << CMODELSHADERS_FRAG_METAL_SV; + return fragOut.str(); +} + +template <> +std::string StageObject_CModelShaders::BuildShader( + const SModelShadersInfo& in) { + return _BuildVS(in); +} + +template <> +std::string StageObject_CModelShaders::BuildShader( + const SModelShadersInfo& in) { + return _BuildFS(in); +} diff --git a/hecl b/hecl index 4d0c69b26..4c65ccf85 160000 --- a/hecl +++ b/hecl @@ -1 +1 @@ -Subproject commit 4d0c69b261948114dcb971b9f1ec9cec58bd194c +Subproject commit 4c65ccf85be21b9869dcdaea09692ca6677f3204