From b659c412263f6dd7df962f7d42f4f51b7c3d5609 Mon Sep 17 00:00:00 2001 From: Tomasz Kramkowski Date: Wed, 2 May 2018 21:22:03 +0100 Subject: Implement diffuse texture loading and basic material support --- Makefile | 4 ++-- cube.fmd | Bin 948 -> 977 bytes ensize.c | 20 ++++++++++++++++++++ ensize.h | 9 +++++++++ faqe.c | 5 ++++- frag.glsl | 5 ++++- gl.h | 16 ++++++++++++++++ glfunc.h | 6 ++++++ model.c | 6 +++++- model.h | 5 ++--- mtl.c | 54 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ mtl.h | 10 ++++++++++ tex.c | 36 ++++++++++++++++++++++++++++++++++++ tex.h | 14 ++++++++++++++ vert.glsl | 2 ++ 15 files changed, 184 insertions(+), 8 deletions(-) create mode 100644 ensize.c create mode 100644 ensize.h create mode 100644 mtl.c create mode 100644 mtl.h create mode 100644 tex.c create mode 100644 tex.h 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 Binary files a/cube.fmd and b/cube.fmd 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 + +#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 + +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 +#include +#include + +#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 +#include +#include + +#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 + * SPDX-License-Identifier: MIT + */ +#ifndef TEX_H +#define TEX_H + +#include + +#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)); -- cgit v1.2.3-54-g00ecf