From d6b5d106c073091d83adf34b47996fb081fbf65e Mon Sep 17 00:00:00 2001 From: Panos Karabelas Date: Fri, 25 Oct 2024 05:34:00 +0100 Subject: [PATCH] [gbuffer] removed specular anti-aliasing since it costs a bit and it's not needed as FSR/TAA cleans it up completely and retains more specular detal --- data/shaders/depth_prepass.hlsl | 2 +- data/shaders/g_buffer.hlsl | 124 +++++++++------------- runtime/Resource/Import/ModelImporter.cpp | 32 +++--- 3 files changed, 68 insertions(+), 90 deletions(-) diff --git a/data/shaders/depth_prepass.hlsl b/data/shaders/depth_prepass.hlsl index a43db3b45..2250ec9b1 100644 --- a/data/shaders/depth_prepass.hlsl +++ b/data/shaders/depth_prepass.hlsl @@ -44,7 +44,7 @@ void main_ps(gbuffer_vertex vertex) const bool has_albedo = f3_value.y == 1.0f; const float alpha = f3_value.z; - float alpha_threshold = get_alpha_threshold(vertex.position); + float alpha_threshold = get_alpha_threshold(vertex.position); // distance based alpha threshold bool mask_alpha = has_alpha_mask && GET_TEXTURE(material_mask).Sample(samplers[sampler_point_wrap], vertex.uv).r <= alpha_threshold; bool mask_albedo = alpha == 1.0f && has_albedo && GET_TEXTURE(material_albedo).Sample(samplers[sampler_anisotropic_wrap], vertex.uv).a <= alpha_threshold; diff --git a/data/shaders/g_buffer.hlsl b/data/shaders/g_buffer.hlsl index 764c09472..3a3d69c4a 100644 --- a/data/shaders/g_buffer.hlsl +++ b/data/shaders/g_buffer.hlsl @@ -21,8 +21,6 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include "common.hlsl" //==================== -static const float g_quality_max_distance = 500.0f; - struct gbuffer { float4 albedo : SV_Target0; @@ -48,14 +46,17 @@ gbuffer_vertex main_vs(Vertex_PosUvNorTan input, uint instance_id : SV_InstanceI gbuffer main_ps(gbuffer_vertex vertex) { - float4 albedo = GetMaterial().color; - float3 normal = vertex.normal.xyz; - float roughness = GetMaterial().roughness; - float metalness = GetMaterial().metallness; - float occlusion = 1.0f; - float emission = 0.0f; - float2 velocity = 0.0f; - + // setup + float4 albedo = GetMaterial().color; + float3 normal = vertex.normal.xyz; + float roughness = GetMaterial().roughness; + float metalness = GetMaterial().metallness; + float occlusion = 1.0f; + float emission = 0.0f; + float2 velocity = 0.0f; + Material material = GetMaterial(); + Surface surface; surface.flags = material.flags; + // velocity { // convert to ndc @@ -70,9 +71,6 @@ gbuffer main_ps(gbuffer_vertex vertex) velocity = ndc_to_uv(position_ndc_current) - ndc_to_uv(position_ndc_previous); } - Material material = GetMaterial(); - Surface surface; surface.flags = material.flags; - // alpha mask float alpha_mask = 1.0f; if (surface.has_texture_alpha_mask()) @@ -99,73 +97,53 @@ gbuffer main_ps(gbuffer_vertex vertex) albedo.a = 1.0f; } - // compute pixel distance - float3 camera_to_pixel_world = buffer_frame.camera_position - vertex.position.xyz; - float pixel_distance = length(camera_to_pixel_world); - - if (pixel_distance < g_quality_max_distance) + // normal mapping + if (surface.has_texture_normal()) { - // normal mapping - if (surface.has_texture_normal()) + // get tangent space normal and apply the user defined intensity, then transform it to world space + float3 normal_sample = sampling::smart(surface, vertex, material_normal).xyz; + float3 tangent_normal = normalize(unpack(normal_sample)); + + // reconstruct z-component as this can be a BC5 two channel normal map + tangent_normal.z = sqrt(max(0.0, 1.0 - tangent_normal.x * tangent_normal.x - tangent_normal.y * tangent_normal.y)); + + float normal_intensity = max(0.012f, GetMaterial().normal); + tangent_normal.xy *= saturate(normal_intensity); + float3x3 tangent_to_world = make_tangent_to_world_matrix(vertex.normal, vertex.tangent); + normal = normalize(mul(tangent_normal, tangent_to_world).xyz); + } + + // roughness + metalness + { + float4 roughness_sample = 1.0f; + if (surface.has_texture_roughness()) { - // get tangent space normal and apply the user defined intensity, then transform it to world space - float3 normal_sample = sampling::smart(surface, vertex, material_normal).xyz; - float3 tangent_normal = normalize(unpack(normal_sample)); + roughness_sample = sampling::smart(surface, vertex, material_roughness); + roughness *= roughness_sample.g; + } - // reconstruct z-component as this can be a BC5 two channel normal map - tangent_normal.z = sqrt(max(0.0, 1.0 - tangent_normal.x * tangent_normal.x - tangent_normal.y * tangent_normal.y)); + float is_single_texture_roughness_metalness = surface.has_single_texture_roughness_metalness() ? 1.0f : 0.0f; + metalness *= (1.0 - is_single_texture_roughness_metalness) + (roughness_sample.b * is_single_texture_roughness_metalness); - float normal_intensity = max(0.012f, GetMaterial().normal); - tangent_normal.xy *= saturate(normal_intensity); - float3x3 tangent_to_world = make_tangent_to_world_matrix(vertex.normal, vertex.tangent); - normal = normalize(mul(tangent_normal, tangent_to_world).xyz); - } - - // roughness + metalness + if (surface.has_texture_metalness() && !surface.has_single_texture_roughness_metalness()) { - float4 roughness_sample = 1.0f; - if (surface.has_texture_roughness()) - { - roughness_sample = sampling::smart(surface, vertex, material_roughness); - roughness *= roughness_sample.g; - } - - float is_single_texture_roughness_metalness = surface.has_single_texture_roughness_metalness() ? 1.0f : 0.0f; - metalness *= (1.0 - is_single_texture_roughness_metalness) + (roughness_sample.b * is_single_texture_roughness_metalness); - - if (surface.has_texture_metalness() && !surface.has_single_texture_roughness_metalness()) - { - metalness *= sampling::smart(surface, vertex, material_metalness).r; - } - } - - // occlusion - if (surface.has_texture_occlusion()) - { - occlusion = sampling::smart(surface, vertex, material_occlusion).r; - } - - // emission - if (surface.has_texture_emissive()) - { - float3 emissive_color = GET_TEXTURE(material_emission).Sample(GET_SAMPLER(sampler_anisotropic_wrap), vertex.uv).rgb; - emission = luminance(emissive_color); - albedo.rgb += emissive_color; - } - - // specular anti-aliasing - { - static const float strength = 1.0f; - static const float max_roughness_gain = 0.02f; - - float roughness2 = roughness * roughness; - float3 dndu = ddx(normal), dndv = ddy(normal); - float variance = (dot(dndu, dndu) + dot(dndv, dndv)); - float kernelRoughness2 = min(variance * strength, max_roughness_gain); - float filteredRoughness2 = saturate(roughness2 + kernelRoughness2); - roughness = fast_sqrt(filteredRoughness2); + metalness *= sampling::smart(surface, vertex, material_metalness).r; } } + + // occlusion + if (surface.has_texture_occlusion()) + { + occlusion = sampling::smart(surface, vertex, material_occlusion).r; + } + + // emission + if (surface.has_texture_emissive()) + { + float3 emissive_color = GET_TEXTURE(material_emission).Sample(GET_SAMPLER(sampler_anisotropic_wrap), vertex.uv).rgb; + emission = luminance(emissive_color); + albedo.rgb += emissive_color; + } // write to g-buffer gbuffer g_buffer; diff --git a/runtime/Resource/Import/ModelImporter.cpp b/runtime/Resource/Import/ModelImporter.cpp index 4af8a4981..6eae7a556 100644 --- a/runtime/Resource/Import/ModelImporter.cpp +++ b/runtime/Resource/Import/ModelImporter.cpp @@ -55,7 +55,7 @@ namespace Spartan bool model_is_gltf = false; const aiScene* scene = nullptr; - Matrix convert_matrix(const aiMatrix4x4& transform) + Matrix to_matrix(const aiMatrix4x4& transform) { return Matrix ( @@ -66,27 +66,27 @@ namespace Spartan ); } - Color convert_color(const aiColor4D& ai_color) + Color to_color(const aiColor4D& ai_color) { return Color(ai_color.r, ai_color.g, ai_color.b, ai_color.a); } - Color convert_color(const aiColor3D& ai_color) + Color to_color(const aiColor3D& ai_color) { return Color(ai_color.r, ai_color.g, ai_color.b, 1.0f); } - Vector3 convert_vector3(const aiVector3D& ai_vector) + Vector3 to_vector3(const aiVector3D& ai_vector) { return Vector3(ai_vector.x, ai_vector.y, ai_vector.z); } - Vector2 convert_vector2(const aiVector2D& ai_vector) + Vector2 to_vector2(const aiVector2D& ai_vector) { return Vector2(ai_vector.x, ai_vector.y); } - Quaternion convert_quaternion(const aiQuaternion& ai_quaternion) + Quaternion to_quaternion(const aiQuaternion& ai_quaternion) { return Quaternion(ai_quaternion.x, ai_quaternion.y, ai_quaternion.z, ai_quaternion.w); } @@ -94,7 +94,7 @@ namespace Spartan void set_entity_transform(const aiNode* node, shared_ptr entity) { // convert to engine matrix - const Matrix matrix_engine = convert_matrix(node->mTransformation); + const Matrix matrix_engine = to_matrix(node->mTransformation); // apply position, rotation and scale entity->SetPositionLocal(matrix_engine.GetTranslation()); @@ -102,7 +102,7 @@ namespace Spartan entity->SetScaleLocal(matrix_engine.GetScale()); } - constexpr void compute_node_count(const aiNode* node, uint32_t* count) + void compute_node_count(const aiNode* node, uint32_t* count) { if (!node) return; @@ -608,11 +608,11 @@ namespace Spartan light->SetFlag(LightFlags::Volumetric, false); // local transform - light->GetEntity()->SetPositionLocal(convert_vector3(light_assimp->mPosition)); - light->GetEntity()->SetRotationLocal(Quaternion::FromLookRotation(convert_vector3(light_assimp->mDirection))); + light->GetEntity()->SetPositionLocal(to_vector3(light_assimp->mPosition)); + light->GetEntity()->SetRotationLocal(Quaternion::FromLookRotation(to_vector3(light_assimp->mDirection))); // color - light->SetColor(convert_color(light_assimp->mColorDiffuse)); + light->SetColor(to_color(light_assimp->mColorDiffuse)); // type if (light_assimp->mType == aiLightSource_DIRECTIONAL) @@ -644,7 +644,7 @@ namespace Spartan const uint32_t index_count = assimp_mesh->mNumFaces * 3; // vertices - vector vertices = vector(vertex_count); + vector vertices(vertex_count); { for (uint32_t i = 0; i < vertex_count; i++) { @@ -686,7 +686,7 @@ namespace Spartan } // indices - vector indices = vector(index_count); + vector indices(index_count); { // get indices by iterating through each face of the mesh. for (uint32_t face_index = 0; face_index < assimp_mesh->mNumFaces; face_index++) @@ -762,7 +762,7 @@ namespace Spartan for (uint32_t k = 0; k < static_cast(assimp_node_anim->mNumPositionKeys); k++) { const auto time = assimp_node_anim->mPositionKeys[k].mTime; - const auto value = convert_vector3(assimp_node_anim->mPositionKeys[k].mValue); + const auto value = to_vector3(assimp_node_anim->mPositionKeys[k].mValue); animation_node.positionFrames.emplace_back(KeyVector{ time, value }); } @@ -771,7 +771,7 @@ namespace Spartan for (uint32_t k = 0; k < static_cast(assimp_node_anim->mNumRotationKeys); k++) { const auto time = assimp_node_anim->mPositionKeys[k].mTime; - const auto value = convert_quaternion(assimp_node_anim->mRotationKeys[k].mValue); + const auto value = to_quaternion(assimp_node_anim->mRotationKeys[k].mValue); animation_node.rotationFrames.emplace_back(KeyQuaternion{ time, value }); } @@ -780,7 +780,7 @@ namespace Spartan for (uint32_t k = 0; k < static_cast(assimp_node_anim->mNumScalingKeys); k++) { const auto time = assimp_node_anim->mPositionKeys[k].mTime; - const auto value = convert_vector3(assimp_node_anim->mScalingKeys[k].mValue); + const auto value = to_vector3(assimp_node_anim->mScalingKeys[k].mValue); animation_node.scaleFrames.emplace_back(KeyVector{ time, value }); }