implemented basic renderer
This commit is contained in:
parent
be1abc3762
commit
5ba261c72c
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
|
@ -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
68
src/renderer/buffer.c
Normal 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
33
src/renderer/buffer.h
Normal 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
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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
94
src/renderer/shader.c
Normal 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
9
src/renderer/shader.h
Normal 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
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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
|
Loading…
Reference in a new issue