Add GL stuff and framerate lock
This commit is contained in:
parent
b30e525d69
commit
3cf0b585dc
2 changed files with 166 additions and 43 deletions
2
Makefile
2
Makefile
|
@ -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
|
||||||
|
|
||||||
|
|
207
main.c
207
main.c
|
@ -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,64 +198,69 @@ 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)
|
||||||
|
loopShouldStop = true;
|
||||||
}
|
}
|
||||||
else if (e.key.mod == SDL_KMOD_LCTRL && e.key.key == SDLK_Q)
|
|
||||||
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
while (time_counter > GetTime()) {
|
while (time_counter > GetTime()) {
|
||||||
/* 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);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue