gfx: render pass sorting
parent
7f90d2304c
commit
87e5d825e6
|
@ -242,6 +242,7 @@ typedef float mat44[16];
|
||||||
void frustum44(mat44 m, float l, float r, float b, float t, float n, float f);
|
void frustum44(mat44 m, float l, float r, float b, float t, float n, float f);
|
||||||
void perspective44(mat44 m, float fovy_degrees, float aspect, float nearp, float farp);
|
void perspective44(mat44 m, float fovy_degrees, float aspect, float nearp, float farp);
|
||||||
void lookat44(mat44 m, vec3 eye, vec3 center, vec3 up);
|
void lookat44(mat44 m, vec3 eye, vec3 center, vec3 up);
|
||||||
|
vec3 pos44(mat44 m);
|
||||||
void translation44(mat44 m, float x, float y, float z);
|
void translation44(mat44 m, float x, float y, float z);
|
||||||
void translate44(mat44 m, float x, float y, float z);
|
void translate44(mat44 m, float x, float y, float z);
|
||||||
void relocate44(mat44 m, float x, float y, float z);
|
void relocate44(mat44 m, float x, float y, float z);
|
||||||
|
@ -1328,8 +1329,12 @@ enum SHADING_MODE {
|
||||||
};
|
};
|
||||||
enum RENDER_PASS {
|
enum RENDER_PASS {
|
||||||
RENDER_PASS_OPAQUE,
|
RENDER_PASS_OPAQUE,
|
||||||
|
RENDER_PASS_TRANSPARENT,
|
||||||
|
RENDER_PASS_OVERRIDES_BEGIN,
|
||||||
RENDER_PASS_SHADOW,
|
RENDER_PASS_SHADOW,
|
||||||
RENDER_PASS_LIGHTMAP,
|
RENDER_PASS_LIGHTMAP,
|
||||||
|
RENDER_PASS_CUSTOM,
|
||||||
|
RENDER_PASS_OVERRIDES_END,
|
||||||
NUM_RENDER_PASSES
|
NUM_RENDER_PASSES
|
||||||
};
|
};
|
||||||
enum MODEL_UNIFORMS {
|
enum MODEL_UNIFORMS {
|
||||||
|
@ -1380,6 +1385,7 @@ typedef struct model_t {
|
||||||
void *verts;
|
void *verts;
|
||||||
int num_verts;
|
int num_verts;
|
||||||
void *tris;
|
void *tris;
|
||||||
|
vec3 *meshcenters;
|
||||||
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;
|
||||||
|
@ -1413,6 +1419,8 @@ enum BILLBOARD_MODE {
|
||||||
void model_render(model_t, mat44 proj, mat44 view, mat44 model, int shader);
|
void model_render(model_t, mat44 proj, mat44 view, mat44 model, int shader);
|
||||||
void model_render_skeleton(model_t, mat44 model);
|
void model_render_skeleton(model_t, mat44 model);
|
||||||
void model_render_instanced(model_t, mat44 proj, mat44 view, mat44 *models, int shader, unsigned count);
|
void model_render_instanced(model_t, mat44 proj, mat44 view, mat44 *models, int shader, unsigned count);
|
||||||
|
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);
|
void model_set_texture(model_t, texture_t t);
|
||||||
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);
|
||||||
|
|
|
@ -0,0 +1,64 @@
|
||||||
|
// render map
|
||||||
|
|
||||||
|
#include "v4k.h"
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
window_create(80, WINDOW_MSAA8);
|
||||||
|
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
|
||||||
|
|
||||||
|
// 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();
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,52 @@
|
||||||
|
# Blender 4.2.1 LTS MTL File: 'None'
|
||||||
|
# www.blender.org
|
||||||
|
|
||||||
|
newmtl Material
|
||||||
|
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.001
|
||||||
|
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.002
|
||||||
|
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.003
|
||||||
|
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
|
||||||
|
|
||||||
|
newmtl Material.004
|
||||||
|
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
|
|
@ -0,0 +1,173 @@
|
||||||
|
# Blender 4.2.1 LTS
|
||||||
|
# www.blender.org
|
||||||
|
mtllib sorting_test.mtl
|
||||||
|
o Cube.001
|
||||||
|
v -8.122441 2.199780 2.665483
|
||||||
|
v -8.122441 2.199780 -2.665483
|
||||||
|
v 8.122441 2.199780 2.665483
|
||||||
|
v 8.122441 2.199780 -2.665483
|
||||||
|
v -8.122441 7.530746 2.665483
|
||||||
|
v -8.122441 7.530746 -2.665483
|
||||||
|
v 8.122441 7.530746 2.665483
|
||||||
|
v 8.122441 7.530746 -2.665483
|
||||||
|
v 15.783228 15.783226 -13.899874
|
||||||
|
v 17.600002 17.600000 2.199389
|
||||||
|
v -15.783228 15.783226 -13.899874
|
||||||
|
v -17.600002 17.600000 2.199389
|
||||||
|
v 15.783228 -15.783228 -13.899874
|
||||||
|
v 17.600002 -17.600002 2.199389
|
||||||
|
v -15.783228 -15.783228 -13.899874
|
||||||
|
v -17.600002 -17.600002 2.199389
|
||||||
|
v -17.600002 17.600000 -13.800612
|
||||||
|
v -17.600002 -17.600002 -13.800612
|
||||||
|
v 17.600002 17.600000 -13.800612
|
||||||
|
v 17.600002 -17.600002 -13.800612
|
||||||
|
v -15.783228 15.783226 0.175428
|
||||||
|
v -15.783228 -15.783228 0.175428
|
||||||
|
v 15.783228 15.783226 0.175428
|
||||||
|
v 15.783228 -15.783228 0.175428
|
||||||
|
v -6.691334 2.669416 -2.804010
|
||||||
|
v -6.691334 2.669416 -7.195704
|
||||||
|
v 6.691334 2.669416 -2.804010
|
||||||
|
v 6.691334 2.669416 -7.195704
|
||||||
|
v -6.691334 7.061110 -2.804010
|
||||||
|
v -6.691334 7.061110 -7.195704
|
||||||
|
v 6.691334 7.061110 -2.804010
|
||||||
|
v 6.691334 7.061110 -7.195704
|
||||||
|
v -8.122442 -7.045201 2.665483
|
||||||
|
v -8.122442 -7.045201 -2.665483
|
||||||
|
v 8.122442 -7.045201 2.665483
|
||||||
|
v 8.122442 -7.045201 -2.665483
|
||||||
|
v -8.122442 -1.714234 2.665483
|
||||||
|
v -8.122442 -1.714234 -2.665483
|
||||||
|
v 8.122442 -1.714234 2.665483
|
||||||
|
v 8.122442 -1.714234 -2.665483
|
||||||
|
v -6.691334 -6.575565 -2.804010
|
||||||
|
v -6.691334 -6.575565 -7.195704
|
||||||
|
v 6.691334 -6.575565 -2.804010
|
||||||
|
v 6.691334 -6.575565 -7.195704
|
||||||
|
v -6.691334 -2.183871 -2.804010
|
||||||
|
v -6.691334 -2.183871 -7.195704
|
||||||
|
v 6.691334 -2.183871 -2.804010
|
||||||
|
v 6.691334 -2.183871 -7.195704
|
||||||
|
v -8.122442 -15.615585 2.665483
|
||||||
|
v -8.122442 -15.615585 -2.665483
|
||||||
|
v 8.122442 -15.615585 2.665483
|
||||||
|
v 8.122442 -15.615585 -2.665483
|
||||||
|
v -8.122442 -10.284618 2.665483
|
||||||
|
v -8.122442 -10.284618 -2.665483
|
||||||
|
v 8.122442 -10.284618 2.665483
|
||||||
|
v 8.122442 -10.284618 -2.665483
|
||||||
|
v -6.691334 -15.145948 -2.804010
|
||||||
|
v -6.691334 -15.145948 -7.195704
|
||||||
|
v 6.691334 -15.145948 -2.804010
|
||||||
|
v 6.691334 -15.145948 -7.195704
|
||||||
|
v -6.691334 -10.754253 -2.804010
|
||||||
|
v -6.691334 -10.754253 -7.195704
|
||||||
|
v 6.691334 -10.754253 -2.804010
|
||||||
|
v 6.691334 -10.754253 -7.195704
|
||||||
|
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
|
||||||
|
vn -0.0000 0.7442 -0.6680
|
||||||
|
vn -0.0546 -0.0000 -0.9985
|
||||||
|
vn 0.7071 0.7071 -0.0000
|
||||||
|
vn -0.0000 -0.0546 -0.9985
|
||||||
|
vn 0.0546 -0.0000 -0.9985
|
||||||
|
vn -0.7071 0.7071 -0.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
|
||||||
|
vt 0.815610 0.670937
|
||||||
|
vt 1.086685 0.728059
|
||||||
|
vt 1.066389 0.553695
|
||||||
|
vt 0.851135 0.506484
|
||||||
|
vt 0.286824 0.345736
|
||||||
|
vt 0.332150 0.541159
|
||||||
|
vt 0.086713 0.717651
|
||||||
|
vt 0.066236 0.538218
|
||||||
|
vt 1.066236 0.538218
|
||||||
|
vt 1.086713 0.717651
|
||||||
|
vt 0.816752 0.660765
|
||||||
|
vt 0.852741 0.491363
|
||||||
|
vt 0.621682 0.280820
|
||||||
|
vt 0.289035 0.361544
|
||||||
|
vt 0.620623 0.297043
|
||||||
|
vt 0.589978 0.486593
|
||||||
|
vt 0.333337 0.554977
|
||||||
|
vt 0.086685 0.728059
|
||||||
|
vt 0.589978 0.500567
|
||||||
|
vt 0.066389 0.553695
|
||||||
|
s 0
|
||||||
|
usemtl Material.001
|
||||||
|
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
|
||||||
|
f 33/1/1 34/2/1 36/3/1 35/4/1
|
||||||
|
f 35/4/2 36/3/2 40/5/2 39/6/2
|
||||||
|
f 39/6/3 40/5/3 38/7/3 37/8/3
|
||||||
|
f 37/8/4 38/7/4 34/9/4 33/10/4
|
||||||
|
f 35/11/5 39/6/5 37/8/5 33/12/5
|
||||||
|
f 40/5/6 36/13/6 34/14/6 38/7/6
|
||||||
|
f 49/1/1 50/2/1 52/3/1 51/4/1
|
||||||
|
f 51/4/2 52/3/2 56/5/2 55/6/2
|
||||||
|
f 55/6/3 56/5/3 54/7/3 53/8/3
|
||||||
|
f 53/8/4 54/7/4 50/9/4 49/10/4
|
||||||
|
f 51/11/5 55/6/5 53/8/5 49/12/5
|
||||||
|
f 56/5/6 52/13/6 50/14/6 54/7/6
|
||||||
|
usemtl Material
|
||||||
|
f 13/15/3 15/16/3 22/17/3 24/18/3
|
||||||
|
f 12/19/4 17/20/4 18/21/4 16/22/4
|
||||||
|
f 16/23/1 18/24/1 20/25/1 14/26/1
|
||||||
|
f 14/26/5 10/27/5 12/19/5 16/23/5
|
||||||
|
f 21/28/7 12/19/7 23/29/7
|
||||||
|
f 14/26/2 20/25/2 19/30/2 10/27/2
|
||||||
|
f 11/31/8 15/32/8 18/21/8 17/20/8
|
||||||
|
f 12/19/9 11/31/9 17/20/9
|
||||||
|
f 15/16/10 13/15/10 20/25/10 18/24/10
|
||||||
|
f 13/15/11 9/33/11 19/30/11 20/25/11
|
||||||
|
f 23/29/6 24/18/6 22/17/6 21/28/6
|
||||||
|
f 15/32/2 11/31/2 21/28/2 22/34/2
|
||||||
|
f 9/33/4 13/15/4 24/18/4 23/29/4
|
||||||
|
f 21/28/9 11/31/9 12/19/9
|
||||||
|
f 10/27/7 23/29/7 12/19/7
|
||||||
|
f 23/29/12 10/27/12 9/33/12
|
||||||
|
f 10/27/12 19/30/12 9/33/12
|
||||||
|
usemtl Material.002
|
||||||
|
f 25/1/1 26/2/1 28/3/1 27/4/1
|
||||||
|
f 27/4/2 28/3/2 32/5/2 31/6/2
|
||||||
|
f 31/6/3 32/5/3 30/7/3 29/8/3
|
||||||
|
f 29/8/4 30/7/4 26/9/4 25/10/4
|
||||||
|
f 27/11/5 31/6/5 29/8/5 25/12/5
|
||||||
|
f 32/5/6 28/13/6 26/14/6 30/7/6
|
||||||
|
usemtl Material.004
|
||||||
|
f 41/1/1 42/2/1 44/3/1 43/4/1
|
||||||
|
f 43/4/2 44/3/2 48/5/2 47/6/2
|
||||||
|
f 47/6/3 48/5/3 46/7/3 45/8/3
|
||||||
|
f 45/8/4 46/7/4 42/9/4 41/10/4
|
||||||
|
f 43/11/5 47/6/5 45/8/5 41/12/5
|
||||||
|
f 48/5/6 44/13/6 42/14/6 46/7/6
|
||||||
|
usemtl Material.003
|
||||||
|
f 57/1/1 58/2/1 60/3/1 59/4/1
|
||||||
|
f 59/4/2 60/3/2 64/5/2 63/6/2
|
||||||
|
f 63/6/3 64/5/3 62/7/3 61/8/3
|
||||||
|
f 61/8/4 62/7/4 58/9/4 57/10/4
|
||||||
|
f 59/11/5 63/6/5 61/8/5 57/12/5
|
||||||
|
f 64/5/6 60/13/6 58/14/6 62/7/6
|
|
@ -15135,6 +15135,7 @@ API void ortho44(mat44 m, float l, float r, float b, float t, float n, float f);
|
||||||
API void frustum44(mat44 m, float l, float r, float b, float t, float n, float f);
|
API void frustum44(mat44 m, float l, float r, float b, float t, float n, float f);
|
||||||
API void perspective44(mat44 m, float fovy_degrees, float aspect, float nearp, float farp);
|
API void perspective44(mat44 m, float fovy_degrees, float aspect, float nearp, float farp);
|
||||||
API void lookat44(mat44 m, vec3 eye, vec3 center, vec3 up);
|
API void lookat44(mat44 m, vec3 eye, vec3 center, vec3 up);
|
||||||
|
API vec3 pos44(mat44 m);
|
||||||
// ---
|
// ---
|
||||||
API void translation44(mat44 m, float x, float y, float z);
|
API void translation44(mat44 m, float x, float y, float z);
|
||||||
API void translate44(mat44 m, float x, float y, float z);
|
API void translate44(mat44 m, float x, float y, float z);
|
||||||
|
@ -17575,8 +17576,13 @@ enum SHADING_MODE {
|
||||||
|
|
||||||
enum RENDER_PASS {
|
enum RENDER_PASS {
|
||||||
RENDER_PASS_OPAQUE,
|
RENDER_PASS_OPAQUE,
|
||||||
|
RENDER_PASS_TRANSPARENT,
|
||||||
|
|
||||||
|
RENDER_PASS_OVERRIDES_BEGIN,
|
||||||
RENDER_PASS_SHADOW,
|
RENDER_PASS_SHADOW,
|
||||||
RENDER_PASS_LIGHTMAP,
|
RENDER_PASS_LIGHTMAP,
|
||||||
|
RENDER_PASS_CUSTOM, // make sure to apply renderstate before calling this
|
||||||
|
RENDER_PASS_OVERRIDES_END,
|
||||||
|
|
||||||
NUM_RENDER_PASSES
|
NUM_RENDER_PASSES
|
||||||
};
|
};
|
||||||
|
@ -17637,6 +17643,7 @@ typedef struct model_t {
|
||||||
void *verts;
|
void *verts;
|
||||||
int num_verts;
|
int num_verts;
|
||||||
void *tris;
|
void *tris;
|
||||||
|
vec3 *meshcenters;
|
||||||
int num_tris;
|
int num_tris;
|
||||||
handle vao, ibo, vbo, vao_instanced;
|
handle vao, ibo, vbo, vao_instanced;
|
||||||
|
|
||||||
|
@ -17677,6 +17684,8 @@ API void model_skybox(model_t*, skybox_t sky, bool load_sh);
|
||||||
API void model_render(model_t, mat44 proj, mat44 view, mat44 model, int shader);
|
API void model_render(model_t, mat44 proj, mat44 view, mat44 model, int shader);
|
||||||
API void model_render_skeleton(model_t, mat44 model);
|
API void model_render_skeleton(model_t, mat44 model);
|
||||||
API void model_render_instanced(model_t, mat44 proj, mat44 view, mat44 *models, int shader, unsigned count);
|
API void model_render_instanced(model_t, mat44 proj, mat44 view, mat44 *models, int shader, unsigned count);
|
||||||
|
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 void model_set_texture(model_t, texture_t t);
|
||||||
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);
|
||||||
|
@ -377451,6 +377460,20 @@ void lookat44(mat44 m, vec3 eye, vec3 center, vec3 up) {
|
||||||
m[ 8] = r.z; m[ 9] = u.z; m[10] = -f.z; m[11] = 0;
|
m[ 8] = r.z; m[ 9] = u.z; m[10] = -f.z; m[11] = 0;
|
||||||
m[12] = -dot3(r, eye); m[13] = -dot3(u, eye); m[14] = dot3(f, eye); m[15] = 1;
|
m[12] = -dot3(r, eye); m[13] = -dot3(u, eye); m[14] = dot3(f, eye); m[15] = 1;
|
||||||
}
|
}
|
||||||
|
vec3 pos44(mat44 m) {
|
||||||
|
vec3 position;
|
||||||
|
|
||||||
|
// The camera position is the negation of the translation vector
|
||||||
|
// transformed by the inverse of the rotation matrix.
|
||||||
|
// Since the upper-left 3x3 part of the view matrix is orthogonal,
|
||||||
|
// its inverse is equal to its transpose.
|
||||||
|
|
||||||
|
position.x = -(m[0] * m[12] + m[1] * m[13] + m[2] * m[14]);
|
||||||
|
position.y = -(m[4] * m[12] + m[5] * m[13] + m[6] * m[14]);
|
||||||
|
position.z = -(m[8] * m[12] + m[9] * m[13] + m[10] * m[14]);
|
||||||
|
|
||||||
|
return position;
|
||||||
|
}
|
||||||
// ---
|
// ---
|
||||||
void translation44(mat44 m, float x, float y, float z) { // identity4 + translate4
|
void translation44(mat44 m, float x, float y, float z) { // identity4 + translate4
|
||||||
m[ 0] = 1.0f; m[ 1] = 0.0f; m[ 2] = 0.0f; m[ 3] = 0.0f;
|
m[ 0] = 1.0f; m[ 1] = 0.0f; m[ 2] = 0.0f; m[ 3] = 0.0f;
|
||||||
|
@ -382590,6 +382613,16 @@ max_aniso = 4;
|
||||||
t->n = n;
|
t->n = n;
|
||||||
t->flags = flags;
|
t->flags = flags;
|
||||||
t->filename = t->filename ? t->filename : "";
|
t->filename = t->filename ? t->filename : "";
|
||||||
|
t->transparent = 0;
|
||||||
|
|
||||||
|
if (t->n == 4 && pixels) {
|
||||||
|
for (int i = 0; i < w * h; i++) {
|
||||||
|
if (((uint8_t *)pixels)[i * 4 + 3] < 255) {
|
||||||
|
t->transparent = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return t->id;
|
return t->id;
|
||||||
}
|
}
|
||||||
|
@ -382598,7 +382631,6 @@ texture_t texture_create(unsigned w, unsigned h, unsigned n, const void *pixels,
|
||||||
texture_t texture = {0};
|
texture_t texture = {0};
|
||||||
glGenTextures( 1, &texture.id );
|
glGenTextures( 1, &texture.id );
|
||||||
texture_update( &texture, w, h, n, pixels, flags );
|
texture_update( &texture, w, h, n, pixels, flags );
|
||||||
texture.transparent = texture.n > 3; // @fixme: should be true only if any pixel.a == 0
|
|
||||||
return texture;
|
return texture;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -384902,12 +384934,12 @@ void model_set_uniforms(model_t m, int shader, mat44 mv, mat44 proj, mat44 view,
|
||||||
glUniformMatrix4fv( loc, 1, GL_FALSE, vp);
|
glUniformMatrix4fv( loc, 1, GL_FALSE, vp);
|
||||||
}
|
}
|
||||||
if( (loc = glGetUniformLocation(shader, "u_cam_pos")) >= 0 ) {
|
if( (loc = glGetUniformLocation(shader, "u_cam_pos")) >= 0 ) {
|
||||||
vec3 pos = vec3(view[12], view[13], view[14]);
|
vec3 pos = pos44(view);
|
||||||
glUniform3fv( loc, 1, &pos.x );
|
glUniform3fv( loc, 1, &pos.x );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
if( (loc = glGetUniformLocation(shader, "cam_pos")) >= 0 ) {
|
if( (loc = glGetUniformLocation(shader, "cam_pos")) >= 0 ) {
|
||||||
vec3 pos = vec3(view[12], view[13], view[14]);
|
vec3 pos = pos44(view);
|
||||||
glUniform3fv( loc, 1, &pos.x );
|
glUniform3fv( loc, 1, &pos.x );
|
||||||
}
|
}
|
||||||
if( (loc = glGetUniformLocation(shader, "u_cam_dir")) >= 0 ) {
|
if( (loc = glGetUniformLocation(shader, "u_cam_dir")) >= 0 ) {
|
||||||
|
@ -385208,9 +385240,13 @@ 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));
|
||||||
|
|
||||||
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;
|
||||||
|
GLfloat *pos = verts[q->meshes[i].first_vertex].position;
|
||||||
|
m->meshcenters[i] = vec3(pos[0], pos[1], pos[2]);
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *str = hdr->ofs_text ? (char *)&q->buf[hdr->ofs_text] : "";
|
const char *str = hdr->ofs_text ? (char *)&q->buf[hdr->ofs_text] : "";
|
||||||
|
@ -385304,7 +385340,7 @@ void model_load_pbr_layer(material_layer_t *layer, const char *texname, bool loa
|
||||||
static
|
static
|
||||||
void model_load_pbr(material_t *mt) {
|
void model_load_pbr(material_t *mt) {
|
||||||
// initialise default colors
|
// initialise default colors
|
||||||
mt->layer[MATERIAL_CHANNEL_DIFFUSE].map.color = vec4(0.5,0.5,0.5,0.5);
|
mt->layer[MATERIAL_CHANNEL_DIFFUSE].map.color = vec4(0.5,0.5,0.5,1.0);
|
||||||
mt->layer[MATERIAL_CHANNEL_NORMALS].map.color = vec4(0,0,0,0);
|
mt->layer[MATERIAL_CHANNEL_NORMALS].map.color = vec4(0,0,0,0);
|
||||||
mt->layer[MATERIAL_CHANNEL_SPECULAR].map.color = vec4(0,0,0,0);
|
mt->layer[MATERIAL_CHANNEL_SPECULAR].map.color = vec4(0,0,0,0);
|
||||||
mt->layer[MATERIAL_CHANNEL_SPECULAR].value = 1.0f; // specular_shininess
|
mt->layer[MATERIAL_CHANNEL_SPECULAR].value = 1.0f; // specular_shininess
|
||||||
|
@ -385504,13 +385540,21 @@ void model_set_renderstates(model_t *m) {
|
||||||
// Opaque pass
|
// Opaque pass
|
||||||
renderstate_t *opaque_rs = &m->rs[RENDER_PASS_OPAQUE];
|
renderstate_t *opaque_rs = &m->rs[RENDER_PASS_OPAQUE];
|
||||||
{
|
{
|
||||||
opaque_rs->blend_enabled = 1;
|
opaque_rs->blend_enabled = 0;
|
||||||
opaque_rs->blend_src = GL_SRC_ALPHA;
|
|
||||||
opaque_rs->blend_dst = GL_ONE_MINUS_SRC_ALPHA;
|
|
||||||
opaque_rs->cull_face_mode = GL_BACK;
|
opaque_rs->cull_face_mode = GL_BACK;
|
||||||
opaque_rs->front_face = GL_CW;
|
opaque_rs->front_face = GL_CW;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Transparent pass
|
||||||
|
renderstate_t *transparent_rs = &m->rs[RENDER_PASS_TRANSPARENT];
|
||||||
|
{
|
||||||
|
transparent_rs->blend_enabled = 1;
|
||||||
|
transparent_rs->blend_src = GL_SRC_ALPHA;
|
||||||
|
transparent_rs->blend_dst = GL_ONE_MINUS_SRC_ALPHA;
|
||||||
|
transparent_rs->cull_face_mode = GL_BACK;
|
||||||
|
transparent_rs->front_face = GL_CW;
|
||||||
|
}
|
||||||
|
|
||||||
// Shadow pass @todo
|
// Shadow pass @todo
|
||||||
renderstate_t *shadow_rs = &m->rs[RENDER_PASS_SHADOW];
|
renderstate_t *shadow_rs = &m->rs[RENDER_PASS_SHADOW];
|
||||||
{
|
{
|
||||||
|
@ -385805,23 +385849,115 @@ void shader_colormap_model_internal(const char *col_name, const char *bool_name,
|
||||||
if( c.texture ) shader_texture( tex_name, *c.texture );
|
if( c.texture ) shader_texture( tex_name, *c.texture );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct drawcall_t {
|
||||||
|
model_t *m;
|
||||||
|
int mesh;
|
||||||
|
union {
|
||||||
|
uint64_t order;
|
||||||
|
struct {
|
||||||
|
uint32_t tex;
|
||||||
|
float distance;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
} drawcall_t;
|
||||||
|
|
||||||
static
|
static
|
||||||
void model_draw_call(model_t m, int shader) {
|
int drawcall_compare(const void *a, const void *b) {
|
||||||
|
const drawcall_t *da = a, *db = b;
|
||||||
|
return da->order < db->order ? 1 : da->order > db->order ? -1 : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
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;
|
||||||
iqm_t *q = m.iqm;
|
iqm_t *q = m.iqm;
|
||||||
|
|
||||||
handle old_shader = last_shader;
|
handle old_shader = last_shader;
|
||||||
shader_bind(shader);
|
shader_bind(shader);
|
||||||
|
|
||||||
renderstate_t *rs = &m.rs[RENDER_PASS_OPAQUE];
|
int rs_idx = model_getpass();
|
||||||
|
renderstate_t *rs = &m.rs[rs_idx];
|
||||||
renderstate_apply(rs);
|
|
||||||
|
|
||||||
glBindVertexArray( q->vao );
|
glBindVertexArray( q->vao );
|
||||||
|
|
||||||
struct iqmtriangle *tris = NULL;
|
static array(int) required_rs = 0;
|
||||||
|
array_resize(required_rs, q->nummeshes);
|
||||||
|
|
||||||
for(int i = 0; i < q->nummeshes; i++) {
|
for(int i = 0; i < q->nummeshes; i++) {
|
||||||
struct iqmmesh *im = &q->meshes[i];
|
struct iqmmesh *im = &q->meshes[i];
|
||||||
|
required_rs[i] = rs_idx;
|
||||||
|
|
||||||
|
if (required_rs[i] < RENDER_PASS_OVERRIDES_BEGIN) {
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static array(drawcall_t) drawcalls = 0;
|
||||||
|
array_resize(drawcalls, 0);
|
||||||
|
|
||||||
|
if (rs_idx > RENDER_PASS_OVERRIDES_BEGIN) {
|
||||||
|
for(int i = 0; i < q->nummeshes; i++) {
|
||||||
|
array_push(drawcalls, (drawcall_t){i, 0});
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if(pass == -1 || pass == RENDER_PASS_OPAQUE) {
|
||||||
|
for(int i = 0; i < q->nummeshes; i++) {
|
||||||
|
// collect opaque drawcalls
|
||||||
|
if (required_rs[i] == RENDER_PASS_OPAQUE) {
|
||||||
|
drawcall_t call;
|
||||||
|
call.mesh = i;
|
||||||
|
call.tex = m.textures[i];
|
||||||
|
call.distance = -1;
|
||||||
|
if (m.shading == SHADING_PBR)
|
||||||
|
call.tex = m.materials[i].layer[MATERIAL_CHANNEL_ALBEDO].map.texture ? m.materials[i].layer[MATERIAL_CHANNEL_ALBEDO].map.texture->id : m.materials[i].layer[MATERIAL_CHANNEL_DIFFUSE].map.texture ? m.materials[i].layer[MATERIAL_CHANNEL_DIFFUSE].map.texture->id : texture_checker().id;
|
||||||
|
array_push(drawcalls, call);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(pass == -1 || pass == RENDER_PASS_TRANSPARENT) {
|
||||||
|
for(int i = 0; i < q->nummeshes; i++) {
|
||||||
|
// collect transparent drawcalls
|
||||||
|
if (required_rs[i] == RENDER_PASS_TRANSPARENT) {
|
||||||
|
drawcall_t call;
|
||||||
|
call.mesh = i;
|
||||||
|
call.tex = m.textures[i];
|
||||||
|
|
||||||
|
// calculate distance from camera
|
||||||
|
// @todo: improve me, uses first mesh triangle
|
||||||
|
{
|
||||||
|
call.distance = len3(sub3(cam_pos, transform344(model_mat, m.meshcenters[i])));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m.shading == SHADING_PBR)
|
||||||
|
call.tex = m.materials[i].layer[MATERIAL_CHANNEL_ALBEDO].map.texture ? m.materials[i].layer[MATERIAL_CHANNEL_ALBEDO].map.texture->id : m.materials[i].layer[MATERIAL_CHANNEL_DIFFUSE].map.texture ? m.materials[i].layer[MATERIAL_CHANNEL_DIFFUSE].map.texture->id : texture_checker().id;
|
||||||
|
array_push(drawcalls, call);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// sort drawcalls by order
|
||||||
|
array_sort(drawcalls, drawcall_compare);
|
||||||
|
|
||||||
|
struct iqmtriangle *tris = NULL;
|
||||||
|
for(int di = 0; di < array_count(drawcalls); di++) {
|
||||||
|
int i = drawcalls[di].mesh;
|
||||||
|
struct iqmmesh *im = &q->meshes[i];
|
||||||
|
|
||||||
|
if (pass != -1 && pass != required_rs[i]) continue;
|
||||||
|
|
||||||
|
if (rs_idx != required_rs[i]) {
|
||||||
|
rs_idx = required_rs[i];
|
||||||
|
rs = &m.rs[rs_idx];
|
||||||
|
renderstate_apply(rs);
|
||||||
|
}
|
||||||
|
|
||||||
if (m.shading != SHADING_PBR) {
|
if (m.shading != SHADING_PBR) {
|
||||||
shader_texture_unit("u_texture2d", q->textures[i], texture_unit());
|
shader_texture_unit("u_texture2d", q->textures[i], texture_unit());
|
||||||
|
@ -385860,7 +385996,7 @@ void model_draw_call(model_t m, int shader) {
|
||||||
shader_bind(old_shader);
|
shader_bind(old_shader);
|
||||||
}
|
}
|
||||||
|
|
||||||
void model_render_instanced(model_t m, mat44 proj, mat44 view, mat44* models, int shader, unsigned count) {
|
void model_render_instanced_pass(model_t m, mat44 proj, mat44 view, mat44* models, int shader, unsigned count, int pass) {
|
||||||
if(!m.iqm) return;
|
if(!m.iqm) return;
|
||||||
iqm_t *q = m.iqm;
|
iqm_t *q = m.iqm;
|
||||||
|
|
||||||
|
@ -385873,11 +386009,19 @@ void model_render_instanced(model_t m, mat44 proj, mat44 view, mat44* models, in
|
||||||
}
|
}
|
||||||
|
|
||||||
model_set_uniforms(m, shader > 0 ? shader : m.program, mv, proj, view, models[0]);
|
model_set_uniforms(m, shader > 0 ? shader : m.program, mv, proj, view, models[0]);
|
||||||
model_draw_call(m, shader > 0 ? shader : m.program);
|
model_draw_call(m, shader > 0 ? shader : m.program, pass, pos44(view), models[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
void model_render_instanced(model_t m, mat44 proj, mat44 view, mat44* models, int shader, unsigned count) {
|
||||||
|
model_render_instanced_pass(m, proj, view, models, shader, count, -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void model_render_pass(model_t m, mat44 proj, mat44 view, mat44 model, int shader, int pass) {
|
||||||
|
model_render_instanced_pass(m, proj, view, (mat44*)model, shader, 1, pass);
|
||||||
}
|
}
|
||||||
|
|
||||||
void model_render(model_t m, mat44 proj, mat44 view, mat44 model, int shader) {
|
void model_render(model_t m, mat44 proj, mat44 view, mat44 model, int shader) {
|
||||||
model_render_instanced(m, proj, view, (mat44*)model, shader, 1);
|
model_render_pass(m, proj, view, model, shader, -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline
|
static inline
|
||||||
|
@ -386216,6 +386360,7 @@ void model_destroy(model_t m) {
|
||||||
FREE(m.texture_names[i]);
|
FREE(m.texture_names[i]);
|
||||||
}
|
}
|
||||||
array_free(m.texture_names);
|
array_free(m.texture_names);
|
||||||
|
FREE(m.meshcenters);
|
||||||
|
|
||||||
iqm_t *q = m.iqm;
|
iqm_t *q = m.iqm;
|
||||||
// if(m.mesh) mesh_destroy(m.mesh);
|
// if(m.mesh) mesh_destroy(m.mesh);
|
||||||
|
@ -386239,6 +386384,7 @@ unsigned model_getpass() {
|
||||||
|
|
||||||
unsigned model_setpass(unsigned pass) {
|
unsigned model_setpass(unsigned pass) {
|
||||||
ASSERT(pass < NUM_RENDER_PASSES);
|
ASSERT(pass < NUM_RENDER_PASSES);
|
||||||
|
ASSERT(pass != RENDER_PASS_OVERRIDES_BEGIN && pass != RENDER_PASS_OVERRIDES_END);
|
||||||
unsigned old_pass = model_renderpass;
|
unsigned old_pass = model_renderpass;
|
||||||
model_renderpass = pass;
|
model_renderpass = pass;
|
||||||
return old_pass;
|
return old_pass;
|
||||||
|
@ -386304,6 +386450,7 @@ void lightmap_bake(lightmap_t *lm, int bounces, void (*drawscene)(lightmap_t *lm
|
||||||
unsigned old_pass = model_setpass(RENDER_PASS_LIGHTMAP);
|
unsigned old_pass = model_setpass(RENDER_PASS_LIGHTMAP);
|
||||||
|
|
||||||
for (int b = 0; b < bounces; b++) {
|
for (int b = 0; b < bounces; b++) {
|
||||||
|
model_setpass(RENDER_PASS_LIGHTMAP);
|
||||||
for (int i = 0; i < array_count(lm->models); i++) {
|
for (int i = 0; i < array_count(lm->models); i++) {
|
||||||
model_t *m = lm->models[i];
|
model_t *m = lm->models[i];
|
||||||
if (!m->lmdata) {
|
if (!m->lmdata) {
|
||||||
|
|
|
@ -522,6 +522,20 @@ void lookat44(mat44 m, vec3 eye, vec3 center, vec3 up) {
|
||||||
m[ 8] = r.z; m[ 9] = u.z; m[10] = -f.z; m[11] = 0;
|
m[ 8] = r.z; m[ 9] = u.z; m[10] = -f.z; m[11] = 0;
|
||||||
m[12] = -dot3(r, eye); m[13] = -dot3(u, eye); m[14] = dot3(f, eye); m[15] = 1;
|
m[12] = -dot3(r, eye); m[13] = -dot3(u, eye); m[14] = dot3(f, eye); m[15] = 1;
|
||||||
}
|
}
|
||||||
|
vec3 pos44(mat44 m) {
|
||||||
|
vec3 position;
|
||||||
|
|
||||||
|
// The camera position is the negation of the translation vector
|
||||||
|
// transformed by the inverse of the rotation matrix.
|
||||||
|
// Since the upper-left 3x3 part of the view matrix is orthogonal,
|
||||||
|
// its inverse is equal to its transpose.
|
||||||
|
|
||||||
|
position.x = -(m[0] * m[12] + m[1] * m[13] + m[2] * m[14]);
|
||||||
|
position.y = -(m[4] * m[12] + m[5] * m[13] + m[6] * m[14]);
|
||||||
|
position.z = -(m[8] * m[12] + m[9] * m[13] + m[10] * m[14]);
|
||||||
|
|
||||||
|
return position;
|
||||||
|
}
|
||||||
// ---
|
// ---
|
||||||
void translation44(mat44 m, float x, float y, float z) { // identity4 + translate4
|
void translation44(mat44 m, float x, float y, float z) { // identity4 + translate4
|
||||||
m[ 0] = 1.0f; m[ 1] = 0.0f; m[ 2] = 0.0f; m[ 3] = 0.0f;
|
m[ 0] = 1.0f; m[ 1] = 0.0f; m[ 2] = 0.0f; m[ 3] = 0.0f;
|
||||||
|
|
|
@ -243,6 +243,7 @@ API void ortho44(mat44 m, float l, float r, float b, float t, float n, float f);
|
||||||
API void frustum44(mat44 m, float l, float r, float b, float t, float n, float f);
|
API void frustum44(mat44 m, float l, float r, float b, float t, float n, float f);
|
||||||
API void perspective44(mat44 m, float fovy_degrees, float aspect, float nearp, float farp);
|
API void perspective44(mat44 m, float fovy_degrees, float aspect, float nearp, float farp);
|
||||||
API void lookat44(mat44 m, vec3 eye, vec3 center, vec3 up);
|
API void lookat44(mat44 m, vec3 eye, vec3 center, vec3 up);
|
||||||
|
API vec3 pos44(mat44 m);
|
||||||
// ---
|
// ---
|
||||||
API void translation44(mat44 m, float x, float y, float z);
|
API void translation44(mat44 m, float x, float y, float z);
|
||||||
API void translate44(mat44 m, float x, float y, float z);
|
API void translate44(mat44 m, float x, float y, float z);
|
||||||
|
|
|
@ -974,6 +974,16 @@ max_aniso = 4;
|
||||||
t->n = n;
|
t->n = n;
|
||||||
t->flags = flags;
|
t->flags = flags;
|
||||||
t->filename = t->filename ? t->filename : "";
|
t->filename = t->filename ? t->filename : "";
|
||||||
|
t->transparent = 0;
|
||||||
|
|
||||||
|
if (t->n == 4 && pixels) {
|
||||||
|
for (int i = 0; i < w * h; i++) {
|
||||||
|
if (((uint8_t *)pixels)[i * 4 + 3] < 255) {
|
||||||
|
t->transparent = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return t->id;
|
return t->id;
|
||||||
}
|
}
|
||||||
|
@ -982,7 +992,6 @@ texture_t texture_create(unsigned w, unsigned h, unsigned n, const void *pixels,
|
||||||
texture_t texture = {0};
|
texture_t texture = {0};
|
||||||
glGenTextures( 1, &texture.id );
|
glGenTextures( 1, &texture.id );
|
||||||
texture_update( &texture, w, h, n, pixels, flags );
|
texture_update( &texture, w, h, n, pixels, flags );
|
||||||
texture.transparent = texture.n > 3; // @fixme: should be true only if any pixel.a == 0
|
|
||||||
return texture;
|
return texture;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3286,12 +3295,12 @@ void model_set_uniforms(model_t m, int shader, mat44 mv, mat44 proj, mat44 view,
|
||||||
glUniformMatrix4fv( loc, 1, GL_FALSE, vp);
|
glUniformMatrix4fv( loc, 1, GL_FALSE, vp);
|
||||||
}
|
}
|
||||||
if( (loc = glGetUniformLocation(shader, "u_cam_pos")) >= 0 ) {
|
if( (loc = glGetUniformLocation(shader, "u_cam_pos")) >= 0 ) {
|
||||||
vec3 pos = vec3(view[12], view[13], view[14]);
|
vec3 pos = pos44(view);
|
||||||
glUniform3fv( loc, 1, &pos.x );
|
glUniform3fv( loc, 1, &pos.x );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
if( (loc = glGetUniformLocation(shader, "cam_pos")) >= 0 ) {
|
if( (loc = glGetUniformLocation(shader, "cam_pos")) >= 0 ) {
|
||||||
vec3 pos = vec3(view[12], view[13], view[14]);
|
vec3 pos = pos44(view);
|
||||||
glUniform3fv( loc, 1, &pos.x );
|
glUniform3fv( loc, 1, &pos.x );
|
||||||
}
|
}
|
||||||
if( (loc = glGetUniformLocation(shader, "u_cam_dir")) >= 0 ) {
|
if( (loc = glGetUniformLocation(shader, "u_cam_dir")) >= 0 ) {
|
||||||
|
@ -3592,9 +3601,13 @@ 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));
|
||||||
|
|
||||||
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;
|
||||||
|
GLfloat *pos = verts[q->meshes[i].first_vertex].position;
|
||||||
|
m->meshcenters[i] = vec3(pos[0], pos[1], pos[2]);
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *str = hdr->ofs_text ? (char *)&q->buf[hdr->ofs_text] : "";
|
const char *str = hdr->ofs_text ? (char *)&q->buf[hdr->ofs_text] : "";
|
||||||
|
@ -3688,7 +3701,7 @@ void model_load_pbr_layer(material_layer_t *layer, const char *texname, bool loa
|
||||||
static
|
static
|
||||||
void model_load_pbr(material_t *mt) {
|
void model_load_pbr(material_t *mt) {
|
||||||
// initialise default colors
|
// initialise default colors
|
||||||
mt->layer[MATERIAL_CHANNEL_DIFFUSE].map.color = vec4(0.5,0.5,0.5,0.5);
|
mt->layer[MATERIAL_CHANNEL_DIFFUSE].map.color = vec4(0.5,0.5,0.5,1.0);
|
||||||
mt->layer[MATERIAL_CHANNEL_NORMALS].map.color = vec4(0,0,0,0);
|
mt->layer[MATERIAL_CHANNEL_NORMALS].map.color = vec4(0,0,0,0);
|
||||||
mt->layer[MATERIAL_CHANNEL_SPECULAR].map.color = vec4(0,0,0,0);
|
mt->layer[MATERIAL_CHANNEL_SPECULAR].map.color = vec4(0,0,0,0);
|
||||||
mt->layer[MATERIAL_CHANNEL_SPECULAR].value = 1.0f; // specular_shininess
|
mt->layer[MATERIAL_CHANNEL_SPECULAR].value = 1.0f; // specular_shininess
|
||||||
|
@ -3888,13 +3901,21 @@ void model_set_renderstates(model_t *m) {
|
||||||
// Opaque pass
|
// Opaque pass
|
||||||
renderstate_t *opaque_rs = &m->rs[RENDER_PASS_OPAQUE];
|
renderstate_t *opaque_rs = &m->rs[RENDER_PASS_OPAQUE];
|
||||||
{
|
{
|
||||||
opaque_rs->blend_enabled = 1;
|
opaque_rs->blend_enabled = 0;
|
||||||
opaque_rs->blend_src = GL_SRC_ALPHA;
|
|
||||||
opaque_rs->blend_dst = GL_ONE_MINUS_SRC_ALPHA;
|
|
||||||
opaque_rs->cull_face_mode = GL_BACK;
|
opaque_rs->cull_face_mode = GL_BACK;
|
||||||
opaque_rs->front_face = GL_CW;
|
opaque_rs->front_face = GL_CW;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Transparent pass
|
||||||
|
renderstate_t *transparent_rs = &m->rs[RENDER_PASS_TRANSPARENT];
|
||||||
|
{
|
||||||
|
transparent_rs->blend_enabled = 1;
|
||||||
|
transparent_rs->blend_src = GL_SRC_ALPHA;
|
||||||
|
transparent_rs->blend_dst = GL_ONE_MINUS_SRC_ALPHA;
|
||||||
|
transparent_rs->cull_face_mode = GL_BACK;
|
||||||
|
transparent_rs->front_face = GL_CW;
|
||||||
|
}
|
||||||
|
|
||||||
// Shadow pass @todo
|
// Shadow pass @todo
|
||||||
renderstate_t *shadow_rs = &m->rs[RENDER_PASS_SHADOW];
|
renderstate_t *shadow_rs = &m->rs[RENDER_PASS_SHADOW];
|
||||||
{
|
{
|
||||||
|
@ -4189,23 +4210,115 @@ void shader_colormap_model_internal(const char *col_name, const char *bool_name,
|
||||||
if( c.texture ) shader_texture( tex_name, *c.texture );
|
if( c.texture ) shader_texture( tex_name, *c.texture );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct drawcall_t {
|
||||||
|
model_t *m;
|
||||||
|
int mesh;
|
||||||
|
union {
|
||||||
|
uint64_t order;
|
||||||
|
struct {
|
||||||
|
uint32_t tex;
|
||||||
|
float distance;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
} drawcall_t;
|
||||||
|
|
||||||
static
|
static
|
||||||
void model_draw_call(model_t m, int shader) {
|
int drawcall_compare(const void *a, const void *b) {
|
||||||
|
const drawcall_t *da = a, *db = b;
|
||||||
|
return da->order < db->order ? 1 : da->order > db->order ? -1 : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
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;
|
||||||
iqm_t *q = m.iqm;
|
iqm_t *q = m.iqm;
|
||||||
|
|
||||||
handle old_shader = last_shader;
|
handle old_shader = last_shader;
|
||||||
shader_bind(shader);
|
shader_bind(shader);
|
||||||
|
|
||||||
renderstate_t *rs = &m.rs[RENDER_PASS_OPAQUE];
|
int rs_idx = model_getpass();
|
||||||
|
renderstate_t *rs = &m.rs[rs_idx];
|
||||||
renderstate_apply(rs);
|
|
||||||
|
|
||||||
glBindVertexArray( q->vao );
|
glBindVertexArray( q->vao );
|
||||||
|
|
||||||
struct iqmtriangle *tris = NULL;
|
static array(int) required_rs = 0;
|
||||||
|
array_resize(required_rs, q->nummeshes);
|
||||||
|
|
||||||
for(int i = 0; i < q->nummeshes; i++) {
|
for(int i = 0; i < q->nummeshes; i++) {
|
||||||
struct iqmmesh *im = &q->meshes[i];
|
struct iqmmesh *im = &q->meshes[i];
|
||||||
|
required_rs[i] = rs_idx;
|
||||||
|
|
||||||
|
if (required_rs[i] < RENDER_PASS_OVERRIDES_BEGIN) {
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static array(drawcall_t) drawcalls = 0;
|
||||||
|
array_resize(drawcalls, 0);
|
||||||
|
|
||||||
|
if (rs_idx > RENDER_PASS_OVERRIDES_BEGIN) {
|
||||||
|
for(int i = 0; i < q->nummeshes; i++) {
|
||||||
|
array_push(drawcalls, (drawcall_t){i, 0});
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if(pass == -1 || pass == RENDER_PASS_OPAQUE) {
|
||||||
|
for(int i = 0; i < q->nummeshes; i++) {
|
||||||
|
// collect opaque drawcalls
|
||||||
|
if (required_rs[i] == RENDER_PASS_OPAQUE) {
|
||||||
|
drawcall_t call;
|
||||||
|
call.mesh = i;
|
||||||
|
call.tex = m.textures[i];
|
||||||
|
call.distance = -1;
|
||||||
|
if (m.shading == SHADING_PBR)
|
||||||
|
call.tex = m.materials[i].layer[MATERIAL_CHANNEL_ALBEDO].map.texture ? m.materials[i].layer[MATERIAL_CHANNEL_ALBEDO].map.texture->id : m.materials[i].layer[MATERIAL_CHANNEL_DIFFUSE].map.texture ? m.materials[i].layer[MATERIAL_CHANNEL_DIFFUSE].map.texture->id : texture_checker().id;
|
||||||
|
array_push(drawcalls, call);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(pass == -1 || pass == RENDER_PASS_TRANSPARENT) {
|
||||||
|
for(int i = 0; i < q->nummeshes; i++) {
|
||||||
|
// collect transparent drawcalls
|
||||||
|
if (required_rs[i] == RENDER_PASS_TRANSPARENT) {
|
||||||
|
drawcall_t call;
|
||||||
|
call.mesh = i;
|
||||||
|
call.tex = m.textures[i];
|
||||||
|
|
||||||
|
// calculate distance from camera
|
||||||
|
// @todo: improve me, uses first mesh triangle
|
||||||
|
{
|
||||||
|
call.distance = len3(sub3(cam_pos, transform344(model_mat, m.meshcenters[i])));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m.shading == SHADING_PBR)
|
||||||
|
call.tex = m.materials[i].layer[MATERIAL_CHANNEL_ALBEDO].map.texture ? m.materials[i].layer[MATERIAL_CHANNEL_ALBEDO].map.texture->id : m.materials[i].layer[MATERIAL_CHANNEL_DIFFUSE].map.texture ? m.materials[i].layer[MATERIAL_CHANNEL_DIFFUSE].map.texture->id : texture_checker().id;
|
||||||
|
array_push(drawcalls, call);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// sort drawcalls by order
|
||||||
|
array_sort(drawcalls, drawcall_compare);
|
||||||
|
|
||||||
|
struct iqmtriangle *tris = NULL;
|
||||||
|
for(int di = 0; di < array_count(drawcalls); di++) {
|
||||||
|
int i = drawcalls[di].mesh;
|
||||||
|
struct iqmmesh *im = &q->meshes[i];
|
||||||
|
|
||||||
|
if (pass != -1 && pass != required_rs[i]) continue;
|
||||||
|
|
||||||
|
if (rs_idx != required_rs[i]) {
|
||||||
|
rs_idx = required_rs[i];
|
||||||
|
rs = &m.rs[rs_idx];
|
||||||
|
renderstate_apply(rs);
|
||||||
|
}
|
||||||
|
|
||||||
if (m.shading != SHADING_PBR) {
|
if (m.shading != SHADING_PBR) {
|
||||||
shader_texture_unit("u_texture2d", q->textures[i], texture_unit());
|
shader_texture_unit("u_texture2d", q->textures[i], texture_unit());
|
||||||
|
@ -4244,7 +4357,7 @@ void model_draw_call(model_t m, int shader) {
|
||||||
shader_bind(old_shader);
|
shader_bind(old_shader);
|
||||||
}
|
}
|
||||||
|
|
||||||
void model_render_instanced(model_t m, mat44 proj, mat44 view, mat44* models, int shader, unsigned count) {
|
void model_render_instanced_pass(model_t m, mat44 proj, mat44 view, mat44* models, int shader, unsigned count, int pass) {
|
||||||
if(!m.iqm) return;
|
if(!m.iqm) return;
|
||||||
iqm_t *q = m.iqm;
|
iqm_t *q = m.iqm;
|
||||||
|
|
||||||
|
@ -4257,11 +4370,19 @@ void model_render_instanced(model_t m, mat44 proj, mat44 view, mat44* models, in
|
||||||
}
|
}
|
||||||
|
|
||||||
model_set_uniforms(m, shader > 0 ? shader : m.program, mv, proj, view, models[0]);
|
model_set_uniforms(m, shader > 0 ? shader : m.program, mv, proj, view, models[0]);
|
||||||
model_draw_call(m, shader > 0 ? shader : m.program);
|
model_draw_call(m, shader > 0 ? shader : m.program, pass, pos44(view), models[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
void model_render_instanced(model_t m, mat44 proj, mat44 view, mat44* models, int shader, unsigned count) {
|
||||||
|
model_render_instanced_pass(m, proj, view, models, shader, count, -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void model_render_pass(model_t m, mat44 proj, mat44 view, mat44 model, int shader, int pass) {
|
||||||
|
model_render_instanced_pass(m, proj, view, (mat44*)model, shader, 1, pass);
|
||||||
}
|
}
|
||||||
|
|
||||||
void model_render(model_t m, mat44 proj, mat44 view, mat44 model, int shader) {
|
void model_render(model_t m, mat44 proj, mat44 view, mat44 model, int shader) {
|
||||||
model_render_instanced(m, proj, view, (mat44*)model, shader, 1);
|
model_render_pass(m, proj, view, model, shader, -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline
|
static inline
|
||||||
|
@ -4600,6 +4721,7 @@ void model_destroy(model_t m) {
|
||||||
FREE(m.texture_names[i]);
|
FREE(m.texture_names[i]);
|
||||||
}
|
}
|
||||||
array_free(m.texture_names);
|
array_free(m.texture_names);
|
||||||
|
FREE(m.meshcenters);
|
||||||
|
|
||||||
iqm_t *q = m.iqm;
|
iqm_t *q = m.iqm;
|
||||||
// if(m.mesh) mesh_destroy(m.mesh);
|
// if(m.mesh) mesh_destroy(m.mesh);
|
||||||
|
@ -4623,6 +4745,7 @@ unsigned model_getpass() {
|
||||||
|
|
||||||
unsigned model_setpass(unsigned pass) {
|
unsigned model_setpass(unsigned pass) {
|
||||||
ASSERT(pass < NUM_RENDER_PASSES);
|
ASSERT(pass < NUM_RENDER_PASSES);
|
||||||
|
ASSERT(pass != RENDER_PASS_OVERRIDES_BEGIN && pass != RENDER_PASS_OVERRIDES_END);
|
||||||
unsigned old_pass = model_renderpass;
|
unsigned old_pass = model_renderpass;
|
||||||
model_renderpass = pass;
|
model_renderpass = pass;
|
||||||
return old_pass;
|
return old_pass;
|
||||||
|
@ -4688,6 +4811,7 @@ void lightmap_bake(lightmap_t *lm, int bounces, void (*drawscene)(lightmap_t *lm
|
||||||
unsigned old_pass = model_setpass(RENDER_PASS_LIGHTMAP);
|
unsigned old_pass = model_setpass(RENDER_PASS_LIGHTMAP);
|
||||||
|
|
||||||
for (int b = 0; b < bounces; b++) {
|
for (int b = 0; b < bounces; b++) {
|
||||||
|
model_setpass(RENDER_PASS_LIGHTMAP);
|
||||||
for (int i = 0; i < array_count(lm->models); i++) {
|
for (int i = 0; i < array_count(lm->models); i++) {
|
||||||
model_t *m = lm->models[i];
|
model_t *m = lm->models[i];
|
||||||
if (!m->lmdata) {
|
if (!m->lmdata) {
|
||||||
|
|
|
@ -608,8 +608,13 @@ enum SHADING_MODE {
|
||||||
|
|
||||||
enum RENDER_PASS {
|
enum RENDER_PASS {
|
||||||
RENDER_PASS_OPAQUE,
|
RENDER_PASS_OPAQUE,
|
||||||
|
RENDER_PASS_TRANSPARENT,
|
||||||
|
|
||||||
|
RENDER_PASS_OVERRIDES_BEGIN,
|
||||||
RENDER_PASS_SHADOW,
|
RENDER_PASS_SHADOW,
|
||||||
RENDER_PASS_LIGHTMAP,
|
RENDER_PASS_LIGHTMAP,
|
||||||
|
RENDER_PASS_CUSTOM, // make sure to apply renderstate before calling this
|
||||||
|
RENDER_PASS_OVERRIDES_END,
|
||||||
|
|
||||||
NUM_RENDER_PASSES
|
NUM_RENDER_PASSES
|
||||||
};
|
};
|
||||||
|
@ -670,6 +675,7 @@ typedef struct model_t {
|
||||||
void *verts;
|
void *verts;
|
||||||
int num_verts;
|
int num_verts;
|
||||||
void *tris;
|
void *tris;
|
||||||
|
vec3 *meshcenters;
|
||||||
int num_tris;
|
int num_tris;
|
||||||
handle vao, ibo, vbo, vao_instanced;
|
handle vao, ibo, vbo, vao_instanced;
|
||||||
|
|
||||||
|
@ -710,6 +716,8 @@ API void model_skybox(model_t*, skybox_t sky, bool load_sh);
|
||||||
API void model_render(model_t, mat44 proj, mat44 view, mat44 model, int shader);
|
API void model_render(model_t, mat44 proj, mat44 view, mat44 model, int shader);
|
||||||
API void model_render_skeleton(model_t, mat44 model);
|
API void model_render_skeleton(model_t, mat44 model);
|
||||||
API void model_render_instanced(model_t, mat44 proj, mat44 view, mat44 *models, int shader, unsigned count);
|
API void model_render_instanced(model_t, mat44 proj, mat44 view, mat44 *models, int shader, unsigned count);
|
||||||
|
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 void model_set_texture(model_t, texture_t t);
|
||||||
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);
|
||||||
|
|
168
engine/v4k.c
168
engine/v4k.c
|
@ -12620,6 +12620,20 @@ void lookat44(mat44 m, vec3 eye, vec3 center, vec3 up) {
|
||||||
m[ 8] = r.z; m[ 9] = u.z; m[10] = -f.z; m[11] = 0;
|
m[ 8] = r.z; m[ 9] = u.z; m[10] = -f.z; m[11] = 0;
|
||||||
m[12] = -dot3(r, eye); m[13] = -dot3(u, eye); m[14] = dot3(f, eye); m[15] = 1;
|
m[12] = -dot3(r, eye); m[13] = -dot3(u, eye); m[14] = dot3(f, eye); m[15] = 1;
|
||||||
}
|
}
|
||||||
|
vec3 pos44(mat44 m) {
|
||||||
|
vec3 position;
|
||||||
|
|
||||||
|
// The camera position is the negation of the translation vector
|
||||||
|
// transformed by the inverse of the rotation matrix.
|
||||||
|
// Since the upper-left 3x3 part of the view matrix is orthogonal,
|
||||||
|
// its inverse is equal to its transpose.
|
||||||
|
|
||||||
|
position.x = -(m[0] * m[12] + m[1] * m[13] + m[2] * m[14]);
|
||||||
|
position.y = -(m[4] * m[12] + m[5] * m[13] + m[6] * m[14]);
|
||||||
|
position.z = -(m[8] * m[12] + m[9] * m[13] + m[10] * m[14]);
|
||||||
|
|
||||||
|
return position;
|
||||||
|
}
|
||||||
// ---
|
// ---
|
||||||
void translation44(mat44 m, float x, float y, float z) { // identity4 + translate4
|
void translation44(mat44 m, float x, float y, float z) { // identity4 + translate4
|
||||||
m[ 0] = 1.0f; m[ 1] = 0.0f; m[ 2] = 0.0f; m[ 3] = 0.0f;
|
m[ 0] = 1.0f; m[ 1] = 0.0f; m[ 2] = 0.0f; m[ 3] = 0.0f;
|
||||||
|
@ -17759,6 +17773,16 @@ max_aniso = 4;
|
||||||
t->n = n;
|
t->n = n;
|
||||||
t->flags = flags;
|
t->flags = flags;
|
||||||
t->filename = t->filename ? t->filename : "";
|
t->filename = t->filename ? t->filename : "";
|
||||||
|
t->transparent = 0;
|
||||||
|
|
||||||
|
if (t->n == 4 && pixels) {
|
||||||
|
for (int i = 0; i < w * h; i++) {
|
||||||
|
if (((uint8_t *)pixels)[i * 4 + 3] < 255) {
|
||||||
|
t->transparent = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return t->id;
|
return t->id;
|
||||||
}
|
}
|
||||||
|
@ -17767,7 +17791,6 @@ texture_t texture_create(unsigned w, unsigned h, unsigned n, const void *pixels,
|
||||||
texture_t texture = {0};
|
texture_t texture = {0};
|
||||||
glGenTextures( 1, &texture.id );
|
glGenTextures( 1, &texture.id );
|
||||||
texture_update( &texture, w, h, n, pixels, flags );
|
texture_update( &texture, w, h, n, pixels, flags );
|
||||||
texture.transparent = texture.n > 3; // @fixme: should be true only if any pixel.a == 0
|
|
||||||
return texture;
|
return texture;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -20071,12 +20094,12 @@ void model_set_uniforms(model_t m, int shader, mat44 mv, mat44 proj, mat44 view,
|
||||||
glUniformMatrix4fv( loc, 1, GL_FALSE, vp);
|
glUniformMatrix4fv( loc, 1, GL_FALSE, vp);
|
||||||
}
|
}
|
||||||
if( (loc = glGetUniformLocation(shader, "u_cam_pos")) >= 0 ) {
|
if( (loc = glGetUniformLocation(shader, "u_cam_pos")) >= 0 ) {
|
||||||
vec3 pos = vec3(view[12], view[13], view[14]);
|
vec3 pos = pos44(view);
|
||||||
glUniform3fv( loc, 1, &pos.x );
|
glUniform3fv( loc, 1, &pos.x );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
if( (loc = glGetUniformLocation(shader, "cam_pos")) >= 0 ) {
|
if( (loc = glGetUniformLocation(shader, "cam_pos")) >= 0 ) {
|
||||||
vec3 pos = vec3(view[12], view[13], view[14]);
|
vec3 pos = pos44(view);
|
||||||
glUniform3fv( loc, 1, &pos.x );
|
glUniform3fv( loc, 1, &pos.x );
|
||||||
}
|
}
|
||||||
if( (loc = glGetUniformLocation(shader, "u_cam_dir")) >= 0 ) {
|
if( (loc = glGetUniformLocation(shader, "u_cam_dir")) >= 0 ) {
|
||||||
|
@ -20377,9 +20400,13 @@ 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));
|
||||||
|
|
||||||
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;
|
||||||
|
GLfloat *pos = verts[q->meshes[i].first_vertex].position;
|
||||||
|
m->meshcenters[i] = vec3(pos[0], pos[1], pos[2]);
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *str = hdr->ofs_text ? (char *)&q->buf[hdr->ofs_text] : "";
|
const char *str = hdr->ofs_text ? (char *)&q->buf[hdr->ofs_text] : "";
|
||||||
|
@ -20473,7 +20500,7 @@ void model_load_pbr_layer(material_layer_t *layer, const char *texname, bool loa
|
||||||
static
|
static
|
||||||
void model_load_pbr(material_t *mt) {
|
void model_load_pbr(material_t *mt) {
|
||||||
// initialise default colors
|
// initialise default colors
|
||||||
mt->layer[MATERIAL_CHANNEL_DIFFUSE].map.color = vec4(0.5,0.5,0.5,0.5);
|
mt->layer[MATERIAL_CHANNEL_DIFFUSE].map.color = vec4(0.5,0.5,0.5,1.0);
|
||||||
mt->layer[MATERIAL_CHANNEL_NORMALS].map.color = vec4(0,0,0,0);
|
mt->layer[MATERIAL_CHANNEL_NORMALS].map.color = vec4(0,0,0,0);
|
||||||
mt->layer[MATERIAL_CHANNEL_SPECULAR].map.color = vec4(0,0,0,0);
|
mt->layer[MATERIAL_CHANNEL_SPECULAR].map.color = vec4(0,0,0,0);
|
||||||
mt->layer[MATERIAL_CHANNEL_SPECULAR].value = 1.0f; // specular_shininess
|
mt->layer[MATERIAL_CHANNEL_SPECULAR].value = 1.0f; // specular_shininess
|
||||||
|
@ -20673,13 +20700,21 @@ void model_set_renderstates(model_t *m) {
|
||||||
// Opaque pass
|
// Opaque pass
|
||||||
renderstate_t *opaque_rs = &m->rs[RENDER_PASS_OPAQUE];
|
renderstate_t *opaque_rs = &m->rs[RENDER_PASS_OPAQUE];
|
||||||
{
|
{
|
||||||
opaque_rs->blend_enabled = 1;
|
opaque_rs->blend_enabled = 0;
|
||||||
opaque_rs->blend_src = GL_SRC_ALPHA;
|
|
||||||
opaque_rs->blend_dst = GL_ONE_MINUS_SRC_ALPHA;
|
|
||||||
opaque_rs->cull_face_mode = GL_BACK;
|
opaque_rs->cull_face_mode = GL_BACK;
|
||||||
opaque_rs->front_face = GL_CW;
|
opaque_rs->front_face = GL_CW;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Transparent pass
|
||||||
|
renderstate_t *transparent_rs = &m->rs[RENDER_PASS_TRANSPARENT];
|
||||||
|
{
|
||||||
|
transparent_rs->blend_enabled = 1;
|
||||||
|
transparent_rs->blend_src = GL_SRC_ALPHA;
|
||||||
|
transparent_rs->blend_dst = GL_ONE_MINUS_SRC_ALPHA;
|
||||||
|
transparent_rs->cull_face_mode = GL_BACK;
|
||||||
|
transparent_rs->front_face = GL_CW;
|
||||||
|
}
|
||||||
|
|
||||||
// Shadow pass @todo
|
// Shadow pass @todo
|
||||||
renderstate_t *shadow_rs = &m->rs[RENDER_PASS_SHADOW];
|
renderstate_t *shadow_rs = &m->rs[RENDER_PASS_SHADOW];
|
||||||
{
|
{
|
||||||
|
@ -20974,23 +21009,115 @@ void shader_colormap_model_internal(const char *col_name, const char *bool_name,
|
||||||
if( c.texture ) shader_texture( tex_name, *c.texture );
|
if( c.texture ) shader_texture( tex_name, *c.texture );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct drawcall_t {
|
||||||
|
model_t *m;
|
||||||
|
int mesh;
|
||||||
|
union {
|
||||||
|
uint64_t order;
|
||||||
|
struct {
|
||||||
|
uint32_t tex;
|
||||||
|
float distance;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
} drawcall_t;
|
||||||
|
|
||||||
static
|
static
|
||||||
void model_draw_call(model_t m, int shader) {
|
int drawcall_compare(const void *a, const void *b) {
|
||||||
|
const drawcall_t *da = a, *db = b;
|
||||||
|
return da->order < db->order ? 1 : da->order > db->order ? -1 : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
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;
|
||||||
iqm_t *q = m.iqm;
|
iqm_t *q = m.iqm;
|
||||||
|
|
||||||
handle old_shader = last_shader;
|
handle old_shader = last_shader;
|
||||||
shader_bind(shader);
|
shader_bind(shader);
|
||||||
|
|
||||||
renderstate_t *rs = &m.rs[RENDER_PASS_OPAQUE];
|
int rs_idx = model_getpass();
|
||||||
|
renderstate_t *rs = &m.rs[rs_idx];
|
||||||
renderstate_apply(rs);
|
|
||||||
|
|
||||||
glBindVertexArray( q->vao );
|
glBindVertexArray( q->vao );
|
||||||
|
|
||||||
struct iqmtriangle *tris = NULL;
|
static array(int) required_rs = 0;
|
||||||
|
array_resize(required_rs, q->nummeshes);
|
||||||
|
|
||||||
for(int i = 0; i < q->nummeshes; i++) {
|
for(int i = 0; i < q->nummeshes; i++) {
|
||||||
struct iqmmesh *im = &q->meshes[i];
|
struct iqmmesh *im = &q->meshes[i];
|
||||||
|
required_rs[i] = rs_idx;
|
||||||
|
|
||||||
|
if (required_rs[i] < RENDER_PASS_OVERRIDES_BEGIN) {
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static array(drawcall_t) drawcalls = 0;
|
||||||
|
array_resize(drawcalls, 0);
|
||||||
|
|
||||||
|
if (rs_idx > RENDER_PASS_OVERRIDES_BEGIN) {
|
||||||
|
for(int i = 0; i < q->nummeshes; i++) {
|
||||||
|
array_push(drawcalls, (drawcall_t){i, 0});
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if(pass == -1 || pass == RENDER_PASS_OPAQUE) {
|
||||||
|
for(int i = 0; i < q->nummeshes; i++) {
|
||||||
|
// collect opaque drawcalls
|
||||||
|
if (required_rs[i] == RENDER_PASS_OPAQUE) {
|
||||||
|
drawcall_t call;
|
||||||
|
call.mesh = i;
|
||||||
|
call.tex = m.textures[i];
|
||||||
|
call.distance = -1;
|
||||||
|
if (m.shading == SHADING_PBR)
|
||||||
|
call.tex = m.materials[i].layer[MATERIAL_CHANNEL_ALBEDO].map.texture ? m.materials[i].layer[MATERIAL_CHANNEL_ALBEDO].map.texture->id : m.materials[i].layer[MATERIAL_CHANNEL_DIFFUSE].map.texture ? m.materials[i].layer[MATERIAL_CHANNEL_DIFFUSE].map.texture->id : texture_checker().id;
|
||||||
|
array_push(drawcalls, call);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(pass == -1 || pass == RENDER_PASS_TRANSPARENT) {
|
||||||
|
for(int i = 0; i < q->nummeshes; i++) {
|
||||||
|
// collect transparent drawcalls
|
||||||
|
if (required_rs[i] == RENDER_PASS_TRANSPARENT) {
|
||||||
|
drawcall_t call;
|
||||||
|
call.mesh = i;
|
||||||
|
call.tex = m.textures[i];
|
||||||
|
|
||||||
|
// calculate distance from camera
|
||||||
|
// @todo: improve me, uses first mesh triangle
|
||||||
|
{
|
||||||
|
call.distance = len3(sub3(cam_pos, transform344(model_mat, m.meshcenters[i])));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m.shading == SHADING_PBR)
|
||||||
|
call.tex = m.materials[i].layer[MATERIAL_CHANNEL_ALBEDO].map.texture ? m.materials[i].layer[MATERIAL_CHANNEL_ALBEDO].map.texture->id : m.materials[i].layer[MATERIAL_CHANNEL_DIFFUSE].map.texture ? m.materials[i].layer[MATERIAL_CHANNEL_DIFFUSE].map.texture->id : texture_checker().id;
|
||||||
|
array_push(drawcalls, call);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// sort drawcalls by order
|
||||||
|
array_sort(drawcalls, drawcall_compare);
|
||||||
|
|
||||||
|
struct iqmtriangle *tris = NULL;
|
||||||
|
for(int di = 0; di < array_count(drawcalls); di++) {
|
||||||
|
int i = drawcalls[di].mesh;
|
||||||
|
struct iqmmesh *im = &q->meshes[i];
|
||||||
|
|
||||||
|
if (pass != -1 && pass != required_rs[i]) continue;
|
||||||
|
|
||||||
|
if (rs_idx != required_rs[i]) {
|
||||||
|
rs_idx = required_rs[i];
|
||||||
|
rs = &m.rs[rs_idx];
|
||||||
|
renderstate_apply(rs);
|
||||||
|
}
|
||||||
|
|
||||||
if (m.shading != SHADING_PBR) {
|
if (m.shading != SHADING_PBR) {
|
||||||
shader_texture_unit("u_texture2d", q->textures[i], texture_unit());
|
shader_texture_unit("u_texture2d", q->textures[i], texture_unit());
|
||||||
|
@ -21029,7 +21156,7 @@ void model_draw_call(model_t m, int shader) {
|
||||||
shader_bind(old_shader);
|
shader_bind(old_shader);
|
||||||
}
|
}
|
||||||
|
|
||||||
void model_render_instanced(model_t m, mat44 proj, mat44 view, mat44* models, int shader, unsigned count) {
|
void model_render_instanced_pass(model_t m, mat44 proj, mat44 view, mat44* models, int shader, unsigned count, int pass) {
|
||||||
if(!m.iqm) return;
|
if(!m.iqm) return;
|
||||||
iqm_t *q = m.iqm;
|
iqm_t *q = m.iqm;
|
||||||
|
|
||||||
|
@ -21042,11 +21169,19 @@ void model_render_instanced(model_t m, mat44 proj, mat44 view, mat44* models, in
|
||||||
}
|
}
|
||||||
|
|
||||||
model_set_uniforms(m, shader > 0 ? shader : m.program, mv, proj, view, models[0]);
|
model_set_uniforms(m, shader > 0 ? shader : m.program, mv, proj, view, models[0]);
|
||||||
model_draw_call(m, shader > 0 ? shader : m.program);
|
model_draw_call(m, shader > 0 ? shader : m.program, pass, pos44(view), models[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
void model_render_instanced(model_t m, mat44 proj, mat44 view, mat44* models, int shader, unsigned count) {
|
||||||
|
model_render_instanced_pass(m, proj, view, models, shader, count, -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void model_render_pass(model_t m, mat44 proj, mat44 view, mat44 model, int shader, int pass) {
|
||||||
|
model_render_instanced_pass(m, proj, view, (mat44*)model, shader, 1, pass);
|
||||||
}
|
}
|
||||||
|
|
||||||
void model_render(model_t m, mat44 proj, mat44 view, mat44 model, int shader) {
|
void model_render(model_t m, mat44 proj, mat44 view, mat44 model, int shader) {
|
||||||
model_render_instanced(m, proj, view, (mat44*)model, shader, 1);
|
model_render_pass(m, proj, view, model, shader, -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline
|
static inline
|
||||||
|
@ -21385,6 +21520,7 @@ void model_destroy(model_t m) {
|
||||||
FREE(m.texture_names[i]);
|
FREE(m.texture_names[i]);
|
||||||
}
|
}
|
||||||
array_free(m.texture_names);
|
array_free(m.texture_names);
|
||||||
|
FREE(m.meshcenters);
|
||||||
|
|
||||||
iqm_t *q = m.iqm;
|
iqm_t *q = m.iqm;
|
||||||
// if(m.mesh) mesh_destroy(m.mesh);
|
// if(m.mesh) mesh_destroy(m.mesh);
|
||||||
|
@ -21408,6 +21544,7 @@ unsigned model_getpass() {
|
||||||
|
|
||||||
unsigned model_setpass(unsigned pass) {
|
unsigned model_setpass(unsigned pass) {
|
||||||
ASSERT(pass < NUM_RENDER_PASSES);
|
ASSERT(pass < NUM_RENDER_PASSES);
|
||||||
|
ASSERT(pass != RENDER_PASS_OVERRIDES_BEGIN && pass != RENDER_PASS_OVERRIDES_END);
|
||||||
unsigned old_pass = model_renderpass;
|
unsigned old_pass = model_renderpass;
|
||||||
model_renderpass = pass;
|
model_renderpass = pass;
|
||||||
return old_pass;
|
return old_pass;
|
||||||
|
@ -21473,6 +21610,7 @@ void lightmap_bake(lightmap_t *lm, int bounces, void (*drawscene)(lightmap_t *lm
|
||||||
unsigned old_pass = model_setpass(RENDER_PASS_LIGHTMAP);
|
unsigned old_pass = model_setpass(RENDER_PASS_LIGHTMAP);
|
||||||
|
|
||||||
for (int b = 0; b < bounces; b++) {
|
for (int b = 0; b < bounces; b++) {
|
||||||
|
model_setpass(RENDER_PASS_LIGHTMAP);
|
||||||
for (int i = 0; i < array_count(lm->models); i++) {
|
for (int i = 0; i < array_count(lm->models); i++) {
|
||||||
model_t *m = lm->models[i];
|
model_t *m = lm->models[i];
|
||||||
if (!m->lmdata) {
|
if (!m->lmdata) {
|
||||||
|
|
|
@ -1202,6 +1202,7 @@ API void ortho44(mat44 m, float l, float r, float b, float t, float n, float f);
|
||||||
API void frustum44(mat44 m, float l, float r, float b, float t, float n, float f);
|
API void frustum44(mat44 m, float l, float r, float b, float t, float n, float f);
|
||||||
API void perspective44(mat44 m, float fovy_degrees, float aspect, float nearp, float farp);
|
API void perspective44(mat44 m, float fovy_degrees, float aspect, float nearp, float farp);
|
||||||
API void lookat44(mat44 m, vec3 eye, vec3 center, vec3 up);
|
API void lookat44(mat44 m, vec3 eye, vec3 center, vec3 up);
|
||||||
|
API vec3 pos44(mat44 m);
|
||||||
// ---
|
// ---
|
||||||
API void translation44(mat44 m, float x, float y, float z);
|
API void translation44(mat44 m, float x, float y, float z);
|
||||||
API void translate44(mat44 m, float x, float y, float z);
|
API void translate44(mat44 m, float x, float y, float z);
|
||||||
|
@ -3642,8 +3643,13 @@ enum SHADING_MODE {
|
||||||
|
|
||||||
enum RENDER_PASS {
|
enum RENDER_PASS {
|
||||||
RENDER_PASS_OPAQUE,
|
RENDER_PASS_OPAQUE,
|
||||||
|
RENDER_PASS_TRANSPARENT,
|
||||||
|
|
||||||
|
RENDER_PASS_OVERRIDES_BEGIN,
|
||||||
RENDER_PASS_SHADOW,
|
RENDER_PASS_SHADOW,
|
||||||
RENDER_PASS_LIGHTMAP,
|
RENDER_PASS_LIGHTMAP,
|
||||||
|
RENDER_PASS_CUSTOM, // make sure to apply renderstate before calling this
|
||||||
|
RENDER_PASS_OVERRIDES_END,
|
||||||
|
|
||||||
NUM_RENDER_PASSES
|
NUM_RENDER_PASSES
|
||||||
};
|
};
|
||||||
|
@ -3704,6 +3710,7 @@ typedef struct model_t {
|
||||||
void *verts;
|
void *verts;
|
||||||
int num_verts;
|
int num_verts;
|
||||||
void *tris;
|
void *tris;
|
||||||
|
vec3 *meshcenters;
|
||||||
int num_tris;
|
int num_tris;
|
||||||
handle vao, ibo, vbo, vao_instanced;
|
handle vao, ibo, vbo, vao_instanced;
|
||||||
|
|
||||||
|
@ -3744,6 +3751,8 @@ API void model_skybox(model_t*, skybox_t sky, bool load_sh);
|
||||||
API void model_render(model_t, mat44 proj, mat44 view, mat44 model, int shader);
|
API void model_render(model_t, mat44 proj, mat44 view, mat44 model, int shader);
|
||||||
API void model_render_skeleton(model_t, mat44 model);
|
API void model_render_skeleton(model_t, mat44 model);
|
||||||
API void model_render_instanced(model_t, mat44 proj, mat44 view, mat44 *models, int shader, unsigned count);
|
API void model_render_instanced(model_t, mat44 proj, mat44 view, mat44 *models, int shader, unsigned count);
|
||||||
|
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 void model_set_texture(model_t, texture_t t);
|
||||||
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);
|
||||||
|
|
Loading…
Reference in New Issue