Improve shader example for outlined rect + outlined circle
This commit is contained in:
parent
e61a294960
commit
9338ec248b
4 changed files with 105 additions and 20 deletions
4
build.c
4
build.c
|
@ -37,10 +37,10 @@ typedef struct Context_Extra {
|
||||||
|
|
||||||
// #include "oogabooga/examples/text_rendering.c"
|
// #include "oogabooga/examples/text_rendering.c"
|
||||||
// #include "oogabooga/examples/custom_logger.c"
|
// #include "oogabooga/examples/custom_logger.c"
|
||||||
#include "oogabooga/examples/renderer_stress_test.c"
|
// #include "oogabooga/examples/renderer_stress_test.c"
|
||||||
// #include "oogabooga/examples/tile_game.c"
|
// #include "oogabooga/examples/tile_game.c"
|
||||||
// #include "oogabooga/examples/audio_test.c"
|
// #include "oogabooga/examples/audio_test.c"
|
||||||
// #include "oogabooga/examples/custom_shader.c"
|
#include "oogabooga/examples/custom_shader.c"
|
||||||
|
|
||||||
// This is where you swap in your own project!
|
// This is where you swap in your own project!
|
||||||
// #include "entry_yourepicgamename.c"
|
// #include "entry_yourepicgamename.c"
|
||||||
|
|
|
@ -10,12 +10,15 @@ typedef struct My_Cbuffer {
|
||||||
// We implement these details which we implement in the shader
|
// We implement these details which we implement in the shader
|
||||||
#define DETAIL_TYPE_ROUNDED_CORNERS 1
|
#define DETAIL_TYPE_ROUNDED_CORNERS 1
|
||||||
#define DETAIL_TYPE_OUTLINED 2
|
#define DETAIL_TYPE_OUTLINED 2
|
||||||
|
#define DETAIL_TYPE_OUTLINED_CIRCLE 3
|
||||||
|
|
||||||
// With custom shading we can extend the rendering library!
|
// With custom shading we can extend the rendering library!
|
||||||
Draw_Quad *draw_rounded_rect(Vector2 p, Vector2 size, Vector4 color, float radius);
|
Draw_Quad *draw_rounded_rect(Vector2 p, Vector2 size, Vector4 color, float radius);
|
||||||
Draw_Quad *draw_rounded_rect_xform(Matrix4 xform, Vector2 size, Vector4 color, float radius);
|
Draw_Quad *draw_rounded_rect_xform(Matrix4 xform, Vector2 size, Vector4 color, float radius);
|
||||||
Draw_Quad *draw_outlined_rect(Vector2 p, Vector2 size, Vector4 color, float line_width);
|
Draw_Quad *draw_outlined_rect(Vector2 p, Vector2 size, Vector4 color, float line_width_pixels);
|
||||||
Draw_Quad *draw_outlined_rect_xform(Matrix4 xform, Vector2 size, Vector4 color, float line_width);
|
Draw_Quad *draw_outlined_rect_xform(Matrix4 xform, Vector2 size, Vector4 color, float line_width_pixels);
|
||||||
|
Draw_Quad *draw_outlined_circle(Vector2 p, Vector2 size, Vector4 color, float line_width_pixels);
|
||||||
|
Draw_Quad *draw_outlined_circle_xform(Matrix4 xform, Vector2 size, Vector4 color, float line_width_pixels);
|
||||||
|
|
||||||
int entry(int argc, char **argv) {
|
int entry(int argc, char **argv) {
|
||||||
|
|
||||||
|
@ -64,7 +67,9 @@ int entry(int argc, char **argv) {
|
||||||
rect_xform = m4_translate(rect_xform, v3(-.25f, -.25f, 0));
|
rect_xform = m4_translate(rect_xform, v3(-.25f, -.25f, 0));
|
||||||
Draw_Quad *q = draw_rounded_rect_xform(rect_xform, v2(.5f, .5f), COLOR_GREEN, 0.1);
|
Draw_Quad *q = draw_rounded_rect_xform(rect_xform, v2(.5f, .5f), COLOR_GREEN, 0.1);
|
||||||
|
|
||||||
draw_outlined_rect(v2(sin(now), -.8), v2(.5, .25), COLOR_RED, 15);
|
draw_outlined_rect(v2(sin(now), -.8), v2(.5, .25), COLOR_RED, 2);
|
||||||
|
|
||||||
|
draw_outlined_circle(v2(-sin(now), -.8), v2(.6, .6), COLOR_BLUE, 2);
|
||||||
|
|
||||||
|
|
||||||
// Shader hot reloading
|
// Shader hot reloading
|
||||||
|
@ -82,6 +87,34 @@ int entry(int argc, char **argv) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Vector2 world_to_screen(Vector2 p) {
|
||||||
|
Vector4 in_view_space = m4_transform(draw_frame.view, v4(p.x, p.y, 0.0, 1.0));
|
||||||
|
Vector4 in_clip_space = m4_transform(draw_frame.projection, in_view_space);
|
||||||
|
|
||||||
|
Vector4 ndc = {
|
||||||
|
.x = in_clip_space.x / in_clip_space.w,
|
||||||
|
.y = in_clip_space.y / in_clip_space.w,
|
||||||
|
.z = in_clip_space.z / in_clip_space.w,
|
||||||
|
.w = in_clip_space.w
|
||||||
|
};
|
||||||
|
|
||||||
|
return v2(
|
||||||
|
(ndc.x + 1.0f) * 0.5f * (f32)window.width,
|
||||||
|
(ndc.y + 1.0f) * 0.5f * (f32)window.height
|
||||||
|
);
|
||||||
|
}
|
||||||
|
Vector2 world_size_to_screen_size(Vector2 s) {
|
||||||
|
Vector2 origin = v2(0, 0);
|
||||||
|
|
||||||
|
Vector2 screen_origin = world_to_screen(origin);
|
||||||
|
Vector2 screen_size_point = world_to_screen(s);
|
||||||
|
|
||||||
|
return v2(
|
||||||
|
screen_size_point.x - screen_origin.x,
|
||||||
|
screen_size_point.y - screen_origin.y
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
Draw_Quad *draw_rounded_rect(Vector2 p, Vector2 size, Vector4 color, float radius) {
|
Draw_Quad *draw_rounded_rect(Vector2 p, Vector2 size, Vector4 color, float radius) {
|
||||||
Draw_Quad *q = draw_rect(p, size, color);
|
Draw_Quad *q = draw_rect(p, size, color);
|
||||||
// detail_type
|
// detail_type
|
||||||
|
@ -98,19 +131,44 @@ Draw_Quad *draw_rounded_rect_xform(Matrix4 xform, Vector2 size, Vector4 color, f
|
||||||
q->userdata[0].y = radius;
|
q->userdata[0].y = radius;
|
||||||
return q;
|
return q;
|
||||||
}
|
}
|
||||||
Draw_Quad *draw_outlined_rect(Vector2 p, Vector2 size, Vector4 color, float line_width) {
|
Draw_Quad *draw_outlined_rect(Vector2 p, Vector2 size, Vector4 color, float line_width_pixels) {
|
||||||
Draw_Quad *q = draw_rect(p, size, color);
|
Draw_Quad *q = draw_rect(p, size, color);
|
||||||
// detail_type
|
// detail_type
|
||||||
q->userdata[0].x = DETAIL_TYPE_OUTLINED;
|
q->userdata[0].x = DETAIL_TYPE_OUTLINED;
|
||||||
// line_width
|
// line_width_pixels
|
||||||
q->userdata[0].y = line_width;
|
q->userdata[0].y = line_width_pixels;
|
||||||
|
// rect_size
|
||||||
|
q->userdata[0].zw = world_size_to_screen_size(size);
|
||||||
return q;
|
return q;
|
||||||
}
|
}
|
||||||
Draw_Quad *draw_outlined_rect_xform(Matrix4 xform, Vector2 size, Vector4 color, float line_width) {
|
Draw_Quad *draw_outlined_rect_xform(Matrix4 xform, Vector2 size, Vector4 color, float line_width_pixels) {
|
||||||
Draw_Quad *q = draw_rect_xform(xform, size, color);
|
Draw_Quad *q = draw_rect_xform(xform, size, color);
|
||||||
// detail_type
|
// detail_type
|
||||||
q->userdata[0].x = DETAIL_TYPE_OUTLINED;
|
q->userdata[0].x = DETAIL_TYPE_OUTLINED;
|
||||||
// line_width
|
// line_width_pixels
|
||||||
q->userdata[0].y = line_width;
|
q->userdata[0].y = line_width_pixels;
|
||||||
|
// rect_size
|
||||||
|
q->userdata[0].zw = world_size_to_screen_size(size);
|
||||||
|
return q;
|
||||||
|
}
|
||||||
|
Draw_Quad *draw_outlined_circle(Vector2 p, Vector2 size, Vector4 color, float line_width_pixels) {
|
||||||
|
Draw_Quad *q = draw_rect(p, size, color);
|
||||||
|
// detail_type
|
||||||
|
q->userdata[0].x = DETAIL_TYPE_OUTLINED_CIRCLE;
|
||||||
|
// line_width_pixels
|
||||||
|
q->userdata[0].y = line_width_pixels;
|
||||||
|
// rect_size_pixels
|
||||||
|
q->userdata[0].zw = world_size_to_screen_size(size); // Transform world space to screen space
|
||||||
|
return q;
|
||||||
|
}
|
||||||
|
Draw_Quad *draw_outlined_circle_xform(Matrix4 xform, Vector2 size, Vector4 color, float line_width_pixels) {
|
||||||
|
Draw_Quad *q = draw_rect_xform(xform, size, color);
|
||||||
|
// detail_type
|
||||||
|
q->userdata[0].x = DETAIL_TYPE_OUTLINED_CIRCLE;
|
||||||
|
// line_width_pixels
|
||||||
|
q->userdata[0].y = line_width_pixels;
|
||||||
|
// rect_size_pixels
|
||||||
|
q->userdata[0].zw = world_size_to_screen_size(size); // Transform world space to screen space
|
||||||
|
|
||||||
return q;
|
return q;
|
||||||
}
|
}
|
|
@ -10,6 +10,7 @@ cbuffer some_cbuffer : register(b0) {
|
||||||
|
|
||||||
#define DETAIL_TYPE_ROUNDED_CORNERS 1
|
#define DETAIL_TYPE_ROUNDED_CORNERS 1
|
||||||
#define DETAIL_TYPE_OUTLINED 2
|
#define DETAIL_TYPE_OUTLINED 2
|
||||||
|
#define DETAIL_TYPE_OUTLINED_CIRCLE 3
|
||||||
|
|
||||||
float4 get_light_contribution(PS_INPUT input) {
|
float4 get_light_contribution(PS_INPUT input) {
|
||||||
|
|
||||||
|
@ -31,6 +32,9 @@ float4 pixel_shader_extension(PS_INPUT input, float4 color) {
|
||||||
|
|
||||||
float detail_type = input.userdata[0].x;
|
float detail_type = input.userdata[0].x;
|
||||||
|
|
||||||
|
// Assumes rect with 90deg corners
|
||||||
|
float2 rect_size_pixels = input.userdata[0].zw;
|
||||||
|
|
||||||
if (detail_type == DETAIL_TYPE_ROUNDED_CORNERS) {
|
if (detail_type == DETAIL_TYPE_ROUNDED_CORNERS) {
|
||||||
float corner_radius = input.userdata[0].y;
|
float corner_radius = input.userdata[0].y;
|
||||||
|
|
||||||
|
@ -44,23 +48,45 @@ float4 pixel_shader_extension(PS_INPUT input, float4 color) {
|
||||||
|
|
||||||
color *= mask;
|
color *= mask;
|
||||||
} else if (detail_type == DETAIL_TYPE_OUTLINED) {
|
} else if (detail_type == DETAIL_TYPE_OUTLINED) {
|
||||||
float line_width = input.userdata[0].y;
|
float line_width_pixels = input.userdata[0].y;
|
||||||
|
|
||||||
float2 pixel_pos = round(input.self_uv*window_size);
|
float2 pixel_pos = round(input.self_uv*rect_size_pixels);
|
||||||
|
|
||||||
float xcenter = window_size.x/2;
|
float xcenter = rect_size_pixels.x/2;
|
||||||
float ycenter = window_size.y/2;
|
float ycenter = rect_size_pixels.y/2;
|
||||||
|
|
||||||
float xedge = pixel_pos.x < xcenter ? 0.0 : window_size.x;
|
float xedge = pixel_pos.x < xcenter ? 0.0 : rect_size_pixels.x;
|
||||||
float yedge = pixel_pos.y < ycenter ? 0.0 : window_size.y;
|
float yedge = pixel_pos.y < ycenter ? 0.0 : rect_size_pixels.y;
|
||||||
|
|
||||||
float xdist = abs(xedge-pixel_pos.x);
|
float xdist = abs(xedge-pixel_pos.x);
|
||||||
float ydist = abs(yedge-pixel_pos.y);
|
float ydist = abs(yedge-pixel_pos.y);
|
||||||
|
|
||||||
if (xdist >= line_width && ydist >= line_width) {
|
if (xdist > line_width_pixels && ydist > line_width_pixels) {
|
||||||
discard;
|
discard;
|
||||||
}
|
}
|
||||||
}
|
} else if (detail_type == DETAIL_TYPE_OUTLINED_CIRCLE) {
|
||||||
|
float line_width_pixels = input.userdata[0].y;
|
||||||
|
float2 rect_size_pixels = input.userdata[0].zw;
|
||||||
|
float line_width_uv = line_width_pixels / min(rect_size_pixels.x, rect_size_pixels.y);
|
||||||
|
|
||||||
|
// For some simple anti-aliasing, we add a little bit of padding around the outline
|
||||||
|
// and fade that padding outwards with a smooth curve towards 0.
|
||||||
|
// Very arbitrary smooth equation that I got from just testing different sizes of the circle.
|
||||||
|
// It's kinda meh.
|
||||||
|
float smooth = ((4.0/line_width_pixels)*6.0)/window_size.x;
|
||||||
|
|
||||||
|
float2 center = float2(0.5, 0.5);
|
||||||
|
float dist = length(input.self_uv - center);
|
||||||
|
|
||||||
|
float mask;
|
||||||
|
if (dist > 0.5-smooth) {
|
||||||
|
mask = 1.0-lerp(0, 1.0, max(dist-0.5+smooth, 0.0)/smooth);
|
||||||
|
} else if (dist < 0.5-line_width_uv+smooth) {
|
||||||
|
mask = smoothstep(0, 1.0, max(dist-0.5+line_width_uv+smooth, 0.0)/smooth);
|
||||||
|
}
|
||||||
|
if (mask <= 0) discard;
|
||||||
|
color *= mask;
|
||||||
|
}
|
||||||
|
|
||||||
float4 light = get_light_contribution(input);
|
float4 light = get_light_contribution(input);
|
||||||
|
|
||||||
|
|
|
@ -132,12 +132,13 @@ void d3d11_update_swapchain() {
|
||||||
DXGI_SWAP_CHAIN_DESC1 scd = ZERO(DXGI_SWAP_CHAIN_DESC1);
|
DXGI_SWAP_CHAIN_DESC1 scd = ZERO(DXGI_SWAP_CHAIN_DESC1);
|
||||||
scd.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
|
scd.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
|
||||||
scd.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING;
|
scd.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING;
|
||||||
|
|
||||||
//scd.BufferDesc.RefreshRate.Numerator = 0;
|
//scd.BufferDesc.RefreshRate.Numerator = 0;
|
||||||
//scd.BufferDesc.RefreshRate.Denominator = 1;
|
//scd.BufferDesc.RefreshRate.Denominator = 1;
|
||||||
|
|
||||||
scd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
|
scd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
|
||||||
scd.SampleDesc.Count = 1;
|
scd.SampleDesc.Count = 1;
|
||||||
scd.SampleDesc.Quality = 0;
|
scd.SampleDesc.Quality = 0; // #Portability
|
||||||
if (d3d11_feature_level < D3D_FEATURE_LEVEL_11_0) {
|
if (d3d11_feature_level < D3D_FEATURE_LEVEL_11_0) {
|
||||||
scd.Scaling = DXGI_SCALING_STRETCH; // for compatability with 7
|
scd.Scaling = DXGI_SCALING_STRETCH; // for compatability with 7
|
||||||
}
|
}
|
||||||
|
|
Reference in a new issue