summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--prge.h19
-rw-r--r--prge_camera.c103
-rw-r--r--prge_camera.h12
-rw-r--r--prge_gui.c43
-rw-r--r--prge_gui.h7
-rw-r--r--prge_input.c21
-rw-r--r--prge_mesh.c65
-rw-r--r--prge_mesh.h9
-rw-r--r--prge_model.c212
-rw-r--r--prge_model.h18
-rw-r--r--prge_shader.c83
-rw-r--r--prge_shader.h15
-rw-r--r--prge_texture.c69
-rw-r--r--prge_texture.h6
-rw-r--r--prge_types.h128
-rw-r--r--prge_window.c10
-rw-r--r--prge_window.h6
17 files changed, 684 insertions, 142 deletions
diff --git a/prge.h b/prge.h
index 066f1f5..3629d8b 100644
--- a/prge.h
+++ b/prge.h
@@ -5,13 +5,28 @@
#include "prge_types.h"
+#include "prge_window.h"
+#include "prge_window.c"
+
#include "prge_input.h"
#include "prge_input.c"
+#define STB_IMAGE_IMPLEMENTATION
+#include "stb_image.h"
+
+#include "prge_texture.h"
+#include "prge_texture.c"
+
#include "prge_shader.h"
#include "prge_shader.c"
-#include "prge_mesh.h"
-#include "prge_mesh.c"
+#include "prge_model.h"
+#include "prge_model.c"
+
+#include "prge_camera.h"
+#include "prge_camera.c"
+
+#include "prge_gui.h"
+#include "prge_gui.c"
#endif /* PRGE_H */
diff --git a/prge_camera.c b/prge_camera.c
new file mode 100644
index 0000000..242b33d
--- /dev/null
+++ b/prge_camera.c
@@ -0,0 +1,103 @@
+Camera camera_init(V3 pos, F32 fov, F32 near, F32 far,
+ F32 yaw, F32 pitch, F32 roll)
+{
+ Camera c;
+
+ c.pos = pos;
+ c.fov = fov;
+ c.near = near;
+ c.far = far;
+ c.yaw = yaw;
+ c.pitch = pitch;
+ c.roll = roll;
+
+ return c;
+}
+
+MAT4 camera_get_view_matrix_first_person(Camera *c)
+{
+ MAT4 v;
+
+ v = mat4transl(MAT4_IDENTITY, v3inv(c->pos));
+ v = mat4rotate(v, v3(c->pitch, c->yaw, c->roll));
+
+ return v;
+}
+
+void camera_get_vectors_first_person(Camera *c, V3 *r, V3 *u, V3 *f)
+{
+ F32 angle, cp, sp, cy, sy, cr, sr;
+
+ angle = DEG2RAD*c->pitch;
+ cp = f32cos(angle);
+ sp = f32sin(angle);
+ angle = DEG2RAD*c->yaw;
+ cy = f32cos(angle);
+ sy = f32sin(angle);
+ angle = DEG2RAD*c->roll;
+ cr = f32cos(angle);
+ sr = f32sin(angle);
+
+ *r = v3(cy*cr, -cy*sr, sy);
+ *u = v3(sp*sy*cr+cp*sr, -sp*sy*sr+cp*cr, -sp*cy);
+ *f = v3(-cp*sy*cr+sp*sr, cp*sy*sr+sp*cr, cp*cy);
+}
+
+MAT4 camera_look_at(Camera c, V3 t, V3 wup)
+{
+ V3 f, r, u;
+ MAT4 transl, rotate, res;
+
+ f = v3norm(v3sub(c.pos, t));
+ r = v3norm(v3cross(wup, f));
+ u = v3cross(f, r);
+
+ transl = mat4transl(MAT4_IDENTITY, v3inv(c.pos));
+ rotate = mat4transp(mat4_change_basis(r, u, f));
+ res = mat4mul(rotate, transl);
+
+ return res;
+}
+
+MAT4 ortho(F32 l, F32 r, F32 b, F32 t, F32 n, F32 f)
+{
+ MAT4 res;
+
+ res = MAT4_IDENTITY;
+ res.m0.x = 2.0f/(r-l);
+ res.m1.y = 2.0f/(t-b);
+ res.m2.z = -2.0f/(f-n);
+ res.m3.x = -(r+l)/(r-l);
+ res.m3.y = -(t+b)/(t-b);
+ res.m3.z = -(f+n)/(f-n);
+
+ return res;
+}
+
+MAT4 persp(F32 fov, F32 ar, F32 n, F32 f)
+{
+ F32 r, t;
+ MAT4 res;
+
+ r = n*f32tan(fov/2.0f*DEG2RAD);
+ t = r/ar;
+
+ res = MAT4_IDENTITY;
+ res.m0.x = n/r;
+ res.m1.y = n/t;
+ res.m2.z = -(f+n)/(f-n);
+ res.m2.w = -1.0f;
+ res.m3.z = (-2.0f*f*n)/(f-n);
+ res.m3.w = 0.0f;
+
+ return res;
+}
+
+MAT4 camera_persp(Camera c, F32 ar)
+{
+ MAT4 res;
+
+ res = persp(c.fov, ar, c.near, c.far);
+
+ return res;
+}
diff --git a/prge_camera.h b/prge_camera.h
new file mode 100644
index 0000000..33957e5
--- /dev/null
+++ b/prge_camera.h
@@ -0,0 +1,12 @@
+#ifndef PRGE_CAMERA_H
+#define PRGE_CAMERA_H
+
+Camera camera_init(V3 pos, F32 fov, F32 near, F32 far, F32 yaw, F32 pitch, F32 roll);
+MAT4 camera_get_view_matrix_first_person(Camera *c);
+void camera_get_vectors_first_person(Camera *c, V3 *l, V3 *u, V3 *f);
+MAT4 camera_look_at(Camera c, V3 t, V3 wup);
+MAT4 ortho(F32 l, F32 r, F32 b, F32 t, F32 n, F32 f);
+MAT4 persp(F32 fov, F32 ar, F32 n, F32 f);
+MAT4 camera_persp(Camera c, F32 ar);
+
+#endif /* PRGE_CAMERA_H */
diff --git a/prge_gui.c b/prge_gui.c
new file mode 100644
index 0000000..f1d03d7
--- /dev/null
+++ b/prge_gui.c
@@ -0,0 +1,43 @@
+B32 in_rect(V2 pos, V2 start, V2 end)
+{
+ B32 res;
+ res = ((pos.x > start.x) && (pos.x < end.x) &&
+ (pos.y > start.y) && (pos.y < end.y));
+ return res;
+}
+
+B32 button(Window *wnd, U32 shader, Input *input, Arena *arena,
+ Str8 name, V2 center, F32 w, F32 h)
+{
+ B32 res;
+ Mesh *quad;
+ V2 start, end;
+ MAT4 model;
+ Str8 info;
+
+ res = 0;
+
+ quad = mesh_gen_quad(arena, v3fromv2(center), V3_ZERO, w, h);
+
+ shader_set_4fv(shader, "color", v4(1.0f, 0.0f, 0.0f, 1.0f));
+
+ start = v2(center.x-w/2.0f, center.y-h/2.0f);
+ end = v2(center.x+w/2.0f, center.y+h/2.0f);
+ if (in_rect(input->mouse_pos, start, end) &&
+ !input->capture_mouse)
+ {
+ shader_set_4fv(shader, "color", v4(0.0f, 0.0f, 1.0f, 1.0f));
+ if (key_first_press(input->mouse_left))
+ res = 1;
+ }
+
+ model = mat4transl(MAT4_IDENTITY, v3(center.x, wnd->height-center.y, 0.0f));
+
+ shader_set_mat4fv(shader, "model", model);
+
+ mesh_draw(quad);
+
+ mesh_clear(quad);
+
+ return res;
+}
diff --git a/prge_gui.h b/prge_gui.h
new file mode 100644
index 0000000..72fc11a
--- /dev/null
+++ b/prge_gui.h
@@ -0,0 +1,7 @@
+#ifndef PRGE_GUI_H
+#define PRGE_GUI_H
+
+B32 in_rect(V2 pos, V2 start, V2 end);
+B32 button(Window *wnd, U32 shader, Input *input, Arena *arena, Str8 name, V2 center, F32 w, F32 h);
+
+#endif /* PRGE_GUI_H */
diff --git a/prge_input.c b/prge_input.c
index e295ebc..b841d6a 100644
--- a/prge_input.c
+++ b/prge_input.c
@@ -3,12 +3,15 @@ Input input_init()
Input input = {0};
input.first_mouse = 1;
input.is_running = 1;
- return(input);
+ return input;
}
void input_update(Input *input)
{
+ input->last_mouse_pos = input->mouse_pos;
input->mouse_offset = V2_ZERO;
+ input->mouse_left.last = input->mouse_left.state;
+ input->mouse_right.last = input->mouse_right.state;
input->move_right.last = input->move_right.state;
input->move_forward.last = input->move_forward.state;
@@ -26,20 +29,20 @@ void input_update(Input *input)
B32 key_is_pressed(Key key)
{
- B32 result = (key.state == KeyState_PRESS);
- return(result);
+ B32 r = (key.state == KeyState_PRESS);
+ return r;
}
B32 key_first_press(Key key)
{
- B32 result = ((key.last == KeyState_RELEASE) &&
- (key.state == KeyState_PRESS));
- return(result);
+ B32 r = ((key.last == KeyState_RELEASE) &&
+ (key.state == KeyState_PRESS));
+ return r;
}
B32 key_was_pressed(Key key)
{
- B32 result = ((key.last == KeyState_PRESS) &&
- (key.state == KeyState_RELEASE));
- return(result);
+ B32 r = ((key.last == KeyState_PRESS) &&
+ (key.state == KeyState_RELEASE));
+ return r;
}
diff --git a/prge_mesh.c b/prge_mesh.c
deleted file mode 100644
index dc2c2da..0000000
--- a/prge_mesh.c
+++ /dev/null
@@ -1,65 +0,0 @@
-Vertex vertex(V3 pos)
-{
- Vertex v = { pos };
- return v;
-}
-
-void mesh_init_buffers(Mesh *mesh)
-{
- Assert(mesh->verts);
- Assert(mesh->nverts > 0);
-
- glGenVertexArrays(1, &mesh->vao);
- glBindVertexArray(mesh->vao);
-
- glGenBuffers(1, &mesh->vbo);
- glBindBuffer(GL_ARRAY_BUFFER, mesh->vbo);
- glBufferData(GL_ARRAY_BUFFER, mesh->nverts*sizeof(Vertex), mesh->verts, GL_STATIC_DRAW);
-
- if (mesh->indices && (mesh->nindices > 0)) {
- glGenBuffers(1, &mesh->ebo);
- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mesh->ebo);
- glBufferData(GL_ELEMENT_ARRAY_BUFFER, mesh->nindices*sizeof(U32), mesh->indices, GL_STATIC_DRAW);
- }
-
- glEnableVertexAttribArray(PRGE_SHADER_POS_LOC);
- glVertexAttribPointer(PRGE_SHADER_POS_LOC, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), 0);
- glBindVertexArray(0);
-}
-
-Mesh *mesh(Arena *arena, Vertex *verts, U32 nverts, U32 *indices, U32 nindices)
-{
- Mesh *mesh = arena_push(arena, sizeof(Mesh));
- mesh->verts = verts;
- mesh->nverts = nverts;
- mesh->indices = indices;
- mesh->nindices = nindices;
- mesh_init_buffers(mesh);
- return mesh;
-}
-
-void mesh_clear(Mesh *mesh)
-{
- glBindVertexArray(mesh->vao);
- glDisableVertexAttribArray(PRGE_SHADER_POS_LOC);
-
- glBindVertexArray(0);
- glDeleteVertexArrays(1, &mesh->vao);
-
- glBindBuffer(GL_ARRAY_BUFFER, 0);
- glDeleteBuffers(1, &mesh->vbo);
-
- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
- glDeleteBuffers(1, &mesh->ebo);
-}
-
-void mesh_draw(Mesh mesh)
-{
- Assert(mesh.vao);
- glBindVertexArray(mesh.vao);
- if (mesh.ebo)
- glDrawElements(GL_TRIANGLES, mesh.nindices, GL_UNSIGNED_INT, 0);
- else
- glDrawArrays(GL_TRIANGLES, 0, mesh.nverts);
- glBindVertexArray(0);
-}
diff --git a/prge_mesh.h b/prge_mesh.h
deleted file mode 100644
index 1f70809..0000000
--- a/prge_mesh.h
+++ /dev/null
@@ -1,9 +0,0 @@
-#ifndef PRGE_MESH_H
-#define PRGE_MESH_H
-
-#define PRGE_SHADER_POS_LOC 0
-
-Vertex vertex(V3 pos);
-Mesh *mesh(Arena *arena, Vertex *verts, U32 nverts, U32 *indices, U32 nindices);
-
-#endif /* PRGE_MESH_H */
diff --git a/prge_model.c b/prge_model.c
new file mode 100644
index 0000000..44ded76
--- /dev/null
+++ b/prge_model.c
@@ -0,0 +1,212 @@
+Vertex vert(V3 pos, V2 texc)
+{
+ Vertex v;
+
+ v.pos = pos;
+ v.texc = texc;
+
+ return v;
+}
+
+void mesh_init_buffers(Mesh *mesh)
+{
+ Assert(mesh->verts);
+ Assert(mesh->nverts > 0);
+
+ glGenVertexArrays(1, &mesh->vao);
+ glBindVertexArray(mesh->vao);
+
+ glGenBuffers(1, &mesh->vbo);
+ glBindBuffer(GL_ARRAY_BUFFER, mesh->vbo);
+ glBufferData(GL_ARRAY_BUFFER, mesh->nverts*sizeof(Vertex), mesh->verts, GL_STATIC_DRAW);
+
+ if (mesh->indices && (mesh->nindices > 0)) {
+ glGenBuffers(1, &mesh->ebo);
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mesh->ebo);
+ glBufferData(GL_ELEMENT_ARRAY_BUFFER, mesh->nindices*sizeof(U32), mesh->indices, GL_STATIC_DRAW);
+ }
+
+ glEnableVertexAttribArray(PRGE_SHADER_POS_LOC);
+ glVertexAttribPointer(PRGE_SHADER_POS_LOC, 3, GL_FLOAT, GL_FALSE,
+ sizeof(Vertex), OffsetOfMember(Vertex, pos));
+ glEnableVertexAttribArray(PRGE_SHADER_TEXC_LOC);
+ glVertexAttribPointer(PRGE_SHADER_TEXC_LOC, 2, GL_FLOAT, GL_FALSE,
+ sizeof(Vertex), (void *)OffsetOfMember(Vertex, texc));
+ glBindVertexArray(0);
+}
+
+Mesh *mesh_init(Arena *arena, V3 origin, V3 rotate, Vertex *verts, U32 nverts, U32 *indices, U32 nindices)
+{
+ Mesh *mesh;
+
+ mesh = arena_push(arena, sizeof(Mesh));
+
+ mesh->origin = origin;
+ mesh->rotate = rotate;
+
+ mesh->verts = verts;
+ mesh->nverts = nverts;
+
+ mesh->indices = indices;
+ mesh->nindices = nindices;
+
+ mesh->ntextures = 0;
+ MemoryZeroArray(mesh->textures);
+
+ mesh_init_buffers(mesh);
+
+ return mesh;
+}
+
+void mesh_add_texture(Mesh *mesh, Texture texture)
+{
+ Assert(mesh->ntextures+1 <= MAX_TEXTURE);
+ mesh->textures[mesh->ntextures++] = texture;
+}
+
+void mesh_clear(Mesh *mesh)
+{
+ glBindVertexArray(mesh->vao);
+ glDisableVertexAttribArray(PRGE_SHADER_POS_LOC);
+
+ glBindVertexArray(0);
+ glDeleteVertexArrays(1, &mesh->vao);
+
+ glBindBuffer(GL_ARRAY_BUFFER, 0);
+ glDeleteBuffers(1, &mesh->vbo);
+
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
+ glDeleteBuffers(1, &mesh->ebo);
+}
+
+void mesh_draw(Mesh *mesh)
+{
+ S32 i;
+
+ Assert(mesh->vao);
+
+ glBindVertexArray(mesh->vao);
+
+ for (i = 0; i < mesh->ntextures; i++) {
+ glActiveTexture(GL_TEXTURE0+i);
+ glBindTexture(GL_TEXTURE_2D, mesh->textures[i].id);
+ }
+
+ if (mesh->ebo)
+ glDrawElements(GL_TRIANGLES, mesh->nindices, GL_UNSIGNED_INT, 0);
+ else
+ glDrawArrays(GL_TRIANGLES, 0, mesh->nverts);
+
+ glBindVertexArray(0);
+}
+
+Mesh *mesh_gen_quad(Arena *arena, V3 origin, V3 rotate, F32 w, F32 h)
+{
+ Mesh *m;
+ Vertex *verts;
+ U32 *indices;
+ U32 nverts, nindices;
+
+ nverts = 4;
+ verts = arena_push(arena, nverts*sizeof(Vertex));
+ verts[0] = vert(v3(-w/2.0f, -h/2.0f, 0.0f), v2(0.0f, 0.0f));
+ verts[1] = vert(v3(-w/2.0f, h/2.0f, 0.0f), v2(0.0f, 1.0f));
+ verts[2] = vert(v3(w/2.0f, -h/2.0f, 0.0f), v2(1.0f, 0.0f));
+ verts[3] = vert(v3(w/2.0f, h/2.0f, 0.0f), v2(1.0f, 1.0f));
+
+ nindices = 6;
+ indices = arena_push(arena, nindices*sizeof(U32));
+ indices[0] = 0;
+ indices[1] = 1;
+ indices[2] = 3;
+ indices[3] = 0;
+ indices[4] = 2;
+ indices[5] = 3;
+
+ m = mesh_init(arena, origin, rotate, verts, nverts, indices, nindices);
+
+ return m;
+}
+
+Mesh *mesh_gen_circle(Arena *arena, V3 origin, V3 rotate, F32 r, U32 nverts)
+{
+ Mesh *m;
+ Vertex *verts;
+ U32 *indices;
+ U32 nindices;
+ F32 angle, dangle;
+ U32 i, vi;
+
+ if (nverts < 3)
+ nverts = 3;
+
+ verts = arena_push(arena, nverts*sizeof(Vertex));
+
+ dangle = 2*F32_PI/(F32)nverts;
+ for (i = 0, angle = 0.0f; i < nverts; i++, angle += dangle)
+ verts[i] = vert(v3(f32cos(angle)*r, f32sin(angle)*r, 0.0f), V2_ZERO);
+
+ nindices = nverts*3;
+ indices = arena_push(arena, nindices*sizeof(U32));
+ for (i = 0, vi = 1; i < nindices; i += 3, vi++) {
+ indices[i] = 0;
+ indices[i+1] = vi;
+ indices[i+2] = (((vi+1) == (nverts)) ? 1 : (vi+1));
+ }
+
+ m = mesh_init(arena, origin, rotate, verts, nverts, indices, nindices);
+
+ return m;
+}
+
+Model *model_init(Arena *arena, V3 origin, V3 rotate, Mesh *meshes, U32 nmeshes)
+{
+ Model *res;
+
+ res = arena_push(arena, sizeof(Model));
+
+ res->origin = origin;
+ res->rotate = rotate;
+ res->meshes = meshes;
+ res->nmeshes = nmeshes;
+
+ return res;
+}
+
+Model *model_load(Arena *arena, V3 origin, V3 rotate, Str8 filename)
+{
+ Model *res;
+
+ res = 0;
+
+ /* TODO(pryazha): Load models with assimp? */
+
+ return res;
+}
+
+void model_draw(U32 shader, MAT4 *proj, MAT4 *view, Model *model)
+{
+ U32 i;
+ MAT4 modelmat, meshmodelmat, resmodelmat;
+ V3 resorigin, resrotate;
+
+ glUseProgram(shader);
+
+ shader_set_mat4fv(shader, PRGE_SHADER_PROJ_MAT, *proj);
+ shader_set_mat4fv(shader, PRGE_SHADER_VIEW_MAT, *view);
+
+ modelmat = mat4rotate(MAT4_IDENTITY, model->rotate);
+ modelmat = mat4transl(modelmat, model->origin);
+
+ for (i = 0; i < model->nmeshes; i++) {
+ meshmodelmat = mat4rotate(MAT4_IDENTITY, model->meshes[i].rotate);
+ meshmodelmat = mat4transl(meshmodelmat, model->meshes[i].origin);
+
+ resmodelmat = mat4mul(modelmat, meshmodelmat);
+
+ shader_set_mat4fv(shader, PRGE_SHADER_MODEL_MAT, resmodelmat);
+ mesh_draw(&model->meshes[i]);
+ }
+
+ glUseProgram(0);
+}
diff --git a/prge_model.h b/prge_model.h
new file mode 100644
index 0000000..d747232
--- /dev/null
+++ b/prge_model.h
@@ -0,0 +1,18 @@
+#ifndef PRGE_MODEL_H
+#define PRGE_MODEL_H
+
+#define MAX_TEXTURE 5
+
+Vertex vert_init(V3 pos, V2 texc);
+
+Mesh *mesh_init(Arena *arena, V3 origin, V3 rotate, Vertex *verts, U32 nverts, U32 *indices, U32 nindices);
+void mesh_add_texture(Mesh *mesh, Texture texture);
+Mesh *mesh_gen_quad(Arena *arena, V3 origin, V3 rotate, F32 w, F32 h);
+Mesh *mesh_gen_circle(Arena *arena, V3 origin, V3 rotate, F32 r, U32 nverts);
+void mesh_draw(Mesh *mesh);
+
+Model *model_init(Arena *arena, V3 origin, V3 rotate, Mesh *meshes, U32 nmeshes);
+Model *model_load(Arena *arena, V3 origin, V3 rotate, Str8 filename);
+void model_draw(U32 shader, MAT4 *proj, MAT4 *view, Model *model);
+
+#endif /* PRGE_MODEL_H */
diff --git a/prge_shader.c b/prge_shader.c
index 21a91f3..96b50f1 100644
--- a/prge_shader.c
+++ b/prge_shader.c
@@ -1,28 +1,33 @@
U32 compile_shader(GLenum type, Str8 filename)
{
- Arena *tmp = arena_alloc(0);
+ Arena *tmp;
+ Str8 src;
+ U32 id;
+ S32 status;
+ const char *csrc;
- Str8 src = str8_read_entire_file(tmp, filename);
+ tmp = arena_alloc(0);
+
+ src = str8_read_entire_file(tmp, filename);
if (!src.ptr || !src.length) {
- str8print(str8_pushf(tmp, "[ERROR] : Failed to read \"%.*s\"\n", str8expand(filename)));
+ str8print(str8pushf(tmp, "[ERROR] : Failed to read \"%.*s\"\n", str8expand(filename)));
arena_release(tmp);
return 0;
}
- const char *csrc = str8_to_cstr(tmp, src);
+ csrc = str8tocstr(tmp, src);
- U32 id = glCreateShader(type);
+ id = glCreateShader(type);
glShaderSource(id, 1, &csrc, 0);
glCompileShader(id);
- S32 status;
glGetShaderiv(id, GL_COMPILE_STATUS, &status);
if (status == GL_FALSE) {
- char log[512];
+ char log[512];
glGetShaderInfoLog(id, 512, 0, log);
- str8print(str8_pushf(tmp, "[ERROR] : Failed to compile : \"%.*s\"\n%s", str8expand(filename), log));
+ str8print(str8pushf(tmp, "[ERROR] : Failed to compile : \"%.*s\"\n%s", str8expand(filename), log));
} else {
- str8print(str8_pushf(tmp, "[INFO] : \"%.*s\" compiled successfully.\n", str8expand(filename)));
+ str8print(str8pushf(tmp, "[INFO] : \"%.*s\" compiled successfully.\n", str8expand(filename)));
}
arena_release(tmp);
@@ -30,36 +35,66 @@ U32 compile_shader(GLenum type, Str8 filename)
return id;
}
-U32 create_shader_program(Str8 vert_filename, Str8 frag_filename)
+U32 load_shader(char *vert_filename, char *geom_filename, char *frag_filename)
{
- U32 vert = compile_shader(GL_VERTEX_SHADER, vert_filename);
- U32 frag = compile_shader(GL_FRAGMENT_SHADER, frag_filename);
+ U32 vert, geom, frag, id;
+ Arena *tmp;
+ S32 success;
+
+ if (vert_filename)
+ vert = compile_shader(GL_VERTEX_SHADER, str8fromcstr(vert_filename));
+ if (geom_filename)
+ geom = compile_shader(GL_GEOMETRY_SHADER, str8fromcstr(geom_filename));
+ if (frag_filename)
+ frag = compile_shader(GL_FRAGMENT_SHADER, str8fromcstr(frag_filename));
- Arena *tmp = arena_alloc(0);
+ tmp = arena_alloc(0);
- U32 id = glCreateProgram();
- glAttachShader(id, vert);
- glAttachShader(id, frag);
+ id = glCreateProgram();
+ if (vert_filename)
+ glAttachShader(id, vert);
+ if (geom_filename)
+ glAttachShader(id, geom);
+ if (frag_filename)
+ glAttachShader(id, frag);
glLinkProgram(id);
- S32 success;
glGetProgramiv(id, GL_LINK_STATUS, &success);
if (success == GL_FALSE) {
- char log[512];
+ char log[512];
glGetProgramInfoLog(id, 512, 0, log);
- str8print(str8_pushf(tmp, "[ERROR]: Failed to link shader program:\n%s", log));
+ str8print(str8pushf(tmp, "[ERROR] : Failed to link shader program:\n%s", log));
} else {
- str8print(str8_pushf(tmp, "[INFO]: Shader program linked successfuly.\n\n"));
+ str8print(str8pushf(tmp, "[INFO] : Shader linked successfuly.\n\n"));
}
- glDeleteShader(vert);
- glDeleteShader(frag);
+ if (vert_filename)
+ glDeleteShader(vert);
+ if (geom_filename)
+ glDeleteShader(geom);
+ if (frag_filename)
+ glDeleteShader(frag);
arena_release(tmp);
return id;
}
-void shader_set_mat4fv(U32 id, char *name, Mat4 m)
+void shader_set_3fv(U32 id, char *name, V3 v)
+{
+ S32 loc;
+ loc = glGetUniformLocation(id, name);
+ glUniform3fv(loc, 1, (F32 *)&v);
+}
+
+void shader_set_4fv(U32 id, char *name, V4 v)
+{
+ S32 loc;
+ loc = glGetUniformLocation(id, name);
+ glUniform4fv(loc, 1, (F32 *)&v);
+}
+
+void shader_set_mat4fv(U32 id, char *name, MAT4 m)
{
- S32 loc = glGetUniformLocation(id, name);
+ S32 loc;
+ loc = glGetUniformLocation(id, name);
glUniformMatrix4fv(loc, 1, 0, (F32 *)&m);
}
diff --git a/prge_shader.h b/prge_shader.h
index 1e065a5..9a399d4 100644
--- a/prge_shader.h
+++ b/prge_shader.h
@@ -1,8 +1,17 @@
#ifndef PRGE_SHADER_H
#define PRGE_SHADER_H
-U32 compile_shader(GLenum type, Str8 filename);
-U32 create_shader_program(Str8 vert_filename, Str8 frag_filename);
-void shader_set_mat4fv(U32 id, char *name, Mat4 m);
+#define PRGE_SHADER_POS_LOC 0
+#define PRGE_SHADER_TEXC_LOC 1
+
+#define PRGE_SHADER_PROJ_MAT "proj"
+#define PRGE_SHADER_VIEW_MAT "view"
+#define PRGE_SHADER_MODEL_MAT "model"
+
+U32 compile_shader(GLenum type, Str8 fname);
+U32 load_shader(char *vert_filename, char *geom_filename, char *frag_filename);
+void shader_set_3fv(U32 id, char *name, V3 v);
+void shader_set_4fv(U32 id, char *name, V4 v);
+void shader_set_mat4fv(U32 id, char *name, MAT4 m);
#endif /* PRGE_SHADER_H */
diff --git a/prge_texture.c b/prge_texture.c
new file mode 100644
index 0000000..cce3374
--- /dev/null
+++ b/prge_texture.c
@@ -0,0 +1,69 @@
+Texture load_texture(Arena *arena, char *filename, B32 gamma_correction)
+{
+ U8 *data;
+
+ S32 nchannels;
+ GLenum internal_format;
+ GLenum data_format;
+
+ Texture texture;
+
+ Arena *temparena;
+
+ char *cfilename;
+ Str8 str;
+
+ Assert(arena);
+
+ MemoryZeroStruct(&texture);
+
+ temparena = arena_alloc(0);
+
+ cfilename = str8tocstr(arena, filename);
+
+ stbi_set_flip_vertically_on_load(1);
+ data = stbi_load(cfilename, &texture.width, &texture.height, &nchannels, 0);
+
+ if (!data) {
+ str = str8pushf(temparena, "[ERROR] : Texture : %s : Failed to load\n", cfilename);
+ goto end;
+ }
+
+ switch (nchannels) {
+ case 1:
+ texture.type = TextureType_R;
+ internal_format = data_format = GL_RED;
+ break;
+ case 3:
+ texture.type = TextureType_RGB;
+ internal_format = (gamma_correction) ? GL_SRGB : GL_RGB;
+ data_format = GL_RGB;
+ break;
+ case 4:
+ texture.type = TextureType_RGBA;
+ internal_format = (gamma_correction) ? GL_SRGB_ALPHA : GL_RGBA;
+ data_format = GL_RGBA;
+ break;
+ default:
+ str = str8pushf(temparena, "[ERROR] : Texture : %s : Unsupported type\n", cfilename);
+ goto end;
+ }
+
+ glGenTextures(1, &texture.id);
+ glBindTexture(GL_TEXTURE_2D, texture.id);
+ glTexImage2D(GL_TEXTURE_2D, 0, internal_format, texture.width, texture.height, 0, data_format, GL_UNSIGNED_BYTE, data);
+ glGenerateMipmap(GL_TEXTURE_2D);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ glBindTexture(GL_TEXTURE_2D, 0);
+
+ str = str8pushf(temparena, "[INFO] : Texture : %s : Loaded successfully\n", cfilename);
+
+end:
+ str8print(str);
+ stbi_image_free(data);
+ arena_release(temparena);
+ return texture;
+}
diff --git a/prge_texture.h b/prge_texture.h
new file mode 100644
index 0000000..cb4c4cc
--- /dev/null
+++ b/prge_texture.h
@@ -0,0 +1,6 @@
+#ifndef PRGE_TEXTURE_H
+#define PRGE_TEXTURE_H
+
+Texture texture_load(Arena *arena, Str8 filename);
+
+#endif /* PRGE_TEXTURE_H */
diff --git a/prge_types.h b/prge_types.h
index ff5b860..1799870 100644
--- a/prge_types.h
+++ b/prge_types.h
@@ -1,50 +1,118 @@
#ifndef PRGE_TYPES_H
#define PRGE_TYPES_H
-enum KeyState_Enum {
- KeyState_RELEASE = 0,
- KeyState_PRESS = 1
-};
+#define MAX_TEXTURE 5
typedef struct {
- enum KeyState_Enum last;
- enum KeyState_Enum state;
+ S32 width;
+ S32 height;
+ Str8 name;
+} Window;
+
+typedef enum {
+ KeyState_RELEASE = 0,
+ KeyState_PRESS = 1
+} KeyStateEnum;
+
+typedef struct {
+ KeyStateEnum last;
+ KeyStateEnum state;
} Key;
typedef struct {
- V2 mouse_pos;
- V2 last_mouse_pos;
- V2 mouse_offset;
- B32 first_mouse;
+ V2 mouse_pos;
+ V2 last_mouse_pos;
+ V2 mouse_offset;
+ B32 first_mouse;
+ B32 capture_mouse;
+ Key mouse_left;
+ Key mouse_right;
- B32 is_running;
+ B32 is_running;
- F32 dt;
+ F32 dt;
- Key move_right;
- Key move_forward;
- Key move_left;
- Key move_backward;
- Key move_up;
- Key move_down;
- Key jump;
- Key action_right;
- Key action_up;
- Key action_left;
- Key action_down;
- Key exit;
+ Key move_right;
+ Key move_forward;
+ Key move_left;
+ Key move_backward;
+ Key move_up;
+ Key move_down;
+ Key jump;
+ Key action_right;
+ Key action_up;
+ Key action_left;
+ Key action_down;
+ Key exit;
} Input;
+typedef enum {
+ TextureType_R = 1,
+ TextureType_RGB = 3,
+ TextureType_RGBA = 4
+} TextureTypeEnum;
+
typedef struct {
- V3 pos;
+ U32 id;
+ Str8 name;
+
+ TextureTypeEnum type;
+
+ S32 width;
+ S32 height;
+
+ void *data;
+} Texture;
+
+typedef struct {
+ V3 pos;
+ V2 texc;
} Vertex;
typedef struct {
- Vertex *verts;
- U32 nverts;
- U32 *indices;
- U32 nindices;
- U32 vao, vbo, ebo;
+ V3 origin;
+ V3 rotate;
+
+ U32 nverts;
+ Vertex *verts;
+
+ U32 nindices;
+ U32 *indices;
+
+ U32 ntextures;
+ Texture textures[MAX_TEXTURE];
+
+ U32 vao, vbo, ebo;
} Mesh;
+typedef struct {
+ V3 origin;
+ V3 rotate;
+
+ U32 nmeshes;
+ Mesh *meshes;
+} Model;
+
+typedef struct {
+ V3 pos;
+
+ F32 fov;
+
+ F32 near;
+ F32 far;
+
+ F32 yaw;
+ F32 pitch;
+ F32 roll;
+} Camera;
+
+typedef struct {
+ U32 nmodels;
+ Model *models;
+
+ Camera camera;
+
+ Str8 bindir;
+} PRGEState;
+
#endif /* PRGE_TYPES_H */
diff --git a/prge_window.c b/prge_window.c
new file mode 100644
index 0000000..444866c
--- /dev/null
+++ b/prge_window.c
@@ -0,0 +1,10 @@
+Window window_init(S32 width, S32 height, Str8 name)
+{
+ Window wnd;
+
+ wnd.width = width;
+ wnd.height = height;
+ wnd.name = name;
+
+ return wnd;
+}
diff --git a/prge_window.h b/prge_window.h
new file mode 100644
index 0000000..e79ee86
--- /dev/null
+++ b/prge_window.h
@@ -0,0 +1,6 @@
+#ifndef PRGE_WINDOW_H
+#define PRGE_WINDOW_H
+
+Window window_init(S32 width, S32 height, Str8 name);
+
+#endif /* PRGE_WINDOW_H */