Complete hello triangle program but with GLAD instead of GLEW

This commit is contained in:
macmacmac 2024-09-08 14:03:29 -04:00
commit 23bc471bc2
7 changed files with 5593 additions and 0 deletions

6
.gitignore vendored Normal file
View File

@ -0,0 +1,6 @@
thirdparty/SDL2/
thirdparty/GLEW/
build/
.cache/
.vscode/

75
CMakeLists.txt Normal file
View File

@ -0,0 +1,75 @@
cmake_minimum_required(VERSION 3.20.0)
project(openglsdl2proj VERSION 0.1.0 LANGUAGES C CXX)
set(EXE_NAME project)
set(SDL2_LOCAL OFF)
set(GLEW_LOCAL OFF)
set(GLEW_NOT_GLAD OFF)
function(copy_shaders_to_target_dir target)
add_custom_command(
TARGET ${target} POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_directory
"$<TARGET_PROPERTY:${target},SOURCE_DIR>/shaders"
"$<TARGET_PROPERTY:${target},BINARY_DIR>/"
)
endfunction()
# Option to switch between a system sdl library and a sdl library from in project
# source code
option(SDL2_LOCAL "Use non-system SDL2 library" OFF)
# Same thing but for GLEW
option(GLEW_LOCAL "Use non-system GLEW library" OFF)
# Copied almost verbatim from here https://wiki.libsdl.org/SDL2/README/cmake#including-sdl-in-your-project
# This either gets SDL2 from it's CMakeLists.txt in source or links it from the system dll
if(SDL2_LOCAL)
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/thirdparty//SDL2 EXCLUDE_FROM_ALL ${CMAKE_CURRENT_BINARY_DIR}/SDL2)
else()
# 1. Look for a SDL2 package, 2. look for the SDL2 component and 3. fail if none can be found
find_package(SDL2 REQUIRED CONFIG REQUIRED COMPONENTS SDL2)
endif()
# Get OpenGL since we need it
#find_package(OpenGL REQUIRED COMPONENTS EGL)
# find glew either by local source code for just link to system dll
if(GLEW_LOCAL AND GLEW_NOT_GLAD)
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/thirdparty/GLEW/build/cmake EXCLUDE_FROM_ALL ${CMAKE_CURRENT_BINARY_DIR}/GLEW)
else()
find_package(GLEW REQUIRED)
endif()
# Main executable
add_executable(${EXE_NAME} ${CMAKE_CURRENT_SOURCE_DIR}/src/main.cc)
# Show all warnings, works for clang and GCC
target_compile_options(${EXE_NAME} PRIVATE -Wall -Wextra -Wpedantic) #-Werror)
# Set c++ standard for executable
set_target_properties(${EXE_NAME}
PROPERTIES
CXX_STANDARD 17
CXX_STANDARD_REQUIRED ON
CXX_EXTENSIONS ON
)
target_include_directories(${EXE_NAME} PRIVATE ${CMAKE_SOURCE_DIR}/include)
copy_shaders_to_target_dir(${EXE_NAME})
# Link to the actual SDL2 library.
# SDL2::SDL2 is the shared SDL library, SDL2::SDL2-static is the static SDL library.
if(NOT SDL2_LOCAL)
target_link_libraries(${EXE_NAME} PRIVATE SDL2::SDL2)
else()
target_link_libraries(${EXE_NAME} PRIVATE SDL2::SDL2-static)
endif()
# Link to OpenGL
#target_link_libraries(${EXE_NAME} PRIVATE OpenGL::EGL)
# Link to GLEW
if(NOT GLEW_LOCAL AND GLEW_NOT_GLAD)
target_link_libraries(${EXE_NAME} PRIVATE ${GLEW_LIBRARIES})
elseif(GLEW_NOT_GLAD)
# Static version of GLEW
target_link_libraries(${EXE_NAME} PRIVATE glew_s)
endif()

1437
include/glad/egl.h Normal file

File diff suppressed because it is too large Load Diff

3787
include/glad/gles2.h Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,4 @@
#version 320 es
out mediump vec4 FragColor;
void main(){ FragColor = vec4(0.0f, 0.5f, 0.25f, 1.0f);}

View File

@ -0,0 +1,7 @@
#version 320 es
layout (location = 0) in vec3 aPos;
void main()
{
gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0);
}

277
src/main.cc Normal file
View File

@ -0,0 +1,277 @@
#include <cstdio>
#include <cstdlib>
#include <ctime>
#define GLAD_EGL_IMPLEMENTATION
#define GLAD_GLES2_IMPLEMENTATION
#include "glad/gles2.h"
#include "SDL.h"
const char *mouseButtonName(int);
bool handleEvents(const SDL_Event&);
const char *readFile(const char *);
int main(const int argc, char **argv) {
for(int i=0;i<argc;i++) {
printf("Arg %d: %s\n", i, argv[i]);
}
SDL_Init(SDL_INIT_VIDEO|SDL_INIT_EVENTS);
SDL_Window *window = SDL_CreateWindow("SDL2 Window",
SDL_WINDOWPOS_CENTERED,
SDL_WINDOWPOS_CENTERED,
512,
512,
SDL_WINDOW_OPENGL|SDL_WINDOW_RESIZABLE);
SDL_Event event;
// Initialize GL context stuff (OpenGL ES 3.2)
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3); // change to 3 later
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 2); // change to 2 later
SDL_GL_SetAttribute(
SDL_GL_CONTEXT_PROFILE_MASK,
SDL_GL_CONTEXT_PROFILE_ES); // SDL_GL_CONTEXT_PROFILE_CORE
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
// Create GL context for SDL2
SDL_GLContext GLContext = SDL_GL_CreateContext(window);
if (GLContext == nullptr) {
fprintf(stderr, "Failed to create OpenGL context!\n");
SDL_DestroyWindow(window);
SDL_Quit();
return 1;
}
SDL_GL_SetSwapInterval(1); // sets VSYNC
// Setup GLAD (OpenGL ES 3.2)
int gladVersion = gladLoadGLES2(reinterpret_cast<GLADloadfunc>(SDL_GL_GetProcAddress));
printf("GL Version %d.%d\n", GLAD_VERSION_MAJOR(gladVersion), GLAD_VERSION_MINOR(gladVersion));
if (gladVersion == 0) {
fputs("Failed to init GLAD\n", stderr);
SDL_GL_DeleteContext(GLContext);
SDL_DestroyWindow(window);
SDL_Quit();
return 1;
}
// Variables needed for next steps
const char* vertexShaderSource = readFile("hello_triangle.vert");
const char* fragmentShaderSource = readFile("hello_triangle.frag");
if(vertexShaderSource == nullptr || fragmentShaderSource == nullptr) {
fputs("Could not get shaders from files!\n", stderr);
SDL_GL_DeleteContext(GLContext);
SDL_DestroyWindow(window);
SDL_Quit();
return 0;
}
int success;
char infoLog[512];
// Vertex shader
GLuint vertexShader;
vertexShader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertexShader, 1, &vertexShaderSource, nullptr);
glCompileShader(vertexShader);
glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &success);
if(!success)
{
glGetShaderInfoLog(vertexShader, 512, nullptr, infoLog);
printf("Vertex shader compile failure!\n%s\n", infoLog);
}
// Fragment shader
GLuint fragmentShader;
fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentShader, 1, &fragmentShaderSource, nullptr);
glCompileShader(fragmentShader);
glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &success);
if(!success)
{
glGetShaderInfoLog(fragmentShader, 512, nullptr, infoLog);
fprintf(stderr, "Fragment shader compile failure!\n%s\n", infoLog);
}
// Shader program
GLuint shaderProgram;
shaderProgram = glCreateProgram();
glAttachShader(shaderProgram, vertexShader);
glAttachShader(shaderProgram, fragmentShader);
glLinkProgram(shaderProgram);
glGetProgramiv(shaderProgram, GL_LINK_STATUS, &success);
if(!success) {
glGetProgramInfoLog(shaderProgram, 512, nullptr, infoLog);
fprintf(stderr, "Shader program linking failure!\n%s\n", infoLog);
}
glDeleteShader(vertexShader);
glDeleteShader(fragmentShader);
// Setup for our hello triangle
float vertices[] = {
-0.5f, -0.5f, 0.0f,
0.5f, -0.5f, 0.0f,
0.0f, 0.5f, 0.0f
};
// Vertex insanity
GLuint VBO, VAO;
glGenVertexArrays(1, &VAO);
glGenBuffers(1, &VBO);
glBindVertexArray(VAO);
// Bind buffers?
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
// Something with the vertex array
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
glEnableVertexAttribArray(0);
// Not sure what this is for
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
// Main loop
bool running = true;
while (running)
{
while (SDL_PollEvent(&event) > 0)
{
running = handleEvents(event);
// set color for window then
// clear color buffer
glClearColor(0.13f, 0.31f, 0.5f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
// Draw our triangle
glUseProgram(shaderProgram);
glBindVertexArray(VAO);
glDrawArrays(GL_TRIANGLES, 0, 3);
// Draw everything to the window
SDL_GL_SwapWindow(window);
}
}
// Cleanup
glDeleteVertexArrays(1, &VAO);
glDeleteBuffers(1, &VBO);
glDeleteProgram(shaderProgram);
SDL_GL_DeleteContext(GLContext);
SDL_DestroyWindow(window);
SDL_Quit();
return 0;
}
const char* readFile(const char* path) {
FILE *fd = nullptr;
#if _MSC_VER
fopen_s(&fd, path, "rb");
#else
fd = fopen(path, "rb");
#endif
long fileSize = 0;
char* buf = nullptr;
if(fd == nullptr) {
fprintf(stderr, "Could not open %s\n", path);
return nullptr;
}
fseek(fd, 0L, SEEK_END);
fileSize = ftell(fd);
fseek(fd, 0L, SEEK_SET);
buf = reinterpret_cast<char*>(malloc(sizeof(char) * (fileSize + 1)));
fread((void*)buf, sizeof(uint8_t), fileSize, fd);
fclose(fd);
buf[fileSize] = '\0';
printf("0x%02x\n", buf[fileSize]);
return buf;
}
char const *mouseButtonName(const int button)
{
const char *result = "NO_BUTTON";
switch (button)
{
case SDL_BUTTON_LEFT:
result = "left";
break;
case SDL_BUTTON_MIDDLE:
result = "middle";
break;
case SDL_BUTTON_RIGHT:
result = "right";
break;
default:
result = "unknown";
break;
}
return result;
}
bool handleEvents(const SDL_Event& event)
{
switch (event.type)
{
case SDL_QUIT:
puts("Quitting application");
return false;
// Shows xy of mouse in window
case SDL_MOUSEMOTION:
printf("Mouse Position = { %d %d }\n",
event.motion.x,
event.motion.y);
return true;
// For debugging, shows name of mouse button pressed
case SDL_MOUSEBUTTONDOWN:
case SDL_MOUSEBUTTONUP:
printf("%s mouse button %s\n",
mouseButtonName(event.button.button)
,((event.button.state == SDL_PRESSED) ? "pressed" : "released"));
return true;
// For debugging, shows name of key that is pressed
case SDL_KEYDOWN:
case SDL_KEYUP:
printf("Key %s %s\n",
SDL_GetKeyName(event.key.keysym.sym),
((event.key.state == SDL_PRESSED) ? "pressed" : "released"));
return true;
// Handle resizing window
case SDL_WINDOWEVENT:
if(event.window.event == SDL_WINDOWEVENT_SIZE_CHANGED) {
glViewport(0,0, event.window.data1,event.window.data2);
}
return true;
default:
return true;
}
}