crude legacy GL backend w/ anti aliasing

This commit is contained in:
2022-11-16 04:46:33 +11:00
parent fc9a6571ec
commit 9ba7a3bda8
5 changed files with 197 additions and 3 deletions

View File

@ -2,15 +2,26 @@ cmake_minimum_required(VERSION 3.1 FATAL_ERROR)
project(padlab C) project(padlab C)
set(CMAKE_C_STANDARD 99) set(CMAKE_C_STANDARD 99)
set(TARGET padlab) set(TARGET padlab)
find_package(SDL2 REQUIRED)
find_package(OpenGL)
set(SOURCES set(SOURCES
maths.h maths.h
draw.c draw.h draw.h
stick.c stick.h stick.c stick.h
analogue.c) analogue.c)
find_package(SDL2 REQUIRED) if (OPENGL_FOUND)
list(APPEND SOURCES draw_opengl.c)
else()
list(APPEND SOURCES draw.c)
endif()
add_executable(${TARGET} ${SOURCES}) add_executable(${TARGET} ${SOURCES})
target_link_libraries(${TARGET} SDL2::SDL2 m) target_link_libraries(${TARGET} SDL2::SDL2 m)
if (OPENGL_FOUND)
target_link_libraries(${TARGET} OpenGL::GL)
endif()
target_compile_options(${TARGET} PRIVATE target_compile_options(${TARGET} PRIVATE
-Wall -Wextra -pedantic -Wno-unused-parameter) -Wall -Wextra -pedantic -Wno-unused-parameter)

View File

@ -38,6 +38,7 @@ int main(int argc, char** argv)
const int winflg = SDL_WINDOW_RESIZABLE | SDL_WINDOW_ALLOW_HIGHDPI; const int winflg = SDL_WINDOW_RESIZABLE | SDL_WINDOW_ALLOW_HIGHDPI;
int winw = WINDOW_WIDTH; int winw = WINDOW_WIDTH;
int winh = WINDOW_HEIGHT; int winh = WINDOW_HEIGHT;
DrawWindowHints();
window = SDL_CreateWindow(CAPTION, winpos, winpos, winw, winh, winflg); window = SDL_CreateWindow(CAPTION, winpos, winpos, winw, winh, winflg);
FATAL(window == NULL, -1) FATAL(window == NULL, -1)

4
draw.c
View File

@ -4,6 +4,8 @@
static SDL_Renderer* rend = NULL; static SDL_Renderer* rend = NULL;
void DrawWindowHints(void) {}
int InitDraw(SDL_Window* window) int InitDraw(SDL_Window* window)
{ {
const int rendflags = SDL_RENDERER_PRESENTVSYNC; const int rendflags = SDL_RENDERER_PRESENTVSYNC;
@ -68,7 +70,7 @@ void DrawCircleSteps(int x, int y, int r, int steps)
double stepsz = (double)TAU / steps; double stepsz = (double)TAU / steps;
int lastx = r; int lastx = r;
int lasty = 0; int lasty = 0;
for (int i = 0; i <= steps; ++i) for (int i = 1; i <= steps; ++i)
{ {
const double mag = (double)r; const double mag = (double)r;
int ofsx = (int)round(cos(stepsz * i) * mag); int ofsx = (int)round(cos(stepsz * i) * mag);

4
draw.h
View File

@ -8,6 +8,10 @@
typedef struct SDL_Window SDL_Window; typedef struct SDL_Window SDL_Window;
// Call before window creation to setup backend-specific
// hints and attributes.
void DrawWindowHints(void);
// Initialise the drawing subsystem. // Initialise the drawing subsystem.
// //
// Params: // Params:

176
draw_opengl.c Normal file
View File

@ -0,0 +1,176 @@
#include "draw.h"
#include <SDL_video.h>
#include <SDL_opengl.h>
#include <stdbool.h>
static SDL_GLContext* ctx = NULL;
static SDL_Window* window = NULL;
static uint32_t colour = 0x00000000;
static uint32_t clrColour = 0x00000000;
static double scaleWidth = 0.0;
static double scaleHeight = 0.0;
static bool antialias = false;
void DrawWindowHints(void)
{
SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 1); // Enable MSAA
SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, 8); // 8x MSAA
// Legacy OpenGL profile
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 1);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 1);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_COMPATIBILITY);
}
int InitDraw(SDL_Window* w)
{
ctx = SDL_GL_CreateContext(w);
window = w;
if (ctx == NULL || window == NULL)
return -1;
SDL_GL_SetSwapInterval(1); // Enable vsync
// Detect if MSAA is available & active
int res;
if (SDL_GL_GetAttribute(SDL_GL_MULTISAMPLEBUFFERS, &res) == 0 && res == 1)
if (SDL_GL_GetAttribute(SDL_GL_MULTISAMPLESAMPLES, &res) == 0 && res > 0)
antialias = true;
// Disable depth test & culling, enable MSAA
glDisable(GL_DEPTH_TEST);
glDisable(GL_CULL_FACE);
glEnable(GL_MULTISAMPLE);
GetDrawSizeInPixels(); // Fills scaleWidth & scaleHeight
// Setup orthographic viewport
glMatrixMode(GL_PROJECTION);
glOrtho(0.0, 1.0f, 1.0f, 0.0, 1.0, -1.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
return 0;
}
void QuitDraw(void)
{
SDL_GL_DeleteContext(ctx);
ctx = NULL;
window = NULL;
}
size GetDrawSizeInPixels(void)
{
size out;
SDL_GL_GetDrawableSize(SDL_GL_GetCurrentWindow(), &out.w, &out.h);
scaleWidth = 1.0 / (double)out.w;
scaleHeight = 1.0 / (double)out.h;
return out;
}
void SetDrawColour(uint32_t c)
{
colour = c;
}
void DrawClear(void)
{
if (clrColour != colour)
{
const float mul = 1.0f / 255.0f;
glClearColor(
(GLclampf)((colour & 0xFF000000) >> 24) * mul,
(GLclampf)((colour & 0x00FF0000) >> 16) * mul,
(GLclampf)((colour & 0x0000FF00) >> 8) * mul,
(GLclampf)((colour & 0x000000FF)) * mul);
clrColour = colour;
}
glClear(GL_COLOR_BUFFER_BIT);
}
static inline void GlColour(void)
{
const float mul = 1.0f / 255.0f;
glColor4f(
(GLclampf)((colour & 0xFF000000) >> 24) * mul,
(GLclampf)((colour & 0x00FF0000) >> 16) * mul,
(GLclampf)((colour & 0x0000FF00) >> 8) * mul,
(GLclampf)((colour & 0x000000FF)) * mul);
}
void DrawPoint(int x, int y)
{
const double fx = ((double)x) * scaleWidth;
const double fy = ((double)y) * scaleHeight;
glBegin(GL_POINTS);
GlColour();
glVertex2d(fx, fy);
glEnd();
}
void DrawRect(int x, int y, int w, int h)
{
const double fx = (double)x * scaleWidth;
const double fy = (double)y * scaleHeight;
const double fw = (double)w * scaleWidth;
const double fh = (double)h * scaleHeight;
glBegin(GL_LINE_LOOP);
GlColour();
glVertex2d(fx, fy);
glVertex2d(fx + fw, fy);
glVertex2d(fx + fw, fy + fh);
glVertex2d(fx, fy + fh);
glEnd();
}
void DrawLine(int x1, int y1, int x2, int y2)
{
const double fx1 = (double)x1 * scaleWidth;
const double fy1 = (double)y1 * scaleHeight;
const double fx2 = (double)x2 * scaleWidth;
const double fy2 = (double)y2 * scaleHeight;
glBegin(GL_LINES);
GlColour();
glVertex2d(fx1, fy1);
glVertex2d(fx2, fy2);
glEnd();
}
void DrawCircle(int x, int y, int r)
{
DrawCircleSteps(x, y, r, (int)(sqrt((double)r) * 8.0));
}
void DrawCircleSteps(int x, int y, int r, int steps)
{
// Circles look better when offset negatively by half a pixel w/o MSAA
const double fx = (antialias ? (double)x : (double)x - 0.5f) * scaleWidth;
const double fy = (antialias ? (double)y : (double)y - 0.5f) * scaleHeight;
const double stepsz = (double)TAU / (double)steps;
const double magw = (double)r * scaleWidth;
const double magh = (double)r * scaleHeight;
glBegin(GL_LINE_LOOP);
GlColour();
glVertex2d(fx + magw, fy);
for (int i = 1; i < steps; ++i)
{
const double theta = stepsz * (double)i;
double ofsx = cos(theta) * magw;
double ofsy = sin(theta) * magh;
glVertex2d(fx + ofsx, fy - ofsy);
}
glEnd();
}
void DrawPresent(void)
{
SDL_GL_SwapWindow(window);
}