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
|
uniform sampler2D gpFillTexture;
uniform sampler2D gpStrokeTexture;
uniform sampler2D gpSceneDepthTexture;
uniform vec3 gpNormal;
layout(location = 0) out vec4 fragColor;
layout(location = 1) out vec4 revealColor;
float length_squared(vec2 v)
{
return dot(v, v);
}
float length_squared(vec3 v)
{
return dot(v, v);
}
vec3 gpencil_lighting(void)
{
vec3 light_accum = vec3(0.0);
for (int i = 0; i < GPENCIL_LIGHT_BUFFER_LEN; i++) {
if (lights[i].color_type.x == -1.0) {
break;
}
vec3 L = lights[i].position.xyz - finalPos;
float vis = 1.0;
/* Spot Attenuation. */
if (lights[i].color_type.w == GP_LIGHT_TYPE_SPOT) {
mat3 rot_scale = mat3(lights[i].right.xyz, lights[i].up.xyz, lights[i].forward.xyz);
vec3 local_L = rot_scale * L;
local_L /= abs(local_L.z);
float ellipse = inversesqrt(length_squared(local_L));
vis *= smoothstep(0.0, 1.0, (ellipse - lights[i].spot_size) / lights[i].spot_blend);
/* Also mask +Z cone. */
vis *= step(0.0, local_L.z);
}
/* Inverse square decay. Skip for suns. */
float L_len_sqr = length_squared(L);
if (lights[i].color_type.w < GP_LIGHT_TYPE_SUN) {
vis /= L_len_sqr;
}
else {
L = lights[i].forward.xyz;
L_len_sqr = 1.0;
}
/* Lambertian falloff */
if (lights[i].color_type.w != GP_LIGHT_TYPE_AMBIENT) {
L /= sqrt(L_len_sqr);
vis *= clamp(dot(gpNormal, L), 0.0, 1.0);
}
light_accum += vis * lights[i].color_type.rgb;
}
/* Clamp to avoid NaNs. */
return clamp(light_accum, 0.0, 1e10);
}
void main()
{
vec4 col;
if (GP_FLAG_TEST(matFlag, GP_STROKE_TEXTURE_USE)) {
bool premul = GP_FLAG_TEST(matFlag, GP_STROKE_TEXTURE_PREMUL);
col = texture_read_as_linearrgb(gpStrokeTexture, premul, finalUvs);
}
else if (GP_FLAG_TEST(matFlag, GP_FILL_TEXTURE_USE)) {
bool use_clip = GP_FLAG_TEST(matFlag, GP_FILL_TEXTURE_CLIP);
vec2 uvs = (use_clip) ? clamp(finalUvs, 0.0, 1.0) : finalUvs;
bool premul = GP_FLAG_TEST(matFlag, GP_FILL_TEXTURE_PREMUL);
col = texture_read_as_linearrgb(gpFillTexture, premul, uvs);
}
else if (GP_FLAG_TEST(matFlag, GP_FILL_GRADIENT_USE)) {
bool radial = GP_FLAG_TEST(matFlag, GP_FILL_GRADIENT_RADIAL);
float fac = clamp(radial ? length(finalUvs * 2.0 - 1.0) : finalUvs.x, 0.0, 1.0);
int matid = matFlag >> GP_MATID_SHIFT;
col = mix(MATERIAL(matid).fill_color, MATERIAL(matid).fill_mix_color, fac);
}
else /* SOLID */ {
col = vec4(1.0);
}
col.rgb *= col.a;
/* Composite all other colors on top of texture color.
* Everything is premult by col.a to have the stencil effect. */
fragColor = col * finalColorMul + col.a * finalColorAdd;
fragColor.rgb *= gpencil_lighting();
fragColor *= stroke_round_cap_mask(strokePt1, strokePt2, strokeThickness, strokeHardeness);
/* For compatibility with colored alpha buffer.
* Note that we are limited to mono-chromatic alpha blending here
* because of the blend equation and the limit of 1 color target
* when using custom color blending. */
revealColor = vec4(0.0, 0.0, 0.0, fragColor.a);
if (fragColor.a < 0.001) {
discard;
}
/* Manual depth test */
vec2 uvs = gl_FragCoord.xy / vec2(textureSize(gpSceneDepthTexture, 0).xy);
float scene_depth = texture(gpSceneDepthTexture, uvs).r;
if (gl_FragCoord.z > scene_depth) {
discard;
}
/* We override the fragment depth using the fragment shader to ensure a constant value.
* This has a cost as the depth test cannot happen early.
* We could do this in the vertex shader but then perspective interpolation of uvs and
* fragment clipping gets really complicated. */
if (depth >= 0.0) {
gl_FragDepth = depth;
}
else {
gl_FragDepth = gl_FragCoord.z;
}
}
|