sub-pixel rectangles with analytical anti-aliasing

main
Allen Webster 2023-04-27 16:45:25 -07:00
parent 97d8c7430e
commit 776dfe46d2
1 changed files with 106 additions and 0 deletions

View File

@ -76,6 +76,10 @@ typedef struct Vertex{
F32 cg;
F32 cb;
F32 ca;
F32 rx0;
F32 ry0;
F32 rx1;
F32 ry1;
} Vertex;
@ -84,6 +88,7 @@ static void opengl_render_init(void);
static void opengl_draw_basic_geometry(Vertex *v, U64 count);
static void opengl_draw_srgb_in_geometry(Vertex *v, U64 count);
static void opengl_draw_texture_geometry(Vertex *v, U64 count, U32 texture);
static void opengl_draw_rect_geometry(Vertex *v, U64 count);
////////////////////////////////
@ -297,6 +302,7 @@ static GLint basic_u_view_xform = -1;
static char srgb_in_vshader[] =
"#version 330\n"
"\n"
@ -355,6 +361,45 @@ static GLint srgb_in_u_view_xform = -1;
static char rect_vshader[] =
"#version 330\n"
"uniform vec2 u_view_xform;\n"
"layout (location = 0) in vec2 v_p;\n"
"layout (location = 1) in vec4 v_r;\n"
"out vec4 f_r;\n"
"void main(){\n"
"vec2 norm_pos = v_p*u_view_xform + vec2(-1.0, -1.0);\n"
"gl_Position = vec4(norm_pos, 0.0, 1.0);\n"
"f_r = v_r;\n"
"}\n"
;
static char rect_fshader[] =
"#version 330\n"
"in vec4 gl_FragCoord;\n"
"in vec4 f_r;\n"
"out vec4 out_color;\n"
"void main(){\n"
"float pix_x0 = gl_FragCoord.x - 0.5;\n"
"float pix_y0 = gl_FragCoord.y - 0.5;\n"
"float pix_x1 = gl_FragCoord.x + 0.5;\n"
"float pix_y1 = gl_FragCoord.y + 0.5;\n"
"float int_x0 = max(pix_x0, f_r.x);\n"
"float int_y0 = max(pix_y0, f_r.y);\n"
"float int_x1 = min(pix_x1, f_r.z);\n"
"float int_y1 = min(pix_y1, f_r.w);\n"
"float cover = (int_x1 - int_x0)*(int_y1 - int_y0);\n"
"out_color = vec4(1, 1, 1, cover);\n"
"}\n"
;
static GLuint rect_program = 0;
static GLint rect_u_view_xform = -1;
static char texture_vshader[] =
"#version 330\n"
"uniform vec2 u_view_xform;\n"
@ -409,6 +454,15 @@ opengl_render_init(void){
srgb_in_u_view_xform = glGetUniformLocation(basic_program, "u_view_xform");
}
//- setup rect shader program
{
GLuint shaders[2] = {0};
shaders[0] = opengl_helper_make_shader(rect_vshader, GL_VERTEX_SHADER);
shaders[1] = opengl_helper_make_shader(rect_fshader, GL_FRAGMENT_SHADER);
rect_program = opengl_helper_make_program(shaders, 2);
rect_u_view_xform = glGetUniformLocation(rect_program, "u_view_xform");
}
//- setup texture shader program
{
GLuint shaders[2] = {0};
@ -523,6 +577,24 @@ opengl_draw_srgb_in_geometry(Vertex *v, U64 count){
glDrawArrays(GL_TRIANGLES, 0, count);
}
static void
opengl_draw_rect_geometry(Vertex *v, U64 count){
glBufferData(GL_ARRAY_BUFFER, sizeof(*v)*count, v, GL_STREAM_DRAW);
glUseProgram(rect_program);
glUniform2f(rect_u_view_xform, 2.f/graphics_w, 2.f/graphics_h);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 2, GL_FLOAT, 0,
sizeof(Vertex), PtrOffsetOf(Vertex, px));
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 4, GL_FLOAT, 0,
sizeof(Vertex), PtrOffsetOf(Vertex, rx0));
glDrawArrays(GL_TRIANGLES, 0, count);
}
static void
opengl_draw_texture_geometry(Vertex *v, U64 count, U32 texture){
glBufferData(GL_ARRAY_BUFFER, sizeof(*v)*count, v, GL_STREAM_DRAW);
@ -602,6 +674,7 @@ WinMain(HINSTANCE hInstance,
F32 test3_y = graphics_h - 110.f;
F32 test4_y = graphics_h - 160.f;
F32 test5_y = graphics_h - 340.f;
F32 test6_y = graphics_h - 450.f;
// render to canvas frame buffer
{
@ -868,7 +941,40 @@ WinMain(HINSTANCE hInstance,
opengl_draw_srgb_in_geometry(v, 6);
}
}
}
// 6: sub-pixel rectangle anti-aliasing
{
F32 top_y = test6_y;
F32 bot_y = test6_y - 20.f;
F32 x_cursor = grad_x0;
for (U32 i = 0; i < 16; i += 1){
F32 l = x_cursor + 4.0625*i;
F32 r = l + 2.f;
F32 floor_l = (F32)(S32)l;
F32 ceil_r = (F32)(S32)r;
if (ceil_r < (F32)r){
ceil_r += 1.f;
}
Vertex v[6];
v[0].px = floor_l; v[0].py = bot_y;
v[1].px = floor_l; v[1].py = top_y;
v[2].px = ceil_r; v[2].py = bot_y;
v[3].px = floor_l; v[3].py = top_y;
v[4].px = ceil_r; v[4].py = bot_y;
v[5].px = ceil_r; v[5].py = top_y;
for (U32 j = 0; j < 6; j += 1){
v[j].rx0 = l;
v[j].ry0 = bot_y;
v[j].rx1 = r;
v[j].ry1 = top_y;
}
opengl_draw_rect_geometry(v, 6);
}
}
}