aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTomasz Kramkowski <tk@the-tk.com>2018-05-02 21:22:03 +0100
committerTomasz Kramkowski <tk@the-tk.com>2018-05-02 21:22:03 +0100
commitb659c412263f6dd7df962f7d42f4f51b7c3d5609 (patch)
treee2495e0b1446527b909a9c9fa2776797c7c28221
parentec93a8eddf70adef2b1439a511d990021ad25d99 (diff)
downloadfaqe-b659c412263f6dd7df962f7d42f4f51b7c3d5609.tar.gz
faqe-b659c412263f6dd7df962f7d42f4f51b7c3d5609.tar.xz
faqe-b659c412263f6dd7df962f7d42f4f51b7c3d5609.zip
Implement diffuse texture loading and basic material support
-rw-r--r--Makefile4
-rw-r--r--cube.fmdbin948 -> 977 bytes
-rw-r--r--ensize.c20
-rw-r--r--ensize.h9
-rw-r--r--faqe.c5
-rw-r--r--frag.glsl5
-rw-r--r--gl.h16
-rw-r--r--glfunc.h6
-rw-r--r--model.c6
-rw-r--r--model.h5
-rw-r--r--mtl.c54
-rw-r--r--mtl.h10
-rw-r--r--tex.c36
-rw-r--r--tex.h14
-rw-r--r--vert.glsl2
15 files changed, 184 insertions, 8 deletions
diff --git a/Makefile b/Makefile
index 5ceed54..9d66590 100644
--- a/Makefile
+++ b/Makefile
@@ -9,13 +9,13 @@ LINMATH_PATH ?= ../linmath
PKG_CONFIG ?= pkg-config
LN ?= ln -sf
-LIBS := sdl2
+LIBS := sdl2 libpng
CPPFLAGS += -D__gl_h_
CFLAGS += $(shell $(PKG_CONFIG) --cflags $(LIBS)) -std=c11 -MMD -MP
LDFLAGS += -Wl,--as-needed
LDLIBS += $(shell $(PKG_CONFIG) --libs $(LIBS)) -lm
-OBJ := faqe.o eprintf.o fmd.o gl.o glprog.o ieee754.o model.o
+OBJ := faqe.o ensize.o eprintf.o fmd.o gl.o glprog.o ieee754.o model.o mtl.o tex.o
all: $(PROG)
diff --git a/cube.fmd b/cube.fmd
index 6177d5d..d99d758 100644
--- a/cube.fmd
+++ b/cube.fmd
Binary files differ
diff --git a/ensize.c b/ensize.c
new file mode 100644
index 0000000..82835a7
--- /dev/null
+++ b/ensize.c
@@ -0,0 +1,20 @@
+#include <assert.h>
+
+#include "ensize.h"
+#include "eprintf.h"
+
+// ensize: realloc p if it is smaller than count given current size
+void *ensize(void *p, size_t selem, size_t nelem, size_t *cur, size_t init)
+{
+ assert(cur != NULL);
+
+ if (*cur >= nelem * selem)
+ return p;
+
+ if (*cur == 0)
+ *cur = init * selem;
+ else
+ *cur *= 2;
+
+ return erealloc(p, *cur);
+}
diff --git a/ensize.h b/ensize.h
new file mode 100644
index 0000000..6837294
--- /dev/null
+++ b/ensize.h
@@ -0,0 +1,9 @@
+#ifndef ENSIZE_H
+#define ENSIZE_H
+
+#include <stddef.h>
+
+void *ensize(void *p, size_t selem, size_t nelem, size_t *cur, size_t init);
+#define ENSIZE(p, n, s, i) ensize((p), sizeof *(p), (n), (s), (i))
+
+#endif // ENSIZE_H
diff --git a/faqe.c b/faqe.c
index 9567d1f..c13b4dc 100644
--- a/faqe.c
+++ b/faqe.c
@@ -36,7 +36,7 @@ int main(int argc, char **argv)
SDL_GLContext *glc;
GLuint prog;
struct {
- GLint model, view, proj;
+ GLint model, view, proj, tex;
} uni;
mat4x4 view;
FILE *cube_file;
@@ -84,9 +84,12 @@ int main(int argc, char **argv)
{ "model", &uni.model },
{ "view", &uni.view },
{ "proj", &uni.proj },
+ { "tex", &uni.tex },
{ 0 },
});
+ gl_uni_set1i(uni.tex, 0);
+
gl_prog_use(prog);
viewport(uni.proj, WIDTH, HEIGHT);
diff --git a/frag.glsl b/frag.glsl
index 4a5e869..5aa26d8 100644
--- a/frag.glsl
+++ b/frag.glsl
@@ -4,11 +4,14 @@
out vec4 color;
in vec3 vnorm;
in vec3 fpos;
+in vec2 fuv;
in vec3 lipos;
+uniform sampler2D tex;
+
void main()
{
- vec3 objco = vec3(1.0, 0.5, 0.31);
+ vec3 objco = vec3(texture(tex, fuv));
vec3 lico = vec3(1.0, 1.0, 1.0);
float amb = 0.1;
diff --git a/gl.h b/gl.h
index 40b650d..76e78d9 100644
--- a/gl.h
+++ b/gl.h
@@ -52,9 +52,25 @@ enum {
GL_CONTEXT_LOST,
GL_CULL_FACE = 0x0b44,
GL_DEPTH_TEST = 0x0b71,
+ GL_TEXTURE_2D = 0x0de1,
+ GL_UNSIGNED_BYTE = 0x1401,
GL_UNSIGNED_INT = 0x1405,
GL_FLOAT = 0x1406,
+ GL_RGB = 0x1907,
GL_LINE = 0x1B01,
+ GL_NEAREST = 0x2600,
+ GL_LINEAR,
+ GL_NEAREST_MIPMAP_NEAREST = 0x2700,
+ GL_LINEAR_MIPMAP_NEAREST,
+ GL_NEAREST_MIPMAP_LINEAR,
+ GL_LINEAR_MIPMAP_LINEAR,
+ GL_TEXTURE_MAG_FILTER = 0x2800,
+ GL_TEXTURE_MIN_FILTER,
+ GL_TEXTURE_WRAP_S,
+ GL_TEXTURE_WRAP_T,
+ GL_CLAMP = 0x2900,
+ GL_REPEAT,
+ GL_TEXTURE0 = 0x84c0,
GL_ARRAY_BUFFER = 0x8892,
GL_ELEMENT_ARRAY_BUFFER = 0x8893,
GL_STREAM_DRAW = 0x88e0,
diff --git a/glfunc.h b/glfunc.h
index 6722567..a5c575e 100644
--- a/glfunc.h
+++ b/glfunc.h
@@ -46,3 +46,9 @@ GL_FUNC(glUniformMatrix4fv, void, gl_uni_setm4fv, GLint location, GLsizei count,
GL_FUNC(glGetIntegerv, void, gl_geti, GLenum pname, GLint *data)
GL_FUNC(glEnable, void, gl_enable, GLenum cap)
GL_FUNC(glDisable, void, gl_disable, GLenum cap)
+GL_FUNC(glGenTextures, void, gl_tex_gen, GLsizei n, GLuint *textures)
+GL_FUNC(glActiveTexture, void, gl_tex_active, GLenum texture)
+GL_FUNC(glBindTexture, void, gl_tex_bind, GLenum target, GLuint texture)
+GL_FUNC(glTexImage2D, void, gl_tex_img2d, GLenum target, GLint level, GLint internalFormat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void *data)
+GL_FUNC(glTexParameteri, void, gl_tex_parami, GLenum target, GLenum pname, GLint param)
+GL_FUNC(glGenerateMipmap, void, gl_tex_genmip, GLenum target)
diff --git a/model.c b/model.c
index 7a6a256..88931c0 100644
--- a/model.c
+++ b/model.c
@@ -44,7 +44,10 @@ void model_load(struct model *mdl, const struct fmd *fmd)
for (int i = 0; i < fmd->nmeshes; i++) {
struct mesh *m = &mdl->meshes[i];
struct fmd_mesh *fm = &fmd->meshes[i];
- m->mtl = NULL;
+ if (fm->midx >= 0)
+ m->mtl = mtl_load(fmd->mtls[fm->midx]);
+ else
+ m->mtl = -1;
m->elems.idx = fm->tidx * NELEM(*fmd->tris);
m->elems.cnt = fm->tcnt * NELEM(*fmd->tris);
}
@@ -55,6 +58,7 @@ void model_render(struct model *mdl)
gl_va_bind(mdl->vao);
for (int i = 0; i < mdl->nmeshes; i++) {
struct mesh *m = &mdl->meshes[i];
+ mtl_use(m->mtl);
gl_draw_elems(GL_TRIANGLES, m->elems.cnt, GL_UNSIGNED_INT, &((GLuint *)NULL)[m->elems.idx]);
}
}
diff --git a/model.h b/model.h
index 33db3b4..182faea 100644
--- a/model.h
+++ b/model.h
@@ -7,11 +7,10 @@
#include "gl.h"
#include "fmd.h"
+#include "mtl.h"
struct mesh {
- struct material {
- GLuint diffuse;
- } *mtl;
+ mtlidx mtl;
struct {
GLuint idx;
GLuint cnt;
diff --git a/mtl.c b/mtl.c
new file mode 100644
index 0000000..7f53fa2
--- /dev/null
+++ b/mtl.c
@@ -0,0 +1,54 @@
+#include <assert.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "ensize.h"
+#include "eprintf.h"
+#include "mtl.h"
+#include "tex.h"
+
+struct mtl {
+ char name[50];
+ GLuint diffuse;
+};
+
+static struct mtl *mtls;
+static int lmtls;
+static size_t nmtls;
+
+int mtl_load(char *name)
+{
+ struct mtl *m;
+ char loc[100];
+ FILE *f;
+
+ for (int i = 0; i < lmtls; i++)
+ if (strcmp(mtls[i].name, name) == 0)
+ return i;
+
+ mtls = ENSIZE(mtls, lmtls + 1, &nmtls, 16);
+ m = &mtls[lmtls];
+
+ snprintf(m->name, sizeof m->name, "%s", name);
+
+ snprintf(loc, sizeof loc, "./tex/%s.png", name);
+ f = fopen(loc, "rb");
+ if (f == NULL)
+ eprintf("Could not open '%s':", loc);
+ m->diffuse = png2tex(f);
+ fclose(f);
+
+ return lmtls++;
+}
+
+void mtl_use(int mtl)
+{
+ assert(mtl < lmtls);
+
+ // TODO: Blank textures or something
+ if (mtl < 0)
+ return;
+
+ gl_tex_active(GL_TEXTURE0);
+ gl_tex_bind(GL_TEXTURE_2D, mtls[mtl].diffuse);
+}
diff --git a/mtl.h b/mtl.h
new file mode 100644
index 0000000..7c427c1
--- /dev/null
+++ b/mtl.h
@@ -0,0 +1,10 @@
+#ifndef MTL_H
+#define MTL_H
+
+#include "gl.h"
+
+typedef int mtlidx;
+mtlidx mtl_load(char *name);
+void mtl_use(mtlidx mtl);
+
+#endif // MTL_H
diff --git a/tex.c b/tex.c
new file mode 100644
index 0000000..6f27b8a
--- /dev/null
+++ b/tex.c
@@ -0,0 +1,36 @@
+#include <assert.h>
+#include <png.h>
+#include <stdlib.h>
+
+#include "eprintf.h"
+#include "tex.h"
+
+GLuint png2tex(FILE *f)
+{
+ png_image pi = { .version = PNG_IMAGE_VERSION };
+ unsigned char *data;
+ size_t size;
+ GLuint id;
+
+ assert(f != NULL);
+
+ png_image_begin_read_from_stdio(&pi, f);
+ pi.format = PNG_FORMAT_RGB;
+ size = sizeof *data * 3 * pi.width * pi.height;
+ data = emalloc(size);
+ png_image_finish_read(&pi, NULL, data, size / pi.height, NULL);
+
+ gl_tex_gen(1, &id);
+ gl_tex_bind(GL_TEXTURE_2D, id);
+ gl_tex_parami(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ gl_tex_parami(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
+ gl_tex_parami(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
+ gl_tex_parami(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
+ gl_tex_img2d(GL_TEXTURE_2D, 0, GL_RGB, pi.width, pi.height, 0, GL_RGB, GL_UNSIGNED_BYTE, data);
+ gl_tex_genmip(GL_TEXTURE_2D);
+
+ free(data);
+ png_image_free(&pi);
+
+ return id;
+}
diff --git a/tex.h b/tex.h
new file mode 100644
index 0000000..c7ad0d2
--- /dev/null
+++ b/tex.h
@@ -0,0 +1,14 @@
+/*
+ * Copyright (C) 2018 Tomasz Kramkowski <tk@the-tk.com>
+ * SPDX-License-Identifier: MIT
+ */
+#ifndef TEX_H
+#define TEX_H
+
+#include <stdio.h>
+
+#include "gl.h"
+
+GLuint png2tex(FILE *f);
+
+#endif // TEX_H
diff --git a/vert.glsl b/vert.glsl
index 5292e99..906408e 100644
--- a/vert.glsl
+++ b/vert.glsl
@@ -7,6 +7,7 @@ layout (location = 2) in vec2 uv;
out vec3 vnorm;
out vec3 fpos;
+out vec2 fuv;
out vec3 lipos;
uniform mat4 model;
@@ -19,6 +20,7 @@ void main()
gl_Position = proj * view * model * vec4(pos, 1.0);
fpos = vec3(view * model * vec4(pos, 1.0));
+ fuv = uv;
// TODO: Try to work out how to only do this ONCE in C or see if it matters
vnorm = mat3(transpose(inverse(view * model))) * norm;
lipos = vec3(view * vec4(light, 1.0));