Testing framework. Shader creation function. More dynstring functions
This commit is contained in:
@@ -1,19 +1,22 @@
|
||||
#include <errno.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "DynString.h"
|
||||
#include "log.h"
|
||||
|
||||
DynString DynString_alloc(const char* str, const size_t len) {
|
||||
DynString dstr = {
|
||||
.data = (char*) malloc(sizeof(char) * len),
|
||||
.len = len
|
||||
.data = (char*) malloc(sizeof(char) * len + 1),
|
||||
.len = len,
|
||||
.capacity = len
|
||||
};
|
||||
if (dstr.data == NULL) {
|
||||
LOG_FATAL("Ran out of memory");
|
||||
}
|
||||
dstr.data = memcpy(dstr.data, str, len);
|
||||
dstr.data[len] = '\0';
|
||||
|
||||
return dstr;
|
||||
}
|
||||
@@ -21,14 +24,20 @@ DynString DynString_alloc(const char* str, const size_t len) {
|
||||
void DynString_free(DynString* dstr) {
|
||||
if (dstr->data != NULL) {
|
||||
free(dstr->data);
|
||||
dstr->data = NULL;
|
||||
}
|
||||
dstr->len = 0;
|
||||
dstr->capacity = 0;
|
||||
}
|
||||
|
||||
bool DynString_is_null(const DynString* dstr) {
|
||||
return dstr->data == NULL;
|
||||
}
|
||||
|
||||
const char* DynString_c_str(const DynString* dstr) {
|
||||
return dstr->data;
|
||||
}
|
||||
|
||||
bool DynString_equal(const DynString* s1, const DynString* s2) {
|
||||
if (s1->len != s2->len) {
|
||||
return false;
|
||||
@@ -47,3 +56,41 @@ bool DynString_equal(const DynString* s1, const DynString* s2) {
|
||||
return true;
|
||||
}
|
||||
|
||||
void DynString_reserve(DynString* dstr, const size_t new_capacity) {
|
||||
if (dstr->capacity >= new_capacity) {
|
||||
return;
|
||||
}
|
||||
|
||||
errno = 0;
|
||||
dstr->data = realloc(dstr->data, new_capacity);
|
||||
if (errno != 0) {
|
||||
LOG_FATAL("Ran out of memory");
|
||||
}
|
||||
dstr->capacity = new_capacity;
|
||||
}
|
||||
|
||||
void DynString_concat_c_str(
|
||||
DynString* dstr,
|
||||
const char* str,
|
||||
const size_t str_len
|
||||
) {
|
||||
const size_t new_len = dstr->len + str_len;
|
||||
if (new_len > dstr->capacity) {
|
||||
DynString_reserve(dstr, new_len + 1);
|
||||
}
|
||||
|
||||
strncpy(dstr->data + dstr->len, str, str_len);
|
||||
dstr->data[new_len] = '\0';
|
||||
dstr->len = new_len;
|
||||
}
|
||||
|
||||
DynString DynString_alloc_concat_c_strs(
|
||||
const char* s1,
|
||||
const size_t s1_len,
|
||||
const char* s2,
|
||||
const size_t s2_len
|
||||
) {
|
||||
DynString dstr = DynString_alloc(s1, s1_len);
|
||||
DynString_concat_c_str(&dstr, s2, s2_len);
|
||||
return dstr;
|
||||
}
|
||||
|
||||
@@ -9,11 +9,24 @@
|
||||
typedef struct {
|
||||
char* data;
|
||||
size_t len;
|
||||
size_t capacity;
|
||||
} DynString;
|
||||
|
||||
DynString DynString_alloc(const char* str, const size_t len);
|
||||
void DynString_free(DynString* dstr);
|
||||
bool DynString_is_null(const DynString* dstr);
|
||||
const char* DynString_c_str(const DynString* dstr);
|
||||
bool DynString_equal(const DynString* s1, const DynString* s2);
|
||||
void DynString_concat_c_str(
|
||||
DynString* dstr,
|
||||
const char* str,
|
||||
const size_t str_len
|
||||
);
|
||||
DynString DynString_alloc_concat_c_strs(
|
||||
const char* s1,
|
||||
const size_t s1_len,
|
||||
const char* s2,
|
||||
const size_t s2_len
|
||||
);
|
||||
|
||||
#endif // DYN_STRING_H_
|
||||
|
||||
70
src/main.c
70
src/main.c
@@ -15,6 +15,7 @@
|
||||
#include "log.h"
|
||||
#include "pltf/gl_funcs.h"
|
||||
#include "pltf/pltf.h"
|
||||
#include "shader.h"
|
||||
|
||||
// int _main() {
|
||||
// return 0;
|
||||
@@ -396,69 +397,10 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR pCmdLine,
|
||||
|
||||
glBindVertexArray(0);
|
||||
|
||||
// clang-format off
|
||||
const char* vertex_shader_src =
|
||||
"#version 460 core\n"
|
||||
"layout (location = 0) in vec3 a_pos;\n"
|
||||
"void main() {\n"
|
||||
" gl_Position = vec4(a_pos, 1.0);\n"
|
||||
"}\n"
|
||||
;
|
||||
|
||||
const char* fragment_shader_src =
|
||||
"#version 460 core\n"
|
||||
"out vec4 frag_color;\n"
|
||||
"void main() {\n"
|
||||
" frag_color = vec4(0.0, 0.0, 0.0, 1.0);\n"
|
||||
"}\n"
|
||||
;
|
||||
// clang-format on
|
||||
|
||||
const unsigned int vert_shader = glCreateShader(GL_VERTEX_SHADER);
|
||||
{
|
||||
const int len = strlen(vertex_shader_src);
|
||||
glShaderSource(vert_shader, 1, &vertex_shader_src, &len);
|
||||
glCompileShader(vert_shader);
|
||||
int compile_status = 0;
|
||||
glGetShaderiv(vert_shader, GL_COMPILE_STATUS, &compile_status);
|
||||
if (compile_status != GL_TRUE) {
|
||||
int info_log_len = 0;
|
||||
glGetShaderiv(vert_shader, GL_INFO_LOG_LENGTH, &info_log_len);
|
||||
char* err_str = (char*) malloc(sizeof(char) * info_log_len);
|
||||
glGetShaderInfoLog(vert_shader, info_log_len - 1, NULL, err_str);
|
||||
LOG_FATALF("Failed to compile vertex shader: %s", err_str);
|
||||
}
|
||||
}
|
||||
const unsigned int frag_shader = glCreateShader(GL_FRAGMENT_SHADER);
|
||||
{
|
||||
const int len = strlen(fragment_shader_src);
|
||||
glShaderSource(frag_shader, 1, &fragment_shader_src, &len);
|
||||
glCompileShader(frag_shader);
|
||||
int compile_status = 0;
|
||||
glGetShaderiv(frag_shader, GL_COMPILE_STATUS, &compile_status);
|
||||
if (compile_status != GL_TRUE) {
|
||||
int info_log_len = 0;
|
||||
glGetShaderiv(frag_shader, GL_INFO_LOG_LENGTH, &info_log_len);
|
||||
char* err_str = (char*) malloc(sizeof(char) * info_log_len);
|
||||
glGetShaderInfoLog(frag_shader, info_log_len - 1, NULL, err_str);
|
||||
LOG_FATALF("Failed to compile fragment shader: %s", err_str);
|
||||
}
|
||||
}
|
||||
|
||||
const unsigned int shader_program = glCreateProgram();
|
||||
{
|
||||
|
||||
glAttachShader(shader_program, vert_shader);
|
||||
glAttachShader(shader_program, frag_shader);
|
||||
glLinkProgram(shader_program);
|
||||
int compile_status = 0;
|
||||
glGetProgramiv(shader_program, GL_LINK_STATUS, &compile_status);
|
||||
if (compile_status != GL_TRUE) {
|
||||
LOG_FATAL("Failed to link shader program.");
|
||||
}
|
||||
glDeleteShader(vert_shader);
|
||||
glDeleteShader(frag_shader);
|
||||
}
|
||||
const unsigned int shader = shader_create(
|
||||
"shader.vert",
|
||||
"shader.frag"
|
||||
);
|
||||
|
||||
MSG msg = { 0 };
|
||||
while (true) {
|
||||
@@ -472,7 +414,7 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR pCmdLine,
|
||||
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
|
||||
glUseProgram(shader_program);
|
||||
glUseProgram(shader);
|
||||
glBindVertexArray(triangle_vao);
|
||||
glDrawArrays(GL_TRIANGLE_STRIP, 0, triangle_vert_count);
|
||||
|
||||
|
||||
88
src/shader.c
Normal file
88
src/shader.c
Normal file
@@ -0,0 +1,88 @@
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "DynString.h"
|
||||
#include "pltf/gl_funcs.h"
|
||||
#include "log.h"
|
||||
|
||||
static char read_buf[512] = { 0 };
|
||||
static const size_t read_buf_len = sizeof(read_buf) / sizeof(read_buf[0]);
|
||||
|
||||
static DynString read_shader_source(const char* path) {
|
||||
const DynString full_path = DynString_alloc_concat_c_strs(
|
||||
SHADERS_PATH,
|
||||
strlen(SHADERS_PATH),
|
||||
path,
|
||||
strlen(path)
|
||||
);
|
||||
|
||||
DynString source = DynString_alloc("", 0);
|
||||
|
||||
FILE* shader_file = fopen(DynString_c_str(&full_path), "r");
|
||||
if (shader_file == NULL) {
|
||||
LOG_ERRORF("Failed to open file %.*s. Errno: %d", DYN_STRING_FMT(full_path), errno);
|
||||
return source;
|
||||
}
|
||||
|
||||
size_t bytes_read = 0;
|
||||
do {
|
||||
bytes_read = fread(read_buf, 1, read_buf_len - 1, shader_file);
|
||||
read_buf[bytes_read] = '\0';
|
||||
DynString_concat_c_str(&source, read_buf, bytes_read);
|
||||
} while (bytes_read == read_buf_len - 1);
|
||||
|
||||
if (fclose(shader_file) == EOF) {
|
||||
LOG_ERRORF("Failed to close file %s. Errno: %d", path, errno);
|
||||
}
|
||||
|
||||
return source;
|
||||
}
|
||||
|
||||
static unsigned int compile_shader(const DynString* shader_src, const GLenum shader_type) {
|
||||
const unsigned int shader = glCreateShader(shader_type);
|
||||
const char* shader_src_c_str = DynString_c_str(shader_src);
|
||||
const int len = (int) shader_src->len;
|
||||
glShaderSource(shader, 1, &shader_src_c_str, &len);
|
||||
glCompileShader(shader);
|
||||
int compile_status = 0;
|
||||
glGetShaderiv(shader, GL_COMPILE_STATUS, &compile_status);
|
||||
if (compile_status != GL_TRUE) {
|
||||
int info_log_len = 0;
|
||||
glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &info_log_len);
|
||||
char* err_str = (char*) malloc(sizeof(char) * info_log_len);
|
||||
glGetShaderInfoLog(shader, info_log_len - 1, NULL, err_str);
|
||||
LOG_FATALF("Failed to compile vertex shader: %s", err_str);
|
||||
}
|
||||
|
||||
return shader;
|
||||
}
|
||||
|
||||
unsigned int shader_create(
|
||||
const char* vertex_shader_path,
|
||||
const char* fragment_shader_path
|
||||
) {
|
||||
DynString vert_source = read_shader_source(vertex_shader_path);
|
||||
DynString frag_source = read_shader_source(fragment_shader_path);
|
||||
|
||||
const unsigned int vert_shader = compile_shader(&vert_source, GL_VERTEX_SHADER);
|
||||
const unsigned int frag_shader = compile_shader(&frag_source, GL_FRAGMENT_SHADER);
|
||||
|
||||
DynString_free(&vert_source);
|
||||
DynString_free(&frag_source);
|
||||
|
||||
const unsigned int shader_program = glCreateProgram();
|
||||
glAttachShader(shader_program, vert_shader);
|
||||
glAttachShader(shader_program, frag_shader);
|
||||
glLinkProgram(shader_program);
|
||||
int compile_status = 0;
|
||||
glGetProgramiv(shader_program, GL_LINK_STATUS, &compile_status);
|
||||
if (compile_status != GL_TRUE) {
|
||||
LOG_FATAL("Failed to link shader program.");
|
||||
}
|
||||
|
||||
glDeleteShader(vert_shader);
|
||||
glDeleteShader(frag_shader);
|
||||
|
||||
return shader_program;
|
||||
}
|
||||
9
src/shader.h
Normal file
9
src/shader.h
Normal file
@@ -0,0 +1,9 @@
|
||||
#ifndef SHADER_H_
|
||||
#define SHADER_H_
|
||||
|
||||
unsigned int shader_create(
|
||||
const char* vertex_shader_path,
|
||||
const char* fragment_shader_path
|
||||
);
|
||||
|
||||
#endif // SHADER_H_
|
||||
7
src/shaders/shader.frag
Normal file
7
src/shaders/shader.frag
Normal file
@@ -0,0 +1,7 @@
|
||||
#version 460 core
|
||||
|
||||
out vec4 frag_color;
|
||||
|
||||
void main() {
|
||||
frag_color = vec4(0.0, 0.0, 0.0, 1.0);
|
||||
}
|
||||
7
src/shaders/shader.vert
Normal file
7
src/shaders/shader.vert
Normal file
@@ -0,0 +1,7 @@
|
||||
#version 460 core
|
||||
|
||||
layout (location = 0) in vec3 a_pos;
|
||||
|
||||
void main() {
|
||||
gl_Position = vec4(a_pos, 1.0);
|
||||
}
|
||||
Reference in New Issue
Block a user