Files
test/source/blender/draw/engines/gpencil/shaders/gpencil_frag.glsl
Clément Foucault fe213f80a4 GPU: Shader: Make info files generated
This is the first step of moving the create infos
back inside shader sources.

All info files are now treated as source files.
However, they are not considered in the include tree
yet. This will come in another following PR.

Each shader source file now generate a `.info` file
containing only the create info declarations.

This renames all info files so that they do not
conflict with their previous versions that were
copied (non-generated).

Pull Request: https://projects.blender.org/blender/blender/pulls/146676
2025-09-25 10:57:02 +02:00

140 lines
5.0 KiB
GLSL

/* SPDX-FileCopyrightText: 2020-2023 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
#include "infos/gpencil_infos.hh"
FRAGMENT_SHADER_CREATE_INFO(gpencil_geometry)
#include "draw_colormanagement_lib.glsl"
#include "draw_grease_pencil_lib.glsl"
#include "gpu_shader_math_vector_lib.glsl"
float3 gpencil_lighting()
{
float3 light_accum = float3(0.0f);
for (int i = 0; i < GPENCIL_LIGHT_BUFFER_LEN; i++) {
if (float3(gp_lights[i]._color).x == -1.0f) {
break;
}
float3 L = gp_lights[i]._position - gp_interp.pos;
float vis = 1.0f;
gpLightType type = gpLightType(floatBitsToUint(gp_lights[i]._type));
/* Spot Attenuation. */
if (type == GP_LIGHT_TYPE_SPOT) {
float3x3 rot_scale = float3x3(gp_lights[i]._right, gp_lights[i]._up, gp_lights[i]._forward);
float3 local_L = rot_scale * L;
local_L /= abs(local_L.z);
float ellipse = inversesqrt(length_squared(local_L));
vis *= smoothstep(
0.0f, 1.0f, (ellipse - gp_lights[i]._spot_size) / gp_lights[i]._spot_blend);
/* Also mask +Z cone. */
vis *= step(0.0f, local_L.z);
}
/* Inverse square decay. Skip for suns. */
float L_len_sqr = length_squared(L);
if (type < GP_LIGHT_TYPE_SUN) {
vis /= L_len_sqr;
}
else {
L = gp_lights[i]._forward;
L_len_sqr = 1.0f;
}
/* Lambertian falloff */
if (type != GP_LIGHT_TYPE_AMBIENT) {
L /= sqrt(L_len_sqr);
vis *= clamp(dot(gp_normal, L), 0.0f, 1.0f);
}
light_accum += vis * gp_lights[i]._color;
}
/* Clamp to avoid NaNs. */
return clamp(light_accum, 0.0f, 1e10f);
}
void main()
{
float4 col;
if (flag_test(gp_interp_flat.mat_flag, GP_STROKE_TEXTURE_USE)) {
bool premul = flag_test(gp_interp_flat.mat_flag, GP_STROKE_TEXTURE_PREMUL);
col = texture_read_as_linearrgb(gp_stroke_tx, premul, gp_interp.uv);
}
else if (flag_test(gp_interp_flat.mat_flag, GP_FILL_TEXTURE_USE)) {
bool use_clip = flag_test(gp_interp_flat.mat_flag, GP_FILL_TEXTURE_CLIP);
float2 uvs = (use_clip) ? clamp(gp_interp.uv, 0.0f, 1.0f) : gp_interp.uv;
bool premul = flag_test(gp_interp_flat.mat_flag, GP_FILL_TEXTURE_PREMUL);
col = texture_read_as_linearrgb(gp_fill_tx, premul, uvs);
}
else if (flag_test(gp_interp_flat.mat_flag, GP_FILL_GRADIENT_USE)) {
bool radial = flag_test(gp_interp_flat.mat_flag, GP_FILL_GRADIENT_RADIAL);
float fac = clamp(radial ? length(gp_interp.uv * 2.0f - 1.0f) : gp_interp.uv.x, 0.0f, 1.0f);
uint matid = gp_interp_flat.mat_flag >> GPENCIl_MATID_SHIFT;
col = mix(gp_materials[matid].fill_color, gp_materials[matid].fill_mix_color, fac);
}
else /* SOLID */ {
col = float4(1.0f);
}
col.rgb *= col.a;
/* Composite all other colors on top of texture color.
* Everything is pre-multiply by `col.a` to have the stencil effect. */
frag_color = col * gp_interp.color_mul + col.a * gp_interp.color_add;
frag_color.rgb *= gpencil_lighting();
frag_color *= gpencil_stroke_round_cap_mask(gp_interp_flat.sspos.xy,
gp_interp_flat.sspos.zw,
gp_interp_flat.aspect,
gp_interp_noperspective.thickness.x,
gp_interp_noperspective.hardness);
/* To avoid aliasing artifacts, we reduce the opacity of small strokes. */
frag_color *= smoothstep(0.0f, 1.0f, gp_interp_noperspective.thickness.y);
/* Holdout materials. */
if (flag_test(gp_interp_flat.mat_flag, GP_STROKE_HOLDOUT | GP_FILL_HOLDOUT)) {
revealColor = frag_color.aaaa;
}
else {
/* NOT holdout materials.
* 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 = float4(0.0f, 0.0f, 0.0f, frag_color.a);
if (frag_color.a < 0.001f) {
gpu_discard_fragment();
return;
}
}
float2 fb_size = max(float2(textureSize(gp_scene_depth_tx, 0).xy),
float2(textureSize(gp_mask_tx, 0).xy));
float2 uvs = gl_FragCoord.xy / fb_size;
/* Manual depth test */
float scene_depth = texture(gp_scene_depth_tx, uvs).r;
if (gl_FragCoord.z > scene_depth) {
gpu_discard_fragment();
return;
}
/* FIXME(fclem): Grrr. This is bad for performance but it's the easiest way to not get
* depth written where the mask obliterate the layer. */
float mask = texture(gp_mask_tx, uvs).r;
if (mask < 0.001f) {
gpu_discard_fragment();
return;
}
/* 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 (gp_interp_flat.depth >= 0.0f) {
gl_FragDepth = gp_interp_flat.depth;
}
else {
gl_FragDepth = gl_FragCoord.z;
}
}