Add Canvas shaders for the core profile
This commit is contained in:
parent
161ff44981
commit
a0db21db7f
4 changed files with 281 additions and 0 deletions
17
Shaders/Canvas/image.frag
Normal file
17
Shaders/Canvas/image.frag
Normal file
|
@ -0,0 +1,17 @@
|
|||
#version 410 core
|
||||
|
||||
out vec4 fragColor;
|
||||
|
||||
in VS_OUT {
|
||||
vec2 texcoord;
|
||||
vec4 vertex_color;
|
||||
} fs_in;
|
||||
|
||||
uniform sampler2D tex;
|
||||
|
||||
void main()
|
||||
{
|
||||
vec4 texel = texture(tex, fs_in.texcoord);
|
||||
// Modulate by the fill color (stored in the vertex color)
|
||||
fragColor = texel * fs_in.vertex_color;
|
||||
}
|
19
Shaders/Canvas/image.vert
Normal file
19
Shaders/Canvas/image.vert
Normal file
|
@ -0,0 +1,19 @@
|
|||
#version 410 core
|
||||
|
||||
layout(location = 0) in vec4 pos;
|
||||
layout(location = 2) in vec4 vertex_color;
|
||||
layout(location = 3) in vec4 multitexcoord0;
|
||||
|
||||
out VS_OUT {
|
||||
vec2 texcoord;
|
||||
vec4 vertex_color;
|
||||
} vs_out;
|
||||
|
||||
uniform mat4 osg_ModelViewProjectionMatrix;
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_Position = osg_ModelViewProjectionMatrix * pos;
|
||||
vs_out.texcoord = multitexcoord0.st;
|
||||
vs_out.vertex_color = vertex_color;
|
||||
}
|
226
Shaders/Canvas/text.frag
Normal file
226
Shaders/Canvas/text.frag
Normal file
|
@ -0,0 +1,226 @@
|
|||
#version 410 core
|
||||
|
||||
#pragma import_defines(BACKDROP_COLOR, SHADOW, OUTLINE)
|
||||
#pragma import_defines(SIGNED_DISTANCE_FIELD, TEXTURE_DIMENSION, GLYPH_DIMENSION)
|
||||
|
||||
#if 0
|
||||
# define ALPHA r
|
||||
# define SDF g
|
||||
#else
|
||||
# define ALPHA a
|
||||
# define SDF r
|
||||
#endif
|
||||
|
||||
out vec4 fragColor;
|
||||
|
||||
in VS_OUT {
|
||||
vec2 texcoord;
|
||||
vec4 vertex_color;
|
||||
} fs_in;
|
||||
|
||||
uniform sampler2D glyphTexture;
|
||||
|
||||
#ifndef TEXTURE_DIMENSION
|
||||
const float TEXTURE_DIMENSION = 1024.0;
|
||||
#endif
|
||||
|
||||
#ifndef GLYPH_DIMENSION
|
||||
const float GLYPH_DIMENSION = 32.0;
|
||||
#endif
|
||||
|
||||
#ifdef SIGNED_DISTANCE_FIELD
|
||||
|
||||
float distanceFromEdge(vec2 tc)
|
||||
{
|
||||
float center_alpha = textureLod(glyphTexture, tc, 0.0).SDF;
|
||||
if (center_alpha==0.0) return -1.0;
|
||||
|
||||
//float distance_scale = (1.0/4.0)*1.41;
|
||||
float distance_scale = (1.0/6.0)*1.41;
|
||||
//float distance_scale = (1.0/8.0)*1.41;
|
||||
|
||||
return (center_alpha-0.5)*distance_scale;
|
||||
}
|
||||
|
||||
#ifdef OUTLINE
|
||||
vec2 colorCoeff(float edge_distance, float blend_width, float blend_half_width)
|
||||
{
|
||||
float outline_width = OUTLINE * 0.5;
|
||||
if (edge_distance > blend_half_width) {
|
||||
return vec2(1.0, 0.0);
|
||||
} else if (edge_distance > -blend_half_width) {
|
||||
float f = smoothstep(0.0, 1.0, (blend_half_width-edge_distance)/(blend_width));
|
||||
return vec2(1.0 - f, f);
|
||||
} else if (edge_distance > (blend_half_width - outline_width)) {
|
||||
return vec2(0.0, 1.0);
|
||||
} else if (edge_distance > -(outline_width + blend_half_width)) {
|
||||
return vec2(0.0, smoothstep(0.0, 1.0, (blend_half_width + outline_width + edge_distance) / blend_width));
|
||||
} else {
|
||||
return vec2(0.0, 0.0);
|
||||
}
|
||||
}
|
||||
#else
|
||||
float colorCoeff(float edge_distance, float blend_width, float blend_half_width)
|
||||
{
|
||||
if (edge_distance>blend_half_width) {
|
||||
return 1.0;
|
||||
} else if (edge_distance>-blend_half_width) {
|
||||
return smoothstep(1.0, 0.0, (blend_half_width-edge_distance)/(blend_width));
|
||||
} else {
|
||||
return 0.0;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
vec4 textColor(vec2 src_texcoord)
|
||||
{
|
||||
float sample_distance_scale = 0.75;
|
||||
vec2 dx = dFdx(src_texcoord)*sample_distance_scale;
|
||||
vec2 dy = dFdy(src_texcoord)*sample_distance_scale;
|
||||
|
||||
float distance_across_pixel = length(dx+dy)*(TEXTURE_DIMENSION/GLYPH_DIMENSION);
|
||||
|
||||
// compute the appropriate number of samples required to avoid aliasing.
|
||||
int maxNumSamplesAcrossSide = 4;
|
||||
|
||||
int numSamplesX = int(TEXTURE_DIMENSION * length(dx));
|
||||
int numSamplesY = int(TEXTURE_DIMENSION * length(dy));
|
||||
if (numSamplesX < 2) numSamplesX = 2;
|
||||
if (numSamplesY < 2) numSamplesY = 2;
|
||||
if (numSamplesX > maxNumSamplesAcrossSide) numSamplesX = maxNumSamplesAcrossSide;
|
||||
if (numSamplesY > maxNumSamplesAcrossSide) numSamplesY = maxNumSamplesAcrossSide;
|
||||
|
||||
vec2 delta_tx = dx/float(numSamplesX-1);
|
||||
vec2 delta_ty = dy/float(numSamplesY-1);
|
||||
|
||||
float numSamples = float(numSamplesX)*float(numSamplesY);
|
||||
float blend_width = 1.5*distance_across_pixel/numSamples;
|
||||
float blend_half_width = blend_width*0.5;
|
||||
|
||||
// check whether fragment is wholly within or outwith glyph body+outline
|
||||
float cd = distanceFromEdge(src_texcoord); // central distance (distance from center to edge)
|
||||
if (cd - blend_half_width > distance_across_pixel) return fs_in.vertex_color; // pixel fully within glyph body
|
||||
|
||||
#ifdef OUTLINE
|
||||
float outline_width = OUTLINE * 0.5;
|
||||
if ((-cd - outline_width - blend_half_width) > distance_across_pixel)
|
||||
return vec4(0.0); // pixel fully outside outline+glyph body
|
||||
vec2 color_coeff = vec2(0.0, 0.0);
|
||||
#else
|
||||
if (-cd - blend_half_width > distance_across_pixel)
|
||||
return vec4(0.0); // pixel fully outside glyph body
|
||||
float color_coeff = 0.0;
|
||||
#endif
|
||||
|
||||
// use multi-sampling to provide high quality antialised fragments
|
||||
vec2 origin = src_texcoord - dx*0.5 - dy*0.5;
|
||||
for(;numSamplesY>0; --numSamplesY) {
|
||||
vec2 pos = origin;
|
||||
int numX = numSamplesX;
|
||||
for(;numX>0; --numX) {
|
||||
#ifdef OUTLINE
|
||||
color_coeff += colorCoeff(distanceFromEdge(pos), blend_width, blend_half_width);
|
||||
#else
|
||||
color_coeff += colorCoeff(distanceFromEdge(pos), blend_width, blend_half_width);
|
||||
#endif
|
||||
pos += delta_tx;
|
||||
}
|
||||
origin += delta_ty;
|
||||
}
|
||||
color_coeff /= numSamples;
|
||||
|
||||
#ifdef OUTLINE
|
||||
float vertex_alpha = fs_in.vertex_color.a * color_coeff.x;
|
||||
float outline_alpha = BACKDROP_COLOR.a * color_coeff.y;
|
||||
float total_alpha = vertex_alpha + outline_alpha;
|
||||
|
||||
if (total_alpha <= 0.0)
|
||||
return vec4(0.0, 0.0, 0.0, 0.0);
|
||||
|
||||
return vec4(fs_in.vertex_color.rgb * (vertex_alpha / total_alpha)
|
||||
+ BACKDROP_COLOR.rgb * (outline_alpha / total_alpha), total_alpha);
|
||||
#else
|
||||
return vec4(fs_in.vertex_color.rgb, fs_in.vertex_color.a * color_coeff);
|
||||
#endif
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
vec4 textColor(vec2 src_texcoord)
|
||||
{
|
||||
#ifdef OUTLINE
|
||||
float alpha = texture(glyphTexture, src_texcoord).ALPHA;
|
||||
float delta_tc = 1.6 * OUTLINE * GLYPH_DIMENSION / TEXTURE_DIMENSION;
|
||||
|
||||
float outline_alpha = alpha;
|
||||
vec2 origin = src_texcoord - vec2(delta_tc*0.5, delta_tc*0.5);
|
||||
|
||||
float numSamples = 3.0;
|
||||
delta_tc = delta_tc / (numSamples - 1.0);
|
||||
|
||||
float background_alpha = 1.0;
|
||||
|
||||
for(float i=0.0; i < numSamples; ++i) {
|
||||
for(float j=0.0; j < numSamples; ++j) {
|
||||
float local_alpha = texture(glyphTexture, origin + vec2(i*delta_tc, j*delta_tc)).ALPHA;
|
||||
outline_alpha = max(outline_alpha, local_alpha);
|
||||
background_alpha = background_alpha * (1.0 - local_alpha);
|
||||
}
|
||||
}
|
||||
|
||||
float mipmapLevel = textureQueryLod(glyphTexture, src_texcoord).x;
|
||||
if (mipmapLevel < 1.0) {
|
||||
outline_alpha = mix(1.0 - background_alpha, outline_alpha, mipmapLevel / 1.0);
|
||||
}
|
||||
|
||||
if (outline_alpha < alpha) outline_alpha = alpha;
|
||||
if (outline_alpha > 1.0) outline_alpha = 1.0;
|
||||
|
||||
if (outline_alpha == 0.0) return vec4(0.0, 0.0, 0.0, 0.0); // outside glyph and outline
|
||||
|
||||
vec4 color = mix(BACKDROP_COLOR, fs_in.vertex_color, smoothstep(0.0, 1.0, alpha));
|
||||
color.a = fs_in.vertex_color.a * smoothstep(0.0, 1.0, outline_alpha);
|
||||
|
||||
return color;
|
||||
#else
|
||||
float alpha = texture(glyphTexture, src_texcoord).ALPHA;
|
||||
if (alpha == 0.0) vec4(0.0, 0.0, 0.0, 0.0);
|
||||
return vec4(fs_in.vertex_color.rgb, fs_in.vertex_color.a * alpha);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
void main()
|
||||
{
|
||||
if (fs_in.texcoord.x < 0.0 && fs_in.texcoord.y < 0.0) {
|
||||
fragColor = fs_in.vertex_color;
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef SHADOW
|
||||
float scale = -1.0 * GLYPH_DIMENSION / TEXTURE_DIMENSION;
|
||||
vec2 delta_tc = SHADOW * scale;
|
||||
vec4 shadow_color = textColor(fs_in.texcoord + delta_tc);
|
||||
shadow_color.rgb = BACKDROP_COLOR.rgb;
|
||||
|
||||
vec4 glyph_color = textColor(fs_in.texcoord);
|
||||
|
||||
// lower the alpha_power value the greater the staturation, no need to be so aggressive with SDF than GREYSCALE
|
||||
#if SIGNED_DISTANCE_FIELD
|
||||
float alpha_power = 0.6;
|
||||
#else
|
||||
float alpha_power = 0.5;
|
||||
#endif
|
||||
|
||||
// over saturate the alpha values to make sure the font and its shadow are clear
|
||||
shadow_color.a = pow(shadow_color.a, alpha_power);
|
||||
glyph_color.a = pow(glyph_color.a, alpha_power);
|
||||
vec4 color = mix(shadow_color, glyph_color, glyph_color.a);
|
||||
#else
|
||||
vec4 color = textColor(fs_in.texcoord);
|
||||
#endif
|
||||
|
||||
if (color.a == 0.0) discard;
|
||||
|
||||
fragColor = color;
|
||||
}
|
19
Shaders/Canvas/text.vert
Normal file
19
Shaders/Canvas/text.vert
Normal file
|
@ -0,0 +1,19 @@
|
|||
#version 410 core
|
||||
|
||||
layout(location = 0) in vec4 pos;
|
||||
layout(location = 2) in vec4 vertex_color;
|
||||
layout(location = 3) in vec4 multitexcoord0;
|
||||
|
||||
out VS_OUT {
|
||||
vec2 texcoord;
|
||||
vec4 vertex_color;
|
||||
} vs_out;
|
||||
|
||||
uniform mat4 osg_ModelViewProjectionMatrix;
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_Position = osg_ModelViewProjectionMatrix * pos;
|
||||
vs_out.texcoord = multitexcoord0.st;
|
||||
vs_out.vertex_color = vertex_color;
|
||||
}
|
Loading…
Add table
Reference in a new issue