Add GL stuff and framerate lock

This commit is contained in:
CRy386i 2024-12-23 03:02:33 +02:00
parent b30e525d69
commit 3cf0b585dc
2 changed files with 166 additions and 43 deletions

View file

@ -1,6 +1,6 @@
CC=gcc CC=gcc
CFLAGS=-O1 -DDEBUG -g -ggdb -std=c23 CFLAGS=-O1 -DDEBUG -g -ggdb -std=c23
LIBS=`pkg-config sdl3 --cflags --libs` LIBS=`pkg-config sdl3 --cflags --libs` -lGL -lGLEW
OBJ = main.o OBJ = main.o

205
main.c
View file

@ -1,13 +1,19 @@
#include <stdio.h> // for fprintf() #include <stdio.h>
#include <stdlib.h> // for exit() #include <stdlib.h>
#include <GL/glew.h>
#include <SDL3/SDL.h> #include <SDL3/SDL.h>
#include <SDL3/SDL_opengl.h>
#include <SDL3/SDL_main.h> // only include this one in the source file with main()! #include <SDL3/SDL_main.h> // only include this one in the source file with main()!
#define INITIAL_FPS 60 #define INITIAL_FPS 60
SDL_Window* window = NULL; SDL_Window* window = NULL;
SDL_Renderer* renderer = NULL; SDL_GLContext glcontext = NULL;
GLuint program;
GLuint vbo;
static double FPS = INITIAL_FPS; static double FPS = INITIAL_FPS;
static double FrameTime = 1.0 / INITIAL_FPS; static double FrameTime = 1.0 / INITIAL_FPS;
@ -16,12 +22,12 @@ static double PerformancePeriod;
static void panic ( const char *text ) __attribute__((noreturn)); static void panic ( const char *text ) __attribute__((noreturn));
static double GetTime() static double GetTime( void )
{ {
return PerformancePeriod * SDL_GetPerformanceCounter(); return PerformancePeriod * SDL_GetPerformanceCounter();
} }
static void SetTitle(SDL_Window * window) static void SetTitle ( SDL_Window *window )
{ {
char title[48] = {0}; char title[48] = {0};
SDL_snprintf(title, sizeof(title), "Crude frame limiter @ %6.3f Hz", FPS); SDL_snprintf(title, sizeof(title), "Crude frame limiter @ %6.3f Hz", FPS);
@ -30,13 +36,121 @@ static void SetTitle(SDL_Window * window)
void panic ( const char *text ) void panic ( const char *text )
{ {
fprintf(stderr, "ERROR: %s. %s\n", text, SDL_GetError()); //fprintf(stderr, "ERROR: %s. %s\n", text, SDL_GetError());
SDL_DestroyRenderer(renderer); SDL_LogCritical(SDL_LOG_CATEGORY_ASSERT, "%s. %s\n", text, SDL_GetError());
SDL_GL_DestroyContext(glcontext);
SDL_DestroyWindow(window); SDL_DestroyWindow(window);
SDL_Quit(); SDL_Quit();
exit(1); exit(1);
} }
char *readFile ( const char *fileName )
{
SDL_IOStream *ioStream = SDL_IOFromFile(fileName, "rb");
if (!ioStream) panic("SDL_IOFromfile");
if (!SDL_SeekIO(ioStream, 0, SDL_IO_SEEK_END)) panic("SDL_SeekIO_END");
long len = SDL_TellIO(ioStream);
if (!len) panic("SDL_TellIO");
if (!SDL_SeekIO(ioStream, 0, SDL_IO_SEEK_SET)) panic("SDL_SeekIO_SET");
char *res = SDL_malloc(len + 1);
if (!res) panic("SDL_malloc_RES");
if (SDL_ReadIO(ioStream, res, len) != (size_t)len) panic("SDL_ReadIO");
if (!SDL_CloseIO(ioStream)) panic("SDL_CloseIO");
/* char *res = SDL_LoadFile_IO(ioStream, NULL, true); */
/* if (!res) panic("SDL_LoadFile_IO"); */
res[len] = 0;
return res;
}
GLuint CreateShader ( const char *shaderFile, GLenum shaderType )
{
const char *strShaderType;
if (shaderType == GL_VERTEX_SHADER) {
strShaderType = "vertex";
} else if (shaderType == GL_GEOMETRY_SHADER) {
strShaderType = "geometry";
} else if (shaderType == GL_FRAGMENT_SHADER) {
strShaderType = "fragment";
} else {
SDL_LogCritical(SDL_LOG_CATEGORY_ASSERT, "Unrecognized shader type.\n");
exit(1);
}
GLuint shader = glCreateShader(shaderType);
if (!shader) {
SDL_LogCritical(SDL_LOG_CATEGORY_ASSERT, "Error create shader type %s\n", strShaderType);
exit(1);
}
GLchar *content = readFile(shaderFile);
glShaderSource(shader, 1, (const GLchar **)&content, NULL);
SDL_free(content);
glCompileShader(shader);
GLint status;
glGetShaderiv(shader, GL_COMPILE_STATUS, &status);
if (status == GL_FALSE) {
GLint infoLen;
glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLen);
GLchar *info = SDL_malloc(sizeof(GLchar) * (infoLen + 1));
glGetShaderInfoLog(shader, infoLen, NULL, info);
SDL_LogCritical(SDL_LOG_CATEGORY_ASSERT, "Filed to compile %s shader:\n%s\n", strShaderType, info);
exit(1);
}
return shader;
}
void CreateProgram ( GLuint *shaders, int len )
{
program = glCreateProgram();
if (!program) {
SDL_LogCritical(SDL_LOG_CATEGORY_ASSERT, "Can't to create shader program\n");
exit(1);
}
for (int i = 0; i < len; i++) {
glAttachShader(program, shaders[i]);
}
glLinkProgram(program);
GLint status;
glGetProgramiv(program, GL_LINK_STATUS, &status);
if (status == GL_FALSE) {
GLint infoLen;
glGetProgramiv(program, GL_INFO_LOG_LENGTH, &infoLen);
GLchar *info = SDL_malloc(sizeof(GLchar) * (infoLen + 1));
glGetProgramInfoLog(program, infoLen, NULL, info);
SDL_LogCritical(SDL_LOG_CATEGORY_ASSERT, "Link failed: %s\n", info);
exit(1);
}
}
void CreateBuffer ( void )
{
float vertices[] = {
-1.0f, -1.0f, 0.0f,
1.0f, -1.0f, 0.0f,
0.0f, 1.0f, 0.0f
};
glGenBuffers(1, &vbo);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
}
void ConfProg ( void )
{
CreateBuffer();
GLuint shaders[] = {
CreateShader("vertex.glsl", GL_VERTEX_SHADER),
CreateShader("fragmet.glsl", GL_FRAGMENT_SHADER)
};
int len = sizeof(shaders) / sizeof(shaders[0]);
CreateProgram(shaders, len);
for (int i = 0; i < len; i++) {
glDeleteShader(shaders[i]);
}
}
int main( int argc, char* argv[] ) int main( int argc, char* argv[] )
{ {
const int WIDTH = 640; const int WIDTH = 640;
@ -48,27 +162,31 @@ int main( int argc, char* argv[] )
SDL_SetHint(SDL_HINT_RENDER_VSYNC, 0); SDL_SetHint(SDL_HINT_RENDER_VSYNC, 0);
if (!SDL_Init(SDL_INIT_VIDEO)) if (!SDL_Init(SDL_INIT_VIDEO)) {
{
panic("SDL_Init failed"); panic("SDL_Init failed");
} }
SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 5);
SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 5);
SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 5);
SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 16);
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
PerformancePeriod = 1.0 / SDL_GetPerformanceFrequency(); PerformancePeriod = 1.0 / SDL_GetPerformanceFrequency();
time_counter = GetTime(); time_counter = GetTime();
window = SDL_CreateWindow("Hello SDL", WIDTH, HEIGHT, SDL_WINDOW_OPENGL); window = SDL_CreateWindow("Hello SDL", WIDTH, HEIGHT, SDL_WINDOW_OPENGL|SDL_WINDOW_RESIZABLE);
if (!window) if (!window) {
{
panic("SDL_CreateWindow"); panic("SDL_CreateWindow");
} }
renderer = SDL_CreateRenderer(window, "opengl"); glcontext = SDL_GL_CreateContext(window);
if (!renderer) if (!glcontext) {
{ panic("SDL_GL_CreateContext");
panic("SDL_CreateRenderer");
} }
//SDL_GetWindowSize(window, &width, &height); ConfProg();
SetTitle(window); SetTitle(window);
//if (!SDL_SetRenderVSync(renderer, 1)) //if (!SDL_SetRenderVSync(renderer, 1))
@ -80,47 +198,45 @@ int main( int argc, char* argv[] )
int red = 0; int red = 0;
int green = 0; int green = 0;
while (!loopShouldStop)
{ int r, g, b;
while (!loopShouldStop) {
SDL_Event e; SDL_Event e;
SDL_zero(e); SDL_zero(e);
while (SDL_PollEvent(&e)) while (SDL_PollEvent(&e)) {
{
if (e.type == SDL_EVENT_QUIT) if (e.type == SDL_EVENT_QUIT)
loopShouldStop = true; loopShouldStop = true;
else if (e.type == SDL_EVENT_KEY_DOWN) else if (e.type == SDL_EVENT_KEY_DOWN) {
{ if (e.key.key == SDLK_X) {
if (e.key.key == SDLK_X)
{
FPS -= 0.1; FPS -= 0.1;
if (FPS < 1) if (FPS < 1) {
{
FPS = 1; FPS = 1;
} }
FrameTime = 1.0 / FPS; FrameTime = 1.0 / FPS;
SetTitle(window); SetTitle(window);
} }
else if (e.key.key == SDLK_C) else if (e.key.key == SDLK_C) {
{
FPS += 0.1; FPS += 0.1;
FrameTime = 1.0 / FPS; FrameTime = 1.0 / FPS;
SetTitle(window); SetTitle(window);
} }
} if (e.key.key == SDLK_ESCAPE)
else if (e.key.mod == SDL_KMOD_LCTRL && e.key.key == SDLK_Q)
loopShouldStop = true; loopShouldStop = true;
} }
}
SDL_SetRenderDrawColor(renderer, red, green, 0, 255); /* SDL_SetRenderDrawColor(renderer, red, green, 0, 255); */
SDL_RenderClear(renderer); /* SDL_RenderClear(renderer); */
glClearColor(0, 0, 0, 1);
glClear(GL_COLOR_BUFFER_BIT);
SDL_GL_SwapWindow(window);
sleep_time = time_counter - GetTime(); sleep_time = time_counter - GetTime();
if (sleep_time * 1000 > delay_threshold) if (sleep_time * 1000 > delay_threshold) {
{
Uint32 ms = (Uint32)(sleep_time * 1000) - delay_threshold; Uint32 ms = (Uint32)(sleep_time * 1000) - delay_threshold;
SDL_Delay(ms); SDL_Delay(ms);
if (time_counter < GetTime()) if (time_counter < GetTime()) {
{
delay_threshold++; delay_threshold++;
SDL_Log("Slept too long. Increased threshold to %u ms.", delay_threshold); SDL_Log("Slept too long. Increased threshold to %u ms.", delay_threshold);
} }
@ -130,14 +246,21 @@ int main( int argc, char* argv[] )
/* Waiting for the right moment. */ /* Waiting for the right moment. */
} }
SDL_RenderPresent(renderer); /* red = (red + 1) % 256; */
red = (red + 1) % 256; /* green = (green + 1) % 64; */
green = (green + 1) % 64;
time_counter += FrameTime; time_counter += FrameTime;
} }
SDL_DestroyRenderer(renderer);
SDL_GL_GetAttribute(SDL_GL_RED_SIZE, &r);
SDL_GL_GetAttribute(SDL_GL_GREEN_SIZE, &g);
SDL_GL_GetAttribute(SDL_GL_BLUE_SIZE, &b);
printf("Red size: %d, Green size: %d, Blue size: %d\n", r, g, b);
SDL_DestroyWindow(window); SDL_DestroyWindow(window);
SDL_GL_DestroyContext(glcontext);
SDL_Quit(); SDL_Quit();
exit(0); exit(0);
} }