Final Platform Layer 0.9.8-beta
Loading...
Searching...
No Matches
Modern OpenGL 3.3+

Table of Contents

main.cpp

#define FPL_IMPLEMENTATION
#define FPL_NO_VIDEO_SOFTWARE
#define FPL_NO_AUDIO
// You have to include GL.h yourself or use any other OpenGL loader you want.
// FPL just creates an OpenGL rendering context for you, but nothing more.
#include <GL/gl.h>
#ifndef APIENTRY
#define APIENTRY
#endif
#define APIENTRYP APIENTRY *
#include <stddef.h>
typedef ptrdiff_t GLsizeiptr;
typedef ptrdiff_t GLintptr;
typedef char GLchar;
#ifndef GL_CONTEXT_PROFILE_MASK
#define GL_CONTEXT_PROFILE_MASK 0x9126
#define GL_CONTEXT_FLAGS 0x821E
#define GL_CONTEXT_FLAG_FORWARD_COMPATIBLE_BIT 0x0001
#define GL_CONTEXT_FLAG_DEBUG_BIT 0x00000002
#define GL_CONTEXT_FLAG_ROBUST_ACCESS_BIT 0x00000004
#define GL_CONTEXT_FLAG_NO_ERROR_BIT 0x00000008
#define GL_CONTEXT_CORE_PROFILE_BIT 0x00000001
#define GL_CONTEXT_COMPATIBILITY_PROFILE_BIT 0x00000002
#endif // GL_CONTEXT_PROFILE_MASK
#define GL_COMPILE_STATUS 0x8B81
#define GL_INFO_LOG_LENGTH 0x8B84
#define GL_FRAGMENT_SHADER 0x8B30
#define GL_VERTEX_SHADER 0x8B31
#define GL_SHADING_LANGUAGE_VERSION 0x8B8C
#define GL_LINK_STATUS 0x8B82
#define GL_STATIC_DRAW 0x88E4
typedef GLuint(APIENTRYP PFNGLCREATESHADERPROC) (GLenum type);
typedef void (APIENTRYP PFNGLSHADERSOURCEPROC) (GLuint shader, GLsizei count, const GLchar *const*string, const GLint *length);
typedef void (APIENTRYP PFNGLCOMPILESHADERPROC) (GLuint shader);
typedef void (APIENTRYP PFNGLGETSHADERIVPROC) (GLuint shader, GLenum pname, GLint *params);
typedef void (APIENTRYP PFNGLATTACHSHADERPROC) (GLuint program, GLuint shader);
typedef GLuint(APIENTRYP PFNGLCREATEPROGRAMPROC) (void);
typedef void (APIENTRYP PFNGLGETSHADERINFOLOGPROC) (GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *infoLog);
typedef void (APIENTRYP PFNGLLINKPROGRAMPROC) (GLuint program);
typedef void (APIENTRYP PFNGLVALIDATEPROGRAMPROC) (GLuint program);
typedef void (APIENTRYP PFNGLGETPROGRAMIVPROC) (GLuint program, GLenum pname, GLint *params);
typedef void (APIENTRYP PFNGLGETPROGRAMINFOLOGPROC) (GLuint program, GLsizei bufSize, GLsizei *length, GLchar *infoLog);
typedef void (APIENTRYP PFNGLDELETESHADERPROC) (GLuint shader);
typedef void (APIENTRYP PFNGLUSEPROGRAMPROC) (GLuint program);
static PFNGLCREATESHADERPROC glCreateShader = NULL;
static PFNGLSHADERSOURCEPROC glShaderSource = NULL;
static PFNGLCOMPILESHADERPROC glCompileShader = NULL;
static PFNGLGETSHADERIVPROC glGetShaderiv = NULL;
static PFNGLATTACHSHADERPROC glAttachShader = NULL;
static PFNGLCREATEPROGRAMPROC glCreateProgram = NULL;
static PFNGLGETSHADERINFOLOGPROC glGetShaderInfoLog = NULL;
static PFNGLLINKPROGRAMPROC glLinkProgram = NULL;
static PFNGLVALIDATEPROGRAMPROC glValidateProgram = NULL;
static PFNGLGETPROGRAMIVPROC glGetProgramiv = NULL;
static PFNGLGETPROGRAMINFOLOGPROC glGetProgramInfoLog = NULL;
static PFNGLDELETESHADERPROC glDeleteShader = NULL;
static PFNGLUSEPROGRAMPROC glUseProgram = NULL;
#define GL_ARRAY_BUFFER 0x8892
typedef void (APIENTRYP PFNGLGENVERTEXARRAYSPROC) (GLsizei n, GLuint *arrays);
typedef void (APIENTRYP PFNGLBINDVERTEXARRAYPROC) (GLuint array);
typedef void (APIENTRYP PFNGLGENBUFFERSPROC) (GLsizei n, GLuint *buffers);
typedef void (APIENTRYP PFNGLBINDBUFFERPROC) (GLenum target, GLuint buffer);
typedef void (APIENTRYP PFNGLBUFFERDATAPROC) (GLenum target, GLsizeiptr size, const void *data, GLenum usage);
typedef void (APIENTRYP PFNGLENABLEVERTEXATTRIBARRAYPROC) (GLuint index);
typedef void (APIENTRYP PFNGLDISABLEVERTEXATTRIBARRAYPROC) (GLuint index);
typedef void (APIENTRYP PFNGLVERTEXATTRIBPOINTERPROC) (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void *pointer);
typedef void (APIENTRYP PFNGLDELETEVERTEXARRAYSPROC) (GLsizei n, const GLuint *arrays);
static PFNGLGENVERTEXARRAYSPROC glGenVertexArrays = NULL;
static PFNGLBINDVERTEXARRAYPROC glBindVertexArray = NULL;
static PFNGLGENBUFFERSPROC glGenBuffers = NULL;
static PFNGLBINDBUFFERPROC glBindBuffer = NULL;
static PFNGLBUFFERDATAPROC glBufferData = NULL;
static PFNGLENABLEVERTEXATTRIBARRAYPROC glEnableVertexAttribArray = NULL;
static PFNGLDISABLEVERTEXATTRIBARRAYPROC glDisableVertexAttribArray = NULL;
static PFNGLVERTEXATTRIBPOINTERPROC glVertexAttribPointer = NULL;
static PFNGLDELETEVERTEXARRAYSPROC glDeleteVertexArrays = NULL;
#if defined(FPL_PLATFORM_WINDOWS)
static void *GLProcAddress(const char *name) {
fpl__VideoState *videoState = (fpl__VideoState *)fpl__global__AppState->video.mem;
fplAssert(videoState != NULL);
fplAssert(videoState->win32.opengl.api.wglGetProcAddress != NULL);
void *result = videoState->win32.opengl.api.wglGetProcAddress(name);
return(result);
}
#else
static void *GLProcAddress(const char *name) {
fpl__VideoState *videoState = (fpl__VideoState *)fpl__global__AppState->video.mem;
fplAssert(videoState != NULL);
fplAssert(videoState->x11.opengl.api.glXGetProcAddress != NULL);
void *result = videoState->x11.opengl.api.glXGetProcAddress((const GLubyte *)name);
return(result);
}
#endif
static void LoadGLExtensions() {
glCreateShader = (PFNGLCREATESHADERPROC)GLProcAddress("glCreateShader");
glShaderSource = (PFNGLSHADERSOURCEPROC)GLProcAddress("glShaderSource");
glCompileShader = (PFNGLCOMPILESHADERPROC)GLProcAddress("glCompileShader");
glGetShaderiv = (PFNGLGETSHADERIVPROC)GLProcAddress("glGetShaderiv");
glAttachShader = (PFNGLATTACHSHADERPROC)GLProcAddress("glAttachShader");
glCreateProgram = (PFNGLCREATEPROGRAMPROC)GLProcAddress("glCreateProgram");
glGetShaderInfoLog = (PFNGLGETSHADERINFOLOGPROC)GLProcAddress("glGetShaderInfoLog");
glLinkProgram = (PFNGLLINKPROGRAMPROC)GLProcAddress("glLinkProgram");
glValidateProgram = (PFNGLVALIDATEPROGRAMPROC)GLProcAddress("glValidateProgram");
glGetProgramiv = (PFNGLGETPROGRAMIVPROC)GLProcAddress("glGetProgramiv");
glGetProgramInfoLog = (PFNGLGETPROGRAMINFOLOGPROC)GLProcAddress("glGetProgramInfoLog");
glDeleteShader = (PFNGLDELETESHADERPROC)GLProcAddress("glDeleteShader");
glUseProgram = (PFNGLUSEPROGRAMPROC)GLProcAddress("glUseProgram");
glGenVertexArrays = (PFNGLGENVERTEXARRAYSPROC)GLProcAddress("glGenVertexArrays");
glBindVertexArray = (PFNGLBINDVERTEXARRAYPROC)GLProcAddress("glBindVertexArray");
glGenBuffers = (PFNGLGENBUFFERSPROC)GLProcAddress("glGenBuffers");
glBindBuffer = (PFNGLBINDBUFFERPROC)GLProcAddress("glBindBuffer");
glBufferData = (PFNGLBUFFERDATAPROC)GLProcAddress("glBufferData");
glEnableVertexAttribArray = (PFNGLENABLEVERTEXATTRIBARRAYPROC)GLProcAddress("glEnableVertexAttribArray");
glDisableVertexAttribArray = (PFNGLENABLEVERTEXATTRIBARRAYPROC)GLProcAddress("glDisableVertexAttribArray");
glVertexAttribPointer = (PFNGLVERTEXATTRIBPOINTERPROC)GLProcAddress("glVertexAttribPointer");
glDeleteVertexArrays = (PFNGLDELETEVERTEXARRAYSPROC)GLProcAddress("glDeleteVertexArrays");
}
#define MODERN_OPENGL 1
static GLuint CreateShaderType(GLenum type, const char *source) {
GLuint shaderId = glCreateShader(type);
glShaderSource(shaderId, 1, &source, NULL);
glCompileShader(shaderId);
char info[1024 * 10] = fplZeroInit;
GLint compileResult;
glGetShaderiv(shaderId, GL_COMPILE_STATUS, &compileResult);
if(!compileResult) {
GLint infoLen;
glGetShaderiv(shaderId, GL_INFO_LOG_LENGTH, &infoLen);
fplAssert(infoLen <= fplArrayCount(info));
glGetShaderInfoLog(shaderId, infoLen, &infoLen, info);
fplConsoleFormatError("Failed compiling %s shader!\n", (type == GL_VERTEX_SHADER ? "vertex" : "fragment"));
fplConsoleFormatError("%s\n", info);
}
return(shaderId);
}
static GLuint CreateShaderProgram(const char *name, const char *vertexSource, const char *fragmentSource) {
GLuint programId = glCreateProgram();
GLuint vertexShader = CreateShaderType(GL_VERTEX_SHADER, vertexSource);
GLuint fragmentShader = CreateShaderType(GL_FRAGMENT_SHADER, fragmentSource);
glAttachShader(programId, vertexShader);
glAttachShader(programId, fragmentShader);
glLinkProgram(programId);
glValidateProgram(programId);
char info[1024 * 10] = fplZeroInit;
GLint linkResult;
glGetProgramiv(programId, GL_LINK_STATUS, &linkResult);
if(!linkResult) {
GLint infoLen;
glGetProgramiv(programId, GL_INFO_LOG_LENGTH, &infoLen);
fplAssert(infoLen <= fplArrayCount(info));
glGetProgramInfoLog(programId, infoLen, &infoLen, info);
fplConsoleFormatError("Failed linking '%s' shader!\n", name);
fplConsoleFormatError("%s\n", info);
}
glDeleteShader(fragmentShader);
glDeleteShader(vertexShader);
return(programId);
}
static bool RunModern() {
LoadGLExtensions();
GLuint vertexArrayID;
glGenVertexArrays(1, &vertexArrayID);
glBindVertexArray(vertexArrayID);
const char *glslVersion = (const char *)glGetString(GL_SHADING_LANGUAGE_VERSION);
fplConsoleFormatOut("OpenGL GLSL Version %s:\n", glslVersion);
int profileMask;
int contextFlags;
glGetIntegerv(GL_CONTEXT_PROFILE_MASK, &profileMask);
glGetIntegerv(GL_CONTEXT_FLAGS, &contextFlags);
fplConsoleFormatOut("OpenGL supported profiles:\n");
fplConsoleFormatOut("\tCore: %s\n", ((profileMask & GL_CONTEXT_CORE_PROFILE_BIT) ? "yes" : "no"));
fplConsoleFormatOut("\tForward: %s\n", ((contextFlags & GL_CONTEXT_FLAG_FORWARD_COMPATIBLE_BIT) ? "yes" : "no"));
fplConsoleOut("Running modern OpenGL\n");
const char vertexSource[] = {
"#version 330 core\n"
"\n"
"layout(location = 0) in vec4 inPosition;\n"
"\n"
"void main() {\n"
"\tgl_Position = inPosition;\n"
"}\n"
};
const char fragmentSource[] = {
"#version 330 core\n"
"\n"
"layout(location = 0) out vec4 outColor;\n"
"\n"
"void main() {\n"
"\toutColor = vec4(1.0, 0.0, 0.0, 1.0);\n"
"}\n"
};
GLuint shaderProgram = CreateShaderProgram("Test", vertexSource, fragmentSource);
float vertices[] = {
0.0f, 0.5f,
-0.5f, -0.5f,
0.5f, -0.5f
};
GLuint buffer;
glGenBuffers(1, &buffer);
glBindBuffer(GL_ARRAY_BUFFER, buffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glUseProgram(shaderProgram);
glBindBuffer(GL_ARRAY_BUFFER, buffer);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(float) * 2, NULL);
glClearColor(0.39f, 0.58f, 0.93f, 1.0f);
while(fplWindowUpdate()) {
while(fplPollEvent(&ev)) {}
fplWindowSize windowArea;
fplGetWindowSize(&windowArea);
glViewport(0, 0, windowArea.width, windowArea.height);
glClear(GL_COLOR_BUFFER_BIT);
glDrawArrays(GL_TRIANGLES, 0, 3);
}
glDisableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
glDeleteVertexArrays(1, &vertexArrayID);
return true;
}
int main(int argc, char **args) {
int result = 0;
fplCopyString("FPL Modern OpenGL", settings.window.title, fplArrayCount(settings.window.title));
const char *version = (const char *)glGetString(GL_VERSION);
const char *vendor = (const char *)glGetString(GL_VENDOR);
const char *renderer = (const char *)glGetString(GL_RENDERER);
fplConsoleFormatOut("OpenGL version: %s\n", version);
fplConsoleFormatOut("OpenGL vendor: %s\n", vendor);
fplConsoleFormatOut("OpenGL renderer: %s\n", renderer);
RunModern();
result = 0;
} else {
result = -1;
}
return(result);
}
Final Platform Layer (FPL) - A C99 Single-Header-File Platform Abstraction Library.
fpl_platform_api void fplConsoleOut(const char *text)
Writes the given text to the standard output console buffer.
fpl_common_api void fplConsoleFormatOut(const char *format,...)
Writes the given formatted text to the standard output console buffer.
fpl_common_api void fplConsoleFormatError(const char *format,...)
Writes the given formatted text to the standard error console buffer.
#define fplAssert(exp)
Breaks with an runtime assertion, when the specified expression evaluates to false.
#define fplZeroInit
Initializes a struct to zero.
#define fplArrayCount(arr)
Returns the element count from a static array. This should ideally produce a compile error when passi...
fpl_common_api void fplPlatformRelease()
Releases the resources allocated by the platform layer.
fpl_common_api bool fplPlatformInit(const fplInitFlags initFlags, const fplSettings *initSettings)
Initializes the platform layer.
fpl_common_api fplSettings fplMakeDefaultSettings()
Creates a full settings structure containing default values.
@ fplInitFlags_Video
Use a video backbuffer (This flag ensures that fplInitFlags_Window is included always)
@ fplOpenGLCompabilityFlags_Core
Use core profile.
@ fplVideoBackendType_OpenGL
OpenGL.
fpl_common_api char * fplCopyString(const char *source, char *dest, const size_t maxDestLen)
Copies the given source string into a destination string.
fpl_common_api void fplVideoFlip()
Forces the window to be redrawn or to swap the back/front buffer.
fpl_platform_api bool fplWindowUpdate()
Clears the internal event queue and updates input devices if needed.
fpl_platform_api bool fplGetWindowSize(fplWindowSize *outSize)
Retrieves the inner window size.
fpl_platform_api bool fplPollEvent(fplEvent *ev)
Polls the next event from the internal event queue or from the OS, handles them, and removes it from ...
A structure containing event data for all event types (Window, Keyboard, Mouse, etc....
fplOpenGLSettings opengl
OpenGL settings.
uint32_t minorVersion
Desired minor version.
fplOpenGLCompabilityFlags compabilityFlags
Compability flags.
uint8_t multiSamplingCount
Multisampling count.
uint32_t majorVersion
Desired major version.
A structure containing settings, such as window, video, etc.
fplWindowSettings window
Window settings.
fplVideoSettings video
Video settings.
fplVideoBackendType backend
video backend type
fplGraphicsApiSettings graphics
Graphics API settings.
char title[FPL_MAX_NAME_LENGTH]
Window title.
A structure containing the size of a window.
uint32_t width
Width in screen coordinates.
uint32_t height
Height in screen coordinates.