implemented basic renderer

This commit is contained in:
Lauchmelder 2022-10-16 23:43:22 +02:00
parent be1abc3762
commit 5ba261c72c
11 changed files with 295 additions and 2 deletions

View file

@ -9,6 +9,8 @@ add_executable(solver
"application.c"
"renderer/window.c"
"renderer/context.c"
"renderer/buffer.c"
"renderer/shader.c"
)
target_link_libraries(solver PRIVATE

View file

@ -7,6 +7,14 @@
#include "renderer/context.h"
static void destroy_application(Application* app)
{
assert(app);
destroy_vao(app->object);
destroy_window(app->window);
}
int init_application(Application* app, const char* name)
{
assert(app);
@ -17,6 +25,57 @@ int init_application(Application* app, const char* name)
return 1;
}
// Create quad for testing
create_vao(&app->object);
float vertices[] = {
-0.5f, -0.5f, 0.0f, 1.0f, 0.0f, 0.0f,
-0.5f, 0.5f, 0.0f, 0.0f, 1.0f, 0.0f,
0.5f, 0.5f, 0.0f, 0.0f, 0.0f, 1.0f,
0.5f, -0.5f, 0.0f, 0.0f, 0.0f, 0.0f
};
attach_vertex_buffer(&app->object, vertices, sizeof(vertices));
unsigned indices[] = {
0, 1, 2,
0, 2, 3
};
attach_element_buffer(&app->object, indices, sizeof(indices));
VertexAttribute layout[] = {
{ GL_FLOAT, 3, 3 * sizeof(float) },
{ GL_FLOAT, 3, 3 * sizeof(float) }
};
set_vertex_layout(&app->object, layout, sizeof(layout) / sizeof(VertexAttribute));
app->shader = create_shader(
"#version 460 core\n"
""
"layout (location = 0) in vec3 pos;"
"layout (location = 1) in vec3 col;"
""
"out vec3 i_col;"
""
"void main() {"
" i_col = col;"
" gl_Position = vec4(pos, 1.0);"
"}",
"#version 460 core\n"
""
"in vec3 i_col;"
"out vec4 FragColor;"
""
"void main() {"
" FragColor = vec4(i_col, 1.0);"
"}"
);
if(app->shader == 0)
{
destroy_application(app);
return 1;
}
return 0;
}
@ -27,6 +86,12 @@ int launch_application(Application* app)
glfwPollEvents();
ctx_clear_screen(0.3f, 0.1f, 0.8f, 1.0f);
bind_shader(app->shader);
ctx_draw_elements(&app->object);
glfwSwapBuffers(app->window);
}
destroy_application(app);
}

View file

@ -2,10 +2,15 @@
#define APPLICATION_H
#include "renderer/window.h"
#include "renderer/buffer.h"
#include "renderer/shader.h"
typedef struct Application
{
GLFWwindow* window;
VertexArrayObject object;
int shader;
} Application;
int init_application(Application* app, const char* name);

68
src/renderer/buffer.c Normal file
View file

@ -0,0 +1,68 @@
#include "buffer.h"
#include <assert.h>
#include <glad/glad.h>
void create_vao(VertexArrayObject* vao)
{
assert(vao);
glGenVertexArrays(1, &vao->vao);
}
void destroy_vao(VertexArrayObject vao)
{
glDeleteBuffers(1, &vao.ebo);
glDeleteBuffers(1, &vao.vbo);
glDeleteVertexArrays(1, &vao.vao);
}
void attach_vertex_buffer(VertexArrayObject* vao, const float* data, size_t size)
{
assert(vao);
glBindVertexArray(vao->vao);
glGenBuffers(1, &vao->vbo);
glBindBuffer(GL_ARRAY_BUFFER, vao->vbo);
glBufferData(GL_ARRAY_BUFFER, size, (const void*)data, GL_STATIC_DRAW);
}
void attach_element_buffer(VertexArrayObject* vao, const unsigned* data, size_t size)
{
assert(vao);
glBindVertexArray(vao->vao);
glGenBuffers(1, &vao->ebo);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vao->ebo);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, size, (const void*)data, GL_STATIC_DRAW);
vao->elements = size / sizeof(unsigned);
}
void set_vertex_layout(VertexArrayObject* vao, VertexAttribute* attributes, size_t count)
{
assert(vao);
assert(attributes);
glBindVertexArray(vao->vao);
size_t stride = 0;
for (size_t i = 0; i < count; i++) {
stride += attributes[i].size;
}
size_t offset = 0;
for (size_t i = 0; i < count; i++) {
glVertexAttribPointer(i, attributes[i].count, attributes[i].type, GL_FALSE, stride, (const void*)(offset));
glEnableVertexAttribArray(i);
offset += attributes[i].size;
}
}
void bind_vao(VertexArrayObject vao)
{
glBindVertexArray(vao.vao);
}

33
src/renderer/buffer.h Normal file
View file

@ -0,0 +1,33 @@
#ifndef BUFFER_H
#define BUFFER_H
#include <stdint.h>
typedef struct VertexArrayObject
{
int vao;
int vbo;
int ebo;
size_t elements;
} VertexArrayObject;
typedef struct VertexAttribute
{
int type;
int count;
size_t size;
} VertexAttribute;
void create_vao(VertexArrayObject* vao);
void destroy_vao(VertexArrayObject vao);
void attach_vertex_buffer(VertexArrayObject* vao, const float* data, size_t size);
void attach_element_buffer(VertexArrayObject* vao, const unsigned* data, size_t size);
void set_vertex_layout(VertexArrayObject* vao, VertexAttribute* attributes, size_t count);
void bind_vao(VertexArrayObject vao);
#endif // BUFFER_H

View file

@ -3,6 +3,8 @@
#include <glad/glad.h>
#include <GLFW/glfw3.h>
#include "buffer.h"
int ctx_init()
{
gladLoadGLLoader((GLADloadproc)glfwGetProcAddress);
@ -18,3 +20,9 @@ void ctx_clear_screen(float r, float g, float b, float a)
glClearColor(r, g, b, a);
glClear(GL_COLOR_BUFFER_BIT);
}
void ctx_draw_elements(VertexArrayObject* vao)
{
bind_vao(*vao);
glDrawElements(GL_TRIANGLES, vao->elements, GL_UNSIGNED_INT, (void*)0);
}

View file

@ -1,10 +1,13 @@
#ifndef CONTEXT_H
#define CONTEXT_H
typedef struct VertexArrayObject VertexArrayObject;
int ctx_init();
void ctx_viewport(int x, int y, int w, int h);
void ctx_clear_screen(float r, float g, float b, float a);
void ctx_draw_elements(VertexArrayObject* vao);
#endif // CONTEXT_H

94
src/renderer/shader.c Normal file
View file

@ -0,0 +1,94 @@
#include "shader.h"
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <assert.h>
#include <glad/glad.h>
static int set_and_compile_shader(GLuint program, GLuint shader, const char* code, char** error)
{
int result;
glShaderSource(shader, 1, &code, NULL);
glCompileShader(shader);
glGetShaderiv(shader, GL_COMPILE_STATUS, &result);
if (result == GL_FALSE)
{
*error = (char*)malloc(1024);
if (*error == NULL) {
fprintf(stderr, "(shader) memory allocation for error buffer failed\n");
return -ENOMEM;
}
glGetShaderInfoLog(shader, 1024, NULL, *error);
(*error)[1023] = NULL;
return 1;
}
glAttachShader(program, shader);
return 0;
}
int create_shader(const char* vertex_shader_code, const char* fragment_shader_code)
{
assert(vertex_shader_code && fragment_shader_code);
int shader = glCreateProgram();
char* error;
int vertex_shader = glCreateShader(GL_VERTEX_SHADER);
if (set_and_compile_shader(shader, vertex_shader, vertex_shader_code, &error) != 0)
{
fprintf(stderr, "vertex shader compilation failed: %s\n", error);
free(error);
glDeleteProgram(shader);
shader = 0;
goto vertex_failed;
}
int fragment_shader = glCreateShader(GL_FRAGMENT_SHADER);
if (set_and_compile_shader(shader, fragment_shader, fragment_shader_code, &error) != 0)
{
fprintf(stderr, "fragment shader compilation failed: %s\n", error);
free(error);
glDeleteProgram(shader);
shader = 0;
goto fragment_failed;
}
glLinkProgram(shader);
int result;
glGetProgramiv(shader, GL_LINK_STATUS, &result);
if (result == GL_FALSE)
{
char error[512];
glGetProgramInfoLog(shader, 512, NULL, error);
fprintf(stderr, "shader linking failed: %s\n", error);
glDeleteProgram(shader);
shader = 0;
}
fragment_failed:
glDeleteShader(fragment_shader);
vertex_failed:
glDeleteShader(vertex_shader);
return shader;
}
void destroy_shader(int shader)
{
glDeleteProgram(shader);
}
void bind_shader(int shader)
{
glUseProgram(shader);
}

9
src/renderer/shader.h Normal file
View file

@ -0,0 +1,9 @@
#ifndef SHADER_H
#define SHADER_H
int create_shader(const char* vertex_shader_code, const char* fragment_shader_code);
void destroy_shader(int shader);
void bind_shader(int shader);
#endif // SHADER_H

View file

@ -5,7 +5,7 @@
#include "context.h"
void default_framebuffer_size_callback(int vw, int vh)
void default_framebuffer_size_callback(GLFWwindow* window, int vw, int vh)
{
ctx_viewport(0, 0, vw, vh);
}
@ -27,4 +27,9 @@ GLFWwindow* create_managed_window(const char* title, int width, int height)
glfwSetFramebufferSizeCallback(window, default_framebuffer_size_callback);
return window;
}
}
void destroy_window(GLFWwindow* window)
{
glfwDestroyWindow(window);
}

View file

@ -4,5 +4,6 @@
typedef struct GLFWwindow GLFWwindow;
GLFWwindow* create_managed_window(const char* title, int width, int height);
void destroy_window(GLFWwindow* window);
#endif // WINDOW_H