From f3b6ed31dc6ac031fc2725520208ba4d5bdc7319 Mon Sep 17 00:00:00 2001 From: Dynamitos Date: Fri, 27 Dec 2024 17:06:43 +0100 Subject: [PATCH] More tangent changes --- res/shaders/BasePass.slang | 3 +- res/shaders/DepthCullingMesh.slang | 2 +- res/shaders/DrawListMesh.slang | 2 +- res/shaders/lib/BRDF.slang | 42 +++--- res/shaders/lib/LightEnv.slang | 11 +- res/shaders/lib/MaterialParameter.slang | 88 ++++++++---- res/shaders/lib/StaticMeshVertexData.slang | 25 +--- res/shaders/raytracing/ClosestHit.slang | 8 +- res/shaders/raytracing/RayGen.slang | 2 +- src/Editor/Asset/MeshLoader.cpp | 72 +++++----- src/Editor/Asset/MeshLoader.h | 2 +- src/Editor/main.cpp | 13 +- src/Engine/Graphics/RenderPass/BasePass.cpp | 4 +- src/Engine/Graphics/StaticMeshVertexData.cpp | 134 ++++++++++++++----- src/Engine/Graphics/StaticMeshVertexData.h | 30 +++-- 15 files changed, 275 insertions(+), 163 deletions(-) diff --git a/res/shaders/BasePass.slang b/res/shaders/BasePass.slang index 3bb6f3e..96ae0ae 100644 --- a/res/shaders/BasePass.slang +++ b/res/shaders/BasePass.slang @@ -35,5 +35,4 @@ float4 fragmentMain(in FragmentParameter params) : SV_Target //result = result / (result + float3(1.0)); //result = pow(result, float3(1.0/2.2)); return float4(result, brdf.getAlpha()); -} - \ No newline at end of file +} \ No newline at end of file diff --git a/res/shaders/DepthCullingMesh.slang b/res/shaders/DepthCullingMesh.slang index d2e07b2..1e2e84a 100644 --- a/res/shaders/DepthCullingMesh.slang +++ b/res/shaders/DepthCullingMesh.slang @@ -52,7 +52,7 @@ void meshMain( { uint vertexIndex = pScene.vertexIndices[m.vertexOffset + v]; VertexAttributes attr = pVertexData.getAttributes(m.indicesOffset + vertexIndex); - vertices[v] = attr.getParameter(inst.transformMatrix); + vertices[v] = attr.getParameter(inst.transformMatrix, inst.inverseTransformMatrix); } } } \ No newline at end of file diff --git a/res/shaders/DrawListMesh.slang b/res/shaders/DrawListMesh.slang index 5768075..84b9d95 100644 --- a/res/shaders/DrawListMesh.slang +++ b/res/shaders/DrawListMesh.slang @@ -54,7 +54,7 @@ void meshMain( { uint vertexIndex = pScene.vertexIndices[m.vertexOffset + v]; VertexAttributes attr = pVertexData.getAttributes(m.indicesOffset + vertexIndex); - vertices[v] = attr.getParameter(inst.transformMatrix); + vertices[v] = attr.getParameter(inst.transformMatrix, inst.inverseTransformMatrix); } } } \ No newline at end of file diff --git a/res/shaders/lib/BRDF.slang b/res/shaders/lib/BRDF.slang index 7685dd3..bed7578 100644 --- a/res/shaders/lib/BRDF.slang +++ b/res/shaders/lib/BRDF.slang @@ -2,7 +2,7 @@ import Common; interface IBRDF { - float3 evaluate(float3 viewDir_TS, float3 lightDir_TS, float3 lightColor); + float3 evaluate(float3x3 tangentToWorld, float3 viewDir_WS, float3 lightDir_WS, float3 lightColor); float3 evaluateAmbient(); float getAlpha(); float3 getTangentNormal(); @@ -27,12 +27,12 @@ struct Phong : IBRDF shininess = 0; } - float3 evaluate(float3 viewDir_TS, float3 lightDir_TS, float3 lightColor) + float3 evaluate(float3x3 tangentToWorld, float3 viewDir_WS, float3 lightDir_WS, float3 lightColor) { - float3 normal_TS = normal; - float3 nDotL = dot(normal_TS, lightDir_TS); - float3 r = 2 * (nDotL) * normal_TS - lightDir_TS; - float rDotV = dot(r, viewDir_TS); + float3 normal_WS = normalize(mul(tangentToWorld, normal)); + float3 nDotL = dot(normal_WS, lightDir_WS); + float3 r = 2 * (nDotL) * normal_WS - lightDir_WS; + float rDotV = dot(r, viewDir_WS); return lightColor * (baseColor * max(nDotL, 0.0));// + specular * pow(max(rDotV, 0.0), max(shininess, 1))); } @@ -70,12 +70,12 @@ struct BlinnPhong : IBRDF ambient = float3(0, 0, 0); } - float3 evaluate(float3 viewDir_TS, float3 lightDir_TS, float3 lightColor) + float3 evaluate(float3x3 tangentToWorld, float3 viewDir_WS, float3 lightDir_WS, float3 lightColor) { - float3 normal_TS = normalize(normal); - float diffuse = max(dot(normal_TS, lightDir_TS), 0); - float3 h = normalize(lightDir_TS + viewDir_TS); - float specular = pow(saturate(dot(normal_TS, h)), shininess); + float3 normal_WS = normalize(mul(tangentToWorld, normal)); + float diffuse = max(dot(normal_WS, lightDir_WS), 0); + float3 h = normalize(lightDir_WS + viewDir_WS); + float specular = pow(saturate(dot(normal_WS, h)), shininess); return (baseColor * diffuse * lightColor) + (specularColor * specular); } @@ -107,10 +107,10 @@ struct CelShading : IBRDF normal = float3(0, 0, 1); } - float3 evaluate(float3 viewDir_TS, float3 lightDir_TS, float3 lightColor) + float3 evaluate(float3x3 tangentToWorld, float3 viewDir_WS, float3 lightDir_WS, float3 lightColor) { - float3 normal_TS = normalize(normal); - float nDotL = dot(normal_TS, lightDir_TS); + float3 normal_WS = normalize(mul(tangentToWorld, normal)); + float nDotL = dot(normal_WS, lightDir_WS); float diffuse = max(nDotL, 0); float3 darkenedBase = baseColor * 0.8; @@ -189,21 +189,21 @@ struct CookTorrance : IBRDF return F0 + (1.0 - F0) * pow(clamp(1.0 - cosTheta, 0.0, 1.0), 5.0); } - float3 evaluate(float3 viewDir_TS, float3 lightDir_TS, float3 lightColor) + float3 evaluate(float3x3 tangentToWorld, float3 viewDir_WS, float3 lightDir_WS, float3 lightColor) { - float3 n = normal;//normalize(mul(tbn, normal)); - float3 h = normalize(lightDir_TS + viewDir_TS); + float3 n = normalize(mul(tangentToWorld, normal)); + float3 h = normalize(lightDir_WS + viewDir_WS); float3 F0 = float3(0.04); F0 = lerp(F0, baseColor, metallic); - float3 F = FresnelSchlick(max(dot(h, viewDir_TS), 0.0), F0); + float3 F = FresnelSchlick(max(dot(h, viewDir_WS), 0.0), F0); float NDF = TrowbridgeReitzGGX(n, h); - float G = Smith(n, viewDir_TS, lightDir_TS); + float G = Smith(n, viewDir_WS, lightDir_WS); float3 num = NDF * G * F; - float denom = 4.0 * max(dot(n, viewDir_TS), 0.0) * max(dot(n, lightDir_TS), 0.0) + 0.000001; + float denom = 4.0 * max(dot(n, viewDir_WS), 0.0) * max(dot(n, lightDir_WS), 0.0) + 0.000001; float3 specular = num / denom; float3 k_s = F; @@ -211,7 +211,7 @@ struct CookTorrance : IBRDF k_d *= 1.0 - metallic; - float nDotL = max(dot(n, lightDir_TS), 0.0); + float nDotL = max(dot(n, lightDir_WS), 0.0); float3 result = (k_d * baseColor / PI + specular) * nDotL * lightColor; return result * ambientOcclusion; diff --git a/res/shaders/lib/LightEnv.slang b/res/shaders/lib/LightEnv.slang index b3e87f9..12b9211 100644 --- a/res/shaders/lib/LightEnv.slang +++ b/res/shaders/lib/LightEnv.slang @@ -14,8 +14,8 @@ struct DirectionalLight : ILightEnv float3 illuminate(LightingParameter params, B brdf) { - float3 dir_TS = mul(params.worldToTangent, -normalize(direction.xyz)); - return brdf.evaluate(params.viewDir_TS, dir_TS, color.xyz); + float3 dir_WS = normalize(direction.xyz); + return brdf.evaluate(params.tangentToWorld, params.viewDir_WS, dir_WS, color.xyz); } }; @@ -26,11 +26,10 @@ struct PointLight : ILightEnv float3 illuminate(LightingParameter params, B brdf) { - float3 pos_TS = mul(params.worldToTangent, position_WS.xyz); - float3 lightDir_TS = pos_TS.xyz - params.position_TS; - float d = length(lightDir_TS); + float3 lightDir_WS = position_WS.xyz - params.position_WS; + float d = length(lightDir_WS); float illuminance = max(1 - d / colorRange.w, 0); - return illuminance * brdf.evaluate(params.viewDir_TS, normalize(lightDir_TS), colorRange.xyz); + return illuminance * brdf.evaluate(params.tangentToWorld, params.viewDir_WS, normalize(lightDir_WS), colorRange.xyz); } bool insidePlane(Plane plane, float3 position) diff --git a/res/shaders/lib/MaterialParameter.slang b/res/shaders/lib/MaterialParameter.slang index 2497619..c7cff0a 100644 --- a/res/shaders/lib/MaterialParameter.slang +++ b/res/shaders/lib/MaterialParameter.slang @@ -9,18 +9,50 @@ struct MaterialParameter struct LightingParameter { - float3x3 worldToTangent; - float3 viewDir_TS; - float3 position_TS; + float3x3 tangentToWorld; + float3 viewDir_WS; + float3 position_WS; } -// Constructs a TBN matrix from a unpacked qtangent for example for after vertex interpolation in the fragment shader -float3x3 constructTBNFromQTangent(float4 q){ - q = normalize(q); // Ensure that the quaternion is normalized in case it is not, for example after interpolation and so on - float3 t2 = q.xyz * 2.0, tx = q.xxx * t2.xyz, ty = q.yyy * t2.xyz, tz = q.www * t2.xyz; - float3 tangent = float3(1.0 - (ty.y + (q.z * t2.z)), tx.y + tz.z, tx.z - tz.y); - float3 normal = float3(tx.z + tz.y, ty.z - tz.x, 1.0 - (tx.x + ty.y)); - return float3x3(tangent, cross(tangent, normal) * ((q.w < 0.0) ? -1.0 : 1.0), normal); + +float3x3 qTangentToMatrix(float4 q){ + q = normalize(q); + float qx2 = q.x + q.x; + float qy2 = q.y + q.y; + float qz2 = q.z + q.z; + float qxqx2 = q.x * qx2; + float qxqy2 = q.x * qy2; + float qxqz2 = q.x * qz2; + float qxqw2 = q.w * qx2; + float qyqy2 = q.y * qy2; + float qyqz2 = q.y * qz2; + float qyqw2 = q.w * qy2; + float qzqz2 = q.z * qz2; + float qzqw2 = q.w * qz2; + float3x3 m = float3x3(1.0 - (qyqy2 + qzqz2), qxqy2 + qzqw2, qxqz2 - qyqw2, + qxqy2 - qzqw2, 1.0 - (qxqx2 + qzqz2), qyqz2 + qxqw2, + qxqz2 + qyqw2, qyqz2 - qxqw2, 1.0 - (qxqx2 + qyqy2)); + m[2] = normalize(cross(m[0], m[1])) * ((q.w < 0.0) ? -1.0 : 1.0); + return m; +} + +float4 qTangentSlerp(float4 q0, float4 q1, float t){ + float co = dot(q0, q1), so, s0, s1, s2 = 1.0, Omega; + if(co < 0.0){ + co = -co; + s2 = -s2; + } + if((1.0 - co) > 1e-8){ + Omega = acos(co); + so = sin(Omega); + s0 = sin((1.0 - t) * Omega) / so; + s1 = sin(t * Omega) / so; + } else { + s0 = 1.0 - t; + s1 = t; + } + float4 r = ((q0 * s0) + (q1 * (s1 * s2))); + return r * ((((q0.w < 0.0) || (q1.w < 0.0)) != (r.w < 0.0)) ? -1.0 : 1.0); } // data passed to fragment shader @@ -28,10 +60,10 @@ struct FragmentParameter { float4 position_CS : SV_Position; #ifndef POS_ONLY - float4 qTangent : QTANGENT; + float3 normal_WS : NORMALWS; + float3 tangent_WS : TANGENTWS; + float3 biTangent_WS : BITANGENTWS; float3 position_WS : POSITIONWS; - float3 position_TS : POSITIONTS; - float3 cameraPos_TS : CAMPOSTS; float3 vertexColor : COLOR; float4 texCoords0 : TEXCOORDS0; float4 texCoords1 : TEXCOORDS1; @@ -55,17 +87,16 @@ struct FragmentParameter LightingParameter getLightingParameter() { - float3x3 worldToTangent = transpose(constructTBNFromQTangent(qTangent)); LightingParameter result; - result.worldToTangent = worldToTangent; - result.viewDir_TS = cameraPos_TS - position_TS; - result.position_TS = position_TS; + result.tangentToWorld = getTangentToWorld(); + result.viewDir_WS = normalize(pViewParams.cameraPosition_WS.xyz - position_WS); + result.position_WS = position_WS; return result; } float3x3 getTangentToWorld() { - return constructTBNFromQTangent(qTangent); + return float3x3(normalize(tangent_WS), normalize(biTangent_WS), normalize(normal_WS)); } #endif static FragmentParameter interpolate(FragmentParameter f0, FragmentParameter f1, FragmentParameter f2, float3 barycentricCoords) @@ -73,14 +104,15 @@ struct FragmentParameter FragmentParameter result; result.position_CS = f0.position_CS * barycentricCoords.x + f1.position_CS * barycentricCoords.y + f2.position_CS * barycentricCoords.z; #ifndef POS_ONLY - result.qTangent = f0.qTangent * barycentricCoords.x + f1.qTangent * barycentricCoords.y + f2.qTangent * barycentricCoords.z; - result.position_WS = f0.position_WS * barycentricCoords.x + f1.position_WS * barycentricCoords.y + f2.position_WS * barycentricCoords.z; + result.normal_WS = f0.normal_WS * barycentricCoords.x + f1.normal_WS * barycentricCoords.y + f2.normal_WS * barycentricCoords.z; + result.tangent_WS = f0.tangent_WS * barycentricCoords.x + f1.tangent_WS * barycentricCoords.y + f2.tangent_WS * barycentricCoords.z; + result.biTangent_WS = f0.biTangent_WS * barycentricCoords.x + f1.biTangent_WS * barycentricCoords.y + f2.biTangent_WS * barycentricCoords.z; + result.position_WS = f0.position_WS * barycentricCoords.x + f1.position_WS * barycentricCoords.y + f2.position_WS * barycentricCoords.z; result.vertexColor = f0.vertexColor * barycentricCoords.x + f1.vertexColor * barycentricCoords.y + f2.vertexColor * barycentricCoords.z; result.texCoords0 = f0.texCoords0 * barycentricCoords.x + f1.texCoords0 * barycentricCoords.y + f2.texCoords0 * barycentricCoords.z; result.texCoords1 = f0.texCoords1 * barycentricCoords.x + f1.texCoords1 * barycentricCoords.y + f2.texCoords1 * barycentricCoords.z; result.texCoords2 = f0.texCoords2 * barycentricCoords.x + f1.texCoords2 * barycentricCoords.y + f2.texCoords2 * barycentricCoords.z; result.texCoords3 = f0.texCoords3 * barycentricCoords.x + f1.texCoords3 * barycentricCoords.y + f2.texCoords3 * barycentricCoords.z; - #endif return result; } @@ -91,11 +123,13 @@ struct VertexAttributes { float3 position_MS; #ifndef POS_ONLY - float4 qTangent; + float3 normal_MS; + float3 tangent_MS; + float3 biTangent_MS; float3 vertexColor; float2 texCoords[MAX_TEXCOORDS]; #endif - FragmentParameter getParameter(float4x4 transformMatrix) + FragmentParameter getParameter(float4x4 transformMatrix, float4x4 inverseTransformMatrix) { float4 modelPos = float4(position_MS, 1); float4 worldPos = mul(transformMatrix, modelPos); @@ -104,12 +138,12 @@ struct VertexAttributes FragmentParameter result; result.position_CS = clipPos; #ifndef POS_ONLY - result.qTangent = qTangent; - float3x3 tbn = constructTBNFromQTangent(qTangent); - result.position_TS = mul(tbn, worldPos.xyz); + float3x3 normalMatrix = transpose(float3x3(inverseTransformMatrix)); + result.tangent_WS = mul(normalMatrix, tangent_MS); + result.biTangent_WS = mul(normalMatrix, biTangent_MS); + result.normal_WS = mul(normalMatrix, normal_MS); result.vertexColor = vertexColor; result.position_WS = worldPos.xyz; - result.cameraPos_TS = mul(tbn, pViewParams.cameraPosition_WS.xyz); result.texCoords0 = float4(texCoords[0], texCoords[1]); result.texCoords1 = float4(texCoords[2], texCoords[3]); result.texCoords2 = float4(texCoords[4], texCoords[5]); diff --git a/res/shaders/lib/StaticMeshVertexData.slang b/res/shaders/lib/StaticMeshVertexData.slang index 5c6a1c2..32d667e 100644 --- a/res/shaders/lib/StaticMeshVertexData.slang +++ b/res/shaders/lib/StaticMeshVertexData.slang @@ -9,29 +9,14 @@ struct StaticMeshVertexData return value / 65535.0f; } - float3x3 decodeQTangentUI32(uint v){ - float4 q = float4(((float3(int3(uint3((uint3(v) >> uint3(0u, 10u, 20u)) & uint2(0x3ffu, 0x1ffu).xxy)) - int2(512, 256).xxy)) / float2(511.0, 255.0).xxy) * 0.7071067811865475, 0.0); - q.w = sqrt(1.0 - clamp(dot(q.xyz, q.xyz), 0.0, 1.0)); - q = normalize(float4[4](q.wxyz, q.xwyz, q.xywz, q.xyzw)[uint((v >> 30u) & 0x3u)]); - float3 t2 = q.xyz * 2.0, tx = q.xxx * t2.xyz, ty = q.yyy * t2.xyz, tz = q.www * t2.xyz; - float3 tangent = float3(1.0 - (ty.y + (q.z * t2.z)), tx.y + tz.z, tx.z - tz.y); - float3 normal = float3(tx.z + tz.y, ty.z - tz.x, 1.0 - (tx.x + ty.y)); - return float3x3(tangent, cross(tangent, normal) * (((v & (1u << 29u)) != 0u) ? -1.0 : 1.0), normal); - } - - // Decodes the UI32 encoded qtangent into a unpacked qtangent for further processing like vertex interpolation and so on - float4 decodeQTangentUI32Raw(uint v){ - float4 q = float4(((float3(int3(uint3((uint3(v) >> uint3(0u, 10u, 20u)) & uint2(0x3ffu, 0x1ffu).xxy)) - int2(512, 256).xxy)) / float2(511.0, 255.0).xxy) * 0.7071067811865475, 0.0); - q.w = sqrt(1.0 - clamp(dot(q.xyz, q.xyz), 0.0, 1.0)); - return normalize(float4[4](q.wxyz, q.xwyz, q.xywz, q.xyzw)[uint((v >> 30u) & 0x3u)]) * (((v & (1u << 29u)) != 0u) ? -1.0 : 1.0); - } - VertexAttributes getAttributes(uint index) { VertexAttributes attributes; attributes.position_MS = float3(positions[index * 3 + 0], positions[index * 3 + 1], positions[index * 3 + 2]); #ifndef POS_ONLY - attributes.qTangent = decodeQTangentUI32Raw(qtangents[index]); + attributes.normal_MS = float3(normals[index * 3 + 0], normals[index * 3 + 1], normals[index * 3 + 2]); + attributes.tangent_MS = float3(tangents[index * 3 + 0], tangents[index * 3 + 1], tangents[index * 3 + 2]); + attributes.biTangent_MS = float3(biTangents[index * 3 + 0], biTangents[index * 3 + 1], biTangents[index * 3 + 2]); for(uint i = 0; i < MAX_TEXCOORDS; ++i) { attributes.texCoords[i] = float2(uint16ToFloat(texCoords[i][index * 2 + 0]), uint16ToFloat(texCoords[i][index * 2 + 1])); @@ -41,7 +26,9 @@ struct StaticMeshVertexData return attributes; } StructuredBuffer positions; - StructuredBuffer qtangents; + StructuredBuffer normals; + StructuredBuffer tangents; + StructuredBuffer biTangents; StructuredBuffer color; StructuredBuffer texCoords[MAX_TEXCOORDS]; }; diff --git a/res/shaders/raytracing/ClosestHit.slang b/res/shaders/raytracing/ClosestHit.slang index 4fc7c07..e7e14e0 100644 --- a/res/shaders/raytracing/ClosestHit.slang +++ b/res/shaders/raytracing/ClosestHit.slang @@ -30,9 +30,9 @@ void closestHit(inout RayPayload hitValue, in BuiltInTriangleIntersectionAttribu VertexAttributes attr1 = pVertexData.getAttributes(vertexIndex1); VertexAttributes attr2 = pVertexData.getAttributes(vertexIndex2); - FragmentParameter f0 = attr0.getParameter(inst.transformMatrix); - FragmentParameter f1 = attr1.getParameter(inst.transformMatrix); - FragmentParameter f2 = attr2.getParameter(inst.transformMatrix); + FragmentParameter f0 = attr0.getParameter(inst.transformMatrix, inst.inverseTransformMatrix); + FragmentParameter f1 = attr1.getParameter(inst.transformMatrix, inst.inverseTransformMatrix); + FragmentParameter f2 = attr2.getParameter(inst.transformMatrix, inst.inverseTransformMatrix); FragmentParameter params = FragmentParameter.interpolate(f0, f1, f2, barycentricCoords); @@ -43,6 +43,6 @@ void closestHit(inout RayPayload hitValue, in BuiltInTriangleIntersectionAttribu hitValue.material.color = float4(brdf.baseColor, 1); hitValue.material.emissive = float3(0, 0, 0); hitValue.shading.position = WorldRayOrigin() + RayTCurrent() * WorldRayDirection(); - hitValue.shading.normal = cross(f2.position_WS - f0.position_WS, f1.position_WS - f0.position_WS); + hitValue.shading.normal = mul(params.getTangentToWorld(), brdf.normal); hitValue.shading.normalLight = dot(hitValue.shading.normal, WorldRayDirection()) < 0 ? hitValue.shading.normal : -hitValue.shading.normal; } \ No newline at end of file diff --git a/res/shaders/raytracing/RayGen.slang b/res/shaders/raytracing/RayGen.slang index 1fda7a8..c0f13d6 100644 --- a/res/shaders/raytracing/RayGen.slang +++ b/res/shaders/raytracing/RayGen.slang @@ -10,7 +10,7 @@ struct Ray const static float S_O = 6.9; const static float f = 0.035; -const static float A = 0.4; +const static float A = 0.04; const static float ka = 0; const static float ks = 0; const static float3 fogEmm = float3(0, 0.01, 0.01); diff --git a/src/Editor/Asset/MeshLoader.cpp b/src/Editor/Asset/MeshLoader.cpp index 3cbd956..57e64d9 100644 --- a/src/Editor/Asset/MeshLoader.cpp +++ b/src/Editor/Asset/MeshLoader.cpp @@ -462,40 +462,44 @@ void MeshLoader::findMeshRoots(aiNode* node, List& meshNodes) { } } -uint32 MeshLoader::encodeQTangent(Matrix3 m) { - float r = (glm::determinant(m) ? -1.0 : 1.0); - m[2] *= r; +Vector4 MeshLoader::encodeQTangent(Matrix3 m) { + float f = 1.0; + if (((((((m[0][0] * m[1][1] * m[2][2]) + (m[0][1] * m[1][2] * m[2][0])) + (m[0][2] * m[1][0] * m[2][1])) - + (m[0][2] * m[1][1] * m[2][0])) - + (m[0][1] * m[1][0] * m[2][2])) - + (m[0][0] * m[1][2] * m[2][1])) < 0.0) { + f = -1.0; + m[2] = -m[2]; + } float t = m[0][0] + (m[1][1] + m[2][2]); - Vector4 q; + Vector4 r; if (t > 2.9999999) { - q = Vector4(0.0, 0.0, 0.0, 1.0); + r = Vector4(0.0, 0.0, 0.0, 1.0); } else if (t > 0.0000001) { float s = sqrt(1.0 + t) * 2.0; - q = Vector4(Vector(m[1][2] - m[2][1], m[2][0] - m[0][2], m[0][1] - m[1][0]) / s, s * 0.25); + r = Vector4(Vector(m[1][2] - m[2][1], m[2][0] - m[0][2], m[0][1] - m[1][0]) / s, s * 0.25); } else if ((m[0][0] > m[1][1]) && (m[0][0] > m[2][2])) { float s = sqrt(1.0 + (m[0][0] - (m[1][1] + m[2][2]))) * 2.0; - q = Vector4(s * 0.25, Vector(m[1][0] + m[0][1], m[2][0] + m[0][2], m[1][2] - m[2][1]) / s); + r = Vector4(s * 0.25, Vector(m[1][0] - m[0][1], m[2][0] - m[0][2], m[0][2] - m[2][1]) / s); } else if (m[1][1] > m[2][2]) { float s = sqrt(1.0 + (m[1][1] - (m[0][0] + m[2][2]))) * 2.0; - q = Vector4(Vector(m[1][0] + m[0][1], m[2][1] + m[1][2], m[2][0] - m[0][2]) / s, s * 0.25); - q = Vector4(q.x, q.w, q.y, q.z); + r = Vector4(Vector(m[1][0] + m[0][1], m[2][1] + m[1][2], m[2][0] - m[0][2]) / s, s * 0.25); + r = Vector4(r.x, r.w, r.y, r.z); } else { float s = sqrt(1.0 + (m[2][2] - (m[0][0] + m[1][1]))) * 2.0; - q = Vector4(Vector(m[2][0] + m[0][2], m[2][1] + m[1][2], m[0][1] - m[1][0]) / s, s * 0.25); - q = Vector4(q.x, q.y, q.w, q.z); + r = Vector4(Vector(m[2][0] + m[0][2], m[2][1] + m[1][2], m[0][1] - m[1][0]) / s, s * 0.25); + r = Vector4(r.x, r.y, r.w, r.z); } - Vector4 qAbs = abs(q = glm::normalize(q)); - int maxComponentIndex = (qAbs.x > qAbs.y) ? ((qAbs.x > qAbs.z) ? ((qAbs.x > qAbs.w) ? 0 : 3) : ((qAbs.z > qAbs.w) ? 2 : 3)) - : ((qAbs.y > qAbs.z) ? ((qAbs.y > qAbs.w) ? 1 : 3) : ((qAbs.z > qAbs.w) ? 2 : 3)); - Vector components[4] = {Vector(q.y, q.z, q.w), Vector(q.x, q.z, q.w), Vector(q.x, q.y, q.w), Vector(q.x, q.y, q.z)}; - - q = Vector4(components[maxComponentIndex] * float(((q[maxComponentIndex] < 0.0) ? -1.0 : 1.0) * 1.4142135623730951), q.w); - return ((uint32(round(glm::clamp(q.x * 511.0, -511.0, 511.0) + 512.0)) & 0x3ffu) << 0u) | - ((uint32(round(glm::clamp(q.y * 511.0, -511.0, 511.0) + 512.0)) & 0x3ffu) << 10u) | - ((uint32(round(glm::clamp(q.z * 255.0, -255.0, 255.0) + 256.0)) & 0x1ffu) << 20u) | - ((uint32(((dot(cross(m[0], m[2]), m[1]) * r) < 0.0) ? 1u : 0u) & 0x1u) << 29u) | ((uint32(maxComponentIndex) & 0x3u) << 30u); + r = normalize(r); + const float threshold = 1.0 / 32767.0; + if (r.w <= threshold) { + r = Vector4(Vector(r) * (float)sqrt(1.0 - (threshold * threshold)), (r.w > 0.0) ? threshold : -threshold); + } + if (((f < 0.0) && (r.w >= 0.0)) || ((f >= 0.0) && (r.w < 0.0))) { + r = -r; + } + return r; } - void MeshLoader::loadGlobalMeshes(const aiScene* scene, const Array& materials, Array& globalMeshes, Component::Collider& collider) { List> work; @@ -512,13 +516,15 @@ void MeshLoader::loadGlobalMeshes(const aiScene* scene, const ArraymAABB.mMax.x, mesh->mAABB.mMax.y, mesh->mAABB.mMax.z)); work.add([=, this, &globalMeshes]() { // assume static mesh for now - Array positions(mesh->mNumVertices); - StaticArray, MAX_TEXCOORDS> texCoords; + Array positions(mesh->mNumVertices); + StaticArray, MAX_TEXCOORDS> texCoords; for (size_t i = 0; i < MAX_TEXCOORDS; ++i) { texCoords[i].resize(mesh->mNumVertices); } - Array normals(mesh->mNumVertices); - Array colors(mesh->mNumVertices); + Array normals(mesh->mNumVertices); + Array tangents(mesh->mNumVertices); + Array biTangents(mesh->mNumVertices); + Array colors(mesh->mNumVertices); for (int32 i = 0; i < mesh->mNumVertices; ++i) { positions[i] = Vector(mesh->mVertices[i].x, mesh->mVertices[i].y, mesh->mVertices[i].z); @@ -536,14 +542,14 @@ void MeshLoader::loadGlobalMeshes(const aiScene* scene, const ArraymTangents[i].x, mesh->mTangents[i].y, mesh->mTangents[i].z); biTangent = Vector(mesh->mBitangents[i].x, mesh->mBitangents[i].y, mesh->mBitangents[i].z); } - Matrix3 tbn = {normal, biTangent, tangent}; - - normals[i] = encodeQTangent(tbn); + normals[i] = normal; + tangents[i] = tangent; + biTangents[i] = biTangent; if (mesh->HasVertexColors(0)) { - colors[i] = U16Vector(mesh->mColors[0][i].r * 65535, mesh->mColors[0][i].g * 65535, mesh->mColors[0][i].b * 65535); + colors[i] = StaticMeshVertexData::ColorType(mesh->mColors[0][i].r * 65535, mesh->mColors[0][i].g * 65535, mesh->mColors[0][i].b * 65535); } else { - colors[i] = U16Vector(1, 1, 1); + colors[i] = StaticMeshVertexData::ColorType(1, 1, 1); } } vertexData->loadPositions(offset, positions); @@ -552,6 +558,8 @@ void MeshLoader::loadGlobalMeshes(const aiScene* scene, const ArrayloadTexCoords(offset, i, texCoords[i]); } vertexData->loadNormals(offset, normals); + vertexData->loadTangents(offset, tangents); + vertexData->loadBitangents(offset, biTangents); vertexData->loadColors(offset, colors); Array indices(mesh->mNumFaces * 3); @@ -575,7 +583,7 @@ void MeshLoader::loadGlobalMeshes(const aiScene* scene, const Arrayblas = graphics->createBottomLevelAccelerationStructure(Gfx::BottomLevelASCreateInfo{ .mesh = globalMeshes[meshIndex], }); - // vertexData->registerBottomLevelAccelerationStructure(globalMeshes[meshIndex]->blas); + vertexData->registerBottomLevelAccelerationStructure(globalMeshes[meshIndex]->blas); }); } getThreadPool().runAndWait(std::move(work)); diff --git a/src/Editor/Asset/MeshLoader.h b/src/Editor/Asset/MeshLoader.h index f50780b..fd4379e 100644 --- a/src/Editor/Asset/MeshLoader.h +++ b/src/Editor/Asset/MeshLoader.h @@ -26,7 +26,7 @@ class MeshLoader { private: void findMeshRoots(aiNode* node, List& meshNodes); - uint32 encodeQTangent(Matrix3 m); + Vector4 encodeQTangent(Matrix3 m); void loadTextures(const aiScene* scene, const std::filesystem::path& meshDirectory, const std::string& importPath, Array& textures); diff --git a/src/Editor/main.cpp b/src/Editor/main.cpp index 1e99107..b7e5c3b 100644 --- a/src/Editor/main.cpp +++ b/src/Editor/main.cpp @@ -96,6 +96,13 @@ int main() { .filePath = sourcePath / "import/textures/skybox.jpg", .type = TextureImportType::TEXTURE_CUBEMAP, }); + AssetImporter::importTexture(TextureImportArgs{ + .filePath = sourcePath / "import/textures/brickwall.jpg", + }); + AssetImporter::importTexture(TextureImportArgs{ + .filePath = sourcePath / "import/textures/brickwall_normal.jpg", + .type = TextureImportType::TEXTURE_NORMAL, + }); // AssetImporter::importMesh(MeshImportArgs{ // .filePath = sourcePath / "import/models/ship.fbx", // .importPath = "ship", @@ -113,7 +120,11 @@ int main() { .filePath = sourcePath / "import/models/after-the-rain-vr-sound/source/Whitechapel.glb", .importPath = "Whitechapel", }); - // AssetImporter::importMesh(MeshImportArgs{521 + //AssetImporter::importMesh(MeshImportArgs{ + // .filePath = sourcePath / "import/models/plane.obj", + // .importPath = "", + //}); + // AssetImporter::importMesh(MeshImportArgs{ // .filePath = sourcePath / "import/models/city-suburbs/source/city-suburbs.obj", // .importPath = "suburbs", // }); diff --git a/src/Engine/Graphics/RenderPass/BasePass.cpp b/src/Engine/Graphics/RenderPass/BasePass.cpp index b875af3..e0c8dd0 100644 --- a/src/Engine/Graphics/RenderPass/BasePass.cpp +++ b/src/Engine/Graphics/RenderPass/BasePass.cpp @@ -79,8 +79,8 @@ BasePass::BasePass(Gfx::PGraphics graphics, PScene scene) : RenderPass(graphics, }); } skybox = Seele::Component::Skybox{ - .day = AssetRegistry::findTexture("", "skyboxsun5deg_tn")->getTexture().cast(), - .night = AssetRegistry::findTexture("", "skyboxsun5deg_tn")->getTexture().cast(), + .day = AssetRegistry::findTexture("", "skybox")->getTexture().cast(), + .night = AssetRegistry::findTexture("", "skybox")->getTexture().cast(), .fogColor = Vector(0.1, 0.1, 0.8), .blendFactor = 0, }; diff --git a/src/Engine/Graphics/StaticMeshVertexData.cpp b/src/Engine/Graphics/StaticMeshVertexData.cpp index feb6f01..5b07c96 100644 --- a/src/Engine/Graphics/StaticMeshVertexData.cpp +++ b/src/Engine/Graphics/StaticMeshVertexData.cpp @@ -18,31 +18,38 @@ StaticMeshVertexData* StaticMeshVertexData::getInstance() { return &instance; } -void StaticMeshVertexData::loadPositions(uint64 offset, const Array& data) { +void StaticMeshVertexData::loadPositions(uint64 offset, const Array& data) { assert(offset + data.size() <= head); - std::memcpy(posData.data() + offset, data.data(), data.size() * sizeof(Vector)); - // positions->updateContents(offset * sizeof(Vector4), data.size() * sizeof(Vector4), data.data()); + std::memcpy(posData.data() + offset, data.data(), data.size() * sizeof(PositionType)); dirty = true; } -void StaticMeshVertexData::loadTexCoords(uint64 offset, uint64 index, const Array& data) { +void StaticMeshVertexData::loadTexCoords(uint64 offset, uint64 index, const Array& data) { assert(offset + data.size() <= head); - std::memcpy(texData[index].data() + offset, data.data(), data.size() * sizeof(U16Vector2)); - // texCoords[index]->updateContents(offset * sizeof(Vector2), data.size() * sizeof(Vector2), data.data()); + std::memcpy(texData[index].data() + offset, data.data(), data.size() * sizeof(TexCoordType)); dirty = true; } -void StaticMeshVertexData::loadNormals(uint64 offset, const Array& data) { +void StaticMeshVertexData::loadNormals(uint64 offset, const Array& data) { assert(offset + data.size() <= head); - std::memcpy(norData.data() + offset, data.data(), data.size() * sizeof(uint32)); - // normals->updateContents(offset * sizeof(Vector4), data.size() * sizeof(Vector4), data.data()); + std::memcpy(norData.data() + offset, data.data(), data.size() * sizeof(NormalType)); dirty = true; } -void StaticMeshVertexData::loadColors(uint64 offset, const Array& data) { +void StaticMeshVertexData::loadTangents(uint64 offset, const Array& data) { assert(offset + data.size() <= head); - std::memcpy(colData.data() + offset, data.data(), data.size() * sizeof(U16Vector)); - // colors->updateContents(offset * sizeof(Vector4), data.size() * sizeof(Vector4), data.data()); + std::memcpy(tanData.data() + offset, data.data(), data.size() * sizeof(TangentType)); + dirty = true; +} +void StaticMeshVertexData::loadBitangents(uint64 offset, const Array& data) { + assert(offset + data.size() <= head); + std::memcpy(bitData.data() + offset, data.data(), data.size() * sizeof(BiTangentType)); + dirty = true; +} + +void StaticMeshVertexData::loadColors(uint64 offset, const Array& data) { + assert(offset + data.size() <= head); + std::memcpy(colData.data() + offset, data.data(), data.size() * sizeof(ColorType)); dirty = true; } @@ -53,20 +60,26 @@ void StaticMeshVertexData::serializeMesh(MeshId id, uint64 numVertices, ArchiveB std::unique_lock l(vertexDataLock); offset = meshOffsets[id]; } - Array tex[MAX_TEXCOORDS]; + Array tex[MAX_TEXCOORDS]; for (size_t i = 0; i < MAX_TEXCOORDS; ++i) { tex[i].resize(numVertices); - std::memcpy(tex[i].data(), texData[i].data() + offset, numVertices * sizeof(U16Vector2)); + std::memcpy(tex[i].data(), texData[i].data() + offset, numVertices * sizeof(TexCoordType)); Serialization::save(buffer, tex[i]); } - Array pos(numVertices); - Array nor(numVertices); - Array col(numVertices); - std::memcpy(pos.data(), posData.data() + offset, numVertices * sizeof(Vector)); - std::memcpy(nor.data(), norData.data() + offset, numVertices * sizeof(uint32)); - std::memcpy(col.data(), colData.data() + offset, numVertices * sizeof(U16Vector)); + Array pos(numVertices); + Array nor(numVertices); + Array tan(numVertices); + Array bit(numVertices); + Array col(numVertices); + std::memcpy(pos.data(), posData.data() + offset, numVertices * sizeof(PositionType)); + std::memcpy(nor.data(), norData.data() + offset, numVertices * sizeof(NormalType)); + std::memcpy(tan.data(), tanData.data() + offset, numVertices * sizeof(TangentType)); + std::memcpy(bit.data(), bitData.data() + offset, numVertices * sizeof(BiTangentType)); + std::memcpy(col.data(), colData.data() + offset, numVertices * sizeof(ColorType)); Serialization::save(buffer, pos); Serialization::save(buffer, nor); + Serialization::save(buffer, tan); + Serialization::save(buffer, bit); Serialization::save(buffer, col); } @@ -77,36 +90,61 @@ uint64 StaticMeshVertexData::deserializeMesh(MeshId id, ArchiveBuffer& buffer) { std::unique_lock l(vertexDataLock); offset = meshOffsets[id]; } - Array tex[MAX_TEXCOORDS]; + Array tex[MAX_TEXCOORDS]; for (size_t i = 0; i < MAX_TEXCOORDS; ++i) { Serialization::load(buffer, tex[i]); loadTexCoords(offset, i, tex[i]); - result += tex[i].size() * sizeof(U16Vector2); + result += tex[i].size() * sizeof(TexCoordType); } - Array pos; - Array nor; - Array col; + Array pos; + Array nor; + Array tan; + Array bit; + Array col; Serialization::load(buffer, pos); Serialization::load(buffer, nor); + Serialization::load(buffer, tan); + Serialization::load(buffer, bit); Serialization::load(buffer, col); loadPositions(offset, pos); loadNormals(offset, nor); + loadTangents(offset, tan); + loadBitangents(offset, bit); loadColors(offset, col); - result += pos.size() * sizeof(Vector); - result += nor.size() * sizeof(uint32); - result += col.size() * sizeof(U16Vector); + result += pos.size() * sizeof(PositionType); + result += nor.size() * sizeof(NormalType); + result += tan.size() * sizeof(TangentType); + result += bit.size() * sizeof(BiTangentType); + result += col.size() * sizeof(ColorType); return result; } void StaticMeshVertexData::init(Gfx::PGraphics _graphics) { VertexData::init(_graphics); descriptorLayout = _graphics->createDescriptorLayout("pVertexData"); - descriptorLayout->addDescriptorBinding(Gfx::DescriptorBinding{.binding = 0, .descriptorType = Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER}); - descriptorLayout->addDescriptorBinding(Gfx::DescriptorBinding{.binding = 1, .descriptorType = Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER}); - descriptorLayout->addDescriptorBinding(Gfx::DescriptorBinding{.binding = 2, .descriptorType = Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER}); + descriptorLayout->addDescriptorBinding(Gfx::DescriptorBinding{ + .binding = 0, + .descriptorType = Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER, + }); + descriptorLayout->addDescriptorBinding(Gfx::DescriptorBinding{ + .binding = 1, + .descriptorType = Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER, + }); + descriptorLayout->addDescriptorBinding(Gfx::DescriptorBinding{ + .binding = 2, + .descriptorType = Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER, + }); descriptorLayout->addDescriptorBinding(Gfx::DescriptorBinding{ .binding = 3, .descriptorType = Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER, + }); + descriptorLayout->addDescriptorBinding(Gfx::DescriptorBinding{ + .binding = 4, + .descriptorType = Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER, + }); + descriptorLayout->addDescriptorBinding(Gfx::DescriptorBinding{ + .binding = 5, + .descriptorType = Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER, .descriptorCount = MAX_TEXCOORDS, }); descriptorLayout->create(); @@ -120,6 +158,8 @@ void StaticMeshVertexData::destroy() { } positions = nullptr; normals = nullptr; + tangents = nullptr; + biTangents = nullptr; colors = nullptr; descriptorSet = nullptr; descriptorLayout = nullptr; @@ -136,6 +176,8 @@ Gfx::PDescriptorSet StaticMeshVertexData::getVertexDataSet() { return descriptor void StaticMeshVertexData::resizeBuffers() { posData.resize(verticesAllocated); norData.resize(verticesAllocated); + tanData.resize(verticesAllocated); + bitData.resize(verticesAllocated); colData.resize(verticesAllocated); for (size_t i = 0; i < MAX_TEXCOORDS; ++i) { texData[i].resize(verticesAllocated); @@ -146,7 +188,7 @@ void StaticMeshVertexData::updateBuffers() { positions = graphics->createShaderBuffer(ShaderBufferCreateInfo{ .sourceData = { - .size = verticesAllocated * sizeof(Vector), + .size = verticesAllocated * sizeof(PositionType), .data = (uint8*)posData.data(), }, .usage = Gfx::SE_BUFFER_USAGE_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT_KHR, @@ -155,15 +197,31 @@ void StaticMeshVertexData::updateBuffers() { normals = graphics->createShaderBuffer(ShaderBufferCreateInfo{ .sourceData = { - .size = verticesAllocated * sizeof(uint32), + .size = verticesAllocated * sizeof(NormalType), .data = (uint8*)norData.data(), }, .name = "Normals", }); + tangents = graphics->createShaderBuffer(ShaderBufferCreateInfo{ + .sourceData = + { + .size = verticesAllocated * sizeof(TangentType), + .data = (uint8*)tanData.data(), + }, + .name = "Tangents", + }); + biTangents = graphics->createShaderBuffer(ShaderBufferCreateInfo{ + .sourceData = + { + .size = verticesAllocated * sizeof(BiTangentType), + .data = (uint8*)bitData.data(), + }, + .name = "BiTangents", + }); colors = graphics->createShaderBuffer(ShaderBufferCreateInfo{ .sourceData = { - .size = verticesAllocated * sizeof(U16Vector), + .size = verticesAllocated * sizeof(ColorType), .data = (uint8*)colData.data(), }, .name = "Colors", @@ -172,7 +230,7 @@ void StaticMeshVertexData::updateBuffers() { texCoords[i] = graphics->createShaderBuffer(ShaderBufferCreateInfo{ .sourceData = { - .size = verticesAllocated * sizeof(U16Vector2), + .size = verticesAllocated * sizeof(TexCoordType), .data = (uint8*)texData[i].data(), }, .name = "TexCoords", @@ -182,9 +240,11 @@ void StaticMeshVertexData::updateBuffers() { descriptorSet = descriptorLayout->allocateDescriptorSet(); descriptorSet->updateBuffer(0, 0, positions); descriptorSet->updateBuffer(1, 0, normals); - descriptorSet->updateBuffer(2, 0, colors); + descriptorSet->updateBuffer(2, 0, tangents); + descriptorSet->updateBuffer(3, 0, biTangents); + descriptorSet->updateBuffer(4, 0, colors); for (size_t i = 0; i < MAX_TEXCOORDS; ++i) { - descriptorSet->updateBuffer(3, i, texCoords[i]); + descriptorSet->updateBuffer(5, i, texCoords[i]); } descriptorSet->writeChanges(); } diff --git a/src/Engine/Graphics/StaticMeshVertexData.h b/src/Engine/Graphics/StaticMeshVertexData.h index 5c1e7d6..dafebc8 100644 --- a/src/Engine/Graphics/StaticMeshVertexData.h +++ b/src/Engine/Graphics/StaticMeshVertexData.h @@ -9,13 +9,22 @@ namespace Seele { class StaticMeshVertexData : public VertexData { public: + using PositionType = Vector; + using NormalType = Vector; + using TangentType = Vector; + using BiTangentType = Vector; + using TexCoordType = U16Vector2; + using ColorType = U16Vector; + StaticMeshVertexData(); virtual ~StaticMeshVertexData(); static StaticMeshVertexData* getInstance(); - void loadPositions(uint64 offset, const Array& data); - void loadTexCoords(uint64 offset, uint64 index, const Array& data); - void loadNormals(uint64 offset, const Array& data); - void loadColors(uint64 offset, const Array& data); + void loadPositions(uint64 offset, const Array& data); + void loadTexCoords(uint64 offset, uint64 index, const Array& data); + void loadNormals(uint64 offset, const Array& data); + void loadTangents(uint64 offset, const Array& data); + void loadBitangents(uint64 offset, const Array& data); + void loadColors(uint64 offset, const Array& data); virtual void serializeMesh(MeshId id, uint64 numVertices, ArchiveBuffer& buffer) override; virtual uint64 deserializeMesh(MeshId id, ArchiveBuffer& buffer) override; virtual void init(Gfx::PGraphics graphics) override; @@ -30,14 +39,19 @@ class StaticMeshVertexData : public VertexData { virtual void resizeBuffers() override; virtual void updateBuffers() override; + Gfx::OShaderBuffer positions; Gfx::OShaderBuffer texCoords[MAX_TEXCOORDS]; Gfx::OShaderBuffer normals; + Gfx::OShaderBuffer tangents; + Gfx::OShaderBuffer biTangents; Gfx::OShaderBuffer colors; - Array posData; - Array texData[MAX_TEXCOORDS]; - Array norData; - Array colData; + Array posData; + Array texData[MAX_TEXCOORDS]; + Array norData; + Array tanData; + Array bitData; + Array colData; Gfx::ODescriptorLayout descriptorLayout; Gfx::PDescriptorSet descriptorSet; };