diff --git a/Engine/Auto/Scripts/editor.lua b/Engine/Auto/Scripts/editor.lua index 2b4b8486..74568e8e 100644 --- a/Engine/Auto/Scripts/editor.lua +++ b/Engine/Auto/Scripts/editor.lua @@ -112,18 +112,15 @@ project("Editor") staticruntime "on" filter { "configurations:Debug" } runtime "Debug" -- /MTd - libdirs { - BinariesPath, - path.join(ThirdPartySourcePath, "AssetPipeline/build/bin/Debug"), - } filter { "configurations:Release" } runtime "Release" -- /MT - libdirs { - BinariesPath, - path.join(ThirdPartySourcePath, "AssetPipeline/build/bin/Release"), - } filter {} + libdirs { + BinariesPath, + path.join(ThirdPartySourcePath, "AssetPipeline/build/bin/%{cfg.buildcfg}"), + } + links { "Engine", "AssetPipelineCore", @@ -141,6 +138,18 @@ project("Editor") } end + if ENABLE_FBX_WORKFLOW then + links { + "FbxConsumer", + "FbxProducer", + } + + defines { + "ENABLE_FBX_CONSUMER", + "ENABLE_FBX_PRODUCER", + } + end + -- Disable these options can reduce the size of compiled binaries. justmycode("Off") editAndContinue("Off") diff --git a/Engine/Auto/Scripts/premake5.lua b/Engine/Auto/Scripts/premake5.lua index d74e1c53..269ca89f 100644 --- a/Engine/Auto/Scripts/premake5.lua +++ b/Engine/Auto/Scripts/premake5.lua @@ -25,24 +25,6 @@ function IsIOSPlatform() return ChoosePlatform == "IOS" end -USE_CLANG_TOOLSET = false -if os.getenv("USE_CLANG_TOOLSET") then - USE_CLANG_TOOLSET = true -end - -DDGI_SDK_PATH = os.getenv("DDGI_SDK_PATH") or "" -if not os.isdir(DDGI_SDK_PATH) then - DDGI_SDK_PATH = "" -end - -ENABLE_FREETYPE = not USE_CLANG_TOOLSET and not IsLinuxPlatform() and not IsAndroidPlatform() -ENABLE_SPDLOG = not USE_CLANG_TOOLSET and not IsLinuxPlatform() and not IsAndroidPlatform() -ENABLE_SUBPROCESS = not USE_CLANG_TOOLSET and not IsLinuxPlatform() and not IsAndroidPlatform() -ENABLE_TRACY = not USE_CLANG_TOOLSET and not IsLinuxPlatform() and not IsAndroidPlatform() -ENABLE_DDGI = DDGI_SDK_PATH ~= "" - -ShouldTreatWaringAsError = not (ENABLE_DDGI or USE_CLANG_TOOLSET) - PlatformSettings = {} PlatformSettings["Windows"] = { DisplayName = "Win64", @@ -77,6 +59,33 @@ function GetPlatformMacroName() return PlatformSettings[ChoosePlatform].MacroName end +dofile("path.lua") + +-------------------------------------------------------------------------------------------------------- +-- Build Options +-------------------------------------------------------------------------------------------------------- +USE_CLANG_TOOLSET = false +if os.getenv("USE_CLANG_TOOLSET") then + USE_CLANG_TOOLSET = true +end + +DDGI_SDK_PATH = os.getenv("DDGI_SDK_PATH") or "" +if not os.isdir(DDGI_SDK_PATH) then + DDGI_SDK_PATH = "" +end + +FBX_SDK_DEBUG_PATH = path.join(ThirdPartySourcePath, "AssetPipeline/build/bin/Debug/libfbxsdk.dll") +FBX_SDK_RELEASE_PATH = path.join(ThirdPartySourcePath, "AssetPipeline/build/bin/Release/libfbxsdk.dll") + +ENABLE_DDGI = DDGI_SDK_PATH ~= "" +ENABLE_FBX_WORKFLOW = os.isfile(FBX_SDK_DEBUG_PATH) and os.isfile(FBX_SDK_RELEASE_PATH) +ENABLE_FREETYPE = not USE_CLANG_TOOLSET and not IsLinuxPlatform() and not IsAndroidPlatform() +ENABLE_SPDLOG = not USE_CLANG_TOOLSET and not IsLinuxPlatform() and not IsAndroidPlatform() +ENABLE_SUBPROCESS = not USE_CLANG_TOOLSET and not IsLinuxPlatform() and not IsAndroidPlatform() +ENABLE_TRACY = not USE_CLANG_TOOLSET and not IsLinuxPlatform() and not IsAndroidPlatform() + +ShouldTreatWaringAsError = not (ENABLE_DDGI or USE_CLANG_TOOLSET) + IDEConfigs = {} IDEConfigs.BuildIDEName = os.getenv("BUILD_IDE_NAME") @@ -92,8 +101,7 @@ function SetLanguageAndToolset(projectName) targetdir(BinariesPath) end --- Parse folder path -dofile("path.lua") +-- Information about make print("================================================================") print("EngineBuildLibKind = "..EngineBuildLibKind) print("CurrentWorkingDirectory = "..CurrentWorkingDirectory) @@ -105,7 +113,12 @@ print("EngineSourcePath = "..EngineSourcePath) print("GameSourcePath = "..GameSourcePath) print("RuntimeSourcePath = "..RuntimeSourcePath) print("IDEConfigs.BuildIDEName = "..IDEConfigs.BuildIDEName) -print("DDGI_SDK_PATH = "..DDGI_SDK_PATH) +print("================================================================") +print("ENABLE_FBX_WORKFLOW = "..tostring(ENABLE_FBX_WORKFLOW)) +print("ENABLE_FREETYPE = "..tostring(ENABLE_FREETYPE)) +print("ENABLE_SPDLOG = "..tostring(ENABLE_SPDLOG)) +print("ENABLE_SUBPROCESS = "..tostring(ENABLE_SUBPROCESS)) +print("ENABLE_TRACY = "..tostring(ENABLE_TRACY)) print("================================================================") -- workspace means solution in Visual Studio @@ -156,53 +169,27 @@ function CopyDllAutomatically() end -- copy dll into binary folder automatically. - filter { "configurations:Debug" } - if IsAndroidPlatform() then - postbuildcommands { - "{COPYFILE} \""..path.join(ThirdPartySourcePath, "sdl/build/Debug/SDL2d.*").."\" \""..BinariesPath.."\"", - "{COPYFILE} \""..path.join(ThirdPartySourcePath, "AssetPipeline/ARM64/Debug/AssetPipelineCore.*").."\" \""..BinariesPath.."\"", - "{COPYFILE} \""..path.join(ThirdPartySourcePath, "AssetPipeline/ARM64/Debug/CDProducer.*").."\" \""..BinariesPath.."\"", - "{COPYFILE} \""..path.join(ThirdPartySourcePath, "AssetPipeline/ARM64/Debug/CDConsumer.*").."\" \""..BinariesPath.."\"", - } - else - postbuildcommands { - "{COPYFILE} \""..path.join(ThirdPartySourcePath, "sdl/build/Debug/SDL2d.*").."\" \""..BinariesPath.."\"", - "{COPYFILE} \""..path.join(ThirdPartySourcePath, "AssetPipeline/build/bin/Debug/AssetPipelineCore.*").."\" \""..BinariesPath.."\"", - "{COPYFILE} \""..path.join(ThirdPartySourcePath, "AssetPipeline/build/bin/Debug/CDProducer.*").."\" \""..BinariesPath.."\"", - "{COPYFILE} \""..path.join(ThirdPartySourcePath, "AssetPipeline/build/bin/Debug/CDConsumer.*").."\" \""..BinariesPath.."\"", - } - end - - if not USE_CLANG_TOOLSET then - postbuildcommands { - "{COPYFILE} \""..path.join(ThirdPartySourcePath, "AssetPipeline/build/bin/Debug/GenericProducer.*").."\" \""..BinariesPath.."\"", - "{COPYFILE} \""..path.join(ThirdPartySourcePath, "AssetPipeline/build/bin/Debug/assimp-*-mtd.*").."\" \""..BinariesPath.."\"", - } - end - filter { "configurations:Release" } - if IsAndroidPlatform() then - postbuildcommands { - "{COPYFILE} \""..path.join(ThirdPartySourcePath, "sdl/build/Release/SDL2.*").."\" \""..BinariesPath.."\"", - "{COPYFILE} \""..path.join(ThirdPartySourcePath, "AssetPipeline/ARM64/Release/AssetPipelineCore.*").."\" \""..BinariesPath.."\"", - "{COPYFILE} \""..path.join(ThirdPartySourcePath, "AssetPipeline/ARM64/Release/CDProducer.*").."\" \""..BinariesPath.."\"", - "{COPYFILE} \""..path.join(ThirdPartySourcePath, "AssetPipeline/ARM64/Release/CDConsumer.*").."\" \""..BinariesPath.."\"", - } - else - postbuildcommands { - "{COPYFILE} \""..path.join(ThirdPartySourcePath, "sdl/build/Release/SDL2.*").."\" \""..BinariesPath.."\"", - "{COPYFILE} \""..path.join(ThirdPartySourcePath, "AssetPipeline/build/bin/Release/AssetPipelineCore.*").."\" \""..BinariesPath.."\"", - "{COPYFILE} \""..path.join(ThirdPartySourcePath, "AssetPipeline/build/bin/Release/CDProducer.*").."\" \""..BinariesPath.."\"", - "{COPYFILE} \""..path.join(ThirdPartySourcePath, "AssetPipeline/build/bin/Release/CDConsumer.*").."\" \""..BinariesPath.."\"", - } - end - - if not USE_CLANG_TOOLSET then - postbuildcommands { - "{COPYFILE} \""..path.join(ThirdPartySourcePath, "AssetPipeline/build/bin/Release/GenericProducer.*").."\" \""..BinariesPath.."\"", - "{COPYFILE} \""..path.join(ThirdPartySourcePath, "AssetPipeline/build/bin/Release/assimp-*-mt.*").."\" \""..BinariesPath.."\"", - } - end - filter {} + postbuildcommands { + "{COPYFILE} \""..path.join(ThirdPartySourcePath, "sdl/build/%{cfg.buildcfg}/SDL2*.*").."\" \""..BinariesPath.."\"", + "{COPYFILE} \""..path.join(ThirdPartySourcePath, "AssetPipeline/build/bin/%{cfg.buildcfg}/AssetPipelineCore.*").."\" \""..BinariesPath.."\"", + "{COPYFILE} \""..path.join(ThirdPartySourcePath, "AssetPipeline/build/bin/%{cfg.buildcfg}/CDProducer.*").."\" \""..BinariesPath.."\"", + "{COPYFILE} \""..path.join(ThirdPartySourcePath, "AssetPipeline/build/bin/%{cfg.buildcfg}/CDConsumer.*").."\" \""..BinariesPath.."\"", + } + + if not USE_CLANG_TOOLSET then + postbuildcommands { + "{COPYFILE} \""..path.join(ThirdPartySourcePath, "AssetPipeline/build/bin/%{cfg.buildcfg}/GenericProducer.*").."\" \""..BinariesPath.."\"", + "{COPYFILE} \""..path.join(ThirdPartySourcePath, "AssetPipeline/build/bin/%{cfg.buildcfg}/assimp-*-mt*.*").."\" \""..BinariesPath.."\"", + } + end + + if ENABLE_FBX_WORKFLOW then + postbuildcommands { + "{COPYFILE} \""..path.join(ThirdPartySourcePath, "AssetPipeline/build/bin/%{cfg.buildcfg}/FbxConsumer.*").."\" \""..BinariesPath.."\"", + "{COPYFILE} \""..path.join(ThirdPartySourcePath, "AssetPipeline/build/bin/%{cfg.buildcfg}/FbxProducer.*").."\" \""..BinariesPath.."\"", + "{COPYFILE} \""..path.join(ThirdPartySourcePath, "AssetPipeline/build/bin/%{cfg.buildcfg}/libfbxsdk.*").."\" \""..BinariesPath.."\"", + } + end if ENABLE_DDGI then postbuildcommands { diff --git a/Engine/BuiltInShaders/common/CelMaterial.sh b/Engine/BuiltInShaders/common/CelMaterial.sh new file mode 100644 index 00000000..c0c2739b --- /dev/null +++ b/Engine/BuiltInShaders/common/CelMaterial.sh @@ -0,0 +1 @@ +uniform vec4 u_outLine; \ No newline at end of file diff --git a/Engine/BuiltInShaders/common/Envirnoment.sh b/Engine/BuiltInShaders/common/Envirnoment.sh index 69356fc9..76b085d7 100644 --- a/Engine/BuiltInShaders/common/Envirnoment.sh +++ b/Engine/BuiltInShaders/common/Envirnoment.sh @@ -25,6 +25,8 @@ SAMPLERCUBE(s_texCubeIrr, IBL_IRRADIANCE_SLOT); SAMPLERCUBE(s_texCubeRad, IBL_RADIANCE_SLOT); SAMPLER2D(s_texLUT, BRDF_LUT_SLOT); +uniform vec4 u_iblStrength; + vec3 SampleEnvIrradiance(vec3 normal, float mip) { // We use the HDR texture which in linear space. vec3 cubeNormalDir = normalize(fixCubeLookup(normal, mip, 256.0)); @@ -74,6 +76,8 @@ vec3 GetIBL(Material material, vec3 vertexNormal, vec3 viewDir) { // Specular envColor += (envSpecularBRDF * envRadiance * finalSpecularOcclusion); + + envColor *= vec3_splat(u_iblStrength.x); #endif return envColor; diff --git a/Engine/BuiltInShaders/common/LightSource.sh b/Engine/BuiltInShaders/common/LightSource.sh index d4abfb97..0ca00e5d 100644 --- a/Engine/BuiltInShaders/common/LightSource.sh +++ b/Engine/BuiltInShaders/common/LightSource.sh @@ -11,7 +11,7 @@ uniform vec4 u_lightCountAndStride; uniform vec4 u_lightParams[LIGHT_LENGTH]; uniform mat4 u_lightViewProjs[4*3]; uniform vec4 u_clipFrustumDepth; -uniform vec4 u_bias[3];//[LIGHT_NUM] +uniform vec4 u_bias[3]; // [LIGHT_NUM] SAMPLERCUBE(s_texCubeShadowMap_1, SHADOW_MAP_CUBE_FIRST_SLOT); SAMPLERCUBE(s_texCubeShadowMap_2, SHADOW_MAP_CUBE_SECOND_SLOT); @@ -49,6 +49,16 @@ U_Light GetLightParams(int pointer) { return light; } +struct CelParameter +{ + vec4 dividLine; + vec4 specular; + vec3 firstShadowColor; + vec3 secondShadowColor; + vec3 rimLightColor; + vec3 rimLight; +}; + // -------------------- Utils -------------------- // // Distance Attenuation @@ -304,6 +314,39 @@ vec3 CalculateDirectionalLight(U_Light light, Material material, vec3 worldPos, return (1.0 - shadow) * (KD * diffuseBRDF + specularBRDF) * irradiance * NdotL; } +vec3 CalculateCelDirectionalLight(U_Light light, Material material, vec3 worldPos, vec3 viewDir, float csmDepth, int lightIndex, CelParameter celParameter) { + // TODO : Remove this normalize in the future and add shadow in cartoon renderer. + vec3 lightDir = normalize(-light.direction); + vec3 harfDir = normalize(lightDir + viewDir); + + float NdotV = dot(material.normal, viewDir); + float NdotL = dot(material.normal, lightDir); + float NdotH = max(dot(material.normal, harfDir), 0.0); + + float halfLambert = 0.5 * NdotL + 0.5; + vec4 dividLine = celParameter.dividLine; + + float firstShadowMask = saturate(1.0 - (halfLambert - (dividLine.x - dividLine.y)) / dividLine.y); // albedo and 1st shadow + float secondShadowMask = saturate (1.0 - (halfLambert - (dividLine.z - dividLine.w)) / dividLine.w); // 1st shadow and 2st shadow + vec3 finalBaseColor = lerp(material.albedo, lerp(celParameter.firstShadowColor, celParameter.secondShadowColor, secondShadowMask), firstShadowMask); + + // Specular + float halfSpecular = 0.5 * NdotH + 0.5; + vec4 specular = celParameter.specular; + vec3 specularMask = specular.y * lerp(1.0 - step(halfSpecular, (1.0 - pow(specular.x, 5.0))), pow(halfSpecular, exp2(lerp(11.0, 1.0, specular.x))), specular.w); + vec3 specularColor = light.color * specularMask * vec3_splat(((1.0 - firstShadowMask) + (firstShadowMask * specular.z)) * light.intensity); + + // Rim + // TODO : Screen Space rim + float f = 1.0 - saturate(NdotV); + vec3 rimLight = celParameter.rimLight; + f = smoothstep(1.0 - rimLight.x, 1.0, f); + f = smoothstep(0.0, rimLight.y, f); + vec3 rim = f * rimLight.xyz * rimLight.z; + + return rim + specularColor + finalBaseColor; +} + // -------------------- Sphere -------------------- // vec3 CalculateSphereDiffuse(U_Light light, Material material, vec3 worldPos, vec3 diffuseBRDF) { @@ -676,6 +719,29 @@ vec3 CalculateLight(U_Light light, Material material, vec3 worldPos, vec3 viewDi return color; } +vec3 CalculateCelLight(U_Light light, Material material, vec3 normal, vec3 viewDir, float csmDepth, int lightIndex, CelParameter celParameter) { + vec3 color = vec3_splat(0.0); + if (light.type == POINT_LIGHT) + { + // TODO : Add cartoon point light. + color = vec3_splat(0.0); + } + else if (light.type == SPOT_LIGHT) + { + // TODO : Add cartoon spot light. + color = vec3_splat(0.0); + } + else if (light.type == DIRECTIONAL_LIGHT) + { + color = CalculateCelDirectionalLight(light, material, normal, viewDir, csmDepth, lightIndex, celParameter); + } + else + { + color = vec3_splat(0.0); + } + return color; +} + vec3 CalculateLights(Material material, vec3 worldPos, vec3 viewDir, vec3 diffuseBRDF, float csmDepth) { vec3 color = vec3_splat(0.0); for(int lightIndex = 0; lightIndex < int(u_lightCountAndStride.x); ++lightIndex) { @@ -685,3 +751,13 @@ vec3 CalculateLights(Material material, vec3 worldPos, vec3 viewDir, vec3 diffus } return color; } + +vec3 CalculateCelLights(Material material, vec3 worldPos, vec3 viewDir, float csmDepth, CelParameter celParameter) { + vec3 color = vec3_splat(0.0); + for(int lightIndex = 0; lightIndex < int(u_lightCountAndStride.x); ++lightIndex) { + int pointer = int(lightIndex * u_lightCountAndStride.y); + U_Light light = GetLightParams(pointer); + color += CalculateCelLight(light, material, worldPos, viewDir, csmDepth, lightIndex, celParameter); + } + return color; +} diff --git a/Engine/BuiltInShaders/shaders/fs_celluloid.sc b/Engine/BuiltInShaders/shaders/fs_celluloid.sc new file mode 100644 index 00000000..c3f2f63e --- /dev/null +++ b/Engine/BuiltInShaders/shaders/fs_celluloid.sc @@ -0,0 +1,56 @@ +$input v_worldPos, v_normal, v_texcoord0, v_TBN, v_color0 + +#include "../common/common.sh" +#include "../common/BRDF.sh" +#include "../common/Material.sh" +#include "../common/Camera.sh" + +#include "../common/LightSource.sh" +#include "../common/Envirnoment.sh" + +uniform vec4 u_emissiveColorAndFactor; +uniform vec4 u_cameraNearFarPlane; + +uniform vec4 u_dividLine; +uniform vec4 u_specular; +uniform vec4 u_firstShadowColor; +uniform vec4 u_secondShadowColor; +uniform vec4 u_rimLightColor; +uniform vec4 u_rimLight; + +vec3 GetCelDirectional(Material material, vec3 worldPos, vec3 viewDir, float csmDepth, CelParameter celParameter) { + return CalculateCelLights(material, worldPos, viewDir, csmDepth, celParameter); +} + +// TODO : add envirnoment light + +void main() +{ + Material material = GetMaterial(v_texcoord0, v_normal, v_TBN); + if (material.opacity < u_alphaCutOff.x) { + discard; + } + + vec3 cameraPos = GetCamera().position.xyz; + vec3 viewDir = normalize(cameraPos - v_worldPos); + + // Directional Light + float csmDepth = (v_color0.z - u_cameraNearFarPlane.x) / (u_cameraNearFarPlane.y - u_cameraNearFarPlane.x); + CelParameter celParameter; + celParameter.dividLine = u_dividLine; + celParameter.specular = u_specular; + celParameter.firstShadowColor = u_firstShadowColor; + celParameter.secondShadowColor = u_secondShadowColor; + celParameter.rimLightColor = u_rimLightColor; + celParameter.rimLight = u_rimLight; + vec3 dirColor = GetCelDirectional(material, v_worldPos, viewDir, csmDepth, celParameter); + + // Emissive + vec3 emiColor = material.emissive * u_emissiveColorAndFactor.xyz * vec3_splat(u_emissiveColorAndFactor.w); + + // Fragment Color + gl_FragData[0] = vec4(dirColor + emiColor, 1.0); + gl_FragData[1] = vec4(emiColor, 1.0); + + // Post-processing will be used in the last pass. +} diff --git a/Engine/BuiltInShaders/shaders/fs_outline.sc b/Engine/BuiltInShaders/shaders/fs_outline.sc new file mode 100644 index 00000000..d1ee69ec --- /dev/null +++ b/Engine/BuiltInShaders/shaders/fs_outline.sc @@ -0,0 +1,9 @@ +#include "../common/common.sh" +#include "../common/Material.sh" + +uniform vec4 u_outLineColor; + +void main() +{ + gl_FragColor = vec4(u_outLineColor.xyz, 1.0); +} \ No newline at end of file diff --git a/Engine/BuiltInShaders/shaders/fs_skybox.sc b/Engine/BuiltInShaders/shaders/fs_skybox.sc index 88d43cb9..167ecc33 100644 --- a/Engine/BuiltInShaders/shaders/fs_skybox.sc +++ b/Engine/BuiltInShaders/shaders/fs_skybox.sc @@ -4,13 +4,15 @@ $input v_worldPos SAMPLERCUBE(s_texSkybox, 0); +uniform vec4 u_skyboxStrength; + void main() { vec3 dir = normalize(v_worldPos.xyz); // Use radiance texture mip0. // We use the HDR texture which in linear space. - vec3 color = textureCubeLod(s_texSkybox, dir, 0.0).xyz * vec3_splat(0.6); + vec3 color = textureCubeLod(s_texSkybox, dir, 0.0).xyz * vec3_splat(u_skyboxStrength.x); gl_FragColor = vec4(color, 1.0); } diff --git a/Engine/BuiltInShaders/shaders/vs_celluloid.sc b/Engine/BuiltInShaders/shaders/vs_celluloid.sc new file mode 100644 index 00000000..0965a061 --- /dev/null +++ b/Engine/BuiltInShaders/shaders/vs_celluloid.sc @@ -0,0 +1,22 @@ +$input a_position, a_normal, a_tangent, a_texcoord0 +$output v_worldPos, v_normal, v_texcoord0, v_TBN, v_color0 + +#include "../common/common.sh" + +void main() +{ + gl_Position = mul(u_modelViewProj, vec4(a_position, 1.0)); + + v_worldPos = mul(u_model[0], vec4(a_position, 1.0)).xyz; + v_color0 = mul(u_modelView, vec4(a_position, 1.0)); + v_normal = normalize(mul(u_modelInvTrans, vec4(a_normal, 0.0)).xyz); + vec3 tangent = normalize(mul(u_modelInvTrans, vec4(a_tangent, 0.0)).xyz); + + // re-orthogonalize T with respect to N + tangent = normalize(tangent - dot(tangent, v_normal) * v_normal); + vec3 biTangent = normalize(cross(v_normal, tangent)); + + // TBN + v_TBN = mtxFromCols(tangent, biTangent, v_normal); + v_texcoord0 = a_texcoord0; +} diff --git a/Engine/BuiltInShaders/shaders/vs_outline.sc b/Engine/BuiltInShaders/shaders/vs_outline.sc new file mode 100644 index 00000000..a69d7d1f --- /dev/null +++ b/Engine/BuiltInShaders/shaders/vs_outline.sc @@ -0,0 +1,17 @@ +$input a_position, a_normal, a_color0 + +#include "../common/common.sh" + +uniform vec4 u_outLineSize; + +void main() +{ + float outline = u_outLineSize.x; + vec4 position = mul(u_modelViewProj, vec4(a_position, 1.0)); + vec3 normal = normalize(mul(u_modelInvTrans, vec4(a_normal, 0.0)).xyz);; + normal = normalize(mul(u_view,vec4(normal,0.0)).xyz); + + // Treat the stroke width according to the screen aspect ratio. + normal.x *= u_viewRect.w / u_viewRect.z; + gl_Position = position + mul(vec4(normal.xy, 0.0 ,0.0),outline); +} diff --git a/Engine/BuiltInShaders/shaders/vs_skeleton.sc b/Engine/BuiltInShaders/shaders/vs_skeleton.sc new file mode 100644 index 00000000..7b95f3bd --- /dev/null +++ b/Engine/BuiltInShaders/shaders/vs_skeleton.sc @@ -0,0 +1,12 @@ +$input a_position, a_indices + +#include "../common/common.sh" + +uniform mat4 u_boneMatrices[128]; + +void main() +{ + mat4 boneTransform = u_boneMatrices[a_indices[0]]; + vec4 localPosition = mul(boneTransform, vec4(a_position, 1.0)); + gl_Position = mul(u_modelViewProj, localPosition); +} \ No newline at end of file diff --git a/Engine/Source/Editor/ECWorld/ECWorldConsumer.cpp b/Engine/Source/Editor/ECWorld/ECWorldConsumer.cpp index c4a94ae4..4eeb520b 100644 --- a/Engine/Source/Editor/ECWorld/ECWorldConsumer.cpp +++ b/Engine/Source/Editor/ECWorld/ECWorldConsumer.cpp @@ -9,11 +9,13 @@ #include "Rendering/RenderContext.h" #include "Rendering/Resources/MeshResource.h" #include "Rendering/Resources/ResourceContext.h" +#include "Rendering/Resources/SkeletonResource.h" #include "Rendering/Resources/TextureResource.h" #include "Rendering/ShaderFeature.h" #include "Resources/ResourceBuilder.h" #include "Resources/ResourceLoader.h" #include "Resources/ShaderBuilder.h" +#include "Rendering/Utility/VertexLayoutUtility.h" #include "Scene/SceneDatabase.h" #include @@ -58,12 +60,14 @@ void ECWorldConsumer::Execute(const cd::SceneDatabase* pSceneDatabase) if (hasSkin) { engine::MaterialType* pMaterialType = m_pSceneWorld->GetAnimationMaterialType(); - AddSkinMesh(meshEntity, mesh, pMaterialType->GetRequiredVertexFormat()); + AddSkinMesh(meshEntity, mesh, pMaterialType->GetRequiredVertexFormat(), pSceneDatabase); // TODO : Use a standalone .cdanim file to play animation. // Currently, we assume that imported SkinMesh will play animation automatically for testing. + //TODO : depens on skeleton to match animation AddAnimation(meshEntity, pSceneDatabase->GetAnimation(0), pSceneDatabase); AddMaterial(meshEntity, nullptr, pMaterialType, pSceneDatabase); + AddSkeleton(meshEntity, pSceneDatabase); } else { @@ -185,9 +189,39 @@ void ECWorldConsumer::AddStaticMesh(engine::Entity entity, const cd::Mesh& mesh, staticMeshComponent.SetMeshResource(pMeshResource); } -void ECWorldConsumer::AddSkinMesh(engine::Entity entity, const cd::Mesh& mesh, const cd::VertexFormat& vertexFormat) +void ECWorldConsumer::AddSkinMesh(engine::Entity entity, const cd::Mesh& mesh, const cd::VertexFormat& vertexFormat, const cd::SceneDatabase* pSceneDatabase) { - AddStaticMesh(entity, mesh, vertexFormat); + assert(mesh.GetVertexCount() > 0 && mesh.GetPolygonCount() > 0); + + engine::World* pWorld = m_pSceneWorld->GetWorld(); + auto& nameComponent = pWorld->CreateComponent(entity); + std::string meshName(mesh.GetName()); + engine::StringCrc meshNameCrc(meshName); + nameComponent.SetName(cd::MoveTemp(meshName)); + + auto& collisionMeshComponent = pWorld->CreateComponent(entity); + collisionMeshComponent.SetType(engine::CollisonMeshType::AABB); + collisionMeshComponent.SetAABB(mesh.GetAABB()); + collisionMeshComponent.Build(); + + auto& staticMeshComponent = pWorld->CreateComponent(entity); + engine::MeshResource* pMeshResource = m_pResourceContext->AddMeshResource(meshNameCrc); + pMeshResource->SetMeshAsset(&mesh); + + //auto& skinMeshComponent = pWorld->CreateComponent(entity); + for (auto skinID : mesh.GetSkinIDs()) + { + pMeshResource->SetSkinAsset(&pSceneDatabase->GetSkin(skinID.Data())); + auto skeletonID = pSceneDatabase->GetSkin(skinID.Data()).GetSkeletonID(); + auto& skeleton = pSceneDatabase->GetSkeleton(skeletonID.Data()); + for (auto boneID : skeleton.GetBoneIDs()) + { + pMeshResource->AddBonesAsset(pSceneDatabase->GetBone(boneID.Data())); + } + } + + pMeshResource->UpdateVertexFormat(vertexFormat); + staticMeshComponent.SetMeshResource(pMeshResource); } void ECWorldConsumer::AddAnimation(engine::Entity entity, const cd::Animation& animation, const cd::SceneDatabase* pSceneDatabase) @@ -205,15 +239,20 @@ void ECWorldConsumer::AddAnimation(engine::Entity entity, const cd::Animation& a void ECWorldConsumer::AddMaterial(engine::Entity entity, const cd::Material* pMaterial, engine::MaterialType* pMaterialType, const cd::SceneDatabase* pSceneDatabase) { - std::set compiledTextureSlot; - std::vector> outputTypeToData; - engine::MaterialComponent& materialComponent = m_pSceneWorld->GetWorld()->CreateComponent(entity); materialComponent.Init(); materialComponent.SetMaterialType(pMaterialType); materialComponent.SetMaterialData(pMaterial); materialComponent.ActivateShaderFeature(engine::GetSkyTypeShaderFeature(m_pSceneWorld->GetSkyComponent(m_pSceneWorld->GetSkyEntity())->GetSkyType())); + if (!pMaterial) + { + return; + } + + std::set compiledTextureSlot; + std::vector> outputTypeToData; + // Expected textures are ready to build. Add more optional texture data. for (cd::MaterialTextureType optionalTextureType : pMaterialType->GetOptionalTextureTypes()) { @@ -429,4 +468,18 @@ void ECWorldConsumer::AddParticleEmitter(engine::Entity entity, const cd::Mesh& particleEmitterComponent.Build(); } +void ECWorldConsumer::AddSkeleton(engine::Entity entity, const cd::SceneDatabase* pSceneDatabase) +{ + engine::World* pWorld = m_pSceneWorld->GetWorld(); + auto& SkeletonComponent = pWorld->CreateComponent(entity); + + auto& skeleton = pSceneDatabase->GetSkeleton(0); + std::string meshName(skeleton.GetName()); + engine::StringCrc meshNameCrc(meshName); + engine::SkeletonResource* pSkeletonResource = m_pResourceContext->AddSkeletonResource(meshNameCrc); + pSkeletonResource->SetSceneDataBase(pSceneDatabase); + SkeletonComponent.SetSkeletonAsset(pSkeletonResource); + +} + } \ No newline at end of file diff --git a/Engine/Source/Editor/ECWorld/ECWorldConsumer.h b/Engine/Source/Editor/ECWorld/ECWorldConsumer.h index 8359055a..fa05132b 100644 --- a/Engine/Source/Editor/ECWorld/ECWorldConsumer.h +++ b/Engine/Source/Editor/ECWorld/ECWorldConsumer.h @@ -66,7 +66,8 @@ class ECWorldConsumer final : public cdtools::IConsumer void AddLight(engine::Entity entity, const cd::Light& light); void AddTransform(engine::Entity entity, const cd::Transform& transform); void AddStaticMesh(engine::Entity entity, const cd::Mesh& mesh, const cd::VertexFormat& vertexFormat); - void AddSkinMesh(engine::Entity entity, const cd::Mesh& mesh, const cd::VertexFormat& vertexFormat); + void AddSkinMesh(engine::Entity entity, const cd::Mesh& mesh, const cd::VertexFormat& vertexFormat, const cd::SceneDatabase* pSceneDatabase); + void AddSkeleton(engine::Entity entity, const cd::SceneDatabase* pSceneDatabase); void AddAnimation(engine::Entity entity, const cd::Animation& animation, const cd::SceneDatabase* pSceneDatabase); void AddMaterial(engine::Entity entity, const cd::Material* pMaterial, engine::MaterialType* pMaterialType, const cd::SceneDatabase* pSceneDatabase); void AddBlendShape(engine::Entity entity, const cd::Mesh* pMesh, const cd::BlendShape& blendShape, const cd::SceneDatabase* pSceneDatabase); diff --git a/Engine/Source/Editor/EditorApp.cpp b/Engine/Source/Editor/EditorApp.cpp index f38605b8..226f483b 100644 --- a/Engine/Source/Editor/EditorApp.cpp +++ b/Engine/Source/Editor/EditorApp.cpp @@ -15,6 +15,7 @@ #include "Rendering/AnimationRenderer.h" #include "Rendering/BlendShapeRenderer.h" #include "Rendering/BlitRenderTargetPass.h" +#include "Rendering/CelluloidRenderer.h" #ifdef ENABLE_DDGI #include "Rendering/DDGIRenderer.h" #endif @@ -27,13 +28,14 @@ #include "Rendering/RenderContext.h" #include "Rendering/Resources/MeshResource.h" #include "Rendering/Resources/ResourceContext.h" +#include "Rendering/Resources/ShaderResource.h" #include "Rendering/SkeletonRenderer.h" #include "Rendering/SkyboxRenderer.h" -#include "Rendering/ShaderCollections.h" #include "Rendering/ShadowMapRenderer.h" #include "Rendering/TerrainRenderer.h" #include "Rendering/WorldRenderer.h" #include "Rendering/ParticleForceFieldRenderer.h" +#include "Rendering/OutLineRenderer.h" #include "Rendering/ParticleRenderer.h" #include "Resources/FileWatcher.h" #include "Resources/ResourceBuilder.h" @@ -97,7 +99,6 @@ void EditorApp::Init(engine::EngineInitArgs initArgs) AddWindow(cd::MoveTemp(pSplashWindow)); InitEditorRenderers(); - EditorRenderersWarmup(); InitEditorImGuiContext(m_initArgs.language); InitECWorld(); @@ -258,26 +259,18 @@ void EditorApp::InitECWorld() void EditorApp::InitMaterialType() { - constexpr const char* WorldProgram = "WorldProgram"; - constexpr const char* AnimationProgram = "AnimationProgram"; - constexpr const char* TerrainProgram = "TerrainProgram"; - constexpr const char* ParticleProgram = "ParticleProgram"; - - constexpr engine::StringCrc WorldProgramCrc{ WorldProgram }; - constexpr engine::StringCrc AnimationProgramCrc{ AnimationProgram }; - constexpr engine::StringCrc TerrainProgramCrc{ TerrainProgram }; - constexpr engine::StringCrc ParticleProgramCrc{ ParticleProgram}; - - m_pRenderContext->RegisterShaderProgram(WorldProgramCrc, { "vs_PBR", "fs_PBR" }); - m_pRenderContext->RegisterShaderProgram(AnimationProgramCrc, { "vs_animation", "fs_animation" }); - m_pRenderContext->RegisterShaderProgram(TerrainProgramCrc, { "vs_terrain", "fs_terrain" }); - m_pRenderContext->RegisterShaderProgram(ParticleProgramCrc, { "vs_particle","fs_particle" }); + m_pRenderContext->RegisterShaderProgram("WorldProgram", "vs_PBR", "fs_PBR"); + m_pRenderContext->RegisterShaderProgram("AnimationProgram", "vs_animation", "fs_animation"); + m_pRenderContext->RegisterShaderProgram("TerrainProgram", "vs_terrain", "fs_terrain"); + m_pRenderContext->RegisterShaderProgram("ParticleProgram", "vs_particle", "fs_particle"); + m_pRenderContext->RegisterShaderProgram("CelluloidProgram", "vs_celluloid", "fs_celluloid"); m_pSceneWorld = std::make_unique(); - m_pSceneWorld->CreatePBRMaterialType(WorldProgram, IsAtmosphericScatteringEnable()); - m_pSceneWorld->CreateAnimationMaterialType(AnimationProgram); - m_pSceneWorld->CreateTerrainMaterialType(TerrainProgram); - m_pSceneWorld->CreateParticleMaterialType(ParticleProgram); + m_pSceneWorld->CreatePBRMaterialType("WorldProgram", IsAtmosphericScatteringEnable()); + m_pSceneWorld->CreateAnimationMaterialType("AnimationProgram"); + m_pSceneWorld->CreateTerrainMaterialType("TerrainProgram"); + m_pSceneWorld->CreateParticleMaterialType("ParticleProgram"); + m_pSceneWorld->CreateCelluloidMaterialType("CelluloidProgram"); } void EditorApp::InitEditorCameraEntity() @@ -389,7 +382,7 @@ void EditorApp::OnShaderHotModifiedCallback(const char* rootDir, const char* fil // Do nothing when a non-shader file is detected. return; } - m_pRenderContext->CheckModifiedProgram(engine::Path::GetFileNameWithoutExtension(filePath)); + m_pRenderContext->OnShaderHotModified(engine::StringCrc{ engine::Path::GetFileNameWithoutExtension(filePath) }); } void EditorApp::UpdateMaterials() @@ -402,77 +395,52 @@ void EditorApp::UpdateMaterials() continue; } - const std::string& programName = pMaterialComponent->GetShaderProgramName(); - const std::string& featuresCombine = pMaterialComponent->GetFeaturesCombine(); - - // New shader feature added, need to compile new variants. - m_pRenderContext->CheckShaderProgram(entity, programName, featuresCombine); - - // Shader source files have been modified, need to re-compile existing variants. - if (m_crtInputFocus && !m_preInputFocus) + if (pMaterialComponent->IsShaderResourceDirty()) { - m_pRenderContext->OnShaderHotModified(entity, programName, featuresCombine); - } - } + // 1. Create a new ShaderResource / Or find an exists one + // 2. Update it to MaterialComponent - if (m_crtInputFocus && !m_preInputFocus) - { - m_pRenderContext->ClearModifiedProgramNameCrcs(); - } -} - -void EditorApp::CompileAndLoadShaders() -{ - // 1. Compile - TaskOutputCallbacks cb; - cb.onErrorOutput.Bind(this); - ShaderBuilder::BuildShaderInfos(m_pRenderContext.get(), cd::MoveTemp(cb)); + const std::string& programName = pMaterialComponent->GetShaderProgramName(); + const std::string& featuresCombine = pMaterialComponent->GetFeaturesCombine(); - // 2. Load - if (!m_pRenderContext->GetShaderCompileInfos().empty()) - { - ResourceBuilder::Get().Update(false, true); - - for (const auto& info : m_pRenderContext->GetShaderCompileInfos()) - { - // Info still in RenderContext::m_shaderCompileInfos means compiling is successful. - const uint32_t entity = info.m_entity; - auto& failedEntities = m_pRenderContext->GetCompileFailedEntities(); - if (failedEntities.find(entity) != failedEntities.end()) + engine::ShaderResource* pShaderResource = m_pResourceContext->GetShaderResource(engine::StringCrc{ programName + featuresCombine }); + if (!pShaderResource) { - engine::MaterialComponent* pMaterialComponent = m_pSceneWorld->GetMaterialComponent(entity); - pMaterialComponent->SetFactor(cd::MaterialPropertyGroup::BaseColor, cd::Vec3f{ 1.0f, 1.0f, 1.0f }); - failedEntities.erase(entity); + // We assume here that the ResourceContext hold informations about an + // original ShaderProgram that does not contain any ShaderFeature. + engine::ShaderResource* pOriginShaderResource = m_pResourceContext->GetShaderResource(engine::StringCrc{ programName }); + assert(pOriginShaderResource); + + engine::ShaderProgramType programtype = pOriginShaderResource->GetType(); + if (engine::ShaderProgramType::Standard == programtype) + { + pShaderResource = m_pRenderContext->RegisterShaderProgram(pOriginShaderResource->GetName(), + pOriginShaderResource->GetShaderInfo(0).name, + pOriginShaderResource->GetShaderInfo(1).name, + featuresCombine); + } + else + { + pShaderResource = m_pRenderContext->RegisterShaderProgram(pOriginShaderResource->GetName(), + pOriginShaderResource->GetShaderInfo(0).name, + programtype, + featuresCombine); + } + + m_pRenderContext->AddRecompileShaderResource(pShaderResource); } - m_pRenderContext->DestroyShaderProgram(info.m_programName, info.m_featuresCombine); - m_pRenderContext->UploadShaderProgram(info.m_programName, info.m_featuresCombine); + assert(pShaderResource); + pMaterialComponent->SetShaderResource(pShaderResource); } - - m_pRenderContext->ClearShaderCompileInfos(); + assert(!pMaterialComponent->IsShaderResourceDirty()); } -} - -void EditorApp::OnShaderCompileFailed(uint32_t handle, std::span str) -{ - auto& infos = m_pRenderContext->GetShaderCompileInfos(); - auto it = infos.begin(); - while (it != infos.end()) + // When the window gains focus, check if the shader for each program has been modified. + if (m_crtInputFocus) { - const auto& handles = it->m_taskHandles; - if (handles.find(handle) != handles.end()) - { - const uint32_t entity = it->m_entity; - m_pRenderContext->AddCompileFailedEntity(entity); - engine::MaterialComponent* pMaterialComponent = m_pSceneWorld->GetMaterialComponent(entity); - pMaterialComponent->SetFactor(cd::MaterialPropertyGroup::BaseColor, cd::Vec3f{ 1.0f, 0.0f, 1.0f }); - it = infos.erase(it); - } - else - { - ++it; - } + m_pRenderContext->OnShaderRecompile(); + ShaderBuilder::BuildRecompileShaderResources(m_pRenderContext.get()); } } @@ -487,9 +455,6 @@ void EditorApp::InitRenderContext(engine::GraphicsBackend backend, void* hwnd) m_pResourceContext = std::make_unique(); m_pRenderContext->SetResourceContext(m_pResourceContext.get()); - - m_pShaderCollections = std::make_unique(); - m_pRenderContext->SetShaderCollections(m_pShaderCollections.get()); } void EditorApp::InitEditorRenderers() @@ -527,11 +492,29 @@ void EditorApp::InitEngineRenderers() AddEngineRenderer(cd::MoveTemp(pPBRSkyRenderer)); } + auto pSkeletonRenderer = std::make_unique(m_pRenderContext->CreateView(), pSceneRenderTarget); + pSkeletonRenderer->SetSceneWorld(m_pSceneWorld.get()); + AddEngineRenderer(cd::MoveTemp(pSkeletonRenderer)); + + auto pAnimationRenderer = std::make_unique(m_pRenderContext->CreateView(), pSceneRenderTarget); + pAnimationRenderer->SetSceneWorld(m_pSceneWorld.get()); + AddEngineRenderer(cd::MoveTemp(pAnimationRenderer)); + auto pSceneRenderer = std::make_unique(m_pRenderContext->CreateView(), pSceneRenderTarget); m_pSceneRenderer = pSceneRenderer.get(); pSceneRenderer->SetSceneWorld(m_pSceneWorld.get()); AddEngineRenderer(cd::MoveTemp(pSceneRenderer)); + auto pCelluloidRenderer = std::make_unique(m_pRenderContext->CreateView(), pSceneRenderTarget); + m_pCelluloidRenderer = pCelluloidRenderer.get(); + pCelluloidRenderer->SetSceneWorld(m_pSceneWorld.get()); + AddEngineRenderer(cd::MoveTemp(pCelluloidRenderer)); + + auto pOutLineRenderer = std::make_unique(m_pRenderContext->CreateView(), pSceneRenderTarget); + m_pOutLineRenderer = pOutLineRenderer.get(); + pOutLineRenderer->SetSceneWorld(m_pSceneWorld.get()); + AddEngineRenderer(cd::MoveTemp(pOutLineRenderer)); + auto pBlendShapeRenderer = std::make_unique(m_pRenderContext->CreateView(), pSceneRenderTarget); pBlendShapeRenderer->SetSceneWorld(m_pSceneWorld.get()); AddEngineRenderer(cd::MoveTemp(pBlendShapeRenderer)); @@ -541,14 +524,6 @@ void EditorApp::InitEngineRenderers() pTerrainRenderer->SetSceneWorld(m_pSceneWorld.get()); AddEngineRenderer(cd::MoveTemp(pTerrainRenderer)); - auto pSkeletonRenderer = std::make_unique(m_pRenderContext->CreateView(), pSceneRenderTarget); - pSkeletonRenderer->SetSceneWorld(m_pSceneWorld.get()); - AddEngineRenderer(cd::MoveTemp(pSkeletonRenderer)); - - auto pAnimationRenderer = std::make_unique(m_pRenderContext->CreateView(), pSceneRenderTarget); - pAnimationRenderer->SetSceneWorld(m_pSceneWorld.get()); - AddEngineRenderer(cd::MoveTemp(pAnimationRenderer)); - auto pWhiteModelRenderer = std::make_unique(m_pRenderContext->CreateView(), pSceneRenderTarget); m_pWhiteModelRenderer = pWhiteModelRenderer.get(); pWhiteModelRenderer->SetSceneWorld(m_pSceneWorld.get()); @@ -597,22 +572,6 @@ void EditorApp::InitEngineRenderers() AddEngineRenderer(std::make_unique(m_pRenderContext->CreateView(), pSceneRenderTarget)); } -void EditorApp::EditorRenderersWarmup() -{ - for (std::unique_ptr& pRenderer : m_pEditorRenderers) - { - pRenderer->Warmup(); - } -} - -void EditorApp::EngineRenderersWarmup() -{ - for (std::unique_ptr& pRenderer : m_pEngineRenderers) - { - pRenderer->Warmup(); - } -} - bool EditorApp::IsAtmosphericScatteringEnable() const { engine::GraphicsBackend backend = engine::Path::GetGraphicsBackend(); @@ -624,24 +583,16 @@ bool EditorApp::IsAtmosphericScatteringEnable() const void EditorApp::InitShaderPrograms(bool compileAllShaders) const { - ShaderBuilder::CompileRegisteredNonUberShader(m_pRenderContext.get()); - if (compileAllShaders) { - ShaderBuilder::CompileUberShaderAllVariants(m_pRenderContext.get(), m_pSceneWorld->GetPBRMaterialType()); + ShaderBuilder::RegisterUberShaderAllVariants(m_pRenderContext.get(), m_pSceneWorld->GetPBRMaterialType()); #ifdef ENABLE_DDGI - ShaderBuilder::CompileUberShaderAllVariants(m_pRenderContext.get(), m_pSceneWorld->GetDDGIMaterialType()); + ShaderBuilder::RegisterUberShaderAllVariants(m_pRenderContext.get(), m_pSceneWorld->GetDDGIMaterialType()); #endif } - else - { - ShaderBuilder::CompileRegisteredUberShader(m_pRenderContext.get(), m_pSceneWorld->GetPBRMaterialType()); -#ifdef ENABLE_DDGI - ShaderBuilder::CompileRegisteredUberShader(m_pRenderContext.get(), m_pSceneWorld->GetDDGIMaterialType()); -#endif - } + ShaderBuilder::BuildRegisteredShaderResources(m_pRenderContext.get()); } void EditorApp::InitEditorController() @@ -674,8 +625,6 @@ bool EditorApp::Update(float deltaTime) { m_bInitEditor = true; - EngineRenderersWarmup(); - // Phase 2 - Project Manager // * TODO : Show project selector //GetMainWindow()->SetTitle("Project Manager"); @@ -751,8 +700,6 @@ bool EditorApp::Update(float deltaTime) m_pEngineImGuiContext->Update(deltaTime); UpdateMaterials(); - CompileAndLoadShaders(); - for (std::unique_ptr& pRenderer : m_pEngineRenderers) { if (pRenderer->IsEnable()) diff --git a/Engine/Source/Editor/EditorApp.h b/Engine/Source/Editor/EditorApp.h index 00617a7f..ade13534 100644 --- a/Engine/Source/Editor/EditorApp.h +++ b/Engine/Source/Editor/EditorApp.h @@ -20,7 +20,6 @@ class ResourceContext; class AABBRenderer; class RenderTarget; class SceneWorld; -class ShaderCollections; } @@ -57,9 +56,6 @@ class EditorApp final : public engine::IApplication void InitEditorRenderers(); void InitEngineRenderers(); - void EditorRenderersWarmup(); - void EngineRenderersWarmup(); - void InitShaderPrograms(bool compileAllShaders = false) const; void AddEditorRenderer(std::unique_ptr pRenderer); void AddEngineRenderer(std::unique_ptr pRenderer); @@ -87,10 +83,7 @@ class EditorApp final : public engine::IApplication void InitFileWatcher(); void OnShaderHotModifiedCallback(const char* rootDir, const char* filePath); - void UpdateMaterials(); - void CompileAndLoadShaders(); - void OnShaderCompileFailed(uint32_t handle, std::span str); bool m_crtInputFocus = true; bool m_preInputFocus = true; @@ -117,11 +110,12 @@ class EditorApp final : public engine::IApplication engine::Renderer* m_pTerrainRenderer = nullptr; engine::Renderer* m_pAABBRenderer = nullptr; engine::Renderer* m_pShadowMapRenderer = nullptr; + engine::Renderer* m_pCelluloidRenderer = nullptr; + engine::Renderer* m_pOutLineRenderer = nullptr; // Rendering std::unique_ptr m_pRenderContext; std::unique_ptr m_pResourceContext; - std::unique_ptr m_pShaderCollections; std::vector> m_pEditorRenderers; std::vector> m_pEngineRenderers; diff --git a/Engine/Source/Editor/Resources/ShaderBuilder.cpp b/Engine/Source/Editor/Resources/ShaderBuilder.cpp index 9697b91a..93ec5e14 100644 --- a/Engine/Source/Editor/Resources/ShaderBuilder.cpp +++ b/Engine/Source/Editor/Resources/ShaderBuilder.cpp @@ -4,134 +4,78 @@ #include "Log/Log.h" #include "Path/Path.h" #include "Rendering/RenderContext.h" -#include "Rendering/ShaderCollections.h" +#include "Rendering/Resources/ResourceContext.h" namespace editor { -namespace +void ShaderBuilder::RegisterUberShaderAllVariants(engine::RenderContext *pRenderContext, engine::MaterialType *pMaterialType) { + const std::string &programName = pMaterialType->GetShaderSchema().GetShaderProgramName(); + const engine::ShaderResource *pOriginShaderResource = pRenderContext->GetResourceContext()->GetShaderResource(engine::StringCrc{ programName }); + const auto &combines = pMaterialType->GetShaderSchema().GetAllFeatureCombines(); + engine::ShaderProgramType programType = pOriginShaderResource->GetType(); -void CompileShaderVariants(const std::set& shaders, const std::set& combines) -{ - for (const std::string& shader : shaders) + for (const auto &combine : combines) { - engine::ShaderType shaderType = engine::GetShaderType(shader); - if (engine::ShaderType::Vertex == shaderType) - { - std::string inputVSFilePath = engine::Path::GetBuiltinShaderInputPath(shader.c_str()); - std::string outputVSFilePath = engine::Path::GetShaderOutputPath(shader.c_str()); - ResourceBuilder::Get().AddShaderBuildTask(engine::ShaderType::Vertex, inputVSFilePath.c_str(), outputVSFilePath.c_str()); - } - else if (engine::ShaderType::Fragment == shaderType) + if (engine::ShaderProgramType::Standard == programType) { - for (const auto& combine : combines) - { - std::string inputFSFilePath = engine::Path::GetBuiltinShaderInputPath(shader.c_str()); - std::string outputFSFilePath = engine::Path::GetShaderOutputPath(shader.c_str(), combine); - ResourceBuilder::Get().AddShaderBuildTask(engine::ShaderType::Fragment, inputFSFilePath.c_str(), outputFSFilePath.c_str(), combine.c_str()); - } + pRenderContext->RegisterShaderProgram(programName.c_str(), + pOriginShaderResource->GetShaderInfo(0).name.c_str(), + pOriginShaderResource->GetShaderInfo(0).name.c_str(), + combine); } else { - // No shader feature support for Vertex and Compute shader. - continue; + pRenderContext->RegisterShaderProgram(programName.c_str(), + pOriginShaderResource->GetShaderInfo(0).name.c_str(), + programType, + combine); } } -} + CD_ENGINE_INFO("Compiling program {0} all variants with count : {1}", programName, combines.size()); } -void ShaderBuilder::CompileRegisteredNonUberShader(engine::RenderContext* pRenderContext) +void ShaderBuilder::BuildRegisteredShaderResources(engine::RenderContext* pRenderContext, TaskOutputCallbacks callbacks) { - for (const auto& shaders : pRenderContext->GetShaderCollections()->GetShaderPrograms()) + for (const auto& [_, pShaderResource] : pRenderContext->GetShaderResources()) { - for (const auto& shader : shaders.second) - { - engine::ShaderType shaderType = engine::GetShaderType(shader); - if (engine::ShaderType::None == shaderType) - { - CD_WARN("Known shader type of {0} in ShaderBuilder!", shader); - continue; - } - - std::string inputShaderPath = engine::Path::GetBuiltinShaderInputPath(shader.c_str()); - std::string outputShaderPath = engine::Path::GetShaderOutputPath(shader.c_str()); - ResourceBuilder::Get().AddShaderBuildTask(shaderType, inputShaderPath.c_str(), outputShaderPath.c_str()); - } + BuildShaderResource(pRenderContext, pShaderResource, callbacks); } + + ResourceBuilder::Get().Update(); } -void ShaderBuilder::CompileRegisteredUberShader(engine::RenderContext* pRenderContext, engine::MaterialType* pMaterialType) +void ShaderBuilder::BuildRecompileShaderResources(engine::RenderContext* pRenderContext, TaskOutputCallbacks callbacks) { - const std::string& programName = pMaterialType->GetShaderSchema().GetShaderProgramName(); - engine::StringCrc programNameCrc = engine::StringCrc(programName); - - if (!pRenderContext->GetShaderCollections()->HasFeatureCombine(programNameCrc)) + for (auto pShaderResource : pRenderContext->GetRecompileShaderResources()) { - return; + BuildShaderResource(pRenderContext, pShaderResource, callbacks); } - const std::set& shaders = pRenderContext->GetShaderCollections()->GetShaders(programNameCrc); - const std::set& combines = pRenderContext->GetShaderCollections()->GetFeatureCombines(programNameCrc); - CD_ENGINE_INFO("Compiling program {0} variant count : {1}", programName, combines.size()); - - CompileShaderVariants(shaders, combines); -} - -void ShaderBuilder::CompileUberShaderAllVariants(engine::RenderContext* pRenderContext, engine::MaterialType* pMaterialType) -{ - const std::string& programName = pMaterialType->GetShaderSchema().GetShaderProgramName(); - - const std::set& shaders = pRenderContext->GetShaderCollections()->GetShaders(engine::StringCrc(programName)); - const std::set& combines = pMaterialType->GetShaderSchema().GetAllFeatureCombines(); - CD_ENGINE_INFO("Compiling program {0} variant count : {1}", programName, combines.size()); - - CompileShaderVariants(shaders, combines); - ResourceBuilder::Get().Update(); + pRenderContext->ClearRecompileShaderResources(); } -void ShaderBuilder::BuildShaderInfos(engine::RenderContext* pRenderContext, TaskOutputCallbacks callbacks) +void ShaderBuilder::BuildShaderResource(engine::RenderContext* pRenderContext, engine::ShaderResource* pShaderResource, TaskOutputCallbacks callbacks) { - std::set newInfos; - - for (auto info : pRenderContext->GetShaderCompileInfos()) + if (engine::ShaderProgramType::Standard == pShaderResource->GetType()) { - engine::ShaderCompileInfo newInfo{ info.m_entity, cd::MoveTemp(info.m_programName), cd::MoveTemp(info.m_featuresCombine) }; - const std::set& shaders = pRenderContext->GetShaderCollections()->GetShaders(engine::StringCrc(newInfo.m_programName)); - - for (const auto& shader : shaders) - { - engine::ShaderType shaderType = engine::GetShaderType(shader); - if (engine::ShaderType::Vertex == shaderType || engine::ShaderType::Compute == shaderType) - { - std::string inputVSFilePath = engine::Path::GetBuiltinShaderInputPath(shader.c_str()); - std::string outputVSFilePath = engine::Path::GetShaderOutputPath(shader.c_str()); - // No uber shader support for VS and CS. - TaskHandle handle = ResourceBuilder::Get().AddShaderBuildTask(shaderType, - inputVSFilePath.c_str(), outputVSFilePath.c_str(), "", callbacks); - newInfo.m_taskHandles.insert(handle); - - } - else if (engine::ShaderType::Fragment == shaderType) - { - std::string inputFSFilePath = engine::Path::GetBuiltinShaderInputPath(shader.c_str()); - std::string outputFSFilePath = engine::Path::GetShaderOutputPath(shader.c_str(), newInfo.m_featuresCombine); - TaskHandle handle = ResourceBuilder::Get().AddShaderBuildTask(engine::ShaderType::Fragment, - inputFSFilePath.c_str(), outputFSFilePath.c_str(), newInfo.m_featuresCombine.c_str(), callbacks); - newInfo.m_taskHandles.insert(handle); - } - else - { - continue; - } - } + const auto& vs = pShaderResource->GetShaderInfo(0); + const auto& fs = pShaderResource->GetShaderInfo(1); - newInfos.emplace(cd::MoveTemp(newInfo)); + TaskHandle vsTaskHandle = ResourceBuilder::Get().AddShaderBuildTask(vs.type, + vs.scPath.c_str(), vs.binPath.c_str(), pShaderResource->GetFeaturesCombine().c_str(), callbacks); + TaskHandle fsTaskHandle = ResourceBuilder::Get().AddShaderBuildTask(fs.type, + fs.scPath.c_str(), fs.binPath.c_str(), pShaderResource->GetFeaturesCombine().c_str(), callbacks); + } + else + { + const auto& shader = pShaderResource->GetShaderInfo(0); + TaskHandle taskHandle = ResourceBuilder::Get().AddShaderBuildTask(shader.type, + shader.scPath.c_str(), shader.binPath.c_str(), pShaderResource->GetFeaturesCombine().c_str(), callbacks); } - - pRenderContext->SetShaderCompileInfos(cd::MoveTemp(newInfos)); } } // namespace editor diff --git a/Engine/Source/Editor/Resources/ShaderBuilder.h b/Engine/Source/Editor/Resources/ShaderBuilder.h index 31132f9b..868c22e1 100644 --- a/Engine/Source/Editor/Resources/ShaderBuilder.h +++ b/Engine/Source/Editor/Resources/ShaderBuilder.h @@ -1,8 +1,8 @@ #pragma once #include "Material/MaterialType.h" +#include "Rendering/Resources/ShaderResource.h" #include "Resources/ResourceBuilder.h" -#include "Rendering/ShaderCompileInfo.h" #include #include @@ -20,12 +20,11 @@ namespace editor class ShaderBuilder { public: - static void CompileRegisteredNonUberShader(engine::RenderContext* pRenderContext); - static void CompileRegisteredUberShader(engine::RenderContext* pRenderContext, engine::MaterialType* pMaterialType); - static void CompileUberShaderAllVariants(engine::RenderContext* pRenderContext, engine::MaterialType* pMaterialType); + static void RegisterUberShaderAllVariants(engine::RenderContext *pRenderContext, engine::MaterialType *pMaterialType); - // Compile specified shader program/program variant. - static void BuildShaderInfos(engine::RenderContext* pRenderContext, TaskOutputCallbacks callbacks = {}); + static void BuildRegisteredShaderResources(engine::RenderContext* pRenderContext, TaskOutputCallbacks callbacks = {}); + static void BuildRecompileShaderResources(engine::RenderContext* pRenderContext, TaskOutputCallbacks callbacks = {}); + static void BuildShaderResource(engine::RenderContext* pRenderContext, engine::ShaderResource* pShaderResource, TaskOutputCallbacks callbacks = {}); }; } // namespace editor diff --git a/Engine/Source/Editor/UILayers/AssetBrowser.cpp b/Engine/Source/Editor/UILayers/AssetBrowser.cpp index 87593cc7..009ac9c9 100644 --- a/Engine/Source/Editor/UILayers/AssetBrowser.cpp +++ b/Engine/Source/Editor/UILayers/AssetBrowser.cpp @@ -1,6 +1,9 @@ #include "AssetBrowser.h" #include "Consumers/CDConsumer/CDConsumer.h" +#ifdef ENABLE_FBX_CONSUMER +#include "Consumers/FbxConsumer/FbxConsumer.h" +#endif #include "ECWorld/ECWorldConsumer.h" #include "ECWorld/MaterialComponent.h" #include "ECWorld/SceneWorld.h" @@ -14,15 +17,17 @@ #include "Material/MaterialType.h" #include "Producers/CDProducer/CDProducer.h" #include "Producers/EffekseerProducer/EffekseerProducer.h" +#ifdef ENABLE_FBX_PRODUCER +#include "Producers/FbxProducer/FbxProducer.h" +#endif +#ifdef ENABLE_GENERIC_PRODUCER +#include "Producers/GenericProducer/GenericProducer.h" +#endif #include "Rendering/WorldRenderer.h" #include "Rendering/RenderContext.h" #include "Resources/ResourceBuilder.h" #include "Resources/ResourceLoader.h" -#ifdef ENABLE_GENERIC_PRODUCER -#include "Producers/GenericProducer/GenericProducer.h" -#endif - #include #include @@ -385,6 +390,15 @@ void AssetBrowser::UpdateAssetFolderTree() CD_INFO("Import asset type: {}", nameof::nameof_enum(m_importOptions.AssetType)); } + else if (ImGui::Selectable("Celluloid Model")) + { + m_importOptions.AssetType = IOAssetType::Model; + m_pImportFileBrowser->SetTitle("ImportAssets - Celluloid Model"); + //m_pImportFileBrowser->SetTypeFilters({ ".fbx", ".gltf" }); // ".obj", ".dae", ".ogex" + m_pImportFileBrowser->Open(); + + CD_INFO("Import asset type: {}", nameof::nameof_enum(m_importOptions.AssetType)); + } #ifdef ENABLE_DDGI else if (ImGui::Selectable("DDGI Model")) @@ -933,15 +947,28 @@ void AssetBrowser::ImportModelFile(const char* pFilePath) // Step 1 : Convert model file to cd::SceneDatabase std::filesystem::path inputFilePath(pFilePath); std::filesystem::path inputFileExtension = inputFilePath.extension(); + bool importedModel = false; + auto newSceneDatabase = std::make_unique(); if (0 == inputFileExtension.compare(".cdbin")) { cdtools::CDProducer cdProducer(pFilePath); - cd::SceneDatabase newSceneDatabase; - cdtools::Processor processor(&cdProducer, nullptr, &newSceneDatabase); + cdtools::Processor processor(&cdProducer, nullptr, newSceneDatabase.get()); processor.Run(); - pSceneDatabase->Merge(cd::MoveTemp(newSceneDatabase)); + importedModel = true; } - else + else if (0 == inputFileExtension.compare(".fbx")) + { +#ifdef ENABLE_FBX_PRODUCER + cdtools::FbxProducer fbxProducer(pFilePath); + fbxProducer.EnableOption(cdtools::FbxProducerOptions::Triangulate); + cdtools::Processor processor(&fbxProducer, nullptr, newSceneDatabase.get()); + processor.Run(); + importedModel = true; +#endif + } + + // Try generic producer only if specialized import workflow is not ready. + if (!importedModel) { #ifdef ENABLE_GENERIC_PRODUCER cdtools::GenericProducer genericProducer(pFilePath); @@ -954,20 +981,22 @@ void AssetBrowser::ImportModelFile(const char* pFilePath) genericProducer.EnableOption(cdtools::GenericProducerOptions::FlattenTransformHierarchy); } - cd::SceneDatabase newSceneDatabase; - cdtools::Processor processor(&genericProducer, nullptr, &newSceneDatabase); + cdtools::Processor processor(&genericProducer, nullptr, newSceneDatabase.get()); processor.EnableOption(cdtools::ProcessorOptions::Dump); processor.Run(); - pSceneDatabase->Merge(cd::MoveTemp(newSceneDatabase)); #else assert("Unable to import this file format."); + return; #endif } + // Move contents in temp scene database to SceneWorld. + pSceneDatabase->Merge(cd::MoveTemp(*newSceneDatabase)); + newSceneDatabase.reset(); + // Step 2 : Process generated cd::SceneDatabase ProcessSceneDatabase(pSceneDatabase, m_importOptions.ImportMesh, m_importOptions.ImportMaterial, m_importOptions.ImportTexture, m_importOptions.ImportCamera, m_importOptions.ImportLight); - // Step 3 : Convert cd::SceneDatabase to entities and components { ECWorldConsumer ecConsumer(pSceneWorld, pCurrentRenderContext); diff --git a/Engine/Source/Editor/UILayers/AssetBrowser.h b/Engine/Source/Editor/UILayers/AssetBrowser.h index 0538a566..da4349c8 100644 --- a/Engine/Source/Editor/UILayers/AssetBrowser.h +++ b/Engine/Source/Editor/UILayers/AssetBrowser.h @@ -51,7 +51,7 @@ struct AssetImportOptions bool ImportMaterial = true; bool ImportMesh = true; bool ImportTexture = true; - bool ImportAnimation = false; + bool ImportAnimation = true; }; struct AssetExportOptions diff --git a/Engine/Source/Editor/UILayers/EntityList.cpp b/Engine/Source/Editor/UILayers/EntityList.cpp index db7cc06c..b72e301f 100644 --- a/Engine/Source/Editor/UILayers/EntityList.cpp +++ b/Engine/Source/Editor/UILayers/EntityList.cpp @@ -32,6 +32,7 @@ void EntityList::AddEntity(engine::SceneWorld* pSceneWorld) cd::SceneDatabase* pSceneDatabase = pSceneWorld->GetSceneDatabase(); engine::MaterialType* pPBRMaterialType = pSceneWorld->GetPBRMaterialType(); engine::MaterialType* pTerrainMaterialType = pSceneWorld->GetTerrainMaterialType(); + engine::MaterialType* pCelluloidMaterialType = pSceneWorld->GetCelluloidMaterialType(); engine::MaterialType* pParticleMaterialType = pSceneWorld->GetParticleMaterialType(); engine::ResourceContext* pResourceContext = GetRenderContext()->GetResourceContext(); @@ -98,19 +99,38 @@ void EntityList::AddEntity(engine::SceneWorld* pSceneWorld) if (ImGui::MenuItem("Add Cube Mesh")) { engine::Entity entity = AddNamedEntity("CubeMesh"); - // TODO : manage temp asset. - static std::optional optMesh = cd::MeshGenerator::Generate(cd::Box(cd::Point(-10.0f), cd::Point(10.0f)), pPBRMaterialType->GetRequiredVertexFormat()); + std::optional optMesh = cd::MeshGenerator::Generate(cd::Box(cd::Point(-10.0f), cd::Point(10.0f)), pPBRMaterialType->GetRequiredVertexFormat()); assert(optMesh.has_value()); + optMesh->SetName(pSceneWorld->GetNameComponent(entity)->GetName()); CreateShapeComponents(entity, cd::MoveTemp(optMesh.value()), pPBRMaterialType); } + + else if (ImGui::MenuItem("Add Celluloid Cube Mesh")) + { + engine::Entity entity = AddNamedEntity("Celluloid Cube"); + std::optional optMesh = cd::MeshGenerator::Generate(cd::Box(cd::Point(-10.0f), cd::Point(10.0f)), pCelluloidMaterialType->GetRequiredVertexFormat()); + assert(optMesh.has_value()); + optMesh->SetName(pSceneWorld->GetNameComponent(entity)->GetName()); + CreateShapeComponents(entity, cd::MoveTemp(optMesh.value()), pCelluloidMaterialType); + } + else if (ImGui::MenuItem("Add Sphere Mesh")) { engine::Entity entity = AddNamedEntity("Sphere"); - // TODO : manage temp asset. - static std::optional optMesh = cd::MeshGenerator::Generate(cd::Sphere(cd::Point(0.0f), 10.0f), 100U, 100U, pPBRMaterialType->GetRequiredVertexFormat()); + std::optional optMesh = cd::MeshGenerator::Generate(cd::Sphere(cd::Point(0.0f), 10.0f), 100U, 100U, pPBRMaterialType->GetRequiredVertexFormat()); assert(optMesh.has_value()); + optMesh->SetName(pSceneWorld->GetNameComponent(entity)->GetName()); CreateShapeComponents(entity, cd::MoveTemp(optMesh.value()), pPBRMaterialType); } + + else if (ImGui::MenuItem("Add Celluloid Sphere Mesh")) + { + engine::Entity entity = AddNamedEntity("Celluloid Sphere"); + std::optional optMesh = cd::MeshGenerator::Generate(cd::Sphere(cd::Point(0.0f), 10.0f), 100U, 100U, pCelluloidMaterialType->GetRequiredVertexFormat()); + assert(optMesh.has_value()); + optMesh->SetName(pSceneWorld->GetNameComponent(entity)->GetName()); + CreateShapeComponents(entity, cd::MoveTemp(optMesh.value()), pCelluloidMaterialType); + } else if (ImGui::MenuItem("Add Terrain Mesh")) { engine::Entity entity = AddNamedEntity("Terrain"); diff --git a/Engine/Source/Editor/UILayers/Inspector.cpp b/Engine/Source/Editor/UILayers/Inspector.cpp index be0cb447..ca1bf356 100644 --- a/Engine/Source/Editor/UILayers/Inspector.cpp +++ b/Engine/Source/Editor/UILayers/Inspector.cpp @@ -1,14 +1,14 @@ #include "Inspector.h" -#include "Rendering/RenderContext.h" -#include "Rendering/ShaderCollections.h" -#include "Resources/ResourceBuilder.h" -#include "Resources/ResourceLoader.h" -#include "Rendering/Resources/ResourceContext.h" -#include "Rendering/Resources/TextureResource.h" #include "Graphics/GraphicsBackend.h" #include "ImGui/ImGuiUtils.hpp" #include "Path/Path.h" +#include "Rendering/RenderContext.h" +#include "Rendering/Resources/ResourceContext.h" +#include "Rendering/Resources/ShaderResource.h" +#include "Rendering/Resources/TextureResource.h" +#include "Resources/ResourceBuilder.h" +#include "Resources/ResourceLoader.h" #include "ImGui/imfilebrowser.h" @@ -228,7 +228,7 @@ void UpdateComponentWidget(engine::SceneWorld* pScene ImGui::SetCursorScreenPos(ImVec2{ currentPos.x, currentPos.y + 66}); } - ImGuiUtils::ImGuiBoolProperty("Use texture", pPropertyGroup->useTexture); + bool isPropertyGroupChanded = ImGuiUtils::ImGuiBoolProperty("Use texture", pPropertyGroup->useTexture); ImGui::SameLine(130.0f); if (ImGui::Button("Select...")) { @@ -239,15 +239,18 @@ void UpdateComponentWidget(engine::SceneWorld* pScene ImGuiUtils::ImGuiVectorProperty("UV Offset", textureInfo.GetUVOffset(), cd::Unit::None, cd::Vec2f::Zero(), cd::Vec2f::One(), false, 0.01f); ImGuiUtils::ImGuiVectorProperty("UV Scale", textureInfo.GetUVScale()); - if (pPropertyGroup->useTexture) - { - pMaterialComponent->ActivateShaderFeature(engine::MaterialTextureTypeToShaderFeature.at(textureType)); - } - else + if (isPropertyGroupChanded) { - pMaterialComponent->DeactivateShaderFeature(engine::MaterialTextureTypeToShaderFeature.at(textureType)); + if (pPropertyGroup->useTexture) + { + pMaterialComponent->ActivateShaderFeature(engine::MaterialTextureTypeToShaderFeature.at(textureType)); + } + else + { + pMaterialComponent->DeactivateShaderFeature(engine::MaterialTextureTypeToShaderFeature.at(textureType)); + } } - + if (cd::MaterialTextureType::BaseColor == textureType) { ImGuiUtils::ColorPickerProperty("Factor", *(pMaterialComponent->GetFactor(textureType))); @@ -275,6 +278,51 @@ void UpdateComponentWidget(engine::SceneWorld* pScene ImGui::PopStyleVar(); } + // Cartoon + { + bool isOpen = ImGui::CollapsingHeader("Cartoon Material", ImGuiTreeNodeFlags_AllowItemOverlap | ImGuiTreeNodeFlags_Selected); + ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(2, 2)); + ImGui::Separator(); + if (isOpen) + { + ImGuiUtils::ImGuiBoolProperty("OutLine", pMaterialComponent->GetToonParameters().isOpenOutLine); + ImGuiUtils::ColorPickerProperty("OutLineColor", pMaterialComponent->GetToonParameters().outLineColor); + ImGuiUtils::ImGuiFloatProperty("OutLineSize", pMaterialComponent->GetToonParameters().outLineSize, cd::Unit::None, 0.0f, 100.0f, false, 0.1f); + ImGuiUtils::ColorPickerProperty("First Shadow Color", pMaterialComponent->GetToonParameters().firstShadowColor); + ImGuiUtils::ColorPickerProperty("Second Color", pMaterialComponent->GetToonParameters().secondShadowColor); + ImGuiUtils::ImGuiFloatProperty("FirsrShadow", pMaterialComponent->GetToonParameters().dividLine.x(), cd::Unit::None, 0.0f, 1.0f, false, 0.01f); + ImGuiUtils::ImGuiFloatProperty("FirstShadow Feather", pMaterialComponent->GetToonParameters().dividLine.y(), cd::Unit::None, 0.0001f, 1.0f, false, 0.01f); + ImGuiUtils::ImGuiFloatProperty("SecondShadow", pMaterialComponent->GetToonParameters().dividLine.z(), cd::Unit::None, 0.0f, 1.0f, false, 0.01f); + ImGuiUtils::ImGuiFloatProperty("SecondShadow Feather", pMaterialComponent->GetToonParameters().dividLine.w(), cd::Unit::None, 0.01f, 1.0f, false, 0.01f); + ImGuiUtils::ImGuiFloatProperty("Specular Size", pMaterialComponent->GetToonParameters().specular.x(), cd::Unit::None, 0.0f, 1.0f, false, 0.01f); + ImGuiUtils::ImGuiFloatProperty("Specular Power", pMaterialComponent->GetToonParameters().specular.y(), cd::Unit::None, 0.0f, 1.0f, false, 0.01f); + ImGuiUtils::ImGuiFloatProperty("Specular Mask", pMaterialComponent->GetToonParameters().specular.z(), cd::Unit::None, 0.0f, 1.0f, false, 0.01f); + ImGuiUtils::ImGuiFloatProperty("High Light Halo", pMaterialComponent->GetToonParameters().specular.w(), cd::Unit::None, 0.0f, 1.0f, false, 0.01f); + ImGuiUtils::ColorPickerProperty("Rim Light Color", pMaterialComponent->GetToonParameters().rimLightColor); + ImGuiUtils::ImGuiFloatProperty("Rim Light Range", pMaterialComponent->GetToonParameters().rimLight.x(), cd::Unit::None, 0.0f, 1.0f, false, 0.01f); + ImGuiUtils::ImGuiFloatProperty("Rim Light Feather", pMaterialComponent->GetToonParameters().rimLight.y(), cd::Unit::None, 0.0f, 1.0f, false, 0.01f); + ImGuiUtils::ImGuiFloatProperty("Rim Light Itensity", pMaterialComponent->GetToonParameters().rimLight.z(), cd::Unit::None, 0.0f, 1.0f, false, 0.01f); + ImGuiUtils::ImGuiFloatProperty("Rim Light Mask", pMaterialComponent->GetToonParameters().rimLight.w(), cd::Unit::None, 0.0f, 1.0f, false, 0.01f); + } + + ImGui::Separator(); + ImGui::PopStyleVar(); + } + + // Ambient + { + bool isOpen = ImGui::CollapsingHeader("Ambient", ImGuiTreeNodeFlags_AllowItemOverlap | ImGuiTreeNodeFlags_DefaultOpen); + ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(2, 2)); + ImGui::Separator(); + if (isOpen) + { + ImGuiUtils::ImGuiFloatProperty("iblStrength", pMaterialComponent->GetIblStrengeth(), cd::Unit::None, 0.01f, 10.0f, false, 0.02f); + } + + ImGui::Separator(); + ImGui::PopStyleVar(); + } + // Shaders { bool isOpen = ImGui::CollapsingHeader("Shader", ImGuiTreeNodeFlags_AllowItemOverlap | ImGuiTreeNodeFlags_DefaultOpen); @@ -283,13 +331,14 @@ void UpdateComponentWidget(engine::SceneWorld* pScene if (isOpen) { - const auto& shaderProgramName = pMaterialComponent->GetShaderProgramName(); - ImGuiUtils::ImGuiStringProperty("Shader Program", shaderProgramName); - engine::RenderContext* pRenderContext = static_cast(ImGui::GetIO().BackendRendererUserData); - for (const auto& shaderFileName : pRenderContext->GetShaderCollections()->GetShaders(engine::StringCrc{ shaderProgramName })) + const engine::ShaderResource* pShaderResource = pMaterialComponent->GetShaderResource(); + + ImGuiUtils::ImGuiStringProperty("Shader Program", pShaderResource->GetName()); + ImGuiUtils::ImGuiStringProperty("Shader", pShaderResource->GetShaderInfo(0).name); + if (engine::ShaderProgramType::Standard == pShaderResource->GetType()) { - ImGuiUtils::ImGuiStringProperty("Shader", shaderFileName); + ImGuiUtils::ImGuiStringProperty("Shader", pShaderResource->GetShaderInfo(1).name); } ImGui::Separator(); @@ -586,6 +635,9 @@ void UpdateComponentWidget(engine::SceneWorld* pSceneWorld } } + ImGui::Separator(); + ImGuiUtils::ImGuiFloatProperty("Skybox Strength", pSkyComponent->GetSkyboxStrength(), cd::Unit::None, 0.01f, 10.0f, false, 0.02f); + if (pSkyComponent->GetAtmophericScatteringEnable()) { ImGui::Separator(); @@ -663,6 +715,32 @@ void UpdateComponentWidget(engine::SceneWor ImGui::PopStyleVar(); } +template<> +void UpdateComponentWidget(engine::SceneWorld* pSceneWorld, engine::Entity entity) +{ + auto* pAnimationComponent = pSceneWorld->GetAnimationComponent(entity); + if (!pAnimationComponent) + { + return; + } + + bool isOpen = ImGui::CollapsingHeader("Animation Component", ImGuiTreeNodeFlags_AllowItemOverlap | ImGuiTreeNodeFlags_DefaultOpen); + ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(2, 2)); + ImGui::Separator(); + + if (isOpen) + { + ImGui::Separator(); + ImGuiUtils::ImGuiBoolProperty("play", pAnimationComponent->GetIsPlaying()); + ImGuiUtils::ImGuiEnumProperty("AnimationClip", pAnimationComponent->GetAnimationClip()); + ImGuiUtils::ImGuiFloatProperty("Factor", pAnimationComponent->GetBlendFactor(), cd::Unit::None, 0.0f, 1.0f, false, 0.01f); + ImGuiUtils::ImGuiFloatProperty("Time", pAnimationComponent->GetAnimationPlayTime(), cd::Unit::None); + ImGuiUtils::ImGuiFloatProperty("PlayBackSpeed", pAnimationComponent->GetPlayBackSpeed(), cd::Unit::None, 0.0f, 10.0f, false, 0.01f); + } + ImGui::Separator(); + ImGui::PopStyleVar(); +} + } namespace editor @@ -714,6 +792,7 @@ void Inspector::Update() details::UpdateComponentWidget(pSceneWorld, m_lastSelectedEntity); details::UpdateComponentWidget(pSceneWorld, m_lastSelectedEntity); details::UpdateComponentWidget(pSceneWorld, m_lastSelectedEntity); + details::UpdateComponentWidget(pSceneWorld, m_lastSelectedEntity); if (IsOpenFileBrowser()) { diff --git a/Engine/Source/Editor/UILayers/MainMenu.cpp b/Engine/Source/Editor/UILayers/MainMenu.cpp index f21c2ac2..9a5fb7bd 100644 --- a/Engine/Source/Editor/UILayers/MainMenu.cpp +++ b/Engine/Source/Editor/UILayers/MainMenu.cpp @@ -224,9 +224,18 @@ void MainMenu::BuildMenu() if (ImGui::MenuItem(CD_TEXT("TEXT_BUILD_PBR_VARIANT"))) { - ShaderBuilder::CompileUberShaderAllVariants(GetRenderContext(), pSceneWorld->GetPBRMaterialType()); + ShaderBuilder::RegisterUberShaderAllVariants(GetRenderContext(), pSceneWorld->GetPBRMaterialType()); + ResourceBuilder::Get().Update(); } +#ifdef ENABLE_DDGI + if (ImGui::MenuItem(CD_TEXT("TEXT_BUILD_PBR_VARIANT"))) + { + ShaderBuilder::RegisterUberShaderAllVariants(m_pRenderContext.get(), m_pSceneWorld->GetDDGIMaterialType()); + ResourceBuilder::Get().Update(); + } +#endif + ImGui::EndMenu(); } } diff --git a/Engine/Source/Editor/UILayers/SceneView.h b/Engine/Source/Editor/UILayers/SceneView.h index fbcb9e1f..f5bce4a4 100644 --- a/Engine/Source/Editor/UILayers/SceneView.h +++ b/Engine/Source/Editor/UILayers/SceneView.h @@ -3,6 +3,7 @@ #include "ECWorld/Entity.h" #include "ImGui/ImGuiBaseLayer.h" #include "Rendering/AABBRenderer.h" +#include "Rendering/CelluloidRenderer.h" #include "Rendering/WhiteModelRenderer.h" #include diff --git a/Engine/Source/Editor/UILayers/SkeletonView.cpp b/Engine/Source/Editor/UILayers/SkeletonView.cpp index fc488cf6..bdd21b3d 100644 --- a/Engine/Source/Editor/UILayers/SkeletonView.cpp +++ b/Engine/Source/Editor/UILayers/SkeletonView.cpp @@ -44,12 +44,17 @@ void SkeletonView::DrawBone(cd::SceneDatabase* pSceneDatabase, const cd::Bone& B void SkeletonView::DrawSkeleton(engine::SceneWorld* pSceneWorld) { cd::SceneDatabase* pSceneDatabase = pSceneWorld->GetSceneDatabase(); - if (0 == pSceneDatabase->GetBoneCount()) + if (0 == pSceneDatabase->GetSkeletonCount()) { return; } - const cd::Bone& rootBone = pSceneDatabase->GetBone(0); - DrawBone(pSceneDatabase, rootBone); + for (uint32_t skeletonIndex = 0; skeletonIndex < pSceneDatabase->GetSkeletonCount(); skeletonIndex++) + { + const cd::Skeleton& skeleton = pSceneDatabase->GetSkeleton(skeletonIndex); + auto rootBoneID = skeleton.GetRootBoneID(); + const cd::Bone& rootBone = pSceneDatabase->GetBone(rootBoneID.Data()); + DrawBone(pSceneDatabase, rootBone); + } } void SkeletonView::Update() @@ -63,11 +68,7 @@ void SkeletonView::Update() ImGui::End(); return; } - engine::AnimationComponent* pAnimationConponent = pSceneWorld->GetAnimationComponent(selectedEntity); - if (pAnimationConponent) - { - DrawSkeleton(pSceneWorld); - } + DrawSkeleton(pSceneWorld); ImGui::End(); } diff --git a/Engine/Source/Editor/UILayers/SkeletonView.h b/Engine/Source/Editor/UILayers/SkeletonView.h index 21252484..8f433088 100644 --- a/Engine/Source/Editor/UILayers/SkeletonView.h +++ b/Engine/Source/Editor/UILayers/SkeletonView.h @@ -2,6 +2,7 @@ #include "Scene/Bone.h" #include "Scene/SceneDatabase.h" +#include "Scene/Skeleton.h" namespace editor { diff --git a/Engine/Source/Runtime/Display/CameraController.cpp b/Engine/Source/Runtime/Display/CameraController.cpp index 43b4360e..f9abc014 100644 --- a/Engine/Source/Runtime/Display/CameraController.cpp +++ b/Engine/Source/Runtime/Display/CameraController.cpp @@ -184,7 +184,7 @@ void CameraController::Update(float deltaTime) PitchLocal(m_verticalSensitivity * Input::Get().GetMousePositionOffsetY() * deltaTime); Yaw(m_horizontalSensitivity * Input::Get().GetMousePositionOffsetX() * deltaTime); } - if (Input::Get().GetMouseScrollOffsetY() && !m_isMoving && m_isMouseInViewScene && !ImGuizmo::IsUsing()) + if (Input::Get().GetMouseScrollOffsetY() && !m_isMoving && m_isMouseInViewScene && !ImGuizmo::IsUsing() && !Input::Get().IsMouseLBPressed() && !Input::Get().IsMouseRBPressed()) { m_isTracking = false; MoveForward(m_movementSpeed * Input::Get().GetMouseScrollOffsetY() * deltaTime * 10.0f); diff --git a/Engine/Source/Runtime/ECWorld/AllComponentsHeader.h b/Engine/Source/Runtime/ECWorld/AllComponentsHeader.h index 7af83610..40028a47 100644 --- a/Engine/Source/Runtime/ECWorld/AllComponentsHeader.h +++ b/Engine/Source/Runtime/ECWorld/AllComponentsHeader.h @@ -13,6 +13,8 @@ #include "ECWorld/NameComponent.h" #include "ECWorld/SkyComponent.h" #include "ECWorld/StaticMeshComponent.h" +#include "ECWorld/SkeletonComponent.h" +#include "ECWorld/SkinMeshComponent.h" #include "ECWorld/TerrainComponent.h" #include "ECWorld/TransformComponent.h" #include "ECWorld/ParticleEmitterComponent.h" diff --git a/Engine/Source/Runtime/ECWorld/AnimationComponent.h b/Engine/Source/Runtime/ECWorld/AnimationComponent.h index 2430324a..45e10454 100644 --- a/Engine/Source/Runtime/ECWorld/AnimationComponent.h +++ b/Engine/Source/Runtime/ECWorld/AnimationComponent.h @@ -16,6 +16,17 @@ class Track; namespace engine { +enum class AnimationClip +{ + Idel, + Walking, + Running, + + Blend, + Switch, + Count, +}; + class AnimationComponent final { public: @@ -35,7 +46,7 @@ class AnimationComponent final const cd::Animation* GetAnimationData() const { return m_pAnimation; } void SetAnimationData(const cd::Animation* pAnimation) { m_pAnimation = pAnimation; } - + // TODO : use std::span to present pointer array. const cd::Track* GetTrackData() const { return m_pTrack; } void SetTrackData(const cd::Track* pTrack) { m_pTrack = pTrack; } @@ -49,14 +60,32 @@ class AnimationComponent final void SetBoneMatricesUniform(uint16_t uniform) { m_boneMatricesUniform = uniform; } uint16_t GetBoneMatrixsUniform() const { return m_boneMatricesUniform; } - void SetBoneMatrices(std::vector boneMatrices) { m_boneMatrices = cd::MoveTemp(boneMatrices); } - std::vector& GetBoneMatrices() { return m_boneMatrices; } - const std::vector& GetBoneMatrices() const { return m_boneMatrices; } + void SetAnimationPlayTime(float time) { m_animationPlayTime = time; } + float& GetAnimationPlayTime() { return m_animationPlayTime; } + + void SetPlayBackSpeed(float time) { m_playBackSpeed = time; } + float& GetPlayBackSpeed() { return m_playBackSpeed; } + + void SetAnimationClip(AnimationClip crtClip) { m_clip = crtClip; } + AnimationClip& GetAnimationClip() { return m_clip; } + const AnimationClip& GeAnimationClip() const { return m_clip; } + + void SetBlendFactor(float factor) { m_blendFactor = factor; } + float& GetBlendFactor() { return m_blendFactor; } + const float GetBlendFactor() const { return m_blendFactor; } + + bool& GetIsPlaying() { return m_playAnimation; } private: + AnimationClip m_clip = AnimationClip::Idel; const cd::Animation* m_pAnimation = nullptr; const cd::Track* m_pTrack = nullptr; - + + float m_blendFactor = 0.0f; + float m_playBackSpeed = 1.0f; + bool m_playAnimation = false; + + float m_animationPlayTime; float m_duration; float m_ticksPerSecond; uint16_t m_boneMatricesUniform; diff --git a/Engine/Source/Runtime/ECWorld/MaterialComponent.cpp b/Engine/Source/Runtime/ECWorld/MaterialComponent.cpp index f8bba0f4..bb2c1c5a 100644 --- a/Engine/Source/Runtime/ECWorld/MaterialComponent.cpp +++ b/Engine/Source/Runtime/ECWorld/MaterialComponent.cpp @@ -2,6 +2,8 @@ #include "Log/Log.h" #include "Material/MaterialType.h" +#include "Rendering/Resources/ShaderResource.h" +#include "Rendering/Resources/TextureResource.h" #include "Scene/Material.h" #include @@ -39,6 +41,22 @@ void MaterialComponent::Init() m_propertyGroups[cd::MaterialPropertyGroup::Emissive] = cd::MoveTemp(propertyGroup); } +void MaterialComponent::Reset() +{ + m_pMaterialData = nullptr; + m_pMaterialType = nullptr; + m_name.clear(); + m_twoSided = false; + m_blendMode = cd::BlendMode::Opaque; + m_alphaCutOff = 1.0f; + m_isShaderFeaturesDirty = true; + m_isShaderResourceDirty = true; + m_pShaderResource = nullptr; + m_shaderFeatures.clear(); + m_featureCombine.clear(); + m_propertyGroups.clear(); +} + void MaterialComponent::SetMaterialData(const cd::Material* pMaterialData) { m_pMaterialData = pMaterialData; @@ -82,49 +100,62 @@ void MaterialComponent::ActivateShaderFeature(ShaderFeature feature) return; } - for (const auto& conflict : m_pMaterialType->GetShaderSchema().GetConflictFeatureSet(feature)) + if (const auto& optConflictFeatureSet = m_pMaterialType->GetShaderSchema().GetConflictFeatureSet(feature); optConflictFeatureSet.has_value()) { - m_shaderFeatures.erase(conflict); + for (const auto& conflictFeature : optConflictFeatureSet.value()) + { + m_shaderFeatures.erase(conflictFeature); + } } m_shaderFeatures.insert(cd::MoveTemp(feature)); - - m_isShaderFeatureDirty = true; + m_isShaderFeaturesDirty = true; + m_isShaderResourceDirty = true; } void MaterialComponent::DeactivateShaderFeature(ShaderFeature feature) { m_shaderFeatures.erase(feature); - - m_isShaderFeatureDirty = true; + m_isShaderFeaturesDirty = true; + m_isShaderResourceDirty = true; } const std::string& MaterialComponent::GetFeaturesCombine() { - if (false == m_isShaderFeatureDirty) + if (false == m_isShaderFeaturesDirty) { return m_featureCombine; } + m_isShaderFeaturesDirty = false; m_featureCombine = m_pMaterialType->GetShaderSchema().GetFeaturesCombine(m_shaderFeatures); - m_isShaderFeatureDirty = false; return m_featureCombine; } -void MaterialComponent::Reset() +void MaterialComponent::SetShaderFeatures(std::set features) { - m_pMaterialData = nullptr; - m_pMaterialType = nullptr; - m_name.clear(); - m_twoSided = false; - m_blendMode = cd::BlendMode::Opaque; - m_alphaCutOff = 1.0f; - m_isShaderFeatureDirty = false; - m_shaderFeatures.clear(); - m_featureCombine.clear(); - m_cacheTextureBlobs.clear(); - m_propertyGroups.clear(); + m_shaderFeatures = cd::MoveTemp(features); + m_isShaderFeaturesDirty = true; + m_isShaderResourceDirty = true; +} + +void MaterialComponent::SetShaderResource(ShaderResource* pShaderResource) +{ + if (m_pShaderResource) + { + m_pShaderResource->SetActive(false); + } + m_pShaderResource = pShaderResource; + m_pShaderResource->SetActive(true); + + m_isShaderResourceDirty = false; +} + +ShaderResource* MaterialComponent::GetShaderResource() const +{ + assert(!m_isShaderResourceDirty); + return m_pShaderResource; } TextureResource* MaterialComponent::GetTextureResource(cd::MaterialTextureType textureType) const diff --git a/Engine/Source/Runtime/ECWorld/MaterialComponent.h b/Engine/Source/Runtime/ECWorld/MaterialComponent.h index ed0ec95d..0f7571f6 100644 --- a/Engine/Source/Runtime/ECWorld/MaterialComponent.h +++ b/Engine/Source/Runtime/ECWorld/MaterialComponent.h @@ -32,6 +32,7 @@ namespace engine class MaterialType; class RenderContext; +class ShaderResource; class TextureResource; class MaterialComponent final @@ -67,6 +68,19 @@ class MaterialComponent final std::variant factor; }; + struct ToonParameters + { + bool isOpenOutLine = false; + cd::Vec3f outLineColor = cd::Vec3f::Zero(); + float outLineSize = 0.5f; + cd::Vec3f firstShadowColor = cd::Vec3f::Zero(); + cd::Vec3f secondShadowColor = cd::Vec3f::Zero(); + cd::Vec4f rimLight = cd::Vec4f::Zero(); + cd::Vec4f dividLine = cd::Vec4f::Zero(); + cd::Vec4f specular = cd::Vec4f::Zero(); + cd::Vec3f rimLightColor = cd::Vec3f::Zero(); + }; + public: MaterialComponent() = default; MaterialComponent(const MaterialComponent&) = default; @@ -76,6 +90,7 @@ class MaterialComponent final ~MaterialComponent() = default; void Init(); + void Reset(); void SetMaterialData(const cd::Material* pMaterialData); cd::Material* GetMaterialData() { return const_cast(m_pMaterialData); } @@ -84,21 +99,25 @@ class MaterialComponent final void SetMaterialType(const engine::MaterialType* pMaterialType) { m_pMaterialType = pMaterialType; } const engine::MaterialType* GetMaterialType() const { return m_pMaterialType; } - void Reset(); - // Basic data. void SetName(std::string name) { m_name = cd::MoveTemp(name); } std::string& GetName() { return m_name; } const std::string& GetName() const { return m_name; } const std::string& GetShaderProgramName() const; - // Uber shader data. + // Uber shader + // Activa one Feature will erase all conflicting Features. void ActivateShaderFeature(ShaderFeature feature); void DeactivateShaderFeature(ShaderFeature feature); - void SetShaderFeatures(std::set options) { m_shaderFeatures = cd::MoveTemp(m_shaderFeatures); } + const std::string& GetFeaturesCombine(); + + void SetShaderFeatures(std::set features); std::set& GetShaderFeatures() { return m_shaderFeatures; } const std::set& GetShaderFeatures() const { return m_shaderFeatures; } - const std::string& GetFeaturesCombine(); + + bool IsShaderResourceDirty() const { return m_isShaderResourceDirty; } + void SetShaderResource(ShaderResource* pShaderResource); + ShaderResource* GetShaderResource() const; // Texture data. TextureResource* GetTextureResource(cd::MaterialTextureType textureType) const; @@ -161,23 +180,32 @@ class MaterialComponent final float& GetAlphaCutOff() { return m_alphaCutOff; } float GetAlphaCutOff() const { return m_alphaCutOff; } + void SetIblStrengeth(float strength) { m_iblStrength = strength; } + float& GetIblStrengeth() { return m_iblStrength; } + float GetIblStrengeth() const { return m_iblStrength; } + + void SetToonParameters(ToonParameters toonParameters) { m_toonParameters = toonParameters; } + ToonParameters& GetToonParameters() { return m_toonParameters; } + ToonParameters GetToonParameters() const { return m_toonParameters; } + private: // Input + std::string m_name; const cd::Material* m_pMaterialData = nullptr; const engine::MaterialType* m_pMaterialType = nullptr; - std::string m_name; - bool m_twoSided; - cd::BlendMode m_blendMode; - float m_alphaCutOff; - - bool m_isShaderFeatureDirty = false; - std::set m_shaderFeatures; + bool m_isShaderFeaturesDirty = true; + bool m_isShaderResourceDirty = true; std::string m_featureCombine; - - std::vector m_cacheTextureBlobs; + std::set m_shaderFeatures; + ShaderResource* m_pShaderResource = nullptr; // Output + bool m_twoSided; + cd::BlendMode m_blendMode; + float m_alphaCutOff; + float m_iblStrength = 0.5f; + ToonParameters m_toonParameters; std::map m_propertyGroups; }; diff --git a/Engine/Source/Runtime/ECWorld/ParticleEmitterComponent.cpp b/Engine/Source/Runtime/ECWorld/ParticleEmitterComponent.cpp index 32dc1ac7..69093d6d 100644 --- a/Engine/Source/Runtime/ECWorld/ParticleEmitterComponent.cpp +++ b/Engine/Source/Runtime/ECWorld/ParticleEmitterComponent.cpp @@ -303,13 +303,16 @@ void ParticleEmitterComponent::ActivateShaderFeature(ShaderFeature feature) return; } - for (const auto& conflict : m_pParticleMaterialType->GetShaderSchema().GetConflictFeatureSet(feature)) + // TODO : Should remove uber shader stuff from ParticleEmitterComponent. + if (const auto& optConflictFeatureSet = m_pParticleMaterialType->GetShaderSchema().GetConflictFeatureSet(feature); optConflictFeatureSet.has_value()) { - m_shaderFeatures.erase(conflict); + for (const auto& conflictFeature : optConflictFeatureSet.value()) + { + m_shaderFeatures.erase(conflictFeature); + } } m_shaderFeatures.insert(cd::MoveTemp(feature)); - m_isShaderFeatureDirty = true; } diff --git a/Engine/Source/Runtime/ECWorld/SceneWorld.cpp b/Engine/Source/Runtime/ECWorld/SceneWorld.cpp index 54cb4aae..a376556b 100644 --- a/Engine/Source/Runtime/ECWorld/SceneWorld.cpp +++ b/Engine/Source/Runtime/ECWorld/SceneWorld.cpp @@ -35,6 +35,8 @@ SceneWorld::SceneWorld() m_pNameComponentStorage = m_pWorld->Register(); m_pSkyComponentStorage = m_pWorld->Register(); m_pStaticMeshComponentStorage = m_pWorld->Register(); + m_pSkinMeshComponentStorage = m_pWorld->Register(); + m_pSkeletonComponentStorage = m_pWorld->Register(); m_pParticleEmitterComponentStorage = m_pWorld->Register(); m_pParticleForceFieldComponentStorage = m_pWorld->Register(); m_pTerrainComponentStorage = m_pWorld->Register(); @@ -112,6 +114,30 @@ void SceneWorld::CreateTerrainMaterialType(std::string shaderProgramName) m_pTerrainMaterialType->SetRequiredVertexFormat(cd::MoveTemp(terrainVertexFormat)); } +void SceneWorld::CreateCelluloidMaterialType(std::string shaderProgramName) +{ + m_pCelluloidMaterialType = std::make_unique(); + m_pCelluloidMaterialType->SetMaterialName("CD_Celluloid"); + + ShaderSchema shaderSchema; + shaderSchema.SetShaderProgramName(cd::MoveTemp(shaderProgramName)); + shaderSchema.AddFeatureSet({ ShaderFeature::ALBEDO_MAP }); + shaderSchema.AddFeatureSet({ ShaderFeature::NORMAL_MAP }); + shaderSchema.AddFeatureSet({ ShaderFeature::EMISSIVE_MAP }); + m_pCelluloidMaterialType->SetShaderSchema(cd::MoveTemp(shaderSchema)); + + cd::VertexFormat celluloidVertexFormat; + celluloidVertexFormat.AddVertexAttributeLayout(cd::VertexAttributeType::Position, cd::GetAttributeValueType(), cd::Point::Size); + celluloidVertexFormat.AddVertexAttributeLayout(cd::VertexAttributeType::Normal, cd::GetAttributeValueType(), cd::Direction::Size); + celluloidVertexFormat.AddVertexAttributeLayout(cd::VertexAttributeType::Tangent, cd::GetAttributeValueType(), cd::Direction::Size); + celluloidVertexFormat.AddVertexAttributeLayout(cd::VertexAttributeType::UV, cd::GetAttributeValueType(), cd::UV::Size); + m_pCelluloidMaterialType->SetRequiredVertexFormat(cd::MoveTemp(celluloidVertexFormat)); + + m_pCelluloidMaterialType->AddOptionalTextureType(cd::MaterialTextureType::BaseColor, ALBEDO_MAP_SLOT); + m_pCelluloidMaterialType->AddOptionalTextureType(cd::MaterialTextureType::Normal, NORMAL_MAP_SLOT); + m_pCelluloidMaterialType->AddOptionalTextureType(cd::MaterialTextureType::Emissive, EMISSIVE_MAP_SLOT); +} + void SceneWorld::CreateParticleMaterialType(std::string shaderProgramName) { m_pParticleMaterialType = std::make_unique(); diff --git a/Engine/Source/Runtime/ECWorld/SceneWorld.h b/Engine/Source/Runtime/ECWorld/SceneWorld.h index 7ee6025c..7438439e 100644 --- a/Engine/Source/Runtime/ECWorld/SceneWorld.h +++ b/Engine/Source/Runtime/ECWorld/SceneWorld.h @@ -38,6 +38,8 @@ class SceneWorld DEFINE_COMPONENT_STORAGE_WITH_APIS(Light); DEFINE_COMPONENT_STORAGE_WITH_APIS(Material); DEFINE_COMPONENT_STORAGE_WITH_APIS(Name); + DEFINE_COMPONENT_STORAGE_WITH_APIS(Skeleton); + DEFINE_COMPONENT_STORAGE_WITH_APIS(SkinMesh); DEFINE_COMPONENT_STORAGE_WITH_APIS(Sky); DEFINE_COMPONENT_STORAGE_WITH_APIS(StaticMesh); DEFINE_COMPONENT_STORAGE_WITH_APIS(ParticleEmitter); @@ -96,6 +98,8 @@ class SceneWorld DeleteLightComponent(entity); DeleteMaterialComponent(entity); DeleteNameComponent(entity); + DeleteSkeletonComponent(entity); + DeleteSkinMeshComponent(entity); DeleteSkyComponent(entity); DeleteStaticMeshComponent(entity); DeleteParticleEmitterComponent(entity); @@ -116,6 +120,9 @@ class SceneWorld void CreateParticleMaterialType(std::string shaderProgramName); CD_FORCEINLINE engine::MaterialType* GetParticleMaterialType() const { return m_pParticleMaterialType.get(); } + void CreateCelluloidMaterialType(std::string shaderProgramName); + CD_FORCEINLINE engine::MaterialType* GetCelluloidMaterialType() const { return m_pCelluloidMaterialType.get(); } + #ifdef ENABLE_DDGI void CreateDDGIMaterialType(std::string shaderProgramName); CD_FORCEINLINE engine::MaterialType* GetDDGIMaterialType() const { return m_pDDGIMaterialType.get(); } @@ -137,8 +144,10 @@ class SceneWorld std::unique_ptr m_pPBRMaterialType; std::unique_ptr m_pAnimationMaterialType; + std::unique_ptr m_pCelluloidMaterialType; std::unique_ptr m_pTerrainMaterialType; std::unique_ptr m_pDDGIMaterialType; + std::unique_ptr m_pPRMaterialType; std::unique_ptr m_pParticleMaterialType; // TODO : wrap them into another class? diff --git a/Engine/Source/Runtime/ECWorld/SkeletonComponent.cpp b/Engine/Source/Runtime/ECWorld/SkeletonComponent.cpp new file mode 100644 index 00000000..9bcab835 --- /dev/null +++ b/Engine/Source/Runtime/ECWorld/SkeletonComponent.cpp @@ -0,0 +1,54 @@ +#include "SkeletonComponent.h" +#include "Rendering/Resources/SkeletonResource.h" + +namespace engine +{ + +namespace details +{ + +} + +void SkeletonComponent::Reset() +{ + +} + +void SkeletonComponent::Build() +{ + +} + +void SkeletonComponent::SetSkeletonAsset(const SkeletonResource* pSkeletonResource) +{ + int boneCount = pSkeletonResource->GetBoneCount(); + m_pSkeletonResource = pSkeletonResource; + m_boneIBH = m_pSkeletonResource->GetIndexBufferHandle(); + m_boneVBH = m_pSkeletonResource->GetVertexBufferHandle(); + m_boneGlobalMatrices.resize(boneCount); + m_boneMatrices.resize(boneCount); + for (int i = 0; i < boneCount; ++i) + { + m_boneGlobalMatrices[i] = cd::Matrix4x4::Identity(); + m_boneMatrices[i] = cd::Matrix4x4::Identity(); + } +} + +void SkeletonComponent::SetBoneMatricesSize(uint32_t boneCount) +{ + m_boneGlobalMatrices.resize(boneCount); + m_boneMatrices.resize(boneCount); + for (uint32_t i = 0; i < boneCount; ++i) + { + m_boneGlobalMatrices[i] = cd::Matrix4x4::Identity(); + m_boneMatrices[i] = cd::Matrix4x4::Identity(); + } +} + +void SkeletonComponent::SetBoneGlobalMatrix(uint32_t index, const cd::Matrix4x4& boneGlobalMatrix) +{ + m_boneGlobalMatrices[index] = boneGlobalMatrix; + m_boneIndex = index; +} + +} \ No newline at end of file diff --git a/Engine/Source/Runtime/ECWorld/SkeletonComponent.h b/Engine/Source/Runtime/ECWorld/SkeletonComponent.h new file mode 100644 index 00000000..e9d1357d --- /dev/null +++ b/Engine/Source/Runtime/ECWorld/SkeletonComponent.h @@ -0,0 +1,80 @@ +#pragma once + +#include "Core/StringCrc.h" +#include "ECWorld/Entity.h" +#include "Scene/Bone.h" +#include + +namespace cd +{ + +class Skeleton; + +} + +namespace engine +{ + +class SkeletonComponent final +{ +public: + static constexpr StringCrc GetClassName() + { + constexpr StringCrc className("SkeletonComponent"); + return className; + } + +public: + SkeletonComponent() = default; + SkeletonComponent(const SkeletonComponent&) = default; + SkeletonComponent& operator=(const SkeletonComponent&) = default; + SkeletonComponent(SkeletonComponent&&) = default; + SkeletonComponent& operator=(SkeletonComponent&&) = default; + ~SkeletonComponent() = default; + + const SkeletonResource* GetSkeletonResource() const { return m_pSkeletonResource; } + void SetSkeletonAsset(const SkeletonResource* pSkeletonResource); + + void SetBoneMatricesUniform(uint16_t uniform) { m_boneMatricesUniform = uniform; } + uint16_t GetBoneMatrixsUniform() const { return m_boneMatricesUniform; } + + void SetBoneVBH(uint16_t boneVBH) { m_boneVBH = boneVBH; } + uint16_t GetBoneVBH() const { return m_boneVBH; } + + void SetBoneIBH(uint16_t boneIBH) { m_boneIBH = boneIBH; } + uint16_t GetBoneIBH() const { return m_boneIBH; } + + void SetBoneMatricesSize(uint32_t boneCount); + void SetBoneGlobalMatrix(uint32_t index, const cd::Matrix4x4& boneChangeMatrix); + const cd::Matrix4x4& GetBoneGlobalMatrix(uint32_t index) { return m_boneGlobalMatrices[index]; } + const std::vector& GetBoneGlobalMatrices() const { return m_boneGlobalMatrices; } + + void SetBoneMatrix(uint32_t index, const cd::Matrix4x4& changeMatrix) { m_boneMatrices[index] = changeMatrix * m_boneMatrices[index]; } + const cd::Matrix4x4& GetBoneMatrix(uint32_t index) { return m_boneMatrices[index]; } + + cd::Matrix4x4& GetRootMatrix() { return m_curRootMatrix; } + void SetRootMatrix(const cd::Matrix4x4& rootMatrix) { m_curRootMatrix = rootMatrix; } + + const cd::AnimationID& GetAnimation(uint32_t index) { return m_animationID[index]; } + void AddAnimationID(uint32_t animationID) { m_animationID.push_back(animationID); } + + void Reset(); + void Build(); + +private: + //input + uint32_t m_boneIndex = engine::INVALID_ENTITY; + const SkeletonResource* m_pSkeletonResource = nullptr; + //output + uint16_t m_boneVBH = UINT16_MAX; + uint16_t m_boneIBH = UINT16_MAX; + uint16_t m_boneMatricesUniform; + + cd::Matrix4x4 m_curRootMatrix = cd::Matrix4x4::Identity(); + std::vector m_boneGlobalMatrices; + std::vector m_boneMatrices; + std::vector m_animationID; + +}; + +} \ No newline at end of file diff --git a/Engine/Source/Runtime/ECWorld/SkinMeshComponent.h b/Engine/Source/Runtime/ECWorld/SkinMeshComponent.h index 67e4f7ed..5200232b 100644 --- a/Engine/Source/Runtime/ECWorld/SkinMeshComponent.h +++ b/Engine/Source/Runtime/ECWorld/SkinMeshComponent.h @@ -31,18 +31,8 @@ class SkinMeshComponent final SkinMeshComponent& operator=(SkinMeshComponent&&) = default; ~SkinMeshComponent() = default; - uint16_t GetBonePositionBuffer() const { return m_boneVBH; } - uint16_t GetIndexBuffer() const { return m_boneIBH; } - void Reset(); void Build(); - -private: - //output - std::vector m_vertexBuffer; - std::vector m_indexBuffer; - uint16_t m_boneVBH = UINT16_MAX; - uint16_t m_boneIBH = UINT16_MAX; }; } \ No newline at end of file diff --git a/Engine/Source/Runtime/ECWorld/SkyComponent.h b/Engine/Source/Runtime/ECWorld/SkyComponent.h index 474e6c2a..c904d4c8 100644 --- a/Engine/Source/Runtime/ECWorld/SkyComponent.h +++ b/Engine/Source/Runtime/ECWorld/SkyComponent.h @@ -33,6 +33,10 @@ class SkyComponent final SkyType& GetSkyType() { return m_type; } const SkyType& GetSkyType() const { return m_type; } + void SetSkyboxStrength(float strength) { m_skyboxStrength = strength; } + float& GetSkyboxStrength() { return m_skyboxStrength; } + float GetSkyboxStrength() const { return m_skyboxStrength; } + void SetAtmophericScatteringEnable(bool state) { m_isAtmophericScatteringEnable = state; } bool& GetAtmophericScatteringEnable() { return m_isAtmophericScatteringEnable; } const bool& GetAtmophericScatteringEnable() const { return m_isAtmophericScatteringEnable; } @@ -75,6 +79,7 @@ class SkyComponent final private: SkyType m_type = SkyType::SkyBox; + float m_skyboxStrength = 0.5f; bool m_isAtmophericScatteringEnable = false; StringCrc m_ATMTransmittanceCrc; diff --git a/Engine/Source/Runtime/Material/ShaderSchema.cpp b/Engine/Source/Runtime/Material/ShaderSchema.cpp index 27c169e9..210e4053 100644 --- a/Engine/Source/Runtime/Material/ShaderSchema.cpp +++ b/Engine/Source/Runtime/Material/ShaderSchema.cpp @@ -1,6 +1,5 @@ #include "ShaderSchema.h" -#include "Base/Template.h" #include "Log/Log.h" #include @@ -10,29 +9,6 @@ namespace engine { -void ShaderSchema::SetShaderProgramName(std::string name) -{ - m_shaderProgramName = cd::MoveTemp(name); -} - -void ShaderSchema::AddFeatureSet(ShaderFeatureSet featureSet) -{ - for (const auto& existingFeatureSet : m_shaderFeatureSets) - { - for (const auto& newFeature : featureSet) - { - if (existingFeatureSet.find(newFeature) != existingFeatureSet.end()) - { - CD_ENGINE_WARN("Shader feature {0} repetitive, skip current feature set adding!", GetFeatureName(newFeature)); - return; - } - } - } - - m_isDirty = true; - m_shaderFeatureSets.insert(cd::MoveTemp(featureSet)); -} - void ShaderSchema::Build() { if (!m_isDirty) @@ -42,7 +18,6 @@ void ShaderSchema::Build() } CleanBuild(); - m_isDirty = false; for (const auto& featureSet : m_shaderFeatureSets) { @@ -76,8 +51,9 @@ void ShaderSchema::Build() } } - // Should ShaderSchema handle uber shader without shader feature? + // ShaderScheme also handles case without ShaderFeature. m_allFeatureCombines.insert(""); + m_isDirty = false; } void ShaderSchema::CleanBuild() @@ -94,7 +70,26 @@ void ShaderSchema::CleanAll() m_shaderFeatureSets.clear(); } -const ShaderFeatureSet ShaderSchema::GetConflictFeatureSet(const ShaderFeature feature) const +void ShaderSchema::AddFeatureSet(ShaderFeatureSet featureSet) +{ + // We trate shader features as set to handel mutually exclusive keywords. + for (const auto& existingFeatureSet : m_shaderFeatureSets) + { + for (const auto& newFeature : featureSet) + { + if (existingFeatureSet.find(newFeature) != existingFeatureSet.end()) + { + CD_ENGINE_WARN("Shader feature {0} repetitive, skip current feature set adding!", GetFeatureName(newFeature)); + return; + } + } + } + + m_isDirty = true; + m_shaderFeatureSets.insert(cd::MoveTemp(featureSet)); +} + +std::optional ShaderSchema::GetConflictFeatureSet(const ShaderFeature feature) const { for (const auto& shaderFeatureSet : m_shaderFeatureSets) { @@ -104,7 +99,7 @@ const ShaderFeatureSet ShaderSchema::GetConflictFeatureSet(const ShaderFeature f } } - return ShaderFeatureSet{}; + return std::nullopt; } std::string ShaderSchema::GetFeaturesCombine(const ShaderFeatureSet& featureSet) const @@ -115,30 +110,34 @@ std::string ShaderSchema::GetFeaturesCombine(const ShaderFeatureSet& featureSet) } std::stringstream ss; - // Use the option order in m_shaderFeatureSets to ensure that inputs in different orders can get a same StringCrc. + // Use the Shader Feature order in m_shaderFeatureSets to ensure that inputs in different orders can get a same StringCrc. for (const auto& registeredSet : m_shaderFeatureSets) { - // Ignore option which contain in parameter but not contain in m_shaderFeatureSets. + // Ignore Shader Feature which contain in parameter but not contain in m_shaderFeatureSets. for (const auto& registeredFeature : registeredSet) { if (featureSet.find(registeredFeature) != featureSet.end()) { + // We assume that theres no conflicting Features in the incoming featureSet parameter. ss << GetFeatureName(registeredFeature); + continue; } } - } + return ss.str(); } -StringCrc ShaderSchema::GetFeaturesCombineCrc(const ShaderFeatureSet& featureSet) const +std::set& ShaderSchema::GetAllFeatureCombines() { - if (m_shaderFeatureSets.empty() || featureSet.empty()) - { - return DefaultUberShaderCrc; - } + assert(!m_isDirty); + return m_allFeatureCombines; +} - return StringCrc(GetFeaturesCombine(featureSet)); +const std::set& ShaderSchema::GetAllFeatureCombines() const +{ + assert(!m_isDirty); + return m_allFeatureCombines; } } \ No newline at end of file diff --git a/Engine/Source/Runtime/Material/ShaderSchema.h b/Engine/Source/Runtime/Material/ShaderSchema.h index d714778e..fc85d1e5 100644 --- a/Engine/Source/Runtime/Material/ShaderSchema.h +++ b/Engine/Source/Runtime/Material/ShaderSchema.h @@ -1,6 +1,7 @@ #pragma once #include "Core/StringCrc.h" +#include "Base/Template.h" #include "Rendering/ShaderFeature.h" #include @@ -40,32 +41,29 @@ class ShaderSchema ShaderSchema& operator=(ShaderSchema&&) = default; ~ShaderSchema() = default; - void SetShaderProgramName(std::string name); + void SetShaderProgramName(std::string name) { m_shaderProgramName = cd::MoveTemp(name); } std::string& GetShaderProgramName() { return m_shaderProgramName; } const std::string& GetShaderProgramName() const { return m_shaderProgramName; } - void AddFeatureSet(ShaderFeatureSet featureSet); - void Build(); void CleanBuild(); void CleanAll(); - const ShaderFeatureSet GetConflictFeatureSet(const ShaderFeature feature) const; - + void AddFeatureSet(ShaderFeatureSet featureSet); + std::optional GetConflictFeatureSet(const ShaderFeature feature) const; std::string GetFeaturesCombine(const ShaderFeatureSet& featureSet) const; - StringCrc GetFeaturesCombineCrc(const ShaderFeatureSet& featureSet) const; - std::set& GetFeatures() { return m_shaderFeatureSets; } - const std::set& GetFeatures() const { return m_shaderFeatureSets; } + std::set& GetFeatureSets() { return m_shaderFeatureSets; } + const std::set& GetFeatureSets() const { return m_shaderFeatureSets; } - std::set& GetAllFeatureCombines() { return m_allFeatureCombines; } - const std::set& GetAllFeatureCombines() const { return m_allFeatureCombines; } + std::set& GetAllFeatureCombines(); + const std::set& GetAllFeatureCombines() const; private: std::string m_shaderProgramName; bool m_isDirty = false; - // Registration order of shader features. + // Registration order of shader feature sets. std::set m_shaderFeatureSets; // All permutations matching the registered shader features. std::set m_allFeatureCombines; diff --git a/Engine/Source/Runtime/Rendering/AABBRenderer.cpp b/Engine/Source/Runtime/Rendering/AABBRenderer.cpp index 69ad57b8..13ac9803 100644 --- a/Engine/Source/Runtime/Rendering/AABBRenderer.cpp +++ b/Engine/Source/Runtime/Rendering/AABBRenderer.cpp @@ -5,6 +5,7 @@ #include "ECWorld/StaticMeshComponent.h" #include "ECWorld/TransformComponent.h" #include "Rendering/RenderContext.h" +#include "Rendering/Resources/ShaderResource.h" #include "Scene/Texture.h" namespace engine @@ -12,17 +13,11 @@ namespace engine void AABBRenderer::Init() { - constexpr StringCrc programCrc = StringCrc("AABBProgram"); - GetRenderContext()->RegisterShaderProgram(programCrc, { "vs_AABB", "fs_AABB" }); + AddDependentShaderResource(GetRenderContext()->RegisterShaderProgram("AABBProgram", "vs_AABB", "fs_AABB")); bgfx::setViewName(GetViewID(), "AABBRenderer"); } -void AABBRenderer::Warmup() -{ - GetRenderContext()->UploadShaderProgram("AABBProgram"); -} - void AABBRenderer::UpdateView(const float* pViewMatrix, const float* pProjectionMatrix) { UpdateViewRenderTarget(); @@ -31,6 +26,15 @@ void AABBRenderer::UpdateView(const float* pViewMatrix, const float* pProjection void AABBRenderer::Render(float deltaTime) { + for (const auto pResource : m_dependentShaderResources) + { + if (ResourceStatus::Ready != pResource->GetStatus() && + ResourceStatus::Optimized != pResource->GetStatus()) + { + return; + } + } + for (Entity entity : m_pCurrentSceneWorld->GetCollisionMeshEntities()) { auto* pCollisionMesh = m_pCurrentSceneWorld->GetCollisionMeshComponent(entity); @@ -52,7 +56,8 @@ void AABBRenderer::Render(float deltaTime) BGFX_STATE_BLEND_FUNC(BGFX_STATE_BLEND_SRC_ALPHA, BGFX_STATE_BLEND_INV_SRC_ALPHA) | BGFX_STATE_PT_LINES; bgfx::setState(state); - GetRenderContext()->Submit(GetViewID(), "AABBProgram"); + constexpr StringCrc programHandleIndex{ "AABBProgram" }; + GetRenderContext()->Submit(GetViewID(), programHandleIndex); } } diff --git a/Engine/Source/Runtime/Rendering/AABBRenderer.h b/Engine/Source/Runtime/Rendering/AABBRenderer.h index b707a658..32145ce5 100644 --- a/Engine/Source/Runtime/Rendering/AABBRenderer.h +++ b/Engine/Source/Runtime/Rendering/AABBRenderer.h @@ -15,7 +15,6 @@ class AABBRenderer final : public Renderer using Renderer::Renderer; virtual void Init() override; - virtual void Warmup() override; virtual void UpdateView(const float* pViewMatrix, const float* pProjectionMatrix) override; virtual void Render(float deltaTime) override; diff --git a/Engine/Source/Runtime/Rendering/AnimationRenderer.cpp b/Engine/Source/Runtime/Rendering/AnimationRenderer.cpp index 8e805724..d1a91488 100644 --- a/Engine/Source/Runtime/Rendering/AnimationRenderer.cpp +++ b/Engine/Source/Runtime/Rendering/AnimationRenderer.cpp @@ -5,14 +5,23 @@ #include "ECWorld/StaticMeshComponent.h" #include "ECWorld/TransformComponent.h" #include "Rendering/RenderContext.h" +#include "Rendering/Resources/MeshResource.h" +#include "Rendering/Resources/ShaderResource.h" #include "Scene/Texture.h" #include -//#include +//#define VISUALIZE_BONE_WEIGHTS namespace engine { +namespace +{ + +constexpr const char* debugBoneIndex = "u_debugBoneIndex"; + +} + namespace details { @@ -136,13 +145,9 @@ void CalculateBoneTransform(std::vector& boneMatrices, const cd:: void AnimationRenderer::Init() { bgfx::setViewName(GetViewID(), "AnimationRenderer"); -} -void AnimationRenderer::Warmup() -{ #ifdef VISUALIZE_BONE_WEIGHTS - m_pRenderContext->CreateUniform("u_debugBoneIndex", bgfx::UniformType::Vec4, 1); - m_pRenderContext->CreateProgram("AnimationProgram", "vs_visualize_bone_weight", "fs_visualize_bone_weight"); + GetRenderContext()->CreateUniform(debugBoneIndex, bgfx::UniformType::Vec4, 1); #endif } @@ -169,15 +174,15 @@ void AnimationRenderer::Render(float deltaTime) passedTime -= changeTime; } - constexpr StringCrc boneIndexUniform("u_debugBoneIndex"); - bgfx::setUniform(m_pRenderContext->GetUniform(boneIndexUniform), selectedBoneIndex, 1); + constexpr StringCrc boneIndexCrc(debugBoneIndex); + GetRenderContext()->FillUniform(boneIndexCrc, selectedBoneIndex, 1); #endif static float animationRunningTime = 0.0f; animationRunningTime += deltaTime; const cd::SceneDatabase* pSceneDatabase = m_pCurrentSceneWorld->GetSceneDatabase(); - for (Entity entity : m_pCurrentSceneWorld->GetAnimationEntities()) + for (Entity entity : m_pCurrentSceneWorld->GetStaticMeshEntities()) { StaticMeshComponent* pMeshComponent = m_pCurrentSceneWorld->GetStaticMeshComponent(entity); if (!pMeshComponent) @@ -187,38 +192,25 @@ void AnimationRenderer::Render(float deltaTime) MaterialComponent* pMaterialComponent = m_pCurrentSceneWorld->GetMaterialComponent(entity); if (!pMaterialComponent || - pMaterialComponent->GetMaterialType() != m_pCurrentSceneWorld->GetAnimationMaterialType() || - !GetRenderContext()->IsShaderProgramValid(pMaterialComponent->GetShaderProgramName(), pMaterialComponent->GetFeaturesCombine())) + pMaterialComponent->GetMaterialType() != m_pCurrentSceneWorld->GetAnimationMaterialType()) { continue; } - TransformComponent* pTransformComponent = m_pCurrentSceneWorld->GetTransformComponent(entity); - bgfx::setTransform(pTransformComponent->GetWorldMatrix().begin()); - - AnimationComponent* pAnimationComponent = m_pCurrentSceneWorld->GetAnimationComponent(entity); - - const cd::Animation* pAnimation = pAnimationComponent->GetAnimationData(); - float ticksPerSecond = pAnimation->GetTicksPerSecond(); - assert(ticksPerSecond > 1.0f); - float animationTime = details::CustomFModf(animationRunningTime * ticksPerSecond, pAnimation->GetDuration()); - - static std::vector boneMatrices; - boneMatrices.clear(); - for (uint16_t boneIndex = 0; boneIndex < 128; ++boneIndex) + const ShaderResource* pShaderResource = pMaterialComponent->GetShaderResource(); + if (ResourceStatus::Ready != pShaderResource->GetStatus() && + ResourceStatus::Optimized != pShaderResource->GetStatus()) { - boneMatrices.push_back(cd::Matrix4x4::Identity()); + continue; } - const cd::Bone& rootBone = pSceneDatabase->GetBone(0); - details::CalculateBoneTransform(boneMatrices, pSceneDatabase, animationTime, rootBone, - cd::Matrix4x4::Identity(), pTransformComponent->GetWorldMatrix().Inverse()); - bgfx::setUniform(bgfx::UniformHandle{pAnimationComponent->GetBoneMatrixsUniform()}, boneMatrices.data(), static_cast(boneMatrices.size())); + TransformComponent* pTransformComponent = m_pCurrentSceneWorld->GetTransformComponent(entity); + bgfx::setTransform(pTransformComponent->GetWorldMatrix().begin()); constexpr uint64_t state = BGFX_STATE_WRITE_MASK | BGFX_STATE_CULL_CCW | BGFX_STATE_MSAA | BGFX_STATE_DEPTH_TEST_LESS; bgfx::setState(state); - GetRenderContext()->Submit(GetViewID(), pMaterialComponent->GetShaderProgramName()); + GetRenderContext()->Submit(GetViewID(), pShaderResource->GetHandle()); } } diff --git a/Engine/Source/Runtime/Rendering/AnimationRenderer.h b/Engine/Source/Runtime/Rendering/AnimationRenderer.h index aeb18f4f..694c6827 100644 --- a/Engine/Source/Runtime/Rendering/AnimationRenderer.h +++ b/Engine/Source/Runtime/Rendering/AnimationRenderer.h @@ -15,7 +15,6 @@ class AnimationRenderer final : public Renderer using Renderer::Renderer; virtual void Init() override; - virtual void Warmup() override; virtual void UpdateView(const float* pViewMatrix, const float* pProjectionMatrix) override; virtual void Render(float deltaTime) override; diff --git a/Engine/Source/Runtime/Rendering/BlendShapeRenderer.cpp b/Engine/Source/Runtime/Rendering/BlendShapeRenderer.cpp index 659b0c23..2ade8034 100644 --- a/Engine/Source/Runtime/Rendering/BlendShapeRenderer.cpp +++ b/Engine/Source/Runtime/Rendering/BlendShapeRenderer.cpp @@ -11,10 +11,11 @@ #include "Material/ShaderSchema.h" #include "Math/Transform.hpp" #include "RenderContext.h" +#include "Rendering/Resources/ShaderResource.h" #include "Scene/Texture.h" -#include "U_IBL.sh" #include "U_AtmophericScattering.sh" #include "U_BlendShape.sh" +#include "U_IBL.sh" namespace engine { @@ -30,32 +31,24 @@ constexpr const char *BlendShapeWeightPosProgram = "BlendShapeWeightPosProgram"; constexpr const char *BlendShapeFinalPosProgram = "BlendShapeFinalPosProgram"; constexpr const char *BlendShapeUpdatePosProgram = "BlendShapeUpdatePosProgram"; -constexpr StringCrc BlendShapeWeightsProgramCrc = StringCrc("BlendShapeWeightsProgram"); -constexpr StringCrc BlendShapeWeightPosProgramCrc = StringCrc("BlendShapeWeightPosProgram"); -constexpr StringCrc BlendShapeFinalPosProgramCrc = StringCrc("BlendShapeFinalPosProgram"); -constexpr StringCrc BlendShapeUpdatePosProgramCrc = StringCrc("BlendShapeUpdatePosProgram"); +constexpr StringCrc BlendShapeWeightsProgramCrc{ BlendShapeWeightsProgram }; +constexpr StringCrc BlendShapeWeightPosProgramCrc{ BlendShapeWeightPosProgram }; +constexpr StringCrc BlendShapeFinalPosProgramCrc{ BlendShapeFinalPosProgram }; +constexpr StringCrc BlendShapeUpdatePosProgramCrc{ BlendShapeUpdatePosProgram }; } void BlendShapeRenderer::Init() { - GetRenderContext()->RegisterShaderProgram(BlendShapeWeightsProgramCrc, { "cs_blendshape_weights" }); - GetRenderContext()->RegisterShaderProgram(BlendShapeWeightPosProgramCrc, { "cs_blendshape_weight_pos" }); - GetRenderContext()->RegisterShaderProgram(BlendShapeFinalPosProgramCrc, { "cs_blendshape_final_pos" }); - GetRenderContext()->RegisterShaderProgram(BlendShapeUpdatePosProgramCrc, { "cs_blendshape_update_pos" }); - - bgfx::setViewName(GetViewID(), "BlendShapeRenderer"); -} + AddDependentShaderResource(GetRenderContext()->RegisterShaderProgram("BlendShapeWeightsProgram", "cs_blendshape_weights", ShaderProgramType::Compute)); + AddDependentShaderResource(GetRenderContext()->RegisterShaderProgram("BlendShapeWeightPosProgram", "cs_blendshape_weight_pos", ShaderProgramType::Compute)); + AddDependentShaderResource(GetRenderContext()->RegisterShaderProgram("BlendShapeFinalPosProgram", "cs_blendshape_final_pos", ShaderProgramType::Compute)); + AddDependentShaderResource(GetRenderContext()->RegisterShaderProgram("BlendShapeUpdatePosProgram", "cs_blendshape_update_pos", ShaderProgramType::Compute)); -void BlendShapeRenderer::Warmup() -{ GetRenderContext()->CreateUniform(morphCountVertexCount, bgfx::UniformType::Vec4, 1); GetRenderContext()->CreateUniform(changedWeight, bgfx::UniformType::Vec4, 1); - GetRenderContext()->UploadShaderProgram(BlendShapeWeightsProgram); - GetRenderContext()->UploadShaderProgram(BlendShapeWeightPosProgram); - GetRenderContext()->UploadShaderProgram(BlendShapeFinalPosProgram); - GetRenderContext()->UploadShaderProgram(BlendShapeUpdatePosProgram); + bgfx::setViewName(GetViewID(), "BlendShapeRenderer"); } void BlendShapeRenderer::UpdateView(const float* pViewMatrix, const float* pProjectionMatrix) @@ -66,6 +59,15 @@ void BlendShapeRenderer::UpdateView(const float* pViewMatrix, const float* pProj void BlendShapeRenderer::Render(float deltaTime) { + for (const auto pResource : m_dependentShaderResources) + { + if (ResourceStatus::Ready != pResource->GetStatus() && + ResourceStatus::Optimized != pResource->GetStatus()) + { + return; + } + } + for (Entity entity : m_pCurrentSceneWorld->GetBlendShapeEntities()) { // No blend shape? @@ -86,18 +88,18 @@ void BlendShapeRenderer::Render(float deltaTime) constexpr StringCrc morphCountVertexCountCrc(morphCountVertexCount); cd::Vec4f morphCount{ static_cast(pBlendShapeComponent->GetActiveMorphCount()), static_cast(pBlendShapeComponent->GetMeshVertexCount()), 0, 0}; GetRenderContext()->FillUniform(morphCountVertexCountCrc, &morphCount, 1); - GetRenderContext()->Dispatch(viewId, BlendShapeWeightsProgram, 1U, 1U, 1U); + GetRenderContext()->Dispatch(viewId, BlendShapeWeightsProgramCrc, 1U, 1U, 1U); bgfx::setBuffer(BS_MORPH_AFFECTED_STAGE, bgfx::VertexBufferHandle{pBlendShapeComponent->GetMorphAffectedVB()}, bgfx::Access::Read); bgfx::setBuffer(BS_FINAL_MORPH_AFFECTED_STAGE, bgfx::DynamicVertexBufferHandle{pBlendShapeComponent->GetFinalMorphAffectedVB()}, bgfx::Access::ReadWrite); GetRenderContext()->FillUniform(morphCountVertexCountCrc, &morphCount, 1); - GetRenderContext()->Dispatch(viewId, BlendShapeWeightPosProgram, 1U, 1U, 1U); + GetRenderContext()->Dispatch(viewId, BlendShapeWeightPosProgramCrc, 1U, 1U, 1U); bgfx::setBuffer(BS_FINAL_MORPH_AFFECTED_STAGE, bgfx::DynamicVertexBufferHandle{pBlendShapeComponent->GetFinalMorphAffectedVB()}, bgfx::Access::ReadWrite); bgfx::setBuffer(BS_ALL_MORPH_VERTEX_ID_STAGE, bgfx::IndexBufferHandle{pBlendShapeComponent->GetAllMorphVertexIDIB()}, bgfx::Access::Read); bgfx::setBuffer(BS_ACTIVE_MORPH_DATA_STAGE, bgfx::DynamicIndexBufferHandle{pBlendShapeComponent->GetActiveMorphOffestLengthWeightIB()}, bgfx::Access::Read); GetRenderContext()->FillUniform(morphCountVertexCountCrc, &morphCount, 1); - GetRenderContext()->Dispatch(viewId, BlendShapeFinalPosProgram, 1U, 1U, 1U); + GetRenderContext()->Dispatch(viewId, BlendShapeFinalPosProgramCrc, 1U, 1U, 1U); pBlendShapeComponent->SetDirty(false); } @@ -113,7 +115,7 @@ void BlendShapeRenderer::Render(float deltaTime) //constexpr StringCrc changedWeightCrc(changedWeight); //cd::Vec4f changedWeightData = cd::Vec4f{ static_cast(pBlendShapeComponent->GetUpdatedWeight()),0,0,0 }; //GetRenderContext()->FillUniform(changedWeightCrc, &changedWeightData, 1); - GetRenderContext()->Dispatch(viewId, BlendShapeUpdatePosProgram, 1U, 1U, 1U); + GetRenderContext()->Dispatch(viewId, BlendShapeUpdatePosProgramCrc, 1U, 1U, 1U); pBlendShapeComponent->ClearNeedUpdate(); } diff --git a/Engine/Source/Runtime/Rendering/BlendShapeRenderer.h b/Engine/Source/Runtime/Rendering/BlendShapeRenderer.h index ec748963..3b7a258a 100644 --- a/Engine/Source/Runtime/Rendering/BlendShapeRenderer.h +++ b/Engine/Source/Runtime/Rendering/BlendShapeRenderer.h @@ -13,7 +13,6 @@ class BlendShapeRenderer final : public Renderer using Renderer::Renderer; virtual void Init() override; - virtual void Warmup() override; virtual void UpdateView(const float* pViewMatrix, const float* pProjectionMatrix) override; virtual void Render(float deltaTime) override; diff --git a/Engine/Source/Runtime/Rendering/BlitRenderTargetPass.cpp b/Engine/Source/Runtime/Rendering/BlitRenderTargetPass.cpp index 18d255a2..12ebbbdb 100644 --- a/Engine/Source/Runtime/Rendering/BlitRenderTargetPass.cpp +++ b/Engine/Source/Runtime/Rendering/BlitRenderTargetPass.cpp @@ -14,10 +14,6 @@ BlitRenderTargetPass::~BlitRenderTargetPass() { } -void BlitRenderTargetPass::Warmup() -{ -} - void BlitRenderTargetPass::UpdateView(const float* pViewMatrix, const float* pProjectionMatrix) { } diff --git a/Engine/Source/Runtime/Rendering/BlitRenderTargetPass.h b/Engine/Source/Runtime/Rendering/BlitRenderTargetPass.h index 410ddd58..e74c4868 100644 --- a/Engine/Source/Runtime/Rendering/BlitRenderTargetPass.h +++ b/Engine/Source/Runtime/Rendering/BlitRenderTargetPass.h @@ -12,7 +12,6 @@ class BlitRenderTargetPass final : public Renderer virtual ~BlitRenderTargetPass(); virtual void Init() override; - virtual void Warmup() override; virtual void UpdateView(const float* pViewMatrix, const float* pProjectionMatrix) override; virtual void Render(float deltaTime) override; diff --git a/Engine/Source/Runtime/Rendering/BloomRenderer.cpp b/Engine/Source/Runtime/Rendering/BloomRenderer.cpp index 7a3e1b5c..1006fd11 100644 --- a/Engine/Source/Runtime/Rendering/BloomRenderer.cpp +++ b/Engine/Source/Runtime/Rendering/BloomRenderer.cpp @@ -1,29 +1,50 @@ #include "BloomRenderer.h" #include "Rendering/RenderContext.h" +#include "Rendering/Resources/ShaderResource.h" #include namespace engine { +namespace +{ + +constexpr const char* CapTureBrightnessProgram = "CapTureBrightnessProgram"; +constexpr const char* DownSampleProgram = "DownSampleProgram"; +constexpr const char* BlurVerticalProgram = "BlurVerticalProgram"; +constexpr const char* BlurHorizontalProgram = "BlurHorizontalProgram"; +constexpr const char* UpSampleProgram = "UpSampleProgram"; +constexpr const char* KawaseBlurProgram = "KawaseBlurProgram"; +constexpr const char* CombineProgram = "CombineProgram"; + +constexpr StringCrc CapTureBrightnessProgramCrc{ CapTureBrightnessProgram }; +constexpr StringCrc DownSampleProgramCrc{ DownSampleProgram }; +constexpr StringCrc BlurVerticalProgramCrc{ BlurVerticalProgram }; +constexpr StringCrc BlurHorizontalProgramCrc{ BlurHorizontalProgram }; +constexpr StringCrc UpSampleProgramCrc{ UpSampleProgram }; +constexpr StringCrc KawaseBlurProgramCrc{ KawaseBlurProgram }; +constexpr StringCrc CombineProgramCrc{ CombineProgram }; + +} + void BloomRenderer::Init() { - constexpr StringCrc CapTureBrightnessProgramCrc = StringCrc("CapTureBrightnessProgram"); - constexpr StringCrc DownSampleProgramCrc = StringCrc("DownSampleProgram"); - constexpr StringCrc BlurVerticalProgramCrc = StringCrc("BlurVerticalProgram"); - constexpr StringCrc BlurHorizontalProgramCrc = StringCrc("BlurHorizontalProgram"); - constexpr StringCrc UpSampleProgramCrc = StringCrc("UpSampleProgram"); - constexpr StringCrc KawaseBlurProgramCrc = StringCrc("KawaseBlurProgram"); - constexpr StringCrc CombineProgramCrc = StringCrc("CombineProgram"); - - GetRenderContext()->RegisterShaderProgram(CapTureBrightnessProgramCrc, { "vs_fullscreen", "fs_captureBrightness" }); - GetRenderContext()->RegisterShaderProgram(DownSampleProgramCrc, { "vs_fullscreen", "fs_dowmsample" }); - GetRenderContext()->RegisterShaderProgram(BlurVerticalProgramCrc, { "vs_fullscreen", "fs_blurvertical" }); - GetRenderContext()->RegisterShaderProgram(BlurHorizontalProgramCrc, { "vs_fullscreen", "fs_blurhorizontal" }); - GetRenderContext()->RegisterShaderProgram(UpSampleProgramCrc, { "vs_fullscreen", "fs_upsample" }); - GetRenderContext()->RegisterShaderProgram(KawaseBlurProgramCrc, { "vs_fullscreen", "fs_kawaseblur" }); - GetRenderContext()->RegisterShaderProgram(CombineProgramCrc, { "vs_fullscreen", "fs_bloom" }); + AddDependentShaderResource(GetRenderContext()->RegisterShaderProgram(CapTureBrightnessProgram, "vs_fullscreen", "fs_captureBrightness")); + AddDependentShaderResource(GetRenderContext()->RegisterShaderProgram(DownSampleProgram, "vs_fullscreen", "fs_dowmsample")); + AddDependentShaderResource(GetRenderContext()->RegisterShaderProgram(BlurVerticalProgram, "vs_fullscreen", "fs_blurvertical")); + AddDependentShaderResource(GetRenderContext()->RegisterShaderProgram(BlurHorizontalProgram, "vs_fullscreen", "fs_blurhorizontal")); + AddDependentShaderResource(GetRenderContext()->RegisterShaderProgram(UpSampleProgram, "vs_fullscreen", "fs_upsample")); + AddDependentShaderResource(GetRenderContext()->RegisterShaderProgram(KawaseBlurProgram, "vs_fullscreen", "fs_kawaseblur")); + AddDependentShaderResource(GetRenderContext()->RegisterShaderProgram(CombineProgram, "vs_fullscreen", "fs_bloom")); + + GetRenderContext()->CreateUniform("s_texture", bgfx::UniformType::Sampler); + GetRenderContext()->CreateUniform("s_bloom", bgfx::UniformType::Sampler); + GetRenderContext()->CreateUniform("s_lightingColor", bgfx::UniformType::Sampler); + GetRenderContext()->CreateUniform("u_textureSize", bgfx::UniformType::Vec4); + GetRenderContext()->CreateUniform("u_bloomIntensity", bgfx::UniformType::Vec4); + GetRenderContext()->CreateUniform("u_luminanceThreshold", bgfx::UniformType::Vec4); bgfx::setViewName(GetViewID(), "BloomRenderer"); @@ -68,24 +89,6 @@ void BloomRenderer::AllocateViewIDs() m_blitColorPassID = GetRenderContext()->CreateView(); } -void BloomRenderer::Warmup() -{ - GetRenderContext()->CreateUniform("s_texture", bgfx::UniformType::Sampler); - GetRenderContext()->CreateUniform("s_bloom", bgfx::UniformType::Sampler); - GetRenderContext()->CreateUniform("s_lightingColor", bgfx::UniformType::Sampler); - GetRenderContext()->CreateUniform("u_textureSize", bgfx::UniformType::Vec4); - GetRenderContext()->CreateUniform("u_bloomIntensity", bgfx::UniformType::Vec4); - GetRenderContext()->CreateUniform("u_luminanceThreshold", bgfx::UniformType::Vec4); - - GetRenderContext()->UploadShaderProgram("CapTureBrightnessProgram"); - GetRenderContext()->UploadShaderProgram("DownSampleProgram"); - GetRenderContext()->UploadShaderProgram("BlurVerticalProgram"); - GetRenderContext()->UploadShaderProgram("BlurHorizontalProgram"); - GetRenderContext()->UploadShaderProgram("UpSampleProgram"); - GetRenderContext()->UploadShaderProgram("KawaseBlurProgram"); - GetRenderContext()->UploadShaderProgram("CombineProgram"); -} - void BloomRenderer::SetEnable(bool value) { Entity entity = m_pCurrentSceneWorld->GetMainCameraEntity(); @@ -148,6 +151,15 @@ void BloomRenderer::UpdateView(const float* pViewMatrix, const float* pProjectio void BloomRenderer::Render(float deltaTime) { + for (const auto pResource : m_dependentShaderResources) + { + if (ResourceStatus::Ready != pResource->GetStatus() && + ResourceStatus::Optimized != pResource->GetStatus()) + { + return; + } + } + constexpr StringCrc sceneRenderTarget("SceneRenderTarget"); const RenderTarget* pInputRT = GetRenderContext()->GetRenderTarget(sceneRenderTarget); @@ -188,7 +200,7 @@ void BloomRenderer::Render(float deltaTime) bgfx::setState(BGFX_STATE_WRITE_RGB | BGFX_STATE_WRITE_A); Renderer::ScreenSpaceQuad(GetRenderTarget(), false); - GetRenderContext()->Submit(GetViewID(), "CapTureBrightnessProgram"); + GetRenderContext()->Submit(GetViewID(), CapTureBrightnessProgramCrc); // downsample int sampleTimes = std::min(pCameraComponent->GetBloomDownSampleTimes(), pCameraComponent->GetBloomDownSampleMaxTimes()); @@ -218,7 +230,7 @@ void BloomRenderer::Render(float deltaTime) bgfx::setState(BGFX_STATE_WRITE_RGB | BGFX_STATE_WRITE_A); Renderer::ScreenSpaceQuad(GetRenderTarget(), false); - GetRenderContext()->Submit(m_startDowmSamplePassID + sampleIndex, "DownSampleProgram"); + GetRenderContext()->Submit(m_startDowmSamplePassID + sampleIndex, DownSampleProgramCrc); } if (pCameraComponent->GetIsBlurEnable() && pCameraComponent->GetBlurTimes() != 0) @@ -261,7 +273,7 @@ void BloomRenderer::Render(float deltaTime) bgfx::setState(BGFX_STATE_WRITE_RGB | BGFX_STATE_WRITE_A | BGFX_STATE_BLEND_ADD); Renderer::ScreenSpaceQuad(GetRenderTarget(), false); - GetRenderContext()->Submit(m_startUpSamplePassID + sampleIndex, "UpSampleProgram"); + GetRenderContext()->Submit(m_startUpSamplePassID + sampleIndex, UpSampleProgramCrc); } // combine @@ -279,7 +291,7 @@ void BloomRenderer::Render(float deltaTime) bgfx::setState(BGFX_STATE_WRITE_RGB | BGFX_STATE_WRITE_A); Renderer::ScreenSpaceQuad(GetRenderTarget(), false); - GetRenderContext()->Submit(m_combinePassID, "CombineProgram"); + GetRenderContext()->Submit(m_combinePassID, CombineProgramCrc); bgfx::blit(m_blitColorPassID, screenTextureHandle, 0, 0, bgfx::getTexture(m_combineFB)); } @@ -322,7 +334,7 @@ void BloomRenderer::Blur(uint16_t width, uint16_t height, int iteration, float b bgfx::setState(BGFX_STATE_WRITE_RGB | BGFX_STATE_WRITE_A); Renderer::ScreenSpaceQuad(GetRenderTarget(), false); - GetRenderContext()->Submit(verticalViewID, "KawaseBlurProgram"); + GetRenderContext()->Submit(verticalViewID, KawaseBlurProgramCrc); //constexpr StringCrc BlurHorizontalprogramName("BlurVerticalProgram"); // use Gaussian Blur //bgfx::submit(horizontal, GetRenderContext()->GetProgram(BlurHorizontalprogramName)); @@ -340,7 +352,7 @@ void BloomRenderer::Blur(uint16_t width, uint16_t height, int iteration, float b bgfx::setState(BGFX_STATE_WRITE_RGB | BGFX_STATE_WRITE_A); Renderer::ScreenSpaceQuad(GetRenderTarget(), false); - GetRenderContext()->Submit(horizontalViewID, "KawaseBlurProgram"); + GetRenderContext()->Submit(horizontalViewID, KawaseBlurProgramCrc); //constexpr StringCrc BlurVerticalprogramName("BlurVerticalProgram"); // use Gaussian Blur //bgfx::submit(horizontal, GetRenderContext()->GetProgram(BlurVerticalprogramName)); diff --git a/Engine/Source/Runtime/Rendering/BloomRenderer.h b/Engine/Source/Runtime/Rendering/BloomRenderer.h index 3988a1e4..04f3bb38 100644 --- a/Engine/Source/Runtime/Rendering/BloomRenderer.h +++ b/Engine/Source/Runtime/Rendering/BloomRenderer.h @@ -16,7 +16,6 @@ namespace engine using Renderer::Renderer; virtual void Init() override; - virtual void Warmup() override; virtual void UpdateView(const float* pViewMatrix, const float* pProjectionMatrix) override; virtual void Render(float deltaTime) override; diff --git a/Engine/Source/Runtime/Rendering/CelluloidRenderer.cpp b/Engine/Source/Runtime/Rendering/CelluloidRenderer.cpp new file mode 100644 index 00000000..5430a1bf --- /dev/null +++ b/Engine/Source/Runtime/Rendering/CelluloidRenderer.cpp @@ -0,0 +1,130 @@ +#include "CelluloidRenderer.h" + +#include "ECWorld/CameraComponent.h" +#include "ECWorld/MaterialComponent.h" +#include "ECWorld/SceneWorld.h" +#include "ECWorld/SkyComponent.h" +#include "ECWorld/StaticMeshComponent.h" +#include "ECWorld/TransformComponent.h" +#include "LightUniforms.h" +#include "Material/ShaderSchema.h" +#include "Math/Transform.hpp" +#include "Rendering/RenderContext.h" +#include "Rendering/Resources/MeshResource.h" +#include "Rendering/Resources/ShaderResource.h" +#include "Rendering/Resources/TextureResource.h" +#include "Scene/Texture.h" +#include "U_AtmophericScattering.sh" +#include "U_IBL.sh" + +namespace engine +{ + +namespace +{ + +constexpr const char* albedoUVOffsetAndScale = "u_albedoUVOffsetAndScale"; +constexpr const char* dividLine = "u_dividLine"; +constexpr const char* specular = "u_specular"; +constexpr const char* rimLight = "u_rimLight"; +constexpr const char* firstShadowColor = "u_firstShadowColor"; +constexpr const char* secondShadowColor = "u_secondShadowColor"; +constexpr const char* rimLightColor = "u_rimLightColor"; + +constexpr uint64_t samplerFlags = BGFX_SAMPLER_U_CLAMP | BGFX_SAMPLER_V_CLAMP | BGFX_SAMPLER_W_CLAMP; +constexpr uint64_t defaultRenderingState = BGFX_STATE_WRITE_MASK | BGFX_STATE_MSAA | BGFX_STATE_DEPTH_TEST_LESS; + +} + +void CelluloidRenderer::Init() +{ + GetRenderContext()->CreateUniform(dividLine, bgfx::UniformType::Vec4, 1); + GetRenderContext()->CreateUniform(specular, bgfx::UniformType::Vec4, 1); + GetRenderContext()->CreateUniform(firstShadowColor, bgfx::UniformType::Vec4, 1); + GetRenderContext()->CreateUniform(secondShadowColor, bgfx::UniformType::Vec4, 1); + GetRenderContext()->CreateUniform(rimLight, bgfx::UniformType::Vec4, 1); + GetRenderContext()->CreateUniform(rimLightColor, bgfx::UniformType::Vec4, 1); + GetRenderContext()->CreateUniform(albedoUVOffsetAndScale, bgfx::UniformType::Vec4, 1); + + bgfx::setViewName(GetViewID(), "CelluloidRenderer"); +} + +void CelluloidRenderer::UpdateView(const float* pViewMatrix, const float* pProjectionMatrix) +{ + UpdateViewRenderTarget(); + bgfx::setViewTransform(GetViewID(), pViewMatrix, pProjectionMatrix); +} + +void CelluloidRenderer::Render(float deltaTime) +{ + // TODO : Remove it. If every renderer need to submit camera related uniform, it should be done not inside Renderer class. + const cd::Transform& cameraTransform = m_pCurrentSceneWorld->GetTransformComponent(m_pCurrentSceneWorld->GetMainCameraEntity())->GetTransform(); + SkyComponent* pSkyComponent = m_pCurrentSceneWorld->GetSkyComponent(m_pCurrentSceneWorld->GetSkyEntity()); + + for (Entity entity : m_pCurrentSceneWorld->GetMaterialEntities()) + { + MaterialComponent* pMaterialComponent = m_pCurrentSceneWorld->GetMaterialComponent(entity); + if (!pMaterialComponent || pMaterialComponent->GetMaterialType() != m_pCurrentSceneWorld->GetCelluloidMaterialType()) + { + continue; + } + + const ShaderResource* pShaderResource = pMaterialComponent->GetShaderResource(); + if (ResourceStatus::Ready != pShaderResource->GetStatus() && + ResourceStatus::Optimized != pShaderResource->GetStatus()) + { + continue; + } + + bool textureSlotBindTable[32] = { false }; + for (const auto& [textureType, propertyGroup] : pMaterialComponent->GetPropertyGroups()) + { + const MaterialComponent::TextureInfo& textureInfo = propertyGroup.textureInfo; + if (textureSlotBindTable[textureInfo.slot]) + { + // already bind. + continue; + } + + TextureResource* pTextureResource = textureInfo.pTextureResource; + if (!propertyGroup.useTexture || + pTextureResource == nullptr || + (pTextureResource->GetStatus() != ResourceStatus::Ready && pTextureResource->GetStatus() != ResourceStatus::Optimized)) + { + continue; + } + + if (cd::MaterialTextureType::BaseColor == textureType) + { + constexpr StringCrc albedoUVOffsetAndScaleCrc(albedoUVOffsetAndScale); + cd::Vec4f uvOffsetAndScaleData(textureInfo.GetUVOffset().x(), textureInfo.GetUVOffset().y(), + textureInfo.GetUVScale().x(), textureInfo.GetUVScale().y()); + GetRenderContext()->FillUniform(albedoUVOffsetAndScaleCrc, &uvOffsetAndScaleData, 1); + } + + textureSlotBindTable[textureInfo.slot] = true; + bgfx::setTexture(textureInfo.slot, bgfx::UniformHandle{ pTextureResource->GetSamplerHandle() }, bgfx::TextureHandle{ pTextureResource->GetTextureHandle() }); + } + constexpr StringCrc dividLineCrc(dividLine); + GetRenderContext()->FillUniform(dividLineCrc, pMaterialComponent->GetToonParameters().dividLine.begin(), 1); + + constexpr StringCrc specularCrc(specular); + GetRenderContext()->FillUniform(specularCrc, pMaterialComponent->GetToonParameters().specular.begin(), 1); + + constexpr StringCrc firstShadowColorCrc(firstShadowColor); + GetRenderContext()->FillUniform(firstShadowColorCrc, pMaterialComponent->GetToonParameters().firstShadowColor.begin(), 1); + + constexpr StringCrc secondShadowColorCrc(secondShadowColor); + GetRenderContext()->FillUniform(secondShadowColorCrc, pMaterialComponent->GetToonParameters().secondShadowColor.begin(), 1); + + constexpr StringCrc rimLightColorCrc(rimLightColor); + GetRenderContext()->FillUniform(rimLightColorCrc, pMaterialComponent->GetToonParameters().rimLightColor.begin(), 1); + + constexpr StringCrc rimLightCrc(rimLight); + GetRenderContext()->FillUniform(rimLightCrc, pMaterialComponent->GetToonParameters().rimLight.begin(), 1); + + GetRenderContext()->Submit(GetViewID(), pShaderResource->GetHandle()); + } +} + +} \ No newline at end of file diff --git a/Engine/Source/Runtime/Rendering/CelluloidRenderer.h b/Engine/Source/Runtime/Rendering/CelluloidRenderer.h new file mode 100644 index 00000000..8dac3d87 --- /dev/null +++ b/Engine/Source/Runtime/Rendering/CelluloidRenderer.h @@ -0,0 +1,27 @@ +#pragma once + +#include "Renderer.h" + +#include + +namespace engine +{ + + class SceneWorld; + + class CelluloidRenderer final : public Renderer + { + public: + using Renderer::Renderer; + + virtual void Init() override; + virtual void UpdateView(const float* pViewMatrix, const float* pProjectionMatrix) override; + virtual void Render(float deltaTime) override; + + void SetSceneWorld(SceneWorld* pSceneWorld) { m_pCurrentSceneWorld = pSceneWorld; } + + private: + SceneWorld* m_pCurrentSceneWorld = nullptr; + }; + +} \ No newline at end of file diff --git a/Engine/Source/Runtime/Rendering/ImGuiRenderer.cpp b/Engine/Source/Runtime/Rendering/ImGuiRenderer.cpp index 5862a700..1804fe0d 100644 --- a/Engine/Source/Runtime/Rendering/ImGuiRenderer.cpp +++ b/Engine/Source/Runtime/Rendering/ImGuiRenderer.cpp @@ -2,6 +2,8 @@ #include "Core/StringCrc.h" #include "Rendering/RenderContext.h" +#include "Rendering/Resources/ResourceContext.h" +#include "Rendering/Resources/ShaderResource.h" #include @@ -10,14 +12,8 @@ namespace engine void ImGuiRenderer::Init() { - constexpr StringCrc programCrc = StringCrc("ImGuiProgram"); - GetRenderContext()->RegisterShaderProgram(programCrc, { "vs_imgui", "fs_imgui" }); + AddDependentShaderResource(GetRenderContext()->RegisterShaderProgram("ImGuiProgram", "vs_imgui", "fs_imgui")); - bgfx::setViewName(GetViewID(), "ImGuiRenderer"); -} - -void ImGuiRenderer::Warmup() -{ constexpr StringCrc imguiVertexLayoutName("imgui_vertex_layout"); if (0 == GetRenderContext()->GetVertexAttributeLayouts(imguiVertexLayoutName).m_stride) { @@ -31,7 +27,8 @@ void ImGuiRenderer::Warmup() } GetRenderContext()->CreateUniform("s_tex", bgfx::UniformType::Sampler); - GetRenderContext()->UploadShaderProgram("ImGuiProgram"); + + bgfx::setViewName(GetViewID(), "ImGuiRenderer"); } void ImGuiRenderer::UpdateView(const float* pViewMatrix, const float* pProjectionMatrix) @@ -79,6 +76,15 @@ void ImGuiRenderer::UpdateView(const float* pViewMatrix, const float* pProjectio void ImGuiRenderer::Render(float deltaTime) { + for (const auto pResource : m_dependentShaderResources) + { + if (ResourceStatus::Ready != pResource->GetStatus() && + ResourceStatus::Optimized != pResource->GetStatus()) + { + return; + } + } + ImDrawData* pImGuiDrawData = ImGui::GetDrawData(); int frameBufferWidth = static_cast(pImGuiDrawData->DisplaySize.x * pImGuiDrawData->FramebufferScale.x); @@ -172,7 +178,8 @@ void ImGuiRenderer::Render(float deltaTime) pEncoder->setVertexBuffer(0, &vertexBuffer, cmd->VtxOffset, numVertices); pEncoder->setIndexBuffer(&indexBuffer, cmd->IdxOffset, cmd->ElemCount); - pEncoder->submit(GetViewID(), GetRenderContext()->GetShaderProgramHandle("ImGuiProgram")); + constexpr StringCrc programHandleIndex{ "ImGuiProgram" }; + pEncoder->submit(GetViewID(), bgfx::ProgramHandle{ GetRenderContext()->GetResourceContext()->GetShaderResource(programHandleIndex)->GetHandle()}); } } } diff --git a/Engine/Source/Runtime/Rendering/ImGuiRenderer.h b/Engine/Source/Runtime/Rendering/ImGuiRenderer.h index 7ade340d..50443a13 100644 --- a/Engine/Source/Runtime/Rendering/ImGuiRenderer.h +++ b/Engine/Source/Runtime/Rendering/ImGuiRenderer.h @@ -11,7 +11,6 @@ class ImGuiRenderer final : public engine::Renderer using Renderer::Renderer; virtual void Init() override; - virtual void Warmup() override; virtual void UpdateView(const float* pViewMatrix, const float* pProjectionMatrix) override; virtual void Render(float deltaTime) override; }; diff --git a/Engine/Source/Runtime/Rendering/OutLineRenderer.cpp b/Engine/Source/Runtime/Rendering/OutLineRenderer.cpp new file mode 100644 index 00000000..fd7b1ffa --- /dev/null +++ b/Engine/Source/Runtime/Rendering/OutLineRenderer.cpp @@ -0,0 +1,93 @@ +#include "OutLineRenderer.h" + +#include "Core/StringCrc.h" +#include "ECWorld/SceneWorld.h" +#include "ECWorld/StaticMeshComponent.h" +#include "ECWorld/TransformComponent.h" +#include "Rendering/RenderContext.h" +#include "Rendering/Resources/ShaderResource.h" +#include "Scene/Texture.h" + +namespace engine +{ + +namespace +{ + +constexpr const char* outLineColor = "u_outLineColor"; +constexpr const char* outLineSize = "u_outLineSize"; + +} + +void OutLineRenderer::Init() +{ + AddDependentShaderResource(GetRenderContext()->RegisterShaderProgram("OutLineProgram", "vs_outline", "fs_outline")); + + GetRenderContext()->CreateUniform(outLineColor, bgfx::UniformType::Vec4, 1); + GetRenderContext()->CreateUniform(outLineSize, bgfx::UniformType::Vec4, 1); + + bgfx::setViewName(GetViewID(), "OutLineRenderer"); +} + +void OutLineRenderer::UpdateView(const float* pViewMatrix, const float* pProjectionMatrix) +{ + UpdateViewRenderTarget(); + bgfx::setViewTransform(GetViewID(), pViewMatrix, pProjectionMatrix); +} + +void OutLineRenderer::Render(float deltaTime) +{ + for (const auto pResource : m_dependentShaderResources) + { + if (ResourceStatus::Ready != pResource->GetStatus() && + ResourceStatus::Optimized != pResource->GetStatus()) + { + return; + } + } + + for (Entity entity : m_pCurrentSceneWorld->GetStaticMeshEntities()) + { + StaticMeshComponent* pMeshComponent = m_pCurrentSceneWorld->GetStaticMeshComponent(entity); + + if (m_pCurrentSceneWorld->GetSkyEntity() == entity) + { + continue; + } + + TerrainComponent* pTerrainComponent = m_pCurrentSceneWorld->GetTerrainComponent(entity); + if (pTerrainComponent) + { + continue; + } + if (!pMeshComponent) + { + continue; + } + + MaterialComponent* pMaterialComponent = m_pCurrentSceneWorld->GetMaterialComponent(entity); + if (!pMaterialComponent->GetToonParameters().isOpenOutLine) + { + continue; + } + if (TransformComponent* pTransformComponent = m_pCurrentSceneWorld->GetTransformComponent(entity)) + { + pTransformComponent->Build(); + bgfx::setTransform(pTransformComponent->GetWorldMatrix().begin()); + } + + constexpr StringCrc outLineColorCrc(outLineColor); + GetRenderContext()->FillUniform(outLineColorCrc, pMaterialComponent->GetToonParameters().outLineColor.begin()); + + constexpr StringCrc outLineSizeCrc(outLineSize); + GetRenderContext()->FillUniform(outLineSizeCrc, &pMaterialComponent->GetToonParameters().outLineSize); + + constexpr uint64_t state = BGFX_STATE_WRITE_MASK | BGFX_STATE_MSAA | BGFX_STATE_DEPTH_TEST_LESS | BGFX_STATE_CULL_CW; + bgfx::setState(state); + + constexpr StringCrc programHandleIndex{ "OutLineProgram" }; + SubmitStaticMeshDrawCall(pMeshComponent, GetViewID(), programHandleIndex); + } +} + +} \ No newline at end of file diff --git a/Engine/Source/Runtime/Rendering/OutLineRenderer.h b/Engine/Source/Runtime/Rendering/OutLineRenderer.h new file mode 100644 index 00000000..9b0dca0e --- /dev/null +++ b/Engine/Source/Runtime/Rendering/OutLineRenderer.h @@ -0,0 +1,27 @@ +#pragma once + +#include "Renderer.h" + +#include + +namespace engine +{ + + class SceneWorld; + + class OutLineRenderer final : public Renderer + { + public: + using Renderer::Renderer; + + virtual void Init() override; + virtual void UpdateView(const float* pViewMatrix, const float* pProjectionMatrix) override; + virtual void Render(float deltaTime) override; + + void SetSceneWorld(SceneWorld* pSceneWorld) { m_pCurrentSceneWorld = pSceneWorld; } + + private: + SceneWorld* m_pCurrentSceneWorld = nullptr; + }; + +} \ No newline at end of file diff --git a/Engine/Source/Runtime/Rendering/PBRSkyRenderer.cpp b/Engine/Source/Runtime/Rendering/PBRSkyRenderer.cpp index 7cdfc3b3..1bd106a4 100644 --- a/Engine/Source/Runtime/Rendering/PBRSkyRenderer.cpp +++ b/Engine/Source/Runtime/Rendering/PBRSkyRenderer.cpp @@ -6,6 +6,7 @@ #include "Math/Box.hpp" #include "Rendering/RenderContext.h" #include "Rendering/Resources/MeshResource.h" +#include "Rendering/Resources/ShaderResource.h" #include "Scene/Mesh.h" #include "Scene/VertexFormat.h" #include "U_AtmophericScattering.sh" @@ -27,6 +28,15 @@ constexpr const char* ProgramComputeScatteringDensity = "ProgramComputeScatte constexpr const char* ProgramComputeIndirectIrradiance = "ProgramComputeIndirectIrradiance"; constexpr const char* ProgramComputeMultipleScattering = "ProgramComputeMultipleScattering"; +constexpr StringCrc ProgramAtmosphericScatteringLUTCrc{ ProgramAtmosphericScatteringLUT }; +constexpr StringCrc ProgramSingleScatteringRayMarchingCrc{ ProgramSingleScatteringRayMarching }; +constexpr StringCrc ProgramComputeTransmittanceCrc{ ProgramComputeTransmittance }; +constexpr StringCrc ProgramComputeDirectIrradianceCrc{ ProgramComputeDirectIrradiance }; +constexpr StringCrc ProgramComputeSingleScatteringCrc{ ProgramComputeSingleScattering }; +constexpr StringCrc ProgramComputeScatteringDensityCrc{ ProgramComputeScatteringDensity }; +constexpr StringCrc ProgramComputeIndirectIrradianceCrc{ ProgramComputeIndirectIrradiance }; +constexpr StringCrc ProgramComputeMultipleScatteringCrc{ ProgramComputeMultipleScattering }; + constexpr const char* TextureTransmittance = "TextureTransmittance"; constexpr const char* TextureIrradiance = "TextureIrradiance"; constexpr const char* TextureScattering = "TextureScattering"; @@ -50,29 +60,15 @@ constexpr uint16_t ScatteringOrders = 6; void PBRSkyRenderer::Init() { - constexpr StringCrc ProgramAtmosphericScatteringLUTCrc(ProgramAtmosphericScatteringLUT); - constexpr StringCrc ProgramSingleScatteringRayMarchingCrc(ProgramSingleScatteringRayMarching); - constexpr StringCrc ProgramComputeTransmittanceCrc(ProgramComputeTransmittance); - constexpr StringCrc ProgramComputeDirectIrradianceCrc(ProgramComputeDirectIrradiance); - constexpr StringCrc ProgramComputeSingleScatteringCrc(ProgramComputeSingleScattering); - constexpr StringCrc ProgramComputeScatteringDensityCrc(ProgramComputeScatteringDensity); - constexpr StringCrc ProgramComputeIndirectIrradianceCrc(ProgramComputeIndirectIrradiance); - constexpr StringCrc ProgramComputeMultipleScatteringCrc(ProgramComputeMultipleScattering); + AddDependentShaderResource(GetRenderContext()->RegisterShaderProgram("ProgramAtmosphericScatteringLUT", "vs_atmSkyBox", "fs_PrecomputedAtmosphericScattering_LUT")); + AddDependentShaderResource(GetRenderContext()->RegisterShaderProgram("ProgramSingleScatteringRayMarching", "vs_atmSkyBox", "fs_SingleScattering_RayMarching")); + AddDependentShaderResource(GetRenderContext()->RegisterShaderProgram("ProgramComputeTransmittance", "cs_ComputeTransmittance", ShaderProgramType::Compute)); + AddDependentShaderResource(GetRenderContext()->RegisterShaderProgram("ProgramComputeDirectIrradiance", "cs_ComputeDirectIrradiance", ShaderProgramType::Compute)); + AddDependentShaderResource(GetRenderContext()->RegisterShaderProgram("ProgramComputeSingleScattering", "cs_ComputeSingleScattering", ShaderProgramType::Compute)); + AddDependentShaderResource(GetRenderContext()->RegisterShaderProgram("ProgramComputeScatteringDensity", "cs_ComputeScatteringDensity", ShaderProgramType::Compute)); + AddDependentShaderResource(GetRenderContext()->RegisterShaderProgram("ProgramComputeIndirectIrradiance", "cs_ComputeIndirectIrradiance", ShaderProgramType::Compute)); + AddDependentShaderResource(GetRenderContext()->RegisterShaderProgram("ProgramComputeMultipleScattering", "cs_ComputeMultipleScattering", ShaderProgramType::Compute)); - GetRenderContext()->RegisterShaderProgram(ProgramAtmosphericScatteringLUTCrc, { "vs_atmSkyBox", "fs_PrecomputedAtmosphericScattering_LUT" }); - GetRenderContext()->RegisterShaderProgram(ProgramSingleScatteringRayMarchingCrc, { "vs_atmSkyBox", "fs_SingleScattering_RayMarching" }); - GetRenderContext()->RegisterShaderProgram(ProgramComputeTransmittanceCrc, { "cs_ComputeTransmittance" }); - GetRenderContext()->RegisterShaderProgram(ProgramComputeDirectIrradianceCrc, { "cs_ComputeDirectIrradiance" }); - GetRenderContext()->RegisterShaderProgram(ProgramComputeSingleScatteringCrc, { "cs_ComputeSingleScattering" }); - GetRenderContext()->RegisterShaderProgram(ProgramComputeScatteringDensityCrc, { "cs_ComputeScatteringDensity" }); - GetRenderContext()->RegisterShaderProgram(ProgramComputeIndirectIrradianceCrc, { "cs_ComputeIndirectIrradiance" }); - GetRenderContext()->RegisterShaderProgram(ProgramComputeMultipleScatteringCrc, { "cs_ComputeMultipleScattering" }); - - bgfx::setViewName(GetViewID(), "PBRSkyRenderer"); -} - -void PBRSkyRenderer::Warmup() -{ GetRenderContext()->CreateTexture(TextureTransmittance, TRANSMITTANCE_TEXTURE_WIDTH, TRANSMITTANCE_TEXTURE_HEIGHT, 1, bgfx::TextureFormat::RGBA32F, FlagTexture2D); GetRenderContext()->CreateTexture(TextureIrradiance, IRRADIANCE_TEXTURE_WIDTH, IRRADIANCE_TEXTURE_HEIGHT, 1, @@ -95,15 +91,7 @@ void PBRSkyRenderer::Warmup() GetRenderContext()->CreateUniform(HeightOffset, bgfx::UniformType::Enum::Vec4, 1); GetRenderContext()->CreateUniform(NumScatteringOrders, bgfx::UniformType::Enum::Vec4, 1); - GetRenderContext()->UploadShaderProgram(ProgramAtmosphericScatteringLUT); - GetRenderContext()->UploadShaderProgram(ProgramSingleScatteringRayMarching); - - GetRenderContext()->UploadShaderProgram(ProgramComputeTransmittance); - GetRenderContext()->UploadShaderProgram(ProgramComputeDirectIrradiance); - GetRenderContext()->UploadShaderProgram(ProgramComputeSingleScattering); - GetRenderContext()->UploadShaderProgram(ProgramComputeScatteringDensity); - GetRenderContext()->UploadShaderProgram(ProgramComputeIndirectIrradiance); - GetRenderContext()->UploadShaderProgram(ProgramComputeMultipleScattering); + bgfx::setViewName(GetViewID(), "PBRSkyRenderer"); } void PBRSkyRenderer::UpdateView(const float* pViewMatrix, const float* pProjectionMatrix) @@ -129,6 +117,15 @@ void PBRSkyRenderer::UpdateView(const float* pViewMatrix, const float* pProjecti void PBRSkyRenderer::Render(float deltaTime) { + for (const auto pResource : m_dependentShaderResources) + { + if (ResourceStatus::Ready != pResource->GetStatus() && + ResourceStatus::Optimized != pResource->GetStatus()) + { + return; + } + } + if (!IsEnable()) { return; @@ -171,7 +168,7 @@ void PBRSkyRenderer::Render(float deltaTime) bgfx::setState(StateRendering); - SubmitStaticMeshDrawCall(pMeshComponent, GetViewID(), ProgramAtmosphericScatteringLUT); + SubmitStaticMeshDrawCall(pMeshComponent, GetViewID(), ProgramAtmosphericScatteringLUTCrc); } bool PBRSkyRenderer::IsEnable() const @@ -204,20 +201,23 @@ void PBRSkyRenderer::Precompute() const // Compute Transmittance. bgfx::setImage(0, GetRenderContext()->GetTexture(TextureTransmittanceCrc), 0, bgfx::Access::Write, bgfx::TextureFormat::RGBA32F); - GetRenderContext()->Dispatch(viewId, ProgramComputeTransmittance, TRANSMITTANCE_TEXTURE_WIDTH / 8U, TRANSMITTANCE_TEXTURE_HEIGHT / 8U, 1U); + GetRenderContext()->Dispatch(viewId, ProgramComputeTransmittanceCrc, + TRANSMITTANCE_TEXTURE_WIDTH / 8U, TRANSMITTANCE_TEXTURE_HEIGHT / 8U, 1U); // Compute direct Irradiance. bgfx::setImage(ATM_TRANSMITTANCE_SLOT, GetRenderContext()->GetTexture(TextureTransmittanceCrc), 0, bgfx::Access::Read, bgfx::TextureFormat::RGBA32F); bgfx::setImage(0, GetRenderContext()->GetTexture(TextureDeltaIrradianceCrc), 0, bgfx::Access::Write, bgfx::TextureFormat::RGBA32F); bgfx::setImage(1, GetRenderContext()->GetTexture(TextureIrradianceCrc), 0, bgfx::Access::Write, bgfx::TextureFormat::RGBA32F); - GetRenderContext()->Dispatch(viewId, ProgramComputeDirectIrradiance, IRRADIANCE_TEXTURE_WIDTH / 8U, IRRADIANCE_TEXTURE_HEIGHT / 8U, 1U); + GetRenderContext()->Dispatch(viewId, ProgramComputeDirectIrradianceCrc, + IRRADIANCE_TEXTURE_WIDTH / 8U, IRRADIANCE_TEXTURE_HEIGHT / 8U, 1U); // Compute single Scattering. bgfx::setImage(ATM_TRANSMITTANCE_SLOT, GetRenderContext()->GetTexture(TextureTransmittanceCrc), 0, bgfx::Access::Read, bgfx::TextureFormat::RGBA32F); bgfx::setImage(0, GetRenderContext()->GetTexture(TextureDeltaRayleighScatteringCrc), 0, bgfx::Access::Write, bgfx::TextureFormat::RGBA32F); bgfx::setImage(1, GetRenderContext()->GetTexture(TextureDeltaMieScatteringCrc), 0, bgfx::Access::Write, bgfx::TextureFormat::RGBA32F); bgfx::setImage(2, GetRenderContext()->GetTexture(TextureScatteringCrc), 0, bgfx::Access::Write, bgfx::TextureFormat::RGBA32F); - GetRenderContext()->Dispatch(viewId, ProgramComputeSingleScattering, SCATTERING_TEXTURE_WIDTH / 8U, SCATTERING_TEXTURE_HEIGHT / 8U, SCATTERING_TEXTURE_DEPTH / 8U); + GetRenderContext()->Dispatch(viewId, ProgramComputeSingleScatteringCrc, + SCATTERING_TEXTURE_WIDTH / 8U, SCATTERING_TEXTURE_HEIGHT / 8U, SCATTERING_TEXTURE_DEPTH / 8U); // Compute multiple Scattering. cd::Vec4f tmpOrder; @@ -233,7 +233,8 @@ void PBRSkyRenderer::Precompute() const bgfx::setImage(ATM_MULTIPLE_SCATTERING_SLOT, GetRenderContext()->GetTexture(TextureDeltaMultipleScatteringCrc), 0, bgfx::Access::Read, bgfx::TextureFormat::RGBA32F); bgfx::setImage(ATM_IRRADIANCE_SLOT, GetRenderContext()->GetTexture(TextureDeltaIrradianceCrc), 0, bgfx::Access::Read, bgfx::TextureFormat::RGBA32F); bgfx::setImage(0, GetRenderContext()->GetTexture(TextureDeltaScatteringDensityCrc), 0, bgfx::Access::Write, bgfx::TextureFormat::RGBA32F); - GetRenderContext()->Dispatch(viewId, ProgramComputeScatteringDensity, SCATTERING_TEXTURE_WIDTH / 8U, SCATTERING_TEXTURE_HEIGHT / 8U, SCATTERING_TEXTURE_DEPTH / 8U); + GetRenderContext()->Dispatch(viewId, ProgramComputeScatteringDensityCrc, + SCATTERING_TEXTURE_WIDTH / 8U, SCATTERING_TEXTURE_HEIGHT / 8U, SCATTERING_TEXTURE_DEPTH / 8U); // 2. Compute indirect Irradiance. tmpOrder.x() = static_cast(order - 1); @@ -244,14 +245,16 @@ void PBRSkyRenderer::Precompute() const bgfx::setImage(ATM_MULTIPLE_SCATTERING_SLOT, GetRenderContext()->GetTexture(TextureDeltaMultipleScatteringCrc), 0, bgfx::Access::Read, bgfx::TextureFormat::RGBA32F); bgfx::setImage(0, GetRenderContext()->GetTexture(TextureDeltaIrradianceCrc), 0, bgfx::Access::Write, bgfx::TextureFormat::RGBA32F); bgfx::setImage(1, GetRenderContext()->GetTexture(TextureIrradianceCrc), 0, bgfx::Access::Write, bgfx::TextureFormat::RGBA32F); - GetRenderContext()->Dispatch(viewId, ProgramComputeIndirectIrradiance, IRRADIANCE_TEXTURE_WIDTH / 8U, IRRADIANCE_TEXTURE_HEIGHT / 8U, 1U); + GetRenderContext()->Dispatch(viewId, ProgramComputeIndirectIrradianceCrc, + IRRADIANCE_TEXTURE_WIDTH / 8U, IRRADIANCE_TEXTURE_HEIGHT / 8U, 1U); // 3. Compute multiple Scattering. bgfx::setImage(ATM_TRANSMITTANCE_SLOT, GetRenderContext()->GetTexture(TextureTransmittanceCrc), 0, bgfx::Access::Read, bgfx::TextureFormat::RGBA32F); bgfx::setImage(ATM_SCATTERING_DENSITY, GetRenderContext()->GetTexture(TextureDeltaScatteringDensityCrc), 0, bgfx::Access::Read, bgfx::TextureFormat::RGBA32F); bgfx::setImage(0, GetRenderContext()->GetTexture(TextureDeltaMultipleScatteringCrc), 0, bgfx::Access::Write, bgfx::TextureFormat::RGBA32F); bgfx::setImage(1, GetRenderContext()->GetTexture(TextureScatteringCrc), 0, bgfx::Access::Write, bgfx::TextureFormat::RGBA32F); - GetRenderContext()->Dispatch(viewId, ProgramComputeMultipleScattering, SCATTERING_TEXTURE_WIDTH / 8U, SCATTERING_TEXTURE_HEIGHT / 8U, SCATTERING_TEXTURE_DEPTH / 8U); + GetRenderContext()->Dispatch(viewId, ProgramComputeMultipleScatteringCrc, + SCATTERING_TEXTURE_WIDTH / 8U, SCATTERING_TEXTURE_HEIGHT / 8U, SCATTERING_TEXTURE_DEPTH / 8U); } CD_ENGINE_TRACE("All compute shaders for precomputing atmospheric scattering texture dispatched."); diff --git a/Engine/Source/Runtime/Rendering/PBRSkyRenderer.h b/Engine/Source/Runtime/Rendering/PBRSkyRenderer.h index f16870c5..380e5620 100644 --- a/Engine/Source/Runtime/Rendering/PBRSkyRenderer.h +++ b/Engine/Source/Runtime/Rendering/PBRSkyRenderer.h @@ -15,7 +15,6 @@ class PBRSkyRenderer final : public Renderer using Renderer::Renderer; virtual void Init() override; - virtual void Warmup() override; virtual void UpdateView(const float* pViewMatrix, const float* pProjectionMatrix) override; virtual void Render(float deltaTime) override; virtual bool IsEnable() const override; diff --git a/Engine/Source/Runtime/Rendering/ParticleForceFieldRenderer.cpp b/Engine/Source/Runtime/Rendering/ParticleForceFieldRenderer.cpp index 2cfc3199..a2ade1ed 100644 --- a/Engine/Source/Runtime/Rendering/ParticleForceFieldRenderer.cpp +++ b/Engine/Source/Runtime/Rendering/ParticleForceFieldRenderer.cpp @@ -4,23 +4,18 @@ #include "ECWorld/SceneWorld.h" #include "ECWorld/TransformComponent.h" #include "Rendering/RenderContext.h" +#include "Rendering/Resources/ShaderResource.h" namespace engine { void ParticleForceFieldRenderer::Init() { - constexpr StringCrc programCrc = StringCrc("ParticleForceFieldProgram"); - GetRenderContext()->RegisterShaderProgram(programCrc, { "vs_particleforcefield", "fs_particleforcefield" }); + AddDependentShaderResource(GetRenderContext()->RegisterShaderProgram("ParticleForceFieldProgram", "vs_particleforcefield", "fs_particleforcefield")); bgfx::setViewName(GetViewID(), "ParticleForceFieldRenderer"); } -void ParticleForceFieldRenderer::Warmup() -{ - GetRenderContext()->UploadShaderProgram("ParticleForceFieldProgram"); -} - void ParticleForceFieldRenderer::UpdateView(const float* pViewMatrix, const float* pProjectionMatrix) { UpdateViewRenderTarget(); @@ -29,6 +24,15 @@ void ParticleForceFieldRenderer::UpdateView(const float* pViewMatrix, const floa void ParticleForceFieldRenderer::Render(float deltaTime) { + for (const auto pResource : m_dependentShaderResources) + { + if (ResourceStatus::Ready != pResource->GetStatus() && + ResourceStatus::Optimized != pResource->GetStatus()) + { + return; + } + } + for (Entity entity : m_pCurrentSceneWorld->GetParticleForceFieldEntities()) { if (auto* pTransformComponent = m_pCurrentSceneWorld->GetTransformComponent(entity)) @@ -44,7 +48,8 @@ void ParticleForceFieldRenderer::Render(float deltaTime) BGFX_STATE_BLEND_FUNC(BGFX_STATE_BLEND_SRC_ALPHA, BGFX_STATE_BLEND_INV_SRC_ALPHA) | BGFX_STATE_PT_LINES; bgfx::setState(state); - GetRenderContext()->Submit(GetViewID(), "ParticleForceFieldProgram"); + constexpr StringCrc programHandleIndex{ "ParticleForceFieldProgram" }; + GetRenderContext()->Submit(GetViewID(), programHandleIndex); } } diff --git a/Engine/Source/Runtime/Rendering/ParticleForceFieldRenderer.h b/Engine/Source/Runtime/Rendering/ParticleForceFieldRenderer.h index 2b021bfc..4a53918a 100644 --- a/Engine/Source/Runtime/Rendering/ParticleForceFieldRenderer.h +++ b/Engine/Source/Runtime/Rendering/ParticleForceFieldRenderer.h @@ -13,7 +13,6 @@ class ParticleForceFieldRenderer final : public Renderer using Renderer::Renderer; virtual void Init() override; - virtual void Warmup() override; virtual void UpdateView(const float* pViewMatrix, const float* pProjectionMatrix) override; virtual void Render(float deltaTime) override; diff --git a/Engine/Source/Runtime/Rendering/ParticleRenderer.cpp b/Engine/Source/Runtime/Rendering/ParticleRenderer.cpp index ed72070b..3295ad78 100644 --- a/Engine/Source/Runtime/Rendering/ParticleRenderer.cpp +++ b/Engine/Source/Runtime/Rendering/ParticleRenderer.cpp @@ -1,15 +1,19 @@ -#include "Log/Log.h" #include "ParticleRenderer.h" + #include "ECWorld/CameraComponent.h" -#include "ECWorld/SceneWorld.h" #include "ECWorld/ParticleForceFieldComponent.h" +#include "ECWorld/SceneWorld.h" #include "ECWorld/TransformComponent.h" +#include "Log/Log.h" #include "Rendering/RenderContext.h" +#include "Rendering/Resources/ShaderResource.h" -namespace engine { +namespace engine +{ namespace { + constexpr const char* particlePos = "u_particlePos"; constexpr const char* particleScale = "u_particleScale"; constexpr const char* shapeRange = "u_shapeRange"; @@ -21,26 +25,15 @@ BGFX_STATE_BLEND_FUNC(BGFX_STATE_BLEND_SRC_ALPHA, BGFX_STATE_BLEND_INV_SRC_ALPHA uint64_t state_lines = BGFX_STATE_WRITE_MASK | BGFX_STATE_MSAA | BGFX_STATE_DEPTH_TEST_LESS | BGFX_STATE_BLEND_FUNC(BGFX_STATE_BLEND_SRC_ALPHA, BGFX_STATE_BLEND_INV_SRC_ALPHA) | BGFX_STATE_PT_LINES; -constexpr const char* ParticleProgram = "ParticleProgram"; -constexpr const char* ParticleEmitterShapeProgram = "ParticleEmitterShapeProgram"; -constexpr const char* WO_BillboardParticleProgram = "WO_BillboardParticleProgram"; - -constexpr StringCrc ParticleProgramCrc = StringCrc{ "ParticleProgram" }; -constexpr StringCrc ParticleEmitterShapeProgramCrc = StringCrc{ "ParticleEmitterShapeProgram" }; -constexpr StringCrc WO_BillboardParticleProgramCrc = StringCrc{ "WO_BillboardParticleProgram" }; } void ParticleRenderer::Init() { - GetRenderContext()->RegisterShaderProgram(ParticleProgramCrc, { "vs_particle", "fs_particle" }); - GetRenderContext()->RegisterShaderProgram(ParticleEmitterShapeProgramCrc, {"vs_particleEmitterShape", "fs_particleEmitterShape"}); - GetRenderContext()->RegisterShaderProgram(WO_BillboardParticleProgramCrc, { "vs_wo_billboardparticle","fs_wo_billboardparticle" }); - - bgfx::setViewName(GetViewID(), "ParticleRenderer"); -} + // TODO : ParticleRenderer should use material to manage ShaderResource instead of Renderer::AddShaderResource. + AddDependentShaderResource(GetRenderContext()->RegisterShaderProgram("ParticleProgram", "vs_particle", "fs_particle")); + AddDependentShaderResource(GetRenderContext()->RegisterShaderProgram("WO_BillboardParticleProgram", "vs_wo_billboardparticle", "fs_wo_billboardparticle")); + AddDependentShaderResource(GetRenderContext()->RegisterShaderProgram("ParticleEmitterShapeProgram", "vs_particleEmitterShape", "fs_particleEmitterShape")); -void ParticleRenderer::Warmup() -{ constexpr const char* particleTexture = "Textures/textures/Particle.png"; m_particleTextureHandle = GetRenderContext()->CreateTexture(particleTexture); GetRenderContext()->CreateUniform("s_texColor", bgfx::UniformType::Sampler); @@ -49,9 +42,7 @@ void ParticleRenderer::Warmup() GetRenderContext()->CreateUniform(shapeRange, bgfx::UniformType::Vec4, 1); GetRenderContext()->CreateUniform(particleColor, bgfx::UniformType::Vec4, 1); - GetRenderContext()->UploadShaderProgram(ParticleProgram); - GetRenderContext()->UploadShaderProgram(ParticleEmitterShapeProgram); - GetRenderContext()->UploadShaderProgram(WO_BillboardParticleProgram); + bgfx::setViewName(GetViewID(), "ParticleRenderer"); } void ParticleRenderer::UpdateView(const float* pViewMatrix, const float* pProjectionMatrix) @@ -62,6 +53,15 @@ void ParticleRenderer::UpdateView(const float* pViewMatrix, const float* pProjec void ParticleRenderer::Render(float deltaTime) { + for (const auto pResource : m_dependentShaderResources) + { + if (ResourceStatus::Ready != pResource->GetStatus() && + ResourceStatus::Optimized != pResource->GetStatus()) + { + return; + } + } + for (Entity entity : m_pCurrentSceneWorld->GetParticleForceFieldEntities()) { ParticleForceFieldComponent* pForceFieldComponent = m_pCurrentSceneWorld->GetParticleForceFieldComponent(entity); @@ -169,11 +169,13 @@ void ParticleRenderer::Render(float deltaTime) if (pEmitterComponent->GetRenderMode() == engine::ParticleRenderMode::Mesh) { - GetRenderContext()->Submit(GetViewID(), ParticleProgram); + constexpr StringCrc programHandleIndex{ "ParticleProgram" }; + GetRenderContext()->Submit(GetViewID(), programHandleIndex); } else if (pEmitterComponent->GetRenderMode() == engine::ParticleRenderMode::Billboard) { - GetRenderContext()->Submit(GetViewID(), WO_BillboardParticleProgram); + constexpr StringCrc programHandleIndex{ "WO_BillboardParticleProgram" }; + GetRenderContext()->Submit(GetViewID(), programHandleIndex); } } else @@ -215,11 +217,13 @@ void ParticleRenderer::Render(float deltaTime) if (pEmitterComponent->GetRenderMode() == engine::ParticleRenderMode::Mesh) { - GetRenderContext()->Submit(GetViewID(), ParticleProgram); + constexpr StringCrc programHandleIndex{ "ParticleProgram" }; + GetRenderContext()->Submit(GetViewID(), programHandleIndex); } else if (pEmitterComponent->GetRenderMode() == engine::ParticleRenderMode::Billboard) { - GetRenderContext()->Submit(GetViewID(), WO_BillboardParticleProgram); + constexpr StringCrc programHandleIndex{ "WO_BillboardParticleProgram" }; + GetRenderContext()->Submit(GetViewID(), programHandleIndex); } } } @@ -236,7 +240,8 @@ void ParticleRenderer::Render(float deltaTime) bgfx::setIndexBuffer(bgfx::IndexBufferHandle{ pEmitterComponent->GetEmitterShapeIndexBufferHandle() }); bgfx::setState(state_lines); - GetRenderContext()->Submit(GetViewID(), ParticleEmitterShapeProgram); + constexpr StringCrc programHandleIndex{ "ParticleEmitterShapeProgram" }; + GetRenderContext()->Submit(GetViewID(), programHandleIndex); } } diff --git a/Engine/Source/Runtime/Rendering/ParticleRenderer.h b/Engine/Source/Runtime/Rendering/ParticleRenderer.h index 6766fb78..4ce854d1 100644 --- a/Engine/Source/Runtime/Rendering/ParticleRenderer.h +++ b/Engine/Source/Runtime/Rendering/ParticleRenderer.h @@ -18,7 +18,6 @@ class ParticleRenderer final : public Renderer using Renderer::Renderer; virtual void Init() override; - virtual void Warmup() override; virtual void UpdateView(const float* pViewMatrix, const float* pProjectionMatrix) override; virtual void Render(float deltaTime) override; diff --git a/Engine/Source/Runtime/Rendering/PostProcessRenderer.cpp b/Engine/Source/Runtime/Rendering/PostProcessRenderer.cpp index 182cde07..ec9e26e5 100644 --- a/Engine/Source/Runtime/Rendering/PostProcessRenderer.cpp +++ b/Engine/Source/Runtime/Rendering/PostProcessRenderer.cpp @@ -1,31 +1,19 @@ #include "PostProcessRenderer.h" #include "Rendering/RenderContext.h" +#include "Rendering/Resources/ShaderResource.h" namespace engine { -namespace -{ - -constexpr const char *PostProcessProgram = "PostProcessProgram"; -constexpr StringCrc PostProcessProgramCrc = StringCrc(PostProcessProgram); - -} - void PostProcessRenderer::Init() { - GetRenderContext()->RegisterShaderProgram(PostProcessProgramCrc, { "vs_fullscreen", "fs_PBR_postProcessing" }); - - bgfx::setViewName(GetViewID(), "PostProcessRenderer"); -} + AddDependentShaderResource(GetRenderContext()->RegisterShaderProgram("PostProcessProgram", "vs_fullscreen", "fs_PBR_postProcessing")); -void PostProcessRenderer::Warmup() -{ GetRenderContext()->CreateUniform("s_lightingColor", bgfx::UniformType::Sampler); GetRenderContext()->CreateUniform("u_postProcessingParams", bgfx::UniformType::Vec4); - GetRenderContext()->UploadShaderProgram(PostProcessProgram); + bgfx::setViewName(GetViewID(), "PostProcessRenderer"); } void PostProcessRenderer::UpdateView(const float* pViewMatrix, const float* pProjectionMatrix) @@ -38,8 +26,16 @@ void PostProcessRenderer::UpdateView(const float* pViewMatrix, const float* pPro void PostProcessRenderer::Render(float deltaTime) { - constexpr StringCrc sceneRenderTarget("SceneRenderTarget"); + for (const auto pResource : m_dependentShaderResources) + { + if (ResourceStatus::Ready != pResource->GetStatus() && + ResourceStatus::Optimized != pResource->GetStatus()) + { + return; + } + } + constexpr StringCrc sceneRenderTarget("SceneRenderTarget"); const RenderTarget* pInputRT = GetRenderContext()->GetRenderTarget(sceneRenderTarget); const RenderTarget* pOutputRT = GetRenderTarget(); @@ -70,7 +66,8 @@ void PostProcessRenderer::Render(float deltaTime) bgfx::setState(BGFX_STATE_WRITE_RGB | BGFX_STATE_WRITE_A); Renderer::ScreenSpaceQuad(GetRenderTarget(), false); - GetRenderContext()->Submit(GetViewID(), PostProcessProgram); + constexpr StringCrc programHandleIndex{ "PostProcessProgram" }; + GetRenderContext()->Submit(GetViewID(), programHandleIndex); } } \ No newline at end of file diff --git a/Engine/Source/Runtime/Rendering/PostProcessRenderer.h b/Engine/Source/Runtime/Rendering/PostProcessRenderer.h index 9dffb805..b51ce4c0 100644 --- a/Engine/Source/Runtime/Rendering/PostProcessRenderer.h +++ b/Engine/Source/Runtime/Rendering/PostProcessRenderer.h @@ -12,7 +12,6 @@ class PostProcessRenderer final : public Renderer using Renderer::Renderer; virtual void Init() override; - virtual void Warmup() override; virtual void UpdateView(const float* pViewMatrix, const float* pProjectionMatrix) override; virtual void Render(float deltaTime) override; diff --git a/Engine/Source/Runtime/Rendering/RenderContext.cpp b/Engine/Source/Runtime/Rendering/RenderContext.cpp index 832e12de..10801ba1 100644 --- a/Engine/Source/Runtime/Rendering/RenderContext.cpp +++ b/Engine/Source/Runtime/Rendering/RenderContext.cpp @@ -4,7 +4,8 @@ #include "Log/Log.h" #include "Path/Path.h" #include "Renderer.h" -#include "Rendering/ShaderCollections.h" +#include "Rendering/Resources/ResourceContext.h" +#include "Rendering/Resources/ShaderResource.h" #include "Rendering/ShaderType.h" #include "Rendering/Utility/VertexLayoutUtility.h" #include "Resources/ResourceLoader.h" @@ -15,7 +16,6 @@ #include #include -//#include #include #include @@ -35,34 +35,6 @@ static void imageReleaseCb(void* _ptr, void* _userData) bimg::imageFree(imageContainer); } -std::tuple IdentifyShaderTypes(const std::set& shaders) -{ - assert(shaders.size() <= 2); - std::tuple shadersTuple = { "", "", "" }; - for (const auto& name : shaders) - { - engine::ShaderType type = engine::GetShaderType(name); - if (engine::ShaderType::Vertex == type) - { - std::get<0>(shadersTuple) = name; - } - else if (engine::ShaderType::Fragment == type) - { - std::get<1>(shadersTuple) = name; - - } - else if (engine::ShaderType::Compute == type) - { - std::get<2>(shadersTuple) = name; - } - else - { - CD_ENGINE_WARN("Unknown shader type of {0}!", name); - } - } - return shadersTuple; -} - } namespace engine @@ -122,16 +94,6 @@ void RenderContext::Init(GraphicsBackend backend, void* hwnd) void RenderContext::Shutdown() { - for (auto it : m_shaderHandles) - { - bgfx::destroy(bgfx::ShaderHandle{ it.second }); - } - - for (auto it : m_shaderProgramHandles) - { - bgfx::destroy(bgfx::ProgramHandle{ it.second }); - } - for (auto it : m_textureHandleCaches) { bgfx::destroy(bgfx::TextureHandle{ it.second }); @@ -147,16 +109,25 @@ void RenderContext::BeginFrame() { } -void RenderContext::Submit(uint16_t viewID, const std::string& programName, const std::string& featuresCombine) +void RenderContext::Submit(uint16_t viewID, uint16_t programHandle) { - assert(bgfx::isValid(GetShaderProgramHandle(programName, featuresCombine))); - bgfx::submit(viewID, GetShaderProgramHandle(programName, featuresCombine)); + assert(bgfx::isValid(bgfx::ProgramHandle{ programHandle })); + bgfx::submit(viewID, bgfx::ProgramHandle{ programHandle }); } -void RenderContext::Dispatch(uint16_t viewID, const std::string& programName, uint32_t numX, uint32_t numY, uint32_t numZ) +void RenderContext::Submit(uint16_t viewID, StringCrc programHandleIndex) { - assert(bgfx::isValid(GetShaderProgramHandle(programName))); - bgfx::dispatch(viewID, GetShaderProgramHandle(programName), numX, numY, numZ); + Submit(viewID, m_pResourceContext->GetShaderResource(programHandleIndex)->GetHandle()); +} + +void RenderContext::Dispatch(uint16_t viewID, uint16_t programHandle, uint32_t numX, uint32_t numY, uint32_t numZ) +{ + assert(bgfx::isValid(bgfx::ProgramHandle{ programHandle })); + bgfx::dispatch(viewID, bgfx::ProgramHandle{ programHandle }, numX, numY, numZ); +} +void RenderContext::Dispatch(uint16_t viewID, StringCrc programHandleIndex, uint32_t numX, uint32_t numY, uint32_t numZ) +{ + Dispatch(viewID, m_pResourceContext->GetShaderResource(programHandleIndex)->GetHandle(), numX, numY, numZ); } void RenderContext::EndFrame() @@ -179,143 +150,74 @@ uint16_t RenderContext::CreateView() return m_currentViewCount++; } -void RenderContext::RegisterShaderProgram(StringCrc programNameCrc, std::initializer_list names) -{ - m_pShaderCollections->RegisterShaderProgram(programNameCrc, cd::MoveTemp(names)); -} - -void RenderContext::AddShaderFeature(StringCrc programNameCrc, std::string combine) +ShaderResource* RenderContext::RegisterShaderProgram(const std::string& programName, const std::string& vsName, const std::string& fsName, const std::string& combine) { - m_pShaderCollections->AddFeatureCombine(programNameCrc, cd::MoveTemp(combine)); -} - -bool RenderContext::CheckShaderProgram(Entity entity, const std::string& programName, const std::string& featuresCombine) -{ - assert(m_pShaderCollections->IsProgramValid(StringCrc{ programName })); - - if (m_shaderProgramHandles.find(StringCrc{ programName + featuresCombine }) == m_shaderProgramHandles.end()) + const StringCrc programCrc{ programName + combine }; + if (m_pResourceContext->GetShaderResource(programCrc)) { - // It only represents that we do not hold the shader program GPU handle, - // whether the shader is compiled or not is unknown. - // The Combile Task will still be added to the queue and ResourceBuilder ensures that - // there is no duplication of compilation behavior. - AddShaderCompileInfo(ShaderCompileInfo{ entity, programName, featuresCombine }); - m_pShaderCollections->AddFeatureCombine(StringCrc{ programName }, featuresCombine); - - return true; + return m_pResourceContext->GetShaderResource(programCrc); } - return false; -} - -bool RenderContext::OnShaderHotModified(Entity entity, const std::string& programName, const std::string& featuresCombine) -{ - assert(m_pShaderCollections->IsProgramValid(StringCrc{ programName })); - - // m_modifiedProgramNameCrcs will be filled by callback function which bound to FileWatcher. - if (m_modifiedProgramNameCrcs.find(engine::StringCrc{ programName }) != m_modifiedProgramNameCrcs.end()) - { - AddShaderCompileInfo(engine::ShaderCompileInfo{ entity, programName, featuresCombine }); + ShaderResource* pShaderResource = m_pResourceContext->AddShaderResource(programCrc); + pShaderResource->SetType(ShaderProgramType::Standard); + pShaderResource->SetName(programName); + pShaderResource->SetShaders(vsName, fsName, combine); - return true; - } + AddShaderResource(StringCrc{ vsName }, pShaderResource); + AddShaderResource(StringCrc{ fsName }, pShaderResource); - return false; + return pShaderResource; } -void RenderContext::UploadShaderProgram(const std::string& programName, const std::string& featuresCombine) +ShaderResource* RenderContext::RegisterShaderProgram(const std::string& programName, const std::string& shaderName, ShaderProgramType type, const std::string& combine) { - assert(m_pShaderCollections->IsProgramValid(StringCrc{ programName })); - - auto [vsName, fsName, csName] = IdentifyShaderTypes(m_pShaderCollections->GetShaders(StringCrc{ programName })); - - if (featuresCombine.empty()) - { - // Non-uber shader case. - if (!vsName.empty() && !fsName.empty() && csName.empty()) - { - CreateProgram(programName, vsName.data(), fsName.data()); - } - else if (!csName.empty()) - { - CreateProgram(programName, csName.data()); - } - else - { - CD_ENGINE_WARN("Unknown non-uber shader program type of {0}!", programName); - } - } - else + StringCrc programCrc{ programName + combine }; + if (m_pResourceContext->GetShaderResource(programCrc)) { - // Uber shader case. - if (!vsName.empty() && !fsName.empty() && csName.empty()) - { - CreateProgram(programName, vsName.data(), fsName.data(), featuresCombine); - } - else - { - CD_ENGINE_WARN("Unknown uber shader program type of {0}!", programName); - } + return m_pResourceContext->GetShaderResource(programCrc); } -} -void RenderContext::DestroyShaderProgram(const std::string& programName, const std::string& featuresCombine) -{ - DestoryProgram(StringCrc{ programName + featuresCombine }); + ShaderResource* pShaderResource = m_pResourceContext->AddShaderResource(StringCrc{ programName + combine }); + pShaderResource->SetType(type); + pShaderResource->SetName(programName); + pShaderResource->SetShader(ProgramTypeToSingleShaderType.at(type), shaderName, combine); - auto [vsName, fsName, csName] = IdentifyShaderTypes(m_pShaderCollections->GetShaders(StringCrc{ programName })); - StringCrc vsCrc{ vsName.data() }; - StringCrc fsCrc{ fsName.data() + featuresCombine }; - StringCrc csCrc{ csName.data() }; + AddShaderResource(StringCrc{ shaderName }, pShaderResource); - DestoryShader(vsCrc); - DestoryShader(fsCrc); - DestoryShader(csCrc); + return pShaderResource; } -void RenderContext::AddShaderCompileInfo(ShaderCompileInfo info) +void RenderContext::OnShaderHotModified(StringCrc modifiedShaderNameCrc) { - if (m_shaderCompileInfos.find(info) == m_shaderCompileInfos.end()) + // Get all ShaderResource variants by shader name. + auto range = m_shaderResources.equal_range(modifiedShaderNameCrc); + for (auto it = range.first; it != range.second; ++it) { - CD_ENGINE_INFO("Shader compile task added for {0} with shader features : [{1}]", info.m_programName, info.m_featuresCombine); - m_shaderCompileInfos.insert(cd::MoveTemp(info)); + m_modifiedShaderResources.insert(it->second); } } -void RenderContext::ClearShaderCompileInfos() -{ - m_shaderCompileInfos.clear(); -} - -void RenderContext::SetShaderCompileInfos(std::set tasks) -{ - m_shaderCompileInfos = cd::MoveTemp(tasks); -} - -void RenderContext::CheckModifiedProgram(std::string modifiedShaderName) +void RenderContext::OnShaderRecompile() { - // Find Shader Program name by Shader File Name. - // TODO : We could devise a mechanism like unity's meta file for recording dependencies on asset files, - // and perhaps both Program and Material information could be retrieved directly from the meta file. - for (const auto& [programName, shaderNames] : m_pShaderCollections->GetShaderPrograms()) + // m_modifiedShaderResources will be filled by callback function which bound to FileWatcher. + auto it = m_modifiedShaderResources.begin(); + while (it != m_modifiedShaderResources.end()) { - for (const auto& shaderName : shaderNames) + ShaderResource* pShaderResource = *it; + if (pShaderResource->IsActive()) + { + pShaderResource->Reset(); + AddRecompileShaderResource(pShaderResource); + + it = m_modifiedShaderResources.erase(it); + } + else { - if (shaderName == modifiedShaderName) - { - // Use set to ensure no duplicate detection are recorded. - m_modifiedProgramNameCrcs.insert(programName); - break; - } + ++it; } } } -void RenderContext::ClearModifiedProgramNameCrcs() -{ - m_modifiedProgramNameCrcs.clear(); -} - void RenderContext::AddCompileFailedEntity(uint32_t entity) { m_compileFailedEntities.insert(entity); @@ -326,44 +228,6 @@ void RenderContext::ClearCompileFailedEntity() m_compileFailedEntities.clear(); } -const RenderContext::ShaderBlob& RenderContext::AddShaderBlob(StringCrc shaderNameCrc, ShaderBlob blob) -{ - const auto& it = m_shaderBlobs.find(shaderNameCrc); - if (it != m_shaderBlobs.end()) - { - return *(it->second); - } - m_shaderBlobs[shaderNameCrc] = std::make_unique(cd::MoveTemp(blob)); - return *m_shaderBlobs.at(shaderNameCrc); -} - -const RenderContext::ShaderBlob& RenderContext::GetShaderBlob(StringCrc shaderNameCrc) const -{ - assert(m_shaderBlobs.find(shaderNameCrc) != m_shaderBlobs.end() && "Shader blob does not exist!"); - return *m_shaderBlobs.at(shaderNameCrc).get(); -} - -bool RenderContext::IsShaderProgramValid(const std::string& programName, const std::string& featuresCombine) const -{ - return bgfx::isValid(GetShaderProgramHandle(programName, featuresCombine)); -} - -void RenderContext::SetShaderProgramHandle(const std::string& programName, bgfx::ProgramHandle handle, const std::string& featuresCombine) -{ - m_shaderProgramHandles[StringCrc{ programName + featuresCombine }] = handle.idx; -} - -bgfx::ProgramHandle RenderContext::GetShaderProgramHandle(const std::string& programName, const std::string& featuresCombine) const -{ - const auto& it = m_shaderProgramHandles.find(StringCrc{ programName + featuresCombine }); - if (it != m_shaderProgramHandles.end()) - { - return { it->second }; - } - - return { bgfx::kInvalidHandle }; -} - RenderTarget* RenderContext::CreateRenderTarget(StringCrc resourceCrc, uint16_t width, uint16_t height, std::vector attachmentDescs) { return CreateRenderTarget(resourceCrc, std::make_unique(width, height, std::move(attachmentDescs))); @@ -388,81 +252,6 @@ RenderTarget* RenderContext::CreateRenderTarget(StringCrc resourceCrc, std::uniq return m_renderTargetCaches[resourceCrc].get(); } -bgfx::ShaderHandle RenderContext::CreateShader(const char* pShaderName, const std::string& combine) -{ - StringCrc shaderNameCrc{ pShaderName + combine }; - auto itShaderCache = m_shaderHandles.find(shaderNameCrc); - if(itShaderCache != m_shaderHandles.end()) - { - return { itShaderCache->second }; - } - - std::string shaderFileFullPath = Path::GetShaderOutputPath(pShaderName, combine); - const auto& shaderBlob = AddShaderBlob(shaderNameCrc, ResourceLoader::LoadFile(shaderFileFullPath.c_str())); - bgfx::ShaderHandle shaderHandle = bgfx::createShader(bgfx::makeRef(shaderBlob.data(), static_cast(shaderBlob.size()))); - - if(bgfx::isValid(shaderHandle)) - { - bgfx::setName(shaderHandle, pShaderName); - m_shaderHandles[shaderNameCrc] = shaderHandle.idx; - } - - return shaderHandle; -} - -bgfx::ProgramHandle RenderContext::CreateProgram(const std::string& programName, const std::string& csName) -{ - StringCrc programNameCrc{ programName }; - auto itProgram = m_shaderProgramHandles.find(programNameCrc); - if (itProgram != m_shaderProgramHandles.end()) - { - return { itProgram->second }; - } - - bgfx::ProgramHandle programHandle = bgfx::createProgram(CreateShader(csName.c_str())); - if (bgfx::isValid(programHandle)) - { - m_shaderProgramHandles[programNameCrc] = programHandle.idx; - } - - return programHandle; -} - -bgfx::ProgramHandle RenderContext::CreateProgram(const std::string& programName, const std::string& vsName, const std::string& fsName, const std::string& featuresCombine) -{ - StringCrc fullProgramNameCrc = StringCrc{ programName + featuresCombine }; - - const auto& it = m_shaderProgramHandles.find(fullProgramNameCrc); - if (it != m_shaderProgramHandles.end()) - { - return { it->second }; - } - - // BGFX will return a valid ProgramHandle with valid VSHandle and invalid FSHandle. - - bgfx::ShaderHandle vsHandle = CreateShader(vsName.c_str()); - if (!bgfx::isValid(vsHandle)) - { - DestoryShader(StringCrc{ vsName }); - return bgfx::ProgramHandle{ bgfx::kInvalidHandle }; - } - - bgfx::ShaderHandle fsHandle = CreateShader(fsName.c_str(), featuresCombine); - if (!bgfx::isValid(fsHandle)) - { - DestoryShader(StringCrc{ fsName + featuresCombine }); - return bgfx::ProgramHandle{ bgfx::kInvalidHandle }; - } - - bgfx::ProgramHandle programHandle = bgfx::createProgram(vsHandle, fsHandle); - if (bgfx::isValid(programHandle)) - { - m_shaderProgramHandles[fullProgramNameCrc] = programHandle.idx; - } - - return programHandle; -} - bgfx::TextureHandle RenderContext::CreateTexture(const char* pFilePath, uint64_t flags) { StringCrc filePathCrc{ pFilePath }; @@ -704,17 +493,6 @@ const bgfx::VertexLayout& RenderContext::GetVertexAttributeLayouts(StringCrc res return dummy; } -bgfx::ShaderHandle RenderContext::GetShader(StringCrc resourceCrc) const -{ - auto itResource = m_shaderHandles.find(resourceCrc); - if (itResource != m_shaderHandles.end()) - { - return { itResource->second }; - } - - return bgfx::ShaderHandle{ bgfx::kInvalidHandle }; -} - bgfx::TextureHandle RenderContext::GetTexture(StringCrc resourceCrc) const { auto itResource = m_textureHandleCaches.find(resourceCrc); @@ -764,29 +542,4 @@ void RenderContext::DestoryUniform(StringCrc resourceCrc) } } -void RenderContext::DestoryShader(StringCrc resourceCrc) -{ - auto it = m_shaderHandles.find(resourceCrc); - if (it != m_shaderHandles.end()) - { - assert(bgfx::isValid(bgfx::ShaderHandle{ it->second })); - bgfx::destroy(bgfx::ShaderHandle{ it->second }); - m_shaderHandles.erase(it); - } - - // Erase shader blob anyway. - m_shaderBlobs.erase(resourceCrc); -} - -void RenderContext::DestoryProgram(StringCrc resourceCrc) -{ - auto it = m_shaderProgramHandles.find(resourceCrc); - if (it != m_shaderProgramHandles.end()) - { - assert(bgfx::isValid(bgfx::ProgramHandle{ it->second })); - bgfx::destroy(bgfx::ProgramHandle{ it->second }); - m_shaderProgramHandles.erase(it); - } -} - } \ No newline at end of file diff --git a/Engine/Source/Runtime/Rendering/RenderContext.h b/Engine/Source/Runtime/Rendering/RenderContext.h index 5b0ceecb..9caf04c9 100644 --- a/Engine/Source/Runtime/Rendering/RenderContext.h +++ b/Engine/Source/Runtime/Rendering/RenderContext.h @@ -3,7 +3,7 @@ #include "Core/StringCrc.h" #include "Graphics/GraphicsBackend.h" #include "Math/Matrix.hpp" -#include "Rendering/ShaderCompileInfo.h" +#include "Rendering/ShaderType.h" #include "RenderTarget.h" #include "Scene/VertexAttribute.h" #include "Scene/VertexFormat.h" @@ -23,7 +23,7 @@ namespace engine class Camera; class Renderer; class ResourceContext; -class ShaderCollections; +class ShaderResource; static constexpr uint8_t MaxViewCount = 255; static constexpr uint8_t MaxRenderTargetCount = 255; @@ -46,8 +46,10 @@ class RenderContext void Init(GraphicsBackend backend, void* hwnd = nullptr); void OnResize(uint16_t width, uint16_t height); void BeginFrame(); - void Submit(uint16_t viewID, const std::string& programName, const std::string& featuresCombine = ""); - void Dispatch(uint16_t viewID, const std::string& programName, uint32_t numX, uint32_t numY, uint32_t numZ); + void Submit(uint16_t viewID, uint16_t programHandle); + void Submit(uint16_t viewID, StringCrc programHandleIndex); + void Dispatch(uint16_t viewID, uint16_t programHandle, uint32_t numX, uint32_t numY, uint32_t numZ); + void Dispatch(uint16_t viewID, StringCrc programHandleIndex, uint32_t numX, uint32_t numY, uint32_t numZ); void EndFrame(); void Shutdown(); @@ -62,59 +64,40 @@ class RenderContext void ResetViewCount() { m_currentViewCount = 0; } uint16_t GetCurrentViewCount() const { return m_currentViewCount; } - ///////////////////////////////////////////////////////////////////// - // Shader collections apis - ///////////////////////////////////////////////////////////////////// - void SetShaderCollections(ShaderCollections* pShaderCollections) { m_pShaderCollections = pShaderCollections; } - const ShaderCollections* GetShaderCollections() const { return m_pShaderCollections; } - - void RegisterShaderProgram(StringCrc programNameCrc, std::initializer_list names); - void AddShaderFeature(StringCrc programNameCrc, std::string combine); - - bool CheckShaderProgram(Entity entity, const std::string& programName, const std::string& featuresCombine = ""); - bool OnShaderHotModified(Entity entity, const std::string& programName, const std::string& featuresCombine = ""); - void UploadShaderProgram(const std::string& programName, const std::string& featuresCombine = ""); - void DestroyShaderProgram(const std::string& programName, const std::string& featuresCombine = ""); - - void AddShaderCompileInfo(ShaderCompileInfo info); - void ClearShaderCompileInfos(); - void SetShaderCompileInfos(std::set tasks); - std::set& GetShaderCompileInfos() { return m_shaderCompileInfos; } - const std::set& GetShaderCompileInfos() const { return m_shaderCompileInfos; } - - void CheckModifiedProgram(std::string modifiedShaderName); - void ClearModifiedProgramNameCrcs(); - std::set& GetModifiedProgramNameCrcs() { return m_modifiedProgramNameCrcs; } - const std::set& GetModifiedProgramNameCrcs() const { return m_modifiedProgramNameCrcs; } + // For Standard ShaderProgramType + ShaderResource* RegisterShaderProgram(const std::string& programName, const std::string& vsName, const std::string& fsName, const std::string& combine = ""); + // For non-Standard ShaderProgramType + ShaderResource* RegisterShaderProgram(const std::string& programName, const std::string& shaderName, ShaderProgramType type, const std::string& combine = ""); + + void AddShaderResource(StringCrc shaderName, ShaderResource* resource) { m_shaderResources.insert({ shaderName, resource }); } + void DeleteShaderResource(StringCrc shaderName) { m_shaderResources.erase(shaderName); } + void SetShaderResources(std::multimap resources) { m_shaderResources = cd::MoveTemp(resources); } + std::multimap& GetShaderResources() { return m_shaderResources; } + const std::multimap& GetShaderResources() const { return m_shaderResources; } + + // Call back function bind to file watcher. + void OnShaderHotModified(StringCrc modifiedShaderNameCrc); + void ClearModifiedShaderResources() { m_modifiedShaderResources.clear(); } + std::set& GetModifiedShaderResources() { return m_modifiedShaderResources; } + const std::set& GetModifiedShaderResources() const { return m_modifiedShaderResources; } + + void OnShaderRecompile(); + void AddRecompileShaderResource(ShaderResource* pShaderResource) { m_recompileShaderResources.insert(pShaderResource); } + void DeleteRecompileShaderResource(ShaderResource* pShaderResource) { m_recompileShaderResources.erase(pShaderResource); } + void ClearRecompileShaderResources() { m_recompileShaderResources.clear(); } + void SetRecompileShaderResources(std::set recompileShaderResources) { m_recompileShaderResources = cd::MoveTemp(recompileShaderResources); } + std::set GetRecompileShaderResources() { return m_recompileShaderResources; } + const std::set GetRecompileShaderResources() const { return m_recompileShaderResources; } void AddCompileFailedEntity(uint32_t entity); void ClearCompileFailedEntity(); std::set& GetCompileFailedEntities() { return m_compileFailedEntities; } const std::set& GetCompileFailedEntities() const { return m_compileFailedEntities; } - ///////////////////////////////////////////////////////////////////// - // Shader blob apis - ///////////////////////////////////////////////////////////////////// - const RenderContext::ShaderBlob& AddShaderBlob(StringCrc shaderNameCrc, ShaderBlob blob); - const ShaderBlob& GetShaderBlob(StringCrc shaderNameCrc) const; - - ///////////////////////////////////////////////////////////////////// - // Resource related apis - ///////////////////////////////////////////////////////////////////// - - bool IsShaderProgramValid(const std::string& programName, const std::string& featuresCombine = "") const; - - void SetShaderProgramHandle(const std::string& programName, bgfx::ProgramHandle handle, const std::string& featuresCombine = ""); - bgfx::ProgramHandle GetShaderProgramHandle(const std::string& programName, const std::string& featuresCombine = "") const; - RenderTarget* CreateRenderTarget(StringCrc resourceCrc, uint16_t width, uint16_t height, std::vector attachmentDescs); RenderTarget* CreateRenderTarget(StringCrc resourceCrc, uint16_t width, uint16_t height, void* pWindowHandle); RenderTarget* CreateRenderTarget(StringCrc resourceCrc, std::unique_ptr pRenderTarget); - bgfx::ShaderHandle CreateShader(const char* filePath, const std::string& combine = ""); - bgfx::ProgramHandle CreateProgram(const std::string& programName, const std::string& csName); - bgfx::ProgramHandle CreateProgram(const std::string& programName, const std::string& vsName, const std::string& fsName, const std::string& featuresCombine = ""); - bgfx::TextureHandle CreateTexture(const char* filePath, uint64_t flags = 0UL); bgfx::TextureHandle CreateTexture(const char* pName, uint16_t width, uint16_t height, uint16_t depth, bgfx::TextureFormat::Enum format, uint64_t flags = 0UL, const void* data = nullptr, uint32_t size = 0); bgfx::TextureHandle UpdateTexture(const char* pName, uint16_t layer, uint8_t mip, uint16_t x, uint16_t y, uint16_t z, uint16_t width, uint16_t height, uint16_t depth, const void* data = nullptr, uint32_t size = 0); @@ -130,15 +113,12 @@ class RenderContext RenderTarget* GetRenderTarget(StringCrc resourceCrc) const; const bgfx::VertexLayout& GetVertexAttributeLayouts(StringCrc resourceCrc) const; - bgfx::ShaderHandle GetShader(StringCrc resourceCrc) const; bgfx::TextureHandle GetTexture(StringCrc resourceCrc) const; bgfx::UniformHandle GetUniform(StringCrc resourceCrc) const; void DestoryRenderTarget(StringCrc resourceCrc); void DestoryTexture(StringCrc resourceCrc); void DestoryUniform(StringCrc resourceCrc); - void DestoryShader(StringCrc resourceCrc); - void DestoryProgram(StringCrc resourceCrc); private: ResourceContext* m_pResourceContext = nullptr; @@ -152,18 +132,10 @@ class RenderContext std::unordered_map m_textureHandleCaches; std::unordered_map m_uniformHandleCaches; - ShaderCollections* m_pShaderCollections = nullptr; - - // Key : StringCrc(Program name), Value : Shader program handle - std::unordered_map m_shaderProgramHandles; - - // Key : StringCrc(Shader name), Value : Shader handle - std::unordered_map m_shaderHandles; - // Key : StringCrc(Shader name), Value : Shader binary data - std::unordered_map> m_shaderBlobs; - - std::set m_shaderCompileInfos; - std::set m_modifiedProgramNameCrcs; + // Key : StringCrc(shader name), Value : ShaderResource* + std::multimap m_shaderResources; + std::set m_modifiedShaderResources; + std::set m_recompileShaderResources; std::set m_compileFailedEntities; }; diff --git a/Engine/Source/Runtime/Rendering/Renderer.cpp b/Engine/Source/Runtime/Rendering/Renderer.cpp index c1eda68e..ffa61a95 100644 --- a/Engine/Source/Runtime/Rendering/Renderer.cpp +++ b/Engine/Source/Runtime/Rendering/Renderer.cpp @@ -4,6 +4,8 @@ #include "Rendering/RenderContext.h" #include "Rendering/RenderTarget.h" #include "Rendering/Resources/MeshResource.h" +#include "Rendering/Resources/ResourceContext.h" +#include "Rendering/Resources/ShaderResource.h" #include @@ -141,7 +143,7 @@ void Renderer::ScreenSpaceQuad(const RenderTarget* pRenderTarget, bool _originBo } } -void Renderer::SubmitStaticMeshDrawCall(StaticMeshComponent* pMeshComponent, uint16_t viewID, const std::string& programName, const std::string& featuresCombine) +void Renderer::SubmitStaticMeshDrawCall(StaticMeshComponent* pMeshComponent, uint16_t viewID, uint16_t programHandle) { const MeshResource* pMeshResource = pMeshComponent->GetMeshResource(); assert(ResourceStatus::Ready == pMeshResource->GetStatus() || ResourceStatus::Optimized == pMeshResource->GetStatus()); @@ -150,9 +152,13 @@ void Renderer::SubmitStaticMeshDrawCall(StaticMeshComponent* pMeshComponent, uin { bgfx::setIndexBuffer(bgfx::IndexBufferHandle{ pMeshResource->GetIndexBufferHandle(indexBufferIndex) }, pMeshComponent->GetStartIndex(), pMeshComponent->GetIndexCount()); - // TODO : Submit interface requires runtime string construction which may hurt performance. - GetRenderContext()->Submit(viewID, programName, featuresCombine); + GetRenderContext()->Submit(viewID, programHandle); } } +void Renderer::SubmitStaticMeshDrawCall(StaticMeshComponent* pMeshComponent, uint16_t viewID, StringCrc programHandleIndex) +{ + SubmitStaticMeshDrawCall(pMeshComponent, viewID, m_pRenderContext->GetResourceContext()->GetShaderResource(programHandleIndex)->GetHandle()); +} + } \ No newline at end of file diff --git a/Engine/Source/Runtime/Rendering/Renderer.h b/Engine/Source/Runtime/Rendering/Renderer.h index 6c716651..b2d259db 100644 --- a/Engine/Source/Runtime/Rendering/Renderer.h +++ b/Engine/Source/Runtime/Rendering/Renderer.h @@ -1,6 +1,9 @@ #pragma once +#include "Core/StringCrc.h" + #include +#include #include namespace engine @@ -9,7 +12,7 @@ namespace engine class Camera; class RenderContext; class RenderTarget; -class ShaderCollections; +class ShaderResource; class StaticMeshComponent; class Renderer @@ -27,8 +30,6 @@ class Renderer static RenderContext* GetRenderContext(); virtual void Init() = 0; - // All registered shaders are compiled in the App::Init stage, simply create the GPU resource here. - virtual void Warmup() = 0; virtual void UpdateView(const float* pViewMatrix, const float* pProjectionMatrix) = 0; virtual void Render(float deltaTime) = 0; @@ -41,15 +42,20 @@ class Renderer virtual void SetEnable(bool value) { m_isEnable = value; } virtual bool IsEnable() const { return m_isEnable; } - void SubmitStaticMeshDrawCall(StaticMeshComponent* pMeshComponent, uint16_t viewID, const std::string& programName, const std::string& featuresCombine = ""); + void SubmitStaticMeshDrawCall(StaticMeshComponent* pMeshComponent, uint16_t viewID, uint16_t programHandle); + void SubmitStaticMeshDrawCall(StaticMeshComponent* pMeshComponent, uint16_t viewID, StringCrc programHandleIndex); public: static void ScreenSpaceQuad(const RenderTarget* pRenderTarget, bool _originBottomLeft = false, float _width = 1.0f, float _height = 1.0f); + void AddDependentShaderResource(ShaderResource *shaderResource) { m_dependentShaderResources.insert(shaderResource); } protected: + bool m_isEnable = true; uint16_t m_viewID = 0; RenderTarget* m_pRenderTarget = nullptr; - bool m_isEnable = true; + + // TODO : Need a generic way to manage the Renderer's dependency on shader resources, improve it. + std::set m_dependentShaderResources; }; } \ No newline at end of file diff --git a/Engine/Source/Runtime/Rendering/Resources/IResource.h b/Engine/Source/Runtime/Rendering/Resources/IResource.h index 1da2aa9e..2181ba41 100644 --- a/Engine/Source/Runtime/Rendering/Resources/IResource.h +++ b/Engine/Source/Runtime/Rendering/Resources/IResource.h @@ -20,6 +20,8 @@ enum class ResourceStatus enum class ResourceType { Mesh, + Shader, + Skeleton, Texture, }; diff --git a/Engine/Source/Runtime/Rendering/Resources/MeshResource.cpp b/Engine/Source/Runtime/Rendering/Resources/MeshResource.cpp index fde3eafa..8915445e 100644 --- a/Engine/Source/Runtime/Rendering/Resources/MeshResource.cpp +++ b/Engine/Source/Runtime/Rendering/Resources/MeshResource.cpp @@ -74,6 +74,16 @@ void MeshResource::SetMeshAsset(const cd::Mesh* pMeshAsset) m_pMeshAsset = pMeshAsset; } +void MeshResource::SetSkinAsset(const cd::Skin* pSkinAsset) +{ + m_pSkinAsset.push_back(pSkinAsset); +} + +void MeshResource::AddBonesAsset(const cd::Bone& bone) +{ + m_pBonesAsset.push_back(&bone); +} + void MeshResource::UpdateVertexFormat(const cd::VertexFormat& vertexFormat) { // Set mesh asset at first so that MeshResource can analyze if it is suitable. @@ -168,15 +178,23 @@ void MeshResource::Reset() { DestroyVertexBufferHandle(); DestroyIndexBufferHandle(); - FreeMeshData(); + ClearMeshData(); SetStatus(ResourceStatus::Loading); } bool MeshResource::BuildVertexBuffer() { assert(m_pMeshAsset && m_vertexCount > 3U); + std::optional optVertexBuffer; + if (m_pSkinAsset.size()) + { + optVertexBuffer = cd::BuildVertexBufferForSkeletalMesh(*m_pMeshAsset, m_currentVertexFormat, *m_pSkinAsset[0], m_pBonesAsset); + } + else + { + optVertexBuffer = cd::BuildVertexBufferForStaticMesh(*m_pMeshAsset, m_currentVertexFormat); + } - std::optional optVertexBuffer = cd::BuildVertexBufferForStaticMesh(*m_pMeshAsset, m_currentVertexFormat); if (!optVertexBuffer.has_value()) { CD_ERROR("Failed to build mesh vertex buffer."); @@ -239,7 +257,8 @@ void MeshResource::SubmitVertexBuffer() { return; } - + bool weight = m_currentVertexFormat.Contains(cd::VertexAttributeType::BoneWeight); + bool index = m_currentVertexFormat.Contains(cd::VertexAttributeType::BoneIndex); m_vertexBufferHandle = details::SubmitVertexBuffer(m_vertexBuffer, m_currentVertexFormat); } @@ -276,12 +295,19 @@ void MeshResource::SubmitIndexBuffer() } } -void MeshResource::FreeMeshData() +void MeshResource::ClearMeshData() { m_vertexBuffer.clear(); m_indexBuffers.clear(); } +void MeshResource::FreeMeshData() +{ + ClearMeshData(); + VertexBuffer().swap(m_vertexBuffer); + std::vector().swap(m_indexBuffers); +} + void MeshResource::DestroyVertexBufferHandle() { if (m_vertexBufferHandle != UINT16_MAX) diff --git a/Engine/Source/Runtime/Rendering/Resources/MeshResource.h b/Engine/Source/Runtime/Rendering/Resources/MeshResource.h index e3a3f161..e08e2914 100644 --- a/Engine/Source/Runtime/Rendering/Resources/MeshResource.h +++ b/Engine/Source/Runtime/Rendering/Resources/MeshResource.h @@ -9,6 +9,8 @@ namespace cd { class Mesh; +class Skin; +class Bone; } @@ -34,6 +36,12 @@ class MeshResource : public IResource const cd::Mesh* GetMeshAsset() const { return m_pMeshAsset; } void SetMeshAsset(const cd::Mesh* pMeshAsset); + + const cd::Skin* GetSkinAsset(int skinIndex) const { return m_pSkinAsset[skinIndex]; } + void SetSkinAsset(const cd::Skin* pSkinAsset); + + const std::vector GetBonesAsset() const { return m_pBonesAsset; } + void AddBonesAsset(const cd::Bone&); void UpdateVertexFormat(const cd::VertexFormat& vertexFormat); @@ -49,6 +57,7 @@ class MeshResource : public IResource bool BuildIndexBuffer(); void SubmitVertexBuffer(); void SubmitIndexBuffer(); + void ClearMeshData(); void FreeMeshData(); void DestroyVertexBufferHandle(); void DestroyIndexBufferHandle(); @@ -56,6 +65,8 @@ class MeshResource : public IResource private: // Asset const cd::Mesh* m_pMeshAsset = nullptr; + std::vector m_pSkinAsset; + std::vector m_pBonesAsset; uint32_t m_vertexCount = 0U; uint32_t m_polygonCount = 0U; uint32_t m_polygonGroupCount = 0U; diff --git a/Engine/Source/Runtime/Rendering/Resources/ResourceContext.cpp b/Engine/Source/Runtime/Rendering/Resources/ResourceContext.cpp index 62a64a65..cd226707 100644 --- a/Engine/Source/Runtime/Rendering/Resources/ResourceContext.cpp +++ b/Engine/Source/Runtime/Rendering/Resources/ResourceContext.cpp @@ -2,6 +2,8 @@ #include "Base/NameOf.h" #include "MeshResource.h" +#include "ShaderResource.h" +#include "SkeletonResource.h" #include "TextureResource.h" namespace engine @@ -31,6 +33,16 @@ MeshResource* ResourceContext::AddMeshResource(StringCrc nameCrc) return static_cast(AddResourceImpl(nameCrc)); } +ShaderResource* ResourceContext::AddShaderResource(StringCrc nameCrc) +{ + return static_cast(AddResourceImpl(nameCrc)); +} + +SkeletonResource* ResourceContext::AddSkeletonResource(StringCrc nameCrc) +{ + return static_cast(AddResourceImpl(nameCrc)); +} + TextureResource* ResourceContext::AddTextureResource(StringCrc nameCrc) { return static_cast(AddResourceImpl(nameCrc)); @@ -41,6 +53,11 @@ MeshResource* ResourceContext::GetMeshResource(StringCrc nameCrc) return static_cast(GetResourceImpl(nameCrc)); } +ShaderResource* ResourceContext::GetShaderResource(StringCrc nameCrc) +{ + return static_cast(GetResourceImpl(nameCrc)); +} + TextureResource* ResourceContext::GetTextureResource(StringCrc nameCrc) { return static_cast(GetResourceImpl(nameCrc)); @@ -60,10 +77,18 @@ IResource* ResourceContext::AddResourceImpl(StringCrc nameCrc) { m_resources[resourceCrc] = std::make_unique(); } + else if constexpr (ResourceType::Shader == RT) + { + m_resources[resourceCrc] = std::make_unique(); + } else if constexpr (ResourceType::Texture == RT) { m_resources[resourceCrc] = std::make_unique(); } + else if constexpr (ResourceType::Skeleton == RT) + { + m_resources[resourceCrc] = std::make_unique(); + } auto* pResource = m_resources[resourceCrc].get(); pResource->SetName(nameCrc); diff --git a/Engine/Source/Runtime/Rendering/Resources/ResourceContext.h b/Engine/Source/Runtime/Rendering/Resources/ResourceContext.h index 6cb0a0c7..9c320b4b 100644 --- a/Engine/Source/Runtime/Rendering/Resources/ResourceContext.h +++ b/Engine/Source/Runtime/Rendering/Resources/ResourceContext.h @@ -11,6 +11,8 @@ namespace engine enum class ResourceType; class IResource; class MeshResource; +class ShaderResource; +class SkeletonResource; class TextureResource; class ResourceContext @@ -28,8 +30,11 @@ class ResourceContext StringCrc GetResourceCrc(ResourceType resourceType, StringCrc nameCrc); MeshResource* AddMeshResource(StringCrc nameCrc); + ShaderResource* AddShaderResource(StringCrc nameCrc); + SkeletonResource* AddSkeletonResource(StringCrc nameCrc); TextureResource* AddTextureResource(StringCrc nameCrc); MeshResource* GetMeshResource(StringCrc nameCrc); + ShaderResource* GetShaderResource(StringCrc nameCrc); TextureResource* GetTextureResource(StringCrc nameCrc); private: diff --git a/Engine/Source/Runtime/Rendering/Resources/ShaderResource.cpp b/Engine/Source/Runtime/Rendering/Resources/ShaderResource.cpp new file mode 100644 index 00000000..d2e9d27a --- /dev/null +++ b/Engine/Source/Runtime/Rendering/Resources/ShaderResource.cpp @@ -0,0 +1,272 @@ +#include "ShaderResource.h" + +#include "Log/Log.h" +#include "Path/Path.h" +#include "Resources/ResourceLoader.h" + +#include + +#include + +namespace engine +{ + +ShaderResource::~ShaderResource() +{ + SetStatus(ResourceStatus::Garbage); + Update(); +} + +void ShaderResource::Update() +{ + switch (GetStatus()) + { + case ResourceStatus::Loading: + { + // TODO : Should integrate the "compiling shader sc file to bin file" process in ShaderResource::Update. + // For now, we just read the shader bin file. + + if (LoadShader()) + { + SetStatus(ResourceStatus::Loaded); + } + break; + } + case ResourceStatus::Loaded: + { + if (!m_shaders[0].binBlob.empty() && !(ShaderProgramType::Standard == m_type && m_shaders[1].binBlob.empty())) + { + // It seems no Rendering data for shader? Skip Building status. + SetStatus(ResourceStatus::Built); + } + break; + } + case ResourceStatus::Building: + { + SetStatus(ResourceStatus::Built); + break; + } + case ResourceStatus::Built: + { + // Build GPU handles + if (BuildShaderHandle() && BuildProgramHandle()) + { + m_recycleCount = 0U; + SetStatus(ResourceStatus::Ready); + } + break; + } + case ResourceStatus::Ready: + { + // Delete CPU data delayed + constexpr uint32_t recycleDelayFrames = 30U; + if (m_recycleCount++ >= recycleDelayFrames) + { + FreeShaderData(0); + FreeShaderData(1); + + m_recycleCount = 0U; + SetStatus(ResourceStatus::Optimized); + } + break; + } + case ResourceStatus::Garbage: + { + // Distory GPU handles + DistoryShaderHandle(0); + DistoryShaderHandle(1); + DistoryProgramHandle(); + SetStatus(ResourceStatus::Destroyed); + break; + } + default: + break; + } +} +void ShaderResource::Reset() +{ + ClearShaderData(0); + ClearShaderData(1); + DistoryShaderHandle(0); + DistoryShaderHandle(1); + DistoryProgramHandle(); + SetStatus(ResourceStatus::Loading); +} + +void ShaderResource::SetShaders(const std::string& vsName, const std::string& fsName, const std::string& combine) +{ + assert(ShaderProgramType::Standard == m_type); + + m_shaders[0].type = ShaderType::Vertex; + m_shaders[0].name = vsName; + m_shaders[0].scPath = engine::Path::GetBuiltinShaderInputPath(vsName.c_str()); + m_shaders[0].binPath = engine::Path::GetShaderOutputPath(vsName.c_str(), combine); + + m_shaders[1].type = ShaderType::Fragment; + m_shaders[1].name = fsName; + m_shaders[1].scPath = engine::Path::GetBuiltinShaderInputPath(fsName.c_str()); + m_shaders[1].binPath = engine::Path::GetShaderOutputPath(fsName.c_str(), combine); + + m_featuresCombine = combine; +} + +void ShaderResource::SetShader(ShaderType type, const std::string& name, const std::string& combine) +{ + assert(ShaderProgramType::Standard != m_type); + + m_shaders[0].type = type; + m_shaders[0].name = name; + m_shaders[0].scPath = engine::Path::GetBuiltinShaderInputPath(name.c_str()); + m_shaders[0].binPath = engine::Path::GetShaderOutputPath(name.c_str(), combine); + + m_featuresCombine = combine; +} + +void ShaderResource::SetShaderInfo(ShaderInfo info, size_t index) +{ + CheckIndex(index); + m_shaders[index] = cd::MoveTemp(info); +} + +ShaderResource::ShaderInfo& ShaderResource::GetShaderInfo(size_t index) +{ + CheckIndex(index); + return m_shaders[index]; +} + +const ShaderResource::ShaderInfo& ShaderResource::GetShaderInfo(size_t index) const +{ + CheckIndex(index); + return m_shaders[index]; +} + +bool ShaderResource::LoadShader() +{ + auto& shader = m_shaders[0]; + if (!Path::FileExists(shader.binPath.c_str())) + { + return false; + } + shader.binBlob = engine::ResourceLoader::LoadFile(shader.binPath.c_str()); + + if (ShaderProgramType::Standard == m_type) + { + auto& fragmentShader = m_shaders[1]; + if (!Path::FileExists(fragmentShader.binPath.c_str())) + { + ClearShaderData(0); + return false; + } + fragmentShader.binBlob = engine::ResourceLoader::LoadFile(fragmentShader.binPath.c_str()); + } + + return true; +} + +bool ShaderResource::BuildShaderHandle() +{ + if (m_shaders[0].binBlob.empty()) + { + return false; + } + + assert(!bgfx::isValid(bgfx::ShaderHandle{ m_shaders[0].handle })); + bgfx::ShaderHandle handle = bgfx::createShader(bgfx::makeRef(m_shaders[0].binBlob.data(), static_cast(m_shaders[0].binBlob.size()))); + if (!bgfx::isValid(handle)) + { + ClearShaderData(0); + return false; + } + m_shaders[0].handle = handle.idx; + + if (ShaderProgramType::Standard == m_type) + { + if (m_shaders[1].binBlob.empty()) + { + ClearShaderData(0); + DistoryShaderHandle(0); + return false; + } + + assert(!bgfx::isValid(bgfx::ShaderHandle{ m_shaders[1].handle })); + bgfx::ShaderHandle fragmentShaderHandle = bgfx::createShader(bgfx::makeRef(m_shaders[1].binBlob.data(), static_cast(m_shaders[1].binBlob.size()))); + if (!bgfx::isValid(fragmentShaderHandle)) + { + ClearShaderData(0); + ClearShaderData(1); + DistoryShaderHandle(0); + return false; + } + m_shaders[1].handle = fragmentShaderHandle.idx; + } + + return true; +} + +bool ShaderResource::BuildProgramHandle() +{ + assert(!bgfx::isValid(bgfx::ProgramHandle{ m_programHandle })); + + if (ShaderProgramType::Standard == m_type) + { + m_programHandle = bgfx::createProgram(bgfx::ShaderHandle{ m_shaders[0].handle }, bgfx::ShaderHandle{ m_shaders[1].handle }).idx; + } + else if (ShaderProgramType::Compute == m_type || ShaderProgramType::VertexOnly == m_type) + { + m_programHandle = bgfx::createProgram(bgfx::ShaderHandle{ m_shaders[0].handle }).idx; + } + else + { + CD_WARN("Unknow shader program type of {}!", m_name); + } + + if (!bgfx::isValid(bgfx::ProgramHandle{ m_programHandle })) + { + return false; + } + + return true; +} + +void ShaderResource::ClearShaderData(size_t index) +{ + m_shaders[index].binBlob.clear(); +} + +void ShaderResource::FreeShaderData(size_t index) +{ + ClearShaderData(index); + ShaderBlob().swap(m_shaders[index].binBlob); +} + +void ShaderResource::DistoryShaderHandle(size_t index) +{ + if (bgfx::isValid(bgfx::ShaderHandle{ m_shaders[index].handle })) + { + bgfx::destroy(bgfx::ShaderHandle{ m_shaders[index].handle }); + m_shaders[index].handle = bgfx::kInvalidHandle; + } +} + +void ShaderResource::DistoryProgramHandle() +{ + if (bgfx::isValid(bgfx::ProgramHandle{ m_programHandle })) + { + bgfx::destroy(bgfx::ProgramHandle{ m_programHandle }); + m_programHandle = bgfx::kInvalidHandle; + } +} + +void ShaderResource::CheckIndex(size_t index) const +{ + if (ShaderProgramType::Standard == m_type) + { + assert(index <= 1); + } + else + { + assert(index == 0); + } +} + +} \ No newline at end of file diff --git a/Engine/Source/Runtime/Rendering/Resources/ShaderResource.h b/Engine/Source/Runtime/Rendering/Resources/ShaderResource.h new file mode 100644 index 00000000..5134cced --- /dev/null +++ b/Engine/Source/Runtime/Rendering/Resources/ShaderResource.h @@ -0,0 +1,90 @@ +#pragma once + +#include "Base/Template.h" +#include "IResource.h" +#include "Rendering/ShaderType.h" + +#include +#include + +namespace engine +{ + +class ShaderResource : public IResource +{ +public: + using ShaderBlob = std::vector; + + struct ShaderInfo + { + ShaderType type; + // Name without shader frature. + std::string name; + std::string scPath; + // Should be the path to a specific variant file. + std::string binPath; + + ShaderBlob binBlob; + uint16_t handle = UINT16_MAX; + }; + +public: + ShaderResource() = default; + ShaderResource(const ShaderResource&) = default; + ShaderResource& operator=(const ShaderResource&) = default; + ShaderResource(ShaderResource&&) = default; + ShaderResource& operator=(ShaderResource&&) = default; + virtual ~ShaderResource(); + + virtual void Update() override; + virtual void Reset() override; + + void SetShaders(const std::string& vsName, const std::string& fsName, const std::string& combine = ""); + void SetShader(ShaderType type, const std::string& name, const std::string& combine = ""); + + void SetShaderInfo(ShaderInfo info, size_t index); + ShaderInfo& GetShaderInfo(size_t index); + const ShaderInfo& GetShaderInfo(size_t index) const; + + void SetActive(bool active) { m_active = active; } + bool IsActive() const { return m_active; } + + void SetName(std::string name) { m_name = cd::MoveTemp(name); } + std::string& GetName() { return m_name; } + const std::string& GetName() const { return m_name; } + + ShaderProgramType GetType() const { return m_type; } + void SetType(ShaderProgramType type) { m_type = type; } + + void SetFeaturesCombine(std::string combine) { m_featuresCombine = cd::MoveTemp(combine); } + std::string& GetFeaturesCombine() { return m_featuresCombine; } + const std::string& GetFeaturesCombine() const { return m_featuresCombine; } + + uint16_t GetHandle() const { return m_programHandle; } + +private: + bool LoadShader(); + bool BuildShaderHandle(); + bool BuildProgramHandle(); + + void ClearShaderData(size_t index); + void FreeShaderData(size_t index); + void DistoryShaderHandle(size_t index); + void DistoryProgramHandle(); + + void CheckIndex(size_t index) const; + + ShaderInfo m_shaders[2]; + + // Runtime + bool m_active = false; + std::string m_name; + ShaderProgramType m_type = ShaderProgramType::None; + std::string m_featuresCombine; + uint32_t m_recycleCount = 0; + + // GPU + uint16_t m_programHandle = UINT16_MAX; +}; + +} \ No newline at end of file diff --git a/Engine/Source/Runtime/Rendering/Resources/SkeletonResource.cpp b/Engine/Source/Runtime/Rendering/Resources/SkeletonResource.cpp new file mode 100644 index 00000000..7e511754 --- /dev/null +++ b/Engine/Source/Runtime/Rendering/Resources/SkeletonResource.cpp @@ -0,0 +1,212 @@ +#include "SkeletonResource.h" + +#include "Log/Log.h" +#include "Rendering/Utility/VertexLayoutUtility.h" +#include "Utilities/MeshUtils.hpp" + +namespace details +{ + +void TraverseBone(const cd::Bone& bone, const cd::SceneDatabase* pSceneDatabase, std::byte* currentDataPtr, + std::byte* currentIndexPtr, uint32_t& vertexOffset, uint32_t& indexOffset) +{ + constexpr uint32_t posDataSize = cd::Point::Size * sizeof(cd::Point::ValueType); + constexpr uint32_t indexDataSize = sizeof(uint16_t); + for (auto& child : bone.GetChildIDs()) + { + const cd::Bone& currBone = pSceneDatabase->GetBone(child.Data()); + cd::Vec3f translate = currBone.GetOffset().Inverse().GetTranslation(); + + uint16_t parentID = currBone.GetParentID().Data(); + uint16_t currBoneID = currBone.GetID().Data(); + uint16_t selectedBoneIndex[4] = { currBoneID, currBoneID, currBoneID, currBoneID }; + std::vector vertexBoneIndexes; + vertexBoneIndexes.resize(4, 0U); + vertexBoneIndexes[0] = currBoneID; + std::memcpy(¤tDataPtr[vertexOffset], translate.begin(), posDataSize); + vertexOffset += posDataSize; + std::memcpy(¤tDataPtr[vertexOffset], selectedBoneIndex, static_cast(4 * sizeof(uint16_t))); + vertexOffset += static_cast(4 * sizeof(uint16_t)); + std::memcpy(¤tIndexPtr[indexOffset], &parentID, indexDataSize); + indexOffset += indexDataSize; + std::memcpy(¤tIndexPtr[indexOffset], &currBoneID, indexDataSize); + indexOffset += indexDataSize; + + TraverseBone(currBone, pSceneDatabase, currentDataPtr, currentIndexPtr, vertexOffset, indexOffset); + } +} + +} + +namespace engine +{ + +SkeletonResource::SkeletonResource() = default; + +SkeletonResource::~SkeletonResource() +{ + // Collect garbage intermediatly. + //SetStatus(ResourceStatus::Garbage); + //Update(); +} + + +void SkeletonResource::Update() +{ + switch (GetStatus()) + { + case ResourceStatus::Loading: + { + if (m_pSceneDatabase) + { + m_boneCount = m_pSceneDatabase->GetBoneCount(); + SetStatus(ResourceStatus::Loaded); + } + break; + } + case ResourceStatus::Loaded: + { + if (m_boneCount > 0U) + { + SetStatus(ResourceStatus::Building); + } + SetStatus(ResourceStatus::Building); + break; + } + case ResourceStatus::Building: + { + BuildSkeletonBuffer(); + SetStatus(ResourceStatus::Built); + break; + } + case ResourceStatus::Built: + { + SubmitVertexBuffer(); + SubmitIndexBuffer(); + m_recycleCount = 0U; + SetStatus(ResourceStatus::Ready); + break; + } + case ResourceStatus::Ready: + { + // Release CPU data later to save memory. + constexpr uint32_t recycleDelayFrames = 30U; + if (m_recycleCount++ >= recycleDelayFrames) + { + FreeSkeletonData(); + SetStatus(ResourceStatus::Optimized); + } + break; + } + case ResourceStatus::Garbage: + { + DestroyVertexBufferHandle(); + DestroyIndexBufferHandle(); + // CPU data will destroy after deconstructor. + SetStatus(ResourceStatus::Destroyed); + break; + } + default: + break; + } +} + +void SkeletonResource::Reset() +{ + DestroyVertexBufferHandle(); + DestroyIndexBufferHandle(); + ClearSkeletonData(); + SetStatus(ResourceStatus::Loading); +} + +void SkeletonResource::BuildSkeletonBuffer() +{ + constexpr uint32_t indexTypeSize = static_cast(sizeof(uint16_t)); + constexpr uint32_t posDataSize = cd::Point::Size * sizeof(cd::Point::ValueType); + m_currentVertexFormat.AddVertexAttributeLayout(cd::VertexAttributeType::Position, cd::AttributeValueType::Float, 3); + m_currentVertexFormat.AddVertexAttributeLayout(cd::VertexAttributeType::BoneIndex, cd::AttributeValueType::Int16, 4U); + m_indexBuffer.resize((m_boneCount - 1) * 2 * indexTypeSize); + m_vertexBuffer.resize(m_boneCount * m_currentVertexFormat.GetStride()); + + uint32_t vbDataSize = 0U; + uint32_t ibDataSize = 0U; + + auto vbDataPtr = m_vertexBuffer.data(); + const cd::Point& position = m_pSceneDatabase->GetBone(0).GetTransform().GetTranslation(); + std::memcpy(&vbDataPtr[vbDataSize], position.begin(), posDataSize); + vbDataSize += posDataSize; + //std::vector vertexBoneIndexes; + uint16_t selectedBoneIndex[4] = { 0U, 0U, 0U, 0U }; + //vertexBoneIndexes.resize(4, 0U); + //vertexBoneIndexes[0] = 0U; + //uint16_t first = 0; + std::memcpy(&vbDataPtr[vbDataSize], selectedBoneIndex, static_cast(4 * sizeof(uint16_t))); + vbDataSize += static_cast(4 * sizeof(uint16_t)); + + details::TraverseBone(m_pSceneDatabase->GetBone(0), m_pSceneDatabase, m_vertexBuffer.data(), m_indexBuffer.data(), vbDataSize, ibDataSize); +} + +void SkeletonResource::SubmitVertexBuffer() +{ + if (m_vertexBufferHandle != UINT16_MAX) + { + return; + } + + bgfx::VertexLayout vertexLayout; + engine::VertexLayoutUtility::CreateVertexLayout(vertexLayout, m_currentVertexFormat.GetVertexAttributeLayouts()); + const bgfx::Memory* pVertexBufferRef = bgfx::makeRef(m_vertexBuffer.data(), static_cast(m_vertexBuffer.size())); + bgfx::VertexBufferHandle vertexBufferHandle = bgfx::createVertexBuffer(pVertexBufferRef, vertexLayout); + assert(bgfx::isValid(vertexBufferHandle)); + m_vertexBufferHandle = vertexBufferHandle.idx; +} + +void SkeletonResource::SubmitIndexBuffer() +{ + if (m_indexBufferHandle != UINT16_MAX) + { + return; + } + + const auto& indexBuffer = m_indexBuffer; + assert(!m_indexBuffer.empty()); + const bgfx::Memory* pIndexBufferRef = bgfx::makeRef(indexBuffer.data(), static_cast(indexBuffer.size())); + + bgfx::IndexBufferHandle indexBufferHandle = bgfx::createIndexBuffer(pIndexBufferRef); + assert(bgfx::isValid(indexBufferHandle)); + m_indexBufferHandle = indexBufferHandle.idx; +} + +void SkeletonResource::ClearSkeletonData() +{ + m_vertexBuffer.clear(); + m_indexBuffer.clear(); +} + +void SkeletonResource::FreeSkeletonData() +{ + //ClearSkeletonData(); + //VertexBuffer().swap(m_vertexBuffer); + //IndexBuffer().swap(m_indexBuffer); +} + +void SkeletonResource::DestroyVertexBufferHandle() +{ + if (m_vertexBufferHandle != UINT16_MAX) + { + bgfx::destroy(bgfx::VertexBufferHandle{ m_vertexBufferHandle }); + m_vertexBufferHandle = UINT16_MAX; + } +} + +void SkeletonResource::DestroyIndexBufferHandle() +{ + if (m_indexBufferHandle != UINT16_MAX) + { + bgfx::destroy(bgfx::IndexBufferHandle{ m_indexBufferHandle }); + m_indexBufferHandle = UINT16_MAX; + } + +} + +} \ No newline at end of file diff --git a/Engine/Source/Runtime/Rendering/Resources/SkeletonResource.h b/Engine/Source/Runtime/Rendering/Resources/SkeletonResource.h new file mode 100644 index 00000000..08792546 --- /dev/null +++ b/Engine/Source/Runtime/Rendering/Resources/SkeletonResource.h @@ -0,0 +1,68 @@ +#pragma once + +#include "IResource.h" +#include "Scene/SceneDatabase.h" + +#include + +namespace cd +{ + +class Bone; + +} + +namespace engine +{ + +class SkeletonResource : public IResource +{ +public: + using VertexBuffer = std::vector; + using IndexBuffer = std::vector; + +public: + SkeletonResource(); + SkeletonResource(const SkeletonResource&) = default; + SkeletonResource& operator=(const SkeletonResource&) = default; + SkeletonResource(SkeletonResource&&) = default; + SkeletonResource& operator=(SkeletonResource&&) = default; + virtual ~SkeletonResource(); + + virtual void Update() override; + virtual void Reset() override; + + void SetSceneDataBase(const cd::SceneDatabase* pSceneDataBase) {m_pSceneDatabase = pSceneDataBase; m_boneCount = m_pSceneDatabase->GetBoneCount();} + + uint32_t GetBoneCount() const { return m_boneCount; } + uint16_t GetVertexBufferHandle() const { return m_vertexBufferHandle; } + uint16_t GetIndexBufferHandle() const { return m_indexBufferHandle; } + +private: + void BuildSkeletonBuffer(); + void SubmitVertexBuffer(); + void SubmitIndexBuffer(); + void ClearSkeletonData(); + void FreeSkeletonData(); + void DestroyVertexBufferHandle(); + void DestroyIndexBufferHandle(); + +private: + // Asset + const cd::SceneDatabase* m_pSceneDatabase; + uint32_t m_boneCount = 0U; + + // Runtime + cd::VertexFormat m_currentVertexFormat; + + // CPU + VertexBuffer m_vertexBuffer; + IndexBuffer m_indexBuffer; + uint32_t m_recycleCount = 0; + + // GPU + uint16_t m_vertexBufferHandle = UINT16_MAX; + uint16_t m_indexBufferHandle = UINT16_MAX; +}; + +} \ No newline at end of file diff --git a/Engine/Source/Runtime/Rendering/Resources/TextureResource.cpp b/Engine/Source/Runtime/Rendering/Resources/TextureResource.cpp index 8e2aee8c..f3637956 100644 --- a/Engine/Source/Runtime/Rendering/Resources/TextureResource.cpp +++ b/Engine/Source/Runtime/Rendering/Resources/TextureResource.cpp @@ -128,7 +128,7 @@ void TextureResource::Update() constexpr uint32_t recycleDelayFrames = 30U; if (m_recycleCount++ >= recycleDelayFrames) { - FreeTextureData(); + ClearTextureData(); m_recycleCount = 0U; SetStatus(ResourceStatus::Optimized); @@ -213,10 +213,9 @@ void TextureResource::BuildTextureHandle() assert(m_textureHandle != UINT16_MAX); } -void TextureResource::FreeTextureData() +void TextureResource::ClearTextureData() { m_textureRawData.clear(); - if (m_textureImageData) { auto* pImageContainer = reinterpret_cast(m_textureImageData); @@ -225,6 +224,12 @@ void TextureResource::FreeTextureData() } } +void TextureResource::FreeTextureData() +{ + ClearTextureData(); + TextureRawData().swap(m_textureRawData); +} + void TextureResource::DestroySamplerHandle() { if (m_samplerHandle != UINT16_MAX) diff --git a/Engine/Source/Runtime/Rendering/Resources/TextureResource.h b/Engine/Source/Runtime/Rendering/Resources/TextureResource.h index d5df475c..f4d20694 100644 --- a/Engine/Source/Runtime/Rendering/Resources/TextureResource.h +++ b/Engine/Source/Runtime/Rendering/Resources/TextureResource.h @@ -51,6 +51,7 @@ class TextureResource : public IResource void BuildSamplerHandle(); void BuildTextureHandle(); + void ClearTextureData(); void FreeTextureData(); void DestroySamplerHandle(); diff --git a/Engine/Source/Runtime/Rendering/ShaderCollections.cpp b/Engine/Source/Runtime/Rendering/ShaderCollections.cpp deleted file mode 100644 index 947c3fc9..00000000 --- a/Engine/Source/Runtime/Rendering/ShaderCollections.cpp +++ /dev/null @@ -1,68 +0,0 @@ -#include "ShaderCollections.h" - -#include "Log/Log.h" - -#include - -namespace engine -{ - -void ShaderCollections::RegisterShaderProgram(StringCrc programNameCrc, std::initializer_list names) -{ - if (IsProgramValid(programNameCrc) || HasFeatureCombine(programNameCrc)) - { - return; - } - - m_shaderPrograms[programNameCrc] = cd::MoveTemp(names); -} - -void ShaderCollections::AddFeatureCombine(StringCrc programNameCrc, std::string combine) -{ - assert(IsProgramValid(programNameCrc) && "Shader program does not exist!"); - - m_programFeatureCombines[programNameCrc].insert(cd::MoveTemp(combine)); -} - -void ShaderCollections::DeleteFeatureCombine(StringCrc programNameCrc, std::string combine) -{ - assert(HasFeatureCombine(programNameCrc) && "Feature combine does not exist!"); - - m_programFeatureCombines[programNameCrc].erase(cd::MoveTemp(combine)); -} - -void ShaderCollections::SetShaders(StringCrc programNameCrc, std::set shaders) -{ - assert(IsProgramValid(programNameCrc) && "Shader program does not exist!"); - - m_shaderPrograms[programNameCrc] = cd::MoveTemp(shaders); -} - -void ShaderCollections::SetFeatureCombines(StringCrc programNameCrc, std::set combine) -{ - assert(IsProgramValid(programNameCrc) && "Shader program does not exist!"); - - m_programFeatureCombines[programNameCrc] = cd::MoveTemp(combine); -} - -bool ShaderCollections::IsProgramValid(StringCrc programNameCrc) const -{ - return (m_shaderPrograms.find(programNameCrc) != m_shaderPrograms.end()); -} - -bool ShaderCollections::HasFeatureCombine(StringCrc programNameCrc) const -{ - return (m_programFeatureCombines.find(programNameCrc) != m_programFeatureCombines.end()); -} - -void ShaderCollections::SetShaderPrograms(std::map> shaders) -{ - m_shaderPrograms = cd::MoveTemp(shaders); -} - -void ShaderCollections::SetProgramFeatureCombines(std::map> combines) -{ - m_programFeatureCombines = cd::MoveTemp(combines); -} - -} \ No newline at end of file diff --git a/Engine/Source/Runtime/Rendering/ShaderCollections.h b/Engine/Source/Runtime/Rendering/ShaderCollections.h deleted file mode 100644 index 8ee8429e..00000000 --- a/Engine/Source/Runtime/Rendering/ShaderCollections.h +++ /dev/null @@ -1,57 +0,0 @@ -#pragma once - -#include "Base/Template.h" -#include "Core/StringCrc.h" - -#include -#include -#include - -namespace engine -{ - -class ShaderCollections final -{ -public: - static constexpr uint16_t InvalidProgramHandle = UINT16_MAX; - -public: - ShaderCollections() = default; - ShaderCollections(const ShaderCollections&) = default; - ShaderCollections& operator=(const ShaderCollections&) = default; - ShaderCollections(ShaderCollections&&) = default; - ShaderCollections& operator=(ShaderCollections&&) = default; - ~ShaderCollections() = default; - - void RegisterShaderProgram(StringCrc programNameCrc, std::initializer_list names); - - void AddFeatureCombine(StringCrc programNameCrc, std::string combine); - void DeleteFeatureCombine(StringCrc programNameCrc, std::string combine); - - void SetShaders(StringCrc programNameCrc, std::set shaders); - std::set& GetShaders(StringCrc programNameCrc) { return m_shaderPrograms[programNameCrc]; } - const std::set& GetShaders(StringCrc programNameCrc) const { return m_shaderPrograms.at(programNameCrc); } - - void SetFeatureCombines(StringCrc programNameCrc, std::set combine); - std::set& GetFeatureCombines(StringCrc programNameCrc) { return m_programFeatureCombines[programNameCrc]; } - const std::set& GetFeatureCombines(StringCrc programNameCrc) const { return m_programFeatureCombines.at(programNameCrc); } - - bool IsProgramValid(StringCrc programNameCrc) const; - bool HasFeatureCombine(StringCrc programNameCrc) const; - - void SetShaderPrograms(std::map> shaders); - std::map>& GetShaderPrograms() { return m_shaderPrograms; } - const std::map>& GetShaderPrograms() const { return m_shaderPrograms; } - - void SetProgramFeatureCombines(std::map> combines); - std::map>& GetProgramFeatureCombines() { return m_programFeatureCombines; } - const std::map>& GetProgramFeatureCombiness() const { return m_programFeatureCombines; } - -private: - // Key : Program name, Value : Shader names - std::map> m_shaderPrograms; - // Key : Program name, Value : Feature combines used as a parameter for compiling shaders - std::map> m_programFeatureCombines; -}; - -} \ No newline at end of file diff --git a/Engine/Source/Runtime/Rendering/ShaderCompileInfo.h b/Engine/Source/Runtime/Rendering/ShaderCompileInfo.h deleted file mode 100644 index 1ece2c39..00000000 --- a/Engine/Source/Runtime/Rendering/ShaderCompileInfo.h +++ /dev/null @@ -1,58 +0,0 @@ -#pragma once - -#include "Base/Template.h" -#include "ECWorld/Entity.h" - -#include -#include - -namespace engine -{ - -class ShaderCompileInfo -{ -public: - ShaderCompileInfo(Entity entity, std::string name, std::string combine = "") : - m_entity(entity), m_programName(cd::MoveTemp(name)), m_featuresCombine(cd::MoveTemp(combine)) {} - ShaderCompileInfo() = delete; - ShaderCompileInfo(const ShaderCompileInfo&) = default; - ShaderCompileInfo& operator=(const ShaderCompileInfo&) = default; - ShaderCompileInfo(ShaderCompileInfo&&) = default; - ShaderCompileInfo& operator=(ShaderCompileInfo&&) = default; - ~ShaderCompileInfo() = default; - - Entity m_entity = INVALID_ENTITY; - std::string m_programName; - std::string m_featuresCombine; - std::set m_taskHandles; - - bool operator==(const ShaderCompileInfo& other) const - { - return (m_entity == other.m_entity) && (m_programName == other.m_programName) && (m_featuresCombine == other.m_featuresCombine); - } - - bool operator<(const ShaderCompileInfo& other) const - { - if (m_entity < other.m_entity) - { - return true; - } - if (m_entity > other.m_entity) - { - return false; - } - - if (m_programName < other.m_programName) - { - return true; - } - if (m_programName > other.m_programName) - { - return false; - } - - return m_featuresCombine < other.m_featuresCombine; - } -}; - -} \ No newline at end of file diff --git a/Engine/Source/Runtime/Rendering/ShaderFeature.h b/Engine/Source/Runtime/Rendering/ShaderFeature.h index c91ba474..d63321c5 100644 --- a/Engine/Source/Runtime/Rendering/ShaderFeature.h +++ b/Engine/Source/Runtime/Rendering/ShaderFeature.h @@ -46,7 +46,7 @@ constexpr const char* ShaderFeatureNames[] = static_assert(static_cast(ShaderFeature::COUNT) == sizeof(ShaderFeatureNames) / sizeof(char*), "Shader features and names mismatch."); -CD_FORCEINLINE constexpr const char* GetFeatureName(ShaderFeature feature) +constexpr const char* GetFeatureName(ShaderFeature feature) { return ShaderFeatureNames[static_cast(feature)]; } diff --git a/Engine/Source/Runtime/Rendering/ShaderType.h b/Engine/Source/Runtime/Rendering/ShaderType.h index a13f5a00..85c68ea7 100644 --- a/Engine/Source/Runtime/Rendering/ShaderType.h +++ b/Engine/Source/Runtime/Rendering/ShaderType.h @@ -2,6 +2,7 @@ #include "base/Platform.h" +#include #include namespace engine @@ -10,12 +11,25 @@ namespace engine enum class ShaderType { None, - Compute, Vertex, - Fragment + Fragment, + Compute, +}; + +enum class ShaderProgramType +{ + None, + Standard, + VertexOnly, + Compute, +}; + +inline const std::map ProgramTypeToSingleShaderType = { + { ShaderProgramType::VertexOnly, ShaderType::Vertex }, + { ShaderProgramType::Compute, ShaderType::Compute }, }; -CD_FORCEINLINE static const ShaderType GetShaderType(const std::string& fileName) +inline ShaderType GetShaderType(const std::string& fileName) { if (fileName._Starts_with("vs_") || fileName._Starts_with("VS_")) { diff --git a/Engine/Source/Runtime/Rendering/ShadowMapRenderer.cpp b/Engine/Source/Runtime/Rendering/ShadowMapRenderer.cpp index 2bc7dddf..705aee72 100644 --- a/Engine/Source/Runtime/Rendering/ShadowMapRenderer.cpp +++ b/Engine/Source/Runtime/Rendering/ShadowMapRenderer.cpp @@ -1,15 +1,16 @@ #include "ShadowMapRenderer.h" #include "ECWorld/CameraComponent.h" +#include "ECWorld/LightComponent.h" #include "ECWorld/SceneWorld.h" #include "ECWorld/StaticMeshComponent.h" #include "ECWorld/TransformComponent.h" -#include "ECWorld/LightComponent.h" #include "LightUniforms.h" #include "Material/ShaderSchema.h" #include "Math/Transform.hpp" #include "Rendering/RenderContext.h" #include "Rendering/Resources/MeshResource.h" +#include "Rendering/Resources/ShaderResource.h" #include @@ -18,18 +19,16 @@ namespace engine namespace { -// uniform name -constexpr const char* cameraPos = "u_cameraPos"; -constexpr const char* lightCountAndStride = "u_lightCountAndStride"; -constexpr const char* lightParams = "u_lightParams"; -constexpr const char* lightPosAndFarPlane = "u_lightWorldPos_farPlane"; -constexpr const char* lightDir = "u_LightDir"; + +constexpr const char* cameraPos = "u_cameraPos"; +constexpr const char* lightCountAndStride = "u_lightCountAndStride"; +constexpr const char* lightParams = "u_lightParams"; +constexpr const char* lightPosAndFarPlane = "u_lightWorldPos_farPlane"; +constexpr const char* lightDir = "u_LightDir"; constexpr const char* heightOffsetAndshadowLength = "u_HeightOffsetAndshadowLength"; -// constexpr uint64_t samplerFlags = BGFX_SAMPLER_U_CLAMP | BGFX_SAMPLER_V_CLAMP | BGFX_SAMPLER_W_CLAMP; -constexpr uint64_t defaultRenderingState = BGFX_STATE_WRITE_RGB | BGFX_STATE_WRITE_A | BGFX_STATE_WRITE_Z -| BGFX_STATE_WRITE_MASK | BGFX_STATE_MSAA | BGFX_STATE_DEPTH_TEST_LESS; +constexpr uint64_t defaultRenderingState = BGFX_STATE_WRITE_RGB | BGFX_STATE_WRITE_A | BGFX_STATE_WRITE_Z | BGFX_STATE_WRITE_MASK | BGFX_STATE_MSAA | BGFX_STATE_DEPTH_TEST_LESS; constexpr uint64_t depthBufferFlags = BGFX_TEXTURE_RT | BGFX_SAMPLER_COMPARE_LEQUAL; constexpr uint64_t linearDepthBufferFlags = BGFX_TEXTURE_RT | BGFX_SAMPLER_U_CLAMP | BGFX_SAMPLER_V_CLAMP; @@ -37,10 +36,8 @@ constexpr uint64_t linearDepthBufferFlags = BGFX_TEXTURE_RT | BGFX_SAMPLER_U_CLA void ShadowMapRenderer::Init() { - constexpr StringCrc shadowMapProgramCrc = StringCrc("ShadowMapProgram"); - GetRenderContext()->RegisterShaderProgram(shadowMapProgramCrc, { "vs_shadowMap", "fs_shadowMap" }); - constexpr StringCrc linearshadowMapProgramCrc = StringCrc("LinearShadowMapProgram"); - GetRenderContext()->RegisterShaderProgram(linearshadowMapProgramCrc, { "vs_shadowMap", "fs_shadowMap_linear" }); + AddDependentShaderResource(GetRenderContext()->RegisterShaderProgram("ShadowMapProgram", "vs_shadowMap", "fs_shadowMap")); + AddDependentShaderResource(GetRenderContext()->RegisterShaderProgram("LinearShadowMapProgram", "vs_shadowMap", "fs_shadowMap_linear")); for (int lightIndex = 0; lightIndex < shadowLightMaxNum; lightIndex++) { @@ -50,12 +47,7 @@ void ShadowMapRenderer::Init() bgfx::setViewName(m_renderPassID[lightIndex * shadowTexturePassMaxNum + mapId], "ShadowMapRenderer"); } } -} -void ShadowMapRenderer::Warmup() -{ - GetRenderContext()->UploadShaderProgram("ShadowMapProgram"); - GetRenderContext()->UploadShaderProgram("LinearShadowMapProgram"); GetRenderContext()->CreateUniform(lightPosAndFarPlane, bgfx::UniformType::Vec4, 1); } @@ -66,6 +58,15 @@ void ShadowMapRenderer::UpdateView(const float* pViewMatrix, const float* pProje void ShadowMapRenderer::Render(float deltaTime) { + for (const auto pResource : m_dependentShaderResources) + { + if (ResourceStatus::Ready != pResource->GetStatus() && + ResourceStatus::Optimized != pResource->GetStatus()) + { + return; + } + } + // TODO : Remove it. If every renderer need to submit camera related uniform, it should be done not inside Renderer class. const cd::Transform& cameraTransform = m_pCurrentSceneWorld->GetTransformComponent(m_pCurrentSceneWorld->GetMainCameraEntity())->GetTransform(); @@ -206,7 +207,7 @@ void ShadowMapRenderer::Render(float deltaTime) for (const auto& corner : cascadeFrustum) { const auto lightSpaceCorner = lightView * cd::Vec4f(corner.x(), corner.y(), corner.z(), 1.0); - minX = std::min(minX, lightSpaceCorner.x()); + minX = std::min(minX, lightSpaceCorner.x()); maxX = std::max(maxX, lightSpaceCorner.x()); minY = std::min(minY, lightSpaceCorner.y()); maxY = std::max(maxY, lightSpaceCorner.y()); @@ -229,7 +230,7 @@ void ShadowMapRenderer::Render(float deltaTime) cd::Matrix4x4 lightCSMViewProj = lightProjection * lightView; lightComponent->AddLightViewProjMatrix(lightCSMViewProj); - // Submit draw call (TODO : one pass MRT + // Submit draw call (TODO : one pass MRT for (Entity entity : m_pCurrentSceneWorld->GetMaterialEntities()) { // No mesh attached? @@ -258,7 +259,8 @@ void ShadowMapRenderer::Render(float deltaTime) } // Mesh - SubmitStaticMeshDrawCall(pMeshComponent, viewId, "ShadowMapProgram"); + constexpr StringCrc programHandleIndex{ "ShadowMapProgram" }; + SubmitStaticMeshDrawCall(pMeshComponent, viewId, programHandleIndex); } } } @@ -336,7 +338,8 @@ void ShadowMapRenderer::Render(float deltaTime) bgfx::setTransform(pTransformComponent->GetWorldMatrix().begin()); } - SubmitStaticMeshDrawCall(pMeshComponent, viewId, "LinearShadowMapProgram"); + constexpr StringCrc programHandleIndex{ "LinearShadowMapProgram" }; + SubmitStaticMeshDrawCall(pMeshComponent, viewId, programHandleIndex); } } } @@ -403,7 +406,8 @@ void ShadowMapRenderer::Render(float deltaTime) } // Mesh - SubmitStaticMeshDrawCall(pMeshComponent, viewId, "ShadowMapProgram"); + constexpr StringCrc programHandleIndex{ "ShadowMapProgram" }; + SubmitStaticMeshDrawCall(pMeshComponent, viewId, programHandleIndex); } } break; @@ -418,4 +422,4 @@ void ShadowMapRenderer::Render(float deltaTime) } } -} +} \ No newline at end of file diff --git a/Engine/Source/Runtime/Rendering/ShadowMapRenderer.h b/Engine/Source/Runtime/Rendering/ShadowMapRenderer.h index 567feba3..0f4a5db6 100644 --- a/Engine/Source/Runtime/Rendering/ShadowMapRenderer.h +++ b/Engine/Source/Runtime/Rendering/ShadowMapRenderer.h @@ -18,7 +18,6 @@ class ShadowMapRenderer final : public Renderer using Renderer::Renderer; virtual void Init() override; - virtual void Warmup() override; virtual void UpdateView(const float* pViewMatrix, const float* pProjectionMatrix) override; virtual void Render(float deltaTime) override; diff --git a/Engine/Source/Runtime/Rendering/SkeletonRenderer.cpp b/Engine/Source/Runtime/Rendering/SkeletonRenderer.cpp index 5cb6f9ed..9f43c110 100644 --- a/Engine/Source/Runtime/Rendering/SkeletonRenderer.cpp +++ b/Engine/Source/Runtime/Rendering/SkeletonRenderer.cpp @@ -2,9 +2,11 @@ #include "Core/StringCrc.h" #include "ECWorld/SceneWorld.h" +#include "ECWorld/SkinMeshComponent.h" #include "ECWorld/TransformComponent.h" #include "Rendering/RenderContext.h" #include "Rendering/Utility/VertexLayoutUtility.h" +#include "Rendering/Resources/ShaderResource.h" namespace engine { @@ -12,9 +14,136 @@ namespace engine namespace details { -constexpr uint32_t posDataSize = cd::Point::Size * sizeof(cd::Point::ValueType); +float CustomFMod(float dividend, float divisor) +{ + if (divisor == 0.0f) + { + return 0.0f; + } + + int quotient = static_cast(dividend / divisor); + float result = dividend - static_cast(quotient) * divisor; + + if (result == 0.0f && dividend != 0.0f) + { + result = 0.0f; + } + if ((dividend < 0 && divisor > 0) || (dividend > 0 && divisor < 0)) + { + result = -result; + } + return result; +} + +void CalculateTransform(std::vector& boneMatrices, const cd::SceneDatabase* pSceneDatabase, + float animationTime, const cd::Bone& bone, const char* clipName, SkeletonComponent* pSkeletonConponent, cd::Matrix4x4& curGlobalDeltaMatrix, float deltaTime, bool isPlaying) +{ + auto CalculateInterpolatedTranslation = [&animationTime](const cd::Track* pTrack) -> cd::Vec3f + { + if (1U == pTrack->GetTranslationKeyCount()) + { + const auto& firstKey = pTrack->GetTranslationKeys()[0]; + return firstKey.GetValue(); + } + + for (uint32_t keyIndex = 0U; keyIndex < pTrack->GetTranslationKeyCount() - 1; ++keyIndex) + { + const auto& nextKey = pTrack->GetTranslationKeys()[keyIndex + 1]; + if (animationTime <= nextKey.GetTime()) + { + const auto& currentKey = pTrack->GetTranslationKeys()[keyIndex]; + float keyFrameDeltaTime = nextKey.GetTime() - currentKey.GetTime(); + float keyFrameRate = (animationTime - currentKey.GetTime()) / keyFrameDeltaTime; + assert(keyFrameRate >= 0.0f && keyFrameRate <= 1.0f); + + return cd::Vec3f::Lerp(currentKey.GetValue(), nextKey.GetValue(), keyFrameRate); + } -constexpr size_t indexTypeSize = sizeof(uint16_t); + } + const auto& Key = pTrack->GetTranslationKeys()[pTrack->GetTranslationKeyCount() - 1]; + return Key.GetValue(); + }; + + auto CalculateInterpolatedRotation = [&animationTime](const cd::Track* pTrack) -> cd::Quaternion + { + if (1U == pTrack->GetRotationKeyCount()) + { + const auto& firstKey = pTrack->GetRotationKeys()[0]; + return firstKey.GetValue(); + } + + for (uint32_t keyIndex = 0U; keyIndex < pTrack->GetRotationKeyCount() - 1; ++keyIndex) + { + const auto& nextKey = pTrack->GetRotationKeys()[keyIndex + 1]; + if (animationTime <= nextKey.GetTime()) + { + const auto& currentKey = pTrack->GetRotationKeys()[keyIndex]; + float keyFrameDeltaTime = nextKey.GetTime() - currentKey.GetTime(); + float keyFrameRate = (animationTime - currentKey.GetTime()) / keyFrameDeltaTime; + assert(keyFrameRate >= 0.0f && keyFrameRate <= 1.0f); + + return cd::Quaternion::SLerp(currentKey.GetValue(), nextKey.GetValue(), keyFrameRate).Normalize(); + } + } + const auto& Key = pTrack->GetRotationKeys()[pTrack->GetTranslationKeyCount() - 1]; + return Key.GetValue(); + }; + + auto CalculateInterpolatedScale = [&animationTime](const cd::Track* pTrack) -> cd::Vec3f + { + if (1U == pTrack->GetScaleKeyCount()) + { + const auto& firstKey = pTrack->GetScaleKeys()[0]; + return firstKey.GetValue(); + } + + for (uint32_t keyIndex = 0U; keyIndex < pTrack->GetScaleKeyCount() - 1; ++keyIndex) + { + const auto& nextKey = pTrack->GetScaleKeys()[keyIndex + 1]; + if (animationTime <= nextKey.GetTime()) + { + const auto& currentKey = pTrack->GetScaleKeys()[keyIndex]; + float keyFrameDeltaTime = nextKey.GetTime() - currentKey.GetTime(); + float keyFrameRate = (animationTime - currentKey.GetTime()) / keyFrameDeltaTime; + assert(keyFrameRate >= 0.0f && keyFrameRate <= 1.0f); + + return cd::Vec3f::Lerp(currentKey.GetValue(), nextKey.GetValue(), keyFrameRate); + } + } + + return cd::Vec3f::One(); + }; + static cd::Matrix4x4 transform = cd::Matrix4x4::Identity(); + + cd::Matrix4x4 curBoneGlobalMatrix = cd::Matrix4x4::Identity(); + if (const cd::Track* pTrack = pSceneDatabase->GetTrackByName((std::string(clipName) + bone.GetName()).c_str())) + { + if (0 == bone.GetID().Data()) + { + + transform = cd::Transform(CalculateInterpolatedTranslation(pTrack), + CalculateInterpolatedRotation(pTrack), + CalculateInterpolatedScale(pTrack)).GetMatrix(); + curBoneGlobalMatrix = transform; + pSkeletonConponent->SetBoneGlobalMatrix(bone.GetID().Data(), transform); + + } + else + { + curBoneGlobalMatrix = pSkeletonConponent->GetBoneGlobalMatrix(bone.GetParentID().Data()) * cd::Transform(CalculateInterpolatedTranslation(pTrack), + CalculateInterpolatedRotation(pTrack), + CalculateInterpolatedScale(pTrack)).GetMatrix(); + pSkeletonConponent->SetBoneGlobalMatrix(bone.GetID().Data(), curBoneGlobalMatrix); + } + } + + boneMatrices[bone.GetID().Data()] = curBoneGlobalMatrix * bone.GetOffset(); + for (cd::BoneID boneID : bone.GetChildIDs()) + { + const cd::Bone& childBone = pSceneDatabase->GetBone(boneID.Data()); + CalculateTransform(boneMatrices, pSceneDatabase, animationTime, childBone, clipName, pSkeletonConponent, curGlobalDeltaMatrix, deltaTime, isPlaying); + } +} cd::Vec3f CalculateBoneTranslate(const cd::Bone& bone, cd::Vec3f& translate, const cd::SceneDatabase* pSceneDatabase) { @@ -27,44 +156,156 @@ cd::Vec3f CalculateBoneTranslate(const cd::Bone& bone, cd::Vec3f& translate, con return translate; } -void TraverseBone(const cd::Bone& bone, const cd::SceneDatabase* pSceneDatabase, std::byte* currentDataPtr, - std::byte* currentIndexPtr, uint32_t& vertexOffset, uint32_t& indexOffset) +cd::Matrix4x4 CalculateInterpolationTransform(const cd::Track* pTrack, const float time) { - constexpr uint32_t posDataSize = cd::Point::Size * sizeof(cd::Point::ValueType); - for (auto& child : bone.GetChildIDs()) + cd::Vec3f localTranslate = cd::Vec3f::Zero(); + cd::Quaternion localRotation = cd::Quaternion::Identity(); + cd::Vec3f localScale = cd::Vec3f::One(); + if (1U == pTrack->GetTranslationKeyCount()) + { + const auto& firstKey = pTrack->GetTranslationKeys()[0]; + localTranslate = firstKey.GetValue(); + } + for (uint32_t keyIndex = 0U; keyIndex < pTrack->GetTranslationKeyCount() - 1; ++keyIndex) { - const cd::Bone& currBone = pSceneDatabase->GetBone(child.Data()); - const cd::Bone& parent = pSceneDatabase->GetBone(currBone.GetParentID().Data()); - cd::Vec3f translate = currBone.GetOffset().GetTranslation(); + const auto& nextKey = pTrack->GetTranslationKeys()[keyIndex + 1]; + if (time <= nextKey.GetTime()) + { + const auto& currentKey = pTrack->GetTranslationKeys()[keyIndex]; + float keyFrameDeltaTime = nextKey.GetTime() - currentKey.GetTime(); + float keyFrameRate = (time - currentKey.GetTime()) / keyFrameDeltaTime; + assert(keyFrameRate >= 0.0f && keyFrameRate <= 1.0f); - //const cd::Vec3f position = details::CalculateBoneTranslate(currBone, translate, pSceneDatabase); + localTranslate = cd::Vec3f::Lerp(currentKey.GetValue(), nextKey.GetValue(), keyFrameRate); + break; + } + const auto& translateKey = pTrack->GetTranslationKeys()[pTrack->GetTranslationKeyCount() - 1]; + localTranslate = translateKey.GetValue(); + } - uint16_t parentID = currBone.GetParentID().Data(); - uint16_t currBoneID = currBone.GetID().Data(); - std::memcpy(¤tDataPtr[vertexOffset], translate.begin(), posDataSize); - vertexOffset += posDataSize; - std::memcpy(¤tIndexPtr[indexOffset], &parentID, indexTypeSize); - indexOffset += static_cast(indexTypeSize); - std::memcpy(¤tIndexPtr[indexOffset], &currBoneID, indexTypeSize); - indexOffset += static_cast(indexTypeSize); - TraverseBone(currBone, pSceneDatabase, currentDataPtr, currentIndexPtr, vertexOffset, indexOffset); + if (1U == pTrack->GetRotationKeyCount()) + { + const auto& firstKey = pTrack->GetRotationKeys()[0]; + localRotation = firstKey.GetValue(); } -} + for (uint32_t keyIndex = 0U; keyIndex < pTrack->GetRotationKeyCount() - 1; ++keyIndex) + { + const auto& nextKey = pTrack->GetRotationKeys()[keyIndex + 1]; + if (time <= nextKey.GetTime()) + { + const auto& currentKey = pTrack->GetRotationKeys()[keyIndex]; + float keyFrameDeltaTime = nextKey.GetTime() - currentKey.GetTime(); + float keyFrameRate = (time - currentKey.GetTime()) / keyFrameDeltaTime; + assert(keyFrameRate >= 0.0f && keyFrameRate <= 1.0f); + + localRotation = cd::Quaternion::SLerp(currentKey.GetValue(), nextKey.GetValue(), keyFrameRate).Normalize(); + break; + } + const auto& rotationKey = pTrack->GetRotationKeys()[pTrack->GetTranslationKeyCount() - 1]; + localRotation = rotationKey.GetValue(); + } + + + if (1U == pTrack->GetScaleKeyCount()) + { + const auto& firstKey = pTrack->GetScaleKeys()[0]; + localScale = firstKey.GetValue(); + } + + for (uint32_t keyIndex = 0U; keyIndex < pTrack->GetScaleKeyCount() - 1; ++keyIndex) + { + const auto& nextKey = pTrack->GetScaleKeys()[keyIndex + 1]; + if (time <= nextKey.GetTime()) + { + const auto& currentKey = pTrack->GetScaleKeys()[keyIndex]; + float keyFrameDeltaTime = nextKey.GetTime() - currentKey.GetTime(); + float keyFrameRate = (time - currentKey.GetTime()) / keyFrameDeltaTime; + assert(keyFrameRate >= 0.0f && keyFrameRate <= 1.0f); + + localScale = cd::Vec3f::Lerp(currentKey.GetValue(), nextKey.GetValue(), keyFrameRate); + break; + } + localScale = cd::Vec3f::One(); + + } + return cd::Transform(localTranslate, localRotation, localScale).GetMatrix(); } -void SkeletonRenderer::Init() +void BlendTwoPos(std::vector& boneMatrices, const cd::SceneDatabase* pSceneDatabase, + float blendTimeProgress, const cd::Bone& bone, const char* clipAName, const char* clipBName, SkeletonComponent* pSkeletonComponent, cd::Matrix4x4& curGlobalDeltaMatrix, const cd::Matrix4x4 rootBoonTransform, const float factor) { - constexpr StringCrc programCrc = StringCrc("SkeletonProgram"); - GetRenderContext()->RegisterShaderProgram(programCrc, {"vs_AABB", "fs_AABB"}); + cd::Matrix4x4 localTransformA = cd::Matrix4x4::Identity(); + cd::Matrix4x4 localTransformB = cd::Matrix4x4::Identity(); + cd::Matrix4x4 curBoneGlobalMatrix = cd::Matrix4x4::Identity(); + float clipATime = pSceneDatabase->GetAnimation(0).GetDuration() * blendTimeProgress; + float clipBTime = pSceneDatabase->GetAnimation(1).GetDuration() * blendTimeProgress; + static float progress = 0.0f; + static cd::Matrix4x4 total = cd::Matrix4x4::Identity(); + static cd::Matrix4x4 lastMatrix = cd::Matrix4x4::Identity(); + const cd::Track* pTrackA = pSceneDatabase->GetTrackByName((std::string(clipAName) + bone.GetName()).c_str()); + if (const cd::Track* pTrackA = pSceneDatabase->GetTrackByName((std::string(clipAName) + bone.GetName()).c_str())) + { + localTransformA = CalculateInterpolationTransform(pTrackA, clipATime); + } + if (const cd::Track* pTrackB = pSceneDatabase->GetTrackByName((std::string(clipBName) + bone.GetName()).c_str())) + { + localTransformB = CalculateInterpolationTransform(pTrackB, clipBTime); + } + + cd::Vec3f translationBlend = cd::Vec3f::Lerp(localTransformA.GetTranslation(), localTransformB.GetTranslation(), factor); + cd::Quaternion rotationBlend = cd::Quaternion::SLerp(cd::Quaternion::FromMatrix(localTransformA.GetRotation()), cd::Quaternion::FromMatrix(localTransformB.GetRotation()), factor); + cd::Vec3f scaleBlend = cd::Vec3f::Lerp(localTransformA.GetScale(), localTransformB.GetScale(), factor); + cd::Matrix4x4 matrixBlend = cd::Transform(translationBlend, rotationBlend, scaleBlend).GetMatrix(); + cd::Matrix4x4 deltaGlobalTransform = cd::Matrix4x4::Identity(); + if (0 == bone.GetID().Data()) + { + //if (blendTimeProgress >= progress) + { + + curBoneGlobalMatrix = total * matrixBlend; + + pSkeletonComponent->SetRootMatrix(curBoneGlobalMatrix); + pSkeletonComponent->SetBoneGlobalMatrix(bone.GetID().Data(), curBoneGlobalMatrix); + lastMatrix = matrixBlend; + + } + /*else + { + const auto& srcTranslation = pTrackA->GetTranslationKeys()[0]; + const auto& srcRotation = pTrackA->GetRotationKeys()[0]; + const auto& srcSale = pTrackA->GetScaleKeys()[0]; + cd::Matrix4x4 srcTransform = cd::Transform(srcTranslation.GetValue(), srcRotation.GetValue(), srcSale.GetValue()).GetMatrix(); + cd::Matrix4x4 deltaTransform = pSkinmeshConponent->GetRootMatrix() * srcTransform.Inverse(); + total = deltaTransform; + deltaTransform = matrixBlend * srcTransform.Inverse(); + total = deltaTransform * total; + curBoneGlobalMatrix = total * pSkinmeshConponent->GetRootMatrix(); + pSkinmeshConponent->SetRootMatrix(curBoneGlobalMatrix); + pSkinmeshConponent->SetBoneGlobalMatrix(bone.GetID().Data(), curBoneGlobalMatrix); + }*/ + progress = blendTimeProgress; + } + else + { + curBoneGlobalMatrix = pSkeletonComponent->GetBoneGlobalMatrix(bone.GetParentID().Data()) * matrixBlend; + pSkeletonComponent->SetBoneGlobalMatrix(bone.GetID().Data(), curBoneGlobalMatrix); + } + boneMatrices[bone.GetID().Data()] = curBoneGlobalMatrix * bone.GetOffset(); + for (cd::BoneID boneID : bone.GetChildIDs()) + { + const cd::Bone& childBone = pSceneDatabase->GetBone(boneID.Data()); + BlendTwoPos(boneMatrices, pSceneDatabase, blendTimeProgress, childBone, clipAName, clipBName, pSkeletonComponent, curGlobalDeltaMatrix, rootBoonTransform, factor); + } +} - bgfx::setViewName(GetViewID(), "SkeletonRenderer"); } -void SkeletonRenderer::Warmup() +void SkeletonRenderer::Init() { - GetRenderContext()->UploadShaderProgram("SkeletonProgram"); + AddDependentShaderResource(GetRenderContext()->RegisterShaderProgram("SkeletonProgram", "vs_skeleton", "fs_AABB")); + bgfx::setViewName(GetViewID(), "SkeletonRenderer"); } void SkeletonRenderer::UpdateView(const float* pViewMatrix, const float* pProjectionMatrix) @@ -75,45 +316,27 @@ void SkeletonRenderer::UpdateView(const float* pViewMatrix, const float* pProjec void SkeletonRenderer::Build() { - const cd::SceneDatabase* pSceneDatabase = m_pCurrentSceneWorld->GetSceneDatabase(); - const uint32_t vertexCount = pSceneDatabase->GetBoneCount(); - if (0 == vertexCount) - { - return; - } - - const cd::Bone& firstBone = pSceneDatabase->GetBone(0); - if (0 != firstBone.GetID().Data()) - { - CD_ENGINE_WARN("First BoneID is not 0"); - return; - } +} - bgfx::setTransform(cd::Matrix4x4::Identity().begin()); - cd::VertexFormat vertexFormat; - vertexFormat.AddVertexAttributeLayout(cd::VertexAttributeType::Position, cd::AttributeValueType::Float, 3); +void SkeletonRenderer::Render(float deltaTime) +{ - constexpr size_t indexTypeSize = sizeof(uint16_t); - m_indexBuffer.resize((vertexCount - 1) * 2 * indexTypeSize); - m_vertexBuffer.resize(vertexCount * vertexFormat.GetStride()); - uint32_t currentVertexOffset = 0U; - uint32_t currentIndexOffset = 0U; - std::byte* pCurrentVertexBuffer = m_vertexBuffer.data(); - const cd::Point& position = firstBone.GetTransform().GetTranslation(); - std::memcpy(&pCurrentVertexBuffer[currentVertexOffset], position.begin(), details::posDataSize); - currentVertexOffset += details::posDataSize; + const cd::SceneDatabase* pSceneDatabase = m_pCurrentSceneWorld->GetSceneDatabase(); - details::TraverseBone(firstBone, pSceneDatabase, m_vertexBuffer.data(), m_indexBuffer.data(), currentVertexOffset, currentIndexOffset); - bgfx::VertexLayout vertexLayout; - VertexLayoutUtility::CreateVertexLayout(vertexLayout, vertexFormat.GetVertexAttributeLayouts()); - m_boneVBH = bgfx::createVertexBuffer(bgfx::makeRef(m_vertexBuffer.data(), static_cast(m_vertexBuffer.size())), vertexLayout).idx; - m_boneIBH = bgfx::createIndexBuffer(bgfx::makeRef(m_indexBuffer.data(), static_cast(m_indexBuffer.size())), 0U).idx; + static float animationRunningTime = 0.0f; + static float playTime = 0.0f;//for replay one animation -} + //const cd::SceneDatabase* pSceneDatabase = m_pCurrentSceneWorld->GetSceneDatabase(); + for (const auto pResource : m_dependentShaderResources) + { + if (ResourceStatus::Ready != pResource->GetStatus() && + ResourceStatus::Optimized != pResource->GetStatus()) + { + return; + } + } -void SkeletonRenderer::Render(float delataTime) -{ for (Entity entity : m_pCurrentSceneWorld->GetAnimationEntities()) { auto pAnimationComponent = m_pCurrentSceneWorld->GetAnimationComponent(entity); @@ -121,23 +344,97 @@ void SkeletonRenderer::Render(float delataTime) { continue; } - if (!hasBuilt) + const cd::SceneDatabase* pSceneDatabase = m_pCurrentSceneWorld->GetSceneDatabase(); + SkeletonComponent* pSkeletonComponent = m_pCurrentSceneWorld->GetSkeletonComponent(entity); + const char* clipName; + float ticksPerSecond = 0.0f; + float duration = 0.0f; + + const SkeletonResource* pSkeletonResource = pSkeletonComponent->GetSkeletonResource(); + if (ResourceStatus::Ready != pSkeletonResource->GetStatus() && + ResourceStatus::Optimized != pSkeletonResource->GetStatus()) { - Build(); - hasBuilt = true; + continue; } - bgfx::setVertexBuffer(0, bgfx::VertexBufferHandle{ m_boneVBH }); - bgfx::setIndexBuffer(bgfx::IndexBufferHandle{ m_boneIBH }); + if (pAnimationComponent && pAnimationComponent->GetIsPlaying()) + { + animationRunningTime += deltaTime * pAnimationComponent->GetPlayBackSpeed(); + } + static cd::Matrix4x4 deltaRootTransform = cd::Matrix4x4::Identity(); + static std::vector globalDeltaBoneMatrix; + static std::vector boneMatrixA; + static std::vector boneMatrixB; + globalDeltaBoneMatrix.clear(); + boneMatrixA.clear(); + boneMatrixB.clear(); + globalDeltaBoneMatrix.resize(128, cd::Matrix4x4::Identity()); + boneMatrixA.resize(128, cd::Matrix4x4::Identity()); + boneMatrixB.resize(128, cd::Matrix4x4::Identity()); + if (engine::AnimationClip::Idel == pAnimationComponent->GetAnimationClip()) + { + cd::Matrix4x4 rootBone = cd::Matrix4x4::Identity(); - constexpr uint64_t state = BGFX_STATE_WRITE_MASK | BGFX_STATE_MSAA | BGFX_STATE_DEPTH_TEST_LESS | + clipName = pSceneDatabase->GetAnimation(0).GetName(); + duration = pSceneDatabase->GetAnimation(0).GetDuration(); + ticksPerSecond = pSceneDatabase->GetAnimation(0).GetTicksPerSecond(); + + float animationTime = details::CustomFMod(animationRunningTime, duration); + pAnimationComponent->SetAnimationPlayTime(animationTime); + + cd::Matrix4x4 curGlobalDeltaMatrix = cd::Matrix4x4::Identity(); + details::CalculateTransform(globalDeltaBoneMatrix, pSceneDatabase, animationTime, pSceneDatabase->GetBone(0), clipName, pSkeletonComponent, curGlobalDeltaMatrix, deltaTime * pAnimationComponent->GetPlayBackSpeed(), pAnimationComponent->GetIsPlaying()); + + } + else if (engine::AnimationClip::Walking == pAnimationComponent->GetAnimationClip()) + { + const cd::Animation& pAnimation = pSceneDatabase->GetAnimation(1); + clipName = pSceneDatabase->GetAnimation(1).GetName(); + duration = pSceneDatabase->GetAnimation(1).GetDuration(); + ticksPerSecond = pSceneDatabase->GetAnimation(1).GetTicksPerSecond(); + float animationTime = details::CustomFMod(animationRunningTime, duration); + } + else if (engine::AnimationClip::Running == pAnimationComponent->GetAnimationClip()) + { + const cd::Animation& pAnimation = pSceneDatabase->GetAnimation(2); + clipName = pSceneDatabase->GetAnimation(2).GetName(); + duration = pSceneDatabase->GetAnimation(2).GetDuration(); + ticksPerSecond = pSceneDatabase->GetAnimation(1).GetTicksPerSecond(); + float animationTime = details::CustomFMod(animationRunningTime, duration); + + //details::CalculateTransform(globalDeltaBoneMatrix, pSceneDatabase, animationTime, pSceneDatabase->GetBone(0), clipName, pSkinMeshComponent, curBoneGlobalMatrix, cd::Matrix4x4::Identity()); + } + else if (engine::AnimationClip::Blend == pAnimationComponent->GetAnimationClip()) + { + float factor = pAnimationComponent->GetBlendFactor(); + float clipATime = pSceneDatabase->GetAnimation(0).GetDuration(); + float clipBTime = pSceneDatabase->GetAnimation(1).GetDuration(); + + float clipARunningTime = details::CustomFMod(animationRunningTime, clipATime); + float clipBRunningTime = details::CustomFMod(animationRunningTime, clipBTime); + const float blendSpeed = clipATime + (clipBTime - clipATime) * factor; + float clipASpeed = clipATime / blendSpeed; + pAnimationComponent->SetPlayBackSpeed(clipASpeed); + float clipBSpeed = clipBTime / blendSpeed; + float clipAProgress = clipARunningTime / clipATime; + + cd::Matrix4x4 curGlobalDeltaMatrix = cd::Matrix4x4::Identity(); + details::BlendTwoPos(globalDeltaBoneMatrix, pSceneDatabase, clipAProgress, pSceneDatabase->GetBone(0), pSceneDatabase->GetAnimation(0).GetName(), pSceneDatabase->GetAnimation(1).GetName(), pSkeletonComponent, curGlobalDeltaMatrix, deltaRootTransform, factor); + } + + bgfx::setTransform(cd::Matrix4x4::Identity().begin()); + + bgfx::setUniform(bgfx::UniformHandle{ pAnimationComponent->GetBoneMatrixsUniform() }, globalDeltaBoneMatrix.data(), static_cast(globalDeltaBoneMatrix.size())); + bgfx::setVertexBuffer(0, bgfx::VertexBufferHandle{ pSkeletonComponent->GetSkeletonResource()->GetVertexBufferHandle()}); + bgfx::setIndexBuffer(bgfx::IndexBufferHandle{ pSkeletonComponent->GetSkeletonResource()->GetIndexBufferHandle() }); + + constexpr uint64_t state = BGFX_STATE_WRITE_MASK | BGFX_STATE_MSAA | BGFX_STATE_BLEND_FUNC(BGFX_STATE_BLEND_SRC_ALPHA, BGFX_STATE_BLEND_INV_SRC_ALPHA) | BGFX_STATE_PT_LINES; bgfx::setState(state); - GetRenderContext()->Submit(GetViewID(), "SkeletonProgram"); + constexpr StringCrc programHandleIndex{ "SkeletonProgram" }; + GetRenderContext()->Submit(GetViewID(), programHandleIndex); } - } - } \ No newline at end of file diff --git a/Engine/Source/Runtime/Rendering/SkeletonRenderer.h b/Engine/Source/Runtime/Rendering/SkeletonRenderer.h index 3ced1d57..4c576c7e 100644 --- a/Engine/Source/Runtime/Rendering/SkeletonRenderer.h +++ b/Engine/Source/Runtime/Rendering/SkeletonRenderer.h @@ -14,7 +14,6 @@ class SkeletonRenderer final : public Renderer using Renderer::Renderer; virtual void Init() override; - virtual void Warmup() override; virtual void UpdateView(const float* pViewMatrix, const float* pProjectionMatrix) override; virtual void Render(float deltaTime) override; void Build(); @@ -26,7 +25,6 @@ class SkeletonRenderer final : public Renderer std::vector m_indexBuffer; uint16_t m_boneVBH = UINT16_MAX; uint16_t m_boneIBH = UINT16_MAX; - bool hasBuilt = false; }; diff --git a/Engine/Source/Runtime/Rendering/SkyType.h b/Engine/Source/Runtime/Rendering/SkyType.h index 5e6200ba..bd94ff03 100644 --- a/Engine/Source/Runtime/Rendering/SkyType.h +++ b/Engine/Source/Runtime/Rendering/SkyType.h @@ -15,16 +15,15 @@ enum class SkyType AtmosphericScattering, }; -static const std::map SkyTypeToShaderFeature -{ - { engine::SkyType::None, engine::ShaderFeature::DEFAULT}, - { engine::SkyType::SkyBox, engine::ShaderFeature::IBL}, - { engine::SkyType::AtmosphericScattering, engine::ShaderFeature::ATM }, +constexpr engine::ShaderFeature SkyTypeToShaderFeature[] = { + ShaderFeature::DEFAULT, + ShaderFeature::IBL, + ShaderFeature::ATM }; -CD_FORCEINLINE engine::ShaderFeature GetSkyTypeShaderFeature(engine::SkyType type) +constexpr engine::ShaderFeature GetSkyTypeShaderFeature(engine::SkyType type) { - return SkyTypeToShaderFeature.at(type); + return SkyTypeToShaderFeature[static_cast(type)]; } } \ No newline at end of file diff --git a/Engine/Source/Runtime/Rendering/SkyboxRenderer.cpp b/Engine/Source/Runtime/Rendering/SkyboxRenderer.cpp index 5d44c160..fb454a74 100644 --- a/Engine/Source/Runtime/Rendering/SkyboxRenderer.cpp +++ b/Engine/Source/Runtime/Rendering/SkyboxRenderer.cpp @@ -5,6 +5,7 @@ #include "ECWorld/SkyComponent.h" #include "Rendering/RenderContext.h" #include "Rendering/Resources/MeshResource.h" +#include "Rendering/Resources/ShaderResource.h" namespace engine { @@ -14,6 +15,7 @@ namespace constexpr const char* skyboxSampler = "s_texSkybox"; constexpr const char* skyboxProgram = "skyboxProgram"; +constexpr const char* skyboxStrength = "u_skyboxStrength"; constexpr uint16_t sampleFalg = BGFX_SAMPLER_U_CLAMP | BGFX_SAMPLER_V_CLAMP | BGFX_SAMPLER_W_CLAMP; constexpr uint64_t renderState = BGFX_STATE_WRITE_MASK | BGFX_STATE_CULL_CCW | BGFX_STATE_MSAA | BGFX_STATE_DEPTH_TEST_LEQUAL; @@ -22,20 +24,14 @@ constexpr uint64_t renderState = BGFX_STATE_WRITE_MASK | BGFX_STATE_CULL_CCW | B void SkyboxRenderer::Init() { - constexpr StringCrc programCrc = StringCrc(skyboxProgram); - GetRenderContext()->RegisterShaderProgram(programCrc, {"vs_skybox", "fs_skybox"}); + AddDependentShaderResource(GetRenderContext()->RegisterShaderProgram("skyboxProgram", "vs_skybox", "fs_skybox")); - bgfx::setViewName(GetViewID(), "SkyboxRenderer"); -} - -void SkyboxRenderer::Warmup() -{ + GetRenderContext()->CreateUniform("s_texSkybox", bgfx::UniformType::Sampler); + GetRenderContext()->CreateUniform(skyboxStrength, bgfx::UniformType::Vec4, 1); SkyComponent* pSkyComponent = m_pCurrentSceneWorld->GetSkyComponent(m_pCurrentSceneWorld->GetSkyEntity()); - - GetRenderContext()->CreateUniform(skyboxSampler, bgfx::UniformType::Sampler); GetRenderContext()->CreateTexture(pSkyComponent->GetRadianceTexturePath().c_str(), sampleFalg); - GetRenderContext()->UploadShaderProgram(skyboxProgram); + bgfx::setViewName(GetViewID(), "SkyboxRenderer"); } void SkyboxRenderer::UpdateView(const float* pViewMatrix, const float* pProjectionMatrix) @@ -66,6 +62,15 @@ void SkyboxRenderer::Render(float deltaTime) return; } + for (const auto pResource : m_dependentShaderResources) + { + if (ResourceStatus::Ready != pResource->GetStatus() && + ResourceStatus::Optimized != pResource->GetStatus()) + { + return; + } + } + StaticMeshComponent* pMeshComponent = m_pCurrentSceneWorld->GetStaticMeshComponent(m_pCurrentSceneWorld->GetSkyEntity()); if (!pMeshComponent) { @@ -84,15 +89,18 @@ void SkyboxRenderer::Render(float deltaTime) SkyComponent* pSkyComponent = m_pCurrentSceneWorld->GetSkyComponent(m_pCurrentSceneWorld->GetSkyEntity()); GetRenderContext()->CreateTexture(pSkyComponent->GetRadianceTexturePath().c_str(), sampleFalg); - constexpr StringCrc samplerCrc(skyboxSampler); + constexpr StringCrc skyboxStrengthCrc{ skyboxStrength }; + GetRenderContext()->FillUniform(skyboxStrengthCrc, &(pSkyComponent->GetSkyboxStrength())); + constexpr StringCrc samplerCrc(skyboxSampler); bgfx::setTexture(0, GetRenderContext()->GetUniform(samplerCrc), GetRenderContext()->GetTexture(StringCrc(pSkyComponent->GetRadianceTexturePath()))); bgfx::setState(renderState); - SubmitStaticMeshDrawCall(pMeshComponent, GetViewID(), skyboxProgram); + constexpr StringCrc programHandleIndex{ "skyboxProgram" }; + SubmitStaticMeshDrawCall(pMeshComponent, GetViewID(), programHandleIndex); } bool SkyboxRenderer::IsEnable() const diff --git a/Engine/Source/Runtime/Rendering/SkyboxRenderer.h b/Engine/Source/Runtime/Rendering/SkyboxRenderer.h index d61cf64b..6cc9ec9a 100644 --- a/Engine/Source/Runtime/Rendering/SkyboxRenderer.h +++ b/Engine/Source/Runtime/Rendering/SkyboxRenderer.h @@ -13,7 +13,6 @@ class SkyboxRenderer final : public Renderer using Renderer::Renderer; virtual void Init() override; - virtual void Warmup() override; virtual void UpdateView(const float* pViewMatrix, const float* pProjectionMatrix) override; virtual void Render(float deltaTime) override; virtual bool IsEnable() const override; diff --git a/Engine/Source/Runtime/Rendering/TerrainRenderer.cpp b/Engine/Source/Runtime/Rendering/TerrainRenderer.cpp index 218f4ff6..0b05e160 100644 --- a/Engine/Source/Runtime/Rendering/TerrainRenderer.cpp +++ b/Engine/Source/Runtime/Rendering/TerrainRenderer.cpp @@ -11,6 +11,7 @@ #include "Math/Transform.hpp" #include "Rendering/RenderContext.h" #include "Rendering/Resources/MeshResource.h" +#include "Rendering/Resources/ShaderResource.h" #include "Scene/Texture.h" #include "U_IBL.sh" #include "U_Terrain.sh" @@ -34,6 +35,7 @@ constexpr const char* elevationTexture = "Terrain"; constexpr const char* lutSampler = "s_texLUT"; constexpr const char* cubeIrradianceSampler = "s_texCubeIrr"; constexpr const char* cubeRadianceSampler = "s_texCubeRad"; +constexpr const char* iblStrength = "u_iblStrength"; constexpr const char* lutTexture = "Textures/lut/ibl_brdf_lut.dds"; @@ -55,11 +57,6 @@ constexpr uint64_t defaultRenderingState = BGFX_STATE_WRITE_MASK | BGFX_STATE_MS } void TerrainRenderer::Init() -{ - bgfx::setViewName(GetViewID(), "TerrainRenderer"); -} - -void TerrainRenderer::Warmup() { SkyComponent* pSkyComponent = m_pCurrentSceneWorld->GetSkyComponent(m_pCurrentSceneWorld->GetSkyEntity()); @@ -76,6 +73,7 @@ void TerrainRenderer::Warmup() GetRenderContext()->CreateTexture(lutTexture); GetRenderContext()->CreateTexture(pSkyComponent->GetIrradianceTexturePath().c_str(), samplerFlags); GetRenderContext()->CreateTexture(pSkyComponent->GetRadianceTexturePath().c_str(), samplerFlags); + GetRenderContext()->CreateUniform(iblStrength, bgfx::UniformType::Vec4, 1); GetRenderContext()->CreateUniform(cameraPos, bgfx::UniformType::Vec4, 1); GetRenderContext()->CreateUniform(cameraNearFarPlane, bgfx::UniformType::Vec4, 1); @@ -90,6 +88,8 @@ void TerrainRenderer::Warmup() GetRenderContext()->CreateUniform(lightParams, bgfx::UniformType::Vec4, LightUniform::VEC4_COUNT); GetRenderContext()->CreateTexture(elevationTexture, 129U, 129U, 1, bgfx::TextureFormat::Enum::R32F, samplerFlags, nullptr, 0); + + bgfx::setViewName(GetViewID(), "TerrainRenderer"); } void TerrainRenderer::UpdateView(const float* pViewMatrix, const float* pProjectionMatrix) @@ -109,8 +109,7 @@ void TerrainRenderer::Render(float deltaTime) { MaterialComponent* pMaterialComponent = m_pCurrentSceneWorld->GetMaterialComponent(entity); if (!pMaterialComponent || - pMaterialComponent->GetMaterialType() != m_pCurrentSceneWorld->GetTerrainMaterialType() || - !GetRenderContext()->IsShaderProgramValid(pMaterialComponent->GetShaderProgramName(), pMaterialComponent->GetFeaturesCombine())) + pMaterialComponent->GetMaterialType() != m_pCurrentSceneWorld->GetTerrainMaterialType()) { // TODO : improve this condition. As we want to skip some feature-specified entities to render. // For example, terrain/particle/... @@ -131,6 +130,13 @@ void TerrainRenderer::Render(float deltaTime) continue; } + const ShaderResource* pShaderResource = pMaterialComponent->GetShaderResource(); + if (ResourceStatus::Ready != pShaderResource->GetStatus() && + ResourceStatus::Optimized != pShaderResource->GetStatus()) + { + continue; + } + // Transform if (TransformComponent* pTransformComponent = m_pCurrentSceneWorld->GetTransformComponent(entity)) { @@ -174,6 +180,9 @@ void TerrainRenderer::Render(float deltaTime) GetRenderContext()->GetUniform(radSamplerCrc), GetRenderContext()->GetTexture(StringCrc(pSkyComponent->GetRadianceTexturePath()))); + constexpr StringCrc iblStrengthCrc{ iblStrength }; + GetRenderContext()->FillUniform(iblStrengthCrc, &(pMaterialComponent->GetIblStrengeth())); + constexpr StringCrc lutsamplerCrc(lutSampler); constexpr StringCrc luttextureCrc(lutTexture); bgfx::setTexture(BRDF_LUT_SLOT, GetRenderContext()->GetUniform(lutsamplerCrc), GetRenderContext()->GetTexture(luttextureCrc)); @@ -224,7 +233,7 @@ void TerrainRenderer::Render(float deltaTime) bgfx::setState(state); - SubmitStaticMeshDrawCall(pMeshComponent, GetViewID(), pMaterialComponent->GetShaderProgramName()); + SubmitStaticMeshDrawCall(pMeshComponent, GetViewID(), pShaderResource->GetHandle()); } } diff --git a/Engine/Source/Runtime/Rendering/TerrainRenderer.h b/Engine/Source/Runtime/Rendering/TerrainRenderer.h index 1e7d5342..01915a3e 100644 --- a/Engine/Source/Runtime/Rendering/TerrainRenderer.h +++ b/Engine/Source/Runtime/Rendering/TerrainRenderer.h @@ -13,7 +13,6 @@ class TerrainRenderer final : public Renderer using Renderer::Renderer; virtual void Init() override; - virtual void Warmup() override; virtual void UpdateView(const float* pViewMatrix, const float* pProjectionMatrix) override; virtual void Render(float deltaTime) override; diff --git a/Engine/Source/Runtime/Rendering/WhiteModelRenderer.cpp b/Engine/Source/Runtime/Rendering/WhiteModelRenderer.cpp index c535bb77..6b45aa51 100644 --- a/Engine/Source/Runtime/Rendering/WhiteModelRenderer.cpp +++ b/Engine/Source/Runtime/Rendering/WhiteModelRenderer.cpp @@ -6,6 +6,7 @@ #include "ECWorld/TransformComponent.h" #include "Rendering/RenderContext.h" #include "Rendering/Resources/MeshResource.h" +#include "Rendering/Resources/ShaderResource.h" #include "Scene/Texture.h" namespace engine @@ -13,17 +14,11 @@ namespace engine void WhiteModelRenderer::Init() { - constexpr StringCrc programCrc = StringCrc("WhiteModelProgram"); - GetRenderContext()->RegisterShaderProgram(programCrc, { "vs_whiteModel", "fs_whiteModel" }); + AddDependentShaderResource(GetRenderContext()->RegisterShaderProgram("WhiteModelProgram", "vs_whiteModel", "fs_whiteModel")); bgfx::setViewName(GetViewID(), "WhiteModelRenderer"); } -void WhiteModelRenderer::Warmup() -{ - GetRenderContext()->UploadShaderProgram("WhiteModelProgram"); -} - void WhiteModelRenderer::UpdateView(const float* pViewMatrix, const float* pProjectionMatrix) { UpdateViewRenderTarget(); @@ -32,6 +27,15 @@ void WhiteModelRenderer::UpdateView(const float* pViewMatrix, const float* pProj void WhiteModelRenderer::Render(float deltaTime) { + for (const auto pResource : m_dependentShaderResources) + { + if (ResourceStatus::Ready != pResource->GetStatus() && + ResourceStatus::Optimized != pResource->GetStatus()) + { + return; + } + } + for (Entity entity : m_pCurrentSceneWorld->GetStaticMeshEntities()) { if (m_pCurrentSceneWorld->GetSkyEntity() == entity) @@ -68,7 +72,8 @@ void WhiteModelRenderer::Render(float deltaTime) BGFX_STATE_BLEND_FUNC(BGFX_STATE_BLEND_SRC_ALPHA, BGFX_STATE_BLEND_INV_SRC_ALPHA); bgfx::setState(state); - SubmitStaticMeshDrawCall(pMeshComponent, GetViewID(), "WhiteModelProgram"); + constexpr StringCrc programHandleIndex{ "WhiteModelProgram" }; + SubmitStaticMeshDrawCall(pMeshComponent, GetViewID(), programHandleIndex); } } diff --git a/Engine/Source/Runtime/Rendering/WhiteModelRenderer.h b/Engine/Source/Runtime/Rendering/WhiteModelRenderer.h index c7a97f99..62325dec 100644 --- a/Engine/Source/Runtime/Rendering/WhiteModelRenderer.h +++ b/Engine/Source/Runtime/Rendering/WhiteModelRenderer.h @@ -15,7 +15,6 @@ class WhiteModelRenderer final : public Renderer using Renderer::Renderer; virtual void Init() override; - virtual void Warmup() override; virtual void UpdateView(const float* pViewMatrix, const float* pProjectionMatrix) override; virtual void Render(float deltaTime) override; diff --git a/Engine/Source/Runtime/Rendering/WireframeRenderer.cpp b/Engine/Source/Runtime/Rendering/WireframeRenderer.cpp index 53e3809a..c4cbf42f 100644 --- a/Engine/Source/Runtime/Rendering/WireframeRenderer.cpp +++ b/Engine/Source/Runtime/Rendering/WireframeRenderer.cpp @@ -6,6 +6,7 @@ #include "ECWorld/TransformComponent.h" #include "Rendering/RenderContext.h" #include "Rendering/Resources/MeshResource.h" +#include "Rendering/Resources/ShaderResource.h" #include "Scene/Texture.h" #undef EDITOR_MODE @@ -15,17 +16,11 @@ namespace engine void WireframeRenderer::Init() { - constexpr StringCrc programCrc = StringCrc("WireframeLineProgram"); - GetRenderContext()->RegisterShaderProgram(programCrc, { "vs_wireframe_line", "fs_wireframe_line" }); + AddDependentShaderResource(GetRenderContext()->RegisterShaderProgram("WireframeLineProgram", "vs_wireframe_line", "fs_wireframe_line")); bgfx::setViewName(GetViewID(), "WireframeRenderer"); } -void WireframeRenderer::Warmup() -{ - GetRenderContext()->UploadShaderProgram("WireframeLineProgram"); -} - void WireframeRenderer::UpdateView(const float* pViewMatrix, const float* pProjectionMatrix) { UpdateViewRenderTarget(); @@ -34,6 +29,15 @@ void WireframeRenderer::UpdateView(const float* pViewMatrix, const float* pProje void WireframeRenderer::Render(float deltaTime) { + for (const auto pResource : m_dependentShaderResources) + { + if (ResourceStatus::Ready != pResource->GetStatus() && + ResourceStatus::Optimized != pResource->GetStatus()) + { + return; + } + } + for (Entity entity : m_pCurrentSceneWorld->GetStaticMeshEntities()) { if (!m_enableGlobalWireframe && m_pCurrentSceneWorld->GetSelectedEntity() != entity) @@ -75,7 +79,8 @@ void WireframeRenderer::Render(float deltaTime) BGFX_STATE_BLEND_FUNC(BGFX_STATE_BLEND_SRC_ALPHA, BGFX_STATE_BLEND_INV_SRC_ALPHA) | BGFX_STATE_PT_LINES; bgfx::setState(state); - SubmitStaticMeshDrawCall(pMeshComponent, GetViewID(), "WireframeLineProgram"); + constexpr StringCrc programHandleIndex{ "ImGuiProgram" }; + SubmitStaticMeshDrawCall(pMeshComponent, GetViewID(), programHandleIndex); } } diff --git a/Engine/Source/Runtime/Rendering/WireframeRenderer.h b/Engine/Source/Runtime/Rendering/WireframeRenderer.h index 90d1b191..209befd1 100644 --- a/Engine/Source/Runtime/Rendering/WireframeRenderer.h +++ b/Engine/Source/Runtime/Rendering/WireframeRenderer.h @@ -15,7 +15,6 @@ class WireframeRenderer final : public Renderer using Renderer::Renderer; virtual void Init() override; - virtual void Warmup() override; virtual void UpdateView(const float* pViewMatrix, const float* pProjectionMatrix) override; virtual void Render(float deltaTime) override; diff --git a/Engine/Source/Runtime/Rendering/WorldRenderer.cpp b/Engine/Source/Runtime/Rendering/WorldRenderer.cpp index 11d35d6a..ed51ec02 100644 --- a/Engine/Source/Runtime/Rendering/WorldRenderer.cpp +++ b/Engine/Source/Runtime/Rendering/WorldRenderer.cpp @@ -11,10 +11,11 @@ #include "Math/Transform.hpp" #include "Rendering/RenderContext.h" #include "Rendering/Resources/MeshResource.h" +#include "Rendering/Resources/ShaderResource.h" #include "Rendering/Resources/TextureResource.h" #include "Scene/Texture.h" -#include "U_IBL.sh" #include "U_AtmophericScattering.sh" +#include "U_IBL.sh" #include "U_Shadow.sh" namespace engine @@ -30,6 +31,7 @@ constexpr const char* cubeRadianceSampler = "s_texCubeRad"; constexpr const char* lutTexture = "Textures/lut/ibl_brdf_lut.dds"; constexpr const char* cameraPos = "u_cameraPos"; +constexpr const char* iblStrength = "u_iblStrength"; constexpr const char* albedoColor = "u_albedoColor"; constexpr const char* emissiveColorAndFactor = "u_emissiveColorAndFactor"; constexpr const char* metallicRoughnessFactor = "u_metallicRoughnessFactor"; @@ -43,29 +45,24 @@ constexpr const char* lightParams = "u_lightParams"; constexpr const char* LightDir = "u_LightDir"; constexpr const char* HeightOffsetAndshadowLength = "u_HeightOffsetAndshadowLength"; -constexpr const char* lightViewProjs= "u_lightViewProjs"; -constexpr const char* cubeShadowMapSamplers[3] = { "s_texCubeShadowMap_1", "s_texCubeShadowMap_2" , "s_texCubeShadowMap_3" }; +constexpr const char* lightViewProjs = "u_lightViewProjs"; +constexpr const char* cubeShadowMapSamplers[3] = { "s_texCubeShadowMap_1", "s_texCubeShadowMap_2" , "s_texCubeShadowMap_3" }; -constexpr const char* cameraNearFarPlane = "u_cameraNearFarPlane"; -constexpr const char* cameraLookAt = "u_cameraLookAt"; -constexpr const char* clipFrustumDepth = "u_clipFrustumDepth"; +constexpr const char* cameraNearFarPlane = "u_cameraNearFarPlane"; +constexpr const char* cameraLookAt = "u_cameraLookAt"; +constexpr const char* clipFrustumDepth = "u_clipFrustumDepth"; -constexpr const char* directionShadowMapTexture = "DirectionShadowMapTexture"; -constexpr const char* pointShadowMapTexture = "PointShadowMapTexture"; -constexpr const char* spotShadowMapTexture = "SpotShadowMapTexture"; +constexpr const char* directionShadowMapTexture = "DirectionShadowMapTexture"; +constexpr const char* pointShadowMapTexture = "PointShadowMapTexture"; +constexpr const char* spotShadowMapTexture = "SpotShadowMapTexture"; -constexpr uint64_t samplerFlags = BGFX_SAMPLER_U_CLAMP | BGFX_SAMPLER_V_CLAMP | BGFX_SAMPLER_W_CLAMP; +constexpr uint64_t samplerFlags = BGFX_SAMPLER_U_CLAMP | BGFX_SAMPLER_V_CLAMP | BGFX_SAMPLER_W_CLAMP; constexpr uint64_t defaultRenderingState = BGFX_STATE_WRITE_MASK | BGFX_STATE_MSAA | BGFX_STATE_DEPTH_TEST_LESS; -constexpr uint64_t blitDstTextureFlags = BGFX_TEXTURE_BLIT_DST | BGFX_SAMPLER_U_CLAMP | BGFX_SAMPLER_V_CLAMP; +constexpr uint64_t blitDstTextureFlags = BGFX_TEXTURE_BLIT_DST | BGFX_SAMPLER_U_CLAMP | BGFX_SAMPLER_V_CLAMP; } void WorldRenderer::Init() -{ - bgfx::setViewName(GetViewID(), "WorldRenderer"); -} - -void WorldRenderer::Warmup() { SkyComponent* pSkyComponent = m_pCurrentSceneWorld->GetSkyComponent(m_pCurrentSceneWorld->GetSkyEntity()); @@ -78,6 +75,7 @@ void WorldRenderer::Warmup() GetRenderContext()->CreateTexture(pSkyComponent->GetRadianceTexturePath().c_str(), samplerFlags); GetRenderContext()->CreateUniform(cameraPos, bgfx::UniformType::Vec4, 1); + GetRenderContext()->CreateUniform(iblStrength, bgfx::UniformType::Vec4, 1); GetRenderContext()->CreateUniform(albedoColor, bgfx::UniformType::Vec4, 1); GetRenderContext()->CreateUniform(emissiveColorAndFactor, bgfx::UniformType::Vec4, 1); GetRenderContext()->CreateUniform(metallicRoughnessFactor, bgfx::UniformType::Vec4, 1); @@ -97,6 +95,8 @@ void WorldRenderer::Warmup() GetRenderContext()->CreateUniform(cameraNearFarPlane, bgfx::UniformType::Vec4, 1); GetRenderContext()->CreateUniform(clipFrustumDepth, bgfx::UniformType::Vec4, 1); + + bgfx::setViewName(GetViewID(), "WorldRenderer"); } void WorldRenderer::UpdateView(const float* pViewMatrix, const float* pProjectionMatrix) @@ -112,13 +112,13 @@ void WorldRenderer::Render(float deltaTime) const cd::Transform& cameraTransform = m_pCurrentSceneWorld->GetTransformComponent(m_pCurrentSceneWorld->GetMainCameraEntity())->GetTransform(); SkyComponent* pSkyComponent = m_pCurrentSceneWorld->GetSkyComponent(m_pCurrentSceneWorld->GetSkyEntity()); - auto lightEntities = m_pCurrentSceneWorld->GetLightEntities(); + const auto lightEntities = m_pCurrentSceneWorld->GetLightEntities(); size_t lightEntityCount = lightEntities.size(); // Blit RTV to SRV to update light shadow map for (int i = 0; i < lightEntityCount; i++) { - auto lightComponent = m_pCurrentSceneWorld->GetLightComponent(lightEntities[i]); + LightComponent* lightComponent = m_pCurrentSceneWorld->GetLightComponent(lightEntities[i]); cd::LightType lightType = lightComponent->GetType(); if (cd::LightType::Directional == lightType) { @@ -177,15 +177,21 @@ void WorldRenderer::Render(float deltaTime) for (Entity entity : m_pCurrentSceneWorld->GetMaterialEntities()) { MaterialComponent* pMaterialComponent = m_pCurrentSceneWorld->GetMaterialComponent(entity); - if (!pMaterialComponent || - pMaterialComponent->GetMaterialType() != m_pCurrentSceneWorld->GetPBRMaterialType() || - !GetRenderContext()->IsShaderProgramValid(pMaterialComponent->GetShaderProgramName(), pMaterialComponent->GetFeaturesCombine())) + if (!pMaterialComponent) { // TODO : improve this condition. As we want to skip some feature-specified entities to render. // For example, terrain/particle/... continue; } + // TODO : Temporary solution for CelluloidRenderer, remove it. + if (pMaterialComponent->GetMaterialType() != m_pCurrentSceneWorld->GetPBRMaterialType() && + pMaterialComponent->GetMaterialType() != m_pCurrentSceneWorld->GetCelluloidMaterialType()&& + pMaterialComponent->GetMaterialType() != m_pCurrentSceneWorld->GetAnimationMaterialType()) + { + continue; + } + // No mesh attached? StaticMeshComponent* pMeshComponent = m_pCurrentSceneWorld->GetStaticMeshComponent(entity); if (!pMeshComponent) @@ -200,10 +206,17 @@ void WorldRenderer::Render(float deltaTime) continue; } + const ShaderResource* pShaderResource = pMaterialComponent->GetShaderResource(); + if (ResourceStatus::Ready != pShaderResource->GetStatus() && + ResourceStatus::Optimized != pShaderResource->GetStatus()) + { + continue; + } + // SkinMesh if(m_pCurrentSceneWorld->GetAnimationComponent(entity)) { - continue; + //continue; } // Transform @@ -265,8 +278,11 @@ void WorldRenderer::Render(float deltaTime) GetRenderContext()->GetUniform(radSamplerCrc), GetRenderContext()->GetTexture(StringCrc(pSkyComponent->GetRadianceTexturePath()))); - constexpr StringCrc lutsamplerCrc(lutSampler); - constexpr StringCrc luttextureCrc(lutTexture); + constexpr StringCrc iblStrengthCrc{ iblStrength }; + GetRenderContext()->FillUniform(iblStrengthCrc, &(pMaterialComponent->GetIblStrengeth())); + + constexpr StringCrc lutsamplerCrc{ lutSampler }; + constexpr StringCrc luttextureCrc{ lutTexture }; bgfx::setTexture(BRDF_LUT_SLOT, GetRenderContext()->GetUniform(lutsamplerCrc), GetRenderContext()->GetTexture(luttextureCrc)); } else if (SkyType::AtmosphericScattering == crtSkyType) @@ -353,7 +369,7 @@ void WorldRenderer::Render(float deltaTime) if (cd::LightType::Directional == lightType) { bgfx::TextureHandle blitDstShadowMapTexture = static_cast(lightComponent->GetShadowMapTexture()); - bgfx::setTexture(SHADOW_MAP_CUBE_FIRST_SLOT+lightIndex, GetRenderContext()->GetUniform(shadowMapSamplerCrcs[lightIndex]), blitDstShadowMapTexture); + bgfx::setTexture(SHADOW_MAP_CUBE_FIRST_SLOT + lightIndex, GetRenderContext()->GetUniform(shadowMapSamplerCrcs[lightIndex]), blitDstShadowMapTexture); // TODO : manual constexpr StringCrc clipFrustumDepthCrc(clipFrustumDepth); GetRenderContext()->FillUniform(clipFrustumDepthCrc, lightComponent->GetComputedCascadeSplit(), 1); @@ -361,13 +377,13 @@ void WorldRenderer::Render(float deltaTime) else if (cd::LightType::Point == lightType) { bgfx::TextureHandle blitDstShadowMapTexture = static_cast(lightComponent->GetShadowMapTexture()); - bgfx::setTexture(SHADOW_MAP_CUBE_FIRST_SLOT+lightIndex, GetRenderContext()->GetUniform(shadowMapSamplerCrcs[lightIndex]), blitDstShadowMapTexture); + bgfx::setTexture(SHADOW_MAP_CUBE_FIRST_SLOT + lightIndex, GetRenderContext()->GetUniform(shadowMapSamplerCrcs[lightIndex]), blitDstShadowMapTexture); } else if (cd::LightType::Spot == lightType) { // Blit RTV(FrameBuffer Texture) to SRV(Texture) bgfx::TextureHandle blitDstShadowMapTexture = static_cast(lightComponent->GetShadowMapTexture()); - bgfx::setTexture(SHADOW_MAP_CUBE_FIRST_SLOT+lightIndex, GetRenderContext()->GetUniform(shadowMapSamplerCrcs[lightIndex]), blitDstShadowMapTexture); + bgfx::setTexture(SHADOW_MAP_CUBE_FIRST_SLOT + lightIndex, GetRenderContext()->GetUniform(shadowMapSamplerCrcs[lightIndex]), blitDstShadowMapTexture); } } @@ -392,11 +408,11 @@ void WorldRenderer::Render(float deltaTime) bgfx::setVertexBuffer(1, bgfx::VertexBufferHandle{ pBlendShapeComponent->GetNonMorphAffectedVB() }); // TODO : BlendShape + multiple index buffers. bgfx::setIndexBuffer(bgfx::IndexBufferHandle{ pMeshComponent->GetMeshResource()->GetIndexBufferHandle(0U) }); - GetRenderContext()->Submit(GetViewID(), pMaterialComponent->GetShaderProgramName(), pMaterialComponent->GetFeaturesCombine()); + GetRenderContext()->Submit(GetViewID(), pShaderResource->GetHandle()); } else { - SubmitStaticMeshDrawCall(pMeshComponent, GetViewID(), pMaterialComponent->GetShaderProgramName(), pMaterialComponent->GetFeaturesCombine()); + SubmitStaticMeshDrawCall(pMeshComponent, GetViewID(), pShaderResource->GetHandle()); } } } diff --git a/Engine/Source/Runtime/Rendering/WorldRenderer.h b/Engine/Source/Runtime/Rendering/WorldRenderer.h index 19d79d93..7ddc7357 100644 --- a/Engine/Source/Runtime/Rendering/WorldRenderer.h +++ b/Engine/Source/Runtime/Rendering/WorldRenderer.h @@ -13,7 +13,6 @@ class WorldRenderer final : public Renderer using Renderer::Renderer; virtual void Init() override; - virtual void Warmup() override; virtual void UpdateView(const float* pViewMatrix, const float* pProjectionMatrix) override; virtual void Render(float deltaTime) override; diff --git a/Engine/Source/ThirdParty/AssetPipeline b/Engine/Source/ThirdParty/AssetPipeline index 4a5644f7..ccd965ba 160000 --- a/Engine/Source/ThirdParty/AssetPipeline +++ b/Engine/Source/ThirdParty/AssetPipeline @@ -1 +1 @@ -Subproject commit 4a5644f700720e95e425a415620d058a32dcf47a +Subproject commit ccd965ba15b46e4cbeb55effb2e4d15790762826 diff --git a/Projects/Test/Textures/skybox/defaultSkybox.hdr b/Projects/Test/Textures/skybox/defaultSkybox.hdr deleted file mode 100644 index e02ad284..00000000 Binary files a/Projects/Test/Textures/skybox/defaultSkybox.hdr and /dev/null differ diff --git a/Projects/Test/Textures/skybox/defaultSkybox_irr.dds b/Projects/Test/Textures/skybox/defaultSkybox_irr.dds index 96bd7d3c..348519f8 100644 Binary files a/Projects/Test/Textures/skybox/defaultSkybox_irr.dds and b/Projects/Test/Textures/skybox/defaultSkybox_irr.dds differ diff --git a/Projects/Test/Textures/skybox/defaultSkybox_rad.dds b/Projects/Test/Textures/skybox/defaultSkybox_rad.dds index ceb72b7b..e2b1d04a 100644 Binary files a/Projects/Test/Textures/skybox/defaultSkybox_rad.dds and b/Projects/Test/Textures/skybox/defaultSkybox_rad.dds differ diff --git a/Projects/Test/Textures/textures/TerrainTest_baseColor.dds b/Projects/Test/Textures/textures/TerrainTest_baseColor.dds index 3dba1a6c..1c2a3fc5 100644 Binary files a/Projects/Test/Textures/textures/TerrainTest_baseColor.dds and b/Projects/Test/Textures/textures/TerrainTest_baseColor.dds differ diff --git a/Projects/Test/Textures/textures/Terrain_baseColor.dds b/Projects/Test/Textures/textures/Terrain_baseColor.dds index a494aa48..044d8e11 100644 Binary files a/Projects/Test/Textures/textures/Terrain_baseColor.dds and b/Projects/Test/Textures/textures/Terrain_baseColor.dds differ diff --git a/Projects/Test/Textures/textures/dirty_baseColor.dds b/Projects/Test/Textures/textures/dirty_baseColor.dds index cda1ee52..e29c0957 100644 Binary files a/Projects/Test/Textures/textures/dirty_baseColor.dds and b/Projects/Test/Textures/textures/dirty_baseColor.dds differ diff --git a/Projects/Test/Textures/textures/forestGround_baseColor.dds b/Projects/Test/Textures/textures/forestGround_baseColor.dds index 57c7c865..2d98c8b8 100644 Binary files a/Projects/Test/Textures/textures/forestGround_baseColor.dds and b/Projects/Test/Textures/textures/forestGround_baseColor.dds differ diff --git a/Projects/Test/Textures/textures/gravel_baseColor.dds b/Projects/Test/Textures/textures/gravel_baseColor.dds index 2f8e134e..e7980fdc 100644 Binary files a/Projects/Test/Textures/textures/gravel_baseColor.dds and b/Projects/Test/Textures/textures/gravel_baseColor.dds differ diff --git a/Projects/Test/Textures/textures/image.dds b/Projects/Test/Textures/textures/image.dds index bd8df43e..4f6d6796 100644 Binary files a/Projects/Test/Textures/textures/image.dds and b/Projects/Test/Textures/textures/image.dds differ diff --git a/Projects/Test/Textures/textures/rockyGrass_baseColor.dds b/Projects/Test/Textures/textures/rockyGrass_baseColor.dds index 6d9ecbab..cbb7c2cd 100644 Binary files a/Projects/Test/Textures/textures/rockyGrass_baseColor.dds and b/Projects/Test/Textures/textures/rockyGrass_baseColor.dds differ diff --git a/Projects/Test/Textures/textures/rockyGround_baseColor.dds b/Projects/Test/Textures/textures/rockyGround_baseColor.dds index dd372024..d3f76dc3 100644 Binary files a/Projects/Test/Textures/textures/rockyGround_baseColor.dds and b/Projects/Test/Textures/textures/rockyGround_baseColor.dds differ diff --git a/Projects/Test/Textures/textures/rockySand_baseColor.dds b/Projects/Test/Textures/textures/rockySand_baseColor.dds index 7911de1b..5a1c876f 100644 Binary files a/Projects/Test/Textures/textures/rockySand_baseColor.dds and b/Projects/Test/Textures/textures/rockySand_baseColor.dds differ diff --git a/Projects/Test/Textures/textures/roughRock_baseColor.dds b/Projects/Test/Textures/textures/roughRock_baseColor.dds index 50d20c82..bcf8ca01 100644 Binary files a/Projects/Test/Textures/textures/roughRock_baseColor.dds and b/Projects/Test/Textures/textures/roughRock_baseColor.dds differ diff --git a/Projects/Test/Textures/textures/sheild_dragone_normal.dds b/Projects/Test/Textures/textures/sheild_dragone_normal.dds index c7e4d6ff..4ff964a8 100644 Binary files a/Projects/Test/Textures/textures/sheild_dragone_normal.dds and b/Projects/Test/Textures/textures/sheild_dragone_normal.dds differ diff --git a/Projects/Test/Textures/textures/snowyRock_baseColor.dds b/Projects/Test/Textures/textures/snowyRock_baseColor.dds index d503fea9..38b6c8de 100644 Binary files a/Projects/Test/Textures/textures/snowyRock_baseColor.dds and b/Projects/Test/Textures/textures/snowyRock_baseColor.dds differ