; --
; Material library for interior shaders, compatible with some original shaders.
; In first half of this file, you can see available templates and parameters for them.
; --

; Base PBR parameters, available to all of these PBR shaders.
[TEMPLATE: _Base_Material_PBR]
F0 = 0.04                ; base reflectivity for non-metal materials with metalness workflow
Emissive = 0, 0, 0       ; emissive value
AlbedoGain = 1, 1, 1     ; RGB multiplier for albedo texture
BlurCubemap = 0          ; forcefully blur cubemap (use it to reduce details in reflections in areas where cubemap does not fit well)

; Flags:
SpecularWorkflow = 0       ; by default metalness workflow is used, set this to 1 to switch to specular (or set optional TextureSpecular value for materials that support it)
ApplyTilingFix = 0         ; apply tiling fix (not available with parallax)
SceneryAO = 0              ; set to 1 if you for some reason have non-material AO in TextureEmAoMeRo ambient occlusion channel, it would disable micro shadow and AO fresnel
SkipAlbedoForEmissive = 0  ; do not use albedo for emissive color
DXT5NMNormalMap = 1        ; set to 1 if normal map is in DXT5NM format (some texture slots of some materials might not support it, check the comments)

; Optional parallax. To use, set this texture to height map (only for materials that support it):
TextureDisplacement =    ; currently, texture has to be square
DisplacementMax = 50     ; maximum distance at which displacement is active
DisplacementMin = 30     ; minimum distance at which displacement is active
ParallaxScale = 0.02     ; parallax depth
ParallaxSteps = 20       ; maximum number of steps, increase to improve visual quality (expensive)
ParallaxOffset = 0.5     ; what value of displacement texture is considered neutral, 0.5 for gray, 0 for white, 1 for black
ParallaxUVToWorld = 0    ; set to UV-to-world scale value to get parallax offset to shift shadow maps and dynamic lights, works well if the object is mapped evenly
                         ; (possibly a temporal option until I figure out a way to compute that scale live reliably)


; Basic PBR shader with extra variance and scenery AO in UV2 (or, alternatively, using scaled UV1 for PBR textures and unscaled UV1 for variance and scenery AO).
; Scenery AO is AO from object surroundings and its geometry, in other words storing those blurry shadows. Unlike it, PBR AO is highly detailed AO drawn for actual
; material (for example, for a brick wall space between bricks might be darker on AO map).
[TEMPLATE: Material_PBR]
UVScale = 1  ; scale for UV1

; Textures:
TextureAlbedo =      ; albedo map without ambient occlusion
TextureNormal =      ; normal texture, only red and green channels are read (DXT5NM format is supported with “DXT5NMNormalMap” flag)
TextureEmAoMeRo =    ; emissive, ambient, metalness and roughness maps in RGBA channels accordingly (arranged for better visual with DXT5/BC7 compression)¹
TextureSpecular =    ; specular map, used only with specular workflow; if not set, metalness map is used as specular map
TextureVarianceAO =  ; optional albedo variance and additional AO map, uses UV2 (only active when corresponding flags are set)

; Flags:
ApplyAOMap = 0          ; apply extra AO map from TextureVarianceAO
ApplyVarianceMap = 0    ; apply albedo variance map from TextureVarianceAO (applied as multiplier)
UseUnscaledUV1For2 = 0  ; use unscaled UV1 instead of UV2 for txVarianceAO (allows to sort of recreate “ksPerPixelMultiMap_NMDetail” logic)


; Shader acting like Kunos multilayer: txDiffuse (with albedo multipliers), txMask, four layers. Currently doesn’t support parallax.
[TEMPLATE: Material_PBR_Multilayer]
DetailNMMult = 1  ; UV multiplier for normal texture (mapped with UV1)
MultR = 1
MultG = 1
MultB = 1
MultA = 1
MagicMult = 1

; Textures:
TextureAlbedo =     ; same as txDiffuse for Kunos shader, applied as multiplier to albedo, with alpha channel for scenery AO
TextureMask =       ; same as txMask for Kunos shader
TextureNormal =     ; same as txDetailNM for Kunos shader, combined with layer normal maps

TextureRAlbedoAO =  ; layers¹
TextureRNmMeRo =
TextureGAlbedoAO =
TextureGNmMeRo =
TextureBAlbedoAO =
TextureBNmMeRo =
TextureAAlbedoAO =
TextureANmMeRo =

; Each layer needs two textures. First texture should contain albedo map and local AO in alpha channel, and second stores R and G 
; channels of normal map in R and G channels, metalness map in blue channel and roughness in alpha channel. If you’re using 
; SpecularWorkflow flag, put specular map instead of metalness. Note: these textures don’t support DXT5NM format, but BC7 should 
; work well.

TextureDisplacement = ; optional displacement texture for parallax. If MultR/G/B/A values are the same, four channels are used,
                      ; channel for each layer. If they are different, only first two channels are used to keep things faster,
                      ; first channel (red) for layer R and second channel (green) for layer G

; Flags:
NormalizeMask = 1       ; make sure sum of R, G, B and A channels of txMask does not exceed 1 (if disabled, materials might look
                        ; overly bright and broken)
ApplyAOFromDiffuse = 0  ; set to 1 to use alpha of TextureAlbedo as global AO

; --
; ¹ — instead of packing channels in textures in some image editor you can instead simply provide up to four textures and/or solid
;     colors as placeholders. Use X@ prefix if you want to specify which specific channel to take from texture (otherwise, target
;     channel will be taken). Few examples:
;
;     TextureEmAoMeRo = 'color::0,0,0,0', ribbed-chipped-metal_ao.png, G@ribbed-chipped-metal_metallic.png, G@ribbed-chipped-metal_roughness.png
;       ; explicitly take green channel for metalness since it might be compressed better than blue, and also take green channel for roughness
;       ; because otherwise by default alpha would be taken (target channel is alpha).
;
;     TextureRAlbedoAO = RGB@rough-wet-cobble-albedo.png, G@rough-wet-cobble-ao.png
;       ; take RGB channels from albedo texture and green channel from AO texture which will fill alpha channel and act as AO
;
;     TextureANmMeRo = RG@rustediron2_normal.png, G@rustediron2_metallic.png, G@rustediron2_roughness.png
;       ; take RG channels from normal map, green channel from metalness texture to fill blue and green from roughness to fill alpha
;     
;     Note: textures will only be combined once and then cached in “assettocorsa\cache\made_textures”. No compression will be applied. For
;     released versions merging textures into some BC7 compressed textures might be a more optimal option, but this one might be helpful for
;     development.
; --

; --
; Here goes second half, actual implementation of those templates.
; If you want to go futher, here is some documentation for the whole format:
; https://github.com/ac-custom-shaders-patch/inipp
; --

[INCLUDE: materials_base.ini]

[FUNCTION: _Material_PBR_PackTexture]
ARGUMENTS = Channels
CODE = '
  if type(Channels) == "table" then
    local r = "make-rgba::"
    for i, v in ipairs(Channels) do r = r.."<"..v.."> " end
    return r
  else
    return Channels
  end
'

[TEMPLATE: _Base_Material_PBR EXTENDS _Base_Material_Custom]
@OUTPUT = SHADER_REPLACEMENT_...
PROP_0 = pbrF0, $F0
PROP_1 = pbrAlbedoGain, $AlbedoGain
PROP_2 = pbrBlurCubemap, $BlurCubemap
PROP_3 = ksEmissive, $Emissive
PROP_4 = extParallaxScale, $ParallaxScale
PROP_5 = extParallaxSteps, $ParallaxSteps
PROP_6 = extParallaxOffset, $ParallaxOffset
PROP_6 = extParallaxTexToWorld, $ParallaxUVToWorld
PROP_7 = extDisplacementRangeBase, $" $DisplacementMin / ($DisplacementMax - $DisplacementMin) "
PROP_8 = extDisplacementRangeInv, $" -1 / ($DisplacementMax - $DisplacementMin) "

[TEMPLATE: Material_PBR EXTENDS _Base_Material_PBR]
SHADER = $" ${TextureDisplacement:exists} and 'fuPBR_parallax' or 'fuPBR' "
PROP_100 = pbrFlags, $" ( ${SkipAlbedoForEmissive:bool} and 1 or 0 )
  + (( ${SpecularWorkflow:bool} or ${TextureSpecular:exists} ) and 2 or 0 )
  + (( ${Dxt5NmNormalMap:bool} or (${TextureNormal:2:str}):lower() == 'dxt5nm' ) and 4 or 0 )
  + ( ${SceneryAO:bool} and 0 or 8 )
  + ( ${ApplyAOMap:bool} and 256 or 0 )
  + ( ${ApplyVarianceMap:bool} and 512 or 0 )
  + ( ${ApplyTilingFix:bool} and 1024 or 0 )
  + ( ${SpecularWorkflow:bool} and ${TextureSpecular:exists} and 2048 or 0 )
  + ( ${UseUnscaledUV1For2:bool} and 4096 or 0 )"
PROP_101 = uvScale, $UVScale
RESOURCE_0 = txAlbedo, $TextureAlbedo
RESOURCE_1 = txNormal2, ${TextureNormal:1}
RESOURCE_2 = txEmAoMeRo, $" _Material_PBR_PackTexture($TextureEmAoMeRo) "
RESOURCE_3 = txDisplacement, $TextureDisplacement
RESOURCE_4 = txSpecular, $TextureSpecular
RESOURCE_5 = txVarianceAO, $TextureVarianceAO

[TEMPLATE: Material_PBR_Multilayer EXTENDS _Base_Material_PBR]
SHADER = $"( ${TextureDisplacement:exists} 
  and ( ${MultR:number} == ${MultG:number} and ${MultG:number} == ${MultB:number} and ${MultB:number} == ${MultA:number} ) and 'fuPBR_multilayer_parallax4' or 'fuPBR_multilayer_parallax2' )
  or 'fuPBR_multilayer' "
PROP_100 = pbrFlags, $" ( ${SkipAlbedoForEmissive:bool} and 1 or 0 )
  + (( ${SpecularWorkflow:bool} or ${TextureSpecular:exists} ) and 2 or 0 )
  + (( ${Dxt5NmNormalMap:bool} or (${TextureNormal:2:str}):lower() == 'dxt5nm' ) and 4 or 0 )
  + ( ${SceneryAO:bool} and 0 or 8 )
  + ( ${ApplyTilingFix:bool} and 256 or 0 )
  + ( ${NormalizeMask:bool} and 512 or 0 )
  + ( ${ApplyAOFromDiffuse:bool} and 1024 or 0 )"
PROP_101 = detailNMMult, $DetailNMMult
PROP_102 = multR, $MultR
PROP_103 = multG, $MultG
PROP_104 = multB, $MultB
PROP_105 = multA, $MultA
PROP_106 = magicMult, $MagicMult
PROP_107 = _multGR, $" ${MultG:number} / ${MultR:number} "
RESOURCE_0 = txDiffuse, $TextureAlbedo
RESOURCE_1 = txMask, $TextureMask
RESOURCE_2 = txNormal2, $TextureNormal
RESOURCE_3 = txDetailRAlbedoAO, $" _Material_PBR_PackTexture($TextureRAlbedoAO) "
RESOURCE_4 = txDetailRNmMeRo, $" _Material_PBR_PackTexture($TextureRNmMeRo) "
RESOURCE_5 = txDetailGAlbedoAO, $" _Material_PBR_PackTexture($TextureGAlbedoAO) "
RESOURCE_6 = txDetailGNmMeRo, $" _Material_PBR_PackTexture($TextureGNmMeRo) "
RESOURCE_7 = txDetailBAlbedoAO, $" _Material_PBR_PackTexture($TextureBAlbedoAO) "
RESOURCE_8 = txDetailBNmMeRo, $" _Material_PBR_PackTexture($TextureBNmMeRo) "
RESOURCE_9 = txDetailAAlbedoAO, $" _Material_PBR_PackTexture($TextureAAlbedoAO) "
RESOURCE_10 = txDetailANmMeRo, $" _Material_PBR_PackTexture($TextureANmMeRo) "
RESOURCE_11 = txDisplacement, $" _Material_PBR_PackTexture($TextureDisplacement) "
