Skip to content

Instantly share code, notes, and snippets.

@leonkasovan
Created November 9, 2024 03:51
Show Gist options
  • Save leonkasovan/61e20ef84bef7b17ea02580db7ba54b6 to your computer and use it in GitHub Desktop.
Save leonkasovan/61e20ef84bef7b17ea02580db7ba54b6 to your computer and use it in GitHub Desktop.
Command line tool to test shader compiler (using OpenGL + SDL2).
/*
Command line tool to test shader compiler (using OpenGL + SDL2).
Run it inside folder that contains shader files.
If filename consists "frag" then it treat as fragment shader.
If filename consists "vert" then it treat as vertex shader.
If filename consists "geo" then it treat as geometry shader.
Build:
gcc main.c -o compile_shader -lGL `sdl2-config --cflags --libs`
*/
#include <GL/gl.h>
#include <SDL2/SDL.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <dirent.h>
// Function to read shader source from a file
char* readShaderSource(const char* shaderFile) {
FILE* file = fopen(shaderFile, "rb");
if (!file) {
printf("Error: Could not open shader file %s\n", shaderFile);
return NULL;
}
fseek(file, 0, SEEK_END);
long length = ftell(file);
fseek(file, 0, SEEK_SET);
char* source = (char*)malloc(length + 1);
fread(source, 1, length, file);
source[length] = '\0';
fclose(file);
return source;
}
// Function to compile a shader
GLuint compileShader(const char* shaderFile, GLenum shaderType) {
// Read the shader source from file
char* shaderSource = readShaderSource(shaderFile);
if (!shaderSource) {
return 0;
}
// Create and compile the shader
GLuint shader = glCreateShader(shaderType);
glShaderSource(shader, 1, (const char**)&shaderSource, NULL);
glCompileShader(shader);
// Check for compilation errors
GLint compileStatus;
glGetShaderiv(shader, GL_COMPILE_STATUS, &compileStatus);
printf("\n--------------------------------------------------------------------\nCompiling %s ...\n", shaderFile);
if (compileStatus == GL_FALSE) {
GLint logLength;
glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &logLength);
char* infoLog = (char*)malloc(logLength);
glGetShaderInfoLog(shader, logLength, NULL, infoLog);
// printf("Error compiling shader (%s): %s\n", shaderFile, infoLog);
printf("%s", infoLog);
free(infoLog);
glDeleteShader(shader);
free(shaderSource);
return 0;
}
// Clean up and return the shader ID
free(shaderSource);
return shader;
}
int main() {
// Initialize SDL
if (SDL_Init(SDL_INIT_VIDEO) < 0)
{
fprintf(stderr, "Failed to initialize SDL: %s\n", SDL_GetError());
return -1;
}
// Set SDL to use an OpenGL context (version 2.1 for compatibility with OpenGL 2.1)
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 1);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
// Create a window with an OpenGL context
SDL_Window *window = SDL_CreateWindow(
"Shader Compile Test",
SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
640, 480,
SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN);
if (!window)
{
fprintf(stderr, "Failed to create SDL window: %s\n", SDL_GetError());
SDL_Quit();
return -1;
}
SDL_GLContext glContext = SDL_GL_CreateContext(window);
if (!glContext)
{
fprintf(stderr, "Failed to create OpenGL context: %s\n", SDL_GetError());
SDL_DestroyWindow(window);
SDL_Quit();
return -1;
}
// Open the directory specified by the user
DIR *dir = opendir(".");
if (dir == NULL)
{
perror("Unable to open directory");
return 1;
}
struct dirent *entry;
// Loop through directory entries
while ((entry = readdir(dir)) != NULL)
{
// Check if 'frag' is in the filename
if (strstr(entry->d_name, "frag") != NULL) {
printf("Result %s %s\n", entry->d_name, compileShader(entry->d_name, GL_FRAGMENT_SHADER) ? "OK" : "FAIL");
} else if (strstr(entry->d_name, "vert") != NULL) {
printf("Result %s %s\n", entry->d_name, compileShader(entry->d_name, GL_VERTEX_SHADER) ? "OK" : "FAIL");
} else if (strstr(entry->d_name, "geo") != NULL) {
printf("Result %s %s\n", entry->d_name, compileShader(entry->d_name, GL_GEOMETRY_SHADER_EXT) ? "OK" : "FAIL");
}
}
// Close the directory
closedir(dir);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment