More tangent changes

This commit is contained in:
Dynamitos
2024-12-27 17:06:43 +01:00
parent 7f4d7c7f71
commit f3b6ed31dc
15 changed files with 275 additions and 163 deletions
+1 -2
View File
@@ -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());
}
}
+1 -1
View File
@@ -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);
}
}
}
+1 -1
View File
@@ -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);
}
}
}
+21 -21
View File
@@ -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;
+5 -6
View File
@@ -14,8 +14,8 @@ struct DirectionalLight : ILightEnv
float3 illuminate<B:IBRDF>(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<B:IBRDF>(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)
+61 -27
View File
@@ -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]);
+6 -19
View File
@@ -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<float> positions;
StructuredBuffer<uint> qtangents;
StructuredBuffer<float> normals;
StructuredBuffer<float> tangents;
StructuredBuffer<float> biTangents;
StructuredBuffer<uint16_t> color;
StructuredBuffer<uint16_t> texCoords[MAX_TEXCOORDS];
};
+4 -4
View File
@@ -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;
}
+1 -1
View File
@@ -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);
+40 -32
View File
@@ -462,40 +462,44 @@ void MeshLoader::findMeshRoots(aiNode* node, List<aiNode*>& 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<PMaterialInstanceAsset>& materials, Array<OMesh>& globalMeshes,
Component::Collider& collider) {
List<std::function<void()>> work;
@@ -512,13 +516,15 @@ void MeshLoader::loadGlobalMeshes(const aiScene* scene, const Array<PMaterialIns
collider.boundingbox.adjust(Vector(mesh->mAABB.mMax.x, mesh->mAABB.mMax.y, mesh->mAABB.mMax.z));
work.add([=, this, &globalMeshes]() {
// assume static mesh for now
Array<Vector> positions(mesh->mNumVertices);
StaticArray<Array<U16Vector2>, MAX_TEXCOORDS> texCoords;
Array<StaticMeshVertexData::PositionType> positions(mesh->mNumVertices);
StaticArray<Array<StaticMeshVertexData::TexCoordType>, MAX_TEXCOORDS> texCoords;
for (size_t i = 0; i < MAX_TEXCOORDS; ++i) {
texCoords[i].resize(mesh->mNumVertices);
}
Array<uint32> normals(mesh->mNumVertices);
Array<U16Vector> colors(mesh->mNumVertices);
Array<StaticMeshVertexData::NormalType> normals(mesh->mNumVertices);
Array<StaticMeshVertexData::TangentType> tangents(mesh->mNumVertices);
Array<StaticMeshVertexData::BiTangentType> biTangents(mesh->mNumVertices);
Array<StaticMeshVertexData::ColorType> 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 Array<PMaterialIns
tangent = Vector(mesh->mTangents[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 Array<PMaterialIns
vertexData->loadTexCoords(offset, i, texCoords[i]);
}
vertexData->loadNormals(offset, normals);
vertexData->loadTangents(offset, tangents);
vertexData->loadBitangents(offset, biTangents);
vertexData->loadColors(offset, colors);
Array<uint32> indices(mesh->mNumFaces * 3);
@@ -575,7 +583,7 @@ void MeshLoader::loadGlobalMeshes(const aiScene* scene, const Array<PMaterialIns
globalMeshes[meshIndex]->blas = graphics->createBottomLevelAccelerationStructure(Gfx::BottomLevelASCreateInfo{
.mesh = globalMeshes[meshIndex],
});
// vertexData->registerBottomLevelAccelerationStructure(globalMeshes[meshIndex]->blas);
vertexData->registerBottomLevelAccelerationStructure(globalMeshes[meshIndex]->blas);
});
}
getThreadPool().runAndWait(std::move(work));
+1 -1
View File
@@ -26,7 +26,7 @@ class MeshLoader {
private:
void findMeshRoots(aiNode* node, List<aiNode*>& meshNodes);
uint32 encodeQTangent(Matrix3 m);
Vector4 encodeQTangent(Matrix3 m);
void loadTextures(const aiScene* scene, const std::filesystem::path& meshDirectory, const std::string& importPath,
Array<PTextureAsset>& textures);
+12 -1
View File
@@ -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",
// });
+2 -2
View File
@@ -79,8 +79,8 @@ BasePass::BasePass(Gfx::PGraphics graphics, PScene scene) : RenderPass(graphics,
});
}
skybox = Seele::Component::Skybox{
.day = AssetRegistry::findTexture("", "skyboxsun5deg_tn")->getTexture().cast<Gfx::TextureCube>(),
.night = AssetRegistry::findTexture("", "skyboxsun5deg_tn")->getTexture().cast<Gfx::TextureCube>(),
.day = AssetRegistry::findTexture("", "skybox")->getTexture().cast<Gfx::TextureCube>(),
.night = AssetRegistry::findTexture("", "skybox")->getTexture().cast<Gfx::TextureCube>(),
.fogColor = Vector(0.1, 0.1, 0.8),
.blendFactor = 0,
};
+97 -37
View File
@@ -18,31 +18,38 @@ StaticMeshVertexData* StaticMeshVertexData::getInstance() {
return &instance;
}
void StaticMeshVertexData::loadPositions(uint64 offset, const Array<Vector>& data) {
void StaticMeshVertexData::loadPositions(uint64 offset, const Array<PositionType>& 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<U16Vector2>& data) {
void StaticMeshVertexData::loadTexCoords(uint64 offset, uint64 index, const Array<TexCoordType>& 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<uint32>& data) {
void StaticMeshVertexData::loadNormals(uint64 offset, const Array<NormalType>& 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<U16Vector>& data) {
void StaticMeshVertexData::loadTangents(uint64 offset, const Array<TangentType>& 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<BiTangentType>& 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<ColorType>& 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<U16Vector2> tex[MAX_TEXCOORDS];
Array<TexCoordType> 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<Vector> pos(numVertices);
Array<uint32> nor(numVertices);
Array<U16Vector> 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<PositionType> pos(numVertices);
Array<NormalType> nor(numVertices);
Array<TangentType> tan(numVertices);
Array<BiTangentType> bit(numVertices);
Array<ColorType> 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<U16Vector2> tex[MAX_TEXCOORDS];
Array<TexCoordType> 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<Vector> pos;
Array<uint32> nor;
Array<U16Vector> col;
Array<PositionType> pos;
Array<NormalType> nor;
Array<TangentType> tan;
Array<BiTangentType> bit;
Array<ColorType> 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();
}
+22 -8
View File
@@ -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<Vector>& data);
void loadTexCoords(uint64 offset, uint64 index, const Array<U16Vector2>& data);
void loadNormals(uint64 offset, const Array<uint32>& data);
void loadColors(uint64 offset, const Array<U16Vector>& data);
void loadPositions(uint64 offset, const Array<PositionType>& data);
void loadTexCoords(uint64 offset, uint64 index, const Array<TexCoordType>& data);
void loadNormals(uint64 offset, const Array<NormalType>& data);
void loadTangents(uint64 offset, const Array<TangentType>& data);
void loadBitangents(uint64 offset, const Array<BiTangentType>& data);
void loadColors(uint64 offset, const Array<ColorType>& 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<Vector> posData;
Array<U16Vector2> texData[MAX_TEXCOORDS];
Array<Quaternion> norData;
Array<U16Vector4> colData;
Array<PositionType> posData;
Array<TexCoordType> texData[MAX_TEXCOORDS];
Array<NormalType> norData;
Array<TangentType> tanData;
Array<BiTangentType> bitData;
Array<ColorType> colData;
Gfx::ODescriptorLayout descriptorLayout;
Gfx::PDescriptorSet descriptorSet;
};