diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/cube.c | 39 | ||||
| -rw-r--r-- | src/cube.h | 4 | ||||
| -rw-r--r-- | src/includes.h | 28 | ||||
| -rw-r--r-- | src/main.c | 152 | ||||
| -rw-r--r-- | src/main.h | 26 | ||||
| -rw-r--r-- | src/object.c | 109 | ||||
| -rw-r--r-- | src/object.h | 47 | ||||
| -rw-r--r-- | src/player.h | 13 | ||||
| -rw-r--r-- | src/shader.c | 39 | ||||
| -rw-r--r-- | src/shader.h | 4 | ||||
| -rw-r--r-- | src/shaders/basic.frag | 6 | ||||
| -rw-r--r-- | src/shaders/basic.vert | 6 | ||||
| -rw-r--r-- | src/shaders/test.frag | 10 | ||||
| -rw-r--r-- | src/shaders/test.vert | 19 |
14 files changed, 502 insertions, 0 deletions
diff --git a/src/cube.c b/src/cube.c new file mode 100644 index 0000000..66723ac --- /dev/null +++ b/src/cube.c @@ -0,0 +1,39 @@ +#include "cube.h" + +ViewModel createCube() +{ + float vertices[] = { + 1.0f, 1.0f, -1.0f, + 1.0f, -1.0f, -1.0f, + -1.0f, -1.0f, -1.0f, + -1.0f, 1.0f, -1.0f, + + 1.0f, 1.0f, 1.0f, + 1.0f, -1.0f, 1.0f, + -1.0f, -1.0f, 1.0f, + -1.0f, 1.0f, 1.0f + }; + unsigned int indices[] = { + 0, 1, 2, + 0, 2, 3, + + 4, 5, 6, + 4, 6, 7, + + 0, 4, 5, + 2, 6, 3, + + 3, 7, 6, + 1, 5, 0, + + 3, 7, 0, + 0, 4, 7, + + 2, 6, 1, + 1, 5, 6 + }; + + ViewModel model; + createViewModel(&model, 8, vertices, 38, indices); + return model; +} diff --git a/src/cube.h b/src/cube.h new file mode 100644 index 0000000..1e932c8 --- /dev/null +++ b/src/cube.h @@ -0,0 +1,4 @@ +#pragma once +#include "object.h" + +ViewModel createCube(); diff --git a/src/includes.h b/src/includes.h new file mode 100644 index 0000000..efbc626 --- /dev/null +++ b/src/includes.h @@ -0,0 +1,28 @@ +#pragma once + +#include <stdio.h> +#include <stddef.h> +#include <math.h> + +#include <SDL3/SDL_init.h> +#include <SDL3/SDL_video.h> +#include <SDL3/SDL_events.h> +#include <SDL3/SDL_iostream.h> +#include <SDL3/SDL_time.h> +#include <SDL3/SDL_timer.h> +#include <SDL3/SDL_stdinc.h> +#include <SDL3/SDL_thread.h> +//#include <SDL3/SDL_image.h> + +#include <cglm/cglm.h> +#include <cglm/mat4.h> +#include <cglm/vec3.h> + +#include <glad/gl.h> + +#include <assimp/cimport.h> +#include <assimp/scene.h> +#include <assimp/mesh.h> +#include <assimp/postprocess.h> + +#include "player.h" diff --git a/src/main.c b/src/main.c new file mode 100644 index 0000000..eb655b7 --- /dev/null +++ b/src/main.c @@ -0,0 +1,152 @@ +#include "includes.h" +#include "main.h" +#include "shader.h" +#include "object.h" +#include "cube.h" + +inline void handleEvents(Game* game) +{ + SDL_Event event; + SDL_PollEvent(&event); + switch (event.type) { + case SDL_EVENT_QUIT: + game->running = 0; + break; + } +} + +int initGame(Game* game) +{ + game->window_width = 600; + game->window_height = 400; + + game->window = SDL_CreateWindow( + "OpenGL Test", + game->window_width, + game->window_height, + SDL_WINDOW_OPENGL + ); + + glm_vec3_zero(game->player.pos); + + // OpenGL stuff starts here + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE); + game->gpu = SDL_GL_CreateContext(game->window); + + SDL_GL_MakeCurrent(game->window, game->gpu); + + //VSYNC: +// SDL_SetWindowSurfaceVSync(game->window, SDL_WINDOW_SURFACE_VSYNC_DISABLED); +// SDL_GL_SetSwapInterval(0); + + game->running = 1; + + int version = gladLoadGL((GLADloadfunc)SDL_GL_GetProcAddress); + if (version == 0) { + return 1; + } + + glEnable(GL_DEPTH_TEST); + + return 0; +} + +int killGame(Game* game) +{ + SDL_GL_DestroyContext(game->gpu); + SDL_DestroyWindow(game->window); + return 0; +} + +void setupProjection(Game* game) +{ + glm_perspective(90.0f, ((float)game->window_width)/((float)game->window_height), 0.1f, 40.0f, game->projection); + + glUniformMatrix4fv(game->projection_loc, 1, GL_FALSE, (float*)game->projection); +} + +int main() +{ + Game game; + initGame(&game); + + unsigned int vertex_shader, fragment_shader, shader_program; + + vertex_shader = loadShader("../src/shaders/test.vert", GL_VERTEX_SHADER); + fragment_shader = loadShader("../src/shaders/test.frag", GL_FRAGMENT_SHADER); + + shader_program = shaderProgram(vertex_shader, fragment_shader); + + glClearColor(0.0f, 0.25f, 0.5f, 1.0f); + +// TODO: texture loading, will add when sdl 3.4 +// +// float tex_coords[] = { +// 1.0f, 1.0f, +// 1.0f, 0.0f, +// 0.0f, 0.0f, +// 0.0f, 1.0f, +// }; +// +// glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); +// glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); +// +// float border_color[] = {1.0f, 1.0f, 1.0f, 1.0f}; +// glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, border_color); +// +// glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); +// glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + + ViewModel cubeModel = createCube(); + + ViewModel pengerModel = loadViewModel("../assets/objects/penger.obj"); + + Object myCube; + + Object penger; + + createObject(&myCube, &cubeModel); + + createObject(&penger, &pengerModel); + + moveObject(&penger, (vec3){0.0f, -0.5f, -1.0f}); + + scaleObject(&penger, (vec3){1.0f, 1.0f, 1.0f}); + + game.transform_loc = glGetUniformLocation(shader_program, "model"); + game.projection_loc = glGetUniformLocation(shader_program, "projection"); + + SDL_Time time; + +// Enable/disable wireframe rendering: + glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); + + glUseProgram(shader_program); + + setupProjection(&game); + + bindViewModel(&pengerModel); + while (game.running) { + for (int i=0;i<628;i++) { + glClear(GL_COLOR_BUFFER_BIT); + glClear(GL_DEPTH_BUFFER_BIT); + + rotateObject(&penger, (float)i/100, (vec3){0.0f, 1.0f, 0.0f}); + drawObject(&game, &penger); + + SDL_GL_SwapWindow(game.window); + + handleEvents(&game); + } + + } + + killViewModel(&pengerModel); + killViewModel(&cubeModel); + glDeleteShader(vertex_shader); + glDeleteShader(fragment_shader); + killGame(&game); + return 0; +} diff --git a/src/main.h b/src/main.h new file mode 100644 index 0000000..389957b --- /dev/null +++ b/src/main.h @@ -0,0 +1,26 @@ +#pragma once +#include "includes.h" + +typedef struct { + SDL_Window *window; + + int window_width; + int window_height; + + mat4 projection; + + SDL_GLContext gpu; + + int transform_loc, projection_loc; + + int running; + + Player player; +} Game; + +void handleEvents(Game* game); + +void setupProjection(float fov, Game* game); + +int initGame(Game* game); +int killGame(Game* game); diff --git a/src/object.c b/src/object.c new file mode 100644 index 0000000..25d504f --- /dev/null +++ b/src/object.c @@ -0,0 +1,109 @@ +#include "object.h" + +void createViewModel(ViewModel *model, int num_vertices, float *vert, int num_indices, unsigned int *indices) +{ + model->num_indices = num_indices; + + glGenVertexArrays(1, &model->VAO); + glBindVertexArray(model->VAO); + + glGenBuffers(1, &model->VBO); + glBindBuffer(GL_ARRAY_BUFFER, model->VBO); + glBufferData(GL_ARRAY_BUFFER, sizeof(float)*num_vertices*3, vert, GL_STATIC_DRAW); + + glGenBuffers(1, &model->EBO); + + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, model->EBO); + glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(unsigned int)*num_indices, indices, GL_STATIC_DRAW); + + glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0); + glEnableVertexAttribArray(0); +} + +void killViewModel(ViewModel *model) +{ + glDeleteVertexArrays(1, &model->VAO); + glDeleteBuffers(1, &model->VBO); + glDeleteBuffers(1, &model->EBO); +} + +void bindViewModel(ViewModel *model) +{ + glBindVertexArray(model->VAO); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, model->EBO); +} + +ViewModel loadViewModel(const char* filename) +{ + const struct aiScene* scene = aiImportFile(filename, + aiProcess_CalcTangentSpace | + aiProcess_Triangulate | + aiProcess_JoinIdenticalVertices | + aiProcess_SortByPType); + + struct aiMesh *mesh = scene->mMeshes[0]; + + unsigned int *indices = malloc(mesh->mNumFaces*3*sizeof(unsigned int)); + int index = 0; + for (unsigned int i=0;i<mesh->mNumFaces;i++) { + memcpy(&indices[index], mesh->mFaces[i].mIndices, 3*sizeof(unsigned int)); + index+=3; + } + + ViewModel model; + createViewModel(&model, mesh->mNumVertices, (float*)mesh->mVertices, mesh->mNumFaces*3, indices); + free(indices); + return model; +} + +void createObject(Object *obj, ViewModel *model) +{ + obj->model = model; + glm_mat4_identity(obj->transform); + + glm_vec3_zero(obj->pos); + glm_vec3_one(obj->size); + + obj->rotation.angle = 0.0f; + glm_vec3_zero(obj->rotation.direction); +} + +void moveObject(Object *obj, vec3 pos) +{ + glm_vec3_copy( + pos, + obj->pos + ); + updateObjectTransform(obj); +} + +void scaleObject(Object *obj, vec3 scale) +{ + glm_scale(obj->transform, scale); + updateObjectTransform(obj); +} + +void rotateObject(Object *obj, float angle, vec3 direction) +{ + obj->rotation.angle = angle; + glm_vec3_copy( + direction, + obj->rotation.direction + ); + updateObjectTransform(obj); +} + +inline void updateObjectTransform(Object *obj) +{ + glm_mat4_identity(obj->transform); + glm_translate(obj->transform, obj->pos); + glm_rotate(obj->transform, obj->rotation.angle, obj->rotation.direction); + glm_scale(obj->transform, obj->size); +} + +void drawObject(Game *game, Object *obj) +{ + glUniformMatrix4fv(game->transform_loc, 1, GL_FALSE, (float*)obj->transform); + + glDrawElements(GL_TRIANGLES, obj->model->num_indices, GL_UNSIGNED_INT, 0); +} diff --git a/src/object.h b/src/object.h new file mode 100644 index 0000000..b4cc06d --- /dev/null +++ b/src/object.h @@ -0,0 +1,47 @@ +#pragma once +#include "main.h" +#include "includes.h" + +typedef struct { + float angle; + vec3 direction; +} Rotation; + +typedef struct { + int num_indices; + + unsigned int VAO, VBO, EBO; +} ViewModel; + +typedef struct { + ViewModel *model; + + vec3 pos, size; + + Rotation rotation; + + mat4 transform; +} Object; + +void createViewModel(ViewModel *model, int num_vertices, float *vert, int num_indices, unsigned int *indices); + +void killViewModel(ViewModel *model); + +void bindViewModel(ViewModel *model); + +ViewModel loadViewModel(const char* filename); + +void createObject(Object *obj, ViewModel *model); + + +void moveObject(Object *obj, vec3 pos); + +void scaleObject(Object *obj, vec3 scale); + +void rotateObject(Object *obj, float angle, vec3 direction); + + +void updateObjectTransform(Object *obj); + + +void drawObject(Game *game, Object *obj); diff --git a/src/player.h b/src/player.h new file mode 100644 index 0000000..f81760c --- /dev/null +++ b/src/player.h @@ -0,0 +1,13 @@ +#pragma once + +typedef struct { + vec3 pos; + vec3 target; + vec3 direction; + vec3 up; +} Camera; + +typedef struct { + vec3 pos; + Camera camera; +} Player; diff --git a/src/shader.c b/src/shader.c new file mode 100644 index 0000000..022879e --- /dev/null +++ b/src/shader.c @@ -0,0 +1,39 @@ +#include "shader.h" +#include "includes.h" + +unsigned int loadShader(const char* filename, unsigned int shadertype) +{ + void* shader_source = SDL_LoadFile(filename, NULL); + unsigned int shader = glCreateShader(shadertype); + glShaderSource(shader, 1, (const char**)&shader_source, NULL); + glCompileShader(shader); + SDL_free(shader_source); + + int success; + + glGetShaderiv(shader, GL_COMPILE_STATUS, &success); + if (!success) { + printf("Couldn't compile shader\n"); + return 0; + } + + return shader; +} + +unsigned int shaderProgram(unsigned int vertex_shader, unsigned int fragment_shader) +{ + unsigned int shader_program; + 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) { + printf("Couldn't link shader program\n"); + return 0; + } + + return shader_program; +} diff --git a/src/shader.h b/src/shader.h new file mode 100644 index 0000000..3bb9421 --- /dev/null +++ b/src/shader.h @@ -0,0 +1,4 @@ +#pragma once + +unsigned int loadShader(const char* filename, unsigned int shadertype); +unsigned int shaderProgram(unsigned int vertex_shader, unsigned int fragment_shader); diff --git a/src/shaders/basic.frag b/src/shaders/basic.frag new file mode 100644 index 0000000..00d2a13 --- /dev/null +++ b/src/shaders/basic.frag @@ -0,0 +1,6 @@ +#version 330 core +out vec4 FragColor; +void main() +{ + FragColor = vec4(1.0f, 0.5f, 0.2f, 1.0f); +} diff --git a/src/shaders/basic.vert b/src/shaders/basic.vert new file mode 100644 index 0000000..684ddbb --- /dev/null +++ b/src/shaders/basic.vert @@ -0,0 +1,6 @@ +#version 330 core +layout (location = 0) in vec3 aPos; +void main() +{ + gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0); +} diff --git a/src/shaders/test.frag b/src/shaders/test.frag new file mode 100644 index 0000000..cd2ee4c --- /dev/null +++ b/src/shaders/test.frag @@ -0,0 +1,10 @@ +#version 330 core + +out vec4 FragColor; + +in vec4 vertexColor; + +void main() +{ + FragColor = vertexColor; +} diff --git a/src/shaders/test.vert b/src/shaders/test.vert new file mode 100644 index 0000000..851352d --- /dev/null +++ b/src/shaders/test.vert @@ -0,0 +1,19 @@ +#version 330 core + +layout (location = 0) in vec3 aPos; + +uniform mat4 projection; +uniform mat4 model; + +out vec4 vertexColor; + +void main() +{ + vec4 v = vec4(aPos, 1.0); + vec4 newPosition = model * v; + vec4 projectedPosition = projection * newPosition; + gl_Position = projectedPosition ; + +// gl_Position = u_mvp * vec4(aPos, 1.0); + vertexColor = vec4(0.0, 0.5, 0.0, 1.0); +} |
