Combine shaders
This commit is contained in:
parent
23608ba524
commit
bbd6f8cf24
|
|
@ -14,44 +14,23 @@ uniform vec4 colDiffuse;
|
||||||
|
|
||||||
uniform vec4 rectangle; // Rectangle dimensions (x, y, width, height)
|
uniform vec4 rectangle; // Rectangle dimensions (x, y, width, height)
|
||||||
uniform vec4 radius; // Corner radius (top-left, top-right, bottom-left, bottom-right)
|
uniform vec4 radius; // Corner radius (top-left, top-right, bottom-left, bottom-right)
|
||||||
|
uniform vec4 color;
|
||||||
|
|
||||||
// TODO: Remove anti-aliasing?
|
// Shadow parameters
|
||||||
|
uniform float shadowRadius;
|
||||||
|
uniform vec2 shadowOffset;
|
||||||
|
uniform float shadowScale;
|
||||||
|
uniform vec4 shadowColor;
|
||||||
|
|
||||||
// Anti-alias using easing function for smmoth edges
|
// Border parameters
|
||||||
uniform float aaPower;
|
uniform float borderThickness;
|
||||||
uniform float aaDistance;
|
uniform vec4 borderColor;
|
||||||
|
|
||||||
// Ease in-out
|
|
||||||
float ease(float x, float p)
|
|
||||||
{
|
|
||||||
if (x < 0.5)
|
|
||||||
{
|
|
||||||
return 1.0/pow(0.5, p - 1.0)*pow(x, p);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return 1.0 - 1.0/pow(0.5, p - 1.0)*pow(1.0 - x, p);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Smoothstep with easing
|
|
||||||
float easestep(float edge0, float edge1, float x, float p)
|
|
||||||
{
|
|
||||||
float t = clamp( (x - edge0)/(edge1 - edge0), 0.0, 1.0 );
|
|
||||||
return ease(t, p);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Anti-alias on edge for x
|
|
||||||
float antiAlias(float edge, float x)
|
|
||||||
{
|
|
||||||
return easestep(edge + aaDistance*0.5, edge - aaDistance*0.5, x, aaPower);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create a rounded rectangle using signed distance field
|
// Create a rounded rectangle using signed distance field
|
||||||
// Thanks to Iñigo Quilez (https://www.iquilezles.org/www/articles/distfunctions/distfunctions.htm)
|
// Thanks to Iñigo Quilez (https://www.iquilezles.org/www/articles/distfunctions/distfunctions.htm)
|
||||||
// And thanks to inobelar (https://www.shadertoy.com/view/fsdyzB) for shader
|
// And thanks to inobelar (https://www.shadertoy.com/view/fsdyzB) for shader
|
||||||
// MIT License
|
// MIT License
|
||||||
float roundedRectangleSDF(
|
float RoundedRectangleSDF(
|
||||||
vec2 fragCoord,
|
vec2 fragCoord,
|
||||||
vec2 center,
|
vec2 center,
|
||||||
vec2 halfSize,
|
vec2 halfSize,
|
||||||
|
|
@ -74,17 +53,29 @@ void main()
|
||||||
// Texel color fetching from texture sampler
|
// Texel color fetching from texture sampler
|
||||||
vec4 texelColor = texture2D(texture0, fragTexCoord);
|
vec4 texelColor = texture2D(texture0, fragTexCoord);
|
||||||
|
|
||||||
// Get fragment coordinate in pixels
|
// Requires fragment coordinate varying pixels
|
||||||
vec2 fragCoord = gl_FragCoord.xy;
|
vec2 fragCoord = gl_FragCoord.xy;
|
||||||
|
|
||||||
// Calculate signed distance field for rounded rectangle
|
// Calculate signed distance field for rounded rectangle
|
||||||
vec2 halfSize = rectangle.zw*0.5;
|
vec2 halfSize = rectangle.zw*0.5;
|
||||||
vec2 center = rectangle.xy + halfSize;
|
vec2 center = rectangle.xy + halfSize;
|
||||||
float sdf = roundedRectangleSDF(fragCoord, center, halfSize, radius);
|
float recSDF = RoundedRectangleSDF(fragCoord, center, halfSize, radius);
|
||||||
|
|
||||||
// Calculate anti-aliased factor
|
// Calculate signed distance field for rectangle shadow
|
||||||
float aa = 1.0 - antiAlias(0.0, -sdf);
|
vec2 shadowHalfSize = halfSize*shadowScale;
|
||||||
|
vec2 shadowCenter = center + shadowOffset;
|
||||||
|
float shadowSDF = RoundedRectangleSDF(fragCoord, shadowCenter, shadowHalfSize, radius);
|
||||||
|
|
||||||
gl_FragColor = texelColor*colDiffuse*fragColor
|
// Caculate alpha factors
|
||||||
*vec4(1.0, 1.0, 1.0, aa);
|
float recFactor = smoothstep(1.0, 0.0, recSDF);
|
||||||
|
float shadowFactor = smoothstep(shadowRadius, 0.0, shadowSDF);
|
||||||
|
float borderFactor = smoothstep(0.0, 1.0, recSDF + borderThickness)*recFactor;
|
||||||
|
|
||||||
|
// Multiply each color by its respective alpha factor
|
||||||
|
vec4 recColor = vec4(color.rgb, color.a*recFactor);
|
||||||
|
vec4 shadowCol = vec4(shadowColor.rgb, shadowColor.a*shadowFactor);
|
||||||
|
vec4 borderCol = vec4(borderColor.rgb, borderColor.a*borderFactor);
|
||||||
|
|
||||||
|
// Combine the colors varying the order (shadow, rectangle, border)
|
||||||
|
gl_FragColor = mix(mix(shadowCol, recColor, recColor.a), borderCol, borderCol.a);
|
||||||
}
|
}
|
||||||
|
|
@ -1,91 +0,0 @@
|
||||||
// Note: SDF by Iñigo Quilez is licensed under MIT License
|
|
||||||
|
|
||||||
#version 100
|
|
||||||
|
|
||||||
precision mediump float;
|
|
||||||
|
|
||||||
// Input vertex attributes (from vertex shader)
|
|
||||||
varying vec2 fragTexCoord;
|
|
||||||
varying vec4 fragColor;
|
|
||||||
|
|
||||||
// Input uniform values
|
|
||||||
uniform sampler2D texture0;
|
|
||||||
uniform vec4 colDiffuse;
|
|
||||||
|
|
||||||
uniform vec4 rectangle; // Rectangle dimensions (x, y, width, height)
|
|
||||||
uniform vec4 radius; // Corner radius (top-left, top-right, bottom-left, bottom-right)
|
|
||||||
uniform float borderThickness;
|
|
||||||
|
|
||||||
// TODO: Remove anti-aliasing?
|
|
||||||
|
|
||||||
// Anti-alias using easing function for smmoth edges
|
|
||||||
uniform float aaPower;
|
|
||||||
uniform float aaDistance;
|
|
||||||
|
|
||||||
// Ease in-out
|
|
||||||
float ease(float x, float p)
|
|
||||||
{
|
|
||||||
if (x < 0.5)
|
|
||||||
{
|
|
||||||
return 1.0/pow(0.5, p - 1.0)*pow(x, p);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return 1.0 - 1.0/pow(0.5, p - 1.0)*pow(1.0 - x, p);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Smoothstep with easing
|
|
||||||
float easestep(float edge0, float edge1, float x, float p)
|
|
||||||
{
|
|
||||||
float t = clamp( (x - edge0)/(edge1 - edge0), 0.0, 1.0 );
|
|
||||||
return ease(t, p);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Anti-alias on edge for x
|
|
||||||
float antiAlias(float edge, float x)
|
|
||||||
{
|
|
||||||
return easestep(edge + aaDistance*0.5, edge - aaDistance*0.5, x, aaPower);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create a rounded rectangle using signed distance field
|
|
||||||
// Thanks to Iñigo Quilez (https://www.iquilezles.org/www/articles/distfunctions/distfunctions.htm)
|
|
||||||
// And thanks to inobelar (https://www.shadertoy.com/view/fsdyzB) for shader
|
|
||||||
// MIT License
|
|
||||||
float roundedRectangleSDF(
|
|
||||||
vec2 fragCoord,
|
|
||||||
vec2 center,
|
|
||||||
vec2 halfSize,
|
|
||||||
vec4 radius
|
|
||||||
)
|
|
||||||
{
|
|
||||||
vec2 fragFromCenter = fragCoord - center;
|
|
||||||
|
|
||||||
// Determine which corner radius to use
|
|
||||||
radius.xy = (fragFromCenter.y > 0.0) ? radius.xy : radius.zw;
|
|
||||||
radius.x = (fragFromCenter.x < 0.0) ? radius.x : radius.y;
|
|
||||||
|
|
||||||
// Calculate signed distance field
|
|
||||||
vec2 dist = abs(fragFromCenter) - halfSize + radius.x;
|
|
||||||
return min(max(dist.x, dist.y), 0.0) + length(max(dist, 0.0)) - radius.x;
|
|
||||||
}
|
|
||||||
|
|
||||||
void main()
|
|
||||||
{
|
|
||||||
// Texel color fetching from texture sampler
|
|
||||||
vec4 texelColor = texture2D(texture0, fragTexCoord);
|
|
||||||
|
|
||||||
// Get fragment coordinate in pixels
|
|
||||||
vec2 fragCoord = gl_FragCoord.xy;
|
|
||||||
|
|
||||||
// Calculate signed distance field for rounded rectangle's border
|
|
||||||
vec2 halfSize = rectangle.zw*0.5;
|
|
||||||
vec2 center = rectangle.xy + halfSize;
|
|
||||||
float sdf = roundedRectangleSDF(fragCoord, center, halfSize, radius);
|
|
||||||
|
|
||||||
// Calculate anti-aliased factor
|
|
||||||
float aa = antiAlias(borderThickness, -sdf) * (1.0 - antiAlias(0.0, -sdf));
|
|
||||||
|
|
||||||
gl_FragColor = texelColor*colDiffuse*fragColor
|
|
||||||
*vec4(1.0, 1.0, 1.0, aa);
|
|
||||||
}
|
|
||||||
|
|
@ -1,98 +0,0 @@
|
||||||
// Note: SDF by Iñigo Quilez is licensed under MIT License
|
|
||||||
|
|
||||||
#version 100
|
|
||||||
|
|
||||||
precision mediump float;
|
|
||||||
|
|
||||||
// Input vertex attributes (from vertex shader)
|
|
||||||
varying vec2 fragTexCoord;
|
|
||||||
varying vec4 fragColor;
|
|
||||||
|
|
||||||
// Input uniform values
|
|
||||||
uniform sampler2D texture0;
|
|
||||||
uniform vec4 colDiffuse;
|
|
||||||
|
|
||||||
uniform vec4 rectangle; // Rectangle dimensions (x, y, width, height)
|
|
||||||
uniform vec4 radius; // Corner radius (top-left, top-right, bottom-left, bottom-right)
|
|
||||||
|
|
||||||
// Shadow parameters
|
|
||||||
uniform float shadowRadius;
|
|
||||||
uniform float shadowPower;
|
|
||||||
uniform vec2 shadowOffset;
|
|
||||||
uniform float shadowScale;
|
|
||||||
|
|
||||||
// TODO: Remove anti-aliasing?
|
|
||||||
|
|
||||||
// Anti-alias using easing function for smmoth edges
|
|
||||||
uniform float aaPower;
|
|
||||||
uniform float aaDistance;
|
|
||||||
|
|
||||||
// Ease in-out
|
|
||||||
float ease(float x, float p)
|
|
||||||
{
|
|
||||||
if (x < 0.5)
|
|
||||||
{
|
|
||||||
return 1.0/pow(0.5, p - 1.0)*pow(x, p);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return 1.0 - 1.0/pow(0.5, p - 1.0)*pow(1.0 - x, p);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Smoothstep with easing
|
|
||||||
float easestep(float edge0, float edge1, float x, float p)
|
|
||||||
{
|
|
||||||
float t = clamp( (x - edge0)/(edge1 - edge0), 0.0, 1.0 );
|
|
||||||
return ease(t, p);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Anti-alias on edge for x
|
|
||||||
float antiAlias(float edge, float x)
|
|
||||||
{
|
|
||||||
return easestep(edge + aaDistance*0.5, edge - aaDistance*0.5, x, aaPower);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create a rounded rectangle using signed distance field
|
|
||||||
// Thanks to Iñigo Quilez (https://www.iquilezles.org/www/articles/distfunctions/distfunctions.htm)
|
|
||||||
// And thanks to inobelar (https://www.shadertoy.com/view/fsdyzB) for shader
|
|
||||||
// MIT License
|
|
||||||
float roundedRectangleSDF(
|
|
||||||
vec2 fragCoord,
|
|
||||||
vec2 center,
|
|
||||||
vec2 halfSize,
|
|
||||||
vec4 radius
|
|
||||||
)
|
|
||||||
{
|
|
||||||
vec2 fragFromCenter = fragCoord - center;
|
|
||||||
|
|
||||||
// Determine which corner radius to use
|
|
||||||
radius.xy = (fragFromCenter.y > 0.0) ? radius.xy : radius.zw;
|
|
||||||
radius.x = (fragFromCenter.x < 0.0) ? radius.x : radius.y;
|
|
||||||
|
|
||||||
// Calculate signed distance field
|
|
||||||
vec2 dist = abs(fragFromCenter) - halfSize + radius.x;
|
|
||||||
return min(max(dist.x, dist.y), 0.0) + length(max(dist, 0.0)) - radius.x;
|
|
||||||
}
|
|
||||||
|
|
||||||
void main()
|
|
||||||
{
|
|
||||||
// Texel color fetching from texture sampler
|
|
||||||
vec4 texelColor = texture2D(texture0, fragTexCoord);
|
|
||||||
|
|
||||||
// Get fragment coordinate in pixels
|
|
||||||
vec2 fragCoord = gl_FragCoord.xy;
|
|
||||||
|
|
||||||
// Calculate signed distance field for rounded rectangle's shadow
|
|
||||||
vec2 halfSize = rectangle.zw*0.5;
|
|
||||||
vec2 center = rectangle.xy + halfSize;
|
|
||||||
|
|
||||||
vec2 shadowHalfSize = halfSize*shadowScale;
|
|
||||||
vec2 shadowCenter = center + shadowOffset;
|
|
||||||
float sdf = roundedRectangleSDF(fragCoord, shadowCenter, shadowHalfSize, radius);
|
|
||||||
|
|
||||||
float aa = easestep(shadowRadius, 0.0, sdf, shadowPower);
|
|
||||||
|
|
||||||
gl_FragColor = texelColor*colDiffuse*fragColor
|
|
||||||
*vec4(1.0, 1.0, 1.0, aa);
|
|
||||||
}
|
|
||||||
|
|
@ -12,51 +12,29 @@ uniform vec4 colDiffuse;
|
||||||
|
|
||||||
uniform vec4 rectangle; // Rectangle dimensions (x, y, width, height)
|
uniform vec4 rectangle; // Rectangle dimensions (x, y, width, height)
|
||||||
uniform vec4 radius; // Corner radius (top-left, top-right, bottom-left, bottom-right)
|
uniform vec4 radius; // Corner radius (top-left, top-right, bottom-left, bottom-right)
|
||||||
|
uniform vec4 color;
|
||||||
|
|
||||||
// TODO: Remove anti-aliasing?
|
// Shadow parameters
|
||||||
|
uniform float shadowRadius;
|
||||||
|
uniform vec2 shadowOffset;
|
||||||
|
uniform float shadowScale;
|
||||||
|
uniform vec4 shadowColor;
|
||||||
|
|
||||||
// Anti-alias using easing function for smmoth edges
|
// Border parameters
|
||||||
uniform float aaPower;
|
uniform float borderThickness;
|
||||||
uniform float aaDistance;
|
uniform vec4 borderColor;
|
||||||
|
|
||||||
// Ease in-out
|
|
||||||
float ease(float x, float p)
|
|
||||||
{
|
|
||||||
if (x < 0.5)
|
|
||||||
{
|
|
||||||
return 1.0/pow(0.5, p - 1.0)*pow(x, p);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return 1.0 - 1.0/pow(0.5, p - 1.0)*pow(1.0 - x, p);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Smoothstep with easing
|
|
||||||
float easestep(float edge0, float edge1, float x, float p)
|
|
||||||
{
|
|
||||||
float t = clamp( (x - edge0)/(edge1 - edge0), 0.0, 1.0 );
|
|
||||||
return ease(t, p);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Anti-alias on edge for x
|
|
||||||
float antiAlias(float edge, float x)
|
|
||||||
{
|
|
||||||
return easestep(edge + aaDistance*0.5, edge - aaDistance*0.5, x, aaPower);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create a rounded rectangle using signed distance field
|
// Create a rounded rectangle using signed distance field
|
||||||
// Thanks to Iñigo Quilez (https://www.iquilezles.org/www/articles/distfunctions/distfunctions.htm)
|
// Thanks to Iñigo Quilez (https://www.iquilezles.org/www/articles/distfunctions/distfunctions.htm)
|
||||||
// And thanks to inobelar (https://www.shadertoy.com/view/fsdyzB) for shader
|
// And thanks to inobelar (https://www.shadertoy.com/view/fsdyzB) for shader
|
||||||
// MIT License
|
// MIT License
|
||||||
float roundedRectangleSDF(
|
float RoundedRectangleSDF(
|
||||||
vec2 fragCoord,
|
vec2 fragCoord,
|
||||||
vec4 rectangle,
|
vec2 center,
|
||||||
|
vec2 halfSize,
|
||||||
vec4 radius
|
vec4 radius
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
vec2 halfSize = rectangle.zw*0.5;
|
|
||||||
vec2 center = rectangle.xy + halfSize;
|
|
||||||
vec2 fragFromCenter = fragCoord - center;
|
vec2 fragFromCenter = fragCoord - center;
|
||||||
|
|
||||||
// Determine which corner radius to use
|
// Determine which corner radius to use
|
||||||
|
|
@ -73,15 +51,29 @@ void main()
|
||||||
// Texel color fetching from texture sampler
|
// Texel color fetching from texture sampler
|
||||||
vec4 texelColor = texture2D(texture0, fragTexCoord);
|
vec4 texelColor = texture2D(texture0, fragTexCoord);
|
||||||
|
|
||||||
// Get fragment coordinate in pixels
|
// Requires fragment coordinate varying pixels
|
||||||
vec2 fragCoord = gl_FragCoord.xy;
|
vec2 fragCoord = gl_FragCoord.xy;
|
||||||
|
|
||||||
// Calculate signed distance field for rounded rectangle
|
// Calculate signed distance field for rounded rectangle
|
||||||
float sdf = roundedRectangleSDF(fragCoord, rectangle, radius);
|
vec2 halfSize = rectangle.zw*0.5;
|
||||||
|
vec2 center = rectangle.xy + halfSize;
|
||||||
|
float recSDF = RoundedRectangleSDF(fragCoord, center, halfSize, radius);
|
||||||
|
|
||||||
// Calculate anti-aliased factor
|
// Calculate signed distance field for rectangle shadow
|
||||||
float aa = 1.0 - antiAlias(0.0, -sdf);
|
vec2 shadowHalfSize = halfSize*shadowScale;
|
||||||
|
vec2 shadowCenter = center + shadowOffset;
|
||||||
|
float shadowSDF = RoundedRectangleSDF(fragCoord, shadowCenter, shadowHalfSize, radius);
|
||||||
|
|
||||||
gl_FragColor = texelColor*colDiffuse*fragColor
|
// Caculate alpha factors
|
||||||
*vec4(1.0, 1.0, 1.0, aa);
|
float recFactor = smoothstep(1.0, 0.0, recSDF);
|
||||||
|
float shadowFactor = smoothstep(shadowRadius, 0.0, shadowSDF);
|
||||||
|
float borderFactor = smoothstep(0.0, 1.0, recSDF + borderThickness)*recFactor;
|
||||||
|
|
||||||
|
// Multiply each color by its respective alpha factor
|
||||||
|
vec4 recColor = vec4(color.rgb, color.a*recFactor);
|
||||||
|
vec4 shadowCol = vec4(shadowColor.rgb, shadowColor.a*shadowFactor);
|
||||||
|
vec4 borderCol = vec4(borderColor.rgb, borderColor.a*borderFactor);
|
||||||
|
|
||||||
|
// Combine the colors varying the order (shadow, rectangle, border)
|
||||||
|
gl_FragColor = mix(mix(shadowCol, recColor, recColor.a), borderCol, borderCol.a);
|
||||||
}
|
}
|
||||||
|
|
@ -1,89 +0,0 @@
|
||||||
// Note: SDF by Iñigo Quilez is licensed under MIT License
|
|
||||||
|
|
||||||
#version 120
|
|
||||||
|
|
||||||
// Input vertex attributes (from vertex shader)
|
|
||||||
varying vec2 fragTexCoord;
|
|
||||||
varying vec4 fragColor;
|
|
||||||
|
|
||||||
// Input uniform values
|
|
||||||
uniform sampler2D texture0;
|
|
||||||
uniform vec4 colDiffuse;
|
|
||||||
|
|
||||||
uniform vec4 rectangle; // Rectangle dimensions (x, y, width, height)
|
|
||||||
uniform vec4 radius; // Corner radius (top-left, top-right, bottom-left, bottom-right)
|
|
||||||
uniform float borderThickness;
|
|
||||||
|
|
||||||
// TODO: Remove anti-aliasing?
|
|
||||||
|
|
||||||
// Anti-alias using easing function for smmoth edges
|
|
||||||
uniform float aaPower;
|
|
||||||
uniform float aaDistance;
|
|
||||||
|
|
||||||
// Ease in-out
|
|
||||||
float ease(float x, float p)
|
|
||||||
{
|
|
||||||
if (x < 0.5)
|
|
||||||
{
|
|
||||||
return 1.0/pow(0.5, p - 1.0)*pow(x, p);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return 1.0 - 1.0/pow(0.5, p - 1.0)*pow(1.0 - x, p);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Smoothstep with easing
|
|
||||||
float easestep(float edge0, float edge1, float x, float p)
|
|
||||||
{
|
|
||||||
float t = clamp( (x - edge0)/(edge1 - edge0), 0.0, 1.0 );
|
|
||||||
return ease(t, p);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Anti-alias on edge for x
|
|
||||||
float antiAlias(float edge, float x)
|
|
||||||
{
|
|
||||||
return easestep(edge + aaDistance*0.5, edge - aaDistance*0.5, x, aaPower);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create a rounded rectangle using signed distance field
|
|
||||||
// Thanks to Iñigo Quilez (https://www.iquilezles.org/www/articles/distfunctions/distfunctions.htm)
|
|
||||||
// And thanks to inobelar (https://www.shadertoy.com/view/fsdyzB) for shader
|
|
||||||
// MIT License
|
|
||||||
float roundedRectangleSDF(
|
|
||||||
vec2 fragCoord,
|
|
||||||
vec2 center,
|
|
||||||
vec2 halfSize,
|
|
||||||
vec4 radius
|
|
||||||
)
|
|
||||||
{
|
|
||||||
vec2 fragFromCenter = fragCoord - center;
|
|
||||||
|
|
||||||
// Determine which corner radius to use
|
|
||||||
radius.xy = (fragFromCenter.y > 0.0) ? radius.xy : radius.zw;
|
|
||||||
radius.x = (fragFromCenter.x < 0.0) ? radius.x : radius.y;
|
|
||||||
|
|
||||||
// Calculate signed distance field
|
|
||||||
vec2 dist = abs(fragFromCenter) - halfSize + radius.x;
|
|
||||||
return min(max(dist.x, dist.y), 0.0) + length(max(dist, 0.0)) - radius.x;
|
|
||||||
}
|
|
||||||
|
|
||||||
void main()
|
|
||||||
{
|
|
||||||
// Texel color fetching from texture sampler
|
|
||||||
vec4 texelColor = texture2D(texture0, fragTexCoord);
|
|
||||||
|
|
||||||
// Get fragment coordinate in pixels
|
|
||||||
vec2 fragCoord = gl_FragCoord.xy;
|
|
||||||
|
|
||||||
// Calculate signed distance field for rounded rectangle's border
|
|
||||||
vec2 halfSize = rectangle.zw*0.5;
|
|
||||||
vec2 center = rectangle.xy + halfSize;
|
|
||||||
float sdf = roundedRectangleSDF(fragCoord, center, halfSize, radius);
|
|
||||||
|
|
||||||
// Calculate anti-aliased factor
|
|
||||||
float aa = antiAlias(borderThickness, -sdf) * (1.0 - antiAlias(0.0, -sdf));
|
|
||||||
|
|
||||||
gl_FragColor = texelColor*colDiffuse*fragColor
|
|
||||||
*vec4(1.0, 1.0, 1.0, aa);
|
|
||||||
}
|
|
||||||
|
|
@ -1,96 +0,0 @@
|
||||||
// Note: SDF by Iñigo Quilez is licensed under MIT License
|
|
||||||
|
|
||||||
#version 120
|
|
||||||
|
|
||||||
// Input vertex attributes (from vertex shader)
|
|
||||||
varying vec2 fragTexCoord;
|
|
||||||
varying vec4 fragColor;
|
|
||||||
|
|
||||||
// Input uniform values
|
|
||||||
uniform sampler2D texture0;
|
|
||||||
uniform vec4 colDiffuse;
|
|
||||||
|
|
||||||
uniform vec4 rectangle; // Rectangle dimensions (x, y, width, height)
|
|
||||||
uniform vec4 radius; // Corner radius (top-left, top-right, bottom-left, bottom-right)
|
|
||||||
|
|
||||||
// Shadow parameters
|
|
||||||
uniform float shadowRadius;
|
|
||||||
uniform float shadowPower;
|
|
||||||
uniform vec2 shadowOffset;
|
|
||||||
uniform float shadowScale;
|
|
||||||
|
|
||||||
// TODO: Remove anti-aliasing?
|
|
||||||
|
|
||||||
// Anti-alias using easing function for smmoth edges
|
|
||||||
uniform float aaPower;
|
|
||||||
uniform float aaDistance;
|
|
||||||
|
|
||||||
// Ease in-out
|
|
||||||
float ease(float x, float p)
|
|
||||||
{
|
|
||||||
if (x < 0.5)
|
|
||||||
{
|
|
||||||
return 1.0/pow(0.5, p - 1.0)*pow(x, p);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return 1.0 - 1.0/pow(0.5, p - 1.0)*pow(1.0 - x, p);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Smoothstep with easing
|
|
||||||
float easestep(float edge0, float edge1, float x, float p)
|
|
||||||
{
|
|
||||||
float t = clamp( (x - edge0)/(edge1 - edge0), 0.0, 1.0 );
|
|
||||||
return ease(t, p);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Anti-alias on edge for x
|
|
||||||
float antiAlias(float edge, float x)
|
|
||||||
{
|
|
||||||
return easestep(edge + aaDistance*0.5, edge - aaDistance*0.5, x, aaPower);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create a rounded rectangle using signed distance field
|
|
||||||
// Thanks to Iñigo Quilez (https://www.iquilezles.org/www/articles/distfunctions/distfunctions.htm)
|
|
||||||
// And thanks to inobelar (https://www.shadertoy.com/view/fsdyzB) for shader
|
|
||||||
// MIT License
|
|
||||||
float roundedRectangleSDF(
|
|
||||||
vec2 fragCoord,
|
|
||||||
vec2 center,
|
|
||||||
vec2 halfSize,
|
|
||||||
vec4 radius
|
|
||||||
)
|
|
||||||
{
|
|
||||||
vec2 fragFromCenter = fragCoord - center;
|
|
||||||
|
|
||||||
// Determine which corner radius to use
|
|
||||||
radius.xy = (fragFromCenter.y > 0.0) ? radius.xy : radius.zw;
|
|
||||||
radius.x = (fragFromCenter.x < 0.0) ? radius.x : radius.y;
|
|
||||||
|
|
||||||
// Calculate signed distance field
|
|
||||||
vec2 dist = abs(fragFromCenter) - halfSize + radius.x;
|
|
||||||
return min(max(dist.x, dist.y), 0.0) + length(max(dist, 0.0)) - radius.x;
|
|
||||||
}
|
|
||||||
|
|
||||||
void main()
|
|
||||||
{
|
|
||||||
// Texel color fetching from texture sampler
|
|
||||||
vec4 texelColor = texture2D(texture0, fragTexCoord);
|
|
||||||
|
|
||||||
// Get fragment coordinate in pixels
|
|
||||||
vec2 fragCoord = gl_FragCoord.xy;
|
|
||||||
|
|
||||||
// Calculate signed distance field for rounded rectangle's shadow
|
|
||||||
vec2 halfSize = rectangle.zw*0.5;
|
|
||||||
vec2 center = rectangle.xy + halfSize;
|
|
||||||
|
|
||||||
vec2 shadowHalfSize = halfSize*shadowScale;
|
|
||||||
vec2 shadowCenter = center + shadowOffset;
|
|
||||||
float sdf = roundedRectangleSDF(fragCoord, shadowCenter, shadowHalfSize, radius);
|
|
||||||
|
|
||||||
float aa = easestep(shadowRadius, 0.0, sdf, shadowPower);
|
|
||||||
|
|
||||||
gl_FragColor = texelColor*colDiffuse*fragColor
|
|
||||||
*vec4(1.0, 1.0, 1.0, aa);
|
|
||||||
}
|
|
||||||
|
|
@ -15,51 +15,29 @@ out vec4 finalColor;
|
||||||
|
|
||||||
uniform vec4 rectangle; // Rectangle dimensions (x, y, width, height)
|
uniform vec4 rectangle; // Rectangle dimensions (x, y, width, height)
|
||||||
uniform vec4 radius; // Corner radius (top-left, top-right, bottom-left, bottom-right)
|
uniform vec4 radius; // Corner radius (top-left, top-right, bottom-left, bottom-right)
|
||||||
|
uniform vec4 color;
|
||||||
|
|
||||||
// TODO: Remove anti-aliasing?
|
// Shadow parameters
|
||||||
|
uniform float shadowRadius;
|
||||||
|
uniform vec2 shadowOffset;
|
||||||
|
uniform float shadowScale;
|
||||||
|
uniform vec4 shadowColor;
|
||||||
|
|
||||||
// Anti-alias using easing function for smmoth edges
|
// Border parameters
|
||||||
uniform float aaPower;
|
uniform float borderThickness;
|
||||||
uniform float aaDistance;
|
uniform vec4 borderColor;
|
||||||
|
|
||||||
// Ease in-out
|
|
||||||
float ease(float x, float p)
|
|
||||||
{
|
|
||||||
if (x < 0.5)
|
|
||||||
{
|
|
||||||
return 1.0/pow(0.5, p - 1.0)*pow(x, p);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return 1.0 - 1.0/pow(0.5, p - 1.0)*pow(1.0 - x, p);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Smoothstep with easing
|
|
||||||
float easestep(float edge0, float edge1, float x, float p)
|
|
||||||
{
|
|
||||||
float t = clamp( (x - edge0)/(edge1 - edge0), 0.0, 1.0 );
|
|
||||||
return ease(t, p);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Anti-alias on edge for x
|
|
||||||
float antiAlias(float edge, float x)
|
|
||||||
{
|
|
||||||
return easestep(edge + aaDistance*0.5, edge - aaDistance*0.5, x, aaPower);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create a rounded rectangle using signed distance field
|
// Create a rounded rectangle using signed distance field
|
||||||
// Thanks to Iñigo Quilez (https://www.iquilezles.org/www/articles/distfunctions/distfunctions.htm)
|
// Thanks to Iñigo Quilez (https://www.iquilezles.org/www/articles/distfunctions/distfunctions.htm)
|
||||||
// And thanks to inobelar (https://www.shadertoy.com/view/fsdyzB) for shader
|
// And thanks to inobelar (https://www.shadertoy.com/view/fsdyzB) for shader
|
||||||
// MIT License
|
// MIT License
|
||||||
float roundedRectangleSDF(
|
float RoundedRectangleSDF(
|
||||||
vec2 fragCoord,
|
vec2 fragCoord,
|
||||||
vec4 rectangle,
|
vec2 center,
|
||||||
|
vec2 halfSize,
|
||||||
vec4 radius
|
vec4 radius
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
vec2 halfSize = rectangle.zw*0.5;
|
|
||||||
vec2 center = rectangle.xy + halfSize;
|
|
||||||
vec2 fragFromCenter = fragCoord - center;
|
vec2 fragFromCenter = fragCoord - center;
|
||||||
|
|
||||||
// Determine which corner radius to use
|
// Determine which corner radius to use
|
||||||
|
|
@ -76,15 +54,29 @@ void main()
|
||||||
// Texel color fetching from texture sampler
|
// Texel color fetching from texture sampler
|
||||||
vec4 texelColor = texture(texture0, fragTexCoord);
|
vec4 texelColor = texture(texture0, fragTexCoord);
|
||||||
|
|
||||||
// Get fragment coordinate in pixels
|
// Requires fragment coordinate in pixels
|
||||||
vec2 fragCoord = gl_FragCoord.xy;
|
vec2 fragCoord = gl_FragCoord.xy;
|
||||||
|
|
||||||
// Calculate signed distance field for rounded rectangle
|
// Calculate signed distance field for rounded rectangle
|
||||||
float sdf = roundedRectangleSDF(fragCoord, rectangle, radius);
|
vec2 halfSize = rectangle.zw*0.5;
|
||||||
|
vec2 center = rectangle.xy + halfSize;
|
||||||
|
float recSDF = RoundedRectangleSDF(fragCoord, center, halfSize, radius);
|
||||||
|
|
||||||
// Calculate anti-aliased factor
|
// Calculate signed distance field for rectangle shadow
|
||||||
float aa = 1.0 - antiAlias(0.0, -sdf);
|
vec2 shadowHalfSize = halfSize*shadowScale;
|
||||||
|
vec2 shadowCenter = center + shadowOffset;
|
||||||
|
float shadowSDF = RoundedRectangleSDF(fragCoord, shadowCenter, shadowHalfSize, radius);
|
||||||
|
|
||||||
finalColor = texelColor*colDiffuse*fragColor
|
// Caculate alpha factors
|
||||||
*vec4(1.0, 1.0, 1.0, aa);
|
float recFactor = smoothstep(1.0, 0.0, recSDF);
|
||||||
|
float shadowFactor = smoothstep(shadowRadius, 0.0, shadowSDF);
|
||||||
|
float borderFactor = smoothstep(0.0, 1.0, recSDF + borderThickness)*recFactor;
|
||||||
|
|
||||||
|
// Multiply each color by its respective alpha factor
|
||||||
|
vec4 recColor = vec4(color.rgb, color.a*recFactor);
|
||||||
|
vec4 shadowCol = vec4(shadowColor.rgb, shadowColor.a*shadowFactor);
|
||||||
|
vec4 borderCol = vec4(borderColor.rgb, borderColor.a*borderFactor);
|
||||||
|
|
||||||
|
// Combine the colors in the order (shadow, rectangle, border)
|
||||||
|
finalColor = mix(mix(shadowCol, recColor, recColor.a), borderCol, borderCol.a);
|
||||||
}
|
}
|
||||||
|
|
@ -1,92 +0,0 @@
|
||||||
// Note: SDF by Iñigo Quilez is licensed under MIT License
|
|
||||||
|
|
||||||
#version 330
|
|
||||||
|
|
||||||
// Input vertex attributes (from vertex shader)
|
|
||||||
in vec2 fragTexCoord;
|
|
||||||
in vec4 fragColor;
|
|
||||||
|
|
||||||
// Input uniform values
|
|
||||||
uniform sampler2D texture0;
|
|
||||||
uniform vec4 colDiffuse;
|
|
||||||
|
|
||||||
// Output fragment color
|
|
||||||
out vec4 finalColor;
|
|
||||||
|
|
||||||
uniform vec4 rectangle; // Rectangle dimensions (x, y, width, height)
|
|
||||||
uniform vec4 radius; // Corner radius (top-left, top-right, bottom-left, bottom-right)
|
|
||||||
uniform float borderThickness;
|
|
||||||
|
|
||||||
// TODO: Remove anti-aliasing?
|
|
||||||
|
|
||||||
// Anti-alias using easing function for smmoth edges
|
|
||||||
uniform float aaPower;
|
|
||||||
uniform float aaDistance;
|
|
||||||
|
|
||||||
// Ease in-out
|
|
||||||
float ease(float x, float p)
|
|
||||||
{
|
|
||||||
if (x < 0.5)
|
|
||||||
{
|
|
||||||
return 1.0/pow(0.5, p - 1.0)*pow(x, p);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return 1.0 - 1.0/pow(0.5, p - 1.0)*pow(1.0 - x, p);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Smoothstep with easing
|
|
||||||
float easestep(float edge0, float edge1, float x, float p)
|
|
||||||
{
|
|
||||||
float t = clamp( (x - edge0)/(edge1 - edge0), 0.0, 1.0 );
|
|
||||||
return ease(t, p);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Anti-alias on edge for x
|
|
||||||
float antiAlias(float edge, float x)
|
|
||||||
{
|
|
||||||
return easestep(edge + aaDistance*0.5, edge - aaDistance*0.5, x, aaPower);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create a rounded rectangle using signed distance field
|
|
||||||
// Thanks to Iñigo Quilez (https://www.iquilezles.org/www/articles/distfunctions/distfunctions.htm)
|
|
||||||
// And thanks to inobelar (https://www.shadertoy.com/view/fsdyzB) for shader
|
|
||||||
// MIT License
|
|
||||||
float roundedRectangleSDF(
|
|
||||||
vec2 fragCoord,
|
|
||||||
vec2 center,
|
|
||||||
vec2 halfSize,
|
|
||||||
vec4 radius
|
|
||||||
)
|
|
||||||
{
|
|
||||||
vec2 fragFromCenter = fragCoord - center;
|
|
||||||
|
|
||||||
// Determine which corner radius to use
|
|
||||||
radius.xy = (fragFromCenter.y > 0.0) ? radius.xy : radius.zw;
|
|
||||||
radius.x = (fragFromCenter.x < 0.0) ? radius.x : radius.y;
|
|
||||||
|
|
||||||
// Calculate signed distance field
|
|
||||||
vec2 dist = abs(fragFromCenter) - halfSize + radius.x;
|
|
||||||
return min(max(dist.x, dist.y), 0.0) + length(max(dist, 0.0)) - radius.x;
|
|
||||||
}
|
|
||||||
|
|
||||||
void main()
|
|
||||||
{
|
|
||||||
// Texel color fetching from texture sampler
|
|
||||||
vec4 texelColor = texture(texture0, fragTexCoord);
|
|
||||||
|
|
||||||
// Get fragment coordinate in pixels
|
|
||||||
vec2 fragCoord = gl_FragCoord.xy;
|
|
||||||
|
|
||||||
// Calculate signed distance field for rounded rectangle's border
|
|
||||||
vec2 halfSize = rectangle.zw*0.5;
|
|
||||||
vec2 center = rectangle.xy + halfSize;
|
|
||||||
float sdf = roundedRectangleSDF(fragCoord, center, halfSize, radius);
|
|
||||||
|
|
||||||
// Calculate anti-aliased factor
|
|
||||||
float aa = antiAlias(borderThickness, -sdf) * (1.0 - antiAlias(0.0, -sdf));
|
|
||||||
|
|
||||||
finalColor = texelColor*colDiffuse*fragColor
|
|
||||||
*vec4(1.0, 1.0, 1.0, aa);
|
|
||||||
}
|
|
||||||
|
|
@ -1,99 +0,0 @@
|
||||||
// Note: SDF by Iñigo Quilez is licensed under MIT License
|
|
||||||
|
|
||||||
#version 330
|
|
||||||
|
|
||||||
// Input vertex attributes (from vertex shader)
|
|
||||||
in vec2 fragTexCoord;
|
|
||||||
in vec4 fragColor;
|
|
||||||
|
|
||||||
// Input uniform values
|
|
||||||
uniform sampler2D texture0;
|
|
||||||
uniform vec4 colDiffuse;
|
|
||||||
|
|
||||||
// Output fragment color
|
|
||||||
out vec4 finalColor;
|
|
||||||
|
|
||||||
uniform vec4 rectangle; // Rectangle dimensions (x, y, width, height)
|
|
||||||
uniform vec4 radius; // Corner radius (top-left, top-right, bottom-left, bottom-right)
|
|
||||||
|
|
||||||
// Shadow parameters
|
|
||||||
uniform float shadowRadius;
|
|
||||||
uniform float shadowPower;
|
|
||||||
uniform vec2 shadowOffset;
|
|
||||||
uniform float shadowScale;
|
|
||||||
|
|
||||||
// TODO: Remove anti-aliasing?
|
|
||||||
|
|
||||||
// Anti-alias using easing function for smmoth edges
|
|
||||||
uniform float aaPower;
|
|
||||||
uniform float aaDistance;
|
|
||||||
|
|
||||||
// Ease in-out
|
|
||||||
float ease(float x, float p)
|
|
||||||
{
|
|
||||||
if (x < 0.5)
|
|
||||||
{
|
|
||||||
return 1.0/pow(0.5, p - 1.0)*pow(x, p);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return 1.0 - 1.0/pow(0.5, p - 1.0)*pow(1.0 - x, p);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Smoothstep with easing
|
|
||||||
float easestep(float edge0, float edge1, float x, float p)
|
|
||||||
{
|
|
||||||
float t = clamp( (x - edge0)/(edge1 - edge0), 0.0, 1.0 );
|
|
||||||
return ease(t, p);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Anti-alias on edge for x
|
|
||||||
float antiAlias(float edge, float x)
|
|
||||||
{
|
|
||||||
return easestep(edge + aaDistance*0.5, edge - aaDistance*0.5, x, aaPower);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create a rounded rectangle using signed distance field
|
|
||||||
// Thanks to Iñigo Quilez (https://www.iquilezles.org/www/articles/distfunctions/distfunctions.htm)
|
|
||||||
// And thanks to inobelar (https://www.shadertoy.com/view/fsdyzB) for shader
|
|
||||||
// MIT License
|
|
||||||
float roundedRectangleSDF(
|
|
||||||
vec2 fragCoord,
|
|
||||||
vec2 center,
|
|
||||||
vec2 halfSize,
|
|
||||||
vec4 radius
|
|
||||||
)
|
|
||||||
{
|
|
||||||
vec2 fragFromCenter = fragCoord - center;
|
|
||||||
|
|
||||||
// Determine which corner radius to use
|
|
||||||
radius.xy = (fragFromCenter.y > 0.0) ? radius.xy : radius.zw;
|
|
||||||
radius.x = (fragFromCenter.x < 0.0) ? radius.x : radius.y;
|
|
||||||
|
|
||||||
// Calculate signed distance field
|
|
||||||
vec2 dist = abs(fragFromCenter) - halfSize + radius.x;
|
|
||||||
return min(max(dist.x, dist.y), 0.0) + length(max(dist, 0.0)) - radius.x;
|
|
||||||
}
|
|
||||||
|
|
||||||
void main()
|
|
||||||
{
|
|
||||||
// Texel color fetching from texture sampler
|
|
||||||
vec4 texelColor = texture(texture0, fragTexCoord);
|
|
||||||
|
|
||||||
// Get fragment coordinate in pixels
|
|
||||||
vec2 fragCoord = gl_FragCoord.xy;
|
|
||||||
|
|
||||||
// Calculate signed distance field for rounded rectangle's shadow
|
|
||||||
vec2 halfSize = rectangle.zw*0.5;
|
|
||||||
vec2 center = rectangle.xy + halfSize;
|
|
||||||
|
|
||||||
vec2 shadowHalfSize = halfSize*shadowScale;
|
|
||||||
vec2 shadowCenter = center + shadowOffset;
|
|
||||||
float sdf = roundedRectangleSDF(fragCoord, shadowCenter, shadowHalfSize, radius);
|
|
||||||
|
|
||||||
float aa = easestep(shadowRadius, 0.0, sdf, shadowPower);
|
|
||||||
|
|
||||||
finalColor = texelColor*colDiffuse*fragColor
|
|
||||||
*vec4(1.0, 1.0, 1.0, aa);
|
|
||||||
}
|
|
||||||
|
|
@ -23,6 +23,44 @@
|
||||||
#define GLSL_VERSION 100
|
#define GLSL_VERSION 100
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------------
|
||||||
|
// Declare custom Structs
|
||||||
|
//------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// Rounded rectangle data
|
||||||
|
typedef struct {
|
||||||
|
Vector4 cornerRadius; // Individual corner radius (top-left, top-right, bottom-left, bottom-right)
|
||||||
|
|
||||||
|
// Shadow variables
|
||||||
|
float shadowRadius;
|
||||||
|
Vector2 shadowOffset;
|
||||||
|
float shadowScale;
|
||||||
|
|
||||||
|
// Border variables
|
||||||
|
float borderThickness; // Inner-border thickness
|
||||||
|
|
||||||
|
// Shader locations
|
||||||
|
int rectangleLoc;
|
||||||
|
int radiusLoc;
|
||||||
|
int colorLoc;
|
||||||
|
int shadowRadiusLoc;
|
||||||
|
int shadowOffsetLoc;
|
||||||
|
int shadowScaleLoc;
|
||||||
|
int shadowColorLoc;
|
||||||
|
int borderThicknessLoc;
|
||||||
|
int borderColorLoc;
|
||||||
|
} RoundedRectangle;
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------------
|
||||||
|
// Module Functions Declaration
|
||||||
|
//------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// Create a rounded rectangle and set uniform locations
|
||||||
|
static RoundedRectangle CreateRoundedRectangle(Vector4 cornerRadius, float shadowRadius, Vector2 shadowOffset, float shadowScale, float borderThickness, Shader shader);
|
||||||
|
|
||||||
|
// Update rounded rectangle uniforms
|
||||||
|
static void UpdateRoundedRectangle(RoundedRectangle rec, Shader shader);
|
||||||
|
|
||||||
//------------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------------
|
||||||
// Program main entry point
|
// Program main entry point
|
||||||
//------------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------------
|
||||||
|
|
@ -33,76 +71,28 @@ int main(void)
|
||||||
const int screenWidth = 800;
|
const int screenWidth = 800;
|
||||||
const int screenHeight = 450;
|
const int screenHeight = 450;
|
||||||
|
|
||||||
SetConfigFlags(FLAG_MSAA_4X_HINT); // Enable Multi Sampling Anti Aliasing 4x (if available)
|
const Color rectangleColor = BLUE;
|
||||||
|
const Color shadowColor = DARKBLUE;
|
||||||
|
const Color borderColor = SKYBLUE;
|
||||||
|
|
||||||
InitWindow(screenWidth, screenHeight, "raylib [shaders] example - Rounded Rectangle");
|
InitWindow(screenWidth, screenHeight, "raylib [shaders] example - Rounded Rectangle");
|
||||||
|
|
||||||
// Shader loading
|
// Load the shader
|
||||||
//--------------------------------------------------------------------------------------
|
Shader shader = LoadShader(TextFormat("resources/shaders/glsl%i/base.vs", GLSL_VERSION),
|
||||||
// Load the rectangle shader which will draw the rectangle with rounded corners
|
|
||||||
Shader rectangleShader = LoadShader(TextFormat("resources/shaders/glsl%i/base.vs", GLSL_VERSION),
|
|
||||||
TextFormat("resources/shaders/glsl%i/rounded_rectangle.fs", GLSL_VERSION));
|
TextFormat("resources/shaders/glsl%i/rounded_rectangle.fs", GLSL_VERSION));
|
||||||
|
|
||||||
// Organized into an array for easy access
|
// Create a rounded rectangle
|
||||||
int rectangleShaderLocs[4] = {
|
RoundedRectangle roundedRectangle = CreateRoundedRectangle(
|
||||||
GetShaderLocation(rectangleShader, "rectangle"), // vec4, rectangle bounds (x, y, width, height, NOTE: Y axis is flipped)
|
(Vector4){ 5.0f, 10.0f, 15.0f, 20.0f }, // Corner radius
|
||||||
GetShaderLocation(rectangleShader, "radius"), // vec4, radius corners (top-left, top-right, bottom-left, bottom-right)
|
20.0f, // Shadow radius
|
||||||
GetShaderLocation(rectangleShader, "aaPower"), // float, anti-aliasing power
|
(Vector2){ 0.0f, -5.0f }, // Shadow offset
|
||||||
GetShaderLocation(rectangleShader, "aaDistance") // float, anti-aliasing distance
|
0.95f, // Shadow scale
|
||||||
};
|
5.0f, // Border thickness
|
||||||
|
shader // Shader
|
||||||
|
);
|
||||||
|
|
||||||
// Load the rectangle shadow shader which will draw the rectangle's shadow
|
// Update shader uniforms
|
||||||
Shader rectangleShadowShader = LoadShader(TextFormat("resources/shaders/glsl%i/base.vs", GLSL_VERSION),
|
UpdateRoundedRectangle(roundedRectangle, shader);
|
||||||
TextFormat("resources/shaders/glsl%i/rounded_rectangle_shadow.fs", GLSL_VERSION));
|
|
||||||
|
|
||||||
int rectangleShadowShaderLocs[8] = {
|
|
||||||
GetShaderLocation(rectangleShadowShader, "rectangle"), // vec4, rectangle bounds (x, y, width, height)
|
|
||||||
GetShaderLocation(rectangleShadowShader, "radius"), // vec4, radius corners (top-left, top-right, bottom-left, bottom-right)
|
|
||||||
GetShaderLocation(rectangleShadowShader, "shadowRadius"), // float, shadow radius
|
|
||||||
GetShaderLocation(rectangleShadowShader, "shadowPower"), // float, shadow power
|
|
||||||
GetShaderLocation(rectangleShadowShader, "shadowOffset"), // vec2, shadow offset (NOTE: Y axis is flipped)
|
|
||||||
GetShaderLocation(rectangleShadowShader, "shadowScale"), // float, shadow scale
|
|
||||||
GetShaderLocation(rectangleShadowShader, "aaPower"), // float, anti-aliasing power
|
|
||||||
GetShaderLocation(rectangleShadowShader, "aaDistance") // float, anti-aliasing distance
|
|
||||||
};
|
|
||||||
|
|
||||||
// Load the rectangle border shader which will draw the rectangle's border
|
|
||||||
Shader rectangleBorderShader = LoadShader(TextFormat("resources/shaders/glsl%i/base.vs", GLSL_VERSION),
|
|
||||||
TextFormat("resources/shaders/glsl%i/rounded_rectangle_border.fs", GLSL_VERSION));
|
|
||||||
|
|
||||||
int rectangleBorderShaderLocs[5] = {
|
|
||||||
GetShaderLocation(rectangleBorderShader, "rectangle"), // vec4, rectangle bounds (x, y, width, height)
|
|
||||||
GetShaderLocation(rectangleBorderShader, "radius"), // vec4, radius corners (top-left, top-right, bottom-left, bottom-right)
|
|
||||||
GetShaderLocation(rectangleBorderShader, "borderThickness"), // float, border thickness
|
|
||||||
GetShaderLocation(rectangleBorderShader, "aaPower"), // float, anti-aliasing power
|
|
||||||
GetShaderLocation(rectangleBorderShader, "aaDistance") // float, anti-aliasing distance
|
|
||||||
};
|
|
||||||
//--------------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
// Set parameters
|
|
||||||
//--------------------------------------------------------------------------------------
|
|
||||||
// Set 4 radius values for the rounded corners in pixels (top-left, top-right, bottom-left, bottom-right)
|
|
||||||
SetShaderValue(rectangleShader, rectangleShaderLocs[1], (float[]){ 5.0f, 10.0f, 15.0f, 20.0f }, SHADER_UNIFORM_VEC4);
|
|
||||||
SetShaderValue(rectangleShadowShader, rectangleShadowShaderLocs[1], (float[]){ 5.0f, 10.0f, 15.0f, 20.0f }, SHADER_UNIFORM_VEC4);
|
|
||||||
SetShaderValue(rectangleBorderShader, rectangleBorderShaderLocs[1], (float[]){ 5.0f, 10.0f, 15.0f, 20.0f }, SHADER_UNIFORM_VEC4);
|
|
||||||
|
|
||||||
// Set shadow parameters (in pixels)
|
|
||||||
SetShaderValue(rectangleShadowShader, rectangleShadowShaderLocs[2], (float[]){ 20.0f }, SHADER_UNIFORM_FLOAT); // Shadow radius
|
|
||||||
SetShaderValue(rectangleShadowShader, rectangleShadowShaderLocs[3], (float[]){ 1.5f }, SHADER_UNIFORM_FLOAT); // Shadow power
|
|
||||||
SetShaderValue(rectangleShadowShader, rectangleShadowShaderLocs[4], (float[]){ 0.0f, -5.0f }, SHADER_UNIFORM_VEC2); // Shadow offset
|
|
||||||
SetShaderValue(rectangleShadowShader, rectangleShadowShaderLocs[5], (float[]){ 0.95f }, SHADER_UNIFORM_FLOAT); // Shadow scale
|
|
||||||
|
|
||||||
// Set border parameters (in pixels)
|
|
||||||
SetShaderValue(rectangleBorderShader, rectangleBorderShaderLocs[2], (float[]){ 5.0f }, SHADER_UNIFORM_FLOAT); // Border thickness
|
|
||||||
|
|
||||||
// Set anti-aliasing (power and distance) parameters for all shaders
|
|
||||||
SetShaderValue(rectangleShader, rectangleShaderLocs[2], (float[]){ 1.5f }, SHADER_UNIFORM_FLOAT);
|
|
||||||
SetShaderValue(rectangleShader, rectangleShaderLocs[3], (float[]){ 1.0f }, SHADER_UNIFORM_FLOAT);
|
|
||||||
SetShaderValue(rectangleShadowShader, rectangleShadowShaderLocs[6], (float[]){ 1.5f }, SHADER_UNIFORM_FLOAT);
|
|
||||||
SetShaderValue(rectangleShadowShader, rectangleShadowShaderLocs[7], (float[]){ 1.0f }, SHADER_UNIFORM_FLOAT);
|
|
||||||
SetShaderValue(rectangleBorderShader, rectangleBorderShaderLocs[3], (float[]){ 1.5f }, SHADER_UNIFORM_FLOAT);
|
|
||||||
SetShaderValue(rectangleBorderShader, rectangleBorderShaderLocs[4], (float[]){ 1.0f }, SHADER_UNIFORM_FLOAT);
|
|
||||||
|
|
||||||
//--------------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
SetTargetFPS(60);
|
SetTargetFPS(60);
|
||||||
//--------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------
|
||||||
|
|
@ -116,78 +106,82 @@ int main(void)
|
||||||
|
|
||||||
ClearBackground(RAYWHITE);
|
ClearBackground(RAYWHITE);
|
||||||
|
|
||||||
// NOTE: Draw rectangle's shadow first using shader
|
// Draw rectangle box with rounded corners using shader
|
||||||
DrawRectangleLines(30, 50, 150, 100, DARKGRAY);
|
|
||||||
DrawText("Rectangle shadow shader", 30, 35, 10, DARKGRAY);
|
|
||||||
|
|
||||||
Rectangle rec = { 50, 70, 110, 60 };
|
Rectangle rec = { 50, 70, 110, 60 };
|
||||||
|
DrawRectangleLines(rec.x - 20, rec.y - 20, rec.width + 40, rec.height + 40, DARKGRAY);
|
||||||
|
DrawText("Rounded rectangle", rec.x - 20, rec.y - 35, 10, DARKGRAY);
|
||||||
|
|
||||||
// Flip Y axis to match shader coordinate system
|
// Flip Y axis to match shader coordinate system
|
||||||
rec.y = GetScreenHeight() - rec.y - rec.height;
|
rec.y = screenHeight - rec.y - rec.height;
|
||||||
|
SetShaderValue(shader, roundedRectangle.rectangleLoc, (float[]){ rec.x, rec.y, rec.width, rec.height }, SHADER_UNIFORM_VEC4);
|
||||||
|
|
||||||
SetShaderValue(rectangleShadowShader, rectangleShadowShaderLocs[0], (float[]){ rec.x, rec.y, rec.width, rec.height }, SHADER_UNIFORM_VEC4);
|
// Only rectangle color
|
||||||
|
SetShaderValue(shader, roundedRectangle.colorLoc, (float[]) { rectangleColor.r/255.0f, rectangleColor.g/255.0f, rectangleColor.b/255.0f, rectangleColor.a/255.0f }, SHADER_UNIFORM_VEC4);
|
||||||
|
SetShaderValue(shader, roundedRectangle.shadowColorLoc, (float[]) { 0.0f, 0.0f, 0.0f, 0.0f }, SHADER_UNIFORM_VEC4);
|
||||||
|
SetShaderValue(shader, roundedRectangle.borderColorLoc, (float[]) { 0.0f, 0.0f, 0.0f, 0.0f }, SHADER_UNIFORM_VEC4);
|
||||||
|
|
||||||
BeginShaderMode(rectangleShadowShader);
|
BeginShaderMode(shader);
|
||||||
DrawRectangle(0, 0, GetScreenWidth(), GetScreenHeight(), DARKBLUE);
|
DrawRectangle(0, 0, screenWidth, screenHeight, WHITE);
|
||||||
EndShaderMode();
|
EndShaderMode();
|
||||||
|
|
||||||
// Draw rectangle box with rounded corners using shader
|
|
||||||
DrawRectangleLines(30, 180, 150, 100, DARKGRAY);
|
|
||||||
DrawText("Rounded rectangle shader", 30, 165, 10, DARKGRAY);
|
|
||||||
|
|
||||||
|
|
||||||
|
// Draw rectangle shadow using shader
|
||||||
rec = (Rectangle){ 50, 200, 110, 60 };
|
rec = (Rectangle){ 50, 200, 110, 60 };
|
||||||
rec.y = GetScreenHeight() - rec.y - rec.height;
|
DrawRectangleLines(rec.x - 20, rec.y - 20, rec.width + 40, rec.height + 40, DARKGRAY);
|
||||||
|
DrawText("Rounded rectangle shadow", rec.x - 20, rec.y - 35, 10, DARKGRAY);
|
||||||
|
|
||||||
SetShaderValue(rectangleShader, rectangleShaderLocs[0], (float[]){ rec.x, rec.y, rec.width, rec.height }, SHADER_UNIFORM_VEC4);
|
rec.y = screenHeight - rec.y - rec.height;
|
||||||
|
SetShaderValue(shader, roundedRectangle.rectangleLoc, (float[]){ rec.x, rec.y, rec.width, rec.height }, SHADER_UNIFORM_VEC4);
|
||||||
|
|
||||||
BeginShaderMode(rectangleShader);
|
// Only shadow color
|
||||||
DrawRectangle(0, 0, GetScreenWidth(), GetScreenHeight(), BLUE);
|
SetShaderValue(shader, roundedRectangle.colorLoc, (float[]) { 0.0f, 0.0f, 0.0f, 0.0f }, SHADER_UNIFORM_VEC4);
|
||||||
|
SetShaderValue(shader, roundedRectangle.shadowColorLoc, (float[]) { shadowColor.r/255.0f, shadowColor.g/255.0f, shadowColor.b/255.0f, shadowColor.a/255.0f }, SHADER_UNIFORM_VEC4);
|
||||||
|
SetShaderValue(shader, roundedRectangle.borderColorLoc, (float[]) { 0.0f, 0.0f, 0.0f, 0.0f }, SHADER_UNIFORM_VEC4);
|
||||||
|
|
||||||
|
BeginShaderMode(shader);
|
||||||
|
DrawRectangle(0, 0, screenWidth, screenHeight, WHITE);
|
||||||
EndShaderMode();
|
EndShaderMode();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Draw rectangle's border using shader
|
// Draw rectangle's border using shader
|
||||||
DrawRectangleLines(30, 310, 150, 100, DARKGRAY);
|
|
||||||
DrawText("Rectangle border shader", 30, 295, 10, DARKGRAY);
|
|
||||||
|
|
||||||
rec = (Rectangle){ 50, 330, 110, 60 };
|
rec = (Rectangle){ 50, 330, 110, 60 };
|
||||||
rec.y = GetScreenHeight() - rec.y - rec.height;
|
DrawRectangleLines(rec.x - 20, rec.y - 20, rec.width + 40, rec.height + 40, DARKGRAY);
|
||||||
|
DrawText("Rounded rectangle border", rec.x - 20, rec.y - 35, 10, DARKGRAY);
|
||||||
|
|
||||||
SetShaderValue(rectangleBorderShader, rectangleBorderShaderLocs[0], (float[]){ rec.x, rec.y, rec.width, rec.height }, SHADER_UNIFORM_VEC4);
|
rec.y = screenHeight - rec.y - rec.height;
|
||||||
|
SetShaderValue(shader, roundedRectangle.rectangleLoc, (float[]){ rec.x, rec.y, rec.width, rec.height }, SHADER_UNIFORM_VEC4);
|
||||||
|
|
||||||
BeginShaderMode(rectangleBorderShader);
|
// Only border color
|
||||||
DrawRectangle(0, 0, GetScreenWidth(), GetScreenHeight(), SKYBLUE);
|
SetShaderValue(shader, roundedRectangle.colorLoc, (float[]) { 0.0f, 0.0f, 0.0f, 0.0f }, SHADER_UNIFORM_VEC4);
|
||||||
|
SetShaderValue(shader, roundedRectangle.shadowColorLoc, (float[]) { 0.0f, 0.0f, 0.0f, 0.0f }, SHADER_UNIFORM_VEC4);
|
||||||
|
SetShaderValue(shader, roundedRectangle.borderColorLoc, (float[]) { borderColor.r/255.0f, borderColor.g/255.0f, borderColor.b/255.0f, borderColor.a/255.0f }, SHADER_UNIFORM_VEC4);
|
||||||
|
|
||||||
|
BeginShaderMode(shader);
|
||||||
|
DrawRectangle(0, 0, screenWidth, screenHeight, WHITE);
|
||||||
EndShaderMode();
|
EndShaderMode();
|
||||||
|
|
||||||
// Draw one more rectangle with all three combined
|
|
||||||
//--------------------------------------------------------------------------------------------------
|
|
||||||
DrawRectangleLines(210, 50, 560, 360, DARKGRAY);
|
|
||||||
DrawText("Rectangle all three combined", 210, 35, 10, DARKGRAY);
|
|
||||||
|
|
||||||
|
|
||||||
|
// Draw one more rectangle with all three colors
|
||||||
rec = (Rectangle){ 240, 80, 500, 300 };
|
rec = (Rectangle){ 240, 80, 500, 300 };
|
||||||
rec.y = GetScreenHeight() - rec.y - rec.height;
|
DrawRectangleLines(rec.x - 30, rec.y - 30, rec.width + 60, rec.height + 60, DARKGRAY);
|
||||||
|
DrawText("Rectangle with all three combined", rec.x - 30, rec.y - 45, 10, DARKGRAY);
|
||||||
|
|
||||||
// Draw shadow
|
rec.y = screenHeight - rec.y - rec.height;
|
||||||
SetShaderValue(rectangleShadowShader, rectangleShadowShaderLocs[0], (float[]){ rec.x, rec.y, rec.width, rec.height }, SHADER_UNIFORM_VEC4);
|
SetShaderValue(shader, roundedRectangle.rectangleLoc, (float[]){ rec.x, rec.y, rec.width, rec.height }, SHADER_UNIFORM_VEC4);
|
||||||
|
|
||||||
BeginShaderMode(rectangleShadowShader);
|
// All three colors
|
||||||
DrawRectangle(0, 0, GetScreenWidth(), GetScreenHeight(), DARKBLUE);
|
SetShaderValue(shader, roundedRectangle.colorLoc, (float[]) { rectangleColor.r/255.0f, rectangleColor.g/255.0f, rectangleColor.b/255.0f, rectangleColor.a/255.0f }, SHADER_UNIFORM_VEC4);
|
||||||
|
SetShaderValue(shader, roundedRectangle.shadowColorLoc, (float[]) { shadowColor.r/255.0f, shadowColor.g/255.0f, shadowColor.b/255.0f, shadowColor.a/255.0f }, SHADER_UNIFORM_VEC4);
|
||||||
|
SetShaderValue(shader, roundedRectangle.borderColorLoc, (float[]) { borderColor.r/255.0f, borderColor.g/255.0f, borderColor.b/255.0f, borderColor.a/255.0f }, SHADER_UNIFORM_VEC4);
|
||||||
|
|
||||||
|
BeginShaderMode(shader);
|
||||||
|
DrawRectangle(0, 0, screenWidth, screenHeight, WHITE);
|
||||||
EndShaderMode();
|
EndShaderMode();
|
||||||
|
|
||||||
// Draw rectangle
|
DrawText("(c) Rounded rectangle SDF by Iñigo Quilez. MIT License.", screenWidth - 300, screenHeight - 20, 10, BLACK);
|
||||||
SetShaderValue(rectangleShader, rectangleShaderLocs[0], (float[]){ rec.x, rec.y, rec.width, rec.height }, SHADER_UNIFORM_VEC4);
|
|
||||||
|
|
||||||
BeginShaderMode(rectangleShader);
|
|
||||||
DrawRectangle(0, 0, GetScreenWidth(), GetScreenHeight(), BLUE);
|
|
||||||
EndShaderMode();
|
|
||||||
|
|
||||||
// Draw border
|
|
||||||
SetShaderValue(rectangleBorderShader, rectangleBorderShaderLocs[0], (float[]){ rec.x, rec.y, rec.width, rec.height }, SHADER_UNIFORM_VEC4);
|
|
||||||
|
|
||||||
BeginShaderMode(rectangleBorderShader);
|
|
||||||
DrawRectangle(0, 0, GetScreenWidth(), GetScreenHeight(), SKYBLUE);
|
|
||||||
EndShaderMode();
|
|
||||||
//--------------------------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
DrawText("(c) Rounded rectangle SDF by Iñigo Quilez. MIT License.", GetScreenWidth() - 300, GetScreenHeight() - 20, 10, BLACK);
|
|
||||||
|
|
||||||
EndDrawing();
|
EndDrawing();
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
|
|
@ -195,14 +189,50 @@ int main(void)
|
||||||
|
|
||||||
// De-Initialization
|
// De-Initialization
|
||||||
//--------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------
|
||||||
|
UnloadShader(shader); // Unload shader
|
||||||
// Unload shader
|
|
||||||
UnloadShader(rectangleShader);
|
|
||||||
UnloadShader(rectangleShadowShader);
|
|
||||||
UnloadShader(rectangleBorderShader);
|
|
||||||
|
|
||||||
CloseWindow(); // Close window and OpenGL context
|
CloseWindow(); // Close window and OpenGL context
|
||||||
//--------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------------
|
||||||
|
// Module Functions Definitions
|
||||||
|
//------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// Create a rounded rectangle and set uniform locations
|
||||||
|
RoundedRectangle CreateRoundedRectangle(Vector4 cornerRadius, float shadowRadius, Vector2 shadowOffset, float shadowScale, float borderThickness, Shader shader)
|
||||||
|
{
|
||||||
|
RoundedRectangle rec;
|
||||||
|
rec.cornerRadius = cornerRadius;
|
||||||
|
rec.shadowRadius = shadowRadius;
|
||||||
|
rec.shadowOffset = shadowOffset;
|
||||||
|
rec.shadowScale = shadowScale;
|
||||||
|
rec.borderThickness = borderThickness;
|
||||||
|
|
||||||
|
// Get shader uniform locations
|
||||||
|
rec.rectangleLoc = GetShaderLocation(shader, "rectangle");
|
||||||
|
rec.radiusLoc = GetShaderLocation(shader, "radius");
|
||||||
|
rec.colorLoc = GetShaderLocation(shader, "color");
|
||||||
|
rec.shadowRadiusLoc = GetShaderLocation(shader, "shadowRadius");
|
||||||
|
rec.shadowOffsetLoc = GetShaderLocation(shader, "shadowOffset");
|
||||||
|
rec.shadowScaleLoc = GetShaderLocation(shader, "shadowScale");
|
||||||
|
rec.shadowColorLoc = GetShaderLocation(shader, "shadowColor");
|
||||||
|
rec.borderThicknessLoc = GetShaderLocation(shader, "borderThickness");
|
||||||
|
rec.borderColorLoc = GetShaderLocation(shader, "borderColor");
|
||||||
|
|
||||||
|
UpdateRoundedRectangle(rec, shader);
|
||||||
|
|
||||||
|
return rec;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update rounded rectangle uniforms
|
||||||
|
void UpdateRoundedRectangle(RoundedRectangle rec, Shader shader)
|
||||||
|
{
|
||||||
|
SetShaderValue(shader, rec.radiusLoc, (float[]){ rec.cornerRadius.x, rec.cornerRadius.y, rec.cornerRadius.z, rec.cornerRadius.w }, SHADER_UNIFORM_VEC4);
|
||||||
|
SetShaderValue(shader, rec.shadowRadiusLoc, &rec.shadowRadius, SHADER_UNIFORM_FLOAT);
|
||||||
|
SetShaderValue(shader, rec.shadowOffsetLoc, (float[]){ rec.shadowOffset.x, rec.shadowOffset.y }, SHADER_UNIFORM_VEC2);
|
||||||
|
SetShaderValue(shader, rec.shadowScaleLoc, &rec.shadowScale, SHADER_UNIFORM_FLOAT);
|
||||||
|
SetShaderValue(shader, rec.borderThicknessLoc, &rec.borderThickness, SHADER_UNIFORM_FLOAT);
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user