summaryrefslogtreecommitdiffstats
path: root/yum_pbr.cginc
blob: c3f5c4a1f38729731e830e40446a74b5439760bd (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
#ifndef __YUM_PBR
#define __YUM_PBR

#include "cnlohr.cginc"
#include "decals.cginc"
#include "features.cginc"
#include "filamented.cginc"
#include "glitter.cginc"
#include "globals.cginc"
#include "math.cginc"
#include "texture_utils.cginc"

struct YumPbr {
  float4 albedo;
  float3 normal;
#if defined(_EMISSION) || (defined(_GLITTER) && (defined(FORWARD_BASE_PASS) || defined(FORWARD_ADD_PASS))) || defined(OUTLINE_PASS)
  float3 emission;
#endif
  float smoothness;
  float roughness;
  float roughness_perceptual;
  float metallic;
  float ao;
};

void propagateRoughness(in float smoothness, out float roughness_perceptual, out float roughness) {
  roughness_perceptual = normalFiltering(1.0 - smoothness, float3(0, 0, 1));
  roughness = roughness_perceptual * roughness_perceptual;
}

YumPbr GetYumPbr(v2f i, float3x3 tangentToWorld) {
  YumPbr result;

  float2 raw_uv = i.uv01.xy;
#if defined(_UV_DOMAIN_WARPING)
  {
    float2 warped_uv = raw_uv;
    float amplitude = _UV_Domain_Warping_Spatial_Strength;
    float frequency = _UV_Domain_Warping_Spatial_Scale;

    float2 speed_direction = _UV_Domain_Warping_Spatial_Direction;
    float2 time_offset = speed_direction * _Time.y * _UV_Domain_Warping_Spatial_Speed;

    const float lacunarity = 2.0;
    const float persistence = 0.5;

    [loop]
    for (uint ii = 0; ii < _UV_Domain_Warping_Spatial_Octaves; ii++) {
      float2 noise_uv = warped_uv * frequency + time_offset;
      float2 offset_sample = _UV_Domain_Warping_Noise.SampleLevel(trilinear_repeat_s, noise_uv, 0).rg;
      offset_sample = (offset_sample * 2.0 - 1.0);
      warped_uv += offset_sample * amplitude;
      frequency *= lacunarity;
      amplitude *= persistence;
    }
    i.uv01.xy = warped_uv;
  }
#endif

#if defined(OUTLINE_PASS)
  result.albedo = _Outline_Color;
  result.albedo.a *= tex2D(_MainTex,
      UV_SCOFF(i, _MainTex_ST, /*which_channel=*/0)).a;
#else
  result.albedo = tex2D(_MainTex,
      UV_SCOFF(i, _MainTex_ST, /*which_channel=*/0)) * _Color;
#endif

#if defined(_3D_SDF)
  {
    float2 sdf_uv_raw = get_uv_by_channel(i, _3D_SDF_UV_Channel);
    float3 sdf_uv = float3(sdf_uv_raw, _3D_SDF_Z + _Time.y * _3D_SDF_Z_Speed);
    sdf_uv.xy = saturate((sdf_uv.xy - (_3D_SDF_ST.zw + 0.5)) * _3D_SDF_ST.xy + (_3D_SDF_ST.zw + 0.5));
    float sdf_value = _3D_SDF_Texture.SampleLevel(trilinear_repeat_s, sdf_uv, 0).r;
    float eps = 1E-4;
    float4 is_lit = sdf_value < _3D_SDF_Thresholds && sdf_uv.x > eps && sdf_uv.x < 1 - eps && sdf_uv.y > eps && sdf_uv.y < 1 - eps;
    float4 skin_albedo = result.albedo;
    result.albedo.rgb = lerp(result.albedo.rgb, lerp(skin_albedo.rgb, _3D_SDF_Color_3.rgb, _3D_SDF_Color_3.a), is_lit.w);
    result.albedo.rgb = lerp(result.albedo.rgb, lerp(skin_albedo.rgb, _3D_SDF_Color_2.rgb, _3D_SDF_Color_2.a), is_lit.z);
    result.albedo.rgb = lerp(result.albedo.rgb, lerp(skin_albedo.rgb, _3D_SDF_Color_1.rgb, _3D_SDF_Color_1.a), is_lit.y);
    result.albedo.rgb = lerp(result.albedo.rgb, lerp(skin_albedo.rgb, _3D_SDF_Color_0.rgb, _3D_SDF_Color_0.a), is_lit.x);
  }
#endif

  float3 normal_tangent = UnpackScaleNormal(
      tex2D(_BumpMap, UV_SCOFF_IMPL(raw_uv, _BumpMap_ST)), _BumpScale);

#if defined(_DETAIL_MAPS)
  float detail_mask = _DetailMask.SampleLevel(point_repeat_s, i.uv01.xy, 0);
  float4 detail_albedo = tex2D(_DetailAlbedoMap,
      UV_SCOFF_IMPL(raw_uv, _DetailNormalMap_ST));
  float3 detail_normal = UnpackScaleNormal(
      tex2D(_DetailNormalMap,
          UV_SCOFF_IMPL(raw_uv, _DetailNormalMap_ST)),
      _DetailNormalMapScale);
  result.albedo = lerp(result.albedo, result.albedo * detail_albedo, detail_mask);
  //result.albedo.a *= detail_albedo.a;
  normal_tangent = lerp(normal_tangent, blendNormalsHill12(normal_tangent, detail_normal), detail_mask);
#endif

#if defined(_ALPHA_MULTIPLIER)
  result.albedo.a = saturate(result.albedo.a * _Alpha_Multiplier);
#endif

#if defined(_EMISSION)
  result.emission = tex2D(_EmissionMap, UV_SCOFF(i, _EmissionMap_ST, /*which_channel=*/0)) * _EmissionColor;
#endif
#if defined(OUTLINE_PASS)
#if defined(_EMISSION)
  result.emission += _Outline_Color * _Outline_Emission;
#else
  result.emission = _Outline_Color * _Outline_Emission;
#endif
#endif

#if defined(_METALLICS)
  float4 metallic_gloss = tex2D(_MetallicGlossMap, UV_SCOFF(i, _MetallicGlossMap_ST, /*which_channel=*/0));
  float metallic = metallic_gloss.r * _Metallic;
  float smoothness = metallic_gloss.a * _Smoothness;

  result.smoothness = smoothness;
  result.metallic = metallic;
#else
  result.smoothness = 0.2;
  result.metallic = 0;
#endif

#if defined(_AMBIENT_OCCLUSION)
  result.ao = lerp(1, tex2D(_OcclusionMap, i.uv01), _OcclusionStrength);
#else
  result.ao = 1;
#endif

  applyDecals(i, result.albedo, normal_tangent, result.metallic, result.smoothness);
  propagateRoughness(result.smoothness, result.roughness_perceptual, result.roughness);

  result.normal = normalize(mul(normal_tangent, tangentToWorld));

#if (defined(FORWARD_BASE_PASS) || defined(FORWARD_ADD_PASS)) && defined(_GLITTER)
  GlitterParams glitter_p;
  glitter_p.color = _Glitter_Color;
  glitter_p.layers = _Glitter_Layers;
  glitter_p.cell_size = _Glitter_Grid_Size;
  glitter_p.size = _Glitter_Size;
  glitter_p.major_minor_ratio = _Glitter_Major_Minor_Ratio;
  glitter_p.angle_randomization_range = _Glitter_Angle_Randomization_Range;
  glitter_p.center_randomization_range = _Glitter_Center_Randomization_Range;
  glitter_p.size_randomization_range = _Glitter_Size_Randomization_Range;
  glitter_p.existence_chance = _Glitter_Existence_Chance;
#if defined(_GLITTER_ANGLE_LIMIT)
  glitter_p.angle_limit = _Glitter_Angle_Limit;
  glitter_p.angle_limit_transition_width = _Glitter_Angle_Limit_Transition_Width;
#endif
#if defined(_GLITTER_MASK)
  glitter_p.mask = _Glitter_Mask.SampleLevel(linear_repeat_s, i.uv01.xy, 0);
#endif
  float4 glitter_albedo = getGlitter(i, glitter_p, result.normal);
  result.albedo = alphaBlend(result.albedo, glitter_albedo);

  float3 gitter_emission = glitter_albedo.rgb * glitter_albedo.a * _Glitter_Emission;
#if defined(_EMISSION)
  result.emission += gitter_emission;
#else
  result.emission = gitter_emission;
#endif
#endif

  return result;
}

#endif