diff --git a/apps/app.c b/apps/app.c index 01212fc2..5e2ddfaa 100644 --- a/apps/app.c +++ b/apps/app.c @@ -223,9 +223,9 @@ pl_app_load(plApiRegistryI* ptApiRegistry, plAppData* ptAppData) ptAppData->uSceneHandle0 = gptRenderer->create_scene(); - // pl_begin_profile_sample("load environments"); - // gptRenderer->load_skybox_from_panorama(ptAppData->uSceneHandle0, "../data/glTF-Sample-Environments-main/field.jpg", 1024); - // pl_end_profile_sample(); + pl_begin_profile_sample("load environments"); + gptRenderer->load_skybox_from_panorama(ptAppData->uSceneHandle0, "../data/glTF-Sample-Environments-main/field.jpg", 1024); + pl_end_profile_sample(); pl_begin_profile_sample("create scene views"); ptAppData->uViewHandle0 = gptRenderer->create_view(ptAppData->uSceneHandle0, (plVec2){ptIO->afMainViewportSize[0] , ptIO->afMainViewportSize[1]}); @@ -250,9 +250,9 @@ pl_app_load(plApiRegistryI* ptApiRegistry, plAppData* ptAppData) plModelLoaderData tLoaderData0 = {0}; pl_begin_profile_sample("load models 0"); - // plMat4 tTransform0 = pl_mat4_translate_xyz(1, 0, 1); - // plMat4 tTransform1 = pl_mat4_translate_xyz(2, 0, 2); - gptModelLoader->load_gltf(ptMainComponentLibrary, "../data/lunar_terrain/lunar_terrain.gltf", NULL, &tLoaderData0); + plMat4 tTransform0 = pl_mat4_translate_xyz(1, 0, 1); + plMat4 tTransform1 = pl_mat4_translate_xyz(2, 0, 2); + gptModelLoader->load_gltf(ptMainComponentLibrary, "../data/town.gltf", NULL, &tLoaderData0); // gptModelLoader->load_gltf(ptMainComponentLibrary, "../data/modern_spacesuit_rigged/modern_spacesuit_rigged.gltf", &tTransform0, &tLoaderData0); // gptModelLoader->load_gltf(ptMainComponentLibrary, "../data/glTF-Sample-Assets-main/Models/FlightHelmet/glTF/FlightHelmet.gltf", NULL, &tLoaderData0); // gptModelLoader->load_gltf(ptMainComponentLibrary, "../data/glTF-Sample-Assets-main/Models/CesiumMan/glTF/CesiumMan.gltf", &tTransform1, &tLoaderData0); diff --git a/shaders/metal/primitive.metal b/shaders/metal/primitive.metal index 2126f1cc..b1bce95e 100644 --- a/shaders/metal/primitive.metal +++ b/shaders/metal/primitive.metal @@ -27,12 +27,18 @@ constant const float INV_GAMMA = 1.0 / GAMMA; #define PL_MESH_FORMAT_FLAG_HAS_TANGENT 1 << 2 #define PL_MESH_FORMAT_FLAG_HAS_TEXCOORD_0 1 << 3 #define PL_MESH_FORMAT_FLAG_HAS_TEXCOORD_1 1 << 4 -#define PL_MESH_FORMAT_FLAG_HAS_COLOR_0 1 << 5 -#define PL_MESH_FORMAT_FLAG_HAS_COLOR_1 1 << 6 -#define PL_MESH_FORMAT_FLAG_HAS_JOINTS_0 1 << 7 -#define PL_MESH_FORMAT_FLAG_HAS_JOINTS_1 1 << 8 -#define PL_MESH_FORMAT_FLAG_HAS_WEIGHTS_0 1 << 9 -#define PL_MESH_FORMAT_FLAG_HAS_WEIGHTS_1 1 << 10 +#define PL_MESH_FORMAT_FLAG_HAS_TEXCOORD_2 1 << 5 +#define PL_MESH_FORMAT_FLAG_HAS_TEXCOORD_3 1 << 6 +#define PL_MESH_FORMAT_FLAG_HAS_TEXCOORD_4 1 << 7 +#define PL_MESH_FORMAT_FLAG_HAS_TEXCOORD_5 1 << 8 +#define PL_MESH_FORMAT_FLAG_HAS_TEXCOORD_6 1 << 9 +#define PL_MESH_FORMAT_FLAG_HAS_TEXCOORD_7 1 << 10 +#define PL_MESH_FORMAT_FLAG_HAS_COLOR_0 1 << 11 +#define PL_MESH_FORMAT_FLAG_HAS_COLOR_1 1 << 12 +#define PL_MESH_FORMAT_FLAG_HAS_JOINTS_0 1 << 13 +#define PL_MESH_FORMAT_FLAG_HAS_JOINTS_1 1 << 14 +#define PL_MESH_FORMAT_FLAG_HAS_WEIGHTS_0 1 << 15 +#define PL_MESH_FORMAT_FLAG_HAS_WEIGHTS_1 1 << 16 // iTextureMappingFlags #define PL_HAS_BASE_COLOR_MAP 1 << 0 @@ -235,7 +241,14 @@ struct VertexOut { float4 tPositionOut [[position]]; float3 tPosition; float4 tWorldPosition; - float2 tUV; + float2 tUV0; + float2 tUV1; + float2 tUV2; + float2 tUV3; + float2 tUV4; + float2 tUV5; + float2 tUV6; + float2 tUV7; float4 tColor; float3 tWorldNormal; float3 tTBN0; @@ -257,9 +270,8 @@ struct plMultipleRenderTargets //----------------------------------------------------------------------------- NormalInfo -pl_get_normal_info(device const BindGroup_0& bg0, device const BindGroup_1& bg1, VertexOut tShaderIn, bool front_facing) +pl_get_normal_info(device const BindGroup_0& bg0, device const BindGroup_1& bg1, VertexOut tShaderIn, bool front_facing, float2 UV) { - float2 UV = tShaderIn.tUV; float2 uv_dx = dfdx(UV); float2 uv_dy = dfdy(UV); @@ -333,7 +345,7 @@ pl_get_normal_info(device const BindGroup_0& bg0, device const BindGroup_1& bg1, } float4 -getBaseColor(device const BindGroup_0& bg0, device const BindGroup_1& bg1, float4 u_ColorFactor, VertexOut tShaderIn) +getBaseColor(device const BindGroup_0& bg0, device const BindGroup_1& bg1, float4 u_ColorFactor, VertexOut tShaderIn, float2 UV) { float4 baseColor = float4(1); @@ -357,7 +369,7 @@ getBaseColor(device const BindGroup_0& bg0, device const BindGroup_1& bg1, float if(bool(iMaterialFlags & PL_MATERIAL_METALLICROUGHNESS) && bool(iTextureMappingFlags & PL_HAS_BASE_COLOR_MAP)) { // baseColor *= texture(u_BaseColorSampler, getBaseColorUV()); - baseColor *= bg1.tBaseColorTexture.sample(bg0.tDefaultSampler, tShaderIn.tUV); + baseColor *= bg1.tBaseColorTexture.sample(bg0.tDefaultSampler, UV); } return baseColor * tShaderIn.tColor; } @@ -369,7 +381,7 @@ linearTosRGB(float3 color) } MaterialInfo -getMetallicRoughnessInfo(VertexOut in, device const BindGroup_0& bg0, device const BindGroup_1& bg1, MaterialInfo info, float u_MetallicFactor, float u_RoughnessFactor, int UVSet) +getMetallicRoughnessInfo(VertexOut in, device const BindGroup_0& bg0, device const BindGroup_1& bg1, MaterialInfo info, float u_MetallicFactor, float u_RoughnessFactor, float2 UV) { info.metallic = u_MetallicFactor; info.perceptualRoughness = u_RoughnessFactor; @@ -378,7 +390,7 @@ getMetallicRoughnessInfo(VertexOut in, device const BindGroup_0& bg0, device con { // Roughness is stored in the 'g' channel, metallic is stored in the 'b' channel. // This layout intentionally reserves the 'r' channel for (optional) occlusion map data - float4 mrSample = float4(bg1.tMetallicRoughnessTexture.sample(bg0.tDefaultSampler, in.tUV).rgb, 1.0); + float4 mrSample = float4(bg1.tMetallicRoughnessTexture.sample(bg0.tDefaultSampler, UV).rgb, 1.0); info.perceptualRoughness *= mrSample.g; info.metallic *= mrSample.b; } @@ -408,6 +420,12 @@ vertex VertexOut vertex_main( float4 inTangent = float4(0.0, 0.0, 0.0, 0.0); float2 inTexCoord0 = float2(0.0, 0.0); float2 inTexCoord1 = float2(0.0, 0.0); + float2 inTexCoord2 = float2(0.0, 0.0); + float2 inTexCoord3 = float2(0.0, 0.0); + float2 inTexCoord4 = float2(0.0, 0.0); + float2 inTexCoord5 = float2(0.0, 0.0); + float2 inTexCoord6 = float2(0.0, 0.0); + float2 inTexCoord7 = float2(0.0, 0.0); float4 inColor0 = float4(1.0, 1.0, 1.0, 1.0); float4 inColor1 = float4(0.0, 0.0, 0.0, 0.0); int iCurrentAttribute = 0; @@ -420,6 +438,12 @@ vertex VertexOut vertex_main( if(iMeshVariantFlags & PL_MESH_FORMAT_FLAG_HAS_TANGENT) { inTangent = bg0.atVertexData[iVertexDataOffset + iCurrentAttribute]; iCurrentAttribute++;} if(iMeshVariantFlags & PL_MESH_FORMAT_FLAG_HAS_TEXCOORD_0){ inTexCoord0 = bg0.atVertexData[iVertexDataOffset + iCurrentAttribute].xy; iCurrentAttribute++;} if(iMeshVariantFlags & PL_MESH_FORMAT_FLAG_HAS_TEXCOORD_1){ inTexCoord1 = bg0.atVertexData[iVertexDataOffset + iCurrentAttribute].xy; iCurrentAttribute++;} + if(iMeshVariantFlags & PL_MESH_FORMAT_FLAG_HAS_TEXCOORD_2){ inTexCoord2 = bg0.atVertexData[iVertexDataOffset + iCurrentAttribute].xy; iCurrentAttribute++;} + if(iMeshVariantFlags & PL_MESH_FORMAT_FLAG_HAS_TEXCOORD_3){ inTexCoord3 = bg0.atVertexData[iVertexDataOffset + iCurrentAttribute].xy; iCurrentAttribute++;} + if(iMeshVariantFlags & PL_MESH_FORMAT_FLAG_HAS_TEXCOORD_4){ inTexCoord4 = bg0.atVertexData[iVertexDataOffset + iCurrentAttribute].xy; iCurrentAttribute++;} + if(iMeshVariantFlags & PL_MESH_FORMAT_FLAG_HAS_TEXCOORD_5){ inTexCoord5 = bg0.atVertexData[iVertexDataOffset + iCurrentAttribute].xy; iCurrentAttribute++;} + if(iMeshVariantFlags & PL_MESH_FORMAT_FLAG_HAS_TEXCOORD_6){ inTexCoord6 = bg0.atVertexData[iVertexDataOffset + iCurrentAttribute].xy; iCurrentAttribute++;} + if(iMeshVariantFlags & PL_MESH_FORMAT_FLAG_HAS_TEXCOORD_7){ inTexCoord7 = bg0.atVertexData[iVertexDataOffset + iCurrentAttribute].xy; iCurrentAttribute++;} if(iMeshVariantFlags & PL_MESH_FORMAT_FLAG_HAS_COLOR_0) { inColor0 = bg0.atVertexData[iVertexDataOffset + iCurrentAttribute]; iCurrentAttribute++;} if(iMeshVariantFlags & PL_MESH_FORMAT_FLAG_HAS_COLOR_1) { inColor1 = bg0.atVertexData[iVertexDataOffset + iCurrentAttribute]; iCurrentAttribute++;} @@ -443,7 +467,14 @@ vertex VertexOut vertex_main( float4 pos = tObjectInfo.tModel * inPosition; tShaderOut.tPosition = pos.xyz / pos.w; tShaderOut.tPositionOut = bg0.data->tCameraViewProjection * pos; - tShaderOut.tUV = inTexCoord0; + tShaderOut.tUV0 = inTexCoord0; + tShaderOut.tUV1 = inTexCoord1; + tShaderOut.tUV2 = inTexCoord2; + tShaderOut.tUV3 = inTexCoord3; + tShaderOut.tUV4 = inTexCoord4; + tShaderOut.tUV5 = inTexCoord5; + tShaderOut.tUV6 = inTexCoord6; + tShaderOut.tUV7 = inTexCoord7; tShaderOut.tWorldPosition = tShaderOut.tPositionOut / tShaderOut.tPositionOut.w; tShaderOut.tColor = inColor0; @@ -459,9 +490,19 @@ fragment plMultipleRenderTargets fragment_main( bool front_facing [[front_facing]] ) { + const float2 tUV[8] = { + in.tUV0, + in.tUV1, + in.tUV2, + in.tUV3, + in.tUV4, + in.tUV5, + in.tUV6, + in.tUV7 + }; tMaterial material = bg0.atMaterials[tObjectInfo.iMaterialIndex]; - float4 tBaseColor = getBaseColor(bg0, bg1, material.u_BaseColorFactor, in); - NormalInfo tNormalInfo = pl_get_normal_info(bg0, bg1, in, front_facing); + float4 tBaseColor = getBaseColor(bg0, bg1, material.u_BaseColorFactor, in, tUV[material.BaseColorUVSet]); + NormalInfo tNormalInfo = pl_get_normal_info(bg0, bg1, in, front_facing, tUV[material.NormalUVSet]); float3 n = tNormalInfo.n; float3 t = tNormalInfo.t; @@ -477,7 +518,7 @@ fragment plMultipleRenderTargets fragment_main( if(bool(iMaterialFlags & PL_MATERIAL_METALLICROUGHNESS)) { - materialInfo = getMetallicRoughnessInfo(in, bg0, bg1, materialInfo, material.u_MetallicFactor, material.u_RoughnessFactor, 0); + materialInfo = getMetallicRoughnessInfo(in, bg0, bg1, materialInfo, material.u_MetallicFactor, material.u_RoughnessFactor, tUV[material.MetallicRoughnessUVSet]); } materialInfo.perceptualRoughness = fast::clamp(materialInfo.perceptualRoughness, 0.0, 1.0); @@ -497,14 +538,14 @@ fragment plMultipleRenderTargets fragment_main( float3 f_emissive = material.u_EmissiveFactor; if(bool(iTextureMappingFlags & PL_HAS_EMISSIVE_MAP)) { - f_emissive *= bg1.tEmissiveTexture.sample(bg0.tDefaultSampler, in.tUV).rgb; + f_emissive *= bg1.tEmissiveTexture.sample(bg0.tDefaultSampler, tUV[material.EmissiveUVSet]).rgb; } // ambient occlusion float ao = 1.0; if(bool(iTextureMappingFlags & PL_HAS_OCCLUSION_MAP)) { - ao = bg1.tOcclusionTexture.sample(bg0.tDefaultSampler, in.tUV).r; + ao = bg1.tOcclusionTexture.sample(bg0.tDefaultSampler, tUV[material.OcclusionUVSet]).r; } plMultipleRenderTargets tMRT; diff --git a/shaders/metal/skinning.metal b/shaders/metal/skinning.metal index 152265a0..fe5e5d57 100644 --- a/shaders/metal/skinning.metal +++ b/shaders/metal/skinning.metal @@ -23,12 +23,18 @@ constant int iDestDataStride [[ function_constant(3) ]]; #define PL_MESH_FORMAT_FLAG_HAS_TANGENT 1 << 2 #define PL_MESH_FORMAT_FLAG_HAS_TEXCOORD_0 1 << 3 #define PL_MESH_FORMAT_FLAG_HAS_TEXCOORD_1 1 << 4 -#define PL_MESH_FORMAT_FLAG_HAS_COLOR_0 1 << 5 -#define PL_MESH_FORMAT_FLAG_HAS_COLOR_1 1 << 6 -#define PL_MESH_FORMAT_FLAG_HAS_JOINTS_0 1 << 7 -#define PL_MESH_FORMAT_FLAG_HAS_JOINTS_1 1 << 8 -#define PL_MESH_FORMAT_FLAG_HAS_WEIGHTS_0 1 << 9 -#define PL_MESH_FORMAT_FLAG_HAS_WEIGHTS_1 1 << 10 +#define PL_MESH_FORMAT_FLAG_HAS_TEXCOORD_2 1 << 5 +#define PL_MESH_FORMAT_FLAG_HAS_TEXCOORD_3 1 << 6 +#define PL_MESH_FORMAT_FLAG_HAS_TEXCOORD_4 1 << 7 +#define PL_MESH_FORMAT_FLAG_HAS_TEXCOORD_5 1 << 8 +#define PL_MESH_FORMAT_FLAG_HAS_TEXCOORD_6 1 << 9 +#define PL_MESH_FORMAT_FLAG_HAS_TEXCOORD_7 1 << 10 +#define PL_MESH_FORMAT_FLAG_HAS_COLOR_0 1 << 11 +#define PL_MESH_FORMAT_FLAG_HAS_COLOR_1 1 << 12 +#define PL_MESH_FORMAT_FLAG_HAS_JOINTS_0 1 << 13 +#define PL_MESH_FORMAT_FLAG_HAS_JOINTS_1 1 << 14 +#define PL_MESH_FORMAT_FLAG_HAS_WEIGHTS_0 1 << 15 +#define PL_MESH_FORMAT_FLAG_HAS_WEIGHTS_1 1 << 16 //----------------------------------------------------------------------------- // [SECTION] bind group 0 diff --git a/shaders/metal/transparent.metal b/shaders/metal/transparent.metal index 99e10e83..a812c0e8 100644 --- a/shaders/metal/transparent.metal +++ b/shaders/metal/transparent.metal @@ -19,6 +19,9 @@ constant int iRenderingFlags [[ function_constant(4) ]]; constant float M_PI = 3.141592653589793; +constant const float GAMMA = 2.2; +constant const float INV_GAMMA = 1.0 / GAMMA; + // iMeshVariantFlags #define PL_MESH_FORMAT_FLAG_NONE 0 #define PL_MESH_FORMAT_FLAG_HAS_POSITION 1 << 0 @@ -26,12 +29,18 @@ constant float M_PI = 3.141592653589793; #define PL_MESH_FORMAT_FLAG_HAS_TANGENT 1 << 2 #define PL_MESH_FORMAT_FLAG_HAS_TEXCOORD_0 1 << 3 #define PL_MESH_FORMAT_FLAG_HAS_TEXCOORD_1 1 << 4 -#define PL_MESH_FORMAT_FLAG_HAS_COLOR_0 1 << 5 -#define PL_MESH_FORMAT_FLAG_HAS_COLOR_1 1 << 6 -#define PL_MESH_FORMAT_FLAG_HAS_JOINTS_0 1 << 7 -#define PL_MESH_FORMAT_FLAG_HAS_JOINTS_1 1 << 8 -#define PL_MESH_FORMAT_FLAG_HAS_WEIGHTS_0 1 << 9 -#define PL_MESH_FORMAT_FLAG_HAS_WEIGHTS_1 1 << 10 +#define PL_MESH_FORMAT_FLAG_HAS_TEXCOORD_2 1 << 5 +#define PL_MESH_FORMAT_FLAG_HAS_TEXCOORD_3 1 << 6 +#define PL_MESH_FORMAT_FLAG_HAS_TEXCOORD_4 1 << 7 +#define PL_MESH_FORMAT_FLAG_HAS_TEXCOORD_5 1 << 8 +#define PL_MESH_FORMAT_FLAG_HAS_TEXCOORD_6 1 << 9 +#define PL_MESH_FORMAT_FLAG_HAS_TEXCOORD_7 1 << 10 +#define PL_MESH_FORMAT_FLAG_HAS_COLOR_0 1 << 11 +#define PL_MESH_FORMAT_FLAG_HAS_COLOR_1 1 << 12 +#define PL_MESH_FORMAT_FLAG_HAS_JOINTS_0 1 << 13 +#define PL_MESH_FORMAT_FLAG_HAS_JOINTS_1 1 << 14 +#define PL_MESH_FORMAT_FLAG_HAS_WEIGHTS_0 1 << 15 +#define PL_MESH_FORMAT_FLAG_HAS_WEIGHTS_1 1 << 16 // iTextureMappingFlags #define PL_HAS_BASE_COLOR_MAP 1 << 0 @@ -197,7 +206,14 @@ struct VertexOut { float4 tPositionOut [[position]]; float3 tPosition; float4 tWorldPosition; - float2 tUV; + float2 tUV0; + float2 tUV1; + float2 tUV2; + float2 tUV3; + float2 tUV4; + float2 tUV5; + float2 tUV6; + float2 tUV7; float4 tColor; float3 tWorldNormal; float3 tTBN0; @@ -229,6 +245,12 @@ vertex VertexOut vertex_main( float4 inTangent = float4(0.0, 0.0, 0.0, 0.0); float2 inTexCoord0 = float2(0.0, 0.0); float2 inTexCoord1 = float2(0.0, 0.0); + float2 inTexCoord2 = float2(0.0, 0.0); + float2 inTexCoord3 = float2(0.0, 0.0); + float2 inTexCoord4 = float2(0.0, 0.0); + float2 inTexCoord5 = float2(0.0, 0.0); + float2 inTexCoord6 = float2(0.0, 0.0); + float2 inTexCoord7 = float2(0.0, 0.0); float4 inColor0 = float4(1.0, 1.0, 1.0, 1.0); float4 inColor1 = float4(0.0, 0.0, 0.0, 0.0); int iCurrentAttribute = 0; @@ -241,6 +263,12 @@ vertex VertexOut vertex_main( if(iMeshVariantFlags & PL_MESH_FORMAT_FLAG_HAS_TANGENT) { inTangent = bg0.atVertexData[iVertexDataOffset + iCurrentAttribute]; iCurrentAttribute++;} if(iMeshVariantFlags & PL_MESH_FORMAT_FLAG_HAS_TEXCOORD_0){ inTexCoord0 = bg0.atVertexData[iVertexDataOffset + iCurrentAttribute].xy; iCurrentAttribute++;} if(iMeshVariantFlags & PL_MESH_FORMAT_FLAG_HAS_TEXCOORD_1){ inTexCoord1 = bg0.atVertexData[iVertexDataOffset + iCurrentAttribute].xy; iCurrentAttribute++;} + if(iMeshVariantFlags & PL_MESH_FORMAT_FLAG_HAS_TEXCOORD_2){ inTexCoord2 = bg0.atVertexData[iVertexDataOffset + iCurrentAttribute].xy; iCurrentAttribute++;} + if(iMeshVariantFlags & PL_MESH_FORMAT_FLAG_HAS_TEXCOORD_3){ inTexCoord3 = bg0.atVertexData[iVertexDataOffset + iCurrentAttribute].xy; iCurrentAttribute++;} + if(iMeshVariantFlags & PL_MESH_FORMAT_FLAG_HAS_TEXCOORD_4){ inTexCoord4 = bg0.atVertexData[iVertexDataOffset + iCurrentAttribute].xy; iCurrentAttribute++;} + if(iMeshVariantFlags & PL_MESH_FORMAT_FLAG_HAS_TEXCOORD_5){ inTexCoord5 = bg0.atVertexData[iVertexDataOffset + iCurrentAttribute].xy; iCurrentAttribute++;} + if(iMeshVariantFlags & PL_MESH_FORMAT_FLAG_HAS_TEXCOORD_6){ inTexCoord6 = bg0.atVertexData[iVertexDataOffset + iCurrentAttribute].xy; iCurrentAttribute++;} + if(iMeshVariantFlags & PL_MESH_FORMAT_FLAG_HAS_TEXCOORD_7){ inTexCoord7 = bg0.atVertexData[iVertexDataOffset + iCurrentAttribute].xy; iCurrentAttribute++;} if(iMeshVariantFlags & PL_MESH_FORMAT_FLAG_HAS_COLOR_0) { inColor0 = bg0.atVertexData[iVertexDataOffset + iCurrentAttribute]; iCurrentAttribute++;} if(iMeshVariantFlags & PL_MESH_FORMAT_FLAG_HAS_COLOR_1) { inColor1 = bg0.atVertexData[iVertexDataOffset + iCurrentAttribute]; iCurrentAttribute++;} @@ -264,7 +292,14 @@ vertex VertexOut vertex_main( float4 pos = tObjectInfo.tModel * inPosition; tShaderOut.tPosition = pos.xyz / pos.w; tShaderOut.tPositionOut = bg0.data->tCameraViewProjection * pos; - tShaderOut.tUV = inTexCoord0; + tShaderOut.tUV0 = inTexCoord0; + tShaderOut.tUV1 = inTexCoord1; + tShaderOut.tUV2 = inTexCoord2; + tShaderOut.tUV3 = inTexCoord3; + tShaderOut.tUV4 = inTexCoord4; + tShaderOut.tUV5 = inTexCoord5; + tShaderOut.tUV6 = inTexCoord6; + tShaderOut.tUV7 = inTexCoord7; tShaderOut.tWorldPosition = tShaderOut.tPositionOut / tShaderOut.tPositionOut.w; tShaderOut.tColor = inColor0; @@ -280,9 +315,9 @@ struct NormalInfo { float3 ntex; // Normal from texture, scaling is accounted for. }; -NormalInfo pl_get_normal_info(device const BindGroup_0& bg0, device const BindGroup_1& bg1, VertexOut tShaderIn, bool front_facing) +NormalInfo +pl_get_normal_info(device const BindGroup_0& bg0, device const BindGroup_1& bg1, VertexOut tShaderIn, bool front_facing, float2 UV) { - float2 UV = tShaderIn.tUV; float2 uv_dx = dfdx(UV); float2 uv_dy = dfdy(UV); @@ -300,29 +335,29 @@ NormalInfo pl_get_normal_info(device const BindGroup_0& bg0, device const BindGr float3 t, b, ng; // Compute geometrical TBN: - if(iMeshVariantFlags & PL_MESH_FORMAT_FLAG_HAS_NORMAL) + if(bool(iMeshVariantFlags & PL_MESH_FORMAT_FLAG_HAS_NORMAL)) { - if(iMeshVariantFlags & PL_MESH_FORMAT_FLAG_HAS_TANGENT) + if(bool(iMeshVariantFlags & PL_MESH_FORMAT_FLAG_HAS_TANGENT)) { // Trivial TBN computation, present as vertex attribute. // Normalize eigenvectors as matrix is linearly interpolated. - t = normalize(tShaderIn.tTBN0); - b = normalize(tShaderIn.tTBN1); - ng = normalize(tShaderIn.tTBN2); + t = fast::normalize(tShaderIn.tTBN0); + b = fast::normalize(tShaderIn.tTBN1); + ng = fast::normalize(tShaderIn.tTBN2); } else { // Normals are either present as vertex attributes or approximated. - ng = normalize(tShaderIn.tWorldNormal); - t = normalize(t_ - ng * dot(ng, t_)); + ng = fast::normalize(tShaderIn.tWorldNormal); + t = fast::normalize(t_ - ng * dot(ng, t_)); b = cross(ng, t); } } else { - ng = normalize(cross(dfdx(tShaderIn.tPosition), dfdy(tShaderIn.tPosition))); - t = normalize(t_ - ng * dot(ng, t_)); + ng = fast::normalize(cross(dfdx(tShaderIn.tPosition), dfdy(tShaderIn.tPosition))); + t = fast::normalize(t_ - ng * dot(ng, t_)); b = cross(ng, t); } @@ -338,13 +373,13 @@ NormalInfo pl_get_normal_info(device const BindGroup_0& bg0, device const BindGr // Compute normals: NormalInfo info; info.ng = ng; - if(iTextureMappingFlags & PL_HAS_NORMAL_MAP) + if(bool(iTextureMappingFlags & PL_HAS_NORMAL_MAP)) { info.ntex = bg1.tNormalTexture.sample(bg0.tDefaultSampler, UV).rgb * 2.0 - float3(1.0); // info.ntex *= vec3(0.2, 0.2, 1.0); // info.ntex *= vec3(u_NormalScale, u_NormalScale, 1.0); - info.ntex = normalize(info.ntex); - info.n = normalize(float3x3(t, b, ng) * info.ntex); + info.ntex = fast::normalize(info.ntex); + info.n = fast::normalize(float3x3(t, b, ng) * info.ntex); } else { @@ -356,7 +391,7 @@ NormalInfo pl_get_normal_info(device const BindGroup_0& bg0, device const BindGr } float4 -getBaseColor(device const BindGroup_0& bg0, device const BindGroup_1& bg1, float4 u_ColorFactor, VertexOut tShaderIn) +getBaseColor(device const BindGroup_0& bg0, device const BindGroup_1& bg1, float4 u_ColorFactor, VertexOut tShaderIn, float2 UV) { float4 baseColor = float4(1); @@ -380,23 +415,19 @@ getBaseColor(device const BindGroup_0& bg0, device const BindGroup_1& bg1, float if(bool(iMaterialFlags & PL_MATERIAL_METALLICROUGHNESS) && bool(iTextureMappingFlags & PL_HAS_BASE_COLOR_MAP)) { // baseColor *= texture(u_BaseColorSampler, getBaseColorUV()); - baseColor *= bg1.tBaseColorTexture.sample(bg0.tDefaultSampler, tShaderIn.tUV); + baseColor *= bg1.tBaseColorTexture.sample(bg0.tDefaultSampler, UV); } return baseColor * tShaderIn.tColor; } -constant const float GAMMA = 2.2; -constant const float INV_GAMMA = 1.0 / GAMMA; - -// linear to sRGB approximation -// see http://chilliant.blogspot.com/2012/08/srgb-approximations-for-hlsl.html -float3 linearTosRGB(float3 color) +float3 +linearTosRGB(float3 color) { return pow(color, float3(INV_GAMMA)); } MaterialInfo -getMetallicRoughnessInfo(VertexOut in, device const BindGroup_0& bg0, device const BindGroup_1& bg1, MaterialInfo info, float u_MetallicFactor, float u_RoughnessFactor, int UVSet) +getMetallicRoughnessInfo(VertexOut in, device const BindGroup_0& bg0, device const BindGroup_1& bg1, MaterialInfo info, float u_MetallicFactor, float u_RoughnessFactor, float2 UV) { info.metallic = u_MetallicFactor; info.perceptualRoughness = u_RoughnessFactor; @@ -405,7 +436,7 @@ getMetallicRoughnessInfo(VertexOut in, device const BindGroup_0& bg0, device con { // Roughness is stored in the 'g' channel, metallic is stored in the 'b' channel. // This layout intentionally reserves the 'r' channel for (optional) occlusion map data - float4 mrSample = float4(bg1.tMetallicRoughnessTexture.sample(bg0.tDefaultSampler, in.tUV).rgb, 1.0); + float4 mrSample = float4(bg1.tMetallicRoughnessTexture.sample(bg0.tDefaultSampler, UV).rgb, 1.0); info.perceptualRoughness *= mrSample.g; info.metallic *= mrSample.b; } @@ -600,20 +631,31 @@ fragment plRenderTargets fragment_main( ) { + const float2 tUV[8] = { + in.tUV0, + in.tUV1, + in.tUV2, + in.tUV3, + in.tUV4, + in.tUV5, + in.tUV6, + in.tUV7 + }; + // settings float3 tSunlightColor = float3(1.0, 1.0, 1.0); float lightIntensity = 1.0; float3 tSunLightDirection = float3(-1.0, -1.0, -1.0); tMaterial material = bg0.atMaterials[tObjectInfo.iMaterialIndex]; - float4 tBaseColor = getBaseColor(bg0, bg1, material.u_BaseColorFactor, in); + float4 tBaseColor = getBaseColor(bg0, bg1, material.u_BaseColorFactor, in, tUV[material.BaseColorUVSet]); if(tBaseColor.a < 0.1) { discard_fragment(); } - NormalInfo tNormalInfo = pl_get_normal_info(bg0, bg1, in, front_facing); + NormalInfo tNormalInfo = pl_get_normal_info(bg0, bg1, in, front_facing, tUV[material.NormalUVSet]); float3 n = tNormalInfo.n; @@ -627,7 +669,7 @@ fragment plRenderTargets fragment_main( if(bool(iMaterialFlags & PL_MATERIAL_METALLICROUGHNESS)) { - materialInfo = getMetallicRoughnessInfo(in, bg0, bg1, materialInfo, material.u_MetallicFactor, material.u_RoughnessFactor, 0); + materialInfo = getMetallicRoughnessInfo(in, bg0, bg1, materialInfo, material.u_MetallicFactor, material.u_RoughnessFactor, tUV[material.MetallicRoughnessUVSet]); } materialInfo.perceptualRoughness = fast::clamp(materialInfo.perceptualRoughness, 0.0, 1.0); @@ -647,14 +689,14 @@ fragment plRenderTargets fragment_main( float3 f_emissive = material.u_EmissiveFactor; if(bool(iTextureMappingFlags & PL_HAS_EMISSIVE_MAP)) { - f_emissive *= bg1.tEmissiveTexture.sample(bg0.tDefaultSampler, in.tUV).rgb; + f_emissive *= bg1.tEmissiveTexture.sample(bg0.tDefaultSampler, tUV[material.EmissiveUVSet]).rgb; } // ambient occlusion float ao = 1.0; if(bool(iTextureMappingFlags & PL_HAS_OCCLUSION_MAP)) { - ao = bg1.tOcclusionTexture.sample(bg0.tDefaultSampler, in.tUV).r; + ao = bg1.tOcclusionTexture.sample(bg0.tDefaultSampler, tUV[material.OcclusionUVSet]).r; } float3 v = normalize(bg0.data->tCameraPos.xyz - in.tPosition.xyz);