Merge branch 'development' of https://github.com/o3de/o3de into daimini/FocusMode/boxSelectAndManipulatorsHidingTests
commit
220eeef386
@ -1,35 +1,25 @@
|
||||
{
|
||||
"description": "",
|
||||
"materialType": "Materials/Types/StandardPBR.materialtype",
|
||||
"parentMaterial": "",
|
||||
"materialTypeVersion": 3,
|
||||
"properties": {
|
||||
"baseColor": {
|
||||
"color": [
|
||||
0.0,
|
||||
0.0,
|
||||
0.0,
|
||||
1.0
|
||||
]
|
||||
},
|
||||
"emissive": {
|
||||
"color": [
|
||||
0.0,
|
||||
0.0,
|
||||
0.0,
|
||||
1.0
|
||||
]
|
||||
},
|
||||
"irradiance": {
|
||||
"color": [
|
||||
0.0,
|
||||
0.0,
|
||||
0.0,
|
||||
1.0
|
||||
]
|
||||
},
|
||||
"opacity": {
|
||||
"factor": 1.0
|
||||
}
|
||||
"propertyValues": {
|
||||
"baseColor.color": [
|
||||
0.0,
|
||||
0.0,
|
||||
0.0,
|
||||
1.0
|
||||
],
|
||||
"emissive.color": [
|
||||
0.0,
|
||||
0.0,
|
||||
0.0,
|
||||
1.0
|
||||
],
|
||||
"irradiance.color": [
|
||||
0.0,
|
||||
0.0,
|
||||
0.0,
|
||||
1.0
|
||||
],
|
||||
"opacity.factor": 1.0
|
||||
}
|
||||
}
|
||||
@ -1,35 +1,25 @@
|
||||
{
|
||||
"description": "",
|
||||
"materialType": "Materials/Types/StandardPBR.materialtype",
|
||||
"parentMaterial": "",
|
||||
"materialTypeVersion": 3,
|
||||
"properties": {
|
||||
"baseColor": {
|
||||
"color": [
|
||||
0.0,
|
||||
1.0,
|
||||
0.0,
|
||||
1.0
|
||||
]
|
||||
},
|
||||
"emissive": {
|
||||
"color": [
|
||||
0.0,
|
||||
0.0,
|
||||
0.0,
|
||||
1.0
|
||||
]
|
||||
},
|
||||
"irradiance": {
|
||||
"color": [
|
||||
0.0,
|
||||
1.0,
|
||||
0.0,
|
||||
1.0
|
||||
]
|
||||
},
|
||||
"opacity": {
|
||||
"factor": 1.0
|
||||
}
|
||||
"propertyValues": {
|
||||
"baseColor.color": [
|
||||
0.0,
|
||||
1.0,
|
||||
0.0,
|
||||
1.0
|
||||
],
|
||||
"emissive.color": [
|
||||
0.0,
|
||||
0.0,
|
||||
0.0,
|
||||
1.0
|
||||
],
|
||||
"irradiance.color": [
|
||||
0.0,
|
||||
1.0,
|
||||
0.0,
|
||||
1.0
|
||||
],
|
||||
"opacity.factor": 1.0
|
||||
}
|
||||
}
|
||||
@ -1,49 +1,29 @@
|
||||
{
|
||||
"description": "",
|
||||
"materialType": "Materials/Types/StandardPBR.materialtype",
|
||||
"parentMaterial": "",
|
||||
"materialTypeVersion": 3,
|
||||
"properties": {
|
||||
"baseColor": {
|
||||
"color": [
|
||||
0.800000011920929,
|
||||
0.800000011920929,
|
||||
0.800000011920929,
|
||||
1.0
|
||||
],
|
||||
"textureMap": "Textures/arch_1k_basecolor.png"
|
||||
},
|
||||
"general": {
|
||||
"applySpecularAA": true
|
||||
},
|
||||
"irradiance": {
|
||||
"color": [
|
||||
1.0,
|
||||
0.885053813457489,
|
||||
0.801281750202179,
|
||||
1.0
|
||||
]
|
||||
},
|
||||
"metallic": {
|
||||
"textureMap": "Textures/arch_1k_metallic.png"
|
||||
},
|
||||
"normal": {
|
||||
"textureMap": "Textures/arch_1k_normal.jpg"
|
||||
},
|
||||
"occlusion": {
|
||||
"diffuseTextureMap": "Textures/arch_1k_ao.png"
|
||||
},
|
||||
"opacity": {
|
||||
"factor": 1.0
|
||||
},
|
||||
"parallax": {
|
||||
"factor": 0.050999999046325687,
|
||||
"pdo": true,
|
||||
"quality": "High",
|
||||
"useTexture": false
|
||||
},
|
||||
"roughness": {
|
||||
"textureMap": "Textures/arch_1k_roughness.png"
|
||||
}
|
||||
"propertyValues": {
|
||||
"baseColor.color": [
|
||||
0.800000011920929,
|
||||
0.800000011920929,
|
||||
0.800000011920929,
|
||||
1.0
|
||||
],
|
||||
"baseColor.textureMap": "Textures/arch_1k_basecolor.png",
|
||||
"general.applySpecularAA": true,
|
||||
"irradiance.color": [
|
||||
1.0,
|
||||
0.885053813457489,
|
||||
0.801281750202179,
|
||||
1.0
|
||||
],
|
||||
"metallic.textureMap": "Textures/arch_1k_metallic.png",
|
||||
"normal.textureMap": "Textures/arch_1k_normal.jpg",
|
||||
"occlusion.diffuseTextureMap": "Textures/arch_1k_ao.png",
|
||||
"opacity.factor": 1.0,
|
||||
"parallax.factor": 0.050999999046325684,
|
||||
"parallax.pdo": true,
|
||||
"parallax.quality": "High",
|
||||
"parallax.useTexture": false,
|
||||
"roughness.textureMap": "Textures/arch_1k_roughness.png"
|
||||
}
|
||||
}
|
||||
@ -1,54 +1,32 @@
|
||||
{
|
||||
"description": "",
|
||||
"materialType": "Materials/Types/StandardPBR.materialtype",
|
||||
"parentMaterial": "",
|
||||
"materialTypeVersion": 3,
|
||||
"properties": {
|
||||
"baseColor": {
|
||||
"color": [
|
||||
0.800000011920929,
|
||||
0.800000011920929,
|
||||
0.800000011920929,
|
||||
1.0
|
||||
],
|
||||
"textureMap": "Textures/bricks_1k_basecolor.png"
|
||||
},
|
||||
"clearCoat": {
|
||||
"factor": 0.5,
|
||||
"normalMap": "Textures/bricks_1k_normal.jpg",
|
||||
"roughness": 0.5
|
||||
},
|
||||
"general": {
|
||||
"applySpecularAA": true
|
||||
},
|
||||
"irradiance": {
|
||||
"color": [
|
||||
1.0,
|
||||
0.9703211784362793,
|
||||
0.9703211784362793,
|
||||
1.0
|
||||
]
|
||||
},
|
||||
"metallic": {
|
||||
"textureMap": "Textures/bricks_1k_metallic.png"
|
||||
},
|
||||
"normal": {
|
||||
"textureMap": "Textures/bricks_1k_normal.jpg"
|
||||
},
|
||||
"occlusion": {
|
||||
"diffuseTextureMap": "Textures/bricks_1k_ao.png"
|
||||
},
|
||||
"opacity": {
|
||||
"factor": 1.0
|
||||
},
|
||||
"parallax": {
|
||||
"algorithm": "ContactRefinement",
|
||||
"factor": 0.03500000014901161,
|
||||
"quality": "Medium",
|
||||
"useTexture": false
|
||||
},
|
||||
"roughness": {
|
||||
"textureMap": "Textures/bricks_1k_roughness.png"
|
||||
}
|
||||
"propertyValues": {
|
||||
"baseColor.color": [
|
||||
0.800000011920929,
|
||||
0.800000011920929,
|
||||
0.800000011920929,
|
||||
1.0
|
||||
],
|
||||
"baseColor.textureMap": "Textures/bricks_1k_basecolor.png",
|
||||
"clearCoat.factor": 0.5,
|
||||
"clearCoat.normalMap": "Textures/bricks_1k_normal.jpg",
|
||||
"clearCoat.roughness": 0.5,
|
||||
"general.applySpecularAA": true,
|
||||
"irradiance.color": [
|
||||
1.0,
|
||||
0.9703211784362793,
|
||||
0.9703211784362793,
|
||||
1.0
|
||||
],
|
||||
"metallic.textureMap": "Textures/bricks_1k_metallic.png",
|
||||
"normal.textureMap": "Textures/bricks_1k_normal.jpg",
|
||||
"occlusion.diffuseTextureMap": "Textures/bricks_1k_ao.png",
|
||||
"opacity.factor": 1.0,
|
||||
"parallax.algorithm": "ContactRefinement",
|
||||
"parallax.factor": 0.03500000014901161,
|
||||
"parallax.quality": "Medium",
|
||||
"parallax.useTexture": false,
|
||||
"roughness.textureMap": "Textures/bricks_1k_roughness.png"
|
||||
}
|
||||
}
|
||||
@ -1,51 +1,31 @@
|
||||
{
|
||||
"description": "",
|
||||
"materialType": "Materials/Types/StandardPBR.materialtype",
|
||||
"parentMaterial": "",
|
||||
"materialTypeVersion": 3,
|
||||
"properties": {
|
||||
"baseColor": {
|
||||
"color": [
|
||||
0.800000011920929,
|
||||
0.800000011920929,
|
||||
0.800000011920929,
|
||||
1.0
|
||||
],
|
||||
"textureMap": "Textures/floor_1k_basecolor.png"
|
||||
},
|
||||
"clearCoat": {
|
||||
"enable": true,
|
||||
"influenceMap": "Textures/floor_1k_ao.png",
|
||||
"normalMap": "Textures/floor_1k_normal.png",
|
||||
"roughness": 0.25
|
||||
},
|
||||
"general": {
|
||||
"applySpecularAA": true
|
||||
},
|
||||
"irradiance": {
|
||||
"color": [
|
||||
1.0,
|
||||
0.9404135346412659,
|
||||
0.8688944578170776,
|
||||
1.0
|
||||
]
|
||||
},
|
||||
"normal": {
|
||||
"textureMap": "Textures/floor_1k_normal.png"
|
||||
},
|
||||
"occlusion": {
|
||||
"diffuseTextureMap": "Textures/floor_1k_ao.png"
|
||||
},
|
||||
"opacity": {
|
||||
"factor": 1.0
|
||||
},
|
||||
"parallax": {
|
||||
"factor": 0.012000000104308129,
|
||||
"pdo": true,
|
||||
"useTexture": false
|
||||
},
|
||||
"roughness": {
|
||||
"textureMap": "Textures/floor_1k_roughness.png"
|
||||
}
|
||||
"propertyValues": {
|
||||
"baseColor.color": [
|
||||
0.800000011920929,
|
||||
0.800000011920929,
|
||||
0.800000011920929,
|
||||
1.0
|
||||
],
|
||||
"baseColor.textureMap": "Textures/floor_1k_basecolor.png",
|
||||
"clearCoat.enable": true,
|
||||
"clearCoat.influenceMap": "Textures/floor_1k_ao.png",
|
||||
"clearCoat.normalMap": "Textures/floor_1k_normal.png",
|
||||
"clearCoat.roughness": 0.25,
|
||||
"general.applySpecularAA": true,
|
||||
"irradiance.color": [
|
||||
1.0,
|
||||
0.9404135346412659,
|
||||
0.8688944578170776,
|
||||
1.0
|
||||
],
|
||||
"normal.textureMap": "Textures/floor_1k_normal.png",
|
||||
"occlusion.diffuseTextureMap": "Textures/floor_1k_ao.png",
|
||||
"opacity.factor": 1.0,
|
||||
"parallax.factor": 0.012000000104308128,
|
||||
"parallax.pdo": true,
|
||||
"parallax.useTexture": false,
|
||||
"roughness.textureMap": "Textures/floor_1k_roughness.png"
|
||||
}
|
||||
}
|
||||
@ -1,44 +1,26 @@
|
||||
{
|
||||
"description": "",
|
||||
"materialType": "Materials/Types/StandardPBR.materialtype",
|
||||
"parentMaterial": "",
|
||||
"materialTypeVersion": 3,
|
||||
"properties": {
|
||||
"baseColor": {
|
||||
"color": [
|
||||
0.800000011920929,
|
||||
0.800000011920929,
|
||||
0.800000011920929,
|
||||
1.0
|
||||
],
|
||||
"textureBlendMode": "Lerp",
|
||||
"textureMap": "Textures/roof_1k_basecolor.png"
|
||||
},
|
||||
"general": {
|
||||
"applySpecularAA": true
|
||||
},
|
||||
"metallic": {
|
||||
"useTexture": false
|
||||
},
|
||||
"normal": {
|
||||
"factor": 0.5,
|
||||
"flipY": true,
|
||||
"textureMap": "Textures/roof_1k_normal.jpg"
|
||||
},
|
||||
"occlusion": {
|
||||
"diffuseTextureMap": "Textures/roof_1k_ao.png"
|
||||
},
|
||||
"opacity": {
|
||||
"factor": 1.0
|
||||
},
|
||||
"parallax": {
|
||||
"algorithm": "ContactRefinement",
|
||||
"factor": 0.019999999552965165,
|
||||
"quality": "Medium",
|
||||
"useTexture": false
|
||||
},
|
||||
"roughness": {
|
||||
"textureMap": "Textures/roof_1k_roughness.png"
|
||||
}
|
||||
"propertyValues": {
|
||||
"baseColor.color": [
|
||||
0.800000011920929,
|
||||
0.800000011920929,
|
||||
0.800000011920929,
|
||||
1.0
|
||||
],
|
||||
"baseColor.textureBlendMode": "Lerp",
|
||||
"baseColor.textureMap": "Textures/roof_1k_basecolor.png",
|
||||
"general.applySpecularAA": true,
|
||||
"metallic.useTexture": false,
|
||||
"normal.factor": 0.5,
|
||||
"normal.flipY": true,
|
||||
"normal.textureMap": "Textures/roof_1k_normal.jpg",
|
||||
"occlusion.diffuseTextureMap": "Textures/roof_1k_ao.png",
|
||||
"opacity.factor": 1.0,
|
||||
"parallax.algorithm": "ContactRefinement",
|
||||
"parallax.factor": 0.019999999552965164,
|
||||
"parallax.quality": "Medium",
|
||||
"parallax.useTexture": false,
|
||||
"roughness.textureMap": "Textures/roof_1k_roughness.png"
|
||||
}
|
||||
}
|
||||
@ -1,35 +1,25 @@
|
||||
{
|
||||
"description": "",
|
||||
"materialType": "Materials/Types/StandardPBR.materialtype",
|
||||
"parentMaterial": "",
|
||||
"materialTypeVersion": 3,
|
||||
"properties": {
|
||||
"baseColor": {
|
||||
"color": [
|
||||
0.0,
|
||||
0.0,
|
||||
1.0,
|
||||
1.0
|
||||
]
|
||||
},
|
||||
"emissive": {
|
||||
"color": [
|
||||
0.0,
|
||||
0.0,
|
||||
0.0,
|
||||
1.0
|
||||
]
|
||||
},
|
||||
"irradiance": {
|
||||
"color": [
|
||||
0.0,
|
||||
0.0,
|
||||
1.0,
|
||||
1.0
|
||||
]
|
||||
},
|
||||
"opacity": {
|
||||
"factor": 1.0
|
||||
}
|
||||
"propertyValues": {
|
||||
"baseColor.color": [
|
||||
0.0,
|
||||
0.0,
|
||||
1.0,
|
||||
1.0
|
||||
],
|
||||
"emissive.color": [
|
||||
0.0,
|
||||
0.0,
|
||||
0.0,
|
||||
1.0
|
||||
],
|
||||
"irradiance.color": [
|
||||
0.0,
|
||||
0.0,
|
||||
1.0,
|
||||
1.0
|
||||
],
|
||||
"opacity.factor": 1.0
|
||||
}
|
||||
}
|
||||
@ -1,35 +1,25 @@
|
||||
{
|
||||
"description": "",
|
||||
"materialType": "Materials/Types/StandardPBR.materialtype",
|
||||
"parentMaterial": "",
|
||||
"materialTypeVersion": 3,
|
||||
"properties": {
|
||||
"baseColor": {
|
||||
"color": [
|
||||
0.800000011920929,
|
||||
0.0,
|
||||
0.0,
|
||||
1.0
|
||||
]
|
||||
},
|
||||
"emissive": {
|
||||
"color": [
|
||||
0.0,
|
||||
0.0,
|
||||
0.0,
|
||||
1.0
|
||||
]
|
||||
},
|
||||
"irradiance": {
|
||||
"color": [
|
||||
1.0,
|
||||
0.0,
|
||||
0.0,
|
||||
1.0
|
||||
]
|
||||
},
|
||||
"opacity": {
|
||||
"factor": 1.0
|
||||
}
|
||||
"propertyValues": {
|
||||
"baseColor.color": [
|
||||
0.800000011920929,
|
||||
0.0,
|
||||
0.0,
|
||||
1.0
|
||||
],
|
||||
"emissive.color": [
|
||||
0.0,
|
||||
0.0,
|
||||
0.0,
|
||||
1.0
|
||||
],
|
||||
"irradiance.color": [
|
||||
1.0,
|
||||
0.0,
|
||||
0.0,
|
||||
1.0
|
||||
],
|
||||
"opacity.factor": 1.0
|
||||
}
|
||||
}
|
||||
@ -1,19 +1,13 @@
|
||||
{
|
||||
"description": "",
|
||||
"materialType": "Materials/Types/StandardPBR.materialtype",
|
||||
"parentMaterial": "",
|
||||
"materialTypeVersion": 3,
|
||||
"properties": {
|
||||
"emissive": {
|
||||
"color": [
|
||||
0.0,
|
||||
0.0,
|
||||
0.0,
|
||||
1.0
|
||||
]
|
||||
},
|
||||
"opacity": {
|
||||
"factor": 1.0
|
||||
}
|
||||
"propertyValues": {
|
||||
"emissive.color": [
|
||||
0.0,
|
||||
0.0,
|
||||
0.0,
|
||||
1.0
|
||||
],
|
||||
"opacity.factor": 1.0
|
||||
}
|
||||
}
|
||||
@ -1,19 +1,13 @@
|
||||
{
|
||||
"description": "",
|
||||
"materialType": "Materials/Types/StandardPBR.materialtype",
|
||||
"parentMaterial": "",
|
||||
"materialTypeVersion": 3,
|
||||
"properties": {
|
||||
"emissive": {
|
||||
"color": [
|
||||
0.0,
|
||||
0.0,
|
||||
0.0,
|
||||
1.0
|
||||
]
|
||||
},
|
||||
"opacity": {
|
||||
"factor": 1.0
|
||||
}
|
||||
"propertyValues": {
|
||||
"emissive.color": [
|
||||
0.0,
|
||||
0.0,
|
||||
0.0,
|
||||
1.0
|
||||
],
|
||||
"opacity.factor": 1.0
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,40 +1,22 @@
|
||||
{
|
||||
"description": "",
|
||||
"parentMaterial": "",
|
||||
"materialType": "Materials/Types/StandardPBR.materialtype",
|
||||
"materialTypeVersion": 4,
|
||||
"properties": {
|
||||
"baseColor": {
|
||||
"textureMap": "../Textures/arch_1k_basecolor.png"
|
||||
},
|
||||
"general": {
|
||||
"applySpecularAA": true
|
||||
},
|
||||
"irradiance": {
|
||||
"color": [
|
||||
0.2663614749908447,
|
||||
0.2383916974067688,
|
||||
0.18117037415504456,
|
||||
1.0
|
||||
]
|
||||
},
|
||||
"normal": {
|
||||
"textureMap": "../Textures/arch_1k_normal.jpg"
|
||||
},
|
||||
"occlusion": {
|
||||
"diffuseTextureMap": "../Textures/arch_1k_ao.png"
|
||||
},
|
||||
"opacity": {
|
||||
"factor": 1.0
|
||||
},
|
||||
"parallax": {
|
||||
"factor": 0.050999999046325684,
|
||||
"pdo": true,
|
||||
"quality": "High",
|
||||
"useTexture": false
|
||||
},
|
||||
"roughness": {
|
||||
"textureMap": "../Textures/arch_1k_roughness.png"
|
||||
}
|
||||
"propertyValues": {
|
||||
"baseColor.textureMap": "../Textures/arch_1k_basecolor.png",
|
||||
"general.applySpecularAA": true,
|
||||
"irradiance.color": [
|
||||
0.2663614749908447,
|
||||
0.2383916974067688,
|
||||
0.18117037415504456,
|
||||
1.0
|
||||
],
|
||||
"normal.textureMap": "../Textures/arch_1k_normal.jpg",
|
||||
"occlusion.diffuseTextureMap": "../Textures/arch_1k_ao.png",
|
||||
"opacity.factor": 1.0,
|
||||
"parallax.factor": 0.050999999046325684,
|
||||
"parallax.pdo": true,
|
||||
"parallax.quality": "High",
|
||||
"parallax.useTexture": false,
|
||||
"roughness.textureMap": "../Textures/arch_1k_roughness.png"
|
||||
}
|
||||
}
|
||||
@ -1,45 +1,25 @@
|
||||
{
|
||||
"description": "",
|
||||
"parentMaterial": "",
|
||||
"materialType": "Materials/Types/StandardPBR.materialtype",
|
||||
"materialTypeVersion": 4,
|
||||
"properties": {
|
||||
"baseColor": {
|
||||
"textureMap": "../Textures/background_1k_basecolor.png"
|
||||
},
|
||||
"clearCoat": {
|
||||
"factor": 0.5,
|
||||
"normalMap": "../Textures/background_1k_normal.jpg",
|
||||
"roughness": 0.4000000059604645
|
||||
},
|
||||
"general": {
|
||||
"applySpecularAA": true
|
||||
},
|
||||
"irradiance": {
|
||||
"color": [
|
||||
0.19806210696697235,
|
||||
0.1746547669172287,
|
||||
0.16513313353061676,
|
||||
1.0
|
||||
]
|
||||
},
|
||||
"normal": {
|
||||
"textureMap": "../Textures/background_1k_normal.jpg"
|
||||
},
|
||||
"occlusion": {
|
||||
"diffuseTextureMap": "../Textures/background_1k_ao.png"
|
||||
},
|
||||
"opacity": {
|
||||
"factor": 1.0
|
||||
},
|
||||
"parallax": {
|
||||
"factor": 0.03099999949336052,
|
||||
"pdo": true,
|
||||
"quality": "High",
|
||||
"useTexture": false
|
||||
},
|
||||
"roughness": {
|
||||
"textureMap": "../Textures/background_1k_roughness.png"
|
||||
}
|
||||
"propertyValues": {
|
||||
"baseColor.textureMap": "../Textures/background_1k_basecolor.png",
|
||||
"clearCoat.factor": 0.5,
|
||||
"clearCoat.normalMap": "../Textures/background_1k_normal.jpg",
|
||||
"clearCoat.roughness": 0.4000000059604645,
|
||||
"general.applySpecularAA": true,
|
||||
"irradiance.color": [
|
||||
0.19806210696697235,
|
||||
0.1746547669172287,
|
||||
0.16513313353061676,
|
||||
1.0
|
||||
],
|
||||
"normal.textureMap": "../Textures/background_1k_normal.jpg",
|
||||
"occlusion.diffuseTextureMap": "../Textures/background_1k_ao.png",
|
||||
"opacity.factor": 1.0,
|
||||
"parallax.factor": 0.03099999949336052,
|
||||
"parallax.pdo": true,
|
||||
"parallax.quality": "High",
|
||||
"parallax.useTexture": false,
|
||||
"roughness.textureMap": "../Textures/background_1k_roughness.png"
|
||||
}
|
||||
}
|
||||
@ -1,45 +1,25 @@
|
||||
{
|
||||
"description": "",
|
||||
"parentMaterial": "",
|
||||
"materialType": "Materials/Types/StandardPBR.materialtype",
|
||||
"materialTypeVersion": 4,
|
||||
"properties": {
|
||||
"baseColor": {
|
||||
"textureMap": "../Textures/bricks_1k_basecolor.png"
|
||||
},
|
||||
"clearCoat": {
|
||||
"factor": 0.5,
|
||||
"normalMap": "../Textures/bricks_1k_normal.jpg",
|
||||
"roughness": 0.5
|
||||
},
|
||||
"general": {
|
||||
"applySpecularAA": true
|
||||
},
|
||||
"irradiance": {
|
||||
"color": [
|
||||
0.27467766404151917,
|
||||
0.27467766404151917,
|
||||
0.270496666431427,
|
||||
1.0
|
||||
]
|
||||
},
|
||||
"normal": {
|
||||
"textureMap": "../Textures/bricks_1k_normal.jpg"
|
||||
},
|
||||
"occlusion": {
|
||||
"diffuseTextureMap": "../Textures/bricks_1k_ao.png"
|
||||
},
|
||||
"opacity": {
|
||||
"factor": 1.0
|
||||
},
|
||||
"parallax": {
|
||||
"algorithm": "ContactRefinement",
|
||||
"factor": 0.03500000014901161,
|
||||
"quality": "Medium",
|
||||
"useTexture": false
|
||||
},
|
||||
"roughness": {
|
||||
"textureMap": "../Textures/bricks_1k_roughness.png"
|
||||
}
|
||||
"propertyValues": {
|
||||
"baseColor.textureMap": "../Textures/bricks_1k_basecolor.png",
|
||||
"clearCoat.factor": 0.5,
|
||||
"clearCoat.normalMap": "../Textures/bricks_1k_normal.jpg",
|
||||
"clearCoat.roughness": 0.5,
|
||||
"general.applySpecularAA": true,
|
||||
"irradiance.color": [
|
||||
0.27467766404151917,
|
||||
0.27467766404151917,
|
||||
0.270496666431427,
|
||||
1.0
|
||||
],
|
||||
"normal.textureMap": "../Textures/bricks_1k_normal.jpg",
|
||||
"occlusion.diffuseTextureMap": "../Textures/bricks_1k_ao.png",
|
||||
"opacity.factor": 1.0,
|
||||
"parallax.algorithm": "ContactRefinement",
|
||||
"parallax.factor": 0.03500000014901161,
|
||||
"parallax.quality": "Medium",
|
||||
"parallax.useTexture": false,
|
||||
"roughness.textureMap": "../Textures/bricks_1k_roughness.png"
|
||||
}
|
||||
}
|
||||
@ -1,36 +1,22 @@
|
||||
{
|
||||
"description": "",
|
||||
"parentMaterial": "",
|
||||
"materialType": "Materials/Types/StandardPBR.materialtype",
|
||||
"materialTypeVersion": 4,
|
||||
"properties": {
|
||||
"baseColor": {
|
||||
"textureMap": "../Textures/ceiling_1k_basecolor.png"
|
||||
},
|
||||
"emissive": {
|
||||
"color": [
|
||||
0.0,
|
||||
0.0,
|
||||
0.0,
|
||||
1.0
|
||||
]
|
||||
},
|
||||
"irradiance": {
|
||||
"color": [
|
||||
0.29176774621009827,
|
||||
0.27888914942741394,
|
||||
0.2501564025878906,
|
||||
1.0
|
||||
]
|
||||
},
|
||||
"normal": {
|
||||
"textureMap": "../Textures/ceiling_1k_normal.png"
|
||||
},
|
||||
"opacity": {
|
||||
"factor": 1.0
|
||||
},
|
||||
"roughness": {
|
||||
"textureMap": "../Textures/ceiling_1k_roughness.png"
|
||||
}
|
||||
"propertyValues": {
|
||||
"baseColor.textureMap": "../Textures/ceiling_1k_basecolor.png",
|
||||
"emissive.color": [
|
||||
0.0,
|
||||
0.0,
|
||||
0.0,
|
||||
1.0
|
||||
],
|
||||
"irradiance.color": [
|
||||
0.29176774621009827,
|
||||
0.27888914942741394,
|
||||
0.2501564025878906,
|
||||
1.0
|
||||
],
|
||||
"normal.textureMap": "../Textures/ceiling_1k_normal.png",
|
||||
"opacity.factor": 1.0,
|
||||
"roughness.textureMap": "../Textures/ceiling_1k_roughness.png"
|
||||
}
|
||||
}
|
||||
@ -1,35 +1,21 @@
|
||||
{
|
||||
"description": "",
|
||||
"parentMaterial": "",
|
||||
"materialType": "Materials/Types/StandardPBR.materialtype",
|
||||
"materialTypeVersion": 4,
|
||||
"properties": {
|
||||
"baseColor": {
|
||||
"textureBlendMode": "Lerp",
|
||||
"textureMap": "../Textures/chain_basecolor.png"
|
||||
},
|
||||
"emissive": {
|
||||
"color": [
|
||||
0.0,
|
||||
0.0,
|
||||
0.0,
|
||||
1.0
|
||||
]
|
||||
},
|
||||
"general": {
|
||||
"doubleSided": true
|
||||
},
|
||||
"metallic": {
|
||||
"factor": 0.8899999856948853
|
||||
},
|
||||
"normal": {
|
||||
"textureMap": "../Textures/chain_normal.jpg"
|
||||
},
|
||||
"opacity": {
|
||||
"alphaSource": "Split",
|
||||
"factor": 1.0,
|
||||
"mode": "Cutout",
|
||||
"textureMap": "../Textures/chain_alpha.png"
|
||||
}
|
||||
"propertyValues": {
|
||||
"baseColor.textureBlendMode": "Lerp",
|
||||
"baseColor.textureMap": "../Textures/chain_basecolor.png",
|
||||
"emissive.color": [
|
||||
0.0,
|
||||
0.0,
|
||||
0.0,
|
||||
1.0
|
||||
],
|
||||
"general.doubleSided": true,
|
||||
"metallic.factor": 0.8899999856948853,
|
||||
"normal.textureMap": "../Textures/chain_normal.jpg",
|
||||
"opacity.alphaSource": "Split",
|
||||
"opacity.factor": 1.0,
|
||||
"opacity.mode": "Cutout",
|
||||
"opacity.textureMap": "../Textures/chain_alpha.png"
|
||||
}
|
||||
}
|
||||
@ -1,45 +1,25 @@
|
||||
{
|
||||
"description": "",
|
||||
"parentMaterial": "",
|
||||
"materialType": "Materials/Types/StandardPBR.materialtype",
|
||||
"materialTypeVersion": 4,
|
||||
"properties": {
|
||||
"baseColor": {
|
||||
"textureMap": "../Textures/columnA_1k_basecolor.png"
|
||||
},
|
||||
"clearCoat": {
|
||||
"factor": 0.5,
|
||||
"normalMap": "../Textures/columnA_1k_normal.jpg",
|
||||
"roughness": 0.30000001192092896
|
||||
},
|
||||
"general": {
|
||||
"applySpecularAA": true
|
||||
},
|
||||
"irradiance": {
|
||||
"color": [
|
||||
1.0,
|
||||
0.8964369893074036,
|
||||
0.8264744281768799,
|
||||
1.0
|
||||
]
|
||||
},
|
||||
"normal": {
|
||||
"textureMap": "../Textures/columnA_1k_normal.jpg"
|
||||
},
|
||||
"occlusion": {
|
||||
"diffuseTextureMap": "../Textures/columnA_1k_ao.png"
|
||||
},
|
||||
"opacity": {
|
||||
"factor": 1.0
|
||||
},
|
||||
"parallax": {
|
||||
"factor": 0.017000000923871994,
|
||||
"pdo": true,
|
||||
"quality": "High",
|
||||
"useTexture": false
|
||||
},
|
||||
"roughness": {
|
||||
"textureMap": "../Textures/columnA_1k_roughness.png"
|
||||
}
|
||||
"propertyValues": {
|
||||
"baseColor.textureMap": "../Textures/columnA_1k_basecolor.png",
|
||||
"clearCoat.factor": 0.5,
|
||||
"clearCoat.normalMap": "../Textures/columnA_1k_normal.jpg",
|
||||
"clearCoat.roughness": 0.30000001192092896,
|
||||
"general.applySpecularAA": true,
|
||||
"irradiance.color": [
|
||||
1.0,
|
||||
0.8964369893074036,
|
||||
0.8264744281768799,
|
||||
1.0
|
||||
],
|
||||
"normal.textureMap": "../Textures/columnA_1k_normal.jpg",
|
||||
"occlusion.diffuseTextureMap": "../Textures/columnA_1k_ao.png",
|
||||
"opacity.factor": 1.0,
|
||||
"parallax.factor": 0.017000000923871994,
|
||||
"parallax.pdo": true,
|
||||
"parallax.quality": "High",
|
||||
"parallax.useTexture": false,
|
||||
"roughness.textureMap": "../Textures/columnA_1k_roughness.png"
|
||||
}
|
||||
}
|
||||
@ -1,45 +1,25 @@
|
||||
{
|
||||
"description": "",
|
||||
"parentMaterial": "",
|
||||
"materialType": "Materials/Types/StandardPBR.materialtype",
|
||||
"materialTypeVersion": 4,
|
||||
"properties": {
|
||||
"baseColor": {
|
||||
"textureMap": "../Textures/columnB_1k_basecolor.png"
|
||||
},
|
||||
"clearCoat": {
|
||||
"factor": 0.5,
|
||||
"normalMap": "../Textures/columnB_1k_normal.jpg",
|
||||
"roughness": 0.30000001192092896
|
||||
},
|
||||
"general": {
|
||||
"applySpecularAA": true
|
||||
},
|
||||
"irradiance": {
|
||||
"color": [
|
||||
0.41788357496261597,
|
||||
0.40723279118537903,
|
||||
0.4286869466304779,
|
||||
1.0
|
||||
]
|
||||
},
|
||||
"normal": {
|
||||
"textureMap": "../Textures/columnB_1k_normal.jpg"
|
||||
},
|
||||
"occlusion": {
|
||||
"diffuseTextureMap": "../Textures/columnB_1k_ao.png"
|
||||
},
|
||||
"opacity": {
|
||||
"factor": 1.0
|
||||
},
|
||||
"parallax": {
|
||||
"factor": 0.020999999716877937,
|
||||
"pdo": true,
|
||||
"quality": "High",
|
||||
"useTexture": false
|
||||
},
|
||||
"roughness": {
|
||||
"textureMap": "../Textures/columnB_1k_roughness.png"
|
||||
}
|
||||
"propertyValues": {
|
||||
"baseColor.textureMap": "../Textures/columnB_1k_basecolor.png",
|
||||
"clearCoat.factor": 0.5,
|
||||
"clearCoat.normalMap": "../Textures/columnB_1k_normal.jpg",
|
||||
"clearCoat.roughness": 0.30000001192092896,
|
||||
"general.applySpecularAA": true,
|
||||
"irradiance.color": [
|
||||
0.41788357496261597,
|
||||
0.40723279118537903,
|
||||
0.4286869466304779,
|
||||
1.0
|
||||
],
|
||||
"normal.textureMap": "../Textures/columnB_1k_normal.jpg",
|
||||
"occlusion.diffuseTextureMap": "../Textures/columnB_1k_ao.png",
|
||||
"opacity.factor": 1.0,
|
||||
"parallax.factor": 0.020999999716877937,
|
||||
"parallax.pdo": true,
|
||||
"parallax.quality": "High",
|
||||
"parallax.useTexture": false,
|
||||
"roughness.textureMap": "../Textures/columnB_1k_roughness.png"
|
||||
}
|
||||
}
|
||||
@ -1,45 +1,25 @@
|
||||
{
|
||||
"description": "",
|
||||
"parentMaterial": "",
|
||||
"materialType": "Materials/Types/StandardPBR.materialtype",
|
||||
"materialTypeVersion": 4,
|
||||
"properties": {
|
||||
"baseColor": {
|
||||
"textureMap": "../Textures/columnC_1k_basecolor.png"
|
||||
},
|
||||
"clearCoat": {
|
||||
"factor": 0.5,
|
||||
"normalMap": "../Textures/columnC_1k_normal.jpg",
|
||||
"roughness": 0.30000001192092896
|
||||
},
|
||||
"general": {
|
||||
"applySpecularAA": true
|
||||
},
|
||||
"irradiance": {
|
||||
"color": [
|
||||
0.32314029335975647,
|
||||
0.29176774621009827,
|
||||
0.24228274822235107,
|
||||
1.0
|
||||
]
|
||||
},
|
||||
"normal": {
|
||||
"textureMap": "../Textures/columnC_1k_normal.jpg"
|
||||
},
|
||||
"occlusion": {
|
||||
"diffuseTextureMap": "../Textures/columnC_1k_ao.png"
|
||||
},
|
||||
"opacity": {
|
||||
"factor": 1.0
|
||||
},
|
||||
"parallax": {
|
||||
"factor": 0.014000000432133675,
|
||||
"pdo": true,
|
||||
"quality": "High",
|
||||
"useTexture": false
|
||||
},
|
||||
"roughness": {
|
||||
"textureMap": "../Textures/columnC_1k_roughness.png"
|
||||
}
|
||||
"propertyValues": {
|
||||
"baseColor.textureMap": "../Textures/columnC_1k_basecolor.png",
|
||||
"clearCoat.factor": 0.5,
|
||||
"clearCoat.normalMap": "../Textures/columnC_1k_normal.jpg",
|
||||
"clearCoat.roughness": 0.30000001192092896,
|
||||
"general.applySpecularAA": true,
|
||||
"irradiance.color": [
|
||||
0.32314029335975647,
|
||||
0.29176774621009827,
|
||||
0.24228274822235107,
|
||||
1.0
|
||||
],
|
||||
"normal.textureMap": "../Textures/columnC_1k_normal.jpg",
|
||||
"occlusion.diffuseTextureMap": "../Textures/columnC_1k_ao.png",
|
||||
"opacity.factor": 1.0,
|
||||
"parallax.factor": 0.014000000432133675,
|
||||
"parallax.pdo": true,
|
||||
"parallax.quality": "High",
|
||||
"parallax.useTexture": false,
|
||||
"roughness.textureMap": "../Textures/columnC_1k_roughness.png"
|
||||
}
|
||||
}
|
||||
@ -1,52 +1,32 @@
|
||||
{
|
||||
"description": "",
|
||||
"parentMaterial": "",
|
||||
"materialType": "Materials/Types/StandardPBR.materialtype",
|
||||
"materialTypeVersion": 4,
|
||||
"properties": {
|
||||
"baseColor": {
|
||||
"color": [
|
||||
1.0,
|
||||
1.0,
|
||||
1.0,
|
||||
1.0
|
||||
],
|
||||
"textureMap": "../Textures/curtainBlue_1k_basecolor.png"
|
||||
},
|
||||
"emissive": {
|
||||
"color": [
|
||||
1.0,
|
||||
1.0,
|
||||
1.0,
|
||||
1.0
|
||||
]
|
||||
},
|
||||
"general": {
|
||||
"applySpecularAA": true
|
||||
},
|
||||
"irradiance": {
|
||||
"color": [
|
||||
0.0,
|
||||
0.14901961386203766,
|
||||
1.0,
|
||||
1.0
|
||||
]
|
||||
},
|
||||
"metallic": {
|
||||
"textureMap": "../Textures/curtain_metallic.png"
|
||||
},
|
||||
"normal": {
|
||||
"factor": 0.5,
|
||||
"textureMap": "../Textures/curtain_normal.jpg"
|
||||
},
|
||||
"occlusion": {
|
||||
"diffuseTextureMap": "../Textures/curtain_ao.png"
|
||||
},
|
||||
"roughness": {
|
||||
"textureMap": "../Textures/curtain_roughness.png"
|
||||
},
|
||||
"specularF0": {
|
||||
"enableMultiScatterCompensation": true
|
||||
}
|
||||
"propertyValues": {
|
||||
"baseColor.color": [
|
||||
1.0,
|
||||
1.0,
|
||||
1.0,
|
||||
1.0
|
||||
],
|
||||
"baseColor.textureMap": "../Textures/curtainBlue_1k_basecolor.png",
|
||||
"emissive.color": [
|
||||
1.0,
|
||||
1.0,
|
||||
1.0,
|
||||
1.0
|
||||
],
|
||||
"general.applySpecularAA": true,
|
||||
"irradiance.color": [
|
||||
0.0,
|
||||
0.14901961386203766,
|
||||
1.0,
|
||||
1.0
|
||||
],
|
||||
"metallic.textureMap": "../Textures/curtain_metallic.png",
|
||||
"normal.factor": 0.5,
|
||||
"normal.textureMap": "../Textures/curtain_normal.jpg",
|
||||
"occlusion.diffuseTextureMap": "../Textures/curtain_ao.png",
|
||||
"roughness.textureMap": "../Textures/curtain_roughness.png",
|
||||
"specularF0.enableMultiScatterCompensation": true
|
||||
}
|
||||
}
|
||||
@ -1,38 +1,20 @@
|
||||
{
|
||||
"description": "",
|
||||
"parentMaterial": "",
|
||||
"materialType": "Materials/Types/StandardPBR.materialtype",
|
||||
"materialTypeVersion": 4,
|
||||
"properties": {
|
||||
"baseColor": {
|
||||
"textureMap": "../Textures/curtainGreen_1k_basecolor.png"
|
||||
},
|
||||
"general": {
|
||||
"applySpecularAA": true
|
||||
},
|
||||
"irradiance": {
|
||||
"color": [
|
||||
0.0,
|
||||
0.15294118225574493,
|
||||
0.0,
|
||||
1.0
|
||||
]
|
||||
},
|
||||
"metallic": {
|
||||
"textureMap": "../Textures/curtain_metallic.png"
|
||||
},
|
||||
"normal": {
|
||||
"factor": 0.5,
|
||||
"textureMap": "../Textures/curtain_normal.jpg"
|
||||
},
|
||||
"occlusion": {
|
||||
"diffuseTextureMap": "../Textures/curtain_ao.png"
|
||||
},
|
||||
"opacity": {
|
||||
"factor": 1.0
|
||||
},
|
||||
"roughness": {
|
||||
"textureMap": "../Textures/curtain_roughness.png"
|
||||
}
|
||||
"propertyValues": {
|
||||
"baseColor.textureMap": "../Textures/curtainGreen_1k_basecolor.png",
|
||||
"general.applySpecularAA": true,
|
||||
"irradiance.color": [
|
||||
0.0,
|
||||
0.15294118225574493,
|
||||
0.0,
|
||||
1.0
|
||||
],
|
||||
"metallic.textureMap": "../Textures/curtain_metallic.png",
|
||||
"normal.factor": 0.5,
|
||||
"normal.textureMap": "../Textures/curtain_normal.jpg",
|
||||
"occlusion.diffuseTextureMap": "../Textures/curtain_ao.png",
|
||||
"opacity.factor": 1.0,
|
||||
"roughness.textureMap": "../Textures/curtain_roughness.png"
|
||||
}
|
||||
}
|
||||
@ -1,43 +1,23 @@
|
||||
{
|
||||
"description": "",
|
||||
"parentMaterial": "",
|
||||
"materialType": "Materials/Types/StandardPBR.materialtype",
|
||||
"materialTypeVersion": 4,
|
||||
"properties": {
|
||||
"baseColor": {
|
||||
"textureMap": "../Textures/curtainRed_1k_basecolor.png"
|
||||
},
|
||||
"general": {
|
||||
"applySpecularAA": true
|
||||
},
|
||||
"irradiance": {
|
||||
"color": [
|
||||
0.41960784792900085,
|
||||
0.003921568859368563,
|
||||
0.003921568859368563,
|
||||
1.0
|
||||
]
|
||||
},
|
||||
"metallic": {
|
||||
"textureMap": "../Textures/curtain_metallic.png"
|
||||
},
|
||||
"normal": {
|
||||
"textureMap": "../Textures/curtain_normal.jpg"
|
||||
},
|
||||
"occlusion": {
|
||||
"diffuseTextureMap": "../Textures/curtain_ao.png"
|
||||
},
|
||||
"opacity": {
|
||||
"factor": 1.0
|
||||
},
|
||||
"roughness": {
|
||||
"textureMap": "../Textures/curtain_roughness.png"
|
||||
},
|
||||
"uv": {
|
||||
"center": [
|
||||
16.0,
|
||||
0.0
|
||||
]
|
||||
}
|
||||
"propertyValues": {
|
||||
"baseColor.textureMap": "../Textures/curtainRed_1k_basecolor.png",
|
||||
"general.applySpecularAA": true,
|
||||
"irradiance.color": [
|
||||
0.41960784792900085,
|
||||
0.003921568859368563,
|
||||
0.003921568859368563,
|
||||
1.0
|
||||
],
|
||||
"metallic.textureMap": "../Textures/curtain_metallic.png",
|
||||
"normal.textureMap": "../Textures/curtain_normal.jpg",
|
||||
"occlusion.diffuseTextureMap": "../Textures/curtain_ao.png",
|
||||
"opacity.factor": 1.0,
|
||||
"roughness.textureMap": "../Textures/curtain_roughness.png",
|
||||
"uv.center": [
|
||||
16.0,
|
||||
0.0
|
||||
]
|
||||
}
|
||||
}
|
||||
@ -1,39 +1,19 @@
|
||||
{
|
||||
"description": "",
|
||||
"parentMaterial": "",
|
||||
"materialType": "Materials/Types/StandardPBR.materialtype",
|
||||
"materialTypeVersion": 4,
|
||||
"properties": {
|
||||
"baseColor": {
|
||||
"textureMap": "../Textures/details_1k_basecolor.png"
|
||||
},
|
||||
"clearCoat": {
|
||||
"factor": 0.5,
|
||||
"normalMap": "../Textures/details_1k_normal.png",
|
||||
"roughness": 0.25
|
||||
},
|
||||
"general": {
|
||||
"applySpecularAA": true
|
||||
},
|
||||
"metallic": {
|
||||
"textureMap": "../Textures/details_1k_metallic.png"
|
||||
},
|
||||
"normal": {
|
||||
"textureMap": "../Textures/details_1k_normal.png"
|
||||
},
|
||||
"occlusion": {
|
||||
"diffuseTextureMap": "../Textures/details_1k_ao.png"
|
||||
},
|
||||
"opacity": {
|
||||
"factor": 1.0
|
||||
},
|
||||
"parallax": {
|
||||
"factor": 0.02500000037252903,
|
||||
"pdo": true,
|
||||
"useTexture": false
|
||||
},
|
||||
"roughness": {
|
||||
"textureMap": "../Textures/details_1k_roughness.png"
|
||||
}
|
||||
"propertyValues": {
|
||||
"baseColor.textureMap": "../Textures/details_1k_basecolor.png",
|
||||
"clearCoat.factor": 0.5,
|
||||
"clearCoat.normalMap": "../Textures/details_1k_normal.png",
|
||||
"clearCoat.roughness": 0.25,
|
||||
"general.applySpecularAA": true,
|
||||
"metallic.textureMap": "../Textures/details_1k_metallic.png",
|
||||
"normal.textureMap": "../Textures/details_1k_normal.png",
|
||||
"occlusion.diffuseTextureMap": "../Textures/details_1k_ao.png",
|
||||
"opacity.factor": 1.0,
|
||||
"parallax.factor": 0.02500000037252903,
|
||||
"parallax.pdo": true,
|
||||
"parallax.useTexture": false,
|
||||
"roughness.textureMap": "../Textures/details_1k_roughness.png"
|
||||
}
|
||||
}
|
||||
@ -1,39 +1,21 @@
|
||||
{
|
||||
"description": "",
|
||||
"parentMaterial": "",
|
||||
"materialType": "Materials/Types/StandardPBR.materialtype",
|
||||
"materialTypeVersion": 4,
|
||||
"properties": {
|
||||
"baseColor": {
|
||||
"textureMap": "../Textures/fabricBlue_1k_basecolor.png"
|
||||
},
|
||||
"general": {
|
||||
"applySpecularAA": true
|
||||
},
|
||||
"irradiance": {
|
||||
"color": [
|
||||
0.0,
|
||||
0.15049973130226135,
|
||||
1.0,
|
||||
1.0
|
||||
],
|
||||
"factor": 0.30000001192092896
|
||||
},
|
||||
"metallic": {
|
||||
"textureMap": "../Textures/fabric_metallic.png"
|
||||
},
|
||||
"normal": {
|
||||
"factor": 0.5,
|
||||
"textureMap": "../Textures/fabric_normal.jpg"
|
||||
},
|
||||
"occlusion": {
|
||||
"diffuseTextureMap": "../Textures/fabric_ao.png"
|
||||
},
|
||||
"opacity": {
|
||||
"factor": 1.0
|
||||
},
|
||||
"roughness": {
|
||||
"textureMap": "../Textures/fabric_roughness.png"
|
||||
}
|
||||
"propertyValues": {
|
||||
"baseColor.textureMap": "../Textures/fabricBlue_1k_basecolor.png",
|
||||
"general.applySpecularAA": true,
|
||||
"irradiance.color": [
|
||||
0.0,
|
||||
0.15049973130226135,
|
||||
1.0,
|
||||
1.0
|
||||
],
|
||||
"irradiance.factor": 0.30000001192092896,
|
||||
"metallic.textureMap": "../Textures/fabric_metallic.png",
|
||||
"normal.factor": 0.5,
|
||||
"normal.textureMap": "../Textures/fabric_normal.jpg",
|
||||
"occlusion.diffuseTextureMap": "../Textures/fabric_ao.png",
|
||||
"opacity.factor": 1.0,
|
||||
"roughness.textureMap": "../Textures/fabric_roughness.png"
|
||||
}
|
||||
}
|
||||
@ -1,39 +1,21 @@
|
||||
{
|
||||
"description": "",
|
||||
"parentMaterial": "",
|
||||
"materialType": "Materials/Types/StandardPBR.materialtype",
|
||||
"materialTypeVersion": 4,
|
||||
"properties": {
|
||||
"baseColor": {
|
||||
"textureMap": "../Textures/fabricGreen_1k_basecolor.png"
|
||||
},
|
||||
"general": {
|
||||
"applySpecularAA": true
|
||||
},
|
||||
"irradiance": {
|
||||
"color": [
|
||||
0.0,
|
||||
0.15292592346668243,
|
||||
0.0012207217514514923,
|
||||
1.0
|
||||
],
|
||||
"factor": 0.30000001192092896
|
||||
},
|
||||
"metallic": {
|
||||
"textureMap": "../Textures/fabric_metallic.png"
|
||||
},
|
||||
"normal": {
|
||||
"factor": 0.5,
|
||||
"textureMap": "../Textures/fabric_normal.jpg"
|
||||
},
|
||||
"occlusion": {
|
||||
"diffuseTextureMap": "../Textures/fabric_ao.png"
|
||||
},
|
||||
"opacity": {
|
||||
"factor": 1.0
|
||||
},
|
||||
"roughness": {
|
||||
"textureMap": "../Textures/fabric_roughness.png"
|
||||
}
|
||||
"propertyValues": {
|
||||
"baseColor.textureMap": "../Textures/fabricGreen_1k_basecolor.png",
|
||||
"general.applySpecularAA": true,
|
||||
"irradiance.color": [
|
||||
0.0,
|
||||
0.15292592346668243,
|
||||
0.0012207217514514923,
|
||||
1.0
|
||||
],
|
||||
"irradiance.factor": 0.30000001192092896,
|
||||
"metallic.textureMap": "../Textures/fabric_metallic.png",
|
||||
"normal.factor": 0.5,
|
||||
"normal.textureMap": "../Textures/fabric_normal.jpg",
|
||||
"occlusion.diffuseTextureMap": "../Textures/fabric_ao.png",
|
||||
"opacity.factor": 1.0,
|
||||
"roughness.textureMap": "../Textures/fabric_roughness.png"
|
||||
}
|
||||
}
|
||||
@ -1,39 +1,21 @@
|
||||
{
|
||||
"description": "",
|
||||
"parentMaterial": "",
|
||||
"materialType": "Materials/Types/StandardPBR.materialtype",
|
||||
"materialTypeVersion": 4,
|
||||
"properties": {
|
||||
"baseColor": {
|
||||
"textureMap": "../Textures/fabricRed_1k_basecolor.png"
|
||||
},
|
||||
"general": {
|
||||
"applySpecularAA": true
|
||||
},
|
||||
"irradiance": {
|
||||
"color": [
|
||||
0.42040130496025085,
|
||||
0.004654001910239458,
|
||||
0.0037232013419270515,
|
||||
1.0
|
||||
],
|
||||
"factor": 0.30000001192092896
|
||||
},
|
||||
"metallic": {
|
||||
"textureMap": "../Textures/fabric_metallic.png"
|
||||
},
|
||||
"normal": {
|
||||
"factor": 0.5,
|
||||
"textureMap": "../Textures/fabric_normal.jpg"
|
||||
},
|
||||
"occlusion": {
|
||||
"diffuseTextureMap": "../Textures/fabric_ao.png"
|
||||
},
|
||||
"opacity": {
|
||||
"factor": 1.0
|
||||
},
|
||||
"roughness": {
|
||||
"textureMap": "../Textures/fabric_roughness.png"
|
||||
}
|
||||
"propertyValues": {
|
||||
"baseColor.textureMap": "../Textures/fabricRed_1k_basecolor.png",
|
||||
"general.applySpecularAA": true,
|
||||
"irradiance.color": [
|
||||
0.42040130496025085,
|
||||
0.004654001910239458,
|
||||
0.0037232013419270515,
|
||||
1.0
|
||||
],
|
||||
"irradiance.factor": 0.30000001192092896,
|
||||
"metallic.textureMap": "../Textures/fabric_metallic.png",
|
||||
"normal.factor": 0.5,
|
||||
"normal.textureMap": "../Textures/fabric_normal.jpg",
|
||||
"occlusion.diffuseTextureMap": "../Textures/fabric_ao.png",
|
||||
"opacity.factor": 1.0,
|
||||
"roughness.textureMap": "../Textures/fabric_roughness.png"
|
||||
}
|
||||
}
|
||||
@ -1,46 +1,24 @@
|
||||
{
|
||||
"description": "",
|
||||
"parentMaterial": "",
|
||||
"materialType": "Materials/Types/StandardPBR.materialtype",
|
||||
"materialTypeVersion": 4,
|
||||
"properties": {
|
||||
"baseColor": {
|
||||
"textureMap": "../Textures/flagpole_1k_basecolor.png"
|
||||
},
|
||||
"general": {
|
||||
"applySpecularAA": true
|
||||
},
|
||||
"irradiance": {
|
||||
"color": [
|
||||
1.0,
|
||||
0.6520485281944275,
|
||||
0.7122911214828491,
|
||||
1.0
|
||||
]
|
||||
},
|
||||
"metallic": {
|
||||
"textureMap": "../Textures/flagpole_1k_metallic.png"
|
||||
},
|
||||
"normal": {
|
||||
"textureMap": "../Textures/flagpole_1k_normal.png"
|
||||
},
|
||||
"occlusion": {
|
||||
"diffuseTextureMap": "../Textures/flagpole_1k_ao.png"
|
||||
},
|
||||
"opacity": {
|
||||
"factor": 1.0
|
||||
},
|
||||
"parallax": {
|
||||
"factor": 0.014000000432133675,
|
||||
"pdo": true,
|
||||
"quality": "High",
|
||||
"useTexture": false
|
||||
},
|
||||
"roughness": {
|
||||
"textureMap": "../Textures/flagpole_1k_roughness.png"
|
||||
},
|
||||
"specularF0": {
|
||||
"enableMultiScatterCompensation": true
|
||||
}
|
||||
"propertyValues": {
|
||||
"baseColor.textureMap": "../Textures/flagpole_1k_basecolor.png",
|
||||
"general.applySpecularAA": true,
|
||||
"irradiance.color": [
|
||||
1.0,
|
||||
0.6520485281944275,
|
||||
0.7122911214828491,
|
||||
1.0
|
||||
],
|
||||
"metallic.textureMap": "../Textures/flagpole_1k_metallic.png",
|
||||
"normal.textureMap": "../Textures/flagpole_1k_normal.png",
|
||||
"occlusion.diffuseTextureMap": "../Textures/flagpole_1k_ao.png",
|
||||
"opacity.factor": 1.0,
|
||||
"parallax.factor": 0.014000000432133675,
|
||||
"parallax.pdo": true,
|
||||
"parallax.quality": "High",
|
||||
"parallax.useTexture": false,
|
||||
"roughness.textureMap": "../Textures/flagpole_1k_roughness.png",
|
||||
"specularF0.enableMultiScatterCompensation": true
|
||||
}
|
||||
}
|
||||
@ -1,44 +1,24 @@
|
||||
{
|
||||
"description": "",
|
||||
"parentMaterial": "",
|
||||
"materialType": "Materials/Types/StandardPBR.materialtype",
|
||||
"materialTypeVersion": 4,
|
||||
"properties": {
|
||||
"baseColor": {
|
||||
"textureMap": "../Textures/floor_1k_basecolor.png"
|
||||
},
|
||||
"clearCoat": {
|
||||
"influenceMap": "../Textures/floor_1k_ao.png",
|
||||
"normalMap": "../Textures/floor_1k_normal.png",
|
||||
"roughness": 0.25
|
||||
},
|
||||
"general": {
|
||||
"applySpecularAA": true
|
||||
},
|
||||
"irradiance": {
|
||||
"color": [
|
||||
1.0,
|
||||
0.9404135346412659,
|
||||
0.8688944578170776,
|
||||
1.0
|
||||
]
|
||||
},
|
||||
"normal": {
|
||||
"textureMap": "../Textures/floor_1k_normal.png"
|
||||
},
|
||||
"occlusion": {
|
||||
"diffuseTextureMap": "../Textures/floor_1k_ao.png"
|
||||
},
|
||||
"opacity": {
|
||||
"factor": 1.0
|
||||
},
|
||||
"parallax": {
|
||||
"factor": 0.012000000104308128,
|
||||
"pdo": true,
|
||||
"useTexture": false
|
||||
},
|
||||
"roughness": {
|
||||
"textureMap": "../Textures/floor_1k_roughness.png"
|
||||
}
|
||||
"propertyValues": {
|
||||
"baseColor.textureMap": "../Textures/floor_1k_basecolor.png",
|
||||
"clearCoat.influenceMap": "../Textures/floor_1k_ao.png",
|
||||
"clearCoat.normalMap": "../Textures/floor_1k_normal.png",
|
||||
"clearCoat.roughness": 0.25,
|
||||
"general.applySpecularAA": true,
|
||||
"irradiance.color": [
|
||||
1.0,
|
||||
0.9404135346412659,
|
||||
0.8688944578170776,
|
||||
1.0
|
||||
],
|
||||
"normal.textureMap": "../Textures/floor_1k_normal.png",
|
||||
"occlusion.diffuseTextureMap": "../Textures/floor_1k_ao.png",
|
||||
"opacity.factor": 1.0,
|
||||
"parallax.factor": 0.012000000104308128,
|
||||
"parallax.pdo": true,
|
||||
"parallax.useTexture": false,
|
||||
"roughness.textureMap": "../Textures/floor_1k_roughness.png"
|
||||
}
|
||||
}
|
||||
@ -1,43 +1,25 @@
|
||||
{
|
||||
"description": "",
|
||||
"parentMaterial": "",
|
||||
"materialType": "Materials/Types/StandardPBR.materialtype",
|
||||
"materialTypeVersion": 4,
|
||||
"properties": {
|
||||
"baseColor": {
|
||||
"textureMap": "../Textures/thorn_basecolor.png"
|
||||
},
|
||||
"clearCoat": {
|
||||
"factor": 0.05000000074505806,
|
||||
"normalMap": "../Textures/thorn_normal.jpg",
|
||||
"roughness": 0.10000000149011612
|
||||
},
|
||||
"general": {
|
||||
"applySpecularAA": true,
|
||||
"doubleSided": true
|
||||
},
|
||||
"irradiance": {
|
||||
"color": [
|
||||
0.46506446599960327,
|
||||
1.0,
|
||||
0.3944609761238098,
|
||||
1.0
|
||||
]
|
||||
},
|
||||
"normal": {
|
||||
"textureMap": "../Textures/thorn_normal.jpg"
|
||||
},
|
||||
"opacity": {
|
||||
"alphaSource": "Split",
|
||||
"factor": 0.20000000298023224,
|
||||
"mode": "Cutout",
|
||||
"textureMap": "../Textures/thorn_alpha.png"
|
||||
},
|
||||
"parallax": {
|
||||
"useTexture": false
|
||||
},
|
||||
"roughness": {
|
||||
"textureMap": "../Textures/thorn_roughness.png"
|
||||
}
|
||||
"propertyValues": {
|
||||
"baseColor.textureMap": "../Textures/thorn_basecolor.png",
|
||||
"clearCoat.factor": 0.05000000074505806,
|
||||
"clearCoat.normalMap": "../Textures/thorn_normal.jpg",
|
||||
"clearCoat.roughness": 0.10000000149011612,
|
||||
"general.applySpecularAA": true,
|
||||
"general.doubleSided": true,
|
||||
"irradiance.color": [
|
||||
0.46506446599960327,
|
||||
1.0,
|
||||
0.3944609761238098,
|
||||
1.0
|
||||
],
|
||||
"normal.textureMap": "../Textures/thorn_normal.jpg",
|
||||
"opacity.alphaSource": "Split",
|
||||
"opacity.factor": 0.20000000298023224,
|
||||
"opacity.mode": "Cutout",
|
||||
"opacity.textureMap": "../Textures/thorn_alpha.png",
|
||||
"parallax.useTexture": false,
|
||||
"roughness.textureMap": "../Textures/thorn_roughness.png"
|
||||
}
|
||||
}
|
||||
@ -1,36 +1,22 @@
|
||||
{
|
||||
"description": "",
|
||||
"parentMaterial": "",
|
||||
"materialType": "Materials/Types/StandardPBR.materialtype",
|
||||
"materialTypeVersion": 4,
|
||||
"properties": {
|
||||
"baseColor": {
|
||||
"textureMap": "../Textures/lion_1k_basecolor.png"
|
||||
},
|
||||
"emissive": {
|
||||
"color": [
|
||||
0.0,
|
||||
0.0,
|
||||
0.0,
|
||||
1.0
|
||||
]
|
||||
},
|
||||
"irradiance": {
|
||||
"color": [
|
||||
0.5583428740501404,
|
||||
0.496940553188324,
|
||||
0.4125429093837738,
|
||||
1.0
|
||||
]
|
||||
},
|
||||
"normal": {
|
||||
"textureMap": "../Textures/lion_1k_normal.jpg"
|
||||
},
|
||||
"opacity": {
|
||||
"factor": 1.0
|
||||
},
|
||||
"roughness": {
|
||||
"textureMap": "../Textures/lion_1k_roughness.png"
|
||||
}
|
||||
"propertyValues": {
|
||||
"baseColor.textureMap": "../Textures/lion_1k_basecolor.png",
|
||||
"emissive.color": [
|
||||
0.0,
|
||||
0.0,
|
||||
0.0,
|
||||
1.0
|
||||
],
|
||||
"irradiance.color": [
|
||||
0.5583428740501404,
|
||||
0.496940553188324,
|
||||
0.4125429093837738,
|
||||
1.0
|
||||
],
|
||||
"normal.textureMap": "../Textures/lion_1k_normal.jpg",
|
||||
"opacity.factor": 1.0,
|
||||
"roughness.textureMap": "../Textures/lion_1k_roughness.png"
|
||||
}
|
||||
}
|
||||
@ -1,47 +1,27 @@
|
||||
{
|
||||
"description": "",
|
||||
"parentMaterial": "",
|
||||
"materialType": "Materials/Types/StandardPBR.materialtype",
|
||||
"materialTypeVersion": 4,
|
||||
"properties": {
|
||||
"baseColor": {
|
||||
"textureBlendMode": "Lerp",
|
||||
"textureMap": "../Textures/roof_1k_basecolor.png"
|
||||
},
|
||||
"general": {
|
||||
"applySpecularAA": true
|
||||
},
|
||||
"irradiance": {
|
||||
"color": [
|
||||
0.29613184928894043,
|
||||
0.3324483036994934,
|
||||
0.45078203082084656,
|
||||
1.0
|
||||
]
|
||||
},
|
||||
"metallic": {
|
||||
"textureMap": "../Textures/roof_1k_metallic.png",
|
||||
"useTexture": false
|
||||
},
|
||||
"normal": {
|
||||
"factor": 0.5,
|
||||
"flipY": true,
|
||||
"textureMap": "../Textures/roof_1k_normal.jpg"
|
||||
},
|
||||
"occlusion": {
|
||||
"diffuseTextureMap": "../Textures/roof_1k_ao.png"
|
||||
},
|
||||
"opacity": {
|
||||
"factor": 1.0
|
||||
},
|
||||
"parallax": {
|
||||
"algorithm": "ContactRefinement",
|
||||
"factor": 0.019999999552965164,
|
||||
"quality": "Medium",
|
||||
"useTexture": false
|
||||
},
|
||||
"roughness": {
|
||||
"textureMap": "../Textures/roof_1k_roughness.png"
|
||||
}
|
||||
"propertyValues": {
|
||||
"baseColor.textureBlendMode": "Lerp",
|
||||
"baseColor.textureMap": "../Textures/roof_1k_basecolor.png",
|
||||
"general.applySpecularAA": true,
|
||||
"irradiance.color": [
|
||||
0.29613184928894043,
|
||||
0.3324483036994934,
|
||||
0.45078203082084656,
|
||||
1.0
|
||||
],
|
||||
"metallic.textureMap": "../Textures/roof_1k_metallic.png",
|
||||
"metallic.useTexture": false,
|
||||
"normal.factor": 0.5,
|
||||
"normal.flipY": true,
|
||||
"normal.textureMap": "../Textures/roof_1k_normal.jpg",
|
||||
"occlusion.diffuseTextureMap": "../Textures/roof_1k_ao.png",
|
||||
"opacity.factor": 1.0,
|
||||
"parallax.algorithm": "ContactRefinement",
|
||||
"parallax.factor": 0.019999999552965164,
|
||||
"parallax.quality": "Medium",
|
||||
"parallax.useTexture": false,
|
||||
"roughness.textureMap": "../Textures/roof_1k_roughness.png"
|
||||
}
|
||||
}
|
||||
@ -1,46 +1,24 @@
|
||||
{
|
||||
"description": "",
|
||||
"parentMaterial": "",
|
||||
"materialType": "Materials/Types/StandardPBR.materialtype",
|
||||
"materialTypeVersion": 4,
|
||||
"properties": {
|
||||
"baseColor": {
|
||||
"textureMap": "../Textures/vase_1k_basecolor.png"
|
||||
},
|
||||
"general": {
|
||||
"applySpecularAA": true
|
||||
},
|
||||
"irradiance": {
|
||||
"color": [
|
||||
1.0,
|
||||
0.8713664412498474,
|
||||
0.6021667718887329,
|
||||
1.0
|
||||
]
|
||||
},
|
||||
"metallic": {
|
||||
"textureMap": "../Textures/vase_1k_metallic.png"
|
||||
},
|
||||
"normal": {
|
||||
"textureMap": "../Textures/vase_1k_normal.jpg"
|
||||
},
|
||||
"occlusion": {
|
||||
"diffuseTextureMap": "../Textures/vase_1k_ao.png"
|
||||
},
|
||||
"opacity": {
|
||||
"factor": 1.0
|
||||
},
|
||||
"parallax": {
|
||||
"factor": 0.027000000700354576,
|
||||
"pdo": true,
|
||||
"quality": "High",
|
||||
"useTexture": false
|
||||
},
|
||||
"roughness": {
|
||||
"textureMap": "../Textures/vase_1k_roughness.png"
|
||||
},
|
||||
"specularF0": {
|
||||
"enableMultiScatterCompensation": true
|
||||
}
|
||||
"propertyValues": {
|
||||
"baseColor.textureMap": "../Textures/vase_1k_basecolor.png",
|
||||
"general.applySpecularAA": true,
|
||||
"irradiance.color": [
|
||||
1.0,
|
||||
0.8713664412498474,
|
||||
0.6021667718887329,
|
||||
1.0
|
||||
],
|
||||
"metallic.textureMap": "../Textures/vase_1k_metallic.png",
|
||||
"normal.textureMap": "../Textures/vase_1k_normal.jpg",
|
||||
"occlusion.diffuseTextureMap": "../Textures/vase_1k_ao.png",
|
||||
"opacity.factor": 1.0,
|
||||
"parallax.factor": 0.027000000700354576,
|
||||
"parallax.pdo": true,
|
||||
"parallax.quality": "High",
|
||||
"parallax.useTexture": false,
|
||||
"roughness.textureMap": "../Textures/vase_1k_roughness.png",
|
||||
"specularF0.enableMultiScatterCompensation": true
|
||||
}
|
||||
}
|
||||
@ -1,43 +1,23 @@
|
||||
{
|
||||
"description": "",
|
||||
"parentMaterial": "",
|
||||
"materialType": "Materials/Types/StandardPBR.materialtype",
|
||||
"materialTypeVersion": 4,
|
||||
"properties": {
|
||||
"baseColor": {
|
||||
"textureMap": "../Textures/vaseHanging_1k_basecolor.png"
|
||||
},
|
||||
"general": {
|
||||
"applySpecularAA": true
|
||||
},
|
||||
"irradiance": {
|
||||
"color": [
|
||||
0.765606164932251,
|
||||
1.0,
|
||||
0.7052567601203918,
|
||||
1.0
|
||||
]
|
||||
},
|
||||
"metallic": {
|
||||
"textureMap": "../Textures/vaseHanging_1k_metallic.png"
|
||||
},
|
||||
"normal": {
|
||||
"textureMap": "../Textures/vaseHanging_1k_normal.png"
|
||||
},
|
||||
"occlusion": {
|
||||
"diffuseTextureMap": "../Textures/vaseHanging_1k_ao.png"
|
||||
},
|
||||
"opacity": {
|
||||
"factor": 1.0
|
||||
},
|
||||
"parallax": {
|
||||
"factor": 0.04600000008940697,
|
||||
"pdo": true,
|
||||
"quality": "High",
|
||||
"useTexture": false
|
||||
},
|
||||
"roughness": {
|
||||
"textureMap": "../Textures/vaseHanging_1k_roughness.png"
|
||||
}
|
||||
"propertyValues": {
|
||||
"baseColor.textureMap": "../Textures/vaseHanging_1k_basecolor.png",
|
||||
"general.applySpecularAA": true,
|
||||
"irradiance.color": [
|
||||
0.765606164932251,
|
||||
1.0,
|
||||
0.7052567601203918,
|
||||
1.0
|
||||
],
|
||||
"metallic.textureMap": "../Textures/vaseHanging_1k_metallic.png",
|
||||
"normal.textureMap": "../Textures/vaseHanging_1k_normal.png",
|
||||
"occlusion.diffuseTextureMap": "../Textures/vaseHanging_1k_ao.png",
|
||||
"opacity.factor": 1.0,
|
||||
"parallax.factor": 0.04600000008940697,
|
||||
"parallax.pdo": true,
|
||||
"parallax.quality": "High",
|
||||
"parallax.useTexture": false,
|
||||
"roughness.textureMap": "../Textures/vaseHanging_1k_roughness.png"
|
||||
}
|
||||
}
|
||||
@ -1,36 +1,26 @@
|
||||
{
|
||||
"description": "",
|
||||
"parentMaterial": "",
|
||||
"materialType": "Materials/Types/StandardPBR.materialtype",
|
||||
"materialTypeVersion": 4,
|
||||
"properties": {
|
||||
"baseColor": {
|
||||
"color": [
|
||||
0.800000011920929,
|
||||
0.800000011920929,
|
||||
0.800000011920929,
|
||||
1.0
|
||||
],
|
||||
"textureBlendMode": "Lerp",
|
||||
"textureMap": "../Textures/vasePlant_1k_basecolor.png"
|
||||
},
|
||||
"general": {
|
||||
"applySpecularAA": true,
|
||||
"doubleSided": true
|
||||
},
|
||||
"irradiance": {
|
||||
"color": [
|
||||
0.09086747467517853,
|
||||
0.4111391007900238,
|
||||
0.0474097803235054,
|
||||
1.0
|
||||
]
|
||||
},
|
||||
"opacity": {
|
||||
"alphaSource": "Split",
|
||||
"factor": 0.23999999463558197,
|
||||
"mode": "Cutout",
|
||||
"textureMap": "../Textures/vasePlant_1k_alpha.png"
|
||||
}
|
||||
"propertyValues": {
|
||||
"baseColor.color": [
|
||||
0.800000011920929,
|
||||
0.800000011920929,
|
||||
0.800000011920929,
|
||||
1.0
|
||||
],
|
||||
"baseColor.textureBlendMode": "Lerp",
|
||||
"baseColor.textureMap": "../Textures/vasePlant_1k_basecolor.png",
|
||||
"general.applySpecularAA": true,
|
||||
"general.doubleSided": true,
|
||||
"irradiance.color": [
|
||||
0.09086747467517853,
|
||||
0.4111391007900238,
|
||||
0.0474097803235054,
|
||||
1.0
|
||||
],
|
||||
"opacity.alphaSource": "Split",
|
||||
"opacity.factor": 0.23999999463558197,
|
||||
"opacity.mode": "Cutout",
|
||||
"opacity.textureMap": "../Textures/vasePlant_1k_alpha.png"
|
||||
}
|
||||
}
|
||||
@ -1,49 +1,27 @@
|
||||
{
|
||||
"description": "",
|
||||
"parentMaterial": "",
|
||||
"materialType": "Materials/Types/StandardPBR.materialtype",
|
||||
"materialTypeVersion": 4,
|
||||
"properties": {
|
||||
"baseColor": {
|
||||
"textureMap": "../Textures/vaseRound_1k_basecolor.png"
|
||||
},
|
||||
"clearCoat": {
|
||||
"factor": 0.5,
|
||||
"influenceMap": "../Textures/vaseRound_1k_ao.png",
|
||||
"normalMap": "../Textures/vaseRound_1k_normal.jpg",
|
||||
"roughness": 0.25
|
||||
},
|
||||
"general": {
|
||||
"applySpecularAA": true
|
||||
},
|
||||
"irradiance": {
|
||||
"color": [
|
||||
0.46933698654174805,
|
||||
0.3824063539505005,
|
||||
0.47861447930336,
|
||||
1.0
|
||||
]
|
||||
},
|
||||
"normal": {
|
||||
"textureMap": "../Textures/vaseRound_1k_normal.jpg"
|
||||
},
|
||||
"occlusion": {
|
||||
"diffuseTextureMap": "../Textures/vaseRound_1k_ao.png"
|
||||
},
|
||||
"opacity": {
|
||||
"factor": 1.0
|
||||
},
|
||||
"parallax": {
|
||||
"factor": 0.019999999552965164,
|
||||
"pdo": true,
|
||||
"quality": "High",
|
||||
"useTexture": false
|
||||
},
|
||||
"roughness": {
|
||||
"textureMap": "../Textures/vaseRound_1k_roughness.png"
|
||||
},
|
||||
"specularF0": {
|
||||
"enableMultiScatterCompensation": true
|
||||
}
|
||||
"propertyValues": {
|
||||
"baseColor.textureMap": "../Textures/vaseRound_1k_basecolor.png",
|
||||
"clearCoat.factor": 0.5,
|
||||
"clearCoat.influenceMap": "../Textures/vaseRound_1k_ao.png",
|
||||
"clearCoat.normalMap": "../Textures/vaseRound_1k_normal.jpg",
|
||||
"clearCoat.roughness": 0.25,
|
||||
"general.applySpecularAA": true,
|
||||
"irradiance.color": [
|
||||
0.46933698654174805,
|
||||
0.3824063539505005,
|
||||
0.47861447930336,
|
||||
1.0
|
||||
],
|
||||
"normal.textureMap": "../Textures/vaseRound_1k_normal.jpg",
|
||||
"occlusion.diffuseTextureMap": "../Textures/vaseRound_1k_ao.png",
|
||||
"opacity.factor": 1.0,
|
||||
"parallax.factor": 0.019999999552965164,
|
||||
"parallax.pdo": true,
|
||||
"parallax.quality": "High",
|
||||
"parallax.useTexture": false,
|
||||
"roughness.textureMap": "../Textures/vaseRound_1k_roughness.png",
|
||||
"specularF0.enableMultiScatterCompensation": true
|
||||
}
|
||||
}
|
||||
@ -1,32 +1,26 @@
|
||||
{
|
||||
"materialType": "Materials/Types/StandardPBR.materialtype",
|
||||
"materialTypeVersion": 1,
|
||||
"properties": {
|
||||
"baseColor": {
|
||||
"color": [ 1.0, 1.0, 1.0 ],
|
||||
"factor": 0.75,
|
||||
"useTexture": false,
|
||||
"textureMap": ""
|
||||
},
|
||||
"metallic": {
|
||||
"factor": 0.0,
|
||||
"useTexture": false,
|
||||
"textureMap": ""
|
||||
},
|
||||
"roughness": {
|
||||
"factor": 0.0,
|
||||
"useTexture": false,
|
||||
"textureMap": ""
|
||||
},
|
||||
"specularF0": {
|
||||
"factor": 0.5,
|
||||
"useTexture": false,
|
||||
"textureMap": ""
|
||||
},
|
||||
"normal": {
|
||||
"factor": 1.0,
|
||||
"useTexture": false,
|
||||
"textureMap": ""
|
||||
}
|
||||
"propertyValues": {
|
||||
"baseColor.color": [
|
||||
1.0,
|
||||
1.0,
|
||||
1.0
|
||||
],
|
||||
"baseColor.factor": 0.75,
|
||||
"baseColor.textureMap": "",
|
||||
"baseColor.useTexture": false,
|
||||
"metallic.factor": 0.0,
|
||||
"metallic.textureMap": "",
|
||||
"metallic.useTexture": false,
|
||||
"normal.factor": 1.0,
|
||||
"normal.textureMap": "",
|
||||
"normal.useTexture": false,
|
||||
"roughness.factor": 0.0,
|
||||
"roughness.textureMap": "",
|
||||
"roughness.useTexture": false,
|
||||
"specularF0.factor": 0.5,
|
||||
"specularF0.textureMap": "",
|
||||
"specularF0.useTexture": false
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,13 +1,9 @@
|
||||
{
|
||||
"parentMaterial": "./basic.material",
|
||||
"materialType": "Materials/Types/StandardPBR.materialtype",
|
||||
"materialTypeVersion": 1,
|
||||
"properties": {
|
||||
"metallic": {
|
||||
"factor": 0.0
|
||||
},
|
||||
"roughness": {
|
||||
"factor": 0.0
|
||||
}
|
||||
"parentMaterial": "./basic.material",
|
||||
"propertyValues": {
|
||||
"metallic.factor": 0.0,
|
||||
"roughness.factor": 0.0
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,13 +1,9 @@
|
||||
{
|
||||
"parentMaterial": "./basic.material",
|
||||
"materialType": "Materials/Types/StandardPBR.materialtype",
|
||||
"materialTypeVersion": 1,
|
||||
"properties": {
|
||||
"metallic": {
|
||||
"factor": 0.0
|
||||
},
|
||||
"roughness": {
|
||||
"factor": 0.1
|
||||
}
|
||||
"parentMaterial": "./basic.material",
|
||||
"propertyValues": {
|
||||
"metallic.factor": 0.0,
|
||||
"roughness.factor": 0.10000000149011612
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,13 +1,9 @@
|
||||
{
|
||||
"parentMaterial": "./basic.material",
|
||||
"materialType": "Materials/Types/StandardPBR.materialtype",
|
||||
"materialTypeVersion": 1,
|
||||
"properties": {
|
||||
"metallic": {
|
||||
"factor": 0.0
|
||||
},
|
||||
"roughness": {
|
||||
"factor": 0.2
|
||||
}
|
||||
"parentMaterial": "./basic.material",
|
||||
"propertyValues": {
|
||||
"metallic.factor": 0.0,
|
||||
"roughness.factor": 0.20000000298023224
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,13 +1,9 @@
|
||||
{
|
||||
"parentMaterial": "./basic.material",
|
||||
"materialType": "Materials/Types/StandardPBR.materialtype",
|
||||
"materialTypeVersion": 1,
|
||||
"properties": {
|
||||
"metallic": {
|
||||
"factor": 0.0
|
||||
},
|
||||
"roughness": {
|
||||
"factor": 0.3
|
||||
}
|
||||
"parentMaterial": "./basic.material",
|
||||
"propertyValues": {
|
||||
"metallic.factor": 0.0,
|
||||
"roughness.factor": 0.30000001192092896
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,13 +1,9 @@
|
||||
{
|
||||
"parentMaterial": "./basic.material",
|
||||
"materialType": "Materials/Types/StandardPBR.materialtype",
|
||||
"materialTypeVersion": 1,
|
||||
"properties": {
|
||||
"metallic": {
|
||||
"factor": 0.0
|
||||
},
|
||||
"roughness": {
|
||||
"factor": 0.4
|
||||
}
|
||||
"parentMaterial": "./basic.material",
|
||||
"propertyValues": {
|
||||
"metallic.factor": 0.0,
|
||||
"roughness.factor": 0.4000000059604645
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,13 +1,9 @@
|
||||
{
|
||||
"parentMaterial": "./basic.material",
|
||||
"materialType": "Materials/Types/StandardPBR.materialtype",
|
||||
"materialTypeVersion": 1,
|
||||
"properties": {
|
||||
"metallic": {
|
||||
"factor": 0.0
|
||||
},
|
||||
"roughness": {
|
||||
"factor": 0.5
|
||||
}
|
||||
"parentMaterial": "./basic.material",
|
||||
"propertyValues": {
|
||||
"metallic.factor": 0.0,
|
||||
"roughness.factor": 0.5
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,13 +1,9 @@
|
||||
{
|
||||
"parentMaterial": "./basic.material",
|
||||
"materialType": "Materials/Types/StandardPBR.materialtype",
|
||||
"materialTypeVersion": 1,
|
||||
"properties": {
|
||||
"metallic": {
|
||||
"factor": 0.0
|
||||
},
|
||||
"roughness": {
|
||||
"factor": 0.6
|
||||
}
|
||||
"parentMaterial": "./basic.material",
|
||||
"propertyValues": {
|
||||
"metallic.factor": 0.0,
|
||||
"roughness.factor": 0.6000000238418579
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,13 +1,9 @@
|
||||
{
|
||||
"parentMaterial": "./basic.material",
|
||||
"materialType": "Materials/Types/StandardPBR.materialtype",
|
||||
"materialTypeVersion": 1,
|
||||
"properties": {
|
||||
"metallic": {
|
||||
"factor": 0.0
|
||||
},
|
||||
"roughness": {
|
||||
"factor": 0.7
|
||||
}
|
||||
"parentMaterial": "./basic.material",
|
||||
"propertyValues": {
|
||||
"metallic.factor": 0.0,
|
||||
"roughness.factor": 0.699999988079071
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,13 +1,9 @@
|
||||
{
|
||||
"parentMaterial": "./basic.material",
|
||||
"materialType": "Materials/Types/StandardPBR.materialtype",
|
||||
"materialTypeVersion": 1,
|
||||
"properties": {
|
||||
"metallic": {
|
||||
"factor": 0.0
|
||||
},
|
||||
"roughness": {
|
||||
"factor": 0.8
|
||||
}
|
||||
"parentMaterial": "./basic.material",
|
||||
"propertyValues": {
|
||||
"metallic.factor": 0.0,
|
||||
"roughness.factor": 0.800000011920929
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,13 +1,9 @@
|
||||
{
|
||||
"parentMaterial": "./basic.material",
|
||||
"materialType": "Materials/Types/StandardPBR.materialtype",
|
||||
"materialTypeVersion": 1,
|
||||
"properties": {
|
||||
"metallic": {
|
||||
"factor": 0.0
|
||||
},
|
||||
"roughness": {
|
||||
"factor": 0.9
|
||||
}
|
||||
"parentMaterial": "./basic.material",
|
||||
"propertyValues": {
|
||||
"metallic.factor": 0.0,
|
||||
"roughness.factor": 0.8999999761581421
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,13 +1,9 @@
|
||||
{
|
||||
"parentMaterial": "./basic.material",
|
||||
"materialType": "Materials/Types/StandardPBR.materialtype",
|
||||
"materialTypeVersion": 1,
|
||||
"properties": {
|
||||
"metallic": {
|
||||
"factor": 0.0
|
||||
},
|
||||
"roughness": {
|
||||
"factor": 1.0
|
||||
}
|
||||
"parentMaterial": "./basic.material",
|
||||
"propertyValues": {
|
||||
"metallic.factor": 0.0,
|
||||
"roughness.factor": 1.0
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,13 +1,9 @@
|
||||
{
|
||||
"parentMaterial": "./basic.material",
|
||||
"materialType": "Materials/Types/StandardPBR.materialtype",
|
||||
"materialTypeVersion": 1,
|
||||
"properties": {
|
||||
"metallic": {
|
||||
"factor": 1.0
|
||||
},
|
||||
"roughness": {
|
||||
"factor": 0.0
|
||||
}
|
||||
"parentMaterial": "./basic.material",
|
||||
"propertyValues": {
|
||||
"metallic.factor": 1.0,
|
||||
"roughness.factor": 0.0
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,13 +1,9 @@
|
||||
{
|
||||
"parentMaterial": "./basic.material",
|
||||
"materialType": "Materials/Types/StandardPBR.materialtype",
|
||||
"materialTypeVersion": 1,
|
||||
"properties": {
|
||||
"metallic": {
|
||||
"factor": 1.0
|
||||
},
|
||||
"roughness": {
|
||||
"factor": 0.1
|
||||
}
|
||||
"parentMaterial": "./basic.material",
|
||||
"propertyValues": {
|
||||
"metallic.factor": 1.0,
|
||||
"roughness.factor": 0.10000000149011612
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,13 +1,9 @@
|
||||
{
|
||||
"parentMaterial": "./basic.material",
|
||||
"materialType": "Materials/Types/StandardPBR.materialtype",
|
||||
"materialTypeVersion": 1,
|
||||
"properties": {
|
||||
"metallic": {
|
||||
"factor": 1.0
|
||||
},
|
||||
"roughness": {
|
||||
"factor": 0.2
|
||||
}
|
||||
"parentMaterial": "./basic.material",
|
||||
"propertyValues": {
|
||||
"metallic.factor": 1.0,
|
||||
"roughness.factor": 0.20000000298023224
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,13 +1,9 @@
|
||||
{
|
||||
"parentMaterial": "./basic.material",
|
||||
"materialType": "Materials/Types/StandardPBR.materialtype",
|
||||
"materialTypeVersion": 1,
|
||||
"properties": {
|
||||
"metallic": {
|
||||
"factor": 1.0
|
||||
},
|
||||
"roughness": {
|
||||
"factor": 0.3
|
||||
}
|
||||
"parentMaterial": "./basic.material",
|
||||
"propertyValues": {
|
||||
"metallic.factor": 1.0,
|
||||
"roughness.factor": 0.30000001192092896
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,13 +1,9 @@
|
||||
{
|
||||
"parentMaterial": "./basic.material",
|
||||
"materialType": "Materials/Types/StandardPBR.materialtype",
|
||||
"materialTypeVersion": 1,
|
||||
"properties": {
|
||||
"metallic": {
|
||||
"factor": 1.0
|
||||
},
|
||||
"roughness": {
|
||||
"factor": 0.4
|
||||
}
|
||||
"parentMaterial": "./basic.material",
|
||||
"propertyValues": {
|
||||
"metallic.factor": 1.0,
|
||||
"roughness.factor": 0.4000000059604645
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,13 +1,9 @@
|
||||
{
|
||||
"parentMaterial": "./basic.material",
|
||||
"materialType": "Materials/Types/StandardPBR.materialtype",
|
||||
"materialTypeVersion": 1,
|
||||
"properties": {
|
||||
"metallic": {
|
||||
"factor": 1.0
|
||||
},
|
||||
"roughness": {
|
||||
"factor": 0.5
|
||||
}
|
||||
"parentMaterial": "./basic.material",
|
||||
"propertyValues": {
|
||||
"metallic.factor": 1.0,
|
||||
"roughness.factor": 0.5
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,13 +1,9 @@
|
||||
{
|
||||
"parentMaterial": "./basic.material",
|
||||
"materialType": "Materials/Types/StandardPBR.materialtype",
|
||||
"materialTypeVersion": 1,
|
||||
"properties": {
|
||||
"metallic": {
|
||||
"factor": 1.0
|
||||
},
|
||||
"roughness": {
|
||||
"factor": 0.6
|
||||
}
|
||||
"parentMaterial": "./basic.material",
|
||||
"propertyValues": {
|
||||
"metallic.factor": 1.0,
|
||||
"roughness.factor": 0.6000000238418579
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,13 +1,9 @@
|
||||
{
|
||||
"parentMaterial": "./basic.material",
|
||||
"materialType": "Materials/Types/StandardPBR.materialtype",
|
||||
"materialTypeVersion": 1,
|
||||
"properties": {
|
||||
"metallic": {
|
||||
"factor": 1.0
|
||||
},
|
||||
"roughness": {
|
||||
"factor": 0.7
|
||||
}
|
||||
"parentMaterial": "./basic.material",
|
||||
"propertyValues": {
|
||||
"metallic.factor": 1.0,
|
||||
"roughness.factor": 0.699999988079071
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,13 +1,9 @@
|
||||
{
|
||||
"parentMaterial": "./basic.material",
|
||||
"materialType": "Materials/Types/StandardPBR.materialtype",
|
||||
"materialTypeVersion": 1,
|
||||
"properties": {
|
||||
"metallic": {
|
||||
"factor": 1.0
|
||||
},
|
||||
"roughness": {
|
||||
"factor": 0.8
|
||||
}
|
||||
"parentMaterial": "./basic.material",
|
||||
"propertyValues": {
|
||||
"metallic.factor": 1.0,
|
||||
"roughness.factor": 0.800000011920929
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,13 +1,9 @@
|
||||
{
|
||||
"parentMaterial": "./basic.material",
|
||||
"materialType": "Materials/Types/StandardPBR.materialtype",
|
||||
"materialTypeVersion": 1,
|
||||
"properties": {
|
||||
"metallic": {
|
||||
"factor": 1.0
|
||||
},
|
||||
"roughness": {
|
||||
"factor": 0.9
|
||||
}
|
||||
"parentMaterial": "./basic.material",
|
||||
"propertyValues": {
|
||||
"metallic.factor": 1.0,
|
||||
"roughness.factor": 0.8999999761581421
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,13 +1,9 @@
|
||||
{
|
||||
"parentMaterial": "./basic.material",
|
||||
"materialType": "Materials/Types/StandardPBR.materialtype",
|
||||
"materialTypeVersion": 1,
|
||||
"properties": {
|
||||
"metallic": {
|
||||
"factor": 1.0
|
||||
},
|
||||
"roughness": {
|
||||
"factor": 1.0
|
||||
}
|
||||
"parentMaterial": "./basic.material",
|
||||
"propertyValues": {
|
||||
"metallic.factor": 1.0,
|
||||
"roughness.factor": 1.0
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,4 +1,4 @@
|
||||
{
|
||||
"materialType": "Materials/Types/StandardPBR.materialtype",
|
||||
"parentMaterial": "Materials/Presets/PBR/default_grid.material"
|
||||
}
|
||||
}
|
||||
@ -1,11 +1,8 @@
|
||||
{
|
||||
"description": "",
|
||||
"materialType": "Materials/Types/StandardPBR.materialtype",
|
||||
"parentMaterial": "Materials/Presets/PBR/default_grid.material",
|
||||
"materialTypeVersion": 3,
|
||||
"properties": {
|
||||
"opacity": {
|
||||
"mode": "Blended"
|
||||
}
|
||||
"parentMaterial": "Materials/Presets/PBR/default_grid.material",
|
||||
"propertyValues": {
|
||||
"opacity.mode": "Blended"
|
||||
}
|
||||
}
|
||||
@ -1,17 +1,13 @@
|
||||
{
|
||||
"description": "",
|
||||
"parentMaterial": "",
|
||||
"materialType": "TestData/Materials/Types/MinimalPBR.materialtype",
|
||||
"materialTypeVersion": 3,
|
||||
"properties": {
|
||||
"settings": {
|
||||
"color": [
|
||||
0.08522164076566696,
|
||||
0.11898985505104065,
|
||||
1.0,
|
||||
1.0
|
||||
],
|
||||
"roughness": 0.33000001311302185
|
||||
}
|
||||
"propertyValues": {
|
||||
"settings.color": [
|
||||
0.08522164076566696,
|
||||
0.11898985505104065,
|
||||
1.0,
|
||||
1.0
|
||||
],
|
||||
"settings.roughness": 0.33000001311302185
|
||||
}
|
||||
}
|
||||
@ -1,3 +1,3 @@
|
||||
{
|
||||
"materialType": "UVs.materialtype"
|
||||
}
|
||||
}
|
||||
@ -1,32 +1,26 @@
|
||||
{
|
||||
"materialType": "Materials/Types/StandardPBR.materialtype",
|
||||
"materialTypeVersion": 1,
|
||||
"properties": {
|
||||
"baseColor": {
|
||||
"color": [ 0.18, 0.18, 0.18 ],
|
||||
"factor": 1.0,
|
||||
"useTexture": false,
|
||||
"textureMap": ""
|
||||
},
|
||||
"metallic": {
|
||||
"factor": 0.0,
|
||||
"useTexture": false,
|
||||
"textureMap": ""
|
||||
},
|
||||
"roughness": {
|
||||
"factor": 1.0,
|
||||
"useTexture": false,
|
||||
"textureMap": ""
|
||||
},
|
||||
"specularF0": {
|
||||
"factor": 0.5,
|
||||
"useTexture": false,
|
||||
"textureMap": ""
|
||||
},
|
||||
"normal": {
|
||||
"factor": 1.0,
|
||||
"useTexture": false,
|
||||
"textureMap": ""
|
||||
}
|
||||
"propertyValues": {
|
||||
"baseColor.color": [
|
||||
0.18000000715255737,
|
||||
0.18000000715255737,
|
||||
0.18000000715255737
|
||||
],
|
||||
"baseColor.factor": 1.0,
|
||||
"baseColor.textureMap": "",
|
||||
"baseColor.useTexture": false,
|
||||
"metallic.factor": 0.0,
|
||||
"metallic.textureMap": "",
|
||||
"metallic.useTexture": false,
|
||||
"normal.factor": 1.0,
|
||||
"normal.textureMap": "",
|
||||
"normal.useTexture": false,
|
||||
"roughness.factor": 1.0,
|
||||
"roughness.textureMap": "",
|
||||
"roughness.useTexture": false,
|
||||
"specularF0.factor": 0.5,
|
||||
"specularF0.textureMap": "",
|
||||
"specularF0.useTexture": false
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,36 +1,20 @@
|
||||
{
|
||||
"materialType": "Materials/Types/StandardPBR.materialtype",
|
||||
"materialTypeVersion": 4,
|
||||
"properties": {
|
||||
"baseColor": {
|
||||
"textureMap": "Materials/decal/airship_symbol_decal.tif"
|
||||
},
|
||||
"general": {
|
||||
"doubleSided": true
|
||||
},
|
||||
"metallic": {
|
||||
"useTexture": false
|
||||
},
|
||||
"normal": {
|
||||
"useTexture": false
|
||||
},
|
||||
"opacity": {
|
||||
"alphaSource": "Split",
|
||||
"factor": 0.6899999976158142,
|
||||
"mode": "Cutout",
|
||||
"textureMap": "Materials/decal/airship_symbol_decal.tif"
|
||||
},
|
||||
"roughness": {
|
||||
"useTexture": false
|
||||
},
|
||||
"specularF0": {
|
||||
"useTexture": false
|
||||
},
|
||||
"uv": {
|
||||
"center": [
|
||||
0.0,
|
||||
1.0
|
||||
]
|
||||
}
|
||||
"propertyValues": {
|
||||
"baseColor.textureMap": "Materials/decal/airship_symbol_decal.tif",
|
||||
"general.doubleSided": true,
|
||||
"metallic.useTexture": false,
|
||||
"normal.useTexture": false,
|
||||
"opacity.alphaSource": "Split",
|
||||
"opacity.factor": 0.6899999976158142,
|
||||
"opacity.mode": "Cutout",
|
||||
"opacity.textureMap": "Materials/decal/airship_symbol_decal.tif",
|
||||
"roughness.useTexture": false,
|
||||
"specularF0.useTexture": false,
|
||||
"uv.center": [
|
||||
0.0,
|
||||
1.0
|
||||
]
|
||||
}
|
||||
}
|
||||
@ -1,13 +1,9 @@
|
||||
{
|
||||
"description": "",
|
||||
"materialType": "Materials/Types/Skin.materialtype",
|
||||
"parentMaterial": "",
|
||||
"materialTypeVersion": 3,
|
||||
"properties": {
|
||||
"wrinkleLayers": {
|
||||
"count": 3,
|
||||
"enable": true,
|
||||
"showBlendValues": true
|
||||
}
|
||||
"propertyValues": {
|
||||
"wrinkleLayers.count": 3,
|
||||
"wrinkleLayers.enable": true,
|
||||
"wrinkleLayers.showBlendValues": true
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,178 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project.
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include <AzCore/DOM/DomComparison.h>
|
||||
#include <AzCore/std/containers/queue.h>
|
||||
#include <AzCore/std/containers/unordered_set.h>
|
||||
|
||||
namespace AZ::Dom
|
||||
{
|
||||
PatchUndoRedoInfo GenerateHierarchicalDeltaPatch(
|
||||
const Value& beforeState, const Value& afterState, const DeltaPatchGenerationParameters& params)
|
||||
{
|
||||
PatchUndoRedoInfo patches;
|
||||
|
||||
auto AddPatch = [&patches](PatchOperation op, PatchOperation inverse)
|
||||
{
|
||||
patches.m_forwardPatches.PushBack(AZStd::move(op));
|
||||
patches.m_inversePatches.PushFront(AZStd::move(inverse));
|
||||
};
|
||||
|
||||
AZStd::function<void(const Path&, const Value&, const Value&)> compareValues;
|
||||
|
||||
struct PendingComparison
|
||||
{
|
||||
Path m_path;
|
||||
const Value& m_before;
|
||||
const Value& m_after;
|
||||
|
||||
PendingComparison(Path path, const Value& before, const Value& after)
|
||||
: m_path(AZStd::move(path))
|
||||
, m_before(before)
|
||||
, m_after(after)
|
||||
{
|
||||
}
|
||||
};
|
||||
AZStd::queue<PendingComparison> entriesToCompare;
|
||||
|
||||
AZStd::unordered_set<AZ::Name::Hash> desiredKeys;
|
||||
auto compareObjects = [&](const Path& path, const Value& before, const Value& after)
|
||||
{
|
||||
desiredKeys.clear();
|
||||
Path subPath = path;
|
||||
for (auto it = after.MemberBegin(); it != after.MemberEnd(); ++it)
|
||||
{
|
||||
desiredKeys.insert(it->first.GetHash());
|
||||
subPath.Push(it->first);
|
||||
auto beforeIt = before.FindMember(it->first);
|
||||
if (beforeIt == before.MemberEnd())
|
||||
{
|
||||
AddPatch(PatchOperation::AddOperation(subPath, it->second), PatchOperation::RemoveOperation(subPath));
|
||||
}
|
||||
else
|
||||
{
|
||||
entriesToCompare.emplace(subPath, beforeIt->second, it->second);
|
||||
}
|
||||
subPath.Pop();
|
||||
}
|
||||
|
||||
for (auto it = before.MemberBegin(); it != before.MemberEnd(); ++it)
|
||||
{
|
||||
if (!desiredKeys.contains(it->first.GetHash()))
|
||||
{
|
||||
subPath.Push(it->first);
|
||||
AddPatch(PatchOperation::RemoveOperation(subPath), PatchOperation::AddOperation(subPath, it->second));
|
||||
subPath.Pop();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
auto compareArrays = [&](const Path& path, const Value& before, const Value& after)
|
||||
{
|
||||
const size_t beforeSize = before.ArraySize();
|
||||
const size_t afterSize = after.ArraySize();
|
||||
|
||||
// If more than replaceThreshold values differ, do a replace operation instead
|
||||
if (params.m_replaceThreshold != DeltaPatchGenerationParameters::NoReplace)
|
||||
{
|
||||
size_t changedValueCount = 0;
|
||||
const size_t entriesToEnumerate = AZStd::min(beforeSize, afterSize);
|
||||
for (size_t i = 0; i < entriesToEnumerate; ++i)
|
||||
{
|
||||
if (before[i] != after[i])
|
||||
{
|
||||
++changedValueCount;
|
||||
if (changedValueCount >= params.m_replaceThreshold)
|
||||
{
|
||||
AddPatch(PatchOperation::ReplaceOperation(path, after), PatchOperation::ReplaceOperation(path, before));
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Path subPath = path;
|
||||
for (size_t i = 0; i < afterSize; ++i)
|
||||
{
|
||||
if (i >= beforeSize)
|
||||
{
|
||||
subPath.Push(PathEntry(PathEntry::EndOfArrayIndex));
|
||||
AddPatch(PatchOperation::AddOperation(subPath, after[i]), PatchOperation::RemoveOperation(subPath));
|
||||
subPath.Pop();
|
||||
}
|
||||
else
|
||||
{
|
||||
subPath.Push(PathEntry(i));
|
||||
entriesToCompare.emplace(subPath, before[i], after[i]);
|
||||
subPath.Pop();
|
||||
}
|
||||
}
|
||||
|
||||
if (beforeSize > afterSize)
|
||||
{
|
||||
subPath.Push(PathEntry(PathEntry::EndOfArrayIndex));
|
||||
for (size_t i = beforeSize; i > afterSize; --i)
|
||||
{
|
||||
AddPatch(PatchOperation::RemoveOperation(subPath), PatchOperation::AddOperation(subPath, before[i - 1]));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
auto compareNodes = [&](const Path& path, const Value& before, const Value& after)
|
||||
{
|
||||
if (before.GetNodeName() != after.GetNodeName())
|
||||
{
|
||||
AddPatch(PatchOperation::ReplaceOperation(path, after), PatchOperation::ReplaceOperation(path, before));
|
||||
}
|
||||
else
|
||||
{
|
||||
compareObjects(path, before, after);
|
||||
compareArrays(path, before, after);
|
||||
}
|
||||
};
|
||||
|
||||
compareValues = [&](const Path& path, const Value& before, const Value& after)
|
||||
{
|
||||
if (before.GetType() != after.GetType())
|
||||
{
|
||||
AddPatch(PatchOperation::ReplaceOperation(path, after), PatchOperation::ReplaceOperation(path, before));
|
||||
}
|
||||
else if (before == after)
|
||||
{
|
||||
// If a shallow comparison succeeds we're pointing to an identical value or container
|
||||
// and don't need to drill down.
|
||||
return;
|
||||
}
|
||||
else if (before.IsObject())
|
||||
{
|
||||
compareObjects(path, before, after);
|
||||
}
|
||||
else if (before.IsArray())
|
||||
{
|
||||
compareArrays(path, before, after);
|
||||
}
|
||||
else if (before.IsNode())
|
||||
{
|
||||
compareNodes(path, before, after);
|
||||
}
|
||||
else
|
||||
{
|
||||
AddPatch(PatchOperation::ReplaceOperation(path, after), PatchOperation::ReplaceOperation(path, before));
|
||||
}
|
||||
};
|
||||
|
||||
entriesToCompare.emplace(Path(), beforeState, afterState);
|
||||
while (!entriesToCompare.empty())
|
||||
{
|
||||
PendingComparison& comparison = entriesToCompare.front();
|
||||
compareValues(comparison.m_path, comparison.m_before, comparison.m_after);
|
||||
entriesToCompare.pop();
|
||||
}
|
||||
return patches;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project.
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <AzCore/DOM/DomPatch.h>
|
||||
|
||||
namespace AZ::Dom
|
||||
{
|
||||
//! A set of patches for applying a change and doing the inverse operation.
|
||||
struct PatchUndoRedoInfo
|
||||
{
|
||||
Patch m_forwardPatches;
|
||||
Patch m_inversePatches;
|
||||
};
|
||||
|
||||
//! Parameters for GenerateHierarchicalDeltaPatch.
|
||||
struct DeltaPatchGenerationParameters
|
||||
{
|
||||
static constexpr size_t NoReplace = AZStd::numeric_limits<size_t>::max();
|
||||
static constexpr size_t AlwaysFullReplace = 0;
|
||||
|
||||
//! The threshold of changed values in a node or array which, if exceeded, will cause the generation to create an
|
||||
//! entire "replace" oepration instead. If set to NoReplace, no replacement will occur.
|
||||
size_t m_replaceThreshold = 3;
|
||||
};
|
||||
|
||||
//! Generates a set of patches such that m_forwardPatches.Apply(beforeState) shall produce a document equivalent to afterState, and
|
||||
//! a subsequent m_inversePatches.Apply(beforeState) shall produce the original document. This patch generation strategy does a
|
||||
//! hierarchical comparison and is not guaranteed to create the minimal set of patches required to transform between the two states.
|
||||
PatchUndoRedoInfo GenerateHierarchicalDeltaPatch(const Value& beforeState, const Value& afterState, const DeltaPatchGenerationParameters& params = {});
|
||||
} // namespace AZ::Dom
|
||||
@ -0,0 +1,799 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project.
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include <AzCore/DOM/DomPatch.h>
|
||||
#include <AzCore/DOM/DomUtils.h>
|
||||
|
||||
namespace AZ::Dom
|
||||
{
|
||||
PatchOperation::PatchOperation(Path destinationPath, Type type, Value value)
|
||||
: m_domPath(AZStd::move(destinationPath))
|
||||
, m_type(type)
|
||||
, m_value(AZStd::move(value))
|
||||
{
|
||||
}
|
||||
|
||||
PatchOperation::PatchOperation(Path destinationPath, Type type, Path sourcePath)
|
||||
: m_domPath(AZStd::move(destinationPath))
|
||||
, m_type(type)
|
||||
, m_value(AZStd::move(sourcePath))
|
||||
{
|
||||
}
|
||||
|
||||
PatchOperation::PatchOperation(Path destinationPath, Type type)
|
||||
: m_domPath(AZStd::move(destinationPath))
|
||||
, m_type(type)
|
||||
{
|
||||
}
|
||||
|
||||
bool PatchOperation::operator==(const PatchOperation& rhs) const
|
||||
{
|
||||
if (m_type != rhs.m_type)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
switch (m_type)
|
||||
{
|
||||
case Type::Add:
|
||||
return m_domPath == rhs.m_domPath && Utils::DeepCompareIsEqual(GetValue(), rhs.GetValue());
|
||||
case Type::Remove:
|
||||
return m_domPath == rhs.m_domPath;
|
||||
case Type::Replace:
|
||||
return m_domPath == rhs.m_domPath && Utils::DeepCompareIsEqual(GetValue(), rhs.GetValue());
|
||||
case Type::Copy:
|
||||
return m_domPath == rhs.m_domPath && GetSourcePath() == rhs.GetSourcePath();
|
||||
case Type::Move:
|
||||
return m_domPath == rhs.m_domPath && GetSourcePath() == rhs.GetSourcePath();
|
||||
case Type::Test:
|
||||
return m_domPath == rhs.m_domPath && Utils::DeepCompareIsEqual(GetValue(), rhs.GetValue());
|
||||
default:
|
||||
AZ_Assert(false, "PatchOperation::GetDomRepresentation: invalid patch type specified");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool PatchOperation::operator!=(const PatchOperation& rhs) const
|
||||
{
|
||||
return !operator==(rhs);
|
||||
}
|
||||
|
||||
PatchOperation::Type PatchOperation::GetType() const
|
||||
{
|
||||
return m_type;
|
||||
}
|
||||
|
||||
void PatchOperation::SetType(Type type)
|
||||
{
|
||||
m_type = type;
|
||||
}
|
||||
|
||||
const Path& PatchOperation::GetDestinationPath() const
|
||||
{
|
||||
return m_domPath;
|
||||
}
|
||||
|
||||
void PatchOperation::SetDestinationPath(Path path)
|
||||
{
|
||||
m_domPath = path;
|
||||
}
|
||||
|
||||
const Value& PatchOperation::GetValue() const
|
||||
{
|
||||
return AZStd::get<Value>(m_value);
|
||||
}
|
||||
|
||||
void PatchOperation::SetValue(Value value)
|
||||
{
|
||||
m_value = AZStd::move(value);
|
||||
}
|
||||
|
||||
const Path& PatchOperation::GetSourcePath() const
|
||||
{
|
||||
return AZStd::get<Path>(m_value);
|
||||
}
|
||||
|
||||
void PatchOperation::SetSourcePath(Path path)
|
||||
{
|
||||
m_value = AZStd::move(path);
|
||||
}
|
||||
|
||||
AZ::Outcome<Value, AZStd::string> PatchOperation::Apply(Value rootElement) const
|
||||
{
|
||||
PatchOutcome outcome = ApplyInPlace(rootElement);
|
||||
if (!outcome.IsSuccess())
|
||||
{
|
||||
return AZ::Failure(outcome.TakeError());
|
||||
}
|
||||
return AZ::Success(AZStd::move(rootElement));
|
||||
}
|
||||
|
||||
PatchOperation::PatchOutcome PatchOperation::ApplyInPlace(Value& rootElement) const
|
||||
{
|
||||
switch (m_type)
|
||||
{
|
||||
case Type::Add:
|
||||
return ApplyAdd(rootElement);
|
||||
case Type::Remove:
|
||||
return ApplyRemove(rootElement);
|
||||
case Type::Replace:
|
||||
return ApplyReplace(rootElement);
|
||||
case Type::Copy:
|
||||
return ApplyCopy(rootElement);
|
||||
case Type::Move:
|
||||
return ApplyMove(rootElement);
|
||||
case Type::Test:
|
||||
return ApplyTest(rootElement);
|
||||
}
|
||||
return AZ::Failure<AZStd::string>("Unsupported DOM patch operation specified");
|
||||
}
|
||||
|
||||
Value PatchOperation::GetDomRepresentation() const
|
||||
{
|
||||
Value serializedPatch(Dom::Type::Object);
|
||||
switch (m_type)
|
||||
{
|
||||
case Type::Add:
|
||||
serializedPatch["op"].SetString("add");
|
||||
serializedPatch["path"].CopyFromString(GetDestinationPath().ToString());
|
||||
serializedPatch["value"] = GetValue();
|
||||
break;
|
||||
case Type::Remove:
|
||||
serializedPatch["op"].SetString("remove");
|
||||
serializedPatch["path"].CopyFromString(GetDestinationPath().ToString());
|
||||
break;
|
||||
case Type::Replace:
|
||||
serializedPatch["op"].SetString("replace");
|
||||
serializedPatch["path"].CopyFromString(GetDestinationPath().ToString());
|
||||
serializedPatch["value"] = GetValue();
|
||||
break;
|
||||
case Type::Copy:
|
||||
serializedPatch["op"].SetString("copy");
|
||||
serializedPatch["from"].CopyFromString(GetSourcePath().ToString());
|
||||
serializedPatch["path"].CopyFromString(GetDestinationPath().ToString());
|
||||
break;
|
||||
case Type::Move:
|
||||
serializedPatch["op"].SetString("move");
|
||||
serializedPatch["from"].CopyFromString(GetSourcePath().ToString());
|
||||
serializedPatch["path"].CopyFromString(GetDestinationPath().ToString());
|
||||
break;
|
||||
case Type::Test:
|
||||
serializedPatch["op"].SetString("test");
|
||||
serializedPatch["path"].CopyFromString(GetDestinationPath().ToString());
|
||||
serializedPatch["value"] = GetValue();
|
||||
break;
|
||||
default:
|
||||
AZ_Assert(false, "PatchOperation::GetDomRepresentation: invalid patch type specified");
|
||||
}
|
||||
return serializedPatch;
|
||||
}
|
||||
|
||||
AZ::Outcome<PatchOperation, AZStd::string> PatchOperation::CreateFromDomRepresentation(Value domValue)
|
||||
{
|
||||
if (!domValue.IsObject())
|
||||
{
|
||||
return AZ::Failure<AZStd::string>("PatchOperation failed to load: PatchOperation must be specified as an Object");
|
||||
}
|
||||
|
||||
auto loadField = [&](const char* field, AZStd::optional<Dom::Type> type = {}) -> AZ::Outcome<Value, AZStd::string>
|
||||
{
|
||||
auto it = domValue.FindMember(field);
|
||||
if (it == domValue.MemberEnd())
|
||||
{
|
||||
return AZ::Failure(AZStd::string::format("PatchOperation failed to load: no \"%s\" specified", field));
|
||||
}
|
||||
|
||||
if (type.has_value() && it->second.GetType() != type)
|
||||
{
|
||||
return AZ::Failure(AZStd::string::format("PatchOperation failed to load: \"%s\" is invalid", field));
|
||||
}
|
||||
|
||||
return AZ::Success(it->second);
|
||||
};
|
||||
|
||||
auto opLoad = loadField("op", Dom::Type::String);
|
||||
if (!opLoad.IsSuccess())
|
||||
{
|
||||
return AZ::Failure(opLoad.TakeError());
|
||||
}
|
||||
AZStd::string_view op = opLoad.GetValue().GetString();
|
||||
if (op == "add")
|
||||
{
|
||||
auto pathLoad = loadField("path", Dom::Type::String);
|
||||
if (!pathLoad.IsSuccess())
|
||||
{
|
||||
return AZ::Failure(pathLoad.TakeError());
|
||||
}
|
||||
auto valueLoad = loadField("value");
|
||||
if (!valueLoad.IsSuccess())
|
||||
{
|
||||
return AZ::Failure(valueLoad.TakeError());
|
||||
}
|
||||
|
||||
return AZ::Success(PatchOperation::AddOperation(Path(pathLoad.GetValue().GetString()), valueLoad.TakeValue()));
|
||||
}
|
||||
else if (op == "remove")
|
||||
{
|
||||
auto pathLoad = loadField("path", Dom::Type::String);
|
||||
if (!pathLoad.IsSuccess())
|
||||
{
|
||||
return AZ::Failure(pathLoad.TakeError());
|
||||
}
|
||||
|
||||
return AZ::Success(PatchOperation::RemoveOperation(Path(pathLoad.GetValue().GetString())));
|
||||
}
|
||||
else if (op == "replace")
|
||||
{
|
||||
auto pathLoad = loadField("path", Dom::Type::String);
|
||||
if (!pathLoad.IsSuccess())
|
||||
{
|
||||
return AZ::Failure(pathLoad.TakeError());
|
||||
}
|
||||
auto valueLoad = loadField("value");
|
||||
if (!valueLoad.IsSuccess())
|
||||
{
|
||||
return AZ::Failure(valueLoad.TakeError());
|
||||
}
|
||||
|
||||
return AZ::Success(PatchOperation::ReplaceOperation(Path(pathLoad.GetValue().GetString()), valueLoad.TakeValue()));
|
||||
}
|
||||
else if (op == "copy")
|
||||
{
|
||||
auto destLoad = loadField("path", Dom::Type::String);
|
||||
if (!destLoad.IsSuccess())
|
||||
{
|
||||
return AZ::Failure(destLoad.TakeError());
|
||||
}
|
||||
auto sourceLoad = loadField("from", Dom::Type::String);
|
||||
if (!sourceLoad.IsSuccess())
|
||||
{
|
||||
return AZ::Failure(sourceLoad.TakeError());
|
||||
}
|
||||
|
||||
return AZ::Success(
|
||||
PatchOperation::CopyOperation(Path(destLoad.GetValue().GetString()), Path(sourceLoad.GetValue().GetString())));
|
||||
}
|
||||
else if (op == "move")
|
||||
{
|
||||
auto destLoad = loadField("path", Dom::Type::String);
|
||||
if (!destLoad.IsSuccess())
|
||||
{
|
||||
return AZ::Failure(destLoad.TakeError());
|
||||
}
|
||||
auto sourceLoad = loadField("from", Dom::Type::String);
|
||||
if (!sourceLoad.IsSuccess())
|
||||
{
|
||||
return AZ::Failure(sourceLoad.TakeError());
|
||||
}
|
||||
|
||||
return AZ::Success(
|
||||
PatchOperation::MoveOperation(Path(destLoad.GetValue().GetString()), Path(sourceLoad.GetValue().GetString())));
|
||||
}
|
||||
else if (op == "test")
|
||||
{
|
||||
auto pathLoad = loadField("path", Dom::Type::String);
|
||||
if (!pathLoad.IsSuccess())
|
||||
{
|
||||
return AZ::Failure(pathLoad.TakeError());
|
||||
}
|
||||
auto valueLoad = loadField("value");
|
||||
if (!valueLoad.IsSuccess())
|
||||
{
|
||||
return AZ::Failure(valueLoad.TakeError());
|
||||
}
|
||||
|
||||
return AZ::Success(PatchOperation::TestOperation(Path(pathLoad.GetValue().GetString()), valueLoad.TakeValue()));
|
||||
}
|
||||
else
|
||||
{
|
||||
return AZ::Failure<AZStd::string>("PatchOperation failed to create DOM representation: invalid \"op\" specified");
|
||||
}
|
||||
}
|
||||
|
||||
AZ::Outcome<AZStd::fixed_vector<PatchOperation, 2>, AZStd::string> PatchOperation::GetInverse(Value stateBeforeApplication) const
|
||||
{
|
||||
switch (m_type)
|
||||
{
|
||||
case Type::Add:
|
||||
{
|
||||
// Add -> Replace (if value already existed in an object) otherwise
|
||||
// Add -> Remove
|
||||
if (m_domPath.Size() > 0 && m_domPath[m_domPath.Size() - 1].IsKey())
|
||||
{
|
||||
const Value* existingValue = stateBeforeApplication.FindChild(m_domPath);
|
||||
if (existingValue != nullptr)
|
||||
{
|
||||
return AZ::Success<InversePatches>({PatchOperation::ReplaceOperation(m_domPath, *existingValue)});
|
||||
}
|
||||
}
|
||||
return AZ::Success<InversePatches>({PatchOperation::RemoveOperation(m_domPath)});
|
||||
}
|
||||
case Type::Remove:
|
||||
{
|
||||
// Remove -> Add
|
||||
const Value* existingValue = stateBeforeApplication.FindChild(m_domPath);
|
||||
if (existingValue == nullptr)
|
||||
{
|
||||
AZStd::string errorMessage = "Unable to invert DOM remove patch, source path not found: ";
|
||||
m_domPath.AppendToString(errorMessage);
|
||||
return AZ::Failure(AZStd::move(errorMessage));
|
||||
}
|
||||
return AZ::Success<InversePatches>({PatchOperation::AddOperation(m_domPath, *existingValue)});
|
||||
}
|
||||
case Type::Replace:
|
||||
{
|
||||
// Replace -> Replace (with old value)
|
||||
const Value* existingValue = stateBeforeApplication.FindChild(m_domPath);
|
||||
if (existingValue == nullptr)
|
||||
{
|
||||
AZStd::string errorMessage = "Unable to invert DOM replace patch, source path not found: ";
|
||||
m_domPath.AppendToString(errorMessage);
|
||||
return AZ::Failure(AZStd::move(errorMessage));
|
||||
}
|
||||
return AZ::Success<InversePatches>({PatchOperation::ReplaceOperation(m_domPath, *existingValue)});
|
||||
}
|
||||
case Type::Copy:
|
||||
{
|
||||
// Copy -> Replace (with old value)
|
||||
const Value* existingValue = stateBeforeApplication.FindChild(m_domPath);
|
||||
if (existingValue == nullptr)
|
||||
{
|
||||
AZStd::string errorMessage = "Unable to invert DOM copy patch, source path not found: ";
|
||||
m_domPath.AppendToString(errorMessage);
|
||||
return AZ::Failure(AZStd::move(errorMessage));
|
||||
}
|
||||
return AZ::Success<InversePatches>({PatchOperation::ReplaceOperation(m_domPath, *existingValue)});
|
||||
}
|
||||
case Type::Move:
|
||||
{
|
||||
const Value* sourceValue = stateBeforeApplication.FindChild(GetSourcePath());
|
||||
if (sourceValue == nullptr)
|
||||
{
|
||||
AZStd::string errorMessage = "Unable to invert DOM copy patch, source path not found: ";
|
||||
m_domPath.AppendToString(errorMessage);
|
||||
return AZ::Failure(AZStd::move(errorMessage));
|
||||
}
|
||||
|
||||
// If there was a value at the destination path, invert with an add / replace
|
||||
const Value* destinationValue = stateBeforeApplication.FindChild(GetDestinationPath());
|
||||
if (destinationValue != nullptr)
|
||||
{
|
||||
InversePatches result({PatchOperation::AddOperation(GetSourcePath(), *sourceValue)});
|
||||
result.push_back(PatchOperation::ReplaceOperation(GetDestinationPath(), *destinationValue));
|
||||
return AZ::Success<InversePatches>({
|
||||
PatchOperation::AddOperation(GetSourcePath(), *sourceValue),
|
||||
PatchOperation::ReplaceOperation(GetDestinationPath(), *destinationValue),
|
||||
});
|
||||
}
|
||||
// Otherwise, just do a move
|
||||
return AZ::Success<InversePatches>({PatchOperation::MoveOperation(GetDestinationPath(), GetSourcePath())});
|
||||
}
|
||||
case Type::Test:
|
||||
{
|
||||
// Test -> Test (no change)
|
||||
// When inverting a sequence of patches, applying them in reverse order should allow the test to continue to succeed
|
||||
return AZ::Success<InversePatches>({*this});
|
||||
}
|
||||
}
|
||||
return AZ::Failure<AZStd::string>("Unable to invert DOM patch, unknown type specified");
|
||||
}
|
||||
|
||||
AZ::Outcome<PatchOperation::PathContext, AZStd::string> PatchOperation::LookupPath(
|
||||
Value& rootElement, const Path& path, ExistenceCheckFlags flags)
|
||||
{
|
||||
const bool verifyFullPath = (flags & ExistenceCheckFlags::VerifyFullPath) != ExistenceCheckFlags::DefaultExistenceCheck;
|
||||
const bool allowEndOfArray = (flags & ExistenceCheckFlags::AllowEndOfArray) != ExistenceCheckFlags::DefaultExistenceCheck;
|
||||
|
||||
Path target = path;
|
||||
if (target.IsEmpty())
|
||||
{
|
||||
Value wrapper(Dom::Type::Array);
|
||||
wrapper.ArrayPushBack(rootElement);
|
||||
return AZ::Success<PathContext>({ wrapper, PathEntry(0) });
|
||||
}
|
||||
|
||||
if (verifyFullPath || !allowEndOfArray)
|
||||
{
|
||||
for (size_t i = 0; i < path.Size(); ++i)
|
||||
{
|
||||
const PathEntry& entry = path[i];
|
||||
if (entry.IsEndOfArray() && (!allowEndOfArray || i != path.Size() - 1))
|
||||
{
|
||||
return AZ::Failure<AZStd::string>("Append to array index (\"-\") specified for path that must already exist");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
PathEntry destinationIndex = target[target.Size() - 1];
|
||||
target.Pop();
|
||||
|
||||
Value* targetValue = rootElement.FindMutableChild(target);
|
||||
if (targetValue == nullptr)
|
||||
{
|
||||
AZStd::string errorMessage = "Path not found: ";
|
||||
target.AppendToString(errorMessage);
|
||||
return AZ::Failure(AZStd::move(errorMessage));
|
||||
}
|
||||
|
||||
if (destinationIndex.IsIndex() || destinationIndex.IsEndOfArray())
|
||||
{
|
||||
if (!targetValue->IsArray() && !targetValue->IsNode())
|
||||
{
|
||||
return AZ::Failure<AZStd::string>("Array index specified for a value that is not an array or node");
|
||||
}
|
||||
|
||||
if (destinationIndex.IsIndex() && destinationIndex.GetIndex() >= targetValue->ArraySize())
|
||||
{
|
||||
return AZ::Failure<AZStd::string>("Array index out bounds");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!targetValue->IsObject() && !targetValue->IsNode())
|
||||
{
|
||||
return AZ::Failure<AZStd::string>("Key specified for a value that is not an object or node");
|
||||
}
|
||||
|
||||
if (verifyFullPath)
|
||||
{
|
||||
if (auto it = targetValue->FindMember(destinationIndex.GetKey()); it == targetValue->MemberEnd())
|
||||
{
|
||||
return AZ::Failure<AZStd::string>("Key not found in container");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return AZ::Success<PathContext>({ *targetValue, AZStd::move(destinationIndex) });
|
||||
}
|
||||
|
||||
PatchOperation::PatchOutcome PatchOperation::ApplyAdd(Value& rootElement) const
|
||||
{
|
||||
auto pathLookup = LookupPath(rootElement, m_domPath, ExistenceCheckFlags::AllowEndOfArray);
|
||||
if (!pathLookup.IsSuccess())
|
||||
{
|
||||
return AZ::Failure(pathLookup.TakeError());
|
||||
}
|
||||
const PathContext& context = pathLookup.GetValue();
|
||||
const PathEntry& destinationIndex = context.m_key;
|
||||
Value& targetValue = context.m_value;
|
||||
|
||||
if (destinationIndex.IsIndex() || destinationIndex.IsEndOfArray())
|
||||
{
|
||||
if (destinationIndex.IsEndOfArray())
|
||||
{
|
||||
targetValue.ArrayPushBack(GetValue());
|
||||
}
|
||||
else
|
||||
{
|
||||
const size_t index = destinationIndex.GetIndex();
|
||||
auto& arrayToChange = targetValue.GetMutableArray();
|
||||
arrayToChange.insert(arrayToChange.begin() + index, GetValue());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
targetValue[destinationIndex] = GetValue();
|
||||
}
|
||||
return AZ::Success();
|
||||
}
|
||||
|
||||
PatchOperation::PatchOutcome PatchOperation::ApplyRemove(Value& rootElement) const
|
||||
{
|
||||
auto pathLookup = LookupPath(rootElement, m_domPath, ExistenceCheckFlags::VerifyFullPath | ExistenceCheckFlags::AllowEndOfArray);
|
||||
if (!pathLookup.IsSuccess())
|
||||
{
|
||||
return AZ::Failure(pathLookup.TakeError());
|
||||
}
|
||||
const PathContext& context = pathLookup.GetValue();
|
||||
const PathEntry& destinationIndex = context.m_key;
|
||||
Value& targetValue = context.m_value;
|
||||
|
||||
if (destinationIndex.IsIndex() || destinationIndex.IsEndOfArray())
|
||||
{
|
||||
size_t index = destinationIndex.IsEndOfArray() ? targetValue.ArraySize() - 1 : destinationIndex.GetIndex();
|
||||
targetValue.ArrayErase(targetValue.MutableArrayBegin() + index);
|
||||
}
|
||||
else
|
||||
{
|
||||
auto it = targetValue.FindMutableMember(destinationIndex.GetKey());
|
||||
targetValue.EraseMember(it);
|
||||
}
|
||||
return AZ::Success();
|
||||
}
|
||||
|
||||
PatchOperation::PatchOutcome PatchOperation::ApplyReplace(Value& rootElement) const
|
||||
{
|
||||
auto pathLookup = LookupPath(rootElement, m_domPath, ExistenceCheckFlags::VerifyFullPath);
|
||||
if (!pathLookup.IsSuccess())
|
||||
{
|
||||
return AZ::Failure(pathLookup.TakeError());
|
||||
}
|
||||
|
||||
rootElement[m_domPath] = GetValue();
|
||||
return AZ::Success();
|
||||
}
|
||||
|
||||
PatchOperation::PatchOutcome PatchOperation::ApplyCopy(Value& rootElement) const
|
||||
{
|
||||
auto sourceLookup = LookupPath(rootElement, GetSourcePath(), ExistenceCheckFlags::VerifyFullPath);
|
||||
if (!sourceLookup.IsSuccess())
|
||||
{
|
||||
return AZ::Failure(sourceLookup.TakeError());
|
||||
}
|
||||
|
||||
auto destLookup = LookupPath(rootElement, m_domPath, ExistenceCheckFlags::AllowEndOfArray);
|
||||
if (!destLookup.IsSuccess())
|
||||
{
|
||||
return AZ::Failure(destLookup.TakeError());
|
||||
}
|
||||
|
||||
rootElement[m_domPath] = rootElement[GetSourcePath()];
|
||||
return AZ::Success();
|
||||
}
|
||||
|
||||
PatchOperation::PatchOutcome PatchOperation::ApplyMove(Value& rootElement) const
|
||||
{
|
||||
auto sourceLookup = LookupPath(rootElement, GetSourcePath(), ExistenceCheckFlags::VerifyFullPath);
|
||||
if (!sourceLookup.IsSuccess())
|
||||
{
|
||||
return AZ::Failure(sourceLookup.TakeError());
|
||||
}
|
||||
|
||||
auto destLookup = LookupPath(rootElement, m_domPath, ExistenceCheckFlags::AllowEndOfArray);
|
||||
if (!destLookup.IsSuccess())
|
||||
{
|
||||
return AZ::Failure(destLookup.TakeError());
|
||||
}
|
||||
|
||||
Value valueToMove = rootElement[GetSourcePath()];
|
||||
const PathContext& sourceContext = sourceLookup.GetValue();
|
||||
if (sourceContext.m_key.IsEndOfArray())
|
||||
{
|
||||
sourceContext.m_value.ArrayPopBack();
|
||||
}
|
||||
else if (sourceContext.m_key.IsIndex())
|
||||
{
|
||||
sourceContext.m_value.ArrayErase(sourceContext.m_value.MutableArrayBegin() + sourceContext.m_key.GetIndex());
|
||||
}
|
||||
else
|
||||
{
|
||||
sourceContext.m_value.EraseMember(sourceContext.m_key.GetKey());
|
||||
}
|
||||
|
||||
rootElement[m_domPath] = AZStd::move(valueToMove);
|
||||
return AZ::Success();
|
||||
}
|
||||
|
||||
PatchOperation::PatchOutcome PatchOperation::ApplyTest(Value& rootElement) const
|
||||
{
|
||||
auto pathLookup = LookupPath(rootElement, m_domPath, ExistenceCheckFlags::VerifyFullPath);
|
||||
if (!pathLookup.IsSuccess())
|
||||
{
|
||||
return AZ::Failure(pathLookup.TakeError());
|
||||
}
|
||||
|
||||
if (!Utils::DeepCompareIsEqual(rootElement[m_domPath], GetValue()))
|
||||
{
|
||||
return AZ::Failure<AZStd::string>("Test failed, values don't match");
|
||||
}
|
||||
|
||||
return AZ::Success();
|
||||
}
|
||||
|
||||
namespace PatchApplicationStrategy
|
||||
{
|
||||
void HaltOnFailure(PatchApplicationState& state)
|
||||
{
|
||||
if (!state.m_outcome.IsSuccess())
|
||||
{
|
||||
state.m_shouldContinue = false;
|
||||
}
|
||||
}
|
||||
|
||||
void IgnoreFailureAndContinue([[maybe_unused]] PatchApplicationState& state)
|
||||
{
|
||||
}
|
||||
} // namespace PatchApplicationStrategy
|
||||
|
||||
Patch::Patch(AZStd::initializer_list<PatchOperation> init)
|
||||
: m_operations(init)
|
||||
{
|
||||
}
|
||||
|
||||
bool Patch::operator==(const Patch& rhs) const
|
||||
{
|
||||
if (m_operations.size() != rhs.m_operations.size())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < m_operations.size(); ++i)
|
||||
{
|
||||
if (m_operations[i] != rhs.m_operations[i])
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Patch::operator!=(const Patch& rhs) const
|
||||
{
|
||||
return !operator==(rhs);
|
||||
}
|
||||
|
||||
const Patch::OperationsContainer& Patch::GetOperations() const
|
||||
{
|
||||
return m_operations;
|
||||
}
|
||||
|
||||
void Patch::PushBack(PatchOperation op)
|
||||
{
|
||||
m_operations.push_back(AZStd::move(op));
|
||||
}
|
||||
|
||||
void Patch::PushFront(PatchOperation op)
|
||||
{
|
||||
m_operations.insert(m_operations.begin(), AZStd::move(op));
|
||||
}
|
||||
|
||||
void Patch::Pop()
|
||||
{
|
||||
m_operations.pop_back();
|
||||
}
|
||||
|
||||
void Patch::Clear()
|
||||
{
|
||||
m_operations.clear();
|
||||
}
|
||||
|
||||
const PatchOperation& Patch::At(size_t index) const
|
||||
{
|
||||
return m_operations[index];
|
||||
}
|
||||
|
||||
size_t Patch::Size() const
|
||||
{
|
||||
return m_operations.size();
|
||||
}
|
||||
|
||||
PatchOperation& Patch::operator[](size_t index)
|
||||
{
|
||||
return m_operations[index];
|
||||
}
|
||||
|
||||
const PatchOperation& Patch::operator[](size_t index) const
|
||||
{
|
||||
return m_operations[index];
|
||||
}
|
||||
|
||||
auto Patch::begin() -> OperationsContainer::iterator
|
||||
{
|
||||
return m_operations.begin();
|
||||
}
|
||||
|
||||
auto Patch::end() -> OperationsContainer::iterator
|
||||
{
|
||||
return m_operations.end();
|
||||
}
|
||||
|
||||
auto Patch::begin() const -> OperationsContainer::const_iterator
|
||||
{
|
||||
return m_operations.begin();
|
||||
}
|
||||
|
||||
auto Patch::end() const -> OperationsContainer::const_iterator
|
||||
{
|
||||
return m_operations.end();
|
||||
}
|
||||
|
||||
auto Patch::cbegin() const -> OperationsContainer::const_iterator
|
||||
{
|
||||
return m_operations.begin();
|
||||
}
|
||||
|
||||
auto Patch::cend() const -> OperationsContainer::const_iterator
|
||||
{
|
||||
return m_operations.end();
|
||||
}
|
||||
|
||||
size_t Patch::size() const
|
||||
{
|
||||
return m_operations.size();
|
||||
}
|
||||
|
||||
AZ::Outcome<Value, AZStd::string> Patch::Apply(Value rootElement, StrategyFunctor strategy) const
|
||||
{
|
||||
auto result = ApplyInPlace(rootElement, strategy);
|
||||
if (!result.IsSuccess())
|
||||
{
|
||||
return AZ::Failure(result.TakeError());
|
||||
}
|
||||
return AZ::Success(AZStd::move(rootElement));
|
||||
}
|
||||
|
||||
AZ::Outcome<void, AZStd::string> Patch::ApplyInPlace(Value& rootElement, StrategyFunctor strategy) const
|
||||
{
|
||||
PatchApplicationState state;
|
||||
state.m_currentState = &rootElement;
|
||||
state.m_patch = this;
|
||||
|
||||
for (const PatchOperation& operation : m_operations)
|
||||
{
|
||||
state.m_lastOperation = &operation;
|
||||
state.m_outcome = operation.ApplyInPlace(rootElement);
|
||||
strategy(state);
|
||||
if (!state.m_shouldContinue)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
return state.m_outcome;
|
||||
}
|
||||
|
||||
Value Patch::GetDomRepresentation() const
|
||||
{
|
||||
Value domValue(Dom::Type::Array);
|
||||
for (const PatchOperation& operation : m_operations)
|
||||
{
|
||||
domValue.ArrayPushBack(operation.GetDomRepresentation());
|
||||
}
|
||||
return domValue;
|
||||
}
|
||||
|
||||
AZ::Outcome<Patch, AZStd::string> Patch::CreateFromDomRepresentation(Value domValue)
|
||||
{
|
||||
if (!domValue.IsArray())
|
||||
{
|
||||
return AZ::Failure<AZStd::string>("Patch must be an array");
|
||||
}
|
||||
|
||||
Patch patch;
|
||||
for (auto it = domValue.ArrayBegin(); it != domValue.ArrayEnd(); ++it)
|
||||
{
|
||||
auto operationLoadResult = PatchOperation::CreateFromDomRepresentation(*it);
|
||||
if (!operationLoadResult.IsSuccess())
|
||||
{
|
||||
return AZ::Failure(operationLoadResult.TakeError());
|
||||
}
|
||||
patch.PushBack(operationLoadResult.TakeValue());
|
||||
}
|
||||
return AZ::Success(AZStd::move(patch));
|
||||
}
|
||||
|
||||
PatchOperation PatchOperation::AddOperation(Path destinationPath, Value value)
|
||||
{
|
||||
return PatchOperation(AZStd::move(destinationPath), PatchOperation::Type::Add, AZStd::move(value));
|
||||
}
|
||||
|
||||
PatchOperation PatchOperation::RemoveOperation(Path pathToRemove)
|
||||
{
|
||||
return PatchOperation(AZStd::move(pathToRemove), PatchOperation::Type::Remove);
|
||||
}
|
||||
|
||||
PatchOperation PatchOperation::ReplaceOperation(Path destinationPath, Value value)
|
||||
{
|
||||
return PatchOperation(AZStd::move(destinationPath), PatchOperation::Type::Replace, AZStd::move(value));
|
||||
}
|
||||
|
||||
PatchOperation PatchOperation::CopyOperation(Path destinationPath, Path sourcePath)
|
||||
{
|
||||
return PatchOperation(AZStd::move(destinationPath), PatchOperation::Type::Copy, AZStd::move(sourcePath));
|
||||
}
|
||||
|
||||
PatchOperation PatchOperation::MoveOperation(Path destinationPath, Path sourcePath)
|
||||
{
|
||||
return PatchOperation(AZStd::move(destinationPath), PatchOperation::Type::Move, AZStd::move(sourcePath));
|
||||
}
|
||||
|
||||
PatchOperation PatchOperation::TestOperation(Path testPath, Value value)
|
||||
{
|
||||
return PatchOperation(AZStd::move(testPath), PatchOperation::Type::Test, AZStd::move(value));
|
||||
}
|
||||
} // namespace AZ::Dom
|
||||
@ -0,0 +1,186 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project.
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <AzCore/DOM/DomPath.h>
|
||||
#include <AzCore/DOM/DomValue.h>
|
||||
#include <AzCore/std/containers/deque.h>
|
||||
|
||||
namespace AZ::Dom
|
||||
{
|
||||
//! A patch operation that represents an atomic operation for mutating or validating a Value.
|
||||
//! PatchOperations can be created with helper methods in Patch. /see Patch
|
||||
class PatchOperation final
|
||||
{
|
||||
public:
|
||||
using PatchOutcome = AZ::Outcome<void, AZStd::string>;
|
||||
|
||||
//! The operation to perform.
|
||||
enum class Type
|
||||
{
|
||||
Add, //!< Inserts or replaces the value at DestinationPath with Value
|
||||
Remove, //!< Removes the entry at DestinationPath
|
||||
Replace, //!< Replaces the value at DestinationPath with Value
|
||||
Copy, //!< Copies the contents of SourcePath to DestinationPath
|
||||
Move, //!< Moves the contents of SourcePath to DestinationPath
|
||||
Test //!< Ensures the contents of DestinationPath match Value or fails, performs no mutations
|
||||
};
|
||||
|
||||
PatchOperation() = default;
|
||||
PatchOperation(const PatchOperation&) = default;
|
||||
PatchOperation(PatchOperation&&) = default;
|
||||
|
||||
PatchOperation(Path destionationPath, Type type, Value value);
|
||||
PatchOperation(Path destionationPath, Type type, Path sourcePath);
|
||||
PatchOperation(Path path, Type type);
|
||||
|
||||
static PatchOperation AddOperation(Path destinationPath, Value value);
|
||||
static PatchOperation RemoveOperation(Path pathToRemove);
|
||||
static PatchOperation ReplaceOperation(Path destinationPath, Value value);
|
||||
static PatchOperation CopyOperation(Path destinationPath, Path sourcePath);
|
||||
static PatchOperation MoveOperation(Path destinationPath, Path sourcePath);
|
||||
static PatchOperation TestOperation(Path testPath, Value value);
|
||||
|
||||
PatchOperation& operator=(const PatchOperation&) = default;
|
||||
PatchOperation& operator=(PatchOperation&&) = default;
|
||||
|
||||
bool operator==(const PatchOperation& rhs) const;
|
||||
bool operator!=(const PatchOperation& rhs) const;
|
||||
|
||||
Type GetType() const;
|
||||
void SetType(Type type);
|
||||
|
||||
const Path& GetDestinationPath() const;
|
||||
void SetDestinationPath(Path path);
|
||||
|
||||
const Value& GetValue() const;
|
||||
void SetValue(Value value);
|
||||
|
||||
const Path& GetSourcePath() const;
|
||||
void SetSourcePath(Path path);
|
||||
|
||||
AZ::Outcome<Value, AZStd::string> Apply(Value rootElement) const;
|
||||
PatchOutcome ApplyInPlace(Value& rootElement) const;
|
||||
|
||||
Value GetDomRepresentation() const;
|
||||
static AZ::Outcome<PatchOperation, AZStd::string> CreateFromDomRepresentation(Value domValue);
|
||||
|
||||
using InversePatches = AZStd::fixed_vector<PatchOperation, 2>;
|
||||
AZ::Outcome<AZStd::fixed_vector<PatchOperation, 2>, AZStd::string> GetInverse(Value stateBeforeApplication) const;
|
||||
|
||||
enum class ExistenceCheckFlags : AZ::u8
|
||||
{
|
||||
DefaultExistenceCheck = 0x0,
|
||||
VerifyFullPath = 0x1,
|
||||
AllowEndOfArray = 0x2,
|
||||
};
|
||||
|
||||
private:
|
||||
struct PathContext
|
||||
{
|
||||
Value& m_value;
|
||||
PathEntry m_key;
|
||||
};
|
||||
|
||||
static AZ::Outcome<PathContext, AZStd::string> LookupPath(
|
||||
Value& rootElement, const Path& path, ExistenceCheckFlags existenceCheckFlags = ExistenceCheckFlags::DefaultExistenceCheck);
|
||||
|
||||
PatchOutcome ApplyAdd(Value& rootElement) const;
|
||||
PatchOutcome ApplyRemove(Value& rootElement) const;
|
||||
PatchOutcome ApplyReplace(Value& rootElement) const;
|
||||
PatchOutcome ApplyCopy(Value& rootElement) const;
|
||||
PatchOutcome ApplyMove(Value& rootElement) const;
|
||||
PatchOutcome ApplyTest(Value& rootElement) const;
|
||||
|
||||
AZStd::variant<AZStd::monostate, Value, Path> m_value;
|
||||
Path m_domPath;
|
||||
Type m_type;
|
||||
};
|
||||
|
||||
AZ_DEFINE_ENUM_BITWISE_OPERATORS(PatchOperation::ExistenceCheckFlags);
|
||||
|
||||
class Patch;
|
||||
|
||||
//! The current state of a Patch application operation.
|
||||
struct PatchApplicationState
|
||||
{
|
||||
//! The outcome of the last operation, may be overridden to produce a different failure outcome.
|
||||
PatchOperation::PatchOutcome m_outcome;
|
||||
//! The patch being applied.
|
||||
const Patch* m_patch = nullptr;
|
||||
//! The last operation attempted.
|
||||
const PatchOperation* m_lastOperation = nullptr;
|
||||
//! The current state of the value being patched, will be returned if the patch operation succeeds.
|
||||
Value* m_currentState = nullptr;
|
||||
//! If set to false, the patch operation should halt.
|
||||
bool m_shouldContinue = true;
|
||||
};
|
||||
|
||||
namespace PatchApplicationStrategy
|
||||
{
|
||||
//! The default patching strategy. Applies all operations in a patch, but halts if any one operation fails.
|
||||
void HaltOnFailure(PatchApplicationState& state);
|
||||
//! Patching strategy that attemps to apply all operations in a patch, but ignores operation failures and continues.
|
||||
void IgnoreFailureAndContinue(PatchApplicationState& state);
|
||||
} // namespace PatchApplicationStrategy
|
||||
|
||||
//! A set of operations that can be applied to a Value to produce a new Value.
|
||||
//! \see PatchOperation
|
||||
class Patch final
|
||||
{
|
||||
public:
|
||||
using StrategyFunctor = AZStd::function<void(PatchApplicationState&)>;
|
||||
using OperationsContainer = AZStd::deque<PatchOperation>;
|
||||
|
||||
Patch() = default;
|
||||
Patch(const Patch&) = default;
|
||||
Patch(Patch&&) = default;
|
||||
Patch(AZStd::initializer_list<PatchOperation> init);
|
||||
|
||||
template<class InputIterator>
|
||||
Patch(InputIterator first, InputIterator last)
|
||||
: m_operations(first, last)
|
||||
{
|
||||
}
|
||||
|
||||
Patch& operator=(const Patch&) = default;
|
||||
Patch& operator=(Patch&&) = default;
|
||||
|
||||
bool operator==(const Patch& rhs) const;
|
||||
bool operator!=(const Patch& rhs) const;
|
||||
|
||||
const OperationsContainer& GetOperations() const;
|
||||
void PushBack(PatchOperation op);
|
||||
void PushFront(PatchOperation op);
|
||||
void Pop();
|
||||
void Clear();
|
||||
const PatchOperation& At(size_t index) const;
|
||||
size_t Size() const;
|
||||
|
||||
PatchOperation& operator[](size_t index);
|
||||
const PatchOperation& operator[](size_t index) const;
|
||||
|
||||
OperationsContainer::iterator begin();
|
||||
OperationsContainer::iterator end();
|
||||
OperationsContainer::const_iterator begin() const;
|
||||
OperationsContainer::const_iterator end() const;
|
||||
OperationsContainer::const_iterator cbegin() const;
|
||||
OperationsContainer::const_iterator cend() const;
|
||||
size_t size() const;
|
||||
|
||||
AZ::Outcome<Value, AZStd::string> Apply(Value rootElement, StrategyFunctor strategy = PatchApplicationStrategy::HaltOnFailure) const;
|
||||
AZ::Outcome<void, AZStd::string> ApplyInPlace(Value& rootElement, StrategyFunctor strategy = PatchApplicationStrategy::HaltOnFailure) const;
|
||||
|
||||
Value GetDomRepresentation() const;
|
||||
static AZ::Outcome<Patch, AZStd::string> CreateFromDomRepresentation(Value domValue);
|
||||
|
||||
private:
|
||||
OperationsContainer m_operations;
|
||||
};
|
||||
} // namespace AZ::Dom
|
||||
@ -0,0 +1,180 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project.
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include <AzCore/DOM/DomPatch.h>
|
||||
#include <AzCore/DOM/DomUtils.h>
|
||||
#include <AzCore/DOM/DomValue.h>
|
||||
#include <AzCore/DOM/DomComparison.h>
|
||||
#include <AzCore/Name/NameDictionary.h>
|
||||
#include <AzCore/UnitTest/TestTypes.h>
|
||||
#include <Tests/DOM/DomFixtures.h>
|
||||
|
||||
namespace AZ::Dom::Benchmark
|
||||
{
|
||||
class DomPatchBenchmark : public Tests::DomBenchmarkFixture
|
||||
{
|
||||
public:
|
||||
void TearDownHarness() override
|
||||
{
|
||||
m_before = {};
|
||||
m_after = {};
|
||||
Tests::DomBenchmarkFixture::TearDownHarness();
|
||||
}
|
||||
|
||||
void SimpleReplace(benchmark::State& state, bool deepCopy, bool apply)
|
||||
{
|
||||
m_before = GenerateDomBenchmarkPayload(state.range(0), state.range(1));
|
||||
m_after = deepCopy ? Utils::DeepCopy(m_before) : m_before;
|
||||
m_after["entries"]["Key0"] = Value("replacement string", true);
|
||||
|
||||
RunBenchmarkInternal(state, apply);
|
||||
}
|
||||
|
||||
void TopLevelReplace(benchmark::State& state, bool apply)
|
||||
{
|
||||
m_before = GenerateDomBenchmarkPayload(state.range(0), state.range(1));
|
||||
m_after = Value(Type::Object);
|
||||
m_after["UnrelatedKey"] = Value(42);
|
||||
|
||||
RunBenchmarkInternal(state, apply);
|
||||
}
|
||||
|
||||
void KeyRemove(benchmark::State& state, bool deepCopy, bool apply)
|
||||
{
|
||||
m_before = GenerateDomBenchmarkPayload(state.range(0), state.range(1));
|
||||
m_after = deepCopy ? Utils::DeepCopy(m_before) : m_before;
|
||||
m_after["entries"].RemoveMember("Key1");
|
||||
|
||||
RunBenchmarkInternal(state, apply);
|
||||
}
|
||||
|
||||
void ArrayAppend(benchmark::State& state, bool deepCopy, bool apply)
|
||||
{
|
||||
m_before = GenerateDomBenchmarkPayload(state.range(0), state.range(1));
|
||||
m_after = deepCopy ? Utils::DeepCopy(m_before) : m_before;
|
||||
m_after["entries"]["Key2"].ArrayPushBack(Value(0));
|
||||
|
||||
RunBenchmarkInternal(state, apply);
|
||||
}
|
||||
|
||||
void ArrayPrepend(benchmark::State& state, bool deepCopy, bool apply)
|
||||
{
|
||||
m_before = GenerateDomBenchmarkPayload(state.range(0), state.range(1));
|
||||
m_after = deepCopy ? Utils::DeepCopy(m_before) : m_before;
|
||||
auto& arr = m_after["entries"]["Key2"].GetMutableArray();
|
||||
arr.insert(arr.begin(), Value(42));
|
||||
|
||||
RunBenchmarkInternal(state, apply);
|
||||
}
|
||||
|
||||
private:
|
||||
void RunBenchmarkInternal(benchmark::State& state, bool apply)
|
||||
{
|
||||
if (apply)
|
||||
{
|
||||
auto patchInfo = GenerateHierarchicalDeltaPatch(m_before, m_after);
|
||||
for (auto _ : state)
|
||||
{
|
||||
auto patchResult = patchInfo.m_forwardPatches.Apply(m_before);
|
||||
benchmark::DoNotOptimize(patchResult);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (auto _ : state)
|
||||
{
|
||||
auto patchInfo = GenerateHierarchicalDeltaPatch(m_before, m_after);
|
||||
benchmark::DoNotOptimize(patchInfo);
|
||||
}
|
||||
}
|
||||
|
||||
state.SetItemsProcessed(state.iterations());
|
||||
}
|
||||
|
||||
Value m_before;
|
||||
Value m_after;
|
||||
};
|
||||
|
||||
BENCHMARK_DEFINE_F(DomPatchBenchmark, AzDomPatch_Generate_SimpleReplace_ShallowCopy)(benchmark::State& state)
|
||||
{
|
||||
SimpleReplace(state, false, false);
|
||||
}
|
||||
DOM_REGISTER_SERIALIZATION_BENCHMARK_MS(DomPatchBenchmark, AzDomPatch_Generate_SimpleReplace_ShallowCopy)
|
||||
|
||||
BENCHMARK_DEFINE_F(DomPatchBenchmark, AzDomPatch_Generate_SimpleReplace_DeepCopy)(benchmark::State& state)
|
||||
{
|
||||
SimpleReplace(state, true, false);
|
||||
}
|
||||
DOM_REGISTER_SERIALIZATION_BENCHMARK_MS(DomPatchBenchmark, AzDomPatch_Generate_SimpleReplace_DeepCopy)
|
||||
|
||||
BENCHMARK_DEFINE_F(DomPatchBenchmark, AzDomPatch_Generate_TopLevelReplace)(benchmark::State& state)
|
||||
{
|
||||
TopLevelReplace(state, false);
|
||||
}
|
||||
DOM_REGISTER_SERIALIZATION_BENCHMARK_MS(DomPatchBenchmark, AzDomPatch_Generate_TopLevelReplace)
|
||||
|
||||
BENCHMARK_DEFINE_F(DomPatchBenchmark, AzDomPatch_Generate_KeyRemove_ShallowCopy)(benchmark::State& state)
|
||||
{
|
||||
KeyRemove(state, false, false);
|
||||
}
|
||||
DOM_REGISTER_SERIALIZATION_BENCHMARK_MS(DomPatchBenchmark, AzDomPatch_Generate_KeyRemove_ShallowCopy)
|
||||
|
||||
BENCHMARK_DEFINE_F(DomPatchBenchmark, AzDomPatch_Generate_KeyRemove_DeepCopy)(benchmark::State& state)
|
||||
{
|
||||
KeyRemove(state, true, false);
|
||||
}
|
||||
DOM_REGISTER_SERIALIZATION_BENCHMARK_MS(DomPatchBenchmark, AzDomPatch_Generate_KeyRemove_DeepCopy)
|
||||
|
||||
BENCHMARK_DEFINE_F(DomPatchBenchmark, AzDomPatch_Generate_ArrayAppend_ShallowCopy)(benchmark::State& state)
|
||||
{
|
||||
ArrayAppend(state, false, false);
|
||||
}
|
||||
DOM_REGISTER_SERIALIZATION_BENCHMARK_MS(DomPatchBenchmark, AzDomPatch_Generate_ArrayAppend_ShallowCopy)
|
||||
|
||||
BENCHMARK_DEFINE_F(DomPatchBenchmark, AzDomPatch_Generate_ArrayAppend_DeepCopy)(benchmark::State& state)
|
||||
{
|
||||
ArrayAppend(state, true, false);
|
||||
}
|
||||
DOM_REGISTER_SERIALIZATION_BENCHMARK_MS(DomPatchBenchmark, AzDomPatch_Generate_ArrayAppend_DeepCopy)
|
||||
|
||||
BENCHMARK_DEFINE_F(DomPatchBenchmark, AzDomPatch_Generate_ArrayPrepend)(benchmark::State& state)
|
||||
{
|
||||
ArrayPrepend(state, true, false);
|
||||
}
|
||||
DOM_REGISTER_SERIALIZATION_BENCHMARK_MS(DomPatchBenchmark, AzDomPatch_Generate_ArrayPrepend)
|
||||
|
||||
BENCHMARK_DEFINE_F(DomPatchBenchmark, AzDomPatch_Apply_SimpleReplace)(benchmark::State& state)
|
||||
{
|
||||
SimpleReplace(state, true, true);
|
||||
}
|
||||
DOM_REGISTER_SERIALIZATION_BENCHMARK_MS(DomPatchBenchmark, AzDomPatch_Apply_SimpleReplace)
|
||||
|
||||
BENCHMARK_DEFINE_F(DomPatchBenchmark, AzDomPatch_Apply_TopLevelReplace)(benchmark::State& state)
|
||||
{
|
||||
TopLevelReplace(state, true);
|
||||
}
|
||||
DOM_REGISTER_SERIALIZATION_BENCHMARK_MS(DomPatchBenchmark, AzDomPatch_Apply_TopLevelReplace)
|
||||
|
||||
BENCHMARK_DEFINE_F(DomPatchBenchmark, AzDomPatch_Apply_KeyRemove)(benchmark::State& state)
|
||||
{
|
||||
KeyRemove(state, true, true);
|
||||
}
|
||||
DOM_REGISTER_SERIALIZATION_BENCHMARK_MS(DomPatchBenchmark, AzDomPatch_Apply_KeyRemove)
|
||||
|
||||
BENCHMARK_DEFINE_F(DomPatchBenchmark, AzDomPatch_Apply_ArrayAppend)(benchmark::State& state)
|
||||
{
|
||||
ArrayAppend(state, true, true);
|
||||
}
|
||||
DOM_REGISTER_SERIALIZATION_BENCHMARK_MS(DomPatchBenchmark, AzDomPatch_Apply_ArrayAppend)
|
||||
|
||||
BENCHMARK_DEFINE_F(DomPatchBenchmark, AzDomPatch_Apply_ArrayPrepend)(benchmark::State& state)
|
||||
{
|
||||
ArrayPrepend(state, true, true);
|
||||
}
|
||||
DOM_REGISTER_SERIALIZATION_BENCHMARK_MS(DomPatchBenchmark, AzDomPatch_Apply_ArrayPrepend)
|
||||
} // namespace AZ::Dom::Benchmark
|
||||
@ -0,0 +1,563 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project.
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include <AzCore/DOM/DomPatch.h>
|
||||
#include <AzCore/DOM/DomComparison.h>
|
||||
#include <Tests/DOM/DomFixtures.h>
|
||||
|
||||
namespace AZ::Dom::Tests
|
||||
{
|
||||
class DomPatchTests : public DomTestFixture
|
||||
{
|
||||
public:
|
||||
void SetUp() override
|
||||
{
|
||||
DomTestFixture::SetUp();
|
||||
|
||||
m_dataset = Value(Type::Object);
|
||||
m_dataset["arr"].SetArray();
|
||||
|
||||
m_dataset["node"].SetNode("SomeNode");
|
||||
m_dataset["node"]["int"] = 5;
|
||||
m_dataset["node"]["null"] = Value();
|
||||
|
||||
for (int i = 0; i < 5; ++i)
|
||||
{
|
||||
m_dataset["arr"].ArrayPushBack(Value(i));
|
||||
m_dataset["node"].ArrayPushBack(Value(i * 2));
|
||||
}
|
||||
|
||||
m_dataset["obj"].SetObject();
|
||||
m_dataset["obj"]["foo"] = true;
|
||||
m_dataset["obj"]["bar"] = false;
|
||||
|
||||
m_deltaDataset = m_dataset;
|
||||
}
|
||||
|
||||
void TearDown() override
|
||||
{
|
||||
m_dataset = m_deltaDataset = Value();
|
||||
|
||||
DomTestFixture::TearDown();
|
||||
}
|
||||
|
||||
PatchUndoRedoInfo GenerateAndVerifyDelta()
|
||||
{
|
||||
PatchUndoRedoInfo info = GenerateHierarchicalDeltaPatch(m_dataset, m_deltaDataset);
|
||||
|
||||
auto result = info.m_forwardPatches.Apply(m_dataset);
|
||||
EXPECT_TRUE(result.IsSuccess());
|
||||
EXPECT_TRUE(Utils::DeepCompareIsEqual(result.GetValue(), m_deltaDataset));
|
||||
|
||||
result = info.m_inversePatches.Apply(result.GetValue());
|
||||
EXPECT_TRUE(result.IsSuccess());
|
||||
EXPECT_TRUE(Utils::DeepCompareIsEqual(result.GetValue(), m_dataset));
|
||||
|
||||
// Verify serialization of the patches
|
||||
auto VerifySerialization = [](const Patch& patch)
|
||||
{
|
||||
Value serializedPatch = patch.GetDomRepresentation();
|
||||
auto deserializePatchResult = Patch::CreateFromDomRepresentation(serializedPatch);
|
||||
EXPECT_TRUE(deserializePatchResult.IsSuccess());
|
||||
EXPECT_EQ(deserializePatchResult.GetValue(), patch);
|
||||
};
|
||||
VerifySerialization(info.m_forwardPatches);
|
||||
VerifySerialization(info.m_inversePatches);
|
||||
|
||||
return info;
|
||||
}
|
||||
|
||||
Value m_dataset;
|
||||
Value m_deltaDataset;
|
||||
};
|
||||
|
||||
TEST_F(DomPatchTests, AddOperation_InsertInObject_Succeeds)
|
||||
{
|
||||
Path p("/obj/baz");
|
||||
PatchOperation op = PatchOperation::AddOperation(p, Value(42));
|
||||
auto result = op.Apply(m_dataset);
|
||||
ASSERT_TRUE(result.IsSuccess());
|
||||
EXPECT_EQ(result.GetValue()[p].GetInt64(), 42);
|
||||
}
|
||||
|
||||
TEST_F(DomPatchTests, AddOperation_ReplaceInObject_Succeeds)
|
||||
{
|
||||
Path p("/obj/foo");
|
||||
PatchOperation op = PatchOperation::AddOperation(p, Value(false));
|
||||
auto result = op.Apply(m_dataset);
|
||||
ASSERT_TRUE(result.IsSuccess());
|
||||
EXPECT_EQ(result.GetValue()[p].GetBool(), false);
|
||||
}
|
||||
|
||||
TEST_F(DomPatchTests, AddOperation_InsertObjectKeyInArray_Fails)
|
||||
{
|
||||
Path p("/arr/key");
|
||||
PatchOperation op = PatchOperation::AddOperation(p, Value(999));
|
||||
auto result = op.Apply(m_dataset);
|
||||
ASSERT_FALSE(result.IsSuccess());
|
||||
}
|
||||
|
||||
TEST_F(DomPatchTests, AddOperation_AppendInArray_Succeeds)
|
||||
{
|
||||
Path p("/arr/-");
|
||||
PatchOperation op = PatchOperation::AddOperation(p, Value(42));
|
||||
auto result = op.Apply(m_dataset);
|
||||
ASSERT_TRUE(result.IsSuccess());
|
||||
EXPECT_EQ(result.GetValue()["arr"][5].GetInt64(), 42);
|
||||
}
|
||||
|
||||
TEST_F(DomPatchTests, AddOperation_InsertKeyInNode_Succeeds)
|
||||
{
|
||||
Path p("/node/attr");
|
||||
PatchOperation op = PatchOperation::AddOperation(p, Value(500));
|
||||
auto result = op.Apply(m_dataset);
|
||||
ASSERT_TRUE(result.IsSuccess());
|
||||
EXPECT_EQ(result.GetValue()[p].GetInt64(), 500);
|
||||
}
|
||||
|
||||
TEST_F(DomPatchTests, AddOperation_ReplaceIndexInNode_Succeeds)
|
||||
{
|
||||
Path p("/node/0");
|
||||
PatchOperation op = PatchOperation::AddOperation(p, Value(42));
|
||||
auto result = op.Apply(m_dataset);
|
||||
ASSERT_TRUE(result.IsSuccess());
|
||||
EXPECT_EQ(result.GetValue()[p].GetInt64(), 42);
|
||||
}
|
||||
|
||||
TEST_F(DomPatchTests, AddOperation_AppendInNode_Succeeds)
|
||||
{
|
||||
Path p("/node/-");
|
||||
PatchOperation op = PatchOperation::AddOperation(p, Value(42));
|
||||
auto result = op.Apply(m_dataset);
|
||||
ASSERT_TRUE(result.IsSuccess());
|
||||
EXPECT_EQ(result.GetValue()["node"][5].GetInt64(), 42);
|
||||
}
|
||||
|
||||
TEST_F(DomPatchTests, AddOperation_InvalidPath_Fails)
|
||||
{
|
||||
Path p("/non/existent/path");
|
||||
PatchOperation op = PatchOperation::AddOperation(p, Value(0));
|
||||
auto result = op.Apply(m_dataset);
|
||||
ASSERT_FALSE(result.IsSuccess());
|
||||
}
|
||||
|
||||
TEST_F(DomPatchTests, RemoveOperation_RemoveKeyFromObject_Succeeds)
|
||||
{
|
||||
Path p("/obj/foo");
|
||||
PatchOperation op = PatchOperation::RemoveOperation(p);
|
||||
auto result = op.Apply(m_dataset);
|
||||
ASSERT_TRUE(result.IsSuccess());
|
||||
EXPECT_FALSE(result.GetValue()["obj"].HasMember("foo"));
|
||||
}
|
||||
|
||||
TEST_F(DomPatchTests, RemoveOperation_RemoveIndexFromArray_Succeeds)
|
||||
{
|
||||
Path p("/arr/0");
|
||||
PatchOperation op = PatchOperation::RemoveOperation(p);
|
||||
auto result = op.Apply(m_dataset);
|
||||
ASSERT_TRUE(result.IsSuccess());
|
||||
EXPECT_EQ(result.GetValue()["arr"].ArraySize(), 4);
|
||||
EXPECT_EQ(result.GetValue()["arr"][0].GetInt64(), 1);
|
||||
}
|
||||
|
||||
TEST_F(DomPatchTests, RemoveOperation_PopArray_Succeeds)
|
||||
{
|
||||
Path p("/arr/-");
|
||||
PatchOperation op = PatchOperation::RemoveOperation(p);
|
||||
auto result = op.Apply(m_dataset);
|
||||
EXPECT_EQ(result.GetValue()["arr"].ArraySize(), 4);
|
||||
}
|
||||
|
||||
TEST_F(DomPatchTests, RemoveOperation_RemoveKeyFromNode_Succeeds)
|
||||
{
|
||||
Path p("/node/int");
|
||||
PatchOperation op = PatchOperation::RemoveOperation(p);
|
||||
auto result = op.Apply(m_dataset);
|
||||
ASSERT_TRUE(result.IsSuccess());
|
||||
EXPECT_FALSE(result.GetValue()["node"].HasMember("int"));
|
||||
}
|
||||
|
||||
TEST_F(DomPatchTests, RemoveOperation_RemoveIndexFromNode_Succeeds)
|
||||
{
|
||||
Path p("/node/1");
|
||||
PatchOperation op = PatchOperation::RemoveOperation(p);
|
||||
auto result = op.Apply(m_dataset);
|
||||
ASSERT_TRUE(result.IsSuccess());
|
||||
EXPECT_EQ(result.GetValue()["node"].ArraySize(), 4);
|
||||
EXPECT_EQ(result.GetValue()["node"][1].GetInt64(), 4);
|
||||
}
|
||||
|
||||
TEST_F(DomPatchTests, RemoveOperation_PopIndexFromNode_Succeeds)
|
||||
{
|
||||
Path p("/node/-");
|
||||
PatchOperation op = PatchOperation::RemoveOperation(p);
|
||||
auto result = op.Apply(m_dataset);
|
||||
ASSERT_TRUE(result.IsSuccess());
|
||||
EXPECT_EQ(result.GetValue()["node"].ArraySize(), 4);
|
||||
}
|
||||
|
||||
TEST_F(DomPatchTests, RemoveOperation_RemoveKeyFromArray_Fails)
|
||||
{
|
||||
Path p("/arr/foo");
|
||||
PatchOperation op = PatchOperation::RemoveOperation(p);
|
||||
auto result = op.Apply(m_dataset);
|
||||
ASSERT_FALSE(result.IsSuccess());
|
||||
}
|
||||
|
||||
TEST_F(DomPatchTests, RemoveOperation_InvalidPath_Fails)
|
||||
{
|
||||
Path p("/non/existent/path");
|
||||
PatchOperation op = PatchOperation::RemoveOperation(p);
|
||||
auto result = op.Apply(m_dataset);
|
||||
ASSERT_FALSE(result.IsSuccess());
|
||||
}
|
||||
|
||||
TEST_F(DomPatchTests, ReplaceOperation_InsertInObject_Fails)
|
||||
{
|
||||
Path p("/obj/baz");
|
||||
PatchOperation op = PatchOperation::ReplaceOperation(p, Value(42));
|
||||
auto result = op.Apply(m_dataset);
|
||||
ASSERT_FALSE(result.IsSuccess());
|
||||
}
|
||||
|
||||
TEST_F(DomPatchTests, ReplaceOperation_ReplaceInObject_Succeeds)
|
||||
{
|
||||
Path p("/obj/foo");
|
||||
PatchOperation op = PatchOperation::ReplaceOperation(p, Value(false));
|
||||
auto result = op.Apply(m_dataset);
|
||||
ASSERT_TRUE(result.IsSuccess());
|
||||
EXPECT_EQ(result.GetValue()[p].GetBool(), false);
|
||||
}
|
||||
|
||||
TEST_F(DomPatchTests, ReplaceOperation_InsertObjectKeyInArray_Fails)
|
||||
{
|
||||
Path p("/arr/key");
|
||||
PatchOperation op = PatchOperation::ReplaceOperation(p, Value(999));
|
||||
auto result = op.Apply(m_dataset);
|
||||
ASSERT_FALSE(result.IsSuccess());
|
||||
}
|
||||
|
||||
TEST_F(DomPatchTests, ReplaceOperation_AppendInArray_Fails)
|
||||
{
|
||||
Path p("/arr/-");
|
||||
PatchOperation op = PatchOperation::ReplaceOperation(p, Value(42));
|
||||
auto result = op.Apply(m_dataset);
|
||||
ASSERT_FALSE(result.IsSuccess());
|
||||
}
|
||||
|
||||
TEST_F(DomPatchTests, ReplaceOperation_InsertKeyInNode_Fails)
|
||||
{
|
||||
Path p("/node/attr");
|
||||
PatchOperation op = PatchOperation::ReplaceOperation(p, Value(500));
|
||||
auto result = op.Apply(m_dataset);
|
||||
ASSERT_FALSE(result.IsSuccess());
|
||||
}
|
||||
|
||||
TEST_F(DomPatchTests, ReplaceOperation_ReplaceIndexInNode_Succeeds)
|
||||
{
|
||||
Path p("/node/0");
|
||||
PatchOperation op = PatchOperation::ReplaceOperation(p, Value(42));
|
||||
auto result = op.Apply(m_dataset);
|
||||
ASSERT_TRUE(result.IsSuccess());
|
||||
EXPECT_EQ(result.GetValue()[p].GetInt64(), 42);
|
||||
}
|
||||
|
||||
TEST_F(DomPatchTests, ReplaceOperation_AppendInNode_Fails)
|
||||
{
|
||||
Path p("/node/-");
|
||||
PatchOperation op = PatchOperation::ReplaceOperation(p, Value(42));
|
||||
auto result = op.Apply(m_dataset);
|
||||
ASSERT_FALSE(result.IsSuccess());
|
||||
}
|
||||
|
||||
TEST_F(DomPatchTests, ReplaceOperation_InvalidPath_Fails)
|
||||
{
|
||||
Path p("/non/existent/path");
|
||||
PatchOperation op = PatchOperation::ReplaceOperation(p, Value(0));
|
||||
auto result = op.Apply(m_dataset);
|
||||
ASSERT_FALSE(result.IsSuccess());
|
||||
}
|
||||
|
||||
TEST_F(DomPatchTests, CopyOperation_ArrayToObject_Succeeds)
|
||||
{
|
||||
Path dest("/obj/arr");
|
||||
Path src("/arr");
|
||||
PatchOperation op = PatchOperation::CopyOperation(dest, src);
|
||||
auto result = op.Apply(m_dataset);
|
||||
ASSERT_TRUE(result.IsSuccess());
|
||||
EXPECT_TRUE(Utils::DeepCompareIsEqual(m_dataset[src], result.GetValue()[dest]));
|
||||
EXPECT_TRUE(Utils::DeepCompareIsEqual(result.GetValue()[src], result.GetValue()[dest]));
|
||||
}
|
||||
|
||||
TEST_F(DomPatchTests, CopyOperation_ObjectToArrayInRange_Succeeds)
|
||||
{
|
||||
Path dest("/arr/0");
|
||||
Path src("/obj");
|
||||
PatchOperation op = PatchOperation::CopyOperation(dest, src);
|
||||
auto result = op.Apply(m_dataset);
|
||||
ASSERT_TRUE(result.IsSuccess());
|
||||
EXPECT_TRUE(Utils::DeepCompareIsEqual(m_dataset[src], result.GetValue()[dest]));
|
||||
EXPECT_TRUE(Utils::DeepCompareIsEqual(result.GetValue()[src], result.GetValue()[dest]));
|
||||
}
|
||||
|
||||
TEST_F(DomPatchTests, CopyOperation_ObjectToArrayOutOfRange_Fails)
|
||||
{
|
||||
Path dest("/arr/5");
|
||||
Path src("/obj");
|
||||
PatchOperation op = PatchOperation::CopyOperation(dest, src);
|
||||
auto result = op.Apply(m_dataset);
|
||||
ASSERT_FALSE(result.IsSuccess());
|
||||
}
|
||||
|
||||
TEST_F(DomPatchTests, CopyOperation_ObjectToNodeChildInRange_Succeeds)
|
||||
{
|
||||
Path dest("/node/0");
|
||||
Path src("/obj");
|
||||
PatchOperation op = PatchOperation::CopyOperation(dest, src);
|
||||
auto result = op.Apply(m_dataset);
|
||||
ASSERT_TRUE(result.IsSuccess());
|
||||
EXPECT_TRUE(Utils::DeepCompareIsEqual(m_dataset[src], result.GetValue()[dest]));
|
||||
EXPECT_TRUE(Utils::DeepCompareIsEqual(result.GetValue()[src], result.GetValue()[dest]));
|
||||
}
|
||||
|
||||
TEST_F(DomPatchTests, CopyOperation_ObjectToNodeChildOutOfRange_Fails)
|
||||
{
|
||||
Path dest("/node/5");
|
||||
Path src("/obj");
|
||||
PatchOperation op = PatchOperation::CopyOperation(dest, src);
|
||||
auto result = op.Apply(m_dataset);
|
||||
ASSERT_FALSE(result.IsSuccess());
|
||||
}
|
||||
|
||||
TEST_F(DomPatchTests, CopyOperation_InvalidSourcePath_Fails)
|
||||
{
|
||||
Path dest("/node/0");
|
||||
Path src("/invalid/path");
|
||||
PatchOperation op = PatchOperation::CopyOperation(dest, src);
|
||||
auto result = op.Apply(m_dataset);
|
||||
ASSERT_FALSE(result.IsSuccess());
|
||||
}
|
||||
|
||||
TEST_F(DomPatchTests, CopyOperation_InvalidDestinationPath_Fails)
|
||||
{
|
||||
Path dest("/invalid/path");
|
||||
Path src("/arr/0");
|
||||
PatchOperation op = PatchOperation::CopyOperation(dest, src);
|
||||
auto result = op.Apply(m_dataset);
|
||||
ASSERT_FALSE(result.IsSuccess());
|
||||
}
|
||||
|
||||
TEST_F(DomPatchTests, MoveOperation_ArrayToObject_Succeeds)
|
||||
{
|
||||
Path dest("/obj/arr");
|
||||
Path src("/arr");
|
||||
PatchOperation op = PatchOperation::MoveOperation(dest, src);
|
||||
auto result = op.Apply(m_dataset);
|
||||
ASSERT_TRUE(result.IsSuccess());
|
||||
EXPECT_TRUE(Utils::DeepCompareIsEqual(m_dataset[src], result.GetValue()[dest]));
|
||||
EXPECT_FALSE(result.GetValue().HasMember("arr"));
|
||||
}
|
||||
|
||||
TEST_F(DomPatchTests, MoveOperation_ObjectToArrayInRange_Succeeds)
|
||||
{
|
||||
Path dest("/arr/0");
|
||||
Path src("/obj");
|
||||
PatchOperation op = PatchOperation::MoveOperation(dest, src);
|
||||
auto result = op.Apply(m_dataset);
|
||||
ASSERT_TRUE(result.IsSuccess());
|
||||
EXPECT_TRUE(Utils::DeepCompareIsEqual(m_dataset[src], result.GetValue()[dest]));
|
||||
EXPECT_FALSE(result.GetValue().HasMember("obj"));
|
||||
}
|
||||
|
||||
TEST_F(DomPatchTests, MoveOperation_ObjectToArrayOutOfRange_Fails)
|
||||
{
|
||||
Path dest("/arr/5");
|
||||
Path src("/obj");
|
||||
PatchOperation op = PatchOperation::MoveOperation(dest, src);
|
||||
auto result = op.Apply(m_dataset);
|
||||
ASSERT_FALSE(result.IsSuccess());
|
||||
}
|
||||
|
||||
TEST_F(DomPatchTests, MoveOperation_ObjectToNodeChildInRange_Succeeds)
|
||||
{
|
||||
Path dest("/node/0");
|
||||
Path src("/obj");
|
||||
PatchOperation op = PatchOperation::MoveOperation(dest, src);
|
||||
auto result = op.Apply(m_dataset);
|
||||
ASSERT_TRUE(result.IsSuccess());
|
||||
EXPECT_TRUE(Utils::DeepCompareIsEqual(m_dataset[src], result.GetValue()[dest]));
|
||||
EXPECT_FALSE(result.GetValue().HasMember("obj"));
|
||||
}
|
||||
|
||||
TEST_F(DomPatchTests, MoveOperation_ObjectToNodeChildOutOfRange_Fails)
|
||||
{
|
||||
Path dest("/node/5");
|
||||
Path src("/obj");
|
||||
PatchOperation op = PatchOperation::MoveOperation(dest, src);
|
||||
auto result = op.Apply(m_dataset);
|
||||
ASSERT_FALSE(result.IsSuccess());
|
||||
}
|
||||
|
||||
TEST_F(DomPatchTests, MoveOperation_InvalidSourcePath_Fails)
|
||||
{
|
||||
Path dest("/node/0");
|
||||
Path src("/invalid/path");
|
||||
PatchOperation op = PatchOperation::MoveOperation(dest, src);
|
||||
auto result = op.Apply(m_dataset);
|
||||
ASSERT_FALSE(result.IsSuccess());
|
||||
}
|
||||
|
||||
TEST_F(DomPatchTests, MoveOperation_InvalidDestinationPath_Fails)
|
||||
{
|
||||
Path dest("/invalid/path");
|
||||
Path src("/arr/0");
|
||||
PatchOperation op = PatchOperation::MoveOperation(dest, src);
|
||||
auto result = op.Apply(m_dataset);
|
||||
ASSERT_FALSE(result.IsSuccess());
|
||||
}
|
||||
|
||||
TEST_F(DomPatchTests, TestOperation_TestCorrectValue_Succeeds)
|
||||
{
|
||||
Path path("/arr/1");
|
||||
Value value(1);
|
||||
PatchOperation op = PatchOperation::TestOperation(path, value);
|
||||
auto result = op.Apply(m_dataset);
|
||||
ASSERT_TRUE(result.IsSuccess());
|
||||
}
|
||||
|
||||
TEST_F(DomPatchTests, TestOperation_TestIncorrectValue_Fails)
|
||||
{
|
||||
Path path("/arr/1");
|
||||
Value value(55);
|
||||
PatchOperation op = PatchOperation::TestOperation(path, value);
|
||||
auto result = op.Apply(m_dataset);
|
||||
ASSERT_FALSE(result.IsSuccess());
|
||||
}
|
||||
|
||||
TEST_F(DomPatchTests, TestOperation_TestCorrectComplexValue_Succeeds)
|
||||
{
|
||||
Path path;
|
||||
Value value = m_dataset;
|
||||
PatchOperation op = PatchOperation::TestOperation(path, value);
|
||||
auto result = op.Apply(m_dataset);
|
||||
ASSERT_TRUE(result.IsSuccess());
|
||||
}
|
||||
|
||||
TEST_F(DomPatchTests, TestOperation_TestIncorrectComplexValue_Fails)
|
||||
{
|
||||
Path path;
|
||||
Value value = m_dataset;
|
||||
value["arr"][4] = 9;
|
||||
PatchOperation op = PatchOperation::TestOperation(path, value);
|
||||
auto result = op.Apply(m_dataset);
|
||||
ASSERT_FALSE(result.IsSuccess());
|
||||
}
|
||||
|
||||
TEST_F(DomPatchTests, TestOperation_TestInvalidPath_Fails)
|
||||
{
|
||||
Path path("/invalid/path");
|
||||
Value value;
|
||||
PatchOperation op = PatchOperation::TestOperation(path, value);
|
||||
auto result = op.Apply(m_dataset);
|
||||
ASSERT_FALSE(result.IsSuccess());
|
||||
}
|
||||
|
||||
TEST_F(DomPatchTests, TestOperation_TestInsertArrayPath_Fails)
|
||||
{
|
||||
Path path("/arr/-");
|
||||
Value value(4);
|
||||
PatchOperation op = PatchOperation::TestOperation(path, value);
|
||||
auto result = op.Apply(m_dataset);
|
||||
ASSERT_FALSE(result.IsSuccess());
|
||||
}
|
||||
|
||||
TEST_F(DomPatchTests, TestPatch_ReplaceArrayValue)
|
||||
{
|
||||
m_deltaDataset["arr"][0] = 5;
|
||||
GenerateAndVerifyDelta();
|
||||
}
|
||||
|
||||
TEST_F(DomPatchTests, TestPatch_AppendArrayValue)
|
||||
{
|
||||
m_deltaDataset["arr"].ArrayPushBack(Value(7));
|
||||
auto result = GenerateAndVerifyDelta();
|
||||
|
||||
// Ensure the generated patch uses the array append operation
|
||||
ASSERT_EQ(result.m_forwardPatches.Size(), 1);
|
||||
EXPECT_TRUE(result.m_forwardPatches[0].GetDestinationPath()[1].IsEndOfArray());
|
||||
}
|
||||
|
||||
TEST_F(DomPatchTests, TestPatch_AppendArrayValues)
|
||||
{
|
||||
m_deltaDataset["arr"].ArrayPushBack(Value(7));
|
||||
m_deltaDataset["arr"].ArrayPushBack(Value(8));
|
||||
m_deltaDataset["arr"].ArrayPushBack(Value(9));
|
||||
GenerateAndVerifyDelta();
|
||||
}
|
||||
|
||||
TEST_F(DomPatchTests, TestPatch_InsertArrayValue)
|
||||
{
|
||||
auto& arr = m_deltaDataset["arr"].GetMutableArray();
|
||||
arr.insert(arr.begin(), Value(42));
|
||||
GenerateAndVerifyDelta();
|
||||
}
|
||||
|
||||
TEST_F(DomPatchTests, TestPatch_InsertObjectKey)
|
||||
{
|
||||
m_deltaDataset["obj"]["newKey"].CopyFromString("test");
|
||||
GenerateAndVerifyDelta();
|
||||
}
|
||||
|
||||
TEST_F(DomPatchTests, TestPatch_DeleteObjectKey)
|
||||
{
|
||||
m_deltaDataset["obj"].RemoveMember("foo");
|
||||
GenerateAndVerifyDelta();
|
||||
}
|
||||
|
||||
TEST_F(DomPatchTests, TestPatch_AppendNodeValues)
|
||||
{
|
||||
m_deltaDataset["node"].ArrayPushBack(Value(7));
|
||||
m_deltaDataset["node"].ArrayPushBack(Value(8));
|
||||
m_deltaDataset["node"].ArrayPushBack(Value(9));
|
||||
GenerateAndVerifyDelta();
|
||||
}
|
||||
|
||||
TEST_F(DomPatchTests, TestPatch_InsertNodeValue)
|
||||
{
|
||||
auto& node = m_deltaDataset["node"].GetMutableNode();
|
||||
node.GetChildren().insert(node.GetChildren().begin(), Value(42));
|
||||
GenerateAndVerifyDelta();
|
||||
}
|
||||
|
||||
TEST_F(DomPatchTests, TestPatch_InsertNodeKey)
|
||||
{
|
||||
m_deltaDataset["node"]["newKey"].CopyFromString("test");
|
||||
GenerateAndVerifyDelta();
|
||||
}
|
||||
|
||||
TEST_F(DomPatchTests, TestPatch_DeleteNodeKey)
|
||||
{
|
||||
m_deltaDataset["node"].RemoveMember("int");
|
||||
GenerateAndVerifyDelta();
|
||||
}
|
||||
|
||||
TEST_F(DomPatchTests, TestPatch_RenameNode)
|
||||
{
|
||||
m_deltaDataset["node"].SetNodeName("RenamedNode");
|
||||
GenerateAndVerifyDelta();
|
||||
}
|
||||
|
||||
TEST_F(DomPatchTests, TestPatch_ReplaceRoot)
|
||||
{
|
||||
m_deltaDataset = Value(Type::Array);
|
||||
m_deltaDataset.ArrayPushBack(Value(2));
|
||||
m_deltaDataset.ArrayPushBack(Value(4));
|
||||
m_deltaDataset.ArrayPushBack(Value(6));
|
||||
GenerateAndVerifyDelta();
|
||||
}
|
||||
} // namespace AZ::Dom::Tests
|
||||
@ -0,0 +1,142 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project.
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#ifdef SHADOWS
|
||||
#include <Atom/Features/Shadow/Shadow.azsli>
|
||||
#endif
|
||||
|
||||
#ifndef MULTILAYER
|
||||
#define MULTILAYER 0
|
||||
#endif
|
||||
|
||||
#ifndef ENABLE_ALPHA_CLIP
|
||||
#define ENABLE_ALPHA_CLIP 0
|
||||
#endif
|
||||
|
||||
#ifndef SHADOWS
|
||||
#define SHADOWS 0
|
||||
#endif
|
||||
|
||||
struct VSInput
|
||||
{
|
||||
float3 m_position : POSITION;
|
||||
float2 m_uv0 : UV0;
|
||||
float2 m_uv1 : UV1;
|
||||
|
||||
// only used for parallax depth calculation
|
||||
float3 m_normal : NORMAL;
|
||||
float4 m_tangent : TANGENT;
|
||||
float3 m_bitangent : BITANGENT;
|
||||
|
||||
#if MULTILAYER
|
||||
// This gets set automatically by the system at runtime only if it's available.
|
||||
// There is a soft naming convention that associates this with o_blendMask_isBound, which will be set to true whenever m_optional_blendMask is available.
|
||||
// (search "m_optional_" in ShaderVariantAssetBuilder for details on the naming convention).
|
||||
// [GFX TODO][ATOM-14475]: Come up with a more elegant way to associate the isBound flag with the input stream.
|
||||
float4 m_optional_blendMask : COLOR0;
|
||||
#endif
|
||||
};
|
||||
|
||||
struct VSDepthOutput
|
||||
{
|
||||
// "centroid" is needed for SV_Depth to compile
|
||||
precise linear centroid float4 m_position : SV_Position;
|
||||
float2 m_uv[UvSetCount] : UV1;
|
||||
|
||||
// only used for parallax depth calculation
|
||||
float3 m_normal : NORMAL;
|
||||
float3 m_tangent : TANGENT;
|
||||
float3 m_bitangent : BITANGENT;
|
||||
float3 m_worldPosition : UV0;
|
||||
|
||||
#if MULTILAYER
|
||||
float3 m_blendMask : UV3;
|
||||
#endif
|
||||
};
|
||||
|
||||
VSDepthOutput MainVS(VSInput IN)
|
||||
{
|
||||
VSDepthOutput OUT;
|
||||
|
||||
float4x4 objectToWorld = GetObjectToWorld();
|
||||
float4 worldPosition = mul(objectToWorld, float4(IN.m_position, 1.0));
|
||||
|
||||
OUT.m_position = mul(ViewSrg::m_viewProjectionMatrix, worldPosition);
|
||||
|
||||
float2 uvs[UvSetCount] = { IN.m_uv0, IN.m_uv1 };
|
||||
TransformUvs(uvs, OUT.m_uv);
|
||||
|
||||
if(ShouldHandleParallaxInDepthShaders())
|
||||
{
|
||||
OUT.m_worldPosition = worldPosition.xyz;
|
||||
|
||||
float3x3 objectToWorldIT = GetNormalToWorld();
|
||||
ConstructTBN(IN.m_normal, IN.m_tangent, IN.m_bitangent, objectToWorld, objectToWorldIT, OUT.m_normal, OUT.m_tangent, OUT.m_bitangent);
|
||||
}
|
||||
|
||||
#if MULTILAYER
|
||||
if(o_blendMask_isBound)
|
||||
{
|
||||
OUT.m_blendMask = IN.m_optional_blendMask.rgb;
|
||||
}
|
||||
else
|
||||
{
|
||||
OUT.m_blendMask = float3(0,0,0);
|
||||
}
|
||||
#endif
|
||||
|
||||
return OUT;
|
||||
}
|
||||
|
||||
struct PSDepthOutput
|
||||
{
|
||||
precise float m_depth : SV_Depth;
|
||||
};
|
||||
|
||||
PSDepthOutput MainPS(VSDepthOutput IN, bool isFrontFace : SV_IsFrontFace)
|
||||
{
|
||||
PSDepthOutput OUT;
|
||||
|
||||
OUT.m_depth = IN.m_position.z;
|
||||
|
||||
if(ShouldHandleParallaxInDepthShaders())
|
||||
{
|
||||
float3 tangents[UvSetCount] = { IN.m_tangent, IN.m_tangent };
|
||||
float3 bitangents[UvSetCount] = { IN.m_bitangent, IN.m_bitangent };
|
||||
|
||||
for (int i = 0; i != UvSetCount; ++i)
|
||||
{
|
||||
EvaluateTangentFrame(
|
||||
IN.m_normal,
|
||||
IN.m_worldPosition,
|
||||
isFrontFace,
|
||||
IN.m_uv[i],
|
||||
i,
|
||||
IN.m_tangent,
|
||||
IN.m_bitangent,
|
||||
tangents[i],
|
||||
bitangents[i]);
|
||||
}
|
||||
|
||||
#if MULTILAYER
|
||||
MultilayerSetPixelDepth(IN.m_blendMask, IN.m_worldPosition, IN.m_normal, tangents, bitangents, IN.m_uv, isFrontFace, OUT.m_depth);
|
||||
#else
|
||||
SetPixelDepth(IN.m_worldPosition, IN.m_normal, tangents, bitangents, IN.m_uv, isFrontFace, OUT.m_depth);
|
||||
#endif
|
||||
|
||||
#if SHADOWS
|
||||
OUT.m_depth += PdoShadowMapBias;
|
||||
#endif
|
||||
}
|
||||
|
||||
#if ENABLE_ALPHA_CLIP
|
||||
GetAlphaAndClip(IN.m_uv);
|
||||
#endif
|
||||
|
||||
return OUT;
|
||||
}
|
||||
@ -0,0 +1,317 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project.
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
// SRGs
|
||||
#include <Atom/Features/PBR/ForwardPassSrg.azsli>
|
||||
|
||||
// Pass Output
|
||||
#include <Atom/Features/PBR/ForwardSubsurfacePassOutput.azsli>
|
||||
|
||||
// Utility
|
||||
#include <Atom/Features/ColorManagement/TransformColor.azsli>
|
||||
|
||||
// Custom Surface & Lighting
|
||||
#include <Atom/Features/PBR/Lighting/EnhancedLighting.azsli>
|
||||
|
||||
// Decals
|
||||
#include <Atom/Features/PBR/Decals.azsli>
|
||||
|
||||
// ---------- Vertex Shader ----------
|
||||
|
||||
struct VSInput
|
||||
{
|
||||
// Base fields (required by the template azsli file)...
|
||||
float3 m_position : POSITION;
|
||||
float3 m_normal : NORMAL;
|
||||
float4 m_tangent : TANGENT;
|
||||
float3 m_bitangent : BITANGENT;
|
||||
|
||||
// Extended fields (only referenced in this azsl file)...
|
||||
float2 m_uv0 : UV0;
|
||||
float2 m_uv1 : UV1;
|
||||
};
|
||||
|
||||
struct VSOutput
|
||||
{
|
||||
// Base fields (required by the template azsli file)...
|
||||
precise linear centroid float4 m_position : SV_Position;
|
||||
float3 m_normal: NORMAL;
|
||||
float3 m_tangent : TANGENT;
|
||||
float3 m_bitangent : BITANGENT;
|
||||
float3 m_worldPosition : UV0;
|
||||
float3 m_shadowCoords[ViewSrg::MaxCascadeCount] : UV5;
|
||||
|
||||
// Extended fields (only referenced in this azsl file)...
|
||||
float2 m_uv[UvSetCount] : UV1;
|
||||
float2 m_detailUv[UvSetCount] : UV3;
|
||||
};
|
||||
|
||||
VSOutput EnhancedPbr_ForwardPassVS(VSInput IN)
|
||||
{
|
||||
VSOutput OUT;
|
||||
|
||||
float4x4 objectToWorld = GetObjectToWorld();
|
||||
float4 worldPosition = mul(objectToWorld, float4(IN.m_position, 1.0));
|
||||
OUT.m_worldPosition = worldPosition.xyz;
|
||||
OUT.m_position = mul(ViewSrg::m_viewProjectionMatrix, worldPosition);
|
||||
|
||||
float2 uv[UvSetCount] = { IN.m_uv0, IN.m_uv1 };
|
||||
TransformUvs(uv, OUT.m_uv);
|
||||
|
||||
float2 detailUv[UvSetCount] = { IN.m_uv0, IN.m_uv1 };
|
||||
TransformDetailUvs(detailUv, OUT.m_detailUv);
|
||||
|
||||
// Shadow coords will be calculated in the pixel shader in this case
|
||||
bool skipShadowCoords = ShouldHandleParallax() && o_parallax_enablePixelDepthOffset;
|
||||
|
||||
float3x3 objectToWorldIT = GetNormalToWorld();
|
||||
ConstructTBN(IN.m_normal, IN.m_tangent, IN.m_bitangent, objectToWorld, objectToWorldIT, OUT.m_normal, OUT.m_tangent, OUT.m_bitangent);
|
||||
|
||||
// directional light shadow
|
||||
const uint shadowIndex = ViewSrg::m_shadowIndexDirectionalLight;
|
||||
if (o_enableShadows && !skipShadowCoords && shadowIndex < SceneSrg::m_directionalLightCount)
|
||||
{
|
||||
DirectionalLightShadow::GetShadowCoords(
|
||||
shadowIndex,
|
||||
worldPosition,
|
||||
OUT.m_normal,
|
||||
OUT.m_shadowCoords);
|
||||
}
|
||||
|
||||
return OUT;
|
||||
}
|
||||
|
||||
|
||||
// ---------- Pixel Shader ----------
|
||||
|
||||
PbrLightingOutput ForwardPassPS_Common(VSOutput IN, bool isFrontFace, out float depth)
|
||||
{
|
||||
const float3 vertexNormal = normalize(IN.m_normal);
|
||||
|
||||
// ------- Tangents & Bitangets -------
|
||||
float3 tangents[UvSetCount] = { IN.m_tangent.xyz, IN.m_tangent.xyz };
|
||||
float3 bitangents[UvSetCount] = { IN.m_bitangent.xyz, IN.m_bitangent.xyz };
|
||||
|
||||
if ((o_parallax_feature_enabled && !o_enableSubsurfaceScattering) || o_normal_useTexture || (o_clearCoat_enabled && o_clearCoat_normal_useTexture) || o_detail_normal_useTexture)
|
||||
{
|
||||
for (int i = 0; i != UvSetCount; ++i)
|
||||
{
|
||||
EvaluateTangentFrame(
|
||||
IN.m_normal,
|
||||
IN.m_worldPosition,
|
||||
isFrontFace,
|
||||
IN.m_uv[i],
|
||||
i,
|
||||
IN.m_tangent,
|
||||
IN.m_bitangent,
|
||||
tangents[i],
|
||||
bitangents[i]);
|
||||
}
|
||||
}
|
||||
|
||||
// ------- Depth & Parallax -------
|
||||
|
||||
depth = IN.m_position.z;
|
||||
|
||||
bool displacementIsClipped = false;
|
||||
|
||||
// Parallax mapping's non uniform uv transformations break screen space subsurface scattering, disable it when subsurface scatteirng is enabled
|
||||
if(ShouldHandleParallax())
|
||||
{
|
||||
EnhancedSetPixelDepth(
|
||||
IN.m_worldPosition,
|
||||
IN.m_normal,
|
||||
tangents,
|
||||
bitangents,
|
||||
IN.m_uv,
|
||||
isFrontFace,
|
||||
IN.m_detailUv,
|
||||
IN.m_position.w,
|
||||
depth,
|
||||
displacementIsClipped);
|
||||
|
||||
// Adjust directional light shadow coorinates for parallax correction
|
||||
if(o_parallax_enablePixelDepthOffset)
|
||||
{
|
||||
const uint shadowIndex = ViewSrg::m_shadowIndexDirectionalLight;
|
||||
if (o_enableShadows && shadowIndex < SceneSrg::m_directionalLightCount)
|
||||
{
|
||||
DirectionalLightShadow::GetShadowCoords(shadowIndex, IN.m_worldPosition, vertexNormal, IN.m_shadowCoords);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SurfaceSettings surfaceSettings;
|
||||
Surface surface;
|
||||
surface.vertexNormal = vertexNormal;
|
||||
surface.position = IN.m_worldPosition;
|
||||
|
||||
// ------- Alpha & Clip -------
|
||||
// TODO: this often invokes a separate sample of the base color texture which is wasteful
|
||||
float alpha = GetAlphaAndClip(IN.m_uv);
|
||||
|
||||
EvaluateEnhancedSurface(IN.m_normal, IN.m_uv, IN.m_detailUv, tangents, bitangents, isFrontFace, displacementIsClipped, surface, surfaceSettings);
|
||||
|
||||
// ------- Lighting Data -------
|
||||
|
||||
LightingData lightingData;
|
||||
|
||||
// Light iterator
|
||||
lightingData.tileIterator.Init(IN.m_position, PassSrg::m_lightListRemapped, PassSrg::m_tileLightData);
|
||||
lightingData.Init(surface.position, surface.normal, surface.roughnessLinear);
|
||||
|
||||
// Directional light shadow coordinates
|
||||
lightingData.shadowCoords = IN.m_shadowCoords;
|
||||
|
||||
lightingData.emissiveLighting = surface.emissiveLighting;
|
||||
lightingData.diffuseAmbientOcclusion = surface.diffuseAmbientOcclusion;
|
||||
lightingData.specularOcclusion = surface.specularOcclusion;
|
||||
|
||||
// Diffuse and Specular response (used in IBL calculations)
|
||||
lightingData.specularResponse = FresnelSchlickWithRoughness(lightingData.NdotV, surface.specularF0, surface.roughnessLinear);
|
||||
lightingData.diffuseResponse = 1.0 - lightingData.specularResponse;
|
||||
|
||||
// ------- Thin Object Light Transmission -------
|
||||
|
||||
// Shrink (absolute) offset towards the normal opposite direction to ensure correct shadow map projection
|
||||
lightingData.shrinkFactor = surface.transmission.transmissionParams.x;
|
||||
|
||||
// Angle offset for subsurface scattering through thin objects
|
||||
lightingData.transmissionNdLBias = surface.transmission.transmissionParams.y;
|
||||
|
||||
// Attenuation applied to hide artifacts due to low-res shadow maps
|
||||
lightingData.distanceAttenuation = surface.transmission.transmissionParams.z;
|
||||
|
||||
if(o_clearCoat_feature_enabled)
|
||||
{
|
||||
// Clear coat layer has fixed IOR = 1.5 and transparent => F0 = (1.5 - 1)^2 / (1.5 + 1)^2 = 0.04
|
||||
lightingData.diffuseResponse *= 1.0 - (FresnelSchlickWithRoughness(lightingData.NdotV, float3(0.04, 0.04, 0.04), surface.clearCoat.roughness) * surface.clearCoat.factor);
|
||||
}
|
||||
|
||||
// ------- Multiscatter -------
|
||||
|
||||
lightingData.CalculateMultiscatterCompensation(surface.specularF0, o_specularF0_enableMultiScatterCompensation);
|
||||
|
||||
// ------- Lighting Calculation -------
|
||||
|
||||
// Apply Decals
|
||||
ApplyDecals(lightingData.tileIterator, surface);
|
||||
|
||||
// Apply Direct Lighting
|
||||
ApplyDirectLighting(surface, lightingData);
|
||||
|
||||
// Apply Image Based Lighting (IBL)
|
||||
ApplyIBL(surface, lightingData);
|
||||
|
||||
// Finalize Lighting
|
||||
lightingData.FinalizeLighting(surface.transmission.tint);
|
||||
|
||||
PbrLightingOutput lightingOutput = GetPbrLightingOutput(surface, lightingData, alpha);
|
||||
|
||||
// ------- Opacity -------
|
||||
|
||||
if (o_opacity_mode == OpacityMode::Blended || o_opacity_mode == OpacityMode::TintedTransparent)
|
||||
{
|
||||
// Increase opacity at grazing angles for surfaces with a low m_opacityAffectsSpecularFactor.
|
||||
// For m_opacityAffectsSpecularFactor values close to 0, that indicates a transparent surface
|
||||
// like glass, so it becomes less transparent at grazing angles. For m_opacityAffectsSpecularFactor
|
||||
// values close to 1.0, that indicates the absence of a surface entirely, so this effect should
|
||||
// not apply.
|
||||
float fresnelAlpha = FresnelSchlickWithRoughness(lightingData.NdotV, alpha, surface.roughnessLinear).x;
|
||||
alpha = lerp(fresnelAlpha, alpha, surfaceSettings.opacityAffectsSpecularFactor);
|
||||
}
|
||||
|
||||
// Note: lightingOutput rendertargets are not always used as named, particularly m_diffuseColor (target 0) and
|
||||
// m_specularColor (target 1). Comments below describe the differences when appropriate.
|
||||
|
||||
if (o_opacity_mode == OpacityMode::Blended)
|
||||
{
|
||||
// [GFX_TODO ATOM-13187] PbrLighting shouldn't be writing directly to render targets. It's confusing when
|
||||
// specular is being added to diffuse just because we're calling render target 0 "diffuse".
|
||||
|
||||
// For blended mode, we do (dest * alpha) + (source * 1.0). This allows the specular
|
||||
// to be added on top of the diffuse, but then the diffuse must be pre-multiplied.
|
||||
// It's done this way because surface transparency doesn't really change specular response (eg, glass).
|
||||
|
||||
lightingOutput.m_diffuseColor.rgb *= lightingOutput.m_diffuseColor.w; // pre-multiply diffuse
|
||||
|
||||
// Add specular. m_opacityAffectsSpecularFactor controls how much the alpha masks out specular contribution.
|
||||
float3 specular = lightingOutput.m_specularColor.rgb;
|
||||
specular = lerp(specular, specular * lightingOutput.m_diffuseColor.w, surfaceSettings.opacityAffectsSpecularFactor);
|
||||
lightingOutput.m_diffuseColor.rgb += specular;
|
||||
|
||||
lightingOutput.m_diffuseColor.w = alpha;
|
||||
}
|
||||
else if (o_opacity_mode == OpacityMode::TintedTransparent)
|
||||
{
|
||||
// See OpacityMode::Blended above for the basic method. TintedTransparent adds onto the above concept by supporting
|
||||
// colored alpha. This is currently a very basic calculation that uses the baseColor as a multiplier with strength
|
||||
// determined by the alpha. We'll modify this later to be more physically accurate and allow surface depth,
|
||||
// absorption, and interior color to be specified.
|
||||
//
|
||||
// The technique uses dual source blending to allow two separate sources to be part of the blending equation
|
||||
// even though ultimately only a single render target is being written to. m_diffuseColor is render target 0 and
|
||||
// m_specularColor render target 1, and the blend mode is (dest * source1color) + (source * 1.0).
|
||||
//
|
||||
// This means that m_specularColor.rgb (source 1) is multiplied against the destination, then
|
||||
// m_diffuseColor.rgb (source) is added to that, and the final result is stored in render target 0.
|
||||
|
||||
lightingOutput.m_diffuseColor.rgb *= lightingOutput.m_diffuseColor.w; // pre-multiply diffuse
|
||||
|
||||
// Add specular. m_opacityAffectsSpecularFactor controls how much the alpha masks out specular contribution.
|
||||
float3 specular = lightingOutput.m_specularColor.rgb;
|
||||
specular = lerp(specular, specular * lightingOutput.m_diffuseColor.w, surfaceSettings.opacityAffectsSpecularFactor);
|
||||
lightingOutput.m_diffuseColor.rgb += specular;
|
||||
|
||||
lightingOutput.m_specularColor.rgb = surface.baseColor * (1.0 - alpha);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Pack factor and quality, drawback: because of precision limit of float16 cannot represent exact 1, maximum representable value is 0.9961
|
||||
uint factorAndQuality = dot(round(float2(saturate(surface.subsurfaceScatteringFactor), surfaceSettings.subsurfaceScatteringQuality) * 255), float2(256, 1));
|
||||
lightingOutput.m_diffuseColor.w = factorAndQuality * (o_enableSubsurfaceScattering ? 1.0 : -1.0);
|
||||
lightingOutput.m_scatterDistance = surfaceSettings.scatterDistance;
|
||||
}
|
||||
|
||||
return lightingOutput;
|
||||
}
|
||||
|
||||
ForwardPassOutputWithDepth EnhancedPbr_ForwardPassPS(VSOutput IN, bool isFrontFace : SV_IsFrontFace)
|
||||
{
|
||||
ForwardPassOutputWithDepth OUT;
|
||||
float depth;
|
||||
|
||||
PbrLightingOutput lightingOutput = ForwardPassPS_Common(IN, isFrontFace, depth);
|
||||
|
||||
OUT.m_diffuseColor = lightingOutput.m_diffuseColor;
|
||||
OUT.m_specularColor = lightingOutput.m_specularColor;
|
||||
OUT.m_specularF0 = lightingOutput.m_specularF0;
|
||||
OUT.m_albedo = lightingOutput.m_albedo;
|
||||
OUT.m_normal = lightingOutput.m_normal;
|
||||
OUT.m_scatterDistance = lightingOutput.m_scatterDistance;
|
||||
OUT.m_depth = depth;
|
||||
return OUT;
|
||||
}
|
||||
|
||||
[earlydepthstencil]
|
||||
ForwardPassOutput EnhancedPbr_ForwardPassPS_EDS(VSOutput IN, bool isFrontFace : SV_IsFrontFace)
|
||||
{
|
||||
ForwardPassOutput OUT;
|
||||
float depth;
|
||||
|
||||
PbrLightingOutput lightingOutput = ForwardPassPS_Common(IN, isFrontFace, depth);
|
||||
|
||||
OUT.m_diffuseColor = lightingOutput.m_diffuseColor;
|
||||
OUT.m_specularColor = lightingOutput.m_specularColor;
|
||||
OUT.m_specularF0 = lightingOutput.m_specularF0;
|
||||
OUT.m_albedo = lightingOutput.m_albedo;
|
||||
OUT.m_normal = lightingOutput.m_normal;
|
||||
OUT.m_scatterDistance = lightingOutput.m_scatterDistance;
|
||||
|
||||
return OUT;
|
||||
}
|
||||
@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project.
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include <Atom/Features/ParallaxMapping.azsli>
|
||||
#include "../MaterialInputs/ParallaxInput.azsli"
|
||||
#include <Atom/Features/MatrixUtility.azsli>
|
||||
|
||||
void EnhancedSetPixelDepth(
|
||||
float3 worldPosition,
|
||||
float3 normal,
|
||||
float3 tangents[UvSetCount],
|
||||
float3 bitangents[UvSetCount],
|
||||
float2 uvs[UvSetCount],
|
||||
bool isFrontFace,
|
||||
inout float2 detailUv[UvSetCount],
|
||||
inout float depthCS,
|
||||
out float depth,
|
||||
out bool isClipped)
|
||||
{
|
||||
// GetParallaxInput applies an tangent offset to the UV. We want to apply the same offset to the detailUv (note: this needs to be tested with content)
|
||||
// The math is: offset = newUv - oldUv; detailUv += offset;
|
||||
// This is the same as: detailUv -= oldUv; detailUv += newUv;
|
||||
detailUv[MaterialSrg::m_parallaxUvIndex] -= uvs[MaterialSrg::m_parallaxUvIndex];
|
||||
|
||||
float3x3 uvMatrix = MaterialSrg::m_parallaxUvIndex == 0 ? MaterialSrg::m_uvMatrix : CreateIdentity3x3();
|
||||
float3x3 uvMatrixInverse = MaterialSrg::m_parallaxUvIndex == 0 ? MaterialSrg::m_uvMatrixInverse : CreateIdentity3x3();
|
||||
|
||||
GetParallaxInput(
|
||||
normal, tangents[MaterialSrg::m_parallaxUvIndex], bitangents[MaterialSrg::m_parallaxUvIndex],
|
||||
MaterialSrg::m_heightmapScale, MaterialSrg::m_heightmapOffset,
|
||||
ObjectSrg::GetWorldMatrix(), uvMatrix, uvMatrixInverse,
|
||||
uvs[MaterialSrg::m_parallaxUvIndex], worldPosition, depth, depthCS, isClipped);
|
||||
|
||||
// Apply second part of the offset to the detail UV (see comment above)
|
||||
detailUv[MaterialSrg::m_parallaxUvIndex] -= uvs[MaterialSrg::m_parallaxUvIndex];
|
||||
}
|
||||
@ -0,0 +1,149 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project.
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include <Atom/Features/PBR/Surfaces/EnhancedSurface.azsli>
|
||||
#include <Atom/Features/MatrixUtility.azsli>
|
||||
|
||||
void EvaluateEnhancedSurface(
|
||||
float3 normal,
|
||||
float2 uvs[UvSetCount],
|
||||
float2 detailUvs[UvSetCount],
|
||||
float3 tangents[UvSetCount],
|
||||
float3 bitangents[UvSetCount],
|
||||
bool isFrontFace,
|
||||
bool displacementIsClipped,
|
||||
inout Surface surface,
|
||||
out SurfaceSettings surfaceSettings)
|
||||
{
|
||||
// ------- Detail Layer Setup -------
|
||||
|
||||
const float2 detailUv = detailUvs[MaterialSrg::m_detail_allMapsUvIndex];
|
||||
|
||||
// When the detail maps and the detail blend mask are on the same UV, they both use the transformed detail UVs because they are 'attached' to each other
|
||||
const float2 detailBlendMaskUv = (MaterialSrg::m_detail_blendMask_uvIndex == MaterialSrg::m_detail_allMapsUvIndex) ?
|
||||
detailUvs[MaterialSrg::m_detail_blendMask_uvIndex] :
|
||||
uvs[MaterialSrg::m_detail_blendMask_uvIndex];
|
||||
|
||||
const float detailLayerBlendFactor = GetDetailLayerBlendFactor(
|
||||
MaterialSrg::m_detail_blendMask_texture,
|
||||
MaterialSrg::m_sampler,
|
||||
detailBlendMaskUv,
|
||||
o_detail_blendMask_useTexture,
|
||||
MaterialSrg::m_detail_blendFactor);
|
||||
|
||||
// ------- Normal -------
|
||||
|
||||
float2 normalUv = uvs[MaterialSrg::m_normalMapUvIndex];
|
||||
float3x3 uvMatrix = MaterialSrg::m_normalMapUvIndex == 0 ? MaterialSrg::m_uvMatrix : CreateIdentity3x3(); // By design, only UV0 is allowed to apply transforms.
|
||||
float detailLayerNormalFactor = MaterialSrg::m_detail_normal_factor * detailLayerBlendFactor;
|
||||
surface.normal = GetDetailedNormalInputWS(
|
||||
isFrontFace, normal,
|
||||
tangents[MaterialSrg::m_normalMapUvIndex], bitangents[MaterialSrg::m_normalMapUvIndex], MaterialSrg::m_normalMap, MaterialSrg::m_sampler, normalUv, MaterialSrg::m_normalFactor, MaterialSrg::m_flipNormalX, MaterialSrg::m_flipNormalY, uvMatrix, o_normal_useTexture,
|
||||
tangents[MaterialSrg::m_detail_allMapsUvIndex], bitangents[MaterialSrg::m_detail_allMapsUvIndex], MaterialSrg::m_detail_normal_texture, MaterialSrg::m_sampler, detailUv, detailLayerNormalFactor, MaterialSrg::m_detail_normal_flipX, MaterialSrg::m_detail_normal_flipY, MaterialSrg::m_detailUvMatrix, o_detail_normal_useTexture);
|
||||
|
||||
//--------------------- Base Color ----------------------
|
||||
|
||||
// [GFX TODO][ATOM-1761] Figure out how we want our base material to expect channels to be encoded, and apply that to the way we pack alpha.
|
||||
|
||||
float detailLayerBaseColorFactor = MaterialSrg::m_detail_baseColor_factor * detailLayerBlendFactor;
|
||||
float2 baseColorUv = uvs[MaterialSrg::m_baseColorMapUvIndex];
|
||||
|
||||
float3 baseColor = GetDetailedBaseColorInput(
|
||||
MaterialSrg::m_baseColorMap, MaterialSrg::m_sampler, baseColorUv, o_baseColor_useTexture, MaterialSrg::m_baseColor, MaterialSrg::m_baseColorFactor, o_baseColorTextureBlendMode,
|
||||
MaterialSrg::m_detail_baseColor_texture, MaterialSrg::m_sampler, detailUv, o_detail_baseColor_useTexture, detailLayerBaseColorFactor);
|
||||
|
||||
if(o_parallax_highlightClipping && displacementIsClipped)
|
||||
{
|
||||
ApplyParallaxClippingHighlight(baseColor);
|
||||
}
|
||||
|
||||
// ------- Metallic -------
|
||||
|
||||
float metallic = 0;
|
||||
if(!o_enableSubsurfaceScattering) // If subsurface scattering is enabled skip texture lookup for metallic, as this quantity won't be used anyway
|
||||
{
|
||||
float2 metallicUv = uvs[MaterialSrg::m_metallicMapUvIndex];
|
||||
metallic = GetMetallicInput(MaterialSrg::m_metallicMap, MaterialSrg::m_sampler, metallicUv, MaterialSrg::m_metallicFactor, o_metallic_useTexture);
|
||||
}
|
||||
|
||||
// ------- Specular -------
|
||||
|
||||
float2 specularUv = uvs[MaterialSrg::m_specularF0MapUvIndex];
|
||||
float specularF0Factor = GetSpecularInput(MaterialSrg::m_specularF0Map, MaterialSrg::m_sampler, specularUv, MaterialSrg::m_specularF0Factor, o_specularF0_useTexture);
|
||||
|
||||
surface.SetAlbedoAndSpecularF0(baseColor, specularF0Factor, metallic);
|
||||
|
||||
// ------- Roughness -------
|
||||
|
||||
float2 roughnessUv = uvs[MaterialSrg::m_roughnessMapUvIndex];
|
||||
surface.roughnessLinear = GetRoughnessInput(MaterialSrg::m_roughnessMap, MaterialSrg::m_sampler, roughnessUv, MaterialSrg::m_roughnessFactor,
|
||||
MaterialSrg::m_roughnessLowerBound, MaterialSrg::m_roughnessUpperBound, o_roughness_useTexture);
|
||||
surface.CalculateRoughnessA();
|
||||
|
||||
// ------- Subsurface -------
|
||||
|
||||
float2 subsurfaceUv = uvs[MaterialSrg::m_subsurfaceScatteringInfluenceMapUvIndex];
|
||||
surface.subsurfaceScatteringFactor = GetSubsurfaceInput(MaterialSrg::m_subsurfaceScatteringInfluenceMap, MaterialSrg::m_sampler, subsurfaceUv, MaterialSrg::m_subsurfaceScatteringFactor);
|
||||
surfaceSettings.subsurfaceScatteringQuality = MaterialSrg::m_subsurfaceScatteringQuality;
|
||||
surfaceSettings.scatterDistance = MaterialSrg::m_scatterDistance;
|
||||
|
||||
// ------- Transmission -------
|
||||
|
||||
float2 transmissionUv = uvs[MaterialSrg::m_transmissionThicknessMapUvIndex];
|
||||
float4 transmissionTintThickness = GeTransmissionInput(MaterialSrg::m_transmissionThicknessMap, MaterialSrg::m_sampler, transmissionUv, MaterialSrg::m_transmissionTintThickness);
|
||||
surface.transmission.tint = transmissionTintThickness.rgb;
|
||||
surface.transmission.thickness = transmissionTintThickness.w;
|
||||
surface.transmission.transmissionParams = MaterialSrg::m_transmissionParams;
|
||||
surface.transmission.scatterDistance = MaterialSrg::m_scatterDistance;
|
||||
|
||||
// ------- Anisotropy -------
|
||||
|
||||
if (o_enableAnisotropy)
|
||||
{
|
||||
// Convert the angle from [0..1] = [0 .. 180 degrees] to radians [0 .. PI]
|
||||
const float anisotropyAngle = MaterialSrg::m_anisotropicAngle * PI;
|
||||
const float anisotropyFactor = MaterialSrg::m_anisotropicFactor;
|
||||
surface.anisotropy.Init(surface.normal, tangents[0], bitangents[0], anisotropyAngle, anisotropyFactor, surface.roughnessA);
|
||||
}
|
||||
|
||||
// ------- Emissive -------
|
||||
|
||||
float2 emissiveUv = uvs[MaterialSrg::m_emissiveMapUvIndex];
|
||||
surface.emissiveLighting = GetEmissiveInput(MaterialSrg::m_emissiveMap, MaterialSrg::m_sampler, emissiveUv, MaterialSrg::m_emissiveIntensity, MaterialSrg::m_emissiveColor.rgb, o_emissiveEnabled, o_emissive_useTexture);
|
||||
|
||||
// ------- Occlusion -------
|
||||
|
||||
surface.diffuseAmbientOcclusion = GetOcclusionInput(MaterialSrg::m_diffuseOcclusionMap, MaterialSrg::m_sampler, uvs[MaterialSrg::m_diffuseOcclusionMapUvIndex], MaterialSrg::m_diffuseOcclusionFactor, o_diffuseOcclusion_useTexture);
|
||||
surface.specularOcclusion = GetOcclusionInput(MaterialSrg::m_specularOcclusionMap, MaterialSrg::m_sampler, uvs[MaterialSrg::m_specularOcclusionMapUvIndex], MaterialSrg::m_specularOcclusionFactor, o_specularOcclusion_useTexture);
|
||||
|
||||
// ------- Clearcoat -------
|
||||
|
||||
// [GFX TODO][ATOM-14603]: Clean up the double uses of these clear coat flags
|
||||
if(o_clearCoat_feature_enabled)
|
||||
{
|
||||
if(o_clearCoat_enabled)
|
||||
{
|
||||
float3x3 uvMatrix = MaterialSrg::m_clearCoatNormalMapUvIndex == 0 ? MaterialSrg::m_uvMatrix : CreateIdentity3x3();
|
||||
GetClearCoatInputs(MaterialSrg::m_clearCoatInfluenceMap, uvs[MaterialSrg::m_clearCoatInfluenceMapUvIndex], MaterialSrg::m_clearCoatFactor, o_clearCoat_factor_useTexture,
|
||||
MaterialSrg::m_clearCoatRoughnessMap, uvs[MaterialSrg::m_clearCoatRoughnessMapUvIndex], MaterialSrg::m_clearCoatRoughness, o_clearCoat_roughness_useTexture,
|
||||
MaterialSrg::m_clearCoatNormalMap, uvs[MaterialSrg::m_clearCoatNormalMapUvIndex], normal, o_clearCoat_normal_useTexture, MaterialSrg::m_clearCoatNormalStrength,
|
||||
uvMatrix, tangents[MaterialSrg::m_clearCoatNormalMapUvIndex], bitangents[MaterialSrg::m_clearCoatNormalMapUvIndex],
|
||||
MaterialSrg::m_sampler, isFrontFace,
|
||||
surface.clearCoat.factor, surface.clearCoat.roughness, surface.clearCoat.normal);
|
||||
}
|
||||
|
||||
// manipulate base layer f0 if clear coat is enabled
|
||||
// modify base layer's normal incidence reflectance
|
||||
// for the derivation of the following equation please refer to:
|
||||
// https://google.github.io/filament/Filament.md.html#materialsystem/clearcoatmodel/baselayermodification
|
||||
float3 f0 = (1.0 - 5.0 * sqrt(surface.specularF0)) / (5.0 - sqrt(surface.specularF0));
|
||||
surface.specularF0 = lerp(surface.specularF0, f0 * f0, surface.clearCoat.factor);
|
||||
}
|
||||
|
||||
surfaceSettings.opacityAffectsSpecularFactor = MaterialSrg::m_opacityAffectsSpecularFactor;
|
||||
}
|
||||
@ -0,0 +1,95 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project.
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include <Atom/Features/PBR/Surfaces/StandardSurface.azsli>
|
||||
#include <Atom/Features/MatrixUtility.azsli>
|
||||
|
||||
void EvaluateStandardSurface(
|
||||
float3 normal,
|
||||
float2 uv[UvSetCount],
|
||||
float3 tangents[UvSetCount],
|
||||
float3 bitangents[UvSetCount],
|
||||
bool isFrontFace,
|
||||
bool displacementIsClipped,
|
||||
inout Surface surface,
|
||||
out SurfaceSettings surfaceSettings)
|
||||
{
|
||||
// ------- Normal -------
|
||||
|
||||
float2 normalUv = uv[MaterialSrg::m_normalMapUvIndex];
|
||||
float3x3 uvMatrix = MaterialSrg::m_normalMapUvIndex == 0 ? MaterialSrg::m_uvMatrix : CreateIdentity3x3(); // By design, only UV0 is allowed to apply transforms.
|
||||
surface.normal = GetNormalInputWS(MaterialSrg::m_normalMap, MaterialSrg::m_sampler, normalUv, MaterialSrg::m_flipNormalX, MaterialSrg::m_flipNormalY, isFrontFace, normal,
|
||||
tangents[MaterialSrg::m_normalMapUvIndex], bitangents[MaterialSrg::m_normalMapUvIndex], uvMatrix, o_normal_useTexture, MaterialSrg::m_normalFactor);
|
||||
|
||||
// ------- Base Color -------
|
||||
|
||||
float2 baseColorUv = uv[MaterialSrg::m_baseColorMapUvIndex];
|
||||
float3 sampledColor = GetBaseColorInput(MaterialSrg::m_baseColorMap, MaterialSrg::m_sampler, baseColorUv, MaterialSrg::m_baseColor.rgb, o_baseColor_useTexture);
|
||||
float3 baseColor = BlendBaseColor(sampledColor, MaterialSrg::m_baseColor.rgb, MaterialSrg::m_baseColorFactor, o_baseColorTextureBlendMode, o_baseColor_useTexture);
|
||||
|
||||
if(o_parallax_highlightClipping && displacementIsClipped)
|
||||
{
|
||||
ApplyParallaxClippingHighlight(baseColor);
|
||||
}
|
||||
|
||||
// ------- Metallic -------
|
||||
|
||||
float2 metallicUv = uv[MaterialSrg::m_metallicMapUvIndex];
|
||||
float metallic = GetMetallicInput(MaterialSrg::m_metallicMap, MaterialSrg::m_sampler, metallicUv, MaterialSrg::m_metallicFactor, o_metallic_useTexture);
|
||||
|
||||
// ------- Specular -------
|
||||
|
||||
float2 specularUv = uv[MaterialSrg::m_specularF0MapUvIndex];
|
||||
float specularF0Factor = GetSpecularInput(MaterialSrg::m_specularF0Map, MaterialSrg::m_sampler, specularUv, MaterialSrg::m_specularF0Factor, o_specularF0_useTexture);
|
||||
|
||||
surface.SetAlbedoAndSpecularF0(baseColor, specularF0Factor, metallic);
|
||||
|
||||
// ------- Roughness -------
|
||||
|
||||
float2 roughnessUv = uv[MaterialSrg::m_roughnessMapUvIndex];
|
||||
surface.roughnessLinear = GetRoughnessInput(MaterialSrg::m_roughnessMap, MaterialSrg::m_sampler, roughnessUv, MaterialSrg::m_roughnessFactor,
|
||||
MaterialSrg::m_roughnessLowerBound, MaterialSrg::m_roughnessUpperBound, o_roughness_useTexture);
|
||||
surface.CalculateRoughnessA();
|
||||
|
||||
// ------- Emissive -------
|
||||
|
||||
float2 emissiveUv = uv[MaterialSrg::m_emissiveMapUvIndex];
|
||||
surface.emissiveLighting = GetEmissiveInput(MaterialSrg::m_emissiveMap, MaterialSrg::m_sampler, emissiveUv, MaterialSrg::m_emissiveIntensity, MaterialSrg::m_emissiveColor.rgb, o_emissiveEnabled, o_emissive_useTexture);
|
||||
|
||||
// ------- Occlusion -------
|
||||
|
||||
surface.diffuseAmbientOcclusion = GetOcclusionInput(MaterialSrg::m_diffuseOcclusionMap, MaterialSrg::m_sampler, uv[MaterialSrg::m_diffuseOcclusionMapUvIndex], MaterialSrg::m_diffuseOcclusionFactor, o_diffuseOcclusion_useTexture);
|
||||
surface.specularOcclusion = GetOcclusionInput(MaterialSrg::m_specularOcclusionMap, MaterialSrg::m_sampler, uv[MaterialSrg::m_specularOcclusionMapUvIndex], MaterialSrg::m_specularOcclusionFactor, o_specularOcclusion_useTexture);
|
||||
|
||||
// ------- Clearcoat -------
|
||||
|
||||
// [GFX TODO][ATOM-14603]: Clean up the double uses of these clear coat flags
|
||||
if(o_clearCoat_feature_enabled)
|
||||
{
|
||||
if(o_clearCoat_enabled)
|
||||
{
|
||||
float3x3 uvMatrix = MaterialSrg::m_clearCoatNormalMapUvIndex == 0 ? MaterialSrg::m_uvMatrix : CreateIdentity3x3();
|
||||
GetClearCoatInputs(MaterialSrg::m_clearCoatInfluenceMap, uv[MaterialSrg::m_clearCoatInfluenceMapUvIndex], MaterialSrg::m_clearCoatFactor, o_clearCoat_factor_useTexture,
|
||||
MaterialSrg::m_clearCoatRoughnessMap, uv[MaterialSrg::m_clearCoatRoughnessMapUvIndex], MaterialSrg::m_clearCoatRoughness, o_clearCoat_roughness_useTexture,
|
||||
MaterialSrg::m_clearCoatNormalMap, uv[MaterialSrg::m_clearCoatNormalMapUvIndex], normal, o_clearCoat_normal_useTexture, MaterialSrg::m_clearCoatNormalStrength,
|
||||
uvMatrix, tangents[MaterialSrg::m_clearCoatNormalMapUvIndex], bitangents[MaterialSrg::m_clearCoatNormalMapUvIndex],
|
||||
MaterialSrg::m_sampler, isFrontFace,
|
||||
surface.clearCoat.factor, surface.clearCoat.roughness, surface.clearCoat.normal);
|
||||
}
|
||||
|
||||
// manipulate base layer f0 if clear coat is enabled
|
||||
// modify base layer's normal incidence reflectance
|
||||
// for the derivation of the following equation please refer to:
|
||||
// https://google.github.io/filament/Filament.md.html#materialsystem/clearcoatmodel/baselayermodification
|
||||
float3 f0 = (1.0 - 5.0 * sqrt(surface.specularF0)) / (5.0 - sqrt(surface.specularF0));
|
||||
surface.specularF0 = lerp(surface.specularF0, f0 * f0, surface.clearCoat.factor);
|
||||
}
|
||||
|
||||
// ------- Opacity -------
|
||||
surfaceSettings.opacityAffectsSpecularFactor = MaterialSrg::m_opacityAffectsSpecularFactor;
|
||||
}
|
||||
@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project.
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
// The built-in tangent frame evaluation forwards the tangent frame interpolanted from the vertex
|
||||
// data streams for UV-index 0. For UV-index 1, the tangent frame is computed from UV surface gradients.
|
||||
void EvaluateTangentFrame(
|
||||
float3 normal,
|
||||
float3 worldPosition,
|
||||
bool isFrontFace,
|
||||
float2 uv,
|
||||
int uvIndex,
|
||||
// The input tangent and bitangent vectors are optional and used to forward data from interpolants
|
||||
float3 IN_tangent,
|
||||
float3 IN_bitangent,
|
||||
out float3 OUT_tangent,
|
||||
out float3 OUT_bitangent)
|
||||
{
|
||||
if (DrawSrg::GetTangentAtUv(uvIndex) == 0)
|
||||
{
|
||||
OUT_tangent = IN_tangent;
|
||||
OUT_bitangent = IN_bitangent;
|
||||
}
|
||||
else
|
||||
{
|
||||
SurfaceGradientNormalMapping_Init(normal, worldPosition, !isFrontFace);
|
||||
SurfaceGradientNormalMapping_GenerateTB(uv, OUT_tangent, OUT_bitangent);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project.
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include <Atom/Features/ParallaxMapping.azsli>
|
||||
#include "../MaterialInputs/ParallaxInput.azsli"
|
||||
#include <Atom/Features/MatrixUtility.azsli>
|
||||
|
||||
void MultilayerSetPixelDepth(
|
||||
float3 blendMask,
|
||||
float3 worldPosition,
|
||||
float3 normal,
|
||||
float3 tangents[UvSetCount],
|
||||
float3 bitangents[UvSetCount],
|
||||
float2 uvs[UvSetCount],
|
||||
bool isFrontFace,
|
||||
out float depth)
|
||||
{
|
||||
s_blendMaskFromVertexStream = blendMask;
|
||||
|
||||
float3x3 uvMatrix = MaterialSrg::m_parallaxUvIndex == 0 ? MaterialSrg::m_uvMatrix : CreateIdentity3x3();
|
||||
float3x3 uvMatrixInverse = MaterialSrg::m_parallaxUvIndex == 0 ? MaterialSrg::m_uvMatrixInverse : CreateIdentity3x3();
|
||||
|
||||
float parallaxOverallOffset = MaterialSrg::m_displacementMax;
|
||||
float parallaxOverallFactor = MaterialSrg::m_displacementMax - MaterialSrg::m_displacementMin;
|
||||
GetParallaxInput(
|
||||
normal, tangents[MaterialSrg::m_parallaxUvIndex], bitangents[MaterialSrg::m_parallaxUvIndex],
|
||||
parallaxOverallFactor, parallaxOverallOffset,
|
||||
ObjectSrg::GetWorldMatrix(), uvMatrix, uvMatrixInverse,
|
||||
uvs[MaterialSrg::m_parallaxUvIndex], worldPosition, depth);
|
||||
}
|
||||
@ -0,0 +1,51 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project.
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include <Atom/Features/ParallaxMapping.azsli>
|
||||
#include "../MaterialInputs/ParallaxInput.azsli"
|
||||
#include <Atom/Features/MatrixUtility.azsli>
|
||||
|
||||
void SetPixelDepth(
|
||||
inout float3 worldPosition,
|
||||
float3 normal,
|
||||
float3 tangents[UvSetCount],
|
||||
float3 bitangents[UvSetCount],
|
||||
inout float2 uvs[UvSetCount],
|
||||
bool isFrontFace,
|
||||
inout float depthNDC)
|
||||
{
|
||||
float3x3 uvMatrix = MaterialSrg::m_parallaxUvIndex == 0 ? MaterialSrg::m_uvMatrix : CreateIdentity3x3();
|
||||
float3x3 uvMatrixInverse = MaterialSrg::m_parallaxUvIndex == 0 ? MaterialSrg::m_uvMatrixInverse : CreateIdentity3x3();
|
||||
|
||||
GetParallaxInput(
|
||||
normal, tangents[MaterialSrg::m_parallaxUvIndex], bitangents[MaterialSrg::m_parallaxUvIndex],
|
||||
MaterialSrg::m_heightmapScale, MaterialSrg::m_heightmapOffset,
|
||||
ObjectSrg::GetWorldMatrix(), uvMatrix, uvMatrixInverse,
|
||||
uvs[MaterialSrg::m_parallaxUvIndex], worldPosition, depthNDC);
|
||||
}
|
||||
|
||||
void SetPixelDepth(
|
||||
inout float3 worldPosition,
|
||||
float3 normal,
|
||||
float3 tangents[UvSetCount],
|
||||
float3 bitangents[UvSetCount],
|
||||
inout float2 uvs[UvSetCount],
|
||||
bool isFrontFace,
|
||||
inout float depthCS,
|
||||
inout float depthNDC,
|
||||
out bool isClipped)
|
||||
{
|
||||
float3x3 uvMatrix = MaterialSrg::m_parallaxUvIndex == 0 ? MaterialSrg::m_uvMatrix : CreateIdentity3x3();
|
||||
float3x3 uvMatrixInverse = MaterialSrg::m_parallaxUvIndex == 0 ? MaterialSrg::m_uvMatrixInverse : CreateIdentity3x3();
|
||||
|
||||
GetParallaxInput(
|
||||
normal, tangents[MaterialSrg::m_parallaxUvIndex], bitangents[MaterialSrg::m_parallaxUvIndex],
|
||||
MaterialSrg::m_heightmapScale, MaterialSrg::m_heightmapOffset,
|
||||
ObjectSrg::GetWorldMatrix(), uvMatrix, uvMatrixInverse,
|
||||
uvs[MaterialSrg::m_parallaxUvIndex], worldPosition, depthNDC, depthCS, isClipped);
|
||||
}
|
||||
@ -0,0 +1,19 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project.
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include "../MaterialInputs/AlphaInput.azsli"
|
||||
|
||||
float GetAlphaAndClip(float2 uvs[UvSetCount])
|
||||
{
|
||||
// Alpha
|
||||
float2 baseColorUV = uvs[MaterialSrg::m_baseColorMapUvIndex];
|
||||
float2 opacityUV = uvs[MaterialSrg::m_opacityMapUvIndex];
|
||||
float alpha = SampleAlpha(MaterialSrg::m_baseColorMap, MaterialSrg::m_opacityMap, baseColorUV, opacityUV, MaterialSrg::m_sampler, o_opacity_source);
|
||||
CheckClipping(alpha, MaterialSrg::m_opacityFactor);
|
||||
return MaterialSrg::m_opacityFactor * alpha;
|
||||
}
|
||||
@ -0,0 +1,12 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project.
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
float4x4 GetObjectToWorld()
|
||||
{
|
||||
return ObjectSrg::GetWorldMatrix();
|
||||
}
|
||||
@ -0,0 +1,18 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project.
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
void TransformDetailUvs(in float2 IN[UvSetCount], out float2 OUT[UvSetCount])
|
||||
{
|
||||
// Our standard practice is to only transform the first UV as that's the one we expect to be used for
|
||||
// tiling. But for detail maps you could actually use either UV stream for tiling. There is no concern about applying
|
||||
// the same transform to both UV sets because the detail map feature forces the same UV set to be used for all detail maps.
|
||||
// Note we might be able to combine these into a single UV similar to what Skin.materialtype does,
|
||||
// but we would need to address how it works with the parallax code below that indexes into the m_detailUV array.
|
||||
OUT[0] = mul(MaterialSrg::m_detailUvMatrix, float3(IN[0], 1.0)).xy;
|
||||
OUT[1] = mul(MaterialSrg::m_detailUvMatrix, float3(IN[1], 1.0)).xy;
|
||||
}
|
||||
@ -0,0 +1,14 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project.
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
void TransformUvs(in float2 IN[UvSetCount], out float2 OUT[UvSetCount])
|
||||
{
|
||||
// By design, only UV0 is allowed to apply transforms.
|
||||
OUT[0] = mul(MaterialSrg::m_uvMatrix, float3(IN[0], 1.0)).xy;
|
||||
OUT[1] = IN[1];
|
||||
}
|
||||
@ -0,0 +1,98 @@
|
||||
# Upcoming material system changes
|
||||
|
||||
Currently, `.materialtype` files specify a set of shaders for each pass in the rendering pipeline.
|
||||
For example, the `StandardPBR.materialtype` asset specifies the following shaders:
|
||||
|
||||
```json
|
||||
[
|
||||
{
|
||||
"file": "./StandardPBR_ForwardPass.shader",
|
||||
"tag": "ForwardPass"
|
||||
},
|
||||
{
|
||||
"file": "./StandardPBR_ForwardPass_EDS.shader",
|
||||
"tag": "ForwardPass_EDS"
|
||||
},
|
||||
{
|
||||
"file": "./StandardPBR_LowEndForward.shader",
|
||||
"tag": "LowEndForward"
|
||||
},
|
||||
{
|
||||
"file": "./StandardPBR_LowEndForward_EDS.shader",
|
||||
"tag": "LowEndForward_EDS"
|
||||
},
|
||||
{
|
||||
"file": "Shaders/Shadow/Shadowmap.shader",
|
||||
"tag": "Shadowmap"
|
||||
},
|
||||
{
|
||||
"file": "./StandardPBR_Shadowmap_WithPS.shader",
|
||||
"tag": "Shadowmap_WithPS"
|
||||
},
|
||||
{
|
||||
"file": "Shaders/Depth/DepthPass.shader",
|
||||
"tag": "DepthPass"
|
||||
},
|
||||
{
|
||||
"file": "./StandardPBR_DepthPass_WithPS.shader",
|
||||
"tag": "DepthPass_WithPS"
|
||||
},
|
||||
{
|
||||
"file": "Shaders/MotionVector/MeshMotionVector.shader",
|
||||
"tag": "MeshMotionVector"
|
||||
},
|
||||
{
|
||||
"file": "Shaders/Depth/DepthPassTransparentMin.shader",
|
||||
"tag": "DepthPassTransparentMin"
|
||||
},
|
||||
{
|
||||
"file": "Shaders/Depth/DepthPassTransparentMax.shader",
|
||||
"tag": "DepthPassTransparentMax"
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
**This will be changing in a future release** to a material type description that specifies shader snippets (aka material functions)
|
||||
instead of explicit shaders.
|
||||
|
||||
## Why is it changing?
|
||||
|
||||
There are two primary reasons to move to a different scheme.
|
||||
|
||||
1. Material types are strongly coupled to the rendering pipeline. If a user wants to change the pipeline, or the engine wants to use, for example, a custom pipeline for mobile, or VR, this isn't possible today without cloning existing material types and changing the shader array.
|
||||
2. The material canvas work that has been prioritized to allow artist-driven material customization benefits from a more modular construction of materials. For example, we'd like to apply a "wind graph" and mix and match that with a "foliage graph" to describe the appearance of some foliage. The current material type description couples all the geometric passes with the material and lighting passes, which makes this sort of decomposition difficult.
|
||||
|
||||
## What is it changing to?
|
||||
|
||||
The best way to understand how this is changing is to inspect the current structure of `EnhancedPBR_ForwardPass.azsl` and `StandardPBR_ForwardPass.azsl`.
|
||||
These shaders start with a number of includes to specify the SRG as follows:
|
||||
|
||||
```hlsl
|
||||
#include "StandardPBR_Common.azsli"
|
||||
#include <Atom/Features/PBR/DefaultObjectSrg.azsli>
|
||||
```
|
||||
|
||||
Later, it includes a number of material functions, for example:
|
||||
|
||||
```hlsl
|
||||
#include "MaterialFunctions/EvaluateStandardSurface.azsli"
|
||||
#include "MaterialFunctions/EvaluateTangentFrame.azsli"
|
||||
#include "MaterialFunctions/ParallaxDepth.azsli"
|
||||
#include "MaterialFunctions/StandardGetNormalToWorld.azsli"
|
||||
#include "MaterialFunctions/StandardGetObjectToWorld.azsli"
|
||||
#include "MaterialFunctions/StandardGetAlphaAndClip.azsli"
|
||||
#include "MaterialFunctions/StandardTransformUvs.azsli"
|
||||
```
|
||||
|
||||
The material function headers define functions that may later be overridden using material graphs.
|
||||
|
||||
Finally, in the case of the standard surface shader, it includes an implementation file:
|
||||
|
||||
```hlsl
|
||||
#include "StandardSurface_ForwardPass.azsli"
|
||||
```
|
||||
|
||||
This file, if you inspect it, _makes no reference to `MaterialSrg`_, and furthermore, does not include files needed to implement any of the material functions.
|
||||
In other words, the structure of the standard pbr forward shader is such that it can be assembled with different components, specifing the SRG, material functions, and implementation.
|
||||
|
||||
In the future, a material pipeline abstraction will allow the `materialtype` asset to specify _only_ the material function files, and the tuple of `materialtype` and `materialpipeline` will allow the material builder to assemble the shader on behalf of the user. The final piece to the puzzle is that (again, in the future), material canvas (in active development) can produce material functions to replace the built-in ones.
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue