Skip to content

Commit

Permalink
model: Load emissive texture
Browse files Browse the repository at this point in the history
Load emissive texture from gltf, add it to the textured model object and
pass it on to the model shader.

Signed-off-by: Alexander Shishkin <[email protected]>
  • Loading branch information
virtuoso committed Oct 13, 2024
1 parent b601da0 commit 889ba1a
Show file tree
Hide file tree
Showing 6 changed files with 86 additions and 16 deletions.
32 changes: 21 additions & 11 deletions core/gltf.c
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,7 @@ struct gltf_animation {
struct gltf_material {
int base_tex;
int normal_tex;
int emission_tex;
double metallic;
double roughness;
};
Expand Down Expand Up @@ -457,6 +458,7 @@ unsigned int gltf_ ## _name ## sz(struct gltf_data *gd, int mesh) \

GLTF_MAT_TEX(base, tex)
GLTF_MAT_TEX(normal, nmap)
GLTF_MAT_TEX(emission, em)

int gltf_root_mesh(struct gltf_data *gd)
{
Expand Down Expand Up @@ -910,21 +912,16 @@ static void gltf_onload(struct lib_handle *h, void *data)
/* Materials */
for (n = mats->children.head; n; n = n->next) {
struct gltf_material *mat;
JsonNode *jwut, *jpbr;
JsonNode *jwut, *jpbr, *jem;

jpbr = json_find_member(n, "pbrMetallicRoughness");
if (!jpbr || jpbr->tag != JSON_OBJECT)
continue;

jwut = json_find_member(jpbr, "baseColorTexture");
/*
* this means the model was exported from blender with "emission" shader
* instead of principal BSDF; we'll still handle it, but print a warning
*/
if (!jwut) {
jwut = json_find_member(n, "emissiveTexture");
warn("found emissiveTexture; this is probably not what you want\n");
}
if (!jwut || jwut->tag != JSON_OBJECT)
continue;

if (!jwut || jwut->tag != JSON_OBJECT)
continue;
jwut = json_find_member(jwut, "index");
Expand All @@ -934,6 +931,14 @@ static void gltf_onload(struct lib_handle *h, void *data)
CHECK(mat = darray_add(&gd->mats.da));
mat->base_tex = jwut->number_;
mat->normal_tex = -1;
mat->emission_tex = -1;

jem = json_find_member(n, "emissiveTexture");
if (jem && jem->tag == JSON_OBJECT) {
JsonNode *jemidx = json_find_member(jem, "index");
if (jemidx && jemidx->tag == JSON_NUMBER)
mat->emission_tex = jemidx->number_;
}

if (jpbr) {
jwut = json_find_member(jpbr, "metallicFactor");
Expand All @@ -952,9 +957,10 @@ static void gltf_onload(struct lib_handle *h, void *data)
}
}

dbg("material %d: tex: %d nmap: %d met: %f rough: %f\n",
dbg("material %d: tex: %d nmap: %d emission: %d met: %f rough: %f\n",
gd->mats.da.nr_el - 1, mat->base_tex,
mat->normal_tex,
mat->emission_tex,
mat->metallic,
mat->roughness
);
Expand Down Expand Up @@ -1072,7 +1078,11 @@ int gltf_instantiate_one(struct gltf_data *gd, int mesh)
}

gd->scene->_model = m;
if (gltf_has_nmap(gd, mesh)) {
if (gltf_has_em(gd, mesh)) {
txm = model3dtx_new_from_buffers2(ref_pass(m), gltf_tex(gd, mesh), gltf_texsz(gd, mesh),
gltf_nmap(gd, mesh), gltf_nmapsz(gd, mesh),
gltf_em(gd, mesh), gltf_emsz(gd, mesh));
} else if (gltf_has_nmap(gd, mesh)) {
txm = model3dtx_new_from_buffers(ref_pass(m), gltf_tex(gd, mesh), gltf_texsz(gd, mesh),
gltf_nmap(gd, mesh), gltf_nmapsz(gd, mesh));
} else {
Expand Down
59 changes: 56 additions & 3 deletions core/model.c
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,9 @@ static int load_gl_texture_buffer(struct shader_prog *p, void *buffer, int width
if (!buffer)
return -EINVAL;

if (p->emission_map < 0 && loc == GL_TEXTURE2)
return -EINVAL;

//hexdump(buffer, 16);
texture_init_target(tex, target);
texture_filters(tex, GL_REPEAT, GL_NEAREST);
Expand All @@ -90,8 +93,8 @@ static int load_gl_texture_buffer(struct shader_prog *p, void *buffer, int width
static int model3d_add_texture_from_buffer(struct model3dtx *txm, GLuint target, void *input, size_t length)
{
struct shader_prog *prog = txm->model->prog;
texture_t *targets[] = { txm->texture, txm->normals };
GLint locs[] = { prog->texture_map, prog->normal_map };
texture_t *targets[] = { txm->texture, txm->normals, txm->emission };
GLint locs[] = { prog->texture_map, prog->normal_map, prog->emission_map };
int width, height, has_alpha, ret;
unsigned char *buffer;

Expand Down Expand Up @@ -138,6 +141,7 @@ static int model3dtx_make(struct ref *ref)
struct model3dtx *txm = container_of(ref, struct model3dtx, ref);
txm->texture = &txm->_texture;
txm->normals = &txm->_normals;
txm->emission = &txm->_emission;
list_init(&txm->entities);
list_init(&txm->entry);
return 0;
Expand All @@ -160,8 +164,14 @@ static void model3dtx_drop(struct ref *ref)
texture_done(txm->texture);
else
texture_deinit(txm->texture);
if (txm->normals)
if (txm->normals != &txm->_normals)
texture_done(txm->normals);
else
texture_deinit(txm->normals);
if (txm->emission != &txm->_emission)
texture_done(txm->emission);
else
texture_deinit(txm->emission);
ref_put(txm->model);
}

Expand Down Expand Up @@ -197,6 +207,17 @@ struct model3dtx *model3dtx_new(struct model3d *model, const char *name)
return model3dtx_new2(model, name, NULL);
}

static void model3dtx_add_fake_emission(struct model3dtx *txm)
{
struct model3d *model = txm->model;
float fake_emission[4] = { 0, 0, 0, 1.0 };

shader_prog_use(model->prog);
load_gl_texture_buffer(model->prog, fake_emission, 1, 1, true, GL_TEXTURE2, model->prog->emission_map,
txm->emission);
shader_prog_done(model->prog);
}

struct model3dtx *model3dtx_new_from_buffer(struct model3d *model, void *buffer, size_t length)
{
if (!buffer || !length)
Expand All @@ -209,6 +230,7 @@ struct model3dtx *model3dtx_new_from_buffer(struct model3d *model, void *buffer,

txm->model = ref_get(model);
model3d_add_texture_from_buffer(txm, GL_TEXTURE0, buffer, length);
model3dtx_add_fake_emission(txm);

return txm;

Expand All @@ -230,6 +252,31 @@ struct model3dtx *model3dtx_new_from_buffers(struct model3d *model, void *tex, s
txm->model = ref_get(model);
model3d_add_texture_from_buffer(txm, GL_TEXTURE0, tex, texsz);
model3d_add_texture_from_buffer(txm, GL_TEXTURE1, norm, normsz);
model3dtx_add_fake_emission(txm);

return txm;

err:
ref_put_passed(model);
return NULL;
}

struct model3dtx *model3dtx_new_from_buffers2(struct model3d *model, void *tex, size_t texsz, void *norm, size_t normsz,
void *em, size_t emsz)
{
if (!tex || !texsz /*|| !norm || !normsz*/ || !em || !emsz)
goto err;

struct model3dtx *txm = ref_new(model3dtx);

if (!txm)
goto err;

txm->model = ref_get(model);
model3d_add_texture_from_buffer(txm, GL_TEXTURE0, tex, texsz);
if (norm && normsz)
model3d_add_texture_from_buffer(txm, GL_TEXTURE1, norm, normsz);
model3d_add_texture_from_buffer(txm, GL_TEXTURE2, em, emsz);

return txm;

Expand Down Expand Up @@ -569,6 +616,12 @@ void model3dtx_prepare(struct model3dtx *txm)
GL(glBindTexture(GL_TEXTURE_2D, texture_id(txm->normals)));
GL(glUniform1i(p->normal_map, 1));
}

if (p->emission_map >= 0 && texture_loaded(txm->emission)) {
GL(glActiveTexture(GL_TEXTURE2));
GL(glBindTexture(GL_TEXTURE_2D, texture_id(txm->emission)));
GL(glUniform1i(p->emission_map, 2));
}
}

void model3dtx_draw(struct model3dtx *txm)
Expand Down
4 changes: 4 additions & 0 deletions core/model.h
Original file line number Diff line number Diff line change
Expand Up @@ -115,8 +115,10 @@ struct model3dtx {
// GLuint texture_id;
texture_t _texture;
texture_t _normals;
texture_t _emission;
texture_t *texture;
texture_t *normals;
texture_t *emission;
// GLuint normals_id;
float metallic;
float roughness;
Expand All @@ -142,6 +144,8 @@ struct model3dtx *model3dtx_new(struct model3d *m, const char *name);
struct model3dtx *model3dtx_new2(struct model3d *model, const char *tex, const char *norm);
struct model3dtx *model3dtx_new_from_buffer(struct model3d *model, void *buffer, size_t length);
struct model3dtx *model3dtx_new_from_buffers(struct model3d *model, void *tex, size_t texsz, void *norm, size_t normsz);
struct model3dtx *model3dtx_new_from_buffers2(struct model3d *model, void *tex, size_t texsz, void *norm, size_t normsz,
void *em, size_t emsz);
struct model3dtx *model3dtx_new_txid(struct model3d *model, unsigned int txid);
struct model3dtx *model3dtx_new_texture(struct model3d *model, texture_t *tex);
struct model3d *model3d_new_cube(struct shader_prog *p);
Expand Down
5 changes: 3 additions & 2 deletions core/shader.c
Original file line number Diff line number Diff line change
Expand Up @@ -214,9 +214,10 @@ shader_prog_from_strings(const char *name, const char *vsh, const char *fsh)
p->normal_map = shader_prog_find_var(p, "normal_map");
p->joints = shader_prog_find_var(p, "joints");
p->weights = shader_prog_find_var(p, "weights");
dbg("model '%s' %d/%d/%d/%d/%d/%d/%d/%d\n",
p->emission_map = shader_prog_find_var(p, "emission_map");
dbg("model '%s' %d/%d/%d/%d/%d/%d/%d/%d/%d\n",
p->name, p->pos, p->norm, p->tex, p->tangent,
p->texture_map, p->normal_map, p->joints, p->weights);
p->texture_map, p->normal_map, p->emission_map, p->joints, p->weights);
if (p->pos < 0) {
shader_prog_done(p);
return NULL;
Expand Down
1 change: 1 addition & 0 deletions core/shader.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ struct shader_prog {
GLint tangent;
GLint texture_map;
GLint normal_map;
GLint emission_map;
GLint joints;
GLint weights;
GLint tex;
Expand Down
1 change: 1 addition & 0 deletions shaders/model.frag
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ in vec4 pass_tangent;

uniform sampler2D model_tex;
uniform sampler2D normal_map;
uniform sampler2D emission_map;
uniform vec3 light_color[4];
uniform vec3 attenuation[4];
uniform float shine_damper;
Expand Down

0 comments on commit 889ba1a

Please sign in to comment.