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;
|
||||
void *tris;
|
||||
vec3 *meshcenters;
|
||||
aabb *meshbounds;
|
||||
float *meshradii;
|
||||
int num_tris;
|
||||
handle vao, ibo, vbo, vao_instanced;
|
||||
int* lod_collapse_map;
|
||||
|
@ -1400,6 +1402,8 @@ typedef struct model_t {
|
|||
unsigned num_instances;
|
||||
int stored_flags;
|
||||
renderstate_t rs[NUM_RENDER_PASSES];
|
||||
bool frustum_enabled;
|
||||
frustum frustum_state;
|
||||
} model_t;
|
||||
enum BILLBOARD_MODE {
|
||||
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_pass(model_t m, mat44 proj, mat44 view, mat44 model, int shader, int pass);
|
||||
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);
|
||||
void model_destroy(model_t);
|
||||
unsigned model_getpass();
|
||||
|
@ -1555,6 +1563,11 @@ typedef struct object_t {
|
|||
float anim_speed;
|
||||
aabb bounds;
|
||||
unsigned billboard;
|
||||
bool disable_frustum_check;
|
||||
handle* old_texture_ids;
|
||||
texture_t* old_textures;
|
||||
float distance;
|
||||
bool skip_draw;
|
||||
bool light_cached;
|
||||
} object_t;
|
||||
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_fps_unlock();
|
||||
|
||||
// load all fx files
|
||||
fx_load("fx**.fs");
|
||||
|
||||
// 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); // --mie for rayleigh/mie scattering
|
||||
skybox_t sky = skybox("bridge3", 0);
|
||||
|
||||
// load static scene
|
||||
model_t map;
|
||||
map = model(option("--model","sorting_test.obj"), 0); // MODEL_NO_TEXTURES);
|
||||
shader_bind(map.program);
|
||||
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_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);
|
||||
|
||||
// apply post-fxs from here
|
||||
fx_begin();
|
||||
|
||||
model_render_pass(map, cam.proj, cam.view, M, 0, -1);
|
||||
|
||||
// post-fxs end here
|
||||
fx_end(0);
|
||||
model_render(map, cam.proj, cam.view, M, 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;
|
||||
void *tris;
|
||||
vec3 *meshcenters;
|
||||
aabb *meshbounds;
|
||||
float *meshradii;
|
||||
int num_tris;
|
||||
handle vao, ibo, vbo, vao_instanced;
|
||||
|
||||
|
@ -17662,6 +17664,9 @@ typedef struct model_t {
|
|||
|
||||
int stored_flags;
|
||||
renderstate_t rs[NUM_RENDER_PASSES];
|
||||
|
||||
bool frustum_enabled;
|
||||
frustum frustum_state;
|
||||
} model_t;
|
||||
|
||||
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_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 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 void model_destroy(model_t);
|
||||
|
||||
|
@ -17884,6 +17893,13 @@ typedef struct object_t {
|
|||
float anim_speed;
|
||||
aabb bounds;
|
||||
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
|
||||
} 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->colormaps = CALLOC(hdr->num_meshes * 8, sizeof(vec4));
|
||||
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++) {
|
||||
int invalid = texture_checker().id;
|
||||
q->textures[i] = invalid;
|
||||
struct iqmmesh *mesh = &q->meshes[i];
|
||||
#if 1
|
||||
GLfloat *pos = verts[q->meshes[i].first_vertex].position;
|
||||
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] : "";
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
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
|
||||
void model_draw_call(model_t m, int shader, int pass, vec3 cam_pos, mat44 model_mat) {
|
||||
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;
|
||||
|
||||
if (required_rs[i] < RENDER_PASS_OVERRIDES_BEGIN) {
|
||||
if (m.flags & MODEL_TRANSPARENT) {
|
||||
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))){
|
||||
if (model_has_transparency_mesh(m, i)) {
|
||||
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
|
||||
// @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)
|
||||
|
@ -386372,6 +386429,8 @@ void model_destroy(model_t m) {
|
|||
}
|
||||
array_free(m.texture_names);
|
||||
FREE(m.meshcenters);
|
||||
FREE(m.meshbounds);
|
||||
FREE(m.meshradii);
|
||||
|
||||
iqm_t *q = m.iqm;
|
||||
// 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];
|
||||
}
|
||||
|
||||
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) {
|
||||
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(last_scene->skybox.program) {
|
||||
|
@ -388047,18 +388114,18 @@ void scene_render(int flags) {
|
|||
model_t *model = &obj->model;
|
||||
anim_t *anim = &obj->anim;
|
||||
mat44 *views = (mat44*)(&cam->view);
|
||||
|
||||
obj->skip_draw = !obj->disable_frustum_check && !frustum_test_aabb(frustum_state, model_aabb(*model, obj->transform));
|
||||
|
||||
// @todo: avoid heap allocs here?
|
||||
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;
|
||||
if( do_retexturing ) {
|
||||
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;
|
||||
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));
|
||||
}
|
||||
}
|
||||
|
@ -388072,32 +388139,80 @@ void scene_render(int flags) {
|
|||
|
||||
if ( flags&SCENE_UPDATE_SH_COEF ) {
|
||||
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);
|
||||
|
||||
if (!obj->disable_frustum_check)
|
||||
model_set_frustum(model, frustum_state);
|
||||
else
|
||||
model_clear_frustum(model);
|
||||
|
||||
if (anim) {
|
||||
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->billboard = obj->billboard;
|
||||
model->rs[RENDER_PASS_OPAQUE].cull_face_enabled = flags&SCENE_CULLFACE ? 1 : 0;
|
||||
model->rs[RENDER_PASS_OPAQUE].polygon_mode_draw = flags&SCENE_WIREFRAME ? GL_LINE : GL_FILL;
|
||||
model_render(*model, cam->proj, cam->view, obj->transform, model->program);
|
||||
for (int p = 0; p < RENDER_PASS_OVERRIDES_BEGIN; ++p) {
|
||||
model->rs[p].cull_face_enabled = flags&SCENE_CULLFACE ? 1 : 0;
|
||||
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 ) {
|
||||
for(int i = 0; i < model->iqm->nummeshes; ++i) {
|
||||
model->iqm->textures[i] = old_texture_ids[i];
|
||||
if (i < array_count(old_textures)) {
|
||||
model->iqm->textures[i] = obj->old_texture_ids[i];
|
||||
if (i < array_count(obj->old_textures)) {
|
||||
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(old_textures, 0);
|
||||
array_resize(obj->old_texture_ids, 0);
|
||||
array_resize(obj->old_textures, 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->colormaps = CALLOC(hdr->num_meshes * 8, sizeof(vec4));
|
||||
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++) {
|
||||
int invalid = texture_checker().id;
|
||||
q->textures[i] = invalid;
|
||||
struct iqmmesh *mesh = &q->meshes[i];
|
||||
#if 1
|
||||
GLfloat *pos = verts[q->meshes[i].first_vertex].position;
|
||||
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] : "";
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
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
|
||||
void model_draw_call(model_t m, int shader, int pass, vec3 cam_pos, mat44 model_mat) {
|
||||
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;
|
||||
|
||||
if (required_rs[i] < RENDER_PASS_OVERRIDES_BEGIN) {
|
||||
if (m.flags & MODEL_TRANSPARENT) {
|
||||
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))){
|
||||
if (model_has_transparency_mesh(m, i)) {
|
||||
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
|
||||
// @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)
|
||||
|
@ -4732,6 +4773,8 @@ void model_destroy(model_t m) {
|
|||
}
|
||||
array_free(m.texture_names);
|
||||
FREE(m.meshcenters);
|
||||
FREE(m.meshbounds);
|
||||
FREE(m.meshradii);
|
||||
|
||||
iqm_t *q = m.iqm;
|
||||
// if(m.mesh) mesh_destroy(m.mesh);
|
||||
|
|
|
@ -677,6 +677,8 @@ typedef struct model_t {
|
|||
int num_verts;
|
||||
void *tris;
|
||||
vec3 *meshcenters;
|
||||
aabb *meshbounds;
|
||||
float *meshradii;
|
||||
int num_tris;
|
||||
handle vao, ibo, vbo, vao_instanced;
|
||||
|
||||
|
@ -694,6 +696,9 @@ typedef struct model_t {
|
|||
|
||||
int stored_flags;
|
||||
renderstate_t rs[NUM_RENDER_PASSES];
|
||||
|
||||
bool frustum_enabled;
|
||||
frustum frustum_state;
|
||||
} model_t;
|
||||
|
||||
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_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 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 void model_destroy(model_t);
|
||||
|
||||
|
|
|
@ -505,8 +505,16 @@ light_t* scene_index_light(unsigned 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) {
|
||||
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(last_scene->skybox.program) {
|
||||
|
@ -532,18 +540,18 @@ void scene_render(int flags) {
|
|||
model_t *model = &obj->model;
|
||||
anim_t *anim = &obj->anim;
|
||||
mat44 *views = (mat44*)(&cam->view);
|
||||
|
||||
obj->skip_draw = !obj->disable_frustum_check && !frustum_test_aabb(frustum_state, model_aabb(*model, obj->transform));
|
||||
|
||||
// @todo: avoid heap allocs here?
|
||||
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;
|
||||
if( do_retexturing ) {
|
||||
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;
|
||||
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));
|
||||
}
|
||||
}
|
||||
|
@ -557,32 +565,80 @@ void scene_render(int flags) {
|
|||
|
||||
if ( flags&SCENE_UPDATE_SH_COEF ) {
|
||||
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);
|
||||
|
||||
if (!obj->disable_frustum_check)
|
||||
model_set_frustum(model, frustum_state);
|
||||
else
|
||||
model_clear_frustum(model);
|
||||
|
||||
if (anim) {
|
||||
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->billboard = obj->billboard;
|
||||
model->rs[RENDER_PASS_OPAQUE].cull_face_enabled = flags&SCENE_CULLFACE ? 1 : 0;
|
||||
model->rs[RENDER_PASS_OPAQUE].polygon_mode_draw = flags&SCENE_WIREFRAME ? GL_LINE : GL_FILL;
|
||||
model_render(*model, cam->proj, cam->view, obj->transform, model->program);
|
||||
for (int p = 0; p < RENDER_PASS_OVERRIDES_BEGIN; ++p) {
|
||||
model->rs[p].cull_face_enabled = flags&SCENE_CULLFACE ? 1 : 0;
|
||||
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 ) {
|
||||
for(int i = 0; i < model->iqm->nummeshes; ++i) {
|
||||
model->iqm->textures[i] = old_texture_ids[i];
|
||||
if (i < array_count(old_textures)) {
|
||||
model->iqm->textures[i] = obj->old_texture_ids[i];
|
||||
if (i < array_count(obj->old_textures)) {
|
||||
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(old_textures, 0);
|
||||
array_resize(obj->old_texture_ids, 0);
|
||||
array_resize(obj->old_textures, 0);
|
||||
}
|
||||
}
|
||||
glBindVertexArray(0);
|
||||
|
|
|
@ -48,6 +48,13 @@ typedef struct object_t {
|
|||
float anim_speed;
|
||||
aabb bounds;
|
||||
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
|
||||
} object_t;
|
||||
|
||||
|
|
147
engine/v4k.c
147
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->colormaps = CALLOC(hdr->num_meshes * 8, sizeof(vec4));
|
||||
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++) {
|
||||
int invalid = texture_checker().id;
|
||||
q->textures[i] = invalid;
|
||||
struct iqmmesh *mesh = &q->meshes[i];
|
||||
#if 1
|
||||
GLfloat *pos = verts[q->meshes[i].first_vertex].position;
|
||||
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] : "";
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
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
|
||||
void model_draw_call(model_t m, int shader, int pass, vec3 cam_pos, mat44 model_mat) {
|
||||
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;
|
||||
|
||||
if (required_rs[i] < RENDER_PASS_OVERRIDES_BEGIN) {
|
||||
if (m.flags & MODEL_TRANSPARENT) {
|
||||
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))){
|
||||
if (model_has_transparency_mesh(m, i)) {
|
||||
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
|
||||
// @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)
|
||||
|
@ -21531,6 +21572,8 @@ void model_destroy(model_t m) {
|
|||
}
|
||||
array_free(m.texture_names);
|
||||
FREE(m.meshcenters);
|
||||
FREE(m.meshbounds);
|
||||
FREE(m.meshradii);
|
||||
|
||||
iqm_t *q = m.iqm;
|
||||
// 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];
|
||||
}
|
||||
|
||||
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) {
|
||||
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(last_scene->skybox.program) {
|
||||
|
@ -23206,18 +23257,18 @@ void scene_render(int flags) {
|
|||
model_t *model = &obj->model;
|
||||
anim_t *anim = &obj->anim;
|
||||
mat44 *views = (mat44*)(&cam->view);
|
||||
|
||||
obj->skip_draw = !obj->disable_frustum_check && !frustum_test_aabb(frustum_state, model_aabb(*model, obj->transform));
|
||||
|
||||
// @todo: avoid heap allocs here?
|
||||
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;
|
||||
if( do_retexturing ) {
|
||||
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;
|
||||
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));
|
||||
}
|
||||
}
|
||||
|
@ -23231,32 +23282,80 @@ void scene_render(int flags) {
|
|||
|
||||
if ( flags&SCENE_UPDATE_SH_COEF ) {
|
||||
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);
|
||||
|
||||
if (!obj->disable_frustum_check)
|
||||
model_set_frustum(model, frustum_state);
|
||||
else
|
||||
model_clear_frustum(model);
|
||||
|
||||
if (anim) {
|
||||
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->billboard = obj->billboard;
|
||||
model->rs[RENDER_PASS_OPAQUE].cull_face_enabled = flags&SCENE_CULLFACE ? 1 : 0;
|
||||
model->rs[RENDER_PASS_OPAQUE].polygon_mode_draw = flags&SCENE_WIREFRAME ? GL_LINE : GL_FILL;
|
||||
model_render(*model, cam->proj, cam->view, obj->transform, model->program);
|
||||
for (int p = 0; p < RENDER_PASS_OVERRIDES_BEGIN; ++p) {
|
||||
model->rs[p].cull_face_enabled = flags&SCENE_CULLFACE ? 1 : 0;
|
||||
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 ) {
|
||||
for(int i = 0; i < model->iqm->nummeshes; ++i) {
|
||||
model->iqm->textures[i] = old_texture_ids[i];
|
||||
if (i < array_count(old_textures)) {
|
||||
model->iqm->textures[i] = obj->old_texture_ids[i];
|
||||
if (i < array_count(obj->old_textures)) {
|
||||
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(old_textures, 0);
|
||||
array_resize(obj->old_texture_ids, 0);
|
||||
array_resize(obj->old_textures, 0);
|
||||
}
|
||||
}
|
||||
glBindVertexArray(0);
|
||||
|
|
16
engine/v4k.h
16
engine/v4k.h
|
@ -3712,6 +3712,8 @@ typedef struct model_t {
|
|||
int num_verts;
|
||||
void *tris;
|
||||
vec3 *meshcenters;
|
||||
aabb *meshbounds;
|
||||
float *meshradii;
|
||||
int num_tris;
|
||||
handle vao, ibo, vbo, vao_instanced;
|
||||
|
||||
|
@ -3729,6 +3731,9 @@ typedef struct model_t {
|
|||
|
||||
int stored_flags;
|
||||
renderstate_t rs[NUM_RENDER_PASSES];
|
||||
|
||||
bool frustum_enabled;
|
||||
frustum frustum_state;
|
||||
} model_t;
|
||||
|
||||
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_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 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 void model_destroy(model_t);
|
||||
|
||||
|
@ -3951,6 +3960,13 @@ typedef struct object_t {
|
|||
float anim_speed;
|
||||
aabb bounds;
|
||||
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
|
||||
} object_t;
|
||||
|
||||
|
|
Loading…
Reference in New Issue