diff --git a/CMakeLists.txt b/CMakeLists.txt index 9be4e92..9ed9e10 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,7 +1,14 @@ cmake_minimum_required(VERSION 3.25) project(ssts C) -add_executable(${PROJECT_NAME} main.c) +set(SOURCE_FILES main.c) +set(HEADER_FILES ) +set(SHADER_FILES shader.vert shader.frag) + +foreach(SHADER IN LISTS SHADER_FILES) +configure_file(${SHADER} ${CMAKE_CURRENT_BINARY_DIR} COPYONLY) +endforeach() +add_executable(${PROJECT_NAME} ${HEADER_FILES} ${SOURCE_FILES} ${SHADER_FILES}) # We need a CMAKE_DIR with some code to find external dependencies set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake/") @@ -9,7 +16,8 @@ set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake/") find_package(OpenGL REQUIRED) find_package(GLUT REQUIRED) find_package(GLEW REQUIRED) +find_package(assimp REQUIRED) -include_directories(${PROJECT_NAME} ${OPENGL_INCLUDE_DIRS} ${GLUT_INCLUDE_DIRS} ${GLEW_INCLUDE_DIRS}) +include_directories(${PROJECT_NAME} ${OPENGL_INCLUDE_DIRS} ${GLUT_INCLUDE_DIRS} ${GLEW_INCLUDE_DIRS} ${ASSIMP_INCLUDE_DIRS}) -target_link_libraries(${PROJECT_NAME} ${OPENGL_LIBRARIES} ${GLUT_LIBRARIES} ${GLEW_LIBRARIES}) \ No newline at end of file +target_link_libraries(${PROJECT_NAME} ${OPENGL_LIBRARIES} ${GLUT_LIBRARIES} ${GLEW_LIBRARIES} ${ASSIMP_LIBRARIES}) \ No newline at end of file diff --git a/main.c b/main.c index 5124e65..87b1f0d 100644 --- a/main.c +++ b/main.c @@ -2,17 +2,175 @@ #include #include -int main(int argc, char **argv) { +unsigned int vao; +unsigned int vbo; +unsigned int shader_program; +unsigned int vertex_shader; +unsigned int fragment_shader; +const char *vertex_shader_location = "./shader.vert"; +const char *fragment_shader_location = "./shader.frag"; + +float vertices[] = { + -0.5f, -0.5f, 0.0f, + 0.5f, -0.5f, 0.0f, + 0.0f, 0.5f, 0.0f +}; + +int load_shader(const char *path, unsigned int shader) { + FILE *fp = fopen(path, "r"); + int len = 0; + char *ftext; + + if (fp == NULL) { + fprintf(stderr, "Error: Cannot open file '%s'\n", path); + return -1; + } + + fseek(fp, 0L, SEEK_END); + len = ftell(fp); + + if (len == -1) { + fprintf(stderr, "Error: Cannot fetch length of file '%s'\n", path); + return -1; + } + + fseek(fp, 0L, SEEK_SET); + + ftext = (char *) malloc(len); + if (ftext == NULL) { + fprintf(stderr, "Error: Cannot allocate enough memory for file's contents '%s'\n", path); + return -1; + } + + fread(ftext, sizeof(char), len, fp); + fclose(fp); + + glShaderSource(shader, 1, (const char **) &ftext, &len); + glCompileShader(shader); + + int success; + glGetShaderiv(shader, GL_COMPILE_STATUS, &success); + + if (success != GL_TRUE) { + int log_length; + glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &log_length); + + char log[log_length]; + glGetShaderInfoLog(shader, log_length, NULL, log); + + fprintf(stderr, "Shader Compilation Error: %s\n", log); + return -1; + } + + // RUD + free(ftext); + + return 0; +} + +int setup() { + vertex_shader = glCreateShader(GL_VERTEX_SHADER); + fragment_shader = glCreateShader(GL_FRAGMENT_SHADER); + + if (load_shader(vertex_shader_location, vertex_shader) == -1) { + return -1; + } + + if (load_shader(fragment_shader_location, fragment_shader) == -1) { + return -1; + } + + shader_program = glCreateProgram(); + glAttachShader(shader_program, vertex_shader); + glAttachShader(shader_program, fragment_shader); + glLinkProgram(shader_program); + + int success; + glGetProgramiv(shader_program, GL_LINK_STATUS, &success); + + if (success != GL_TRUE) { + int log_length; + glGetProgramiv(shader_program, GL_INFO_LOG_LENGTH, &log_length); + + char log[log_length]; + glGetProgramInfoLog(shader_program, log_length, NULL, log); + + fprintf(stderr, "Shader Compilation Error: %s\n", log); + return -1; + } + + glGenVertexArrays(1, &vao); + glGenBuffers(1, &vbo); + + // RUD + glDeleteShader(vertex_shader); + glDeleteShader(fragment_shader); + + return 0; +} + +int post_setup() { + glBindVertexArray(vao); + + glBindBuffer(GL_ARRAY_BUFFER, vbo); + glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); + + glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*) 0); + glEnableVertexAttribArray(0); + + glBindBuffer(GL_ARRAY_BUFFER, 0); + glBindVertexArray(0); +} + +void keyboard(unsigned char key, int x, int y) { + switch (key) { + case '\x1B': + { + exit(EXIT_SUCCESS); + break; + } + } +} + + +void display() { + glClearColor(0.0f, 0.0f, 0.0f, 0.0f); + glClear(GL_COLOR_BUFFER_BIT); + + glUseProgram(shader_program); + glBindVertexArray(vao); + + glDrawArrays(GL_TRIANGLES, 0, 3); + + glutSwapBuffers(); +} + +int main(int argc, char **argv) { glutInit(&argc, argv); glutCreateWindow("Simple Space Time Simulator"); GLenum err = glewInit(); if (err != GLEW_OK) { fprintf(stderr, "Error: %s\n", glewGetErrorString(err)); + return EXIT_FAILURE; + } + + fprintf(stdout, "Status: using with GLEW %s\n", glewGetString(GLEW_VERSION)); + + glutKeyboardFunc(&keyboard); + glutDisplayFunc(&display); + + if (setup() == -1) { + fprintf(stderr, "Error: Failed to setup\n"); return -1; } - fprintf(stdout, "Status: using GLEW %s\n", glewGetString(GLEW_VERSION)); + if (post_setup() == -1) { + fprintf(stderr, "Error: Failed to post-setup\n"); + return -1; + } - return 0; + glutMainLoop(); + + return EXIT_SUCCESS; } diff --git a/shader.frag b/shader.frag new file mode 100644 index 0000000..6a826ed --- /dev/null +++ b/shader.frag @@ -0,0 +1,6 @@ +#version 330 core +out vec4 FragColor; + +void main() { + FragColor = vec4(1.0f, 1.0f, 1.0f, 1.0f); +} \ No newline at end of file diff --git a/shader.vert b/shader.vert new file mode 100644 index 0000000..3c19984 --- /dev/null +++ b/shader.vert @@ -0,0 +1,6 @@ +#version 330 core +layout (location = 0) in vec3 pos; + +void main() { + gl_Position = vec4(pos.x, pos.y, pos.z, 1.0f); +} \ No newline at end of file