diff options
Diffstat (limited to 'source/blender/draw/engines/gpencil/shaders/gpencil_vfx_frag.glsl')
-rw-r--r-- | source/blender/draw/engines/gpencil/shaders/gpencil_vfx_frag.glsl | 354 |
1 files changed, 354 insertions, 0 deletions
diff --git a/source/blender/draw/engines/gpencil/shaders/gpencil_vfx_frag.glsl b/source/blender/draw/engines/gpencil/shaders/gpencil_vfx_frag.glsl new file mode 100644 index 00000000000..503248558ad --- /dev/null +++ b/source/blender/draw/engines/gpencil/shaders/gpencil_vfx_frag.glsl @@ -0,0 +1,354 @@ + +uniform sampler2D colorBuf; +uniform sampler2D revealBuf; + +in vec4 uvcoordsvar; + +/* Reminder: This is considered SRC color in blend equations. + * Same operation on all buffers. */ +layout(location = 0) out vec4 fragColor; +layout(location = 1) out vec4 fragRevealage; + +float gaussian_weight(float x) +{ + return exp(-x * x / (2.0 * 0.35 * 0.35)); +} + +#if defined(COMPOSITE) + +uniform bool isFirstPass; + +void main() +{ + if (isFirstPass) { + /* Blend mode is multiply. */ + fragColor.rgb = fragRevealage.rgb = texture(revealBuf, uvcoordsvar.xy).rgb; + fragColor.a = fragRevealage.a = 1.0; + } + else { + /* Blend mode is additive. */ + fragRevealage = vec4(0.0); + fragColor.rgb = texture(colorBuf, uvcoordsvar.xy).rgb; + fragColor.a = 0.0; + } +} + +#elif defined(COLORIZE) + +uniform vec3 lowColor; +uniform vec3 highColor; +uniform float factor; +uniform int mode; + +const mat3 sepia_mat = mat3( + vec3(0.393, 0.349, 0.272), vec3(0.769, 0.686, 0.534), vec3(0.189, 0.168, 0.131)); + +# define MODE_GRAYSCALE 0 +# define MODE_SEPIA 1 +# define MODE_DUOTONE 2 +# define MODE_CUSTOM 3 +# define MODE_TRANSPARENT 4 + +void main() +{ + fragColor = texture(colorBuf, uvcoordsvar.xy); + fragRevealage = texture(revealBuf, uvcoordsvar.xy); + + float luma = dot(fragColor.rgb, vec3(0.2126, 0.7152, 0.723)); + + /* No blending. */ + switch (mode) { + case MODE_GRAYSCALE: + fragColor.rgb = mix(fragColor.rgb, vec3(luma), factor); + break; + case MODE_SEPIA: + fragColor.rgb = mix(fragColor.rgb, sepia_mat * fragColor.rgb, factor); + break; + case MODE_DUOTONE: + fragColor.rgb = luma * ((luma <= factor) ? lowColor : highColor); + break; + case MODE_CUSTOM: + fragColor.rgb = mix(fragColor.rgb, luma * lowColor, factor); + break; + case MODE_TRANSPARENT: + default: + fragColor.rgb *= factor; + fragRevealage.rgb = mix(vec3(1.0), fragRevealage.rgb, factor); + break; + } +} + +#elif defined(BLUR) + +uniform vec2 offset; +uniform int sampCount; + +void main() +{ + vec2 pixel_size = 1.0 / vec2(textureSize(revealBuf, 0).xy); + vec2 ofs = offset * pixel_size; + + fragColor = vec4(0.0); + fragRevealage = vec4(0.0); + + /* No blending. */ + float weight_accum = 0.0; + for (int i = -sampCount; i <= sampCount; i++) { + float x = float(i) / float(sampCount); + float weight = gaussian_weight(x); + weight_accum += weight; + vec2 uv = uvcoordsvar.xy + ofs * x; + fragColor.rgb += texture(colorBuf, uv).rgb * weight; + fragRevealage.rgb += texture(revealBuf, uv).rgb * weight; + } + + fragColor /= weight_accum; + fragRevealage /= weight_accum; +} + +#elif defined(TRANSFORM) + +uniform vec2 axisFlip = vec2(1.0); +uniform vec2 waveDir = vec2(0.0); +uniform vec2 waveOffset = vec2(0.0); +uniform float wavePhase = 0.0; +uniform vec2 swirlCenter = vec2(0.0); +uniform float swirlAngle = 0.0; +uniform float swirlRadius = 0.0; + +void main() +{ + vec2 uv = (uvcoordsvar.xy - 0.5) * axisFlip + 0.5; + + /* Wave deform. */ + float wave_time = dot(uv, waveDir.xy); + uv += sin(wave_time + wavePhase) * waveOffset; + /* Swirl deform. */ + if (swirlRadius > 0.0) { + vec2 tex_size = vec2(textureSize(colorBuf, 0).xy); + vec2 pix_coord = uv * tex_size - swirlCenter; + float dist = length(pix_coord); + float percent = clamp((swirlRadius - dist) / swirlRadius, 0.0, 1.0); + float theta = percent * percent * swirlAngle; + float s = sin(theta); + float c = cos(theta); + mat2 rot = mat2(vec2(c, -s), vec2(s, c)); + uv = (rot * pix_coord + swirlCenter) / tex_size; + } + + fragColor = texture(colorBuf, uv); + fragRevealage = texture(revealBuf, uv); +} + +#elif defined(GLOW) + +uniform vec4 glowColor; +uniform vec2 offset; +uniform int sampCount; +uniform vec3 threshold; +uniform bool firstPass; +uniform bool glowUnder; +uniform int blendMode; + +void main() +{ + vec2 pixel_size = 1.0 / vec2(textureSize(revealBuf, 0).xy); + vec2 ofs = offset * pixel_size; + + fragColor = vec4(0.0); + fragRevealage = vec4(0.0); + + float weight_accum = 0.0; + for (int i = -sampCount; i <= sampCount; i++) { + float x = float(i) / float(sampCount); + float weight = gaussian_weight(x); + weight_accum += weight; + vec2 uv = uvcoordsvar.xy + ofs * x; + vec3 col = texture(colorBuf, uv).rgb; + vec3 rev = texture(revealBuf, uv).rgb; + if (threshold.x > -1.0) { + if (threshold.y > -1.0) { + if (all(lessThan(abs(col - threshold), vec3(0.05)))) { + weight = 0.0; + } + } + else { + if (dot(col, vec3(1.0 / 3.0)) < threshold.x) { + weight = 0.0; + } + } + } + fragColor.rgb += col * weight; + fragRevealage.rgb += (1.0 - rev) * weight; + } + + if (weight_accum > 0.0) { + fragColor *= glowColor.rgbb / weight_accum; + fragRevealage = fragRevealage / weight_accum; + } + fragRevealage = 1.0 - fragRevealage; + + if (glowUnder) { + if (firstPass) { + /* In first pass we copy the revealage buffer in the alpha channel. + * This let us do the alpha under in second pass. */ + vec3 original_revealage = texture(revealBuf, uvcoordsvar.xy).rgb; + fragRevealage.a = clamp(dot(original_revealage.rgb, vec3(0.333334)), 0.0, 1.0); + } + else { + /* Recover original revealage. */ + fragRevealage.a = texture(revealBuf, uvcoordsvar.xy).a; + } + } + + if (!firstPass) { + fragColor.a = clamp(1.0 - dot(fragRevealage.rgb, vec3(0.333334)), 0.0, 1.0); + fragRevealage.a *= glowColor.a; + blend_mode_output(blendMode, fragColor, fragRevealage.a, fragColor, fragRevealage); + } +} + +#elif defined(RIM) + +uniform vec2 blurDir; +uniform vec2 uvOffset; +uniform vec3 rimColor; +uniform vec3 maskColor; +uniform int sampCount; +uniform int blendMode; +uniform bool isFirstPass; + +void main() +{ + /* Blur revealage buffer. */ + fragRevealage = vec4(0.0); + float weight_accum = 0.0; + for (int i = -sampCount; i <= sampCount; i++) { + float x = float(i) / float(sampCount); + float weight = gaussian_weight(x); + weight_accum += weight; + vec2 uv = uvcoordsvar.xy + blurDir * x + uvOffset; + vec3 col = texture(revealBuf, uv).rgb; + if (any(not(equal(vec2(0.0), floor(uv))))) { + col = vec3(0.0); + } + fragRevealage.rgb += col * weight; + } + fragRevealage /= weight_accum; + + if (isFirstPass) { + /* In first pass we copy the reveal buffer. This let us do alpha masking in second pass. */ + fragColor = texture(revealBuf, uvcoordsvar.xy); + /* Also add the masked color to the reveal buffer. */ + vec3 col = texture(colorBuf, uvcoordsvar.xy).rgb; + if (all(lessThan(abs(col - maskColor), vec3(0.05)))) { + fragColor = vec4(1.0); + } + } + else { + /* Premult by foreground alpha (alpha mask). */ + float mask = 1.0 - clamp(dot(vec3(0.333334), texture(colorBuf, uvcoordsvar.xy).rgb), 0.0, 1.0); + + /* fragRevealage is blurred shadow. */ + float rim = clamp(dot(vec3(0.333334), fragRevealage.rgb), 0.0, 1.0); + + vec4 color = vec4(rimColor, 1.0); + + blend_mode_output(blendMode, color, rim * mask, fragColor, fragRevealage); + } +} + +#elif defined(SHADOW) + +uniform vec4 shadowColor; +uniform vec2 uvRotX; +uniform vec2 uvRotY; +uniform vec2 uvOffset; +uniform vec2 blurDir; +uniform vec2 waveDir; +uniform vec2 waveOffset; +uniform float wavePhase; +uniform int sampCount; +uniform bool isFirstPass; + +vec2 compute_uvs(float x) +{ + vec2 uv = uvcoordsvar.xy; + /* Tranform UV (loc, rot, scale) */ + uv = uv.x * uvRotX + uv.y * uvRotY + uvOffset; + uv += blurDir * x; + /* Wave deform. */ + float wave_time = dot(uv, waveDir.xy); + uv += sin(wave_time + wavePhase) * waveOffset; + return uv; +} + +void main() +{ + /* Blur revealage buffer. */ + fragRevealage = vec4(0.0); + float weight_accum = 0.0; + for (int i = -sampCount; i <= sampCount; i++) { + float x = float(i) / float(sampCount); + float weight = gaussian_weight(x); + weight_accum += weight; + vec2 uv = compute_uvs(x); + vec3 col = texture(revealBuf, uv).rgb; + if (any(not(equal(vec2(0.0), floor(uv))))) { + col = vec3(1.0); + } + fragRevealage.rgb += col * weight; + } + fragRevealage /= weight_accum; + + /* No blending in first pass, alpha over premult in second pass. */ + if (isFirstPass) { + /* In first pass we copy the reveal buffer. This let us do alpha under in second pass. */ + fragColor = texture(revealBuf, uvcoordsvar.xy); + } + else { + /* fragRevealage is blurred shadow. */ + float shadow_fac = 1.0 - clamp(dot(vec3(0.333334), fragRevealage.rgb), 0.0, 1.0); + /* Premult by foreground revealage (alpha under). */ + vec3 original_revealage = texture(colorBuf, uvcoordsvar.xy).rgb; + shadow_fac *= clamp(dot(vec3(0.333334), original_revealage), 0.0, 1.0); + /* Modulate by opacity */ + shadow_fac *= shadowColor.a; + /* Apply shadow color. */ + fragColor.rgb = mix(vec3(0.0), shadowColor.rgb, shadow_fac); + /* Alpha over (mask behind the shadow). */ + fragColor.a = shadow_fac; + + fragRevealage.rgb = original_revealage * (1.0 - shadow_fac); + /* Replace the whole revealage buffer. */ + fragRevealage.a = 1.0; + } +} + +#elif defined(PIXELIZE) + +uniform vec2 targetPixelSize; +uniform vec2 targetPixelOffset; +uniform vec2 accumOffset; +uniform int sampCount; + +void main() +{ + vec2 pixel = floor((uvcoordsvar.xy - targetPixelOffset) / targetPixelSize); + vec2 uv = (pixel + 0.5) * targetPixelSize + targetPixelOffset; + + fragColor = vec4(0.0); + fragRevealage = vec4(0.0); + + for (int i = -sampCount; i <= sampCount; i++) { + float x = float(i) / float(sampCount + 1); + vec2 uv_ofs = uv + accumOffset * 0.5 * x; + fragColor += texture(colorBuf, uv_ofs); + fragRevealage += texture(revealBuf, uv_ofs); + } + + fragColor /= float(sampCount) * 2.0 + 1.0; + fragRevealage /= float(sampCount) * 2.0 + 1.0; +} + +#endif |