Splitting the program of fragment C files
And odd header files
This commit is contained in:
parent
c646198aa8
commit
f6bb22bb05
6 changed files with 238 additions and 210 deletions
7
Makefile
7
Makefile
|
@ -2,12 +2,13 @@ CC=gcc
|
||||||
CFLAGS=-O1 -DDEBUG -g -ggdb -std=c23
|
CFLAGS=-O1 -DDEBUG -g -ggdb -std=c23
|
||||||
LIBS=`pkg-config sdl3 --cflags --libs` -lGL -lGLEW -lm
|
LIBS=`pkg-config sdl3 --cflags --libs` -lGL -lGLEW -lm
|
||||||
|
|
||||||
OBJ = main.o
|
HEADER = opengl.h readfile.h
|
||||||
|
OBJ = main.o opengl.o readfile.o
|
||||||
|
|
||||||
all: mobiground
|
all: mobiground
|
||||||
|
|
||||||
%.o: %.c # Add all .o and .c files to compiler
|
%.o: %.c $(HEADER)
|
||||||
$(CC) -c -o $@ $< $(CFLAGS) # compile, generate, all output, prerequisite implicit rule, compile flags.
|
$(CC) -c -o $@ $< $(CFLAGS)
|
||||||
|
|
||||||
mobiground: $(OBJ)
|
mobiground: $(OBJ)
|
||||||
$(CC) -o $@ $^ $(CFLAGS) $(LIBS)
|
$(CC) -o $@ $^ $(CFLAGS) $(LIBS)
|
||||||
|
|
230
main.c
230
main.c
|
@ -6,24 +6,15 @@
|
||||||
#include <SDL3/SDL.h>
|
#include <SDL3/SDL.h>
|
||||||
#include <SDL3/SDL_opengl.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()!
|
||||||
|
#include "opengl.h"
|
||||||
|
|
||||||
#define INITIAL_FPS 60
|
#define INITIAL_FPS 60
|
||||||
|
|
||||||
SDL_Window* window = NULL;
|
|
||||||
SDL_GLContext glcontext = NULL;
|
|
||||||
|
|
||||||
GLuint program;
|
|
||||||
GLuint vbo;
|
|
||||||
GLuint ibo;
|
|
||||||
GLuint projMatrLoc;
|
|
||||||
|
|
||||||
static double FPS = INITIAL_FPS;
|
static double FPS = INITIAL_FPS;
|
||||||
static double FrameTime = 1.0 / INITIAL_FPS;
|
static double FrameTime = 1.0 / INITIAL_FPS;
|
||||||
|
|
||||||
static double PerformancePeriod;
|
static double PerformancePeriod;
|
||||||
|
|
||||||
static void panicError ( void ) __attribute__((noreturn));
|
|
||||||
|
|
||||||
static double GetTime( void )
|
static double GetTime( void )
|
||||||
{
|
{
|
||||||
return PerformancePeriod * SDL_GetPerformanceCounter();
|
return PerformancePeriod * SDL_GetPerformanceCounter();
|
||||||
|
@ -45,6 +36,7 @@ float toRad ( float deg )
|
||||||
|
|
||||||
void resizeWindow ( int width, int height )
|
void resizeWindow ( int width, int height )
|
||||||
{
|
{
|
||||||
|
shaderProgram_t sp;
|
||||||
float n = 1.0f; // near
|
float n = 1.0f; // near
|
||||||
float f = 3.0f; // far
|
float f = 3.0f; // far
|
||||||
float fov = toRad(90); // 90 or 65 for console
|
float fov = toRad(90); // 90 or 65 for console
|
||||||
|
@ -55,196 +47,20 @@ void resizeWindow ( int width, int height )
|
||||||
float projMatr[] = {
|
float projMatr[] = {
|
||||||
n/r, 0, 0, 0,
|
n/r, 0, 0, 0,
|
||||||
0, n/t, 0, 0,
|
0, n/t, 0, 0,
|
||||||
0, 0, (f+n)/(n-f), -1,
|
0, 0, (f+n)/(n-f), -1,
|
||||||
0, 0, 2.0f*n*f/(n-f), 0
|
0, 0, 2.0f*n*f/(n-f), 0
|
||||||
}; // it's not rows, it's columns, 'GL_FALSE'
|
}; // it's not rows, it's columns, 'GL_FALSE'
|
||||||
SDL_LogVerbose(SDL_LOG_CATEGORY_RENDER, "n=%.1f f=%.1f fov=%.2f aspect=%.2f t=%.2f r=%.2f\n", n, f, fov, aspect, t, r);
|
SDL_LogVerbose(SDL_LOG_CATEGORY_RENDER, "n=%.1f f=%.1f fov=%.2f aspect=%.2f t=%.2f r=%.2f\n", n, f, fov, aspect, t, r);
|
||||||
glUseProgram(program);
|
glUseProgram(sp.program);
|
||||||
glUniformMatrix4fv(projMatrLoc, 1, GL_FALSE, projMatr);
|
glUniformMatrix4fv(sp.projMatrLoc, 1, GL_FALSE, projMatr);
|
||||||
glUseProgram(0);
|
glUseProgram(0);
|
||||||
glViewport(0, 0, (GLsizei)width, (GLsizei)height);
|
glViewport(0, 0, (GLsizei)width, (GLsizei)height);
|
||||||
}
|
}
|
||||||
|
|
||||||
void panicError ( void )
|
|
||||||
{
|
|
||||||
SDL_GL_DestroyContext(glcontext);
|
|
||||||
SDL_DestroyWindow(window);
|
|
||||||
SDL_Quit();
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
char *readFile ( const char *fileName )
|
|
||||||
{
|
|
||||||
SDL_IOStream *ioStream = SDL_IOFromFile(fileName, "rb");
|
|
||||||
if (!ioStream) {
|
|
||||||
SDL_LogCritical(SDL_LOG_CATEGORY_ASSERT, "ioStream: %s.", SDL_GetError());
|
|
||||||
panicError();
|
|
||||||
}
|
|
||||||
if (SDL_SeekIO(ioStream, 0, SDL_IO_SEEK_END) == -1) {
|
|
||||||
SDL_LogCritical(SDL_LOG_CATEGORY_ASSERT, "SDL_SeekIO_END: %s.", SDL_GetError());
|
|
||||||
panicError();
|
|
||||||
}
|
|
||||||
long len = SDL_TellIO(ioStream);
|
|
||||||
if (len == -1) {
|
|
||||||
SDL_LogCritical(SDL_LOG_CATEGORY_ASSERT, "SDL_TellIO: %s.", SDL_GetError());
|
|
||||||
panicError();
|
|
||||||
}
|
|
||||||
if (SDL_SeekIO(ioStream, 0, SDL_IO_SEEK_SET) == -1) {
|
|
||||||
SDL_LogCritical(SDL_LOG_CATEGORY_ASSERT, "SDL_IO_SEEK_SET: %s.", SDL_GetError());
|
|
||||||
panicError();
|
|
||||||
}
|
|
||||||
char *res = SDL_malloc(len + 1);
|
|
||||||
if (!res) {
|
|
||||||
SDL_LogCritical(SDL_LOG_CATEGORY_ASSERT, "SDL_malloc: %s.", SDL_GetError());
|
|
||||||
panicError();
|
|
||||||
}
|
|
||||||
if (SDL_ReadIO(ioStream, res, len) != (size_t)len) {
|
|
||||||
SDL_LogCritical(SDL_LOG_CATEGORY_ASSERT, "SDL_ReadIO: %s.", SDL_GetError());
|
|
||||||
panicError();
|
|
||||||
}
|
|
||||||
if (!SDL_CloseIO(ioStream)) {
|
|
||||||
SDL_LogCritical(SDL_LOG_CATEGORY_ASSERT, "SDL_CloseIO: %s.", SDL_GetError());
|
|
||||||
panicError();
|
|
||||||
}
|
|
||||||
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.");
|
|
||||||
panicError();
|
|
||||||
}
|
|
||||||
GLuint shader = glCreateShader(shaderType);
|
|
||||||
if (!shader) {
|
|
||||||
SDL_LogCritical(SDL_LOG_CATEGORY_ASSERT, "Error create shader type %s.", strShaderType);
|
|
||||||
panicError();
|
|
||||||
}
|
|
||||||
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.", strShaderType, info);
|
|
||||||
panicError();
|
|
||||||
}
|
|
||||||
return shader;
|
|
||||||
}
|
|
||||||
|
|
||||||
void createProgram ( GLuint *shaders, int len )
|
|
||||||
{
|
|
||||||
program = glCreateProgram();
|
|
||||||
if (!program) {
|
|
||||||
SDL_LogCritical(SDL_LOG_CATEGORY_ASSERT, "Can't to create shader program.");
|
|
||||||
panicError();
|
|
||||||
}
|
|
||||||
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", info);
|
|
||||||
panicError();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void createBuffer ( void )
|
|
||||||
{
|
|
||||||
GLushort indices[] = {
|
|
||||||
0, 1, 2,
|
|
||||||
0, 2, 3
|
|
||||||
};
|
|
||||||
float vertices[] = {
|
|
||||||
-1.0f, -1.0f, -2.0f, 1.0f, // left-bottom
|
|
||||||
-1.0f, 1.0f, -2.0f, 1.0f, // left-top
|
|
||||||
1.0f, 1.0f, -2.0f, 1.0f, // right-top
|
|
||||||
1.0f, -1.0f, -2.0f, 1.0f, // right-bottom
|
|
||||||
|
|
||||||
// colours
|
|
||||||
1.0f, 0.0f, 0.0f, 1.0f, // red
|
|
||||||
0.0f, 1.0f, 0.0f, 1.0f, // green
|
|
||||||
1.0f, 0.0f, 1.0f, 1.0f, // purple
|
|
||||||
1.0f, 1.0f, 0.0f, 1.0f // yellow
|
|
||||||
};
|
|
||||||
glGenBuffers(1, &vbo);
|
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, vbo);
|
|
||||||
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
|
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
|
||||||
|
|
||||||
glGenBuffers(1, &ibo);
|
|
||||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo);
|
|
||||||
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
|
|
||||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
void setUniformLocation ( void )
|
|
||||||
{
|
|
||||||
projMatrLoc = glGetUniformLocation(program, "projMatr");
|
|
||||||
}
|
|
||||||
|
|
||||||
void startShaderProg ( void )
|
|
||||||
{
|
|
||||||
createBuffer();
|
|
||||||
|
|
||||||
GLuint shaders[] = {
|
|
||||||
createShader("vertex.glsl", GL_VERTEX_SHADER),
|
|
||||||
createShader("fragment.glsl", GL_FRAGMENT_SHADER)
|
|
||||||
};
|
|
||||||
int len = sizeof(shaders) / sizeof(shaders[0]);
|
|
||||||
createProgram(shaders, len);
|
|
||||||
for (int i = 0; i < len; i++) {
|
|
||||||
glDeleteShader(shaders[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
setUniformLocation();
|
|
||||||
glEnable(GL_DEPTH_TEST);
|
|
||||||
glDepthMask(GL_TRUE);
|
|
||||||
glDepthFunc(GL_LEQUAL);
|
|
||||||
glDepthRange(0.0f, 1.0f);
|
|
||||||
}
|
|
||||||
|
|
||||||
void _GLBuffer( void )
|
|
||||||
{
|
|
||||||
glClearColor(0.0f, 0.0f, 1.0f, 0.0f);
|
|
||||||
glClearDepth(1.0f);
|
|
||||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
|
||||||
glUseProgram(program);
|
|
||||||
|
|
||||||
glEnableVertexAttribArray(0);
|
|
||||||
glEnableVertexAttribArray(1);
|
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, vbo);
|
|
||||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo);
|
|
||||||
glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, 0);
|
|
||||||
glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, 0, (void *) (4*4*sizeof(float)));
|
|
||||||
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, 0);
|
|
||||||
glDisableVertexAttribArray(0);
|
|
||||||
glDisableVertexAttribArray(1);
|
|
||||||
|
|
||||||
glUseProgram(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
int main( int argc, char* argv[] )
|
int main( int argc, char* argv[] )
|
||||||
{
|
{
|
||||||
|
_glWindows_t glW;
|
||||||
const int WIDTH = 640;
|
const int WIDTH = 640;
|
||||||
const int HEIGHT = 480;
|
const int HEIGHT = 480;
|
||||||
int delayThreshold = 2;
|
int delayThreshold = 2;
|
||||||
|
@ -256,12 +72,12 @@ 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)) {
|
||||||
SDL_LogCritical(SDL_LOG_CATEGORY_ASSERT, "SDL_Init failed: %s", SDL_GetError());
|
SDL_LogCritical(SDL_LOG_CATEGORY_ASSERT, "SDL_Init failed: %s", SDL_GetError());
|
||||||
panicError();
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE)) {
|
if (!SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_COMPATIBILITY)) {
|
||||||
SDL_LogCritical(SDL_LOG_CATEGORY_ASSERT, "Set atrribute SDL_GL_CONTEXT_PROFILE_MASK: %s", SDL_GetError());
|
SDL_LogCritical(SDL_LOG_CATEGORY_ASSERT, "Set atrribute SDL_GL_CONTEXT_PROFILE_MASK: %s", SDL_GetError());
|
||||||
panicError();
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
|
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
|
||||||
|
@ -277,19 +93,19 @@ int main( int argc, char* argv[] )
|
||||||
PerformancePeriod = 1.0 / SDL_GetPerformanceFrequency();
|
PerformancePeriod = 1.0 / SDL_GetPerformanceFrequency();
|
||||||
timeCounter = GetTime();
|
timeCounter = GetTime();
|
||||||
|
|
||||||
window = SDL_CreateWindow("Hello SDL", WIDTH, HEIGHT, SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE);
|
glW.window = SDL_CreateWindow("Hello SDL", WIDTH, HEIGHT, SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE);
|
||||||
if (!window) {
|
if (!glW.window) {
|
||||||
SDL_LogCritical(SDL_LOG_CATEGORY_ASSERT, "SDL_CreateWindow: %s", SDL_GetError());
|
SDL_LogCritical(SDL_LOG_CATEGORY_ASSERT, "SDL_CreateWindow: %s", SDL_GetError());
|
||||||
panicError();
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
glcontext = SDL_GL_CreateContext(window);
|
glW.glcontext = SDL_GL_CreateContext(glW.window);
|
||||||
if (!glcontext) {
|
if (!glW.glcontext) {
|
||||||
SDL_LogCritical(SDL_LOG_CATEGORY_ASSERT, "SDL_GL_CreateContext: %s", SDL_GetError());
|
SDL_LogCritical(SDL_LOG_CATEGORY_ASSERT, "SDL_GL_CreateContext: %s", SDL_GetError());
|
||||||
panicError();
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
SetTitle(window);
|
SetTitle(glW.window);
|
||||||
|
|
||||||
SDL_HideCursor();
|
SDL_HideCursor();
|
||||||
|
|
||||||
|
@ -297,7 +113,7 @@ int main( int argc, char* argv[] )
|
||||||
GLenum err = glewInit();
|
GLenum err = glewInit();
|
||||||
if (err != GLEW_OK) {
|
if (err != GLEW_OK) {
|
||||||
SDL_LogCritical(SDL_LOG_CATEGORY_ASSERT, "glewInit: %s", glewGetErrorString(err));
|
SDL_LogCritical(SDL_LOG_CATEGORY_ASSERT, "glewInit: %s", glewGetErrorString(err));
|
||||||
panicError();
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
SDL_LogVerbose(SDL_LOG_CATEGORY_RENDER, "Status: Using GLEW %s\n", glewGetString(GLEW_VERSION));
|
SDL_LogVerbose(SDL_LOG_CATEGORY_RENDER, "Status: Using GLEW %s\n", glewGetString(GLEW_VERSION));
|
||||||
|
@ -337,11 +153,11 @@ int main( int argc, char* argv[] )
|
||||||
FPS = 1;
|
FPS = 1;
|
||||||
}
|
}
|
||||||
FrameTime = 1.0 / FPS;
|
FrameTime = 1.0 / FPS;
|
||||||
SetTitle(window);
|
SetTitle(glW.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(glW.window);
|
||||||
}
|
}
|
||||||
if (e.key.key == SDLK_ESCAPE)
|
if (e.key.key == SDLK_ESCAPE)
|
||||||
loopShouldStop = true;
|
loopShouldStop = true;
|
||||||
|
@ -349,9 +165,9 @@ int main( int argc, char* argv[] )
|
||||||
}
|
}
|
||||||
|
|
||||||
_GLBuffer();
|
_GLBuffer();
|
||||||
if (!SDL_GL_SwapWindow(window)) {
|
if (!SDL_GL_SwapWindow(glW.window)) {
|
||||||
SDL_LogCritical(SDL_LOG_CATEGORY_ASSERT, "SDL_GL_SwapWwindow: %s", SDL_GetError());
|
SDL_LogCritical(SDL_LOG_CATEGORY_ASSERT, "SDL_GL_SwapWwindow: %s", SDL_GetError());
|
||||||
panicError();
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
sleepTime = timeCounter - GetTime();
|
sleepTime = timeCounter - GetTime();
|
||||||
|
@ -370,8 +186,8 @@ int main( int argc, char* argv[] )
|
||||||
timeCounter += FrameTime;
|
timeCounter += FrameTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
SDL_DestroyWindow(window);
|
SDL_DestroyWindow(glW.window);
|
||||||
SDL_GL_DestroyContext(glcontext);
|
SDL_GL_DestroyContext(glW.glcontext);
|
||||||
SDL_Quit();
|
SDL_Quit();
|
||||||
exit(EXIT_SUCCESS);
|
exit(EXIT_SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
143
opengl.c
Normal file
143
opengl.c
Normal file
|
@ -0,0 +1,143 @@
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include <GL/glew.h>
|
||||||
|
#include <SDL3/SDL.h>
|
||||||
|
#include <SDL3/SDL_opengl.h>
|
||||||
|
|
||||||
|
#include "opengl.h"
|
||||||
|
#include "readfile.h"
|
||||||
|
|
||||||
|
shaderProgram_t sp;
|
||||||
|
|
||||||
|
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.");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
GLuint shader = glCreateShader(shaderType);
|
||||||
|
if (!shader) {
|
||||||
|
SDL_LogCritical(SDL_LOG_CATEGORY_ASSERT, "Error create shader type %s.", strShaderType);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
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.", strShaderType, info);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
return shader;
|
||||||
|
}
|
||||||
|
|
||||||
|
void createProgram ( GLuint *shaders, int len )
|
||||||
|
{
|
||||||
|
sp.program = glCreateProgram();
|
||||||
|
if (!sp.program) {
|
||||||
|
SDL_LogCritical(SDL_LOG_CATEGORY_ASSERT, "Can't to create shader program.");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
for (int i = 0; i < len; i++) {
|
||||||
|
glAttachShader(sp.program, shaders[i]);
|
||||||
|
}
|
||||||
|
glLinkProgram(sp.program);
|
||||||
|
GLint status;
|
||||||
|
glGetProgramiv(sp.program, GL_LINK_STATUS, &status);
|
||||||
|
if (status == GL_FALSE) {
|
||||||
|
GLint infoLen;
|
||||||
|
glGetProgramiv(sp.program, GL_INFO_LOG_LENGTH, &infoLen);
|
||||||
|
GLchar *info = SDL_malloc(sizeof(GLchar) * (infoLen + 1));
|
||||||
|
glGetProgramInfoLog(sp.program, infoLen, NULL, info);
|
||||||
|
SDL_LogCritical(SDL_LOG_CATEGORY_ASSERT, "Link failed: %s", info);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void createBuffer ( void )
|
||||||
|
{
|
||||||
|
GLushort indices[] = {
|
||||||
|
0, 1, 2,
|
||||||
|
0, 2, 3
|
||||||
|
};
|
||||||
|
float vertices[] = {
|
||||||
|
-1.0f, -1.0f, -2.0f, 1.0f, // left-bottom
|
||||||
|
-1.0f, 1.0f, -2.0f, 1.0f, // left-top
|
||||||
|
1.0f, 1.0f, -2.0f, 1.0f, // right-top
|
||||||
|
1.0f, -1.0f, -2.0f, 1.0f, // right-bottom
|
||||||
|
|
||||||
|
// colours
|
||||||
|
1.0f, 0.0f, 0.0f, 1.0f, // red
|
||||||
|
0.0f, 1.0f, 0.0f, 1.0f, // green
|
||||||
|
1.0f, 0.0f, 1.0f, 1.0f, // purple
|
||||||
|
1.0f, 1.0f, 0.0f, 1.0f // yellow
|
||||||
|
};
|
||||||
|
glGenBuffers(1, &sp.vbo);
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, sp.vbo);
|
||||||
|
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||||
|
|
||||||
|
glGenBuffers(1, &sp.ibo);
|
||||||
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, sp.ibo);
|
||||||
|
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
|
||||||
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void setUniformLocation ( void )
|
||||||
|
{
|
||||||
|
sp.projMatrLoc = glGetUniformLocation(sp.program, "projMatr");
|
||||||
|
}
|
||||||
|
|
||||||
|
void startShaderProg ( void )
|
||||||
|
{
|
||||||
|
createBuffer();
|
||||||
|
|
||||||
|
GLuint shaders[] = {
|
||||||
|
createShader("vertex.glsl", GL_VERTEX_SHADER),
|
||||||
|
createShader("fragment.glsl", GL_FRAGMENT_SHADER)
|
||||||
|
};
|
||||||
|
int len = sizeof(shaders) / sizeof(shaders[0]);
|
||||||
|
createProgram(shaders, len);
|
||||||
|
for (int i = 0; i < len; i++) {
|
||||||
|
glDeleteShader(shaders[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
setUniformLocation();
|
||||||
|
glEnable(GL_DEPTH_TEST);
|
||||||
|
glDepthMask(GL_TRUE);
|
||||||
|
glDepthFunc(GL_LEQUAL);
|
||||||
|
glDepthRange(0.0f, 1.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
void _GLBuffer( void )
|
||||||
|
{
|
||||||
|
glClearColor(0.0f, 0.0f, 1.0f, 0.0f);
|
||||||
|
glClearDepth(1.0f);
|
||||||
|
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||||
|
glUseProgram(sp.program);
|
||||||
|
|
||||||
|
glEnableVertexAttribArray(0);
|
||||||
|
glEnableVertexAttribArray(1);
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, sp.vbo);
|
||||||
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, sp.ibo);
|
||||||
|
glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, 0);
|
||||||
|
glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, 0, (void *) (4*4*sizeof(float)));
|
||||||
|
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, 0);
|
||||||
|
glDisableVertexAttribArray(0);
|
||||||
|
glDisableVertexAttribArray(1);
|
||||||
|
|
||||||
|
glUseProgram(0);
|
||||||
|
}
|
22
opengl.h
Normal file
22
opengl.h
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
#ifndef OPENGL_H
|
||||||
|
#define OPENGL_H
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
SDL_Window* window;
|
||||||
|
SDL_GLContext glcontext;
|
||||||
|
} _glWindows_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
GLuint program;
|
||||||
|
GLuint vbo;
|
||||||
|
GLuint ibo;
|
||||||
|
GLuint projMatrLoc;
|
||||||
|
} shaderProgram_t;
|
||||||
|
|
||||||
|
GLuint createShader ( const char *shaderFile, GLenum shaderType );
|
||||||
|
void createProgram ( GLuint *shaders, int len );
|
||||||
|
void createBuffer ( void );
|
||||||
|
void startShaderProg ( void );
|
||||||
|
void _GLBuffer( void );
|
||||||
|
|
||||||
|
#endif
|
40
readfile.c
Normal file
40
readfile.c
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <SDL3/SDL.h>
|
||||||
|
#include "readfile.h"
|
||||||
|
|
||||||
|
char *readFile ( const char *fileName )
|
||||||
|
{
|
||||||
|
SDL_IOStream *ioStream = SDL_IOFromFile(fileName, "rb");
|
||||||
|
if (!ioStream) {
|
||||||
|
SDL_LogCritical(SDL_LOG_CATEGORY_ASSERT, "ioStream: %s.", SDL_GetError());
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
if (SDL_SeekIO(ioStream, 0, SDL_IO_SEEK_END) == -1) {
|
||||||
|
SDL_LogCritical(SDL_LOG_CATEGORY_ASSERT, "SDL_SeekIO_END: %s.", SDL_GetError());
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
long len = SDL_TellIO(ioStream);
|
||||||
|
if (len == -1) {
|
||||||
|
SDL_LogCritical(SDL_LOG_CATEGORY_ASSERT, "SDL_TellIO: %s.", SDL_GetError());
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
if (SDL_SeekIO(ioStream, 0, SDL_IO_SEEK_SET) == -1) {
|
||||||
|
SDL_LogCritical(SDL_LOG_CATEGORY_ASSERT, "SDL_IO_SEEK_SET: %s.", SDL_GetError());
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
char *res = SDL_malloc(len + 1);
|
||||||
|
if (!res) {
|
||||||
|
SDL_LogCritical(SDL_LOG_CATEGORY_ASSERT, "SDL_malloc: %s.", SDL_GetError());
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
if (SDL_ReadIO(ioStream, res, len) != (size_t)len) {
|
||||||
|
SDL_LogCritical(SDL_LOG_CATEGORY_ASSERT, "SDL_ReadIO: %s.", SDL_GetError());
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
if (!SDL_CloseIO(ioStream)) {
|
||||||
|
SDL_LogCritical(SDL_LOG_CATEGORY_ASSERT, "SDL_CloseIO: %s.", SDL_GetError());
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
res[len] = 0;
|
||||||
|
return res;
|
||||||
|
}
|
6
readfile.h
Normal file
6
readfile.h
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
#ifndef READFILE_H
|
||||||
|
#define READFILE_H
|
||||||
|
|
||||||
|
char *readFile ( const char *fileName );
|
||||||
|
|
||||||
|
#endif
|
Loading…
Add table
Reference in a new issue