diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/assets.h | 8 | ||||
| -rw-r--r-- | src/objects/material.h | 6 | ||||
| -rw-r--r-- | src/objects/model.h | 1 | ||||
| -rw-r--r-- | src/objects/pass.c | 12 | ||||
| -rw-r--r-- | src/objects/pass.h | 8 | ||||
| -rw-r--r-- | src/shader.c | 170 | ||||
| -rw-r--r-- | src/shader.h | 44 | ||||
| -rw-r--r-- | src/texture.h | 1 |
8 files changed, 242 insertions, 8 deletions
diff --git a/src/assets.h b/src/assets.h index cffb936..0a49bfe 100644 --- a/src/assets.h +++ b/src/assets.h @@ -48,12 +48,12 @@ typedef struct { // not thread-safe extern mri_asset_manager asset_manager; -#define asset_ptr(asset) &asset.data[asset.pos] -#define seek(asset, n) asset.pos += n +#define asset_ptr(asset) &(asset).data[(asset).pos] +#define seek(asset, n) (asset).pos += n #define read_value(asset, type) ({ \ type val = *((type *)(asset_ptr(asset))); \ - seek(asset, sizeof(type)); \ + seek((asset), sizeof(type)); \ val; \ }) @@ -63,7 +63,7 @@ extern mri_asset_manager asset_manager; .len = _n, \ .ptr = asset_ptr(asset) \ }; \ - seek(asset, _n); \ + seek((asset), _n); \ val; \ }) diff --git a/src/objects/material.h b/src/objects/material.h index 72b2d45..e7311c0 100644 --- a/src/objects/material.h +++ b/src/objects/material.h @@ -1,11 +1,13 @@ #ifndef _MATERIAL_H #define _MATERIAL_H +#include <jansson.h> + #include "pass.h" -typedef struct { +struct mri_material { mvec(mri_pass) passes; -} mri_material; +}; void mri_material_parse(mri_material *material, json_t *value); void mri_material_unload(mri_material *material); diff --git a/src/objects/model.h b/src/objects/model.h index e59b369..f1068d7 100644 --- a/src/objects/model.h +++ b/src/objects/model.h @@ -3,6 +3,7 @@ #include <jansson.h> +#include "pass.h" #include "material.h" typedef struct { diff --git a/src/objects/pass.c b/src/objects/pass.c index c90eb92..ba9de8c 100644 --- a/src/objects/pass.c +++ b/src/objects/pass.c @@ -1,10 +1,15 @@ #include "pass.h" +#include "material.h" #include "../json.h" #include "../texture.h" #include "../assets.h" void mri_pass_parse(mri_pass *pass, json_t *root) { + // TODO + pass->material = (mri_material *)malloc(sizeof(mri_material)); + mri_material_parse(pass->material, json_object_get(root, "material")); + json_t *texture; json_t *textures = json_object_get(root, "textures"); json_array(texture, textures) { @@ -13,7 +18,14 @@ void mri_pass_parse(mri_pass *pass, json_t *root) { mri_texture_unload(pass->textures[i]); } } + + json_t *shader = json_object_get(root, "shader"); + if (json_is_string(shader)) { + mri_shader_load(&pass->shader, json_string_value(shader)); + mri_shader_unload(&pass->shader); + } } void mri_pass_unload(mri_pass *pass) { + free(pass->material); } diff --git a/src/objects/pass.h b/src/objects/pass.h index aa8e2fb..ce34edd 100644 --- a/src/objects/pass.h +++ b/src/objects/pass.h @@ -3,11 +3,15 @@ #include <jansson.h> +#include "../shader.h" #include "../texture.h" +typedef struct mri_material mri_material; + typedef struct { - // mri_shader *shader; - // mri_material *material; + mri_material *material; + + mri_shader shader; mri_texture *textures[7]; // mvec(mri_uniform) uniforms; diff --git a/src/shader.c b/src/shader.c new file mode 100644 index 0000000..c2d7d1a --- /dev/null +++ b/src/shader.c @@ -0,0 +1,170 @@ +#include <string.h> +#include <stdlib.h> +#include <stdio.h> + +#include "shader.h" +#include "assets.h" +#include "log.h" + +static const char *gl_compat = + "#define highp\n" + "#define mediump\n" + "#define lowp\n" + "#define mul(x, y) (y * x)\n" + "#define frac fract\n" + "#define CAST2(x) (vec2(x))\n" + "#define CAST3(x) (vec3(x))\n" + "#define CAST4(x) (vec4(x))\n" + "#define CAST3X3(x) (mat3(x))\n" + "#define saturate(x) (clamp(x, 0.0, 1.0))\n" + "#define texSample2D texture2D\n" + "#define texSample2DLod texture2DLod\n" + "#define texture2DLod texture2D\n" + "#define atan2(y,x) atan(x,y)\n" + "#define ddx dFdx\n" + "#define ddy(x) dFdy(-(x))\n" + "#define GLSL 1\n\0"; + +static const char *version = "#version 120\n"; + +static char *build_shader_source(mri_shader *shader, char *buffer, bool first) { + size_t source_len = strlen(buffer) + strlen(gl_compat); + size_t source_index = 0; + + char *source = (char *)malloc(source_len); + source[source_index] = '\0'; + + if (first) { + source_index += strlen(gl_compat) + 1; + strncat(source, gl_compat, source_index); + } + + char *line = buffer; + + while (line) { + char *next_line = strchr(line, '\n'); + size_t len = next_line ? (size_t)(next_line - line) : strlen(line); + + if (memcmp(line, "#include", 8) == 0) { + char *open = strchr(line, '"') + 1; + char *close = strchr(open, '"') + 1; + + char *include = (char *)malloc(close - open); + snprintf(include, close - open, "%s", open); + + mri_asset *include_asset = mri_asset_manager_get(include, SHADER); + + if (include_asset->type == ASSET_VOID) { + return NULL; + } + + char *include_str = mri_str_to_c_str(read_string(*include_asset, include_asset->size)); + char *include_src = build_shader_source(shader, include_str, false); + + if (!include_src) { + return NULL; + } + + size_t include_len = strlen(include_src); + + if (!(source = realloc(source, source_len + include_len))) { + log_error("%s", "failed to allocate memory for shader source"); + abort(); // fatal + } + + strncat(source, include_src, include_len + 1); + source_index += include_len + 1; + + free(include); + free(include_src); + free(include_str); + } else if (memcmp(line, "uniform", 7) == 0) { + mri_uniform _u = {0}; + mvec_push(shader->uniforms, _u); + + mri_uniform *u = &mvec_last(shader->uniforms); + + char *type_start = strchr(line, ' ') + 1; + char *type_end = strchr(type_start, ' ') + 1; + + char *type = (char *)malloc(type_end - type_start); + snprintf(type, type_end - type_start, "%s", type_start); + + if (memcmp(type, "float", 5) == 0) u->type = TYPE_FLOAT; + else if (memcmp(type, "vec4", 4) == 0) u->type = TYPE_VEC4; + else if (memcmp(type, "vec3", 4) == 0) u->type = TYPE_VEC3; + else if (memcmp(type, "vec2", 4) == 0) u->type = TYPE_VEC2; + else if (memcmp(type, "sampler2D", 10) == 0) { + u->type = TYPE_SAMPLER2D; + } + + char *name_end = strchr(type_end, ';') + 1; + + u->uname = (char *)malloc(name_end - type_end); + snprintf(u->uname, name_end - type_end, "%s", type_end); + + char *combo_start = strchr(line, '/'); + + if (combo_start && combo_start - line < len) { + // parse combo + } + } else { + strncat(source, line, len + 1); + source_index += len + 1; + source[source_index] = '\0'; + } + + line = next_line ? next_line + 1 : NULL; + } + + return source; +} + +void mri_shader_load(mri_shader *shader, const char *name) { + mvec_init(shader->uniforms); + + mri_asset *vertex_asset = mri_asset_manager_get(name, VERTEX_SHADER); + if (vertex_asset->type != ASSET_VOID) { + char *vertex_str = mri_str_to_c_str(read_string(*vertex_asset, vertex_asset->size)); + shader->vertex_source = build_shader_source(shader, vertex_str, true); + + if (!shader->vertex_source) { + log_error("failed to parse shader (%s.vert)", name); + } + + free(vertex_str); + } else { + log_error("failed to load shader file (%s.vert)", name); + } + + mri_asset *fragment_asset = mri_asset_manager_get(name, FRAGMENT_SHADER); + if (fragment_asset->type != ASSET_VOID) { + char *fragment_str = mri_str_to_c_str(read_string(*fragment_asset, fragment_asset->size)); + shader->fragment_source = build_shader_source(shader, fragment_str, true); + + if (!shader->fragment_source) { + log_error("failed to parse shader (%s.frag)", name); + } + + free(fragment_str); + } else { + log_error("failed to load shader file (%s.frag)", name); + } +} + +void mri_shader_unload(mri_shader *shader) { + free(shader->vertex_source); + free(shader->fragment_source); + + mri_uniform *uniform; + mvec_loop_ptr(shader->uniforms, uniform) { + printf("%s\n", uniform->uname); + printf("%i\n", uniform->type); + free(uniform->uname); + } + + mvec_free(shader->uniforms); +} + + + diff --git a/src/shader.h b/src/shader.h new file mode 100644 index 0000000..a9548c3 --- /dev/null +++ b/src/shader.h @@ -0,0 +1,44 @@ +#ifndef _SHADER_H +#define _SHADER_H + +#include "texture.h" + +typedef enum { + TYPE_FLOAT, + TYPE_VEC4, + TYPE_VEC3, + TYPE_VEC2, + TYPE_MAT4, + TYPE_SAMPLER2D +} mri_uniform_type; + +typedef struct { + mri_uniform_type type; + const char *name; + const char *uname; + vec4 value; +} mri_uniform; + +typedef struct { + const char *name; + int value; +} mri_combo; + +typedef struct { + const char *name; + + char *vertex_source; + char *fragment_source; + + int texture_count; + + mri_texture *textures[7]; + + mvec(mri_combo) combos; + mvec(mri_uniform) uniforms; +} mri_shader; + +void mri_shader_load(mri_shader *shader, const char *name); +void mri_shader_unload(mri_shader *shader); + +#endif // _SHADER_H diff --git a/src/texture.h b/src/texture.h index a750ba6..58e3b67 100644 --- a/src/texture.h +++ b/src/texture.h @@ -1,6 +1,7 @@ #ifndef _TEXTURE_H #define _TEXTURE_H +#include <stdbool.h> #include <cglm/cglm.h> #include "assets.h" |