From e74df3477c59b33ff64761552693257bb0717177 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Madar=C3=A1sz?= Date: Mon, 15 Apr 2024 10:54:30 +0200 Subject: [PATCH] gfx: unify shader locations in model api --- bind/v4k.lua | 26 +++++ engine/joint/v4k.h | 229 ++++++++++++++++++++++++-------------- engine/split/v4k_render.c | 200 +++++++++++++++++++-------------- engine/split/v4k_render.h | 29 +++++ engine/v4k.c | 200 +++++++++++++++++++-------------- engine/v4k.h | 29 +++++ 6 files changed, 464 insertions(+), 249 deletions(-) diff --git a/bind/v4k.lua b/bind/v4k.lua index 4dddf5c..46afd96 100644 --- a/bind/v4k.lua +++ b/bind/v4k.lua @@ -1368,6 +1368,31 @@ enum RENDER_PASS { RENDER_PASS_LIGHTMAP, NUM_RENDER_PASSES }; +enum MODEL_UNIFORMS { + MODEL_UNIFORM_MV, + MODEL_UNIFORM_MVP, + MODEL_UNIFORM_VP, + MODEL_UNIFORM_CAM_POS, + MODEL_UNIFORM_CAM_DIR, + MODEL_UNIFORM_BILLBOARD, + MODEL_UNIFORM_TEXLIT, + MODEL_UNIFORM_MODEL, + MODEL_UNIFORM_VIEW, + MODEL_UNIFORM_INV_VIEW, + MODEL_UNIFORM_PROJ, + MODEL_UNIFORM_SKINNED, + MODEL_UNIFORM_VS_BONE_MATRIX, + MODEL_UNIFORM_U_MATCAPS, + MODEL_UNIFORM_RESOLUTION, + MODEL_UNIFORM_HAS_TEX_SKYSPHERE, + MODEL_UNIFORM_HAS_TEX_SKYENV, + MODEL_UNIFORM_TEX_SKYSPHERE, + MODEL_UNIFORM_SKYSPHERE_MIP_COUNT, + MODEL_UNIFORM_TEX_SKYENV, + MODEL_UNIFORM_TEX_BRDF_LUT, + MODEL_UNIFORM_FRAME_COUNT, + NUM_MODEL_UNIFORMS +}; typedef struct model_t { struct iqm_t *iqm; int shading; @@ -1375,6 +1400,7 @@ typedef struct model_t { handle *textures; char **texture_names; material_t* materials; + unsigned uniforms[NUM_MODEL_UNIFORMS]; texture_t sky_refl, sky_env; texture_t lightmap; float *lmdata; diff --git a/engine/joint/v4k.h b/engine/joint/v4k.h index 9ae207e..8c56d7e 100644 --- a/engine/joint/v4k.h +++ b/engine/joint/v4k.h @@ -17624,6 +17624,34 @@ enum RENDER_PASS { NUM_RENDER_PASSES }; +enum MODEL_UNIFORMS { + MODEL_UNIFORM_MV, + MODEL_UNIFORM_MVP, + MODEL_UNIFORM_VP, + MODEL_UNIFORM_CAM_POS, + MODEL_UNIFORM_CAM_DIR, + MODEL_UNIFORM_BILLBOARD, + MODEL_UNIFORM_TEXLIT, + MODEL_UNIFORM_MODEL, + MODEL_UNIFORM_VIEW, + MODEL_UNIFORM_INV_VIEW, + MODEL_UNIFORM_PROJ, + MODEL_UNIFORM_SKINNED, + MODEL_UNIFORM_VS_BONE_MATRIX, + MODEL_UNIFORM_U_MATCAPS, + MODEL_UNIFORM_RESOLUTION, + MODEL_UNIFORM_HAS_TEX_SKYSPHERE, + MODEL_UNIFORM_HAS_TEX_SKYENV, + MODEL_UNIFORM_TEX_SKYSPHERE, + MODEL_UNIFORM_SKYSPHERE_MIP_COUNT, + MODEL_UNIFORM_TEX_SKYENV, + MODEL_UNIFORM_TEX_BRDF_LUT, + MODEL_UNIFORM_FRAME_COUNT, + + NUM_MODEL_UNIFORMS +}; + + typedef struct model_t { struct iqm_t *iqm; // private @@ -17632,6 +17660,7 @@ typedef struct model_t { handle *textures; char **texture_names; array(material_t) materials; + unsigned uniforms[NUM_MODEL_UNIFORMS]; texture_t sky_refl, sky_env; @@ -383318,6 +383347,30 @@ int shader_uniform(const char *name) { } unsigned shader_get_active() { return last_shader; } unsigned shader_bind(unsigned program) { if (program == last_shader) return last_shader; unsigned ret = last_shader; return glUseProgram(last_shader = program), ret; } +static inline void shader_int_(unsigned uniform, int i) { glUniform1i(uniform, i); } +static inline void shader_float_(unsigned uniform, float f) { glUniform1f(uniform, f); } +static inline void shader_vec2_(unsigned uniform, vec2 v) { glUniform2fv(uniform, 1, &v.x); } +static inline void shader_vec3_(unsigned uniform, vec3 v) { glUniform3fv(uniform, 1, &v.x); } +static inline void shader_vec3v_(unsigned uniform, int count, vec3 *v) { glUniform3fv(uniform, count, &v[0].x); } +static inline void shader_vec4_(unsigned uniform, vec4 v) { glUniform4fv(uniform, 1, &v.x); } +static inline void shader_mat44_(unsigned uniform, mat44 m) { glUniformMatrix4fv(uniform, 1, GL_FALSE/*GL_TRUE*/, m); } +static inline void shader_cubemap_(unsigned sampler, unsigned texture) { + int id = texture_unit(); + glUniform1i(sampler, id); + glActiveTexture(GL_TEXTURE0 + id); + glBindTexture(GL_TEXTURE_CUBE_MAP, texture); +} +static inline void shader_bool_(unsigned uniform, bool x) { glUniform1i(uniform, x); } +static inline void shader_uint_(unsigned uniform, unsigned x ) { glUniform1ui(uniform, x); } +static inline void shader_texture_unit_(unsigned sampler, unsigned id, unsigned unit) { + // @todo. if tex.h == 1 ? GL_TEXTURE_1D : GL_TEXTURE_2D + glUniform1i(sampler, unit); + glActiveTexture(GL_TEXTURE0 + unit); + glBindTexture(GL_TEXTURE_2D, id); +} +static inline void shader_texture_(unsigned sampler, texture_t t) { shader_texture_unit_(sampler, t.id, texture_unit()); } + +// public api void shader_int(const char *uniform, int i) { glUniform1i(shader_uniform(uniform), i); } void shader_float(const char *uniform, float f) { glUniform1f(shader_uniform(uniform), f); } void shader_vec2(const char *uniform, vec2 v) { glUniform2fv(shader_uniform(uniform), 1, &v.x); } @@ -385751,119 +385804,71 @@ void model_set_uniforms(model_t m, int shader, mat44 mv, mat44 proj, mat44 view, shader_bind(shader); int loc; //if( (loc = glGetUniformLocation(shader, "M")) >= 0 ) glUniformMatrix4fv( loc, 1, GL_FALSE/*GL_TRUE*/, m); // RIM - if( (loc = glGetUniformLocation(shader, "MV")) >= 0 ) { - glUniformMatrix4fv( loc, 1, GL_FALSE, mv); + if( (loc = m.uniforms[MODEL_UNIFORM_MV]) >= 0 ) { + shader_mat44_(loc, mv); } - else - if( (loc = glGetUniformLocation(shader, "u_mv")) >= 0 ) { - glUniformMatrix4fv( loc, 1, GL_FALSE, mv); - } - if( (loc = glGetUniformLocation(shader, "MVP")) >= 0 ) { + if( (loc = m.uniforms[MODEL_UNIFORM_MVP]) >= 0 ) { mat44 mvp; multiply44x2(mvp, proj, mv); // multiply44x3(mvp, proj, view, model); - glUniformMatrix4fv( loc, 1, GL_FALSE, mvp); + shader_mat44_(loc, mvp); } - else - if( (loc = glGetUniformLocation(shader, "u_mvp")) >= 0 ) { - mat44 mvp; multiply44x2(mvp, proj, mv); // multiply44x3(mvp, proj, view, model); - glUniformMatrix4fv( loc, 1, GL_FALSE, mvp); - } - if( (loc = glGetUniformLocation(shader, "VP")) >= 0 ) { + if( (loc = m.uniforms[MODEL_UNIFORM_VP]) >= 0 ) { mat44 vp; multiply44x2(vp, proj, view); - glUniformMatrix4fv( loc, 1, GL_FALSE, vp); + shader_mat44_(loc, vp); } - else - if( (loc = glGetUniformLocation(shader, "u_vp")) >= 0 ) { - mat44 vp; multiply44x2(vp, proj, view); - glUniformMatrix4fv( loc, 1, GL_FALSE, vp); - } - if( (loc = glGetUniformLocation(shader, "u_cam_pos")) >= 0 ) { + if( (loc = m.uniforms[MODEL_UNIFORM_CAM_POS]) >= 0 ) { vec3 pos = vec3(view[12], view[13], view[14]); - glUniform3fv( loc, 1, &pos.x ); + shader_vec3_(loc, pos); } - else - if( (loc = glGetUniformLocation(shader, "cam_pos")) >= 0 ) { - vec3 pos = vec3(view[12], view[13], view[14]); - glUniform3fv( loc, 1, &pos.x ); - } - if( (loc = glGetUniformLocation(shader, "u_cam_dir")) >= 0 ) { + if( (loc = m.uniforms[MODEL_UNIFORM_CAM_DIR]) >= 0 ) { vec3 dir = norm3(vec3(view[2], view[6], view[10])); - glUniform3fv( loc, 1, &dir.x ); + shader_vec3_(loc, dir); } - else - if( (loc = glGetUniformLocation(shader, "cam_dir")) >= 0 ) { - vec3 dir = norm3(vec3(view[2], view[6], view[10])); - glUniform3fv( loc, 1, &dir.x ); + if( (loc = m.uniforms[MODEL_UNIFORM_BILLBOARD]) >= 0 ) { + shader_int_(loc, m.billboard); } - if( (loc = glGetUniformLocation(shader, "billboard")) >= 0 ) { - glUniform1i( loc, m.billboard ); + if( (loc = m.uniforms[MODEL_UNIFORM_TEXLIT]) >= 0 ) { + shader_int_(loc, (m.lightmap.w != 0)); } - else - if( (loc = glGetUniformLocation(shader, "u_billboard")) >= 0 ) { - glUniform1i( loc, m.billboard ); + if ((loc = m.uniforms[MODEL_UNIFORM_MODEL]) >= 0) { + shader_mat44_(loc, model); } - if( (loc = glGetUniformLocation(shader, "texlit")) >= 0 ) { - glUniform1i( loc, (m.lightmap.w != 0) ); + if ((loc = m.uniforms[MODEL_UNIFORM_VIEW]) >= 0) { + shader_mat44_(loc, view); } - else - if( (loc = glGetUniformLocation(shader, "u_texlit")) >= 0 ) { - glUniform1i( loc, (m.lightmap.w != 0) ); - } -#if 0 - // @todo: mat44 projview (useful?) -#endif - if ((loc = glGetUniformLocation(shader, "M")) >= 0) { - glUniformMatrix4fv(loc, 1, GL_FALSE, model); - } - else - if ((loc = glGetUniformLocation(shader, "model")) >= 0) { - glUniformMatrix4fv(loc, 1, GL_FALSE, model); - } - if ((loc = glGetUniformLocation(shader, "V")) >= 0) { - glUniformMatrix4fv(loc, 1, GL_FALSE, view); - } - else - if ((loc = glGetUniformLocation(shader, "view")) >= 0) { - glUniformMatrix4fv(loc, 1, GL_FALSE, view); - } - if ((loc = glGetUniformLocation(shader, "inv_view")) >= 0) { + if ((loc = m.uniforms[MODEL_UNIFORM_INV_VIEW]) >= 0) { mat44 inv_view; - invert44( inv_view, view); - glUniformMatrix4fv(loc, 1, GL_FALSE, inv_view); + invert44(inv_view, view); + shader_mat44_(loc, inv_view); } - if ((loc = glGetUniformLocation(shader, "P")) >= 0) { - glUniformMatrix4fv(loc, 1, GL_FALSE, proj); + if ((loc = m.uniforms[MODEL_UNIFORM_PROJ]) >= 0) { + shader_mat44_(loc, proj); } - else - if ((loc = glGetUniformLocation(shader, "proj")) >= 0) { - glUniformMatrix4fv(loc, 1, GL_FALSE, proj); - } - if( (loc = glGetUniformLocation(shader, "SKINNED")) >= 0 ) glUniform1i( loc, q->numanims ? GL_TRUE : GL_FALSE); + if( (loc = m.uniforms[MODEL_UNIFORM_SKINNED]) >= 0 ) shader_int_(loc, q->numanims ? GL_TRUE : GL_FALSE); if( q->numanims ) - if( (loc = glGetUniformLocation(shader, "vsBoneMatrix")) >= 0 ) glUniformMatrix3x4fv( loc, q->numjoints, GL_FALSE, q->outframe[0]); - - if ((loc = glGetUniformLocation(shader, "u_matcaps")) >= 0) { - glUniform1i(loc, m.flags & MODEL_MATCAPS ? GL_TRUE:GL_FALSE); + if( (loc = m.uniforms[MODEL_UNIFORM_VS_BONE_MATRIX]) >= 0 ) glUniformMatrix3x4fv( loc, q->numjoints, GL_FALSE, q->outframe[0]); + if ((loc = m.uniforms[MODEL_UNIFORM_U_MATCAPS]) >= 0) { + shader_int_(loc, m.flags & MODEL_MATCAPS ? GL_TRUE:GL_FALSE); } if (m.shading == SHADING_PBR) { handle old_shader = last_shader; shader_bind(shader); - shader_vec2( "resolution", vec2(window_width(),window_height())); + shader_vec2_( m.uniforms[MODEL_UNIFORM_RESOLUTION], vec2(window_width(),window_height())); bool has_tex_skysphere = m.sky_refl.id != texture_checker().id; bool has_tex_skyenv = m.sky_env.id != texture_checker().id; - shader_bool( "has_tex_skysphere", has_tex_skysphere ); - shader_bool( "has_tex_skyenv", has_tex_skyenv ); + shader_bool_( m.uniforms[MODEL_UNIFORM_HAS_TEX_SKYSPHERE], has_tex_skysphere ); + shader_bool_( m.uniforms[MODEL_UNIFORM_HAS_TEX_SKYENV], has_tex_skyenv ); if( has_tex_skysphere ) { float mipCount = floor( log2( max(m.sky_refl.w, m.sky_refl.h) ) ); - shader_texture("tex_skysphere", m.sky_refl); - shader_float( "skysphere_mip_count", mipCount ); + shader_texture_(m.uniforms[MODEL_UNIFORM_TEX_SKYSPHERE], m.sky_refl); + shader_float_( m.uniforms[MODEL_UNIFORM_SKYSPHERE_MIP_COUNT], mipCount ); } if( has_tex_skyenv ) { - shader_texture( "tex_skyenv", m.sky_env ); + shader_texture_( m.uniforms[MODEL_UNIFORM_TEX_SKYENV], m.sky_env ); } - shader_texture( "tex_brdf_lut", brdf_lut() ); - shader_uint( "frame_count", (unsigned)window_frame() ); + shader_texture_( m.uniforms[MODEL_UNIFORM_TEX_BRDF_LUT], brdf_lut() ); + shader_uint_( m.uniforms[MODEL_UNIFORM_FRAME_COUNT], (unsigned)window_frame() ); shader_bind(old_shader); } } @@ -386724,6 +386729,63 @@ void model_render(model_t m, mat44 proj, mat44 view, mat44 model, int shader) { model_render_instanced(m, proj, view, (mat44*)model, shader, 1); } +static inline +void model_init_uniforms(model_t *m) { + unsigned shader = m->program; + if (glGetUniformLocation(shader, "u_mv") >= 0) + m->uniforms[MODEL_UNIFORM_MV] = glGetUniformLocation(shader, "u_mv"); + else + m->uniforms[MODEL_UNIFORM_MV] = glGetUniformLocation(shader, "MV"); + if (glGetUniformLocation(shader, "u_mvp") >= 0) + m->uniforms[MODEL_UNIFORM_MVP] = glGetUniformLocation(shader, "u_mvp"); + else + m->uniforms[MODEL_UNIFORM_MVP] = glGetUniformLocation(shader, "MVP"); + if (glGetUniformLocation(shader, "u_vp") >= 0) + m->uniforms[MODEL_UNIFORM_VP] = glGetUniformLocation(shader, "u_vp"); + else + m->uniforms[MODEL_UNIFORM_VP] = glGetUniformLocation(shader, "VP"); + if (glGetUniformLocation(shader, "u_cam_pos") >= 0) + m->uniforms[MODEL_UNIFORM_CAM_POS] = glGetUniformLocation(shader, "u_cam_pos"); + else + m->uniforms[MODEL_UNIFORM_CAM_POS] = glGetUniformLocation(shader, "cam_pos"); + if (glGetUniformLocation(shader, "u_cam_dir") >= 0) + m->uniforms[MODEL_UNIFORM_CAM_DIR] = glGetUniformLocation(shader, "u_cam_dir"); + else + m->uniforms[MODEL_UNIFORM_CAM_DIR] = glGetUniformLocation(shader, "cam_dir"); + if (glGetUniformLocation(shader, "u_billboard") >= 0) + m->uniforms[MODEL_UNIFORM_BILLBOARD] = glGetUniformLocation(shader, "u_billboard"); + else + m->uniforms[MODEL_UNIFORM_BILLBOARD] = glGetUniformLocation(shader, "billboard"); + if (glGetUniformLocation(shader, "u_texlit") >= 0) + m->uniforms[MODEL_UNIFORM_TEXLIT] = glGetUniformLocation(shader, "u_texlit"); + else + m->uniforms[MODEL_UNIFORM_TEXLIT] = glGetUniformLocation(shader, "texlit"); + if (glGetUniformLocation(shader, "M") >= 0) + m->uniforms[MODEL_UNIFORM_MODEL] = glGetUniformLocation(shader, "M"); + else + m->uniforms[MODEL_UNIFORM_MODEL] = glGetUniformLocation(shader, "model"); + if (glGetUniformLocation(shader, "V") >= 0) + m->uniforms[MODEL_UNIFORM_VIEW] = glGetUniformLocation(shader, "V"); + else + m->uniforms[MODEL_UNIFORM_VIEW] = glGetUniformLocation(shader, "view"); + m->uniforms[MODEL_UNIFORM_INV_VIEW] = glGetUniformLocation(shader, "inv_view"); + if (glGetUniformLocation(shader, "P") >= 0) + m->uniforms[MODEL_UNIFORM_PROJ] = glGetUniformLocation(shader, "P"); + else + m->uniforms[MODEL_UNIFORM_PROJ] = glGetUniformLocation(shader, "proj"); + m->uniforms[MODEL_UNIFORM_SKINNED] = glGetUniformLocation(shader, "SKINNED"); + m->uniforms[MODEL_UNIFORM_VS_BONE_MATRIX] = glGetUniformLocation(shader, "vsBoneMatrix"); + m->uniforms[MODEL_UNIFORM_U_MATCAPS] = glGetUniformLocation(shader, "u_matcaps"); + m->uniforms[MODEL_UNIFORM_HAS_TEX_SKYSPHERE] = glGetUniformLocation(shader, "has_tex_skysphere"); + m->uniforms[MODEL_UNIFORM_HAS_TEX_SKYENV] = glGetUniformLocation(shader, "has_tex_skyenv"); + m->uniforms[MODEL_UNIFORM_TEX_SKYSPHERE] = glGetUniformLocation(shader, "tex_skysphere"); + m->uniforms[MODEL_UNIFORM_SKYSPHERE_MIP_COUNT] = glGetUniformLocation(shader, "skysphere_mip_count"); + m->uniforms[MODEL_UNIFORM_TEX_SKYENV] = glGetUniformLocation(shader, "tex_skyenv"); + m->uniforms[MODEL_UNIFORM_TEX_BRDF_LUT] = glGetUniformLocation(shader, "tex_brdf_lut"); + m->uniforms[MODEL_UNIFORM_FRAME_COUNT] = glGetUniformLocation(shader, "frame_count"); + m->uniforms[MODEL_UNIFORM_RESOLUTION] = glGetUniformLocation(shader, "resolution"); +} + void model_shading(model_t *m, int shading) { m->shading = shading; int flags = m->stored_flags; @@ -386744,6 +386806,7 @@ void model_shading(model_t *m, int shading) { "att_position,att_texcoord,att_normal,att_tangent,att_instanced_matrix,,,,att_indexes,att_weights,att_vertexindex,att_color,att_bitangent,att_texcoord2","fragColor", va("%s,%s", shading == SHADING_PBR ? "SHADING_PBR" : "SHADING_PHONG", (flags&MODEL_RIMLIGHT)?"RIM":"")); m->program = shaderprog; + model_init_uniforms(m); } void model_skybox(model_t *mdl, skybox_t sky, bool load_sh) { diff --git a/engine/split/v4k_render.c b/engine/split/v4k_render.c index 531f89f..653019f 100644 --- a/engine/split/v4k_render.c +++ b/engine/split/v4k_render.c @@ -713,6 +713,30 @@ int shader_uniform(const char *name) { } unsigned shader_get_active() { return last_shader; } unsigned shader_bind(unsigned program) { if (program == last_shader) return last_shader; unsigned ret = last_shader; return glUseProgram(last_shader = program), ret; } +static inline void shader_int_(unsigned uniform, int i) { glUniform1i(uniform, i); } +static inline void shader_float_(unsigned uniform, float f) { glUniform1f(uniform, f); } +static inline void shader_vec2_(unsigned uniform, vec2 v) { glUniform2fv(uniform, 1, &v.x); } +static inline void shader_vec3_(unsigned uniform, vec3 v) { glUniform3fv(uniform, 1, &v.x); } +static inline void shader_vec3v_(unsigned uniform, int count, vec3 *v) { glUniform3fv(uniform, count, &v[0].x); } +static inline void shader_vec4_(unsigned uniform, vec4 v) { glUniform4fv(uniform, 1, &v.x); } +static inline void shader_mat44_(unsigned uniform, mat44 m) { glUniformMatrix4fv(uniform, 1, GL_FALSE/*GL_TRUE*/, m); } +static inline void shader_cubemap_(unsigned sampler, unsigned texture) { + int id = texture_unit(); + glUniform1i(sampler, id); + glActiveTexture(GL_TEXTURE0 + id); + glBindTexture(GL_TEXTURE_CUBE_MAP, texture); +} +static inline void shader_bool_(unsigned uniform, bool x) { glUniform1i(uniform, x); } +static inline void shader_uint_(unsigned uniform, unsigned x ) { glUniform1ui(uniform, x); } +static inline void shader_texture_unit_(unsigned sampler, unsigned id, unsigned unit) { + // @todo. if tex.h == 1 ? GL_TEXTURE_1D : GL_TEXTURE_2D + glUniform1i(sampler, unit); + glActiveTexture(GL_TEXTURE0 + unit); + glBindTexture(GL_TEXTURE_2D, id); +} +static inline void shader_texture_(unsigned sampler, texture_t t) { shader_texture_unit_(sampler, t.id, texture_unit()); } + +// public api void shader_int(const char *uniform, int i) { glUniform1i(shader_uniform(uniform), i); } void shader_float(const char *uniform, float f) { glUniform1f(shader_uniform(uniform), f); } void shader_vec2(const char *uniform, vec2 v) { glUniform2fv(shader_uniform(uniform), 1, &v.x); } @@ -3146,119 +3170,71 @@ void model_set_uniforms(model_t m, int shader, mat44 mv, mat44 proj, mat44 view, shader_bind(shader); int loc; //if( (loc = glGetUniformLocation(shader, "M")) >= 0 ) glUniformMatrix4fv( loc, 1, GL_FALSE/*GL_TRUE*/, m); // RIM - if( (loc = glGetUniformLocation(shader, "MV")) >= 0 ) { - glUniformMatrix4fv( loc, 1, GL_FALSE, mv); + if( (loc = m.uniforms[MODEL_UNIFORM_MV]) >= 0 ) { + shader_mat44_(loc, mv); } - else - if( (loc = glGetUniformLocation(shader, "u_mv")) >= 0 ) { - glUniformMatrix4fv( loc, 1, GL_FALSE, mv); - } - if( (loc = glGetUniformLocation(shader, "MVP")) >= 0 ) { + if( (loc = m.uniforms[MODEL_UNIFORM_MVP]) >= 0 ) { mat44 mvp; multiply44x2(mvp, proj, mv); // multiply44x3(mvp, proj, view, model); - glUniformMatrix4fv( loc, 1, GL_FALSE, mvp); + shader_mat44_(loc, mvp); } - else - if( (loc = glGetUniformLocation(shader, "u_mvp")) >= 0 ) { - mat44 mvp; multiply44x2(mvp, proj, mv); // multiply44x3(mvp, proj, view, model); - glUniformMatrix4fv( loc, 1, GL_FALSE, mvp); - } - if( (loc = glGetUniformLocation(shader, "VP")) >= 0 ) { + if( (loc = m.uniforms[MODEL_UNIFORM_VP]) >= 0 ) { mat44 vp; multiply44x2(vp, proj, view); - glUniformMatrix4fv( loc, 1, GL_FALSE, vp); + shader_mat44_(loc, vp); } - else - if( (loc = glGetUniformLocation(shader, "u_vp")) >= 0 ) { - mat44 vp; multiply44x2(vp, proj, view); - glUniformMatrix4fv( loc, 1, GL_FALSE, vp); - } - if( (loc = glGetUniformLocation(shader, "u_cam_pos")) >= 0 ) { + if( (loc = m.uniforms[MODEL_UNIFORM_CAM_POS]) >= 0 ) { vec3 pos = vec3(view[12], view[13], view[14]); - glUniform3fv( loc, 1, &pos.x ); + shader_vec3_(loc, pos); } - else - if( (loc = glGetUniformLocation(shader, "cam_pos")) >= 0 ) { - vec3 pos = vec3(view[12], view[13], view[14]); - glUniform3fv( loc, 1, &pos.x ); - } - if( (loc = glGetUniformLocation(shader, "u_cam_dir")) >= 0 ) { + if( (loc = m.uniforms[MODEL_UNIFORM_CAM_DIR]) >= 0 ) { vec3 dir = norm3(vec3(view[2], view[6], view[10])); - glUniform3fv( loc, 1, &dir.x ); + shader_vec3_(loc, dir); } - else - if( (loc = glGetUniformLocation(shader, "cam_dir")) >= 0 ) { - vec3 dir = norm3(vec3(view[2], view[6], view[10])); - glUniform3fv( loc, 1, &dir.x ); + if( (loc = m.uniforms[MODEL_UNIFORM_BILLBOARD]) >= 0 ) { + shader_int_(loc, m.billboard); } - if( (loc = glGetUniformLocation(shader, "billboard")) >= 0 ) { - glUniform1i( loc, m.billboard ); + if( (loc = m.uniforms[MODEL_UNIFORM_TEXLIT]) >= 0 ) { + shader_int_(loc, (m.lightmap.w != 0)); } - else - if( (loc = glGetUniformLocation(shader, "u_billboard")) >= 0 ) { - glUniform1i( loc, m.billboard ); + if ((loc = m.uniforms[MODEL_UNIFORM_MODEL]) >= 0) { + shader_mat44_(loc, model); } - if( (loc = glGetUniformLocation(shader, "texlit")) >= 0 ) { - glUniform1i( loc, (m.lightmap.w != 0) ); + if ((loc = m.uniforms[MODEL_UNIFORM_VIEW]) >= 0) { + shader_mat44_(loc, view); } - else - if( (loc = glGetUniformLocation(shader, "u_texlit")) >= 0 ) { - glUniform1i( loc, (m.lightmap.w != 0) ); - } -#if 0 - // @todo: mat44 projview (useful?) -#endif - if ((loc = glGetUniformLocation(shader, "M")) >= 0) { - glUniformMatrix4fv(loc, 1, GL_FALSE, model); - } - else - if ((loc = glGetUniformLocation(shader, "model")) >= 0) { - glUniformMatrix4fv(loc, 1, GL_FALSE, model); - } - if ((loc = glGetUniformLocation(shader, "V")) >= 0) { - glUniformMatrix4fv(loc, 1, GL_FALSE, view); - } - else - if ((loc = glGetUniformLocation(shader, "view")) >= 0) { - glUniformMatrix4fv(loc, 1, GL_FALSE, view); - } - if ((loc = glGetUniformLocation(shader, "inv_view")) >= 0) { + if ((loc = m.uniforms[MODEL_UNIFORM_INV_VIEW]) >= 0) { mat44 inv_view; - invert44( inv_view, view); - glUniformMatrix4fv(loc, 1, GL_FALSE, inv_view); + invert44(inv_view, view); + shader_mat44_(loc, inv_view); } - if ((loc = glGetUniformLocation(shader, "P")) >= 0) { - glUniformMatrix4fv(loc, 1, GL_FALSE, proj); + if ((loc = m.uniforms[MODEL_UNIFORM_PROJ]) >= 0) { + shader_mat44_(loc, proj); } - else - if ((loc = glGetUniformLocation(shader, "proj")) >= 0) { - glUniformMatrix4fv(loc, 1, GL_FALSE, proj); - } - if( (loc = glGetUniformLocation(shader, "SKINNED")) >= 0 ) glUniform1i( loc, q->numanims ? GL_TRUE : GL_FALSE); + if( (loc = m.uniforms[MODEL_UNIFORM_SKINNED]) >= 0 ) shader_int_(loc, q->numanims ? GL_TRUE : GL_FALSE); if( q->numanims ) - if( (loc = glGetUniformLocation(shader, "vsBoneMatrix")) >= 0 ) glUniformMatrix3x4fv( loc, q->numjoints, GL_FALSE, q->outframe[0]); - - if ((loc = glGetUniformLocation(shader, "u_matcaps")) >= 0) { - glUniform1i(loc, m.flags & MODEL_MATCAPS ? GL_TRUE:GL_FALSE); + if( (loc = m.uniforms[MODEL_UNIFORM_VS_BONE_MATRIX]) >= 0 ) glUniformMatrix3x4fv( loc, q->numjoints, GL_FALSE, q->outframe[0]); + if ((loc = m.uniforms[MODEL_UNIFORM_U_MATCAPS]) >= 0) { + shader_int_(loc, m.flags & MODEL_MATCAPS ? GL_TRUE:GL_FALSE); } if (m.shading == SHADING_PBR) { handle old_shader = last_shader; shader_bind(shader); - shader_vec2( "resolution", vec2(window_width(),window_height())); + shader_vec2_( m.uniforms[MODEL_UNIFORM_RESOLUTION], vec2(window_width(),window_height())); bool has_tex_skysphere = m.sky_refl.id != texture_checker().id; bool has_tex_skyenv = m.sky_env.id != texture_checker().id; - shader_bool( "has_tex_skysphere", has_tex_skysphere ); - shader_bool( "has_tex_skyenv", has_tex_skyenv ); + shader_bool_( m.uniforms[MODEL_UNIFORM_HAS_TEX_SKYSPHERE], has_tex_skysphere ); + shader_bool_( m.uniforms[MODEL_UNIFORM_HAS_TEX_SKYENV], has_tex_skyenv ); if( has_tex_skysphere ) { float mipCount = floor( log2( max(m.sky_refl.w, m.sky_refl.h) ) ); - shader_texture("tex_skysphere", m.sky_refl); - shader_float( "skysphere_mip_count", mipCount ); + shader_texture_(m.uniforms[MODEL_UNIFORM_TEX_SKYSPHERE], m.sky_refl); + shader_float_( m.uniforms[MODEL_UNIFORM_SKYSPHERE_MIP_COUNT], mipCount ); } if( has_tex_skyenv ) { - shader_texture( "tex_skyenv", m.sky_env ); + shader_texture_( m.uniforms[MODEL_UNIFORM_TEX_SKYENV], m.sky_env ); } - shader_texture( "tex_brdf_lut", brdf_lut() ); - shader_uint( "frame_count", (unsigned)window_frame() ); + shader_texture_( m.uniforms[MODEL_UNIFORM_TEX_BRDF_LUT], brdf_lut() ); + shader_uint_( m.uniforms[MODEL_UNIFORM_FRAME_COUNT], (unsigned)window_frame() ); shader_bind(old_shader); } } @@ -4119,6 +4095,63 @@ void model_render(model_t m, mat44 proj, mat44 view, mat44 model, int shader) { model_render_instanced(m, proj, view, (mat44*)model, shader, 1); } +static inline +void model_init_uniforms(model_t *m) { + unsigned shader = m->program; + if (glGetUniformLocation(shader, "u_mv") >= 0) + m->uniforms[MODEL_UNIFORM_MV] = glGetUniformLocation(shader, "u_mv"); + else + m->uniforms[MODEL_UNIFORM_MV] = glGetUniformLocation(shader, "MV"); + if (glGetUniformLocation(shader, "u_mvp") >= 0) + m->uniforms[MODEL_UNIFORM_MVP] = glGetUniformLocation(shader, "u_mvp"); + else + m->uniforms[MODEL_UNIFORM_MVP] = glGetUniformLocation(shader, "MVP"); + if (glGetUniformLocation(shader, "u_vp") >= 0) + m->uniforms[MODEL_UNIFORM_VP] = glGetUniformLocation(shader, "u_vp"); + else + m->uniforms[MODEL_UNIFORM_VP] = glGetUniformLocation(shader, "VP"); + if (glGetUniformLocation(shader, "u_cam_pos") >= 0) + m->uniforms[MODEL_UNIFORM_CAM_POS] = glGetUniformLocation(shader, "u_cam_pos"); + else + m->uniforms[MODEL_UNIFORM_CAM_POS] = glGetUniformLocation(shader, "cam_pos"); + if (glGetUniformLocation(shader, "u_cam_dir") >= 0) + m->uniforms[MODEL_UNIFORM_CAM_DIR] = glGetUniformLocation(shader, "u_cam_dir"); + else + m->uniforms[MODEL_UNIFORM_CAM_DIR] = glGetUniformLocation(shader, "cam_dir"); + if (glGetUniformLocation(shader, "u_billboard") >= 0) + m->uniforms[MODEL_UNIFORM_BILLBOARD] = glGetUniformLocation(shader, "u_billboard"); + else + m->uniforms[MODEL_UNIFORM_BILLBOARD] = glGetUniformLocation(shader, "billboard"); + if (glGetUniformLocation(shader, "u_texlit") >= 0) + m->uniforms[MODEL_UNIFORM_TEXLIT] = glGetUniformLocation(shader, "u_texlit"); + else + m->uniforms[MODEL_UNIFORM_TEXLIT] = glGetUniformLocation(shader, "texlit"); + if (glGetUniformLocation(shader, "M") >= 0) + m->uniforms[MODEL_UNIFORM_MODEL] = glGetUniformLocation(shader, "M"); + else + m->uniforms[MODEL_UNIFORM_MODEL] = glGetUniformLocation(shader, "model"); + if (glGetUniformLocation(shader, "V") >= 0) + m->uniforms[MODEL_UNIFORM_VIEW] = glGetUniformLocation(shader, "V"); + else + m->uniforms[MODEL_UNIFORM_VIEW] = glGetUniformLocation(shader, "view"); + m->uniforms[MODEL_UNIFORM_INV_VIEW] = glGetUniformLocation(shader, "inv_view"); + if (glGetUniformLocation(shader, "P") >= 0) + m->uniforms[MODEL_UNIFORM_PROJ] = glGetUniformLocation(shader, "P"); + else + m->uniforms[MODEL_UNIFORM_PROJ] = glGetUniformLocation(shader, "proj"); + m->uniforms[MODEL_UNIFORM_SKINNED] = glGetUniformLocation(shader, "SKINNED"); + m->uniforms[MODEL_UNIFORM_VS_BONE_MATRIX] = glGetUniformLocation(shader, "vsBoneMatrix"); + m->uniforms[MODEL_UNIFORM_U_MATCAPS] = glGetUniformLocation(shader, "u_matcaps"); + m->uniforms[MODEL_UNIFORM_HAS_TEX_SKYSPHERE] = glGetUniformLocation(shader, "has_tex_skysphere"); + m->uniforms[MODEL_UNIFORM_HAS_TEX_SKYENV] = glGetUniformLocation(shader, "has_tex_skyenv"); + m->uniforms[MODEL_UNIFORM_TEX_SKYSPHERE] = glGetUniformLocation(shader, "tex_skysphere"); + m->uniforms[MODEL_UNIFORM_SKYSPHERE_MIP_COUNT] = glGetUniformLocation(shader, "skysphere_mip_count"); + m->uniforms[MODEL_UNIFORM_TEX_SKYENV] = glGetUniformLocation(shader, "tex_skyenv"); + m->uniforms[MODEL_UNIFORM_TEX_BRDF_LUT] = glGetUniformLocation(shader, "tex_brdf_lut"); + m->uniforms[MODEL_UNIFORM_FRAME_COUNT] = glGetUniformLocation(shader, "frame_count"); + m->uniforms[MODEL_UNIFORM_RESOLUTION] = glGetUniformLocation(shader, "resolution"); +} + void model_shading(model_t *m, int shading) { m->shading = shading; int flags = m->stored_flags; @@ -4139,6 +4172,7 @@ void model_shading(model_t *m, int shading) { "att_position,att_texcoord,att_normal,att_tangent,att_instanced_matrix,,,,att_indexes,att_weights,att_vertexindex,att_color,att_bitangent,att_texcoord2","fragColor", va("%s,%s", shading == SHADING_PBR ? "SHADING_PBR" : "SHADING_PHONG", (flags&MODEL_RIMLIGHT)?"RIM":"")); m->program = shaderprog; + model_init_uniforms(m); } void model_skybox(model_t *mdl, skybox_t sky, bool load_sh) { diff --git a/engine/split/v4k_render.h b/engine/split/v4k_render.h index 4f24986..aa644cf 100644 --- a/engine/split/v4k_render.h +++ b/engine/split/v4k_render.h @@ -602,6 +602,34 @@ enum RENDER_PASS { NUM_RENDER_PASSES }; +enum MODEL_UNIFORMS { + MODEL_UNIFORM_MV, + MODEL_UNIFORM_MVP, + MODEL_UNIFORM_VP, + MODEL_UNIFORM_CAM_POS, + MODEL_UNIFORM_CAM_DIR, + MODEL_UNIFORM_BILLBOARD, + MODEL_UNIFORM_TEXLIT, + MODEL_UNIFORM_MODEL, + MODEL_UNIFORM_VIEW, + MODEL_UNIFORM_INV_VIEW, + MODEL_UNIFORM_PROJ, + MODEL_UNIFORM_SKINNED, + MODEL_UNIFORM_VS_BONE_MATRIX, + MODEL_UNIFORM_U_MATCAPS, + MODEL_UNIFORM_RESOLUTION, + MODEL_UNIFORM_HAS_TEX_SKYSPHERE, + MODEL_UNIFORM_HAS_TEX_SKYENV, + MODEL_UNIFORM_TEX_SKYSPHERE, + MODEL_UNIFORM_SKYSPHERE_MIP_COUNT, + MODEL_UNIFORM_TEX_SKYENV, + MODEL_UNIFORM_TEX_BRDF_LUT, + MODEL_UNIFORM_FRAME_COUNT, + + NUM_MODEL_UNIFORMS +}; + + typedef struct model_t { struct iqm_t *iqm; // private @@ -610,6 +638,7 @@ typedef struct model_t { handle *textures; char **texture_names; array(material_t) materials; + unsigned uniforms[NUM_MODEL_UNIFORMS]; texture_t sky_refl, sky_env; diff --git a/engine/v4k.c b/engine/v4k.c index 4361fda..73be7ea 100644 --- a/engine/v4k.c +++ b/engine/v4k.c @@ -17887,6 +17887,30 @@ int shader_uniform(const char *name) { } unsigned shader_get_active() { return last_shader; } unsigned shader_bind(unsigned program) { if (program == last_shader) return last_shader; unsigned ret = last_shader; return glUseProgram(last_shader = program), ret; } +static inline void shader_int_(unsigned uniform, int i) { glUniform1i(uniform, i); } +static inline void shader_float_(unsigned uniform, float f) { glUniform1f(uniform, f); } +static inline void shader_vec2_(unsigned uniform, vec2 v) { glUniform2fv(uniform, 1, &v.x); } +static inline void shader_vec3_(unsigned uniform, vec3 v) { glUniform3fv(uniform, 1, &v.x); } +static inline void shader_vec3v_(unsigned uniform, int count, vec3 *v) { glUniform3fv(uniform, count, &v[0].x); } +static inline void shader_vec4_(unsigned uniform, vec4 v) { glUniform4fv(uniform, 1, &v.x); } +static inline void shader_mat44_(unsigned uniform, mat44 m) { glUniformMatrix4fv(uniform, 1, GL_FALSE/*GL_TRUE*/, m); } +static inline void shader_cubemap_(unsigned sampler, unsigned texture) { + int id = texture_unit(); + glUniform1i(sampler, id); + glActiveTexture(GL_TEXTURE0 + id); + glBindTexture(GL_TEXTURE_CUBE_MAP, texture); +} +static inline void shader_bool_(unsigned uniform, bool x) { glUniform1i(uniform, x); } +static inline void shader_uint_(unsigned uniform, unsigned x ) { glUniform1ui(uniform, x); } +static inline void shader_texture_unit_(unsigned sampler, unsigned id, unsigned unit) { + // @todo. if tex.h == 1 ? GL_TEXTURE_1D : GL_TEXTURE_2D + glUniform1i(sampler, unit); + glActiveTexture(GL_TEXTURE0 + unit); + glBindTexture(GL_TEXTURE_2D, id); +} +static inline void shader_texture_(unsigned sampler, texture_t t) { shader_texture_unit_(sampler, t.id, texture_unit()); } + +// public api void shader_int(const char *uniform, int i) { glUniform1i(shader_uniform(uniform), i); } void shader_float(const char *uniform, float f) { glUniform1f(shader_uniform(uniform), f); } void shader_vec2(const char *uniform, vec2 v) { glUniform2fv(shader_uniform(uniform), 1, &v.x); } @@ -20320,119 +20344,71 @@ void model_set_uniforms(model_t m, int shader, mat44 mv, mat44 proj, mat44 view, shader_bind(shader); int loc; //if( (loc = glGetUniformLocation(shader, "M")) >= 0 ) glUniformMatrix4fv( loc, 1, GL_FALSE/*GL_TRUE*/, m); // RIM - if( (loc = glGetUniformLocation(shader, "MV")) >= 0 ) { - glUniformMatrix4fv( loc, 1, GL_FALSE, mv); + if( (loc = m.uniforms[MODEL_UNIFORM_MV]) >= 0 ) { + shader_mat44_(loc, mv); } - else - if( (loc = glGetUniformLocation(shader, "u_mv")) >= 0 ) { - glUniformMatrix4fv( loc, 1, GL_FALSE, mv); - } - if( (loc = glGetUniformLocation(shader, "MVP")) >= 0 ) { + if( (loc = m.uniforms[MODEL_UNIFORM_MVP]) >= 0 ) { mat44 mvp; multiply44x2(mvp, proj, mv); // multiply44x3(mvp, proj, view, model); - glUniformMatrix4fv( loc, 1, GL_FALSE, mvp); + shader_mat44_(loc, mvp); } - else - if( (loc = glGetUniformLocation(shader, "u_mvp")) >= 0 ) { - mat44 mvp; multiply44x2(mvp, proj, mv); // multiply44x3(mvp, proj, view, model); - glUniformMatrix4fv( loc, 1, GL_FALSE, mvp); - } - if( (loc = glGetUniformLocation(shader, "VP")) >= 0 ) { + if( (loc = m.uniforms[MODEL_UNIFORM_VP]) >= 0 ) { mat44 vp; multiply44x2(vp, proj, view); - glUniformMatrix4fv( loc, 1, GL_FALSE, vp); + shader_mat44_(loc, vp); } - else - if( (loc = glGetUniformLocation(shader, "u_vp")) >= 0 ) { - mat44 vp; multiply44x2(vp, proj, view); - glUniformMatrix4fv( loc, 1, GL_FALSE, vp); - } - if( (loc = glGetUniformLocation(shader, "u_cam_pos")) >= 0 ) { + if( (loc = m.uniforms[MODEL_UNIFORM_CAM_POS]) >= 0 ) { vec3 pos = vec3(view[12], view[13], view[14]); - glUniform3fv( loc, 1, &pos.x ); + shader_vec3_(loc, pos); } - else - if( (loc = glGetUniformLocation(shader, "cam_pos")) >= 0 ) { - vec3 pos = vec3(view[12], view[13], view[14]); - glUniform3fv( loc, 1, &pos.x ); - } - if( (loc = glGetUniformLocation(shader, "u_cam_dir")) >= 0 ) { + if( (loc = m.uniforms[MODEL_UNIFORM_CAM_DIR]) >= 0 ) { vec3 dir = norm3(vec3(view[2], view[6], view[10])); - glUniform3fv( loc, 1, &dir.x ); + shader_vec3_(loc, dir); } - else - if( (loc = glGetUniformLocation(shader, "cam_dir")) >= 0 ) { - vec3 dir = norm3(vec3(view[2], view[6], view[10])); - glUniform3fv( loc, 1, &dir.x ); + if( (loc = m.uniforms[MODEL_UNIFORM_BILLBOARD]) >= 0 ) { + shader_int_(loc, m.billboard); } - if( (loc = glGetUniformLocation(shader, "billboard")) >= 0 ) { - glUniform1i( loc, m.billboard ); + if( (loc = m.uniforms[MODEL_UNIFORM_TEXLIT]) >= 0 ) { + shader_int_(loc, (m.lightmap.w != 0)); } - else - if( (loc = glGetUniformLocation(shader, "u_billboard")) >= 0 ) { - glUniform1i( loc, m.billboard ); + if ((loc = m.uniforms[MODEL_UNIFORM_MODEL]) >= 0) { + shader_mat44_(loc, model); } - if( (loc = glGetUniformLocation(shader, "texlit")) >= 0 ) { - glUniform1i( loc, (m.lightmap.w != 0) ); + if ((loc = m.uniforms[MODEL_UNIFORM_VIEW]) >= 0) { + shader_mat44_(loc, view); } - else - if( (loc = glGetUniformLocation(shader, "u_texlit")) >= 0 ) { - glUniform1i( loc, (m.lightmap.w != 0) ); - } -#if 0 - // @todo: mat44 projview (useful?) -#endif - if ((loc = glGetUniformLocation(shader, "M")) >= 0) { - glUniformMatrix4fv(loc, 1, GL_FALSE, model); - } - else - if ((loc = glGetUniformLocation(shader, "model")) >= 0) { - glUniformMatrix4fv(loc, 1, GL_FALSE, model); - } - if ((loc = glGetUniformLocation(shader, "V")) >= 0) { - glUniformMatrix4fv(loc, 1, GL_FALSE, view); - } - else - if ((loc = glGetUniformLocation(shader, "view")) >= 0) { - glUniformMatrix4fv(loc, 1, GL_FALSE, view); - } - if ((loc = glGetUniformLocation(shader, "inv_view")) >= 0) { + if ((loc = m.uniforms[MODEL_UNIFORM_INV_VIEW]) >= 0) { mat44 inv_view; - invert44( inv_view, view); - glUniformMatrix4fv(loc, 1, GL_FALSE, inv_view); + invert44(inv_view, view); + shader_mat44_(loc, inv_view); } - if ((loc = glGetUniformLocation(shader, "P")) >= 0) { - glUniformMatrix4fv(loc, 1, GL_FALSE, proj); + if ((loc = m.uniforms[MODEL_UNIFORM_PROJ]) >= 0) { + shader_mat44_(loc, proj); } - else - if ((loc = glGetUniformLocation(shader, "proj")) >= 0) { - glUniformMatrix4fv(loc, 1, GL_FALSE, proj); - } - if( (loc = glGetUniformLocation(shader, "SKINNED")) >= 0 ) glUniform1i( loc, q->numanims ? GL_TRUE : GL_FALSE); + if( (loc = m.uniforms[MODEL_UNIFORM_SKINNED]) >= 0 ) shader_int_(loc, q->numanims ? GL_TRUE : GL_FALSE); if( q->numanims ) - if( (loc = glGetUniformLocation(shader, "vsBoneMatrix")) >= 0 ) glUniformMatrix3x4fv( loc, q->numjoints, GL_FALSE, q->outframe[0]); - - if ((loc = glGetUniformLocation(shader, "u_matcaps")) >= 0) { - glUniform1i(loc, m.flags & MODEL_MATCAPS ? GL_TRUE:GL_FALSE); + if( (loc = m.uniforms[MODEL_UNIFORM_VS_BONE_MATRIX]) >= 0 ) glUniformMatrix3x4fv( loc, q->numjoints, GL_FALSE, q->outframe[0]); + if ((loc = m.uniforms[MODEL_UNIFORM_U_MATCAPS]) >= 0) { + shader_int_(loc, m.flags & MODEL_MATCAPS ? GL_TRUE:GL_FALSE); } if (m.shading == SHADING_PBR) { handle old_shader = last_shader; shader_bind(shader); - shader_vec2( "resolution", vec2(window_width(),window_height())); + shader_vec2_( m.uniforms[MODEL_UNIFORM_RESOLUTION], vec2(window_width(),window_height())); bool has_tex_skysphere = m.sky_refl.id != texture_checker().id; bool has_tex_skyenv = m.sky_env.id != texture_checker().id; - shader_bool( "has_tex_skysphere", has_tex_skysphere ); - shader_bool( "has_tex_skyenv", has_tex_skyenv ); + shader_bool_( m.uniforms[MODEL_UNIFORM_HAS_TEX_SKYSPHERE], has_tex_skysphere ); + shader_bool_( m.uniforms[MODEL_UNIFORM_HAS_TEX_SKYENV], has_tex_skyenv ); if( has_tex_skysphere ) { float mipCount = floor( log2( max(m.sky_refl.w, m.sky_refl.h) ) ); - shader_texture("tex_skysphere", m.sky_refl); - shader_float( "skysphere_mip_count", mipCount ); + shader_texture_(m.uniforms[MODEL_UNIFORM_TEX_SKYSPHERE], m.sky_refl); + shader_float_( m.uniforms[MODEL_UNIFORM_SKYSPHERE_MIP_COUNT], mipCount ); } if( has_tex_skyenv ) { - shader_texture( "tex_skyenv", m.sky_env ); + shader_texture_( m.uniforms[MODEL_UNIFORM_TEX_SKYENV], m.sky_env ); } - shader_texture( "tex_brdf_lut", brdf_lut() ); - shader_uint( "frame_count", (unsigned)window_frame() ); + shader_texture_( m.uniforms[MODEL_UNIFORM_TEX_BRDF_LUT], brdf_lut() ); + shader_uint_( m.uniforms[MODEL_UNIFORM_FRAME_COUNT], (unsigned)window_frame() ); shader_bind(old_shader); } } @@ -21293,6 +21269,63 @@ void model_render(model_t m, mat44 proj, mat44 view, mat44 model, int shader) { model_render_instanced(m, proj, view, (mat44*)model, shader, 1); } +static inline +void model_init_uniforms(model_t *m) { + unsigned shader = m->program; + if (glGetUniformLocation(shader, "u_mv") >= 0) + m->uniforms[MODEL_UNIFORM_MV] = glGetUniformLocation(shader, "u_mv"); + else + m->uniforms[MODEL_UNIFORM_MV] = glGetUniformLocation(shader, "MV"); + if (glGetUniformLocation(shader, "u_mvp") >= 0) + m->uniforms[MODEL_UNIFORM_MVP] = glGetUniformLocation(shader, "u_mvp"); + else + m->uniforms[MODEL_UNIFORM_MVP] = glGetUniformLocation(shader, "MVP"); + if (glGetUniformLocation(shader, "u_vp") >= 0) + m->uniforms[MODEL_UNIFORM_VP] = glGetUniformLocation(shader, "u_vp"); + else + m->uniforms[MODEL_UNIFORM_VP] = glGetUniformLocation(shader, "VP"); + if (glGetUniformLocation(shader, "u_cam_pos") >= 0) + m->uniforms[MODEL_UNIFORM_CAM_POS] = glGetUniformLocation(shader, "u_cam_pos"); + else + m->uniforms[MODEL_UNIFORM_CAM_POS] = glGetUniformLocation(shader, "cam_pos"); + if (glGetUniformLocation(shader, "u_cam_dir") >= 0) + m->uniforms[MODEL_UNIFORM_CAM_DIR] = glGetUniformLocation(shader, "u_cam_dir"); + else + m->uniforms[MODEL_UNIFORM_CAM_DIR] = glGetUniformLocation(shader, "cam_dir"); + if (glGetUniformLocation(shader, "u_billboard") >= 0) + m->uniforms[MODEL_UNIFORM_BILLBOARD] = glGetUniformLocation(shader, "u_billboard"); + else + m->uniforms[MODEL_UNIFORM_BILLBOARD] = glGetUniformLocation(shader, "billboard"); + if (glGetUniformLocation(shader, "u_texlit") >= 0) + m->uniforms[MODEL_UNIFORM_TEXLIT] = glGetUniformLocation(shader, "u_texlit"); + else + m->uniforms[MODEL_UNIFORM_TEXLIT] = glGetUniformLocation(shader, "texlit"); + if (glGetUniformLocation(shader, "M") >= 0) + m->uniforms[MODEL_UNIFORM_MODEL] = glGetUniformLocation(shader, "M"); + else + m->uniforms[MODEL_UNIFORM_MODEL] = glGetUniformLocation(shader, "model"); + if (glGetUniformLocation(shader, "V") >= 0) + m->uniforms[MODEL_UNIFORM_VIEW] = glGetUniformLocation(shader, "V"); + else + m->uniforms[MODEL_UNIFORM_VIEW] = glGetUniformLocation(shader, "view"); + m->uniforms[MODEL_UNIFORM_INV_VIEW] = glGetUniformLocation(shader, "inv_view"); + if (glGetUniformLocation(shader, "P") >= 0) + m->uniforms[MODEL_UNIFORM_PROJ] = glGetUniformLocation(shader, "P"); + else + m->uniforms[MODEL_UNIFORM_PROJ] = glGetUniformLocation(shader, "proj"); + m->uniforms[MODEL_UNIFORM_SKINNED] = glGetUniformLocation(shader, "SKINNED"); + m->uniforms[MODEL_UNIFORM_VS_BONE_MATRIX] = glGetUniformLocation(shader, "vsBoneMatrix"); + m->uniforms[MODEL_UNIFORM_U_MATCAPS] = glGetUniformLocation(shader, "u_matcaps"); + m->uniforms[MODEL_UNIFORM_HAS_TEX_SKYSPHERE] = glGetUniformLocation(shader, "has_tex_skysphere"); + m->uniforms[MODEL_UNIFORM_HAS_TEX_SKYENV] = glGetUniformLocation(shader, "has_tex_skyenv"); + m->uniforms[MODEL_UNIFORM_TEX_SKYSPHERE] = glGetUniformLocation(shader, "tex_skysphere"); + m->uniforms[MODEL_UNIFORM_SKYSPHERE_MIP_COUNT] = glGetUniformLocation(shader, "skysphere_mip_count"); + m->uniforms[MODEL_UNIFORM_TEX_SKYENV] = glGetUniformLocation(shader, "tex_skyenv"); + m->uniforms[MODEL_UNIFORM_TEX_BRDF_LUT] = glGetUniformLocation(shader, "tex_brdf_lut"); + m->uniforms[MODEL_UNIFORM_FRAME_COUNT] = glGetUniformLocation(shader, "frame_count"); + m->uniforms[MODEL_UNIFORM_RESOLUTION] = glGetUniformLocation(shader, "resolution"); +} + void model_shading(model_t *m, int shading) { m->shading = shading; int flags = m->stored_flags; @@ -21313,6 +21346,7 @@ void model_shading(model_t *m, int shading) { "att_position,att_texcoord,att_normal,att_tangent,att_instanced_matrix,,,,att_indexes,att_weights,att_vertexindex,att_color,att_bitangent,att_texcoord2","fragColor", va("%s,%s", shading == SHADING_PBR ? "SHADING_PBR" : "SHADING_PHONG", (flags&MODEL_RIMLIGHT)?"RIM":"")); m->program = shaderprog; + model_init_uniforms(m); } void model_skybox(model_t *mdl, skybox_t sky, bool load_sh) { diff --git a/engine/v4k.h b/engine/v4k.h index 938d1ad..82e7c26 100644 --- a/engine/v4k.h +++ b/engine/v4k.h @@ -3691,6 +3691,34 @@ enum RENDER_PASS { NUM_RENDER_PASSES }; +enum MODEL_UNIFORMS { + MODEL_UNIFORM_MV, + MODEL_UNIFORM_MVP, + MODEL_UNIFORM_VP, + MODEL_UNIFORM_CAM_POS, + MODEL_UNIFORM_CAM_DIR, + MODEL_UNIFORM_BILLBOARD, + MODEL_UNIFORM_TEXLIT, + MODEL_UNIFORM_MODEL, + MODEL_UNIFORM_VIEW, + MODEL_UNIFORM_INV_VIEW, + MODEL_UNIFORM_PROJ, + MODEL_UNIFORM_SKINNED, + MODEL_UNIFORM_VS_BONE_MATRIX, + MODEL_UNIFORM_U_MATCAPS, + MODEL_UNIFORM_RESOLUTION, + MODEL_UNIFORM_HAS_TEX_SKYSPHERE, + MODEL_UNIFORM_HAS_TEX_SKYENV, + MODEL_UNIFORM_TEX_SKYSPHERE, + MODEL_UNIFORM_SKYSPHERE_MIP_COUNT, + MODEL_UNIFORM_TEX_SKYENV, + MODEL_UNIFORM_TEX_BRDF_LUT, + MODEL_UNIFORM_FRAME_COUNT, + + NUM_MODEL_UNIFORMS +}; + + typedef struct model_t { struct iqm_t *iqm; // private @@ -3699,6 +3727,7 @@ typedef struct model_t { handle *textures; char **texture_names; array(material_t) materials; + unsigned uniforms[NUM_MODEL_UNIFORMS]; texture_t sky_refl, sky_env;