wip: frustum culling (per-model for now)
parent
d1cc36207f
commit
708629c80f
13
bind/v4k.lua
13
bind/v4k.lua
|
@ -1387,6 +1387,8 @@ typedef struct model_t {
|
||||||
int num_verts;
|
int num_verts;
|
||||||
void *tris;
|
void *tris;
|
||||||
vec3 *meshcenters;
|
vec3 *meshcenters;
|
||||||
|
aabb *meshbounds;
|
||||||
|
float *meshradii;
|
||||||
int num_tris;
|
int num_tris;
|
||||||
handle vao, ibo, vbo, vao_instanced;
|
handle vao, ibo, vbo, vao_instanced;
|
||||||
int* lod_collapse_map;
|
int* lod_collapse_map;
|
||||||
|
@ -1400,6 +1402,8 @@ typedef struct model_t {
|
||||||
unsigned num_instances;
|
unsigned num_instances;
|
||||||
int stored_flags;
|
int stored_flags;
|
||||||
renderstate_t rs[NUM_RENDER_PASSES];
|
renderstate_t rs[NUM_RENDER_PASSES];
|
||||||
|
bool frustum_enabled;
|
||||||
|
frustum frustum_state;
|
||||||
} model_t;
|
} model_t;
|
||||||
enum BILLBOARD_MODE {
|
enum BILLBOARD_MODE {
|
||||||
BILLBOARD_X = 0x1,
|
BILLBOARD_X = 0x1,
|
||||||
|
@ -1423,6 +1427,10 @@ enum BILLBOARD_MODE {
|
||||||
void model_render_instanced_pass(model_t m, mat44 proj, mat44 view, mat44* models, int shader, unsigned count, int pass);
|
void model_render_instanced_pass(model_t m, mat44 proj, mat44 view, mat44* models, int shader, unsigned count, int pass);
|
||||||
void model_render_pass(model_t m, mat44 proj, mat44 view, mat44 model, int shader, int pass);
|
void model_render_pass(model_t m, mat44 proj, mat44 view, mat44 model, int shader, int pass);
|
||||||
void model_set_texture(model_t*, texture_t t);
|
void model_set_texture(model_t*, texture_t t);
|
||||||
|
bool model_has_transparency_mesh(model_t m, int mesh);
|
||||||
|
bool model_has_transparency(model_t m);
|
||||||
|
void model_set_frustum(model_t *m, frustum f);
|
||||||
|
void model_clear_frustum(model_t *m);
|
||||||
bool model_get_bone_pose(model_t m, unsigned joint, mat34 *out);
|
bool model_get_bone_pose(model_t m, unsigned joint, mat34 *out);
|
||||||
void model_destroy(model_t);
|
void model_destroy(model_t);
|
||||||
unsigned model_getpass();
|
unsigned model_getpass();
|
||||||
|
@ -1555,6 +1563,11 @@ typedef struct object_t {
|
||||||
float anim_speed;
|
float anim_speed;
|
||||||
aabb bounds;
|
aabb bounds;
|
||||||
unsigned billboard;
|
unsigned billboard;
|
||||||
|
bool disable_frustum_check;
|
||||||
|
handle* old_texture_ids;
|
||||||
|
texture_t* old_textures;
|
||||||
|
float distance;
|
||||||
|
bool skip_draw;
|
||||||
bool light_cached;
|
bool light_cached;
|
||||||
} object_t;
|
} object_t;
|
||||||
object_t object();
|
object_t object();
|
||||||
|
|
|
@ -0,0 +1,58 @@
|
||||||
|
// render map
|
||||||
|
|
||||||
|
#include "v4k.h"
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
window_create(80, WINDOW_MSAA8);
|
||||||
|
window_title(__FILE__);
|
||||||
|
window_fps_unlock();
|
||||||
|
|
||||||
|
// load skybox
|
||||||
|
skybox_t sky = skybox("bridge3", 0);
|
||||||
|
|
||||||
|
// load static scene
|
||||||
|
model_t map, prop;
|
||||||
|
map = model(option("--model","sorting_test.obj"), 0); // MODEL_NO_TEXTURES);
|
||||||
|
prop = model(option("--model","sorting_test2.obj"), 0); // MODEL_NO_TEXTURES);
|
||||||
|
shader_bind(map.program);
|
||||||
|
skybox_sh_shader(&sky);
|
||||||
|
prop.program = map.program;
|
||||||
|
|
||||||
|
// define scene
|
||||||
|
object_t *prop_obj = scene_spawn();
|
||||||
|
object_model(prop_obj, prop);
|
||||||
|
|
||||||
|
object_t *map_obj = scene_spawn();
|
||||||
|
object_model(map_obj, map);
|
||||||
|
|
||||||
|
// camera
|
||||||
|
camera_t cam = camera();
|
||||||
|
cam.speed *= 0.05f;
|
||||||
|
|
||||||
|
// demo loop
|
||||||
|
while (window_swap())
|
||||||
|
{
|
||||||
|
// input
|
||||||
|
if( input_down(KEY_ESC) ) break;
|
||||||
|
if( input_down(KEY_F5) ) window_reload();
|
||||||
|
if( input_down(KEY_F11) ) window_fullscreen( window_has_fullscreen() ^ 1 );
|
||||||
|
if( input_down(KEY_X) ) window_screenshot(__FILE__ ".png");
|
||||||
|
if( input_down(KEY_Z) ) window_record(__FILE__ ".mp4");
|
||||||
|
|
||||||
|
// fps camera
|
||||||
|
bool active = ui_active() || ui_hover() || gizmo_active() ? false : input(MOUSE_L) || input(MOUSE_M) || input(MOUSE_R);
|
||||||
|
if( active ) cam.speed = clampf(cam.speed + input_diff(MOUSE_W) / 10, 0.05f, 5.0f);
|
||||||
|
vec2 mouse = scale2(vec2(input_diff(MOUSE_X), -input_diff(MOUSE_Y)), 0.2f * active);
|
||||||
|
vec3 wasdecq = scale3(vec3(input(KEY_D)-input(KEY_A),input(KEY_E)-(input(KEY_C)||input(KEY_Q)),input(KEY_W)-input(KEY_S)), cam.speed);
|
||||||
|
camera_moveby(&cam, wasdecq);
|
||||||
|
camera_fps(&cam, mouse.x,mouse.y);
|
||||||
|
window_cursor( !active );
|
||||||
|
|
||||||
|
// draw skybox
|
||||||
|
profile("Skybox") {
|
||||||
|
skybox_render(&sky, cam.proj, cam.view);
|
||||||
|
}
|
||||||
|
|
||||||
|
scene_render(SCENE_FOREGROUND);
|
||||||
|
}
|
||||||
|
}
|
|
@ -7,21 +7,14 @@ int main() {
|
||||||
window_title(__FILE__);
|
window_title(__FILE__);
|
||||||
window_fps_unlock();
|
window_fps_unlock();
|
||||||
|
|
||||||
// load all fx files
|
|
||||||
fx_load("fx**.fs");
|
|
||||||
|
|
||||||
// load skybox
|
// load skybox
|
||||||
// skybox_t sky = skybox(flag("--mie") ? 0 : "hdr/Tokyo_BigSight_1k.hdr", 0); // --mie for rayleigh/mie scattering
|
skybox_t sky = skybox("bridge3", 0);
|
||||||
skybox_t sky = skybox("bridge3", 0); // --mie for rayleigh/mie scattering
|
|
||||||
|
|
||||||
// load static scene
|
// load static scene
|
||||||
model_t map;
|
model_t map;
|
||||||
map = model(option("--model","sorting_test.obj"), 0); // MODEL_NO_TEXTURES);
|
map = model(option("--model","sorting_test.obj"), 0); // MODEL_NO_TEXTURES);
|
||||||
shader_bind(map.program);
|
shader_bind(map.program);
|
||||||
skybox_sh_shader(&sky);
|
skybox_sh_shader(&sky);
|
||||||
// translation44(map.pivot, 0,-1,0);
|
|
||||||
// rotate44(map.pivot, -90,1,0,0);
|
|
||||||
// scale44(map.pivot, 10,10,10);
|
|
||||||
|
|
||||||
// camera
|
// camera
|
||||||
camera_t cam = camera();
|
camera_t cam = camera();
|
||||||
|
@ -53,12 +46,6 @@ int main() {
|
||||||
|
|
||||||
mat44 M; copy44(M, map.pivot);// translate44(M, 0,0,0); scale44(M, scale,scale,scale);
|
mat44 M; copy44(M, map.pivot);// translate44(M, 0,0,0); scale44(M, scale,scale,scale);
|
||||||
|
|
||||||
// apply post-fxs from here
|
model_render(map, cam.proj, cam.view, M, 0);
|
||||||
fx_begin();
|
|
||||||
|
|
||||||
model_render_pass(map, cam.proj, cam.view, M, 0, -1);
|
|
||||||
|
|
||||||
// post-fxs end here
|
|
||||||
fx_end(0);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,52 @@
|
||||||
|
# Blender 4.2.1 LTS MTL File: 'None'
|
||||||
|
# www.blender.org
|
||||||
|
|
||||||
|
newmtl Material.006
|
||||||
|
Ns 250.000000
|
||||||
|
Ka 1.000000 1.000000 1.000000
|
||||||
|
Ks 0.500000 0.500000 0.500000
|
||||||
|
Ke 0.000000 0.000000 0.000000
|
||||||
|
Ni 1.500000
|
||||||
|
d 1.000000
|
||||||
|
illum 2
|
||||||
|
map_Kd E:/v4games/v4k/demos/art/matcaps/material3.jpg
|
||||||
|
|
||||||
|
newmtl Material.007
|
||||||
|
Ns 250.000000
|
||||||
|
Ka 1.000000 1.000000 1.000000
|
||||||
|
Ks 0.500000 0.500000 0.500000
|
||||||
|
Ke 0.000000 0.000000 0.000000
|
||||||
|
Ni 1.450000
|
||||||
|
d 1.000000
|
||||||
|
illum 2
|
||||||
|
map_Kd E:/v4games/v4k/demos/art/matcaps/test_steel.jpg
|
||||||
|
|
||||||
|
newmtl Material.008
|
||||||
|
Ns 250.000000
|
||||||
|
Ka 1.000000 1.000000 1.000000
|
||||||
|
Kd 0.059941 0.801453 0.027650
|
||||||
|
Ks 0.500000 0.500000 0.500000
|
||||||
|
Ke 0.000000 0.000000 0.000000
|
||||||
|
Ni 1.500000
|
||||||
|
d 0.228070
|
||||||
|
illum 9
|
||||||
|
|
||||||
|
newmtl Material.009
|
||||||
|
Ns 250.000000
|
||||||
|
Ka 1.000000 1.000000 1.000000
|
||||||
|
Kd 0.015818 0.013069 0.801024
|
||||||
|
Ks 0.500000 0.500000 0.500000
|
||||||
|
Ke 0.000000 0.000000 0.000000
|
||||||
|
Ni 1.500000
|
||||||
|
d 0.294737
|
||||||
|
illum 9
|
||||||
|
|
||||||
|
newmtl Material.010
|
||||||
|
Ns 250.000000
|
||||||
|
Ka 1.000000 1.000000 1.000000
|
||||||
|
Kd 0.800063 0.776954 0.209224
|
||||||
|
Ks 0.500000 0.500000 0.500000
|
||||||
|
Ke 0.000000 0.000000 0.000000
|
||||||
|
Ni 1.500000
|
||||||
|
d 0.480702
|
||||||
|
illum 9
|
|
@ -0,0 +1,70 @@
|
||||||
|
# Blender 4.2.1 LTS
|
||||||
|
# www.blender.org
|
||||||
|
mtllib sorting_test2.mtl
|
||||||
|
o Cube.001
|
||||||
|
v 6.691334 -10.979122 -7.520660
|
||||||
|
v 6.691334 -10.979120 -11.912354
|
||||||
|
v -6.691334 -10.979122 -7.520660
|
||||||
|
v -6.691334 -10.979120 -11.912354
|
||||||
|
v 6.691333 -15.370816 -7.520660
|
||||||
|
v 6.691333 -15.370816 -11.912354
|
||||||
|
v -6.691335 -15.370814 -7.520660
|
||||||
|
v -6.691335 -15.370814 -11.912354
|
||||||
|
v 6.691334 -1.734141 -7.520659
|
||||||
|
v 6.691334 -1.734141 -11.912354
|
||||||
|
v -6.691334 -1.734140 -7.520659
|
||||||
|
v -6.691334 -1.734140 -11.912354
|
||||||
|
v 6.691334 -6.125834 -7.520660
|
||||||
|
v 6.691334 -6.125834 -11.912353
|
||||||
|
v -6.691333 -6.125834 -7.520660
|
||||||
|
v -6.691333 -6.125834 -11.912353
|
||||||
|
v 6.691335 6.836245 -7.520658
|
||||||
|
v 6.691335 6.836244 -11.912353
|
||||||
|
v -6.691332 6.836244 -7.520658
|
||||||
|
v -6.691332 6.836243 -11.912353
|
||||||
|
v 6.691335 2.444547 -7.520658
|
||||||
|
v 6.691335 2.444549 -11.912353
|
||||||
|
v -6.691333 2.444548 -7.520658
|
||||||
|
v -6.691333 2.444550 -11.912353
|
||||||
|
vn -0.0000 1.0000 -0.0000
|
||||||
|
vn -1.0000 -0.0000 -0.0000
|
||||||
|
vn -0.0000 -1.0000 -0.0000
|
||||||
|
vn 1.0000 -0.0000 -0.0000
|
||||||
|
vn -0.0000 -0.0000 1.0000
|
||||||
|
vn -0.0000 -0.0000 -1.0000
|
||||||
|
vt 0.375000 0.000000
|
||||||
|
vt 0.625000 0.000000
|
||||||
|
vt 0.625000 0.250000
|
||||||
|
vt 0.375000 0.250000
|
||||||
|
vt 0.625000 0.500000
|
||||||
|
vt 0.375000 0.500000
|
||||||
|
vt 0.625000 0.750000
|
||||||
|
vt 0.375000 0.750000
|
||||||
|
vt 0.625000 1.000000
|
||||||
|
vt 0.375000 1.000000
|
||||||
|
vt 0.125000 0.500000
|
||||||
|
vt 0.125000 0.750000
|
||||||
|
vt 0.875000 0.500000
|
||||||
|
vt 0.875000 0.750000
|
||||||
|
s 0
|
||||||
|
usemtl Material.008
|
||||||
|
f 1/1/1 2/2/1 4/3/1 3/4/1
|
||||||
|
f 3/4/2 4/3/2 8/5/2 7/6/2
|
||||||
|
f 7/6/3 8/5/3 6/7/3 5/8/3
|
||||||
|
f 5/8/4 6/7/4 2/9/4 1/10/4
|
||||||
|
f 3/11/5 7/6/5 5/8/5 1/12/5
|
||||||
|
f 8/5/6 4/13/6 2/14/6 6/7/6
|
||||||
|
usemtl Material.009
|
||||||
|
f 9/1/1 10/2/1 12/3/1 11/4/1
|
||||||
|
f 11/4/2 12/3/2 16/5/2 15/6/2
|
||||||
|
f 15/6/3 16/5/3 14/7/3 13/8/3
|
||||||
|
f 13/8/4 14/7/4 10/9/4 9/10/4
|
||||||
|
f 11/11/5 15/6/5 13/8/5 9/12/5
|
||||||
|
f 16/5/6 12/13/6 10/14/6 14/7/6
|
||||||
|
usemtl Material.010
|
||||||
|
f 17/1/1 18/2/1 20/3/1 19/4/1
|
||||||
|
f 19/4/2 20/3/2 24/5/2 23/6/2
|
||||||
|
f 23/6/3 24/5/3 22/7/3 21/8/3
|
||||||
|
f 21/8/4 22/7/4 18/9/4 17/10/4
|
||||||
|
f 19/11/5 23/6/5 21/8/5 17/12/5
|
||||||
|
f 24/5/6 20/13/6 18/14/6 22/7/6
|
|
@ -17645,6 +17645,8 @@ typedef struct model_t {
|
||||||
int num_verts;
|
int num_verts;
|
||||||
void *tris;
|
void *tris;
|
||||||
vec3 *meshcenters;
|
vec3 *meshcenters;
|
||||||
|
aabb *meshbounds;
|
||||||
|
float *meshradii;
|
||||||
int num_tris;
|
int num_tris;
|
||||||
handle vao, ibo, vbo, vao_instanced;
|
handle vao, ibo, vbo, vao_instanced;
|
||||||
|
|
||||||
|
@ -17662,6 +17664,9 @@ typedef struct model_t {
|
||||||
|
|
||||||
int stored_flags;
|
int stored_flags;
|
||||||
renderstate_t rs[NUM_RENDER_PASSES];
|
renderstate_t rs[NUM_RENDER_PASSES];
|
||||||
|
|
||||||
|
bool frustum_enabled;
|
||||||
|
frustum frustum_state;
|
||||||
} model_t;
|
} model_t;
|
||||||
|
|
||||||
enum BILLBOARD_MODE {
|
enum BILLBOARD_MODE {
|
||||||
|
@ -17688,6 +17693,10 @@ API void model_render_instanced(model_t, mat44 proj, mat44 view, mat44 *mode
|
||||||
API void model_render_instanced_pass(model_t m, mat44 proj, mat44 view, mat44* models, int shader, unsigned count, int pass);
|
API void model_render_instanced_pass(model_t m, mat44 proj, mat44 view, mat44* models, int shader, unsigned count, int pass);
|
||||||
API void model_render_pass(model_t m, mat44 proj, mat44 view, mat44 model, int shader, int pass);
|
API void model_render_pass(model_t m, mat44 proj, mat44 view, mat44 model, int shader, int pass);
|
||||||
API void model_set_texture(model_t*, texture_t t);
|
API void model_set_texture(model_t*, texture_t t);
|
||||||
|
API bool model_has_transparency_mesh(model_t m, int mesh);
|
||||||
|
API bool model_has_transparency(model_t m);
|
||||||
|
API void model_set_frustum(model_t *m, frustum f);
|
||||||
|
API void model_clear_frustum(model_t *m);
|
||||||
API bool model_get_bone_pose(model_t m, unsigned joint, mat34 *out);
|
API bool model_get_bone_pose(model_t m, unsigned joint, mat34 *out);
|
||||||
API void model_destroy(model_t);
|
API void model_destroy(model_t);
|
||||||
|
|
||||||
|
@ -17884,6 +17893,13 @@ typedef struct object_t {
|
||||||
float anim_speed;
|
float anim_speed;
|
||||||
aabb bounds;
|
aabb bounds;
|
||||||
unsigned billboard; // [0..7] x(4),y(2),z(1) masks
|
unsigned billboard; // [0..7] x(4),y(2),z(1) masks
|
||||||
|
bool disable_frustum_check;
|
||||||
|
|
||||||
|
// internal states
|
||||||
|
array(handle) old_texture_ids;
|
||||||
|
array(texture_t) old_textures;
|
||||||
|
float distance;
|
||||||
|
bool skip_draw;
|
||||||
bool light_cached; //< used by scene to update light data
|
bool light_cached; //< used by scene to update light data
|
||||||
} object_t;
|
} object_t;
|
||||||
|
|
||||||
|
@ -385244,12 +385260,19 @@ bool model_load_meshes(iqm_t *q, const struct iqmheader *hdr, model_t *m) {
|
||||||
q->textures = CALLOC(hdr->num_meshes * 8, sizeof(GLuint));
|
q->textures = CALLOC(hdr->num_meshes * 8, sizeof(GLuint));
|
||||||
q->colormaps = CALLOC(hdr->num_meshes * 8, sizeof(vec4));
|
q->colormaps = CALLOC(hdr->num_meshes * 8, sizeof(vec4));
|
||||||
m->meshcenters = CALLOC(hdr->num_meshes, sizeof(vec3));
|
m->meshcenters = CALLOC(hdr->num_meshes, sizeof(vec3));
|
||||||
|
m->meshbounds = CALLOC(hdr->num_meshes, sizeof(aabb));
|
||||||
|
m->meshradii = CALLOC(hdr->num_meshes, sizeof(float));
|
||||||
|
|
||||||
for(int i = 0; i < (int)hdr->num_meshes; i++) {
|
for(int i = 0; i < (int)hdr->num_meshes; i++) {
|
||||||
int invalid = texture_checker().id;
|
int invalid = texture_checker().id;
|
||||||
q->textures[i] = invalid;
|
q->textures[i] = invalid;
|
||||||
|
struct iqmmesh *mesh = &q->meshes[i];
|
||||||
|
#if 1
|
||||||
GLfloat *pos = verts[q->meshes[i].first_vertex].position;
|
GLfloat *pos = verts[q->meshes[i].first_vertex].position;
|
||||||
m->meshcenters[i] = vec3(pos[0], pos[1], pos[2]);
|
m->meshcenters[i] = vec3(pos[0], pos[1], pos[2]);
|
||||||
|
#else
|
||||||
|
// for (int j = 0; j < )
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *str = hdr->ofs_text ? (char *)&q->buf[hdr->ofs_text] : "";
|
const char *str = hdr->ofs_text ? (char *)&q->buf[hdr->ofs_text] : "";
|
||||||
|
@ -385876,6 +385899,46 @@ int drawcall_compare(const void *a, const void *b) {
|
||||||
return da->order < db->order ? 1 : da->order > db->order ? -1 : 0;
|
return da->order < db->order ? 1 : da->order > db->order ? -1 : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool model_has_transparency_mesh(model_t m, int mesh) {
|
||||||
|
if(!m.iqm) return false;
|
||||||
|
iqm_t *q = m.iqm;
|
||||||
|
|
||||||
|
if (m.flags & MODEL_TRANSPARENT) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (m.materials[mesh].layer[0].map.color.a < 1 || (m.materials[mesh].layer[0].map.texture && m.materials[mesh].layer[0].map.texture->transparent)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (m.shading == SHADING_PBR && (m.materials[mesh].layer[MATERIAL_CHANNEL_ALBEDO].map.color.a < 1 || (m.materials[mesh].layer[MATERIAL_CHANNEL_ALBEDO].map.texture && m.materials[mesh].layer[MATERIAL_CHANNEL_ALBEDO].map.texture->transparent))){
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool model_has_transparency(model_t m) {
|
||||||
|
if(!m.iqm) return false;
|
||||||
|
iqm_t *q = m.iqm;
|
||||||
|
|
||||||
|
for (int i = 0; i < q->nummeshes; i++) {
|
||||||
|
if (model_has_transparency_mesh(m, i)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void model_set_frustum(model_t *m, frustum f) {
|
||||||
|
m->frustum_enabled = 1;
|
||||||
|
m->frustum_state = f;
|
||||||
|
}
|
||||||
|
|
||||||
|
void model_clear_frustum(model_t *m) {
|
||||||
|
m->frustum_enabled = 0;
|
||||||
|
}
|
||||||
|
|
||||||
static
|
static
|
||||||
void model_draw_call(model_t m, int shader, int pass, vec3 cam_pos, mat44 model_mat) {
|
void model_draw_call(model_t m, int shader, int pass, vec3 cam_pos, mat44 model_mat) {
|
||||||
if(!m.iqm) return;
|
if(!m.iqm) return;
|
||||||
|
@ -385897,13 +385960,7 @@ void model_draw_call(model_t m, int shader, int pass, vec3 cam_pos, mat44 model_
|
||||||
required_rs[i] = rs_idx;
|
required_rs[i] = rs_idx;
|
||||||
|
|
||||||
if (required_rs[i] < RENDER_PASS_OVERRIDES_BEGIN) {
|
if (required_rs[i] < RENDER_PASS_OVERRIDES_BEGIN) {
|
||||||
if (m.flags & MODEL_TRANSPARENT) {
|
if (model_has_transparency_mesh(m, i)) {
|
||||||
required_rs[i] = RENDER_PASS_TRANSPARENT;
|
|
||||||
}
|
|
||||||
if (m.materials[i].layer[0].map.color.a < 1 || (m.materials[i].layer[0].map.texture && m.materials[i].layer[0].map.texture->transparent)) {
|
|
||||||
required_rs[i] = RENDER_PASS_TRANSPARENT;
|
|
||||||
}
|
|
||||||
if (m.shading == SHADING_PBR && (m.materials[i].layer[MATERIAL_CHANNEL_ALBEDO].map.color.a < 1 || (m.materials[i].layer[MATERIAL_CHANNEL_ALBEDO].map.texture && m.materials[i].layer[MATERIAL_CHANNEL_ALBEDO].map.texture->transparent))){
|
|
||||||
required_rs[i] = RENDER_PASS_TRANSPARENT;
|
required_rs[i] = RENDER_PASS_TRANSPARENT;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -385943,7 +386000,7 @@ void model_draw_call(model_t m, int shader, int pass, vec3 cam_pos, mat44 model_
|
||||||
// calculate distance from camera
|
// calculate distance from camera
|
||||||
// @todo: improve me, uses first mesh triangle
|
// @todo: improve me, uses first mesh triangle
|
||||||
{
|
{
|
||||||
call.distance = len3(sub3(cam_pos, transform344(model_mat, m.meshcenters[i])));
|
call.distance = len3sq(sub3(cam_pos, transform344(model_mat, m.meshcenters[i])));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m.shading == SHADING_PBR)
|
if (m.shading == SHADING_PBR)
|
||||||
|
@ -386372,6 +386429,8 @@ void model_destroy(model_t m) {
|
||||||
}
|
}
|
||||||
array_free(m.texture_names);
|
array_free(m.texture_names);
|
||||||
FREE(m.meshcenters);
|
FREE(m.meshcenters);
|
||||||
|
FREE(m.meshbounds);
|
||||||
|
FREE(m.meshradii);
|
||||||
|
|
||||||
iqm_t *q = m.iqm;
|
iqm_t *q = m.iqm;
|
||||||
// if(m.mesh) mesh_destroy(m.mesh);
|
// if(m.mesh) mesh_destroy(m.mesh);
|
||||||
|
@ -388020,8 +388079,16 @@ light_t* scene_index_light(unsigned light_index) {
|
||||||
return &last_scene->lights[light_index];
|
return &last_scene->lights[light_index];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
int scene_obj_distance_compare(const void *a, const void *b) {
|
||||||
|
const object_t *da = a, *db = b;
|
||||||
|
return da->distance < db->distance ? 1 : da->distance > db->distance ? -1 : 0;
|
||||||
|
}
|
||||||
|
|
||||||
void scene_render(int flags) {
|
void scene_render(int flags) {
|
||||||
camera_t *cam = camera_get_active();
|
camera_t *cam = camera_get_active();
|
||||||
|
mat44 projview; multiply44x2(projview, cam->proj, cam->view);
|
||||||
|
frustum frustum_state = frustum_build(projview);
|
||||||
|
|
||||||
if(flags & SCENE_BACKGROUND) {
|
if(flags & SCENE_BACKGROUND) {
|
||||||
if(last_scene->skybox.program) {
|
if(last_scene->skybox.program) {
|
||||||
|
@ -388048,17 +388115,17 @@ void scene_render(int flags) {
|
||||||
anim_t *anim = &obj->anim;
|
anim_t *anim = &obj->anim;
|
||||||
mat44 *views = (mat44*)(&cam->view);
|
mat44 *views = (mat44*)(&cam->view);
|
||||||
|
|
||||||
// @todo: avoid heap allocs here?
|
obj->skip_draw = !obj->disable_frustum_check && !frustum_test_aabb(frustum_state, model_aabb(*model, obj->transform));
|
||||||
static array(handle) old_texture_ids = 0;
|
|
||||||
static array(texture_t) old_textures = 0;
|
if (obj->skip_draw) continue;
|
||||||
|
|
||||||
int do_retexturing = model->iqm && model->shading != SHADING_PBR && array_count(obj->textures) > 0;
|
int do_retexturing = model->iqm && model->shading != SHADING_PBR && array_count(obj->textures) > 0;
|
||||||
if( do_retexturing ) {
|
if( do_retexturing ) {
|
||||||
for(int i = 0; i < model->iqm->nummeshes; ++i) {
|
for(int i = 0; i < model->iqm->nummeshes; ++i) {
|
||||||
array_push(old_texture_ids, model->iqm->textures[i]);
|
array_push(obj->old_texture_ids, model->iqm->textures[i]);
|
||||||
model->iqm->textures[i] = (*array_back(obj->textures)).id;
|
model->iqm->textures[i] = (*array_back(obj->textures)).id;
|
||||||
if (model->materials[i].layer[MATERIAL_CHANNEL_DIFFUSE].map.texture) {
|
if (model->materials[i].layer[MATERIAL_CHANNEL_DIFFUSE].map.texture) {
|
||||||
array_push(old_textures, *model->materials[i].layer[MATERIAL_CHANNEL_DIFFUSE].map.texture);
|
array_push(obj->old_textures, *model->materials[i].layer[MATERIAL_CHANNEL_DIFFUSE].map.texture);
|
||||||
*model->materials[i].layer[MATERIAL_CHANNEL_DIFFUSE].map.texture = (*array_back(obj->textures));
|
*model->materials[i].layer[MATERIAL_CHANNEL_DIFFUSE].map.texture = (*array_back(obj->textures));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -388072,32 +388139,80 @@ void scene_render(int flags) {
|
||||||
|
|
||||||
if ( flags&SCENE_UPDATE_SH_COEF ) {
|
if ( flags&SCENE_UPDATE_SH_COEF ) {
|
||||||
shader_bind(model->program);
|
shader_bind(model->program);
|
||||||
shader_vec3v("u_coefficients_sh", 9, last_scene->skybox.cubemap.sh);
|
skybox_sh_shader(&last_scene->skybox);
|
||||||
}
|
}
|
||||||
|
|
||||||
model_skybox(model, last_scene->skybox, 0);
|
model_skybox(model, last_scene->skybox, 0);
|
||||||
|
|
||||||
|
if (!obj->disable_frustum_check)
|
||||||
|
model_set_frustum(model, frustum_state);
|
||||||
|
else
|
||||||
|
model_clear_frustum(model);
|
||||||
|
|
||||||
if (anim) {
|
if (anim) {
|
||||||
float delta = window_delta() * obj->anim_speed;
|
float delta = window_delta() * obj->anim_speed;
|
||||||
model->curframe = model_animate_clip(*model, model->curframe + delta, anim->from, anim->to, anim->flags & ANIM_LOOP );
|
model->curframe = model_animate_clip(*model, model->curframe + delta, anim->from, anim->to, anim->flags & ANIM_LOOP );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
model->billboard = obj->billboard;
|
model->billboard = obj->billboard;
|
||||||
model->rs[RENDER_PASS_OPAQUE].cull_face_enabled = flags&SCENE_CULLFACE ? 1 : 0;
|
for (int p = 0; p < RENDER_PASS_OVERRIDES_BEGIN; ++p) {
|
||||||
model->rs[RENDER_PASS_OPAQUE].polygon_mode_draw = flags&SCENE_WIREFRAME ? GL_LINE : GL_FILL;
|
model->rs[p].cull_face_enabled = flags&SCENE_CULLFACE ? 1 : 0;
|
||||||
model_render(*model, cam->proj, cam->view, obj->transform, model->program);
|
model->rs[p].polygon_mode_draw = flags&SCENE_WIREFRAME ? GL_LINE : GL_FILL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Collect all transparency enabled models and sort them by distance */
|
||||||
|
static array(object_t*) transparent_objects = 0;
|
||||||
|
for(unsigned j = 0, obj_count = scene_count(); j < obj_count; ++j ) {
|
||||||
|
object_t *obj = scene_index(j);
|
||||||
|
model_t *model = &obj->model;
|
||||||
|
|
||||||
|
if (obj->skip_draw) continue;
|
||||||
|
|
||||||
|
if (model_has_transparency(*model)) {
|
||||||
|
obj->distance = len3sq(sub3(cam->position, transform344(model->pivot, add3(obj->pos, model->meshcenters[0]))));
|
||||||
|
array_push(transparent_objects, obj);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
array_sort(transparent_objects, scene_obj_distance_compare);
|
||||||
|
|
||||||
|
/* Opaque pass */
|
||||||
|
for(unsigned j = 0, obj_count = scene_count(); j < obj_count; ++j ) {
|
||||||
|
object_t *obj = scene_index(j);
|
||||||
|
model_t *model = &obj->model;
|
||||||
|
if (obj->skip_draw) continue;
|
||||||
|
|
||||||
|
model_render_pass(*model, cam->proj, cam->view, obj->transform, model->program, RENDER_PASS_OPAQUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Transparency pass */
|
||||||
|
for (unsigned j = 0; j < array_count(transparent_objects); ++j) {
|
||||||
|
object_t *obj = transparent_objects[j];
|
||||||
|
model_t *model = &obj->model;
|
||||||
|
if (obj->skip_draw) continue;
|
||||||
|
|
||||||
|
model_render_pass(*model, cam->proj, cam->view, obj->transform, model->program, RENDER_PASS_TRANSPARENT);
|
||||||
|
}
|
||||||
|
|
||||||
|
array_resize(transparent_objects, 0);
|
||||||
|
|
||||||
|
for(unsigned j = 0, obj_count = scene_count(); j < obj_count; ++j ) {
|
||||||
|
object_t *obj = scene_index(j);
|
||||||
|
model_t *model = &obj->model;
|
||||||
|
if (obj->skip_draw) continue;
|
||||||
|
|
||||||
|
int do_retexturing = model->iqm && model->shading != SHADING_PBR && array_count(obj->textures) > 0;
|
||||||
if( do_retexturing ) {
|
if( do_retexturing ) {
|
||||||
for(int i = 0; i < model->iqm->nummeshes; ++i) {
|
for(int i = 0; i < model->iqm->nummeshes; ++i) {
|
||||||
model->iqm->textures[i] = old_texture_ids[i];
|
model->iqm->textures[i] = obj->old_texture_ids[i];
|
||||||
if (i < array_count(old_textures)) {
|
if (i < array_count(obj->old_textures)) {
|
||||||
if (model->materials[i].layer[MATERIAL_CHANNEL_DIFFUSE].map.texture)
|
if (model->materials[i].layer[MATERIAL_CHANNEL_DIFFUSE].map.texture)
|
||||||
*model->materials[i].layer[MATERIAL_CHANNEL_DIFFUSE].map.texture = old_textures[i];
|
*model->materials[i].layer[MATERIAL_CHANNEL_DIFFUSE].map.texture = obj->old_textures[i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
array_resize(old_texture_ids, 0);
|
array_resize(obj->old_texture_ids, 0);
|
||||||
array_resize(old_textures, 0);
|
array_resize(obj->old_textures, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
glBindVertexArray(0);
|
glBindVertexArray(0);
|
||||||
|
|
|
@ -3604,12 +3604,19 @@ bool model_load_meshes(iqm_t *q, const struct iqmheader *hdr, model_t *m) {
|
||||||
q->textures = CALLOC(hdr->num_meshes * 8, sizeof(GLuint));
|
q->textures = CALLOC(hdr->num_meshes * 8, sizeof(GLuint));
|
||||||
q->colormaps = CALLOC(hdr->num_meshes * 8, sizeof(vec4));
|
q->colormaps = CALLOC(hdr->num_meshes * 8, sizeof(vec4));
|
||||||
m->meshcenters = CALLOC(hdr->num_meshes, sizeof(vec3));
|
m->meshcenters = CALLOC(hdr->num_meshes, sizeof(vec3));
|
||||||
|
m->meshbounds = CALLOC(hdr->num_meshes, sizeof(aabb));
|
||||||
|
m->meshradii = CALLOC(hdr->num_meshes, sizeof(float));
|
||||||
|
|
||||||
for(int i = 0; i < (int)hdr->num_meshes; i++) {
|
for(int i = 0; i < (int)hdr->num_meshes; i++) {
|
||||||
int invalid = texture_checker().id;
|
int invalid = texture_checker().id;
|
||||||
q->textures[i] = invalid;
|
q->textures[i] = invalid;
|
||||||
|
struct iqmmesh *mesh = &q->meshes[i];
|
||||||
|
#if 1
|
||||||
GLfloat *pos = verts[q->meshes[i].first_vertex].position;
|
GLfloat *pos = verts[q->meshes[i].first_vertex].position;
|
||||||
m->meshcenters[i] = vec3(pos[0], pos[1], pos[2]);
|
m->meshcenters[i] = vec3(pos[0], pos[1], pos[2]);
|
||||||
|
#else
|
||||||
|
// for (int j = 0; j < )
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *str = hdr->ofs_text ? (char *)&q->buf[hdr->ofs_text] : "";
|
const char *str = hdr->ofs_text ? (char *)&q->buf[hdr->ofs_text] : "";
|
||||||
|
@ -4236,6 +4243,46 @@ int drawcall_compare(const void *a, const void *b) {
|
||||||
return da->order < db->order ? 1 : da->order > db->order ? -1 : 0;
|
return da->order < db->order ? 1 : da->order > db->order ? -1 : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool model_has_transparency_mesh(model_t m, int mesh) {
|
||||||
|
if(!m.iqm) return false;
|
||||||
|
iqm_t *q = m.iqm;
|
||||||
|
|
||||||
|
if (m.flags & MODEL_TRANSPARENT) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (m.materials[mesh].layer[0].map.color.a < 1 || (m.materials[mesh].layer[0].map.texture && m.materials[mesh].layer[0].map.texture->transparent)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (m.shading == SHADING_PBR && (m.materials[mesh].layer[MATERIAL_CHANNEL_ALBEDO].map.color.a < 1 || (m.materials[mesh].layer[MATERIAL_CHANNEL_ALBEDO].map.texture && m.materials[mesh].layer[MATERIAL_CHANNEL_ALBEDO].map.texture->transparent))){
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool model_has_transparency(model_t m) {
|
||||||
|
if(!m.iqm) return false;
|
||||||
|
iqm_t *q = m.iqm;
|
||||||
|
|
||||||
|
for (int i = 0; i < q->nummeshes; i++) {
|
||||||
|
if (model_has_transparency_mesh(m, i)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void model_set_frustum(model_t *m, frustum f) {
|
||||||
|
m->frustum_enabled = 1;
|
||||||
|
m->frustum_state = f;
|
||||||
|
}
|
||||||
|
|
||||||
|
void model_clear_frustum(model_t *m) {
|
||||||
|
m->frustum_enabled = 0;
|
||||||
|
}
|
||||||
|
|
||||||
static
|
static
|
||||||
void model_draw_call(model_t m, int shader, int pass, vec3 cam_pos, mat44 model_mat) {
|
void model_draw_call(model_t m, int shader, int pass, vec3 cam_pos, mat44 model_mat) {
|
||||||
if(!m.iqm) return;
|
if(!m.iqm) return;
|
||||||
|
@ -4257,13 +4304,7 @@ void model_draw_call(model_t m, int shader, int pass, vec3 cam_pos, mat44 model_
|
||||||
required_rs[i] = rs_idx;
|
required_rs[i] = rs_idx;
|
||||||
|
|
||||||
if (required_rs[i] < RENDER_PASS_OVERRIDES_BEGIN) {
|
if (required_rs[i] < RENDER_PASS_OVERRIDES_BEGIN) {
|
||||||
if (m.flags & MODEL_TRANSPARENT) {
|
if (model_has_transparency_mesh(m, i)) {
|
||||||
required_rs[i] = RENDER_PASS_TRANSPARENT;
|
|
||||||
}
|
|
||||||
if (m.materials[i].layer[0].map.color.a < 1 || (m.materials[i].layer[0].map.texture && m.materials[i].layer[0].map.texture->transparent)) {
|
|
||||||
required_rs[i] = RENDER_PASS_TRANSPARENT;
|
|
||||||
}
|
|
||||||
if (m.shading == SHADING_PBR && (m.materials[i].layer[MATERIAL_CHANNEL_ALBEDO].map.color.a < 1 || (m.materials[i].layer[MATERIAL_CHANNEL_ALBEDO].map.texture && m.materials[i].layer[MATERIAL_CHANNEL_ALBEDO].map.texture->transparent))){
|
|
||||||
required_rs[i] = RENDER_PASS_TRANSPARENT;
|
required_rs[i] = RENDER_PASS_TRANSPARENT;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4303,7 +4344,7 @@ void model_draw_call(model_t m, int shader, int pass, vec3 cam_pos, mat44 model_
|
||||||
// calculate distance from camera
|
// calculate distance from camera
|
||||||
// @todo: improve me, uses first mesh triangle
|
// @todo: improve me, uses first mesh triangle
|
||||||
{
|
{
|
||||||
call.distance = len3(sub3(cam_pos, transform344(model_mat, m.meshcenters[i])));
|
call.distance = len3sq(sub3(cam_pos, transform344(model_mat, m.meshcenters[i])));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m.shading == SHADING_PBR)
|
if (m.shading == SHADING_PBR)
|
||||||
|
@ -4732,6 +4773,8 @@ void model_destroy(model_t m) {
|
||||||
}
|
}
|
||||||
array_free(m.texture_names);
|
array_free(m.texture_names);
|
||||||
FREE(m.meshcenters);
|
FREE(m.meshcenters);
|
||||||
|
FREE(m.meshbounds);
|
||||||
|
FREE(m.meshradii);
|
||||||
|
|
||||||
iqm_t *q = m.iqm;
|
iqm_t *q = m.iqm;
|
||||||
// if(m.mesh) mesh_destroy(m.mesh);
|
// if(m.mesh) mesh_destroy(m.mesh);
|
||||||
|
|
|
@ -677,6 +677,8 @@ typedef struct model_t {
|
||||||
int num_verts;
|
int num_verts;
|
||||||
void *tris;
|
void *tris;
|
||||||
vec3 *meshcenters;
|
vec3 *meshcenters;
|
||||||
|
aabb *meshbounds;
|
||||||
|
float *meshradii;
|
||||||
int num_tris;
|
int num_tris;
|
||||||
handle vao, ibo, vbo, vao_instanced;
|
handle vao, ibo, vbo, vao_instanced;
|
||||||
|
|
||||||
|
@ -694,6 +696,9 @@ typedef struct model_t {
|
||||||
|
|
||||||
int stored_flags;
|
int stored_flags;
|
||||||
renderstate_t rs[NUM_RENDER_PASSES];
|
renderstate_t rs[NUM_RENDER_PASSES];
|
||||||
|
|
||||||
|
bool frustum_enabled;
|
||||||
|
frustum frustum_state;
|
||||||
} model_t;
|
} model_t;
|
||||||
|
|
||||||
enum BILLBOARD_MODE {
|
enum BILLBOARD_MODE {
|
||||||
|
@ -720,6 +725,10 @@ API void model_render_instanced(model_t, mat44 proj, mat44 view, mat44 *mode
|
||||||
API void model_render_instanced_pass(model_t m, mat44 proj, mat44 view, mat44* models, int shader, unsigned count, int pass);
|
API void model_render_instanced_pass(model_t m, mat44 proj, mat44 view, mat44* models, int shader, unsigned count, int pass);
|
||||||
API void model_render_pass(model_t m, mat44 proj, mat44 view, mat44 model, int shader, int pass);
|
API void model_render_pass(model_t m, mat44 proj, mat44 view, mat44 model, int shader, int pass);
|
||||||
API void model_set_texture(model_t*, texture_t t);
|
API void model_set_texture(model_t*, texture_t t);
|
||||||
|
API bool model_has_transparency_mesh(model_t m, int mesh);
|
||||||
|
API bool model_has_transparency(model_t m);
|
||||||
|
API void model_set_frustum(model_t *m, frustum f);
|
||||||
|
API void model_clear_frustum(model_t *m);
|
||||||
API bool model_get_bone_pose(model_t m, unsigned joint, mat34 *out);
|
API bool model_get_bone_pose(model_t m, unsigned joint, mat34 *out);
|
||||||
API void model_destroy(model_t);
|
API void model_destroy(model_t);
|
||||||
|
|
||||||
|
|
|
@ -505,8 +505,16 @@ light_t* scene_index_light(unsigned light_index) {
|
||||||
return &last_scene->lights[light_index];
|
return &last_scene->lights[light_index];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
int scene_obj_distance_compare(const void *a, const void *b) {
|
||||||
|
const object_t *da = a, *db = b;
|
||||||
|
return da->distance < db->distance ? 1 : da->distance > db->distance ? -1 : 0;
|
||||||
|
}
|
||||||
|
|
||||||
void scene_render(int flags) {
|
void scene_render(int flags) {
|
||||||
camera_t *cam = camera_get_active();
|
camera_t *cam = camera_get_active();
|
||||||
|
mat44 projview; multiply44x2(projview, cam->proj, cam->view);
|
||||||
|
frustum frustum_state = frustum_build(projview);
|
||||||
|
|
||||||
if(flags & SCENE_BACKGROUND) {
|
if(flags & SCENE_BACKGROUND) {
|
||||||
if(last_scene->skybox.program) {
|
if(last_scene->skybox.program) {
|
||||||
|
@ -533,17 +541,17 @@ void scene_render(int flags) {
|
||||||
anim_t *anim = &obj->anim;
|
anim_t *anim = &obj->anim;
|
||||||
mat44 *views = (mat44*)(&cam->view);
|
mat44 *views = (mat44*)(&cam->view);
|
||||||
|
|
||||||
// @todo: avoid heap allocs here?
|
obj->skip_draw = !obj->disable_frustum_check && !frustum_test_aabb(frustum_state, model_aabb(*model, obj->transform));
|
||||||
static array(handle) old_texture_ids = 0;
|
|
||||||
static array(texture_t) old_textures = 0;
|
if (obj->skip_draw) continue;
|
||||||
|
|
||||||
int do_retexturing = model->iqm && model->shading != SHADING_PBR && array_count(obj->textures) > 0;
|
int do_retexturing = model->iqm && model->shading != SHADING_PBR && array_count(obj->textures) > 0;
|
||||||
if( do_retexturing ) {
|
if( do_retexturing ) {
|
||||||
for(int i = 0; i < model->iqm->nummeshes; ++i) {
|
for(int i = 0; i < model->iqm->nummeshes; ++i) {
|
||||||
array_push(old_texture_ids, model->iqm->textures[i]);
|
array_push(obj->old_texture_ids, model->iqm->textures[i]);
|
||||||
model->iqm->textures[i] = (*array_back(obj->textures)).id;
|
model->iqm->textures[i] = (*array_back(obj->textures)).id;
|
||||||
if (model->materials[i].layer[MATERIAL_CHANNEL_DIFFUSE].map.texture) {
|
if (model->materials[i].layer[MATERIAL_CHANNEL_DIFFUSE].map.texture) {
|
||||||
array_push(old_textures, *model->materials[i].layer[MATERIAL_CHANNEL_DIFFUSE].map.texture);
|
array_push(obj->old_textures, *model->materials[i].layer[MATERIAL_CHANNEL_DIFFUSE].map.texture);
|
||||||
*model->materials[i].layer[MATERIAL_CHANNEL_DIFFUSE].map.texture = (*array_back(obj->textures));
|
*model->materials[i].layer[MATERIAL_CHANNEL_DIFFUSE].map.texture = (*array_back(obj->textures));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -557,32 +565,80 @@ void scene_render(int flags) {
|
||||||
|
|
||||||
if ( flags&SCENE_UPDATE_SH_COEF ) {
|
if ( flags&SCENE_UPDATE_SH_COEF ) {
|
||||||
shader_bind(model->program);
|
shader_bind(model->program);
|
||||||
shader_vec3v("u_coefficients_sh", 9, last_scene->skybox.cubemap.sh);
|
skybox_sh_shader(&last_scene->skybox);
|
||||||
}
|
}
|
||||||
|
|
||||||
model_skybox(model, last_scene->skybox, 0);
|
model_skybox(model, last_scene->skybox, 0);
|
||||||
|
|
||||||
|
if (!obj->disable_frustum_check)
|
||||||
|
model_set_frustum(model, frustum_state);
|
||||||
|
else
|
||||||
|
model_clear_frustum(model);
|
||||||
|
|
||||||
if (anim) {
|
if (anim) {
|
||||||
float delta = window_delta() * obj->anim_speed;
|
float delta = window_delta() * obj->anim_speed;
|
||||||
model->curframe = model_animate_clip(*model, model->curframe + delta, anim->from, anim->to, anim->flags & ANIM_LOOP );
|
model->curframe = model_animate_clip(*model, model->curframe + delta, anim->from, anim->to, anim->flags & ANIM_LOOP );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
model->billboard = obj->billboard;
|
model->billboard = obj->billboard;
|
||||||
model->rs[RENDER_PASS_OPAQUE].cull_face_enabled = flags&SCENE_CULLFACE ? 1 : 0;
|
for (int p = 0; p < RENDER_PASS_OVERRIDES_BEGIN; ++p) {
|
||||||
model->rs[RENDER_PASS_OPAQUE].polygon_mode_draw = flags&SCENE_WIREFRAME ? GL_LINE : GL_FILL;
|
model->rs[p].cull_face_enabled = flags&SCENE_CULLFACE ? 1 : 0;
|
||||||
model_render(*model, cam->proj, cam->view, obj->transform, model->program);
|
model->rs[p].polygon_mode_draw = flags&SCENE_WIREFRAME ? GL_LINE : GL_FILL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Collect all transparency enabled models and sort them by distance */
|
||||||
|
static array(object_t*) transparent_objects = 0;
|
||||||
|
for(unsigned j = 0, obj_count = scene_count(); j < obj_count; ++j ) {
|
||||||
|
object_t *obj = scene_index(j);
|
||||||
|
model_t *model = &obj->model;
|
||||||
|
|
||||||
|
if (obj->skip_draw) continue;
|
||||||
|
|
||||||
|
if (model_has_transparency(*model)) {
|
||||||
|
obj->distance = len3sq(sub3(cam->position, transform344(model->pivot, add3(obj->pos, model->meshcenters[0]))));
|
||||||
|
array_push(transparent_objects, obj);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
array_sort(transparent_objects, scene_obj_distance_compare);
|
||||||
|
|
||||||
|
/* Opaque pass */
|
||||||
|
for(unsigned j = 0, obj_count = scene_count(); j < obj_count; ++j ) {
|
||||||
|
object_t *obj = scene_index(j);
|
||||||
|
model_t *model = &obj->model;
|
||||||
|
if (obj->skip_draw) continue;
|
||||||
|
|
||||||
|
model_render_pass(*model, cam->proj, cam->view, obj->transform, model->program, RENDER_PASS_OPAQUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Transparency pass */
|
||||||
|
for (unsigned j = 0; j < array_count(transparent_objects); ++j) {
|
||||||
|
object_t *obj = transparent_objects[j];
|
||||||
|
model_t *model = &obj->model;
|
||||||
|
if (obj->skip_draw) continue;
|
||||||
|
|
||||||
|
model_render_pass(*model, cam->proj, cam->view, obj->transform, model->program, RENDER_PASS_TRANSPARENT);
|
||||||
|
}
|
||||||
|
|
||||||
|
array_resize(transparent_objects, 0);
|
||||||
|
|
||||||
|
for(unsigned j = 0, obj_count = scene_count(); j < obj_count; ++j ) {
|
||||||
|
object_t *obj = scene_index(j);
|
||||||
|
model_t *model = &obj->model;
|
||||||
|
if (obj->skip_draw) continue;
|
||||||
|
|
||||||
|
int do_retexturing = model->iqm && model->shading != SHADING_PBR && array_count(obj->textures) > 0;
|
||||||
if( do_retexturing ) {
|
if( do_retexturing ) {
|
||||||
for(int i = 0; i < model->iqm->nummeshes; ++i) {
|
for(int i = 0; i < model->iqm->nummeshes; ++i) {
|
||||||
model->iqm->textures[i] = old_texture_ids[i];
|
model->iqm->textures[i] = obj->old_texture_ids[i];
|
||||||
if (i < array_count(old_textures)) {
|
if (i < array_count(obj->old_textures)) {
|
||||||
if (model->materials[i].layer[MATERIAL_CHANNEL_DIFFUSE].map.texture)
|
if (model->materials[i].layer[MATERIAL_CHANNEL_DIFFUSE].map.texture)
|
||||||
*model->materials[i].layer[MATERIAL_CHANNEL_DIFFUSE].map.texture = old_textures[i];
|
*model->materials[i].layer[MATERIAL_CHANNEL_DIFFUSE].map.texture = obj->old_textures[i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
array_resize(old_texture_ids, 0);
|
array_resize(obj->old_texture_ids, 0);
|
||||||
array_resize(old_textures, 0);
|
array_resize(obj->old_textures, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
glBindVertexArray(0);
|
glBindVertexArray(0);
|
||||||
|
|
|
@ -48,6 +48,13 @@ typedef struct object_t {
|
||||||
float anim_speed;
|
float anim_speed;
|
||||||
aabb bounds;
|
aabb bounds;
|
||||||
unsigned billboard; // [0..7] x(4),y(2),z(1) masks
|
unsigned billboard; // [0..7] x(4),y(2),z(1) masks
|
||||||
|
bool disable_frustum_check;
|
||||||
|
|
||||||
|
// internal states
|
||||||
|
array(handle) old_texture_ids;
|
||||||
|
array(texture_t) old_textures;
|
||||||
|
float distance;
|
||||||
|
bool skip_draw;
|
||||||
bool light_cached; //< used by scene to update light data
|
bool light_cached; //< used by scene to update light data
|
||||||
} object_t;
|
} object_t;
|
||||||
|
|
||||||
|
|
145
engine/v4k.c
145
engine/v4k.c
|
@ -20403,12 +20403,19 @@ bool model_load_meshes(iqm_t *q, const struct iqmheader *hdr, model_t *m) {
|
||||||
q->textures = CALLOC(hdr->num_meshes * 8, sizeof(GLuint));
|
q->textures = CALLOC(hdr->num_meshes * 8, sizeof(GLuint));
|
||||||
q->colormaps = CALLOC(hdr->num_meshes * 8, sizeof(vec4));
|
q->colormaps = CALLOC(hdr->num_meshes * 8, sizeof(vec4));
|
||||||
m->meshcenters = CALLOC(hdr->num_meshes, sizeof(vec3));
|
m->meshcenters = CALLOC(hdr->num_meshes, sizeof(vec3));
|
||||||
|
m->meshbounds = CALLOC(hdr->num_meshes, sizeof(aabb));
|
||||||
|
m->meshradii = CALLOC(hdr->num_meshes, sizeof(float));
|
||||||
|
|
||||||
for(int i = 0; i < (int)hdr->num_meshes; i++) {
|
for(int i = 0; i < (int)hdr->num_meshes; i++) {
|
||||||
int invalid = texture_checker().id;
|
int invalid = texture_checker().id;
|
||||||
q->textures[i] = invalid;
|
q->textures[i] = invalid;
|
||||||
|
struct iqmmesh *mesh = &q->meshes[i];
|
||||||
|
#if 1
|
||||||
GLfloat *pos = verts[q->meshes[i].first_vertex].position;
|
GLfloat *pos = verts[q->meshes[i].first_vertex].position;
|
||||||
m->meshcenters[i] = vec3(pos[0], pos[1], pos[2]);
|
m->meshcenters[i] = vec3(pos[0], pos[1], pos[2]);
|
||||||
|
#else
|
||||||
|
// for (int j = 0; j < )
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *str = hdr->ofs_text ? (char *)&q->buf[hdr->ofs_text] : "";
|
const char *str = hdr->ofs_text ? (char *)&q->buf[hdr->ofs_text] : "";
|
||||||
|
@ -21035,6 +21042,46 @@ int drawcall_compare(const void *a, const void *b) {
|
||||||
return da->order < db->order ? 1 : da->order > db->order ? -1 : 0;
|
return da->order < db->order ? 1 : da->order > db->order ? -1 : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool model_has_transparency_mesh(model_t m, int mesh) {
|
||||||
|
if(!m.iqm) return false;
|
||||||
|
iqm_t *q = m.iqm;
|
||||||
|
|
||||||
|
if (m.flags & MODEL_TRANSPARENT) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (m.materials[mesh].layer[0].map.color.a < 1 || (m.materials[mesh].layer[0].map.texture && m.materials[mesh].layer[0].map.texture->transparent)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (m.shading == SHADING_PBR && (m.materials[mesh].layer[MATERIAL_CHANNEL_ALBEDO].map.color.a < 1 || (m.materials[mesh].layer[MATERIAL_CHANNEL_ALBEDO].map.texture && m.materials[mesh].layer[MATERIAL_CHANNEL_ALBEDO].map.texture->transparent))){
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool model_has_transparency(model_t m) {
|
||||||
|
if(!m.iqm) return false;
|
||||||
|
iqm_t *q = m.iqm;
|
||||||
|
|
||||||
|
for (int i = 0; i < q->nummeshes; i++) {
|
||||||
|
if (model_has_transparency_mesh(m, i)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void model_set_frustum(model_t *m, frustum f) {
|
||||||
|
m->frustum_enabled = 1;
|
||||||
|
m->frustum_state = f;
|
||||||
|
}
|
||||||
|
|
||||||
|
void model_clear_frustum(model_t *m) {
|
||||||
|
m->frustum_enabled = 0;
|
||||||
|
}
|
||||||
|
|
||||||
static
|
static
|
||||||
void model_draw_call(model_t m, int shader, int pass, vec3 cam_pos, mat44 model_mat) {
|
void model_draw_call(model_t m, int shader, int pass, vec3 cam_pos, mat44 model_mat) {
|
||||||
if(!m.iqm) return;
|
if(!m.iqm) return;
|
||||||
|
@ -21056,13 +21103,7 @@ void model_draw_call(model_t m, int shader, int pass, vec3 cam_pos, mat44 model_
|
||||||
required_rs[i] = rs_idx;
|
required_rs[i] = rs_idx;
|
||||||
|
|
||||||
if (required_rs[i] < RENDER_PASS_OVERRIDES_BEGIN) {
|
if (required_rs[i] < RENDER_PASS_OVERRIDES_BEGIN) {
|
||||||
if (m.flags & MODEL_TRANSPARENT) {
|
if (model_has_transparency_mesh(m, i)) {
|
||||||
required_rs[i] = RENDER_PASS_TRANSPARENT;
|
|
||||||
}
|
|
||||||
if (m.materials[i].layer[0].map.color.a < 1 || (m.materials[i].layer[0].map.texture && m.materials[i].layer[0].map.texture->transparent)) {
|
|
||||||
required_rs[i] = RENDER_PASS_TRANSPARENT;
|
|
||||||
}
|
|
||||||
if (m.shading == SHADING_PBR && (m.materials[i].layer[MATERIAL_CHANNEL_ALBEDO].map.color.a < 1 || (m.materials[i].layer[MATERIAL_CHANNEL_ALBEDO].map.texture && m.materials[i].layer[MATERIAL_CHANNEL_ALBEDO].map.texture->transparent))){
|
|
||||||
required_rs[i] = RENDER_PASS_TRANSPARENT;
|
required_rs[i] = RENDER_PASS_TRANSPARENT;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -21102,7 +21143,7 @@ void model_draw_call(model_t m, int shader, int pass, vec3 cam_pos, mat44 model_
|
||||||
// calculate distance from camera
|
// calculate distance from camera
|
||||||
// @todo: improve me, uses first mesh triangle
|
// @todo: improve me, uses first mesh triangle
|
||||||
{
|
{
|
||||||
call.distance = len3(sub3(cam_pos, transform344(model_mat, m.meshcenters[i])));
|
call.distance = len3sq(sub3(cam_pos, transform344(model_mat, m.meshcenters[i])));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m.shading == SHADING_PBR)
|
if (m.shading == SHADING_PBR)
|
||||||
|
@ -21531,6 +21572,8 @@ void model_destroy(model_t m) {
|
||||||
}
|
}
|
||||||
array_free(m.texture_names);
|
array_free(m.texture_names);
|
||||||
FREE(m.meshcenters);
|
FREE(m.meshcenters);
|
||||||
|
FREE(m.meshbounds);
|
||||||
|
FREE(m.meshradii);
|
||||||
|
|
||||||
iqm_t *q = m.iqm;
|
iqm_t *q = m.iqm;
|
||||||
// if(m.mesh) mesh_destroy(m.mesh);
|
// if(m.mesh) mesh_destroy(m.mesh);
|
||||||
|
@ -23179,8 +23222,16 @@ light_t* scene_index_light(unsigned light_index) {
|
||||||
return &last_scene->lights[light_index];
|
return &last_scene->lights[light_index];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
int scene_obj_distance_compare(const void *a, const void *b) {
|
||||||
|
const object_t *da = a, *db = b;
|
||||||
|
return da->distance < db->distance ? 1 : da->distance > db->distance ? -1 : 0;
|
||||||
|
}
|
||||||
|
|
||||||
void scene_render(int flags) {
|
void scene_render(int flags) {
|
||||||
camera_t *cam = camera_get_active();
|
camera_t *cam = camera_get_active();
|
||||||
|
mat44 projview; multiply44x2(projview, cam->proj, cam->view);
|
||||||
|
frustum frustum_state = frustum_build(projview);
|
||||||
|
|
||||||
if(flags & SCENE_BACKGROUND) {
|
if(flags & SCENE_BACKGROUND) {
|
||||||
if(last_scene->skybox.program) {
|
if(last_scene->skybox.program) {
|
||||||
|
@ -23207,17 +23258,17 @@ void scene_render(int flags) {
|
||||||
anim_t *anim = &obj->anim;
|
anim_t *anim = &obj->anim;
|
||||||
mat44 *views = (mat44*)(&cam->view);
|
mat44 *views = (mat44*)(&cam->view);
|
||||||
|
|
||||||
// @todo: avoid heap allocs here?
|
obj->skip_draw = !obj->disable_frustum_check && !frustum_test_aabb(frustum_state, model_aabb(*model, obj->transform));
|
||||||
static array(handle) old_texture_ids = 0;
|
|
||||||
static array(texture_t) old_textures = 0;
|
if (obj->skip_draw) continue;
|
||||||
|
|
||||||
int do_retexturing = model->iqm && model->shading != SHADING_PBR && array_count(obj->textures) > 0;
|
int do_retexturing = model->iqm && model->shading != SHADING_PBR && array_count(obj->textures) > 0;
|
||||||
if( do_retexturing ) {
|
if( do_retexturing ) {
|
||||||
for(int i = 0; i < model->iqm->nummeshes; ++i) {
|
for(int i = 0; i < model->iqm->nummeshes; ++i) {
|
||||||
array_push(old_texture_ids, model->iqm->textures[i]);
|
array_push(obj->old_texture_ids, model->iqm->textures[i]);
|
||||||
model->iqm->textures[i] = (*array_back(obj->textures)).id;
|
model->iqm->textures[i] = (*array_back(obj->textures)).id;
|
||||||
if (model->materials[i].layer[MATERIAL_CHANNEL_DIFFUSE].map.texture) {
|
if (model->materials[i].layer[MATERIAL_CHANNEL_DIFFUSE].map.texture) {
|
||||||
array_push(old_textures, *model->materials[i].layer[MATERIAL_CHANNEL_DIFFUSE].map.texture);
|
array_push(obj->old_textures, *model->materials[i].layer[MATERIAL_CHANNEL_DIFFUSE].map.texture);
|
||||||
*model->materials[i].layer[MATERIAL_CHANNEL_DIFFUSE].map.texture = (*array_back(obj->textures));
|
*model->materials[i].layer[MATERIAL_CHANNEL_DIFFUSE].map.texture = (*array_back(obj->textures));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -23231,32 +23282,80 @@ void scene_render(int flags) {
|
||||||
|
|
||||||
if ( flags&SCENE_UPDATE_SH_COEF ) {
|
if ( flags&SCENE_UPDATE_SH_COEF ) {
|
||||||
shader_bind(model->program);
|
shader_bind(model->program);
|
||||||
shader_vec3v("u_coefficients_sh", 9, last_scene->skybox.cubemap.sh);
|
skybox_sh_shader(&last_scene->skybox);
|
||||||
}
|
}
|
||||||
|
|
||||||
model_skybox(model, last_scene->skybox, 0);
|
model_skybox(model, last_scene->skybox, 0);
|
||||||
|
|
||||||
|
if (!obj->disable_frustum_check)
|
||||||
|
model_set_frustum(model, frustum_state);
|
||||||
|
else
|
||||||
|
model_clear_frustum(model);
|
||||||
|
|
||||||
if (anim) {
|
if (anim) {
|
||||||
float delta = window_delta() * obj->anim_speed;
|
float delta = window_delta() * obj->anim_speed;
|
||||||
model->curframe = model_animate_clip(*model, model->curframe + delta, anim->from, anim->to, anim->flags & ANIM_LOOP );
|
model->curframe = model_animate_clip(*model, model->curframe + delta, anim->from, anim->to, anim->flags & ANIM_LOOP );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
model->billboard = obj->billboard;
|
model->billboard = obj->billboard;
|
||||||
model->rs[RENDER_PASS_OPAQUE].cull_face_enabled = flags&SCENE_CULLFACE ? 1 : 0;
|
for (int p = 0; p < RENDER_PASS_OVERRIDES_BEGIN; ++p) {
|
||||||
model->rs[RENDER_PASS_OPAQUE].polygon_mode_draw = flags&SCENE_WIREFRAME ? GL_LINE : GL_FILL;
|
model->rs[p].cull_face_enabled = flags&SCENE_CULLFACE ? 1 : 0;
|
||||||
model_render(*model, cam->proj, cam->view, obj->transform, model->program);
|
model->rs[p].polygon_mode_draw = flags&SCENE_WIREFRAME ? GL_LINE : GL_FILL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Collect all transparency enabled models and sort them by distance */
|
||||||
|
static array(object_t*) transparent_objects = 0;
|
||||||
|
for(unsigned j = 0, obj_count = scene_count(); j < obj_count; ++j ) {
|
||||||
|
object_t *obj = scene_index(j);
|
||||||
|
model_t *model = &obj->model;
|
||||||
|
|
||||||
|
if (obj->skip_draw) continue;
|
||||||
|
|
||||||
|
if (model_has_transparency(*model)) {
|
||||||
|
obj->distance = len3sq(sub3(cam->position, transform344(model->pivot, add3(obj->pos, model->meshcenters[0]))));
|
||||||
|
array_push(transparent_objects, obj);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
array_sort(transparent_objects, scene_obj_distance_compare);
|
||||||
|
|
||||||
|
/* Opaque pass */
|
||||||
|
for(unsigned j = 0, obj_count = scene_count(); j < obj_count; ++j ) {
|
||||||
|
object_t *obj = scene_index(j);
|
||||||
|
model_t *model = &obj->model;
|
||||||
|
if (obj->skip_draw) continue;
|
||||||
|
|
||||||
|
model_render_pass(*model, cam->proj, cam->view, obj->transform, model->program, RENDER_PASS_OPAQUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Transparency pass */
|
||||||
|
for (unsigned j = 0; j < array_count(transparent_objects); ++j) {
|
||||||
|
object_t *obj = transparent_objects[j];
|
||||||
|
model_t *model = &obj->model;
|
||||||
|
if (obj->skip_draw) continue;
|
||||||
|
|
||||||
|
model_render_pass(*model, cam->proj, cam->view, obj->transform, model->program, RENDER_PASS_TRANSPARENT);
|
||||||
|
}
|
||||||
|
|
||||||
|
array_resize(transparent_objects, 0);
|
||||||
|
|
||||||
|
for(unsigned j = 0, obj_count = scene_count(); j < obj_count; ++j ) {
|
||||||
|
object_t *obj = scene_index(j);
|
||||||
|
model_t *model = &obj->model;
|
||||||
|
if (obj->skip_draw) continue;
|
||||||
|
|
||||||
|
int do_retexturing = model->iqm && model->shading != SHADING_PBR && array_count(obj->textures) > 0;
|
||||||
if( do_retexturing ) {
|
if( do_retexturing ) {
|
||||||
for(int i = 0; i < model->iqm->nummeshes; ++i) {
|
for(int i = 0; i < model->iqm->nummeshes; ++i) {
|
||||||
model->iqm->textures[i] = old_texture_ids[i];
|
model->iqm->textures[i] = obj->old_texture_ids[i];
|
||||||
if (i < array_count(old_textures)) {
|
if (i < array_count(obj->old_textures)) {
|
||||||
if (model->materials[i].layer[MATERIAL_CHANNEL_DIFFUSE].map.texture)
|
if (model->materials[i].layer[MATERIAL_CHANNEL_DIFFUSE].map.texture)
|
||||||
*model->materials[i].layer[MATERIAL_CHANNEL_DIFFUSE].map.texture = old_textures[i];
|
*model->materials[i].layer[MATERIAL_CHANNEL_DIFFUSE].map.texture = obj->old_textures[i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
array_resize(old_texture_ids, 0);
|
array_resize(obj->old_texture_ids, 0);
|
||||||
array_resize(old_textures, 0);
|
array_resize(obj->old_textures, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
glBindVertexArray(0);
|
glBindVertexArray(0);
|
||||||
|
|
16
engine/v4k.h
16
engine/v4k.h
|
@ -3712,6 +3712,8 @@ typedef struct model_t {
|
||||||
int num_verts;
|
int num_verts;
|
||||||
void *tris;
|
void *tris;
|
||||||
vec3 *meshcenters;
|
vec3 *meshcenters;
|
||||||
|
aabb *meshbounds;
|
||||||
|
float *meshradii;
|
||||||
int num_tris;
|
int num_tris;
|
||||||
handle vao, ibo, vbo, vao_instanced;
|
handle vao, ibo, vbo, vao_instanced;
|
||||||
|
|
||||||
|
@ -3729,6 +3731,9 @@ typedef struct model_t {
|
||||||
|
|
||||||
int stored_flags;
|
int stored_flags;
|
||||||
renderstate_t rs[NUM_RENDER_PASSES];
|
renderstate_t rs[NUM_RENDER_PASSES];
|
||||||
|
|
||||||
|
bool frustum_enabled;
|
||||||
|
frustum frustum_state;
|
||||||
} model_t;
|
} model_t;
|
||||||
|
|
||||||
enum BILLBOARD_MODE {
|
enum BILLBOARD_MODE {
|
||||||
|
@ -3755,6 +3760,10 @@ API void model_render_instanced(model_t, mat44 proj, mat44 view, mat44 *mode
|
||||||
API void model_render_instanced_pass(model_t m, mat44 proj, mat44 view, mat44* models, int shader, unsigned count, int pass);
|
API void model_render_instanced_pass(model_t m, mat44 proj, mat44 view, mat44* models, int shader, unsigned count, int pass);
|
||||||
API void model_render_pass(model_t m, mat44 proj, mat44 view, mat44 model, int shader, int pass);
|
API void model_render_pass(model_t m, mat44 proj, mat44 view, mat44 model, int shader, int pass);
|
||||||
API void model_set_texture(model_t*, texture_t t);
|
API void model_set_texture(model_t*, texture_t t);
|
||||||
|
API bool model_has_transparency_mesh(model_t m, int mesh);
|
||||||
|
API bool model_has_transparency(model_t m);
|
||||||
|
API void model_set_frustum(model_t *m, frustum f);
|
||||||
|
API void model_clear_frustum(model_t *m);
|
||||||
API bool model_get_bone_pose(model_t m, unsigned joint, mat34 *out);
|
API bool model_get_bone_pose(model_t m, unsigned joint, mat34 *out);
|
||||||
API void model_destroy(model_t);
|
API void model_destroy(model_t);
|
||||||
|
|
||||||
|
@ -3951,6 +3960,13 @@ typedef struct object_t {
|
||||||
float anim_speed;
|
float anim_speed;
|
||||||
aabb bounds;
|
aabb bounds;
|
||||||
unsigned billboard; // [0..7] x(4),y(2),z(1) masks
|
unsigned billboard; // [0..7] x(4),y(2),z(1) masks
|
||||||
|
bool disable_frustum_check;
|
||||||
|
|
||||||
|
// internal states
|
||||||
|
array(handle) old_texture_ids;
|
||||||
|
array(texture_t) old_textures;
|
||||||
|
float distance;
|
||||||
|
bool skip_draw;
|
||||||
bool light_cached; //< used by scene to update light data
|
bool light_cached; //< used by scene to update light data
|
||||||
} object_t;
|
} object_t;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue