port font shaders to new texture format

This commit is contained in:
Ronja 2021-02-09 15:37:50 +01:00
parent 83b933f8a7
commit 10e74c620d
4 changed files with 314 additions and 181 deletions

View file

@ -12,7 +12,14 @@ input View {
} }
input Font { input Font {
image2D pages[8] image2D page0,
image2D page1,
image2D page2,
image2D page3,
image2D page4,
image2D page5,
image2D page6,
image2D page7
} }
stage vertex vert( stage vertex vert(
@ -31,20 +38,20 @@ stage fragment frag(
fragment in { float4 color, float2 uv, float page }) fragment in { float4 color, float2 uv, float page })
{ {
int page = int(in.page); int page = int(in.page);
float4 msdf_sample = texture(input.font.pages[0], in.uv.xy); float4 msdf_sample = texture(input.font.page0, in.uv.xy);
if(page == 1) { msdf_sample = texture(input.font.pages[1], in.uv.xy); } if(page == 1) { msdf_sample = texture(input.font.page1, in.uv.xy); }
if(page == 2) { msdf_sample = texture(input.font.pages[2], in.uv.xy); } if(page == 2) { msdf_sample = texture(input.font.page2, in.uv.xy); }
if(page == 3) { msdf_sample = texture(input.font.pages[3], in.uv.xy); } if(page == 3) { msdf_sample = texture(input.font.page3, in.uv.xy); }
if(page == 4) { msdf_sample = texture(input.font.pages[4], in.uv.xy); } if(page == 4) { msdf_sample = texture(input.font.page4, in.uv.xy); }
if(page == 5) { msdf_sample = texture(input.font.pages[5], in.uv.xy); } if(page == 5) { msdf_sample = texture(input.font.page5, in.uv.xy); }
if(page == 6) { msdf_sample = texture(input.font.pages[6], in.uv.xy); } if(page == 6) { msdf_sample = texture(input.font.page6, in.uv.xy); }
if(page == 7) { msdf_sample = texture(input.font.pages[7], in.uv.xy); } if(page == 7) { msdf_sample = texture(input.font.page7, in.uv.xy); }
float r = msdf_sample.r; float r = msdf_sample.r;
float g = msdf_sample.g; float g = msdf_sample.g;
float b = msdf_sample.b; float b = msdf_sample.b;
float median = max(min(r, g), min(max(r, g), b)); float median = max(min(r, g), min(max(r, g), b));
float opacity = float(median > 0.5); float opacity = step(0.5, median);
stage.color[0] = float4(in.color.rgb, in.color.a * opacity); stage.color[0] = float4(in.color.rgb, in.color.a * opacity);
} }

View file

@ -21,43 +21,107 @@ material_basis = {
winding = "counter_clockwise" winding = "counter_clockwise"
layers = ["default"] layers = ["default"]
inputs = { inputs = {
font.pages = { font.page0 = {
type = "image" type = "image"
count = 8 value = {
value = [ type = "image2D"
{ sampler_state = "linear_repeat"
type = "image2D" }
sampler_state = "linear_repeat"
}
{
type = "image2D"
sampler_state = "linear_repeat"
}
{
type = "image2D"
sampler_state = "linear_repeat"
}
{
type = "image2D"
sampler_state = "linear_repeat"
}
{
type = "image2D"
sampler_state = "linear_repeat"
}
{
type = "image2D"
sampler_state = "linear_repeat"
}
{
type = "image2D"
sampler_state = "linear_repeat"
}
{
type = "image2D"
sampler_state = "linear_repeat"
}
]
} }
font.page1 = {
type = "image"
value = {
type = "image2D"
sampler_state = "linear_repeat"
}
}
font.page2 = {
type = "image"
value = {
type = "image2D"
sampler_state = "linear_repeat"
}
}
font.page3 = {
type = "image"
value = {
type = "image2D"
sampler_state = "linear_repeat"
}
}
font.page4 = {
type = "image"
value = {
type = "image2D"
sampler_state = "linear_repeat"
}
}
font.page5 = {
type = "image"
value = {
type = "image2D"
sampler_state = "linear_repeat"
}
}
font.page6 = {
type = "image"
value = {
type = "image2D"
sampler_state = "linear_repeat"
}
}
font.page7 = {
type = "image"
value = {
type = "image2D"
sampler_state = "linear_repeat"
}
}
// font.pages = {
// type = "image"
// count = 8
// value = [
// {
// type = "image2D"
// sampler_state = "linear_repeat"
// image = "luxe: image/empty"
// }
// {
// type = "image2D"
// sampler_state = "linear_repeat"
// image = "luxe: image/empty"
// }
// {
// type = "image2D"
// sampler_state = "linear_repeat"
// image = "luxe: image/empty"
// }
// {
// type = "image2D"
// sampler_state = "linear_repeat"
// image = "luxe: image/empty"
// }
// {
// type = "image2D"
// sampler_state = "linear_repeat"
// image = "luxe: image/empty"
// }
// {
// type = "image2D"
// sampler_state = "linear_repeat"
// image = "luxe: image/empty"
// }
// {
// type = "image2D"
// sampler_state = "linear_repeat"
// image = "luxe: image/empty"
// }
// {
// type = "image2D"
// sampler_state = "linear_repeat"
// image = "luxe: image/empty"
// }
// ]
// }
} }
} }

View file

@ -12,7 +12,14 @@ input View {
} }
input Font { input Font {
image2D pages[8] image2D page0,
image2D page1,
image2D page2,
image2D page3,
image2D page4,
image2D page5,
image2D page6,
image2D page7
} }
input UI { input UI {
@ -29,116 +36,115 @@ input FUI {
#0 image2D tex_mask #0 image2D tex_mask
} }
stage vertex vert( stage vertex vert(
input { View view, UI ui }, input { View view, UI ui },
vertex in { vertex in {
#0 float4 pos, #0 float4 pos,
#1 float4 color, #1 float4 color,
#2 float2 uv, #2 float2 uv,
#3 float4 data, #3 float4 data,
#4 float2 bounds #4 float2 bounds
}, },
fragment out { fragment out {
float4 color, float4 color,
float2 uv, float2 uv,
float2 mask_uv, float2 mask_uv,
float clip, float clip,
float page float page
}) })
{ {
out.uv = in.uv; out.uv = in.uv;
out.color = in.color; out.color = in.color;
out.clip = in.data.x; out.clip = in.data.x;
out.page = in.pos.w; out.page = in.pos.w;
//for fonts the text pos is text local and needs to be converted to canvas space. //for fonts the text pos is text local and needs to be converted to canvas space.
//we pass the bounds of the text item in via the vertices (I know) so we can calculate bounds-local space. //we pass the bounds of the text item in via the vertices (I know) so we can calculate bounds-local space.
//Then we convert that to canvas space, by * (bounds_w/canvas_w) //Then we convert that to canvas space, by * (bounds_w/canvas_w)
//Then finally we add to the canvas local u/v from the data.z/w in //Then finally we add to the canvas local u/v from the data.z/w in
float bounds_u = 0.0; float bounds_u = 0.0;
float bounds_v = 0.0; float bounds_v = 0.0;
if(in.bounds.x != 0.0) { bounds_u = (in.pos.x / in.bounds.x); } if(in.bounds.x != 0.0) { bounds_u = (in.pos.x / in.bounds.x); }
if(in.bounds.y != 0.0) { bounds_v = 1.0 - (in.pos.y / in.bounds.y); } if(in.bounds.y != 0.0) { bounds_v = 1.0 - (in.pos.y / in.bounds.y); }
//bounds_u/v is the 0...1 value for where this vert is in the text item itself //bounds_u/v is the 0...1 value for where this vert is in the text item itself
//Note we flip the bounds_v because the text is in world space, bottom left origin, y+ up, //Note we flip the bounds_v because the text is in world space, bottom left origin, y+ up,
//canvas space is top left, y+ down so it has to be reversed to be bounds local in canvas space //canvas space is top left, y+ down so it has to be reversed to be bounds local in canvas space
float to_canvas_u = in.bounds.x / input.ui.canvas_size.x; float to_canvas_u = in.bounds.x / input.ui.canvas_size.x;
float to_canvas_v = in.bounds.y / input.ui.canvas_size.y; float to_canvas_v = in.bounds.y / input.ui.canvas_size.y;
//to_canvas_u is the text item width and height in 0...1 relative to the canvas //to_canvas_u is the text item width and height in 0...1 relative to the canvas
//e.g if the text item width is 100 and the canvas is 200, the value is 0.5 //e.g if the text item width is 100 and the canvas is 200, the value is 0.5
//then what we do is add in.data.y/z which is the text x/y position, //then what we do is add in.data.y/z which is the text x/y position,
//but relative to the canvas space. we add this to shift the x/y into place. //but relative to the canvas space. we add this to shift the x/y into place.
bounds_u = (bounds_u * to_canvas_u) + in.data.y; bounds_u = (bounds_u * to_canvas_u) + in.data.y;
bounds_v = (bounds_v * to_canvas_v) + in.data.z; bounds_v = (bounds_v * to_canvas_v) + in.data.z;
out.mask_uv = float2(bounds_u, bounds_v); out.mask_uv = float2(bounds_u, bounds_v);
stage.pos = input.view.mvp * float4(in.pos.xyz, 1.0); stage.pos = input.view.mvp * float4(in.pos.xyz, 1.0);
} }
stage fragment frag( stage fragment frag(
input { FUI ui, Font font }, input { FUI ui, Font font },
fragment in { fragment in {
float4 color, float4 color,
float2 uv, float2 uv,
float2 mask_uv, float2 mask_uv,
float clip, float clip,
float page float page
}) })
{ {
//outside mask uvs? //outside mask uvs?
bool outside_mask = in.mask_uv.x < 0.0 || bool outside_mask = in.mask_uv.x < 0.0 ||
in.mask_uv.x > 1.0 || in.mask_uv.x > 1.0 ||
in.mask_uv.y < 0.0 || in.mask_uv.y < 0.0 ||
in.mask_uv.y > 1.0; in.mask_uv.y > 1.0;
if(outside_mask) { if(outside_mask) {
discard; discard;
// stage.color[0] = float4(1,0.2,0.3,1); // stage.color[0] = float4(1,0.2,0.3,1);
return; return;
} }
float4 mask = texture(input.ui.tex_mask, in.mask_uv); float4 mask = texture(input.ui.tex_mask, in.mask_uv);
//16 bit mask //16 bit mask
// float mask_clip = round(mask.r * 65535.0); // float mask_clip = round(mask.r * 65535.0);
//8 bit mask //8 bit mask
int lsb = int(round(mask.r * 255.0)); int lsb = int(round(mask.r * 255.0));
int msb = int(round(mask.g * 255.0)) * 256; //<< 8; int msb = int(round(mask.g * 255.0)) * 256; //<< 8;
int mask_clip = lsb | msb; int mask_clip = lsb | msb;
// int mask_clip = lsb + msb; //webgl1 // int mask_clip = lsb + msb; //webgl1
//outside our clipping bounds? //outside our clipping bounds?
int my_clip = int(in.clip); int my_clip = int(in.clip);
if(my_clip != 0 && mask_clip < my_clip) { if(my_clip != 0 && mask_clip < my_clip) {
discard; discard;
// stage.color[0] = float4(0,1,1,0.2); // stage.color[0] = float4(0,1,1,0.2);
return; return;
} }
int page = int(in.page); int page = int(in.page);
float4 msdf_sample = texture(input.font.pages[0], in.uv.xy); float4 msdf_sample = texture(input.font.page0, in.uv.xy);
if(page == 1) { msdf_sample = texture(input.font.pages[1], in.uv.xy); } if(page == 1) { msdf_sample = texture(input.font.page1, in.uv.xy); }
if(page == 2) { msdf_sample = texture(input.font.pages[2], in.uv.xy); } if(page == 2) { msdf_sample = texture(input.font.page2, in.uv.xy); }
if(page == 3) { msdf_sample = texture(input.font.pages[3], in.uv.xy); } if(page == 3) { msdf_sample = texture(input.font.page3, in.uv.xy); }
if(page == 4) { msdf_sample = texture(input.font.pages[4], in.uv.xy); } if(page == 4) { msdf_sample = texture(input.font.page4, in.uv.xy); }
if(page == 5) { msdf_sample = texture(input.font.pages[5], in.uv.xy); } if(page == 5) { msdf_sample = texture(input.font.page5, in.uv.xy); }
if(page == 6) { msdf_sample = texture(input.font.pages[6], in.uv.xy); } if(page == 6) { msdf_sample = texture(input.font.page6, in.uv.xy); }
if(page == 7) { msdf_sample = texture(input.font.pages[7], in.uv.xy); } if(page == 7) { msdf_sample = texture(input.font.page7, in.uv.xy); }
float r = msdf_sample.r; float r = msdf_sample.r;
float g = msdf_sample.g; float g = msdf_sample.g;
float b = msdf_sample.b; float b = msdf_sample.b;
float median = max(min(r, g), min(max(r, g), b)); float median = max(min(r, g), min(max(r, g), b));
float opacity = float(median > 0.5); float opacity = step(0.5, median);
stage.color[0] = float4(in.color.rgb, in.color.a * opacity * mask.a); stage.color[0] = float4(in.color.rgb, in.color.a * opacity * mask.a);
}
}

View file

@ -28,44 +28,100 @@ material_basis = {
sampler_state = "nearest_clamp" sampler_state = "nearest_clamp"
} }
} }
font.pages = { font.page0 = {
type = "image" type = "image"
count = 8 value = {
value = [ type = "image2D"
{ sampler_state = "linear_repeat"
type = "image2D" }
sampler_state = "linear_repeat"
}
{
type = "image2D"
sampler_state = "linear_repeat"
}
{
type = "image2D"
sampler_state = "linear_repeat"
}
{
type = "image2D"
sampler_state = "linear_repeat"
}
{
type = "image2D"
sampler_state = "linear_repeat"
}
{
type = "image2D"
sampler_state = "linear_repeat"
}
{
type = "image2D"
sampler_state = "linear_repeat"
}
{
type = "image2D"
sampler_state = "linear_repeat"
}
]
} }
font.page1 = {
type = "image"
value = {
type = "image2D"
sampler_state = "linear_repeat"
}
}
font.page2 = {
type = "image"
value = {
type = "image2D"
sampler_state = "linear_repeat"
}
}
font.page3 = {
type = "image"
value = {
type = "image2D"
sampler_state = "linear_repeat"
}
}
font.page4 = {
type = "image"
value = {
type = "image2D"
sampler_state = "linear_repeat"
}
}
font.page5 = {
type = "image"
value = {
type = "image2D"
sampler_state = "linear_repeat"
}
}
font.page6 = {
type = "image"
value = {
type = "image2D"
sampler_state = "linear_repeat"
}
}
font.page7 = {
type = "image"
value = {
type = "image2D"
sampler_state = "linear_repeat"
}
}
// font.pages = {
// type = "image"
// count = 8
// value = [
// {
// type = "image2D"
// sampler_state = "linear_repeat"
// }
// {
// type = "image2D"
// sampler_state = "linear_repeat"
// }
// {
// type = "image2D"
// sampler_state = "linear_repeat"
// }
// {
// type = "image2D"
// sampler_state = "linear_repeat"
// }
// {
// type = "image2D"
// sampler_state = "linear_repeat"
// }
// {
// type = "image2D"
// sampler_state = "linear_repeat"
// }
// {
// type = "image2D"
// sampler_state = "linear_repeat"
// }
// {
// type = "image2D"
// sampler_state = "linear_repeat"
// }
// ]
// }
ui.canvas_size = { ui.canvas_size = {
type = "float2" type = "float2"
value = [1 1] value = [1 1]