From b47c47df5461f69480432c8ee856e811dbcd620b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Madar=C3=A1sz?= Date: Mon, 11 Sep 2023 15:16:16 +0200 Subject: [PATCH] render: improve skybox_mie_calc_sh and add sky_intensity --- demos/99-cubemap.c | 12 ++++++++---- demos/99-sponza.c | 2 +- engine/bind/v4k.lua | 10 +++++++++- engine/joint/v4k.h | 41 ++++++++++++++++++++++++++++++++------- engine/split/v4k_render.c | 37 +++++++++++++++++++++++++++++------ engine/split/v4k_render.h | 4 +++- engine/v4k.c | 37 +++++++++++++++++++++++++++++------ engine/v4k.h | 4 +++- 8 files changed, 120 insertions(+), 27 deletions(-) diff --git a/demos/99-cubemap.c b/demos/99-cubemap.c index 0da6d7d..2e4c5c4 100644 --- a/demos/99-cubemap.c +++ b/demos/99-cubemap.c @@ -44,10 +44,6 @@ int main(int argc, char** argv) { sky = skybox(flag("--mie") ? 0 : SKY_DIRS[SKY_DIR], 0); mdl = model(OBJ_MDLS[OBJ_MDL], 0); // rotation44(mdl.pivot, 0, 1,0,0); // @fixme: -90,1,0,0 -> should we rotate SHMs as well? compensate rotation in shader? - - if (flag("--mie")) { - skybox_mie_calc_sh(&sky); - } } // fps camera @@ -63,6 +59,14 @@ int main(int argc, char** argv) { // render mat44 mvp; multiply44x2(mvp, cam.proj, cam.view); { + if (flag("--mie")) { + // skybox_sh_reset(&sky); + skybox_mie_calc_sh(&sky, 4.0f); + // float x = cosf((float)window_time())*4; + // skybox_sh_add_light(&sky, vec3(0.3,0.3,0.3), vec3(0,1,0), 16*absf(cosf((float)window_time()*2))+2); + // skybox_sh_add_light(&sky, vec3(0.6,0,0), vec3(x,1,0), 2); + } + skybox_render(&sky, cam.proj, cam.view); shader_bind(mdl.program); diff --git a/demos/99-sponza.c b/demos/99-sponza.c index c5ad108..f15765a 100644 --- a/demos/99-sponza.c +++ b/demos/99-sponza.c @@ -40,7 +40,7 @@ int main() { if (flag("--mie") && sky_update_until <= window_time()) { shader_bind(sky.program); shader_vec3("uSunPos", vec3(0, (cosf((float)window_time()*0.25)*0.3)+0.2, -1)); - skybox_mie_calc_sh(&sky); + skybox_mie_calc_sh(&sky, 2.0f); sky_update_until = window_time() + 0.02; } diff --git a/engine/bind/v4k.lua b/engine/bind/v4k.lua index f97f94d..4de1d9e 100644 --- a/engine/bind/v4k.lua +++ b/engine/bind/v4k.lua @@ -1189,6 +1189,12 @@ ffi.cdef([[ //lcpp INF [0000] vec3: macro name but used as C declaration in:API vec3 pose(bool forward, float curframe, int minframe, int maxframe, bool loop, float *opt_retframe); //lcpp INF [0000] vec3: macro name but used as C declaration in:STATIC vec3 pose(bool forward, float curframe, int minframe, int maxframe, bool loop, float *opt_retframe); //lcpp INF [0000] vec3: macro name but used as C declaration in: vec3 pose(bool forward, float curframe, int minframe, int maxframe, bool loop, float *opt_retframe); +//lcpp INF [0000] vec3: macro name but used as C declaration in:API void skybox_sh_add_light(skybox_t *sky, vec3 light, vec3 dir, float strength); +//lcpp INF [0000] vec3: macro name but used as C declaration in:API void skybox_sh_add_light(skybox_t *sky, vec3 light, vec3 dir, float strength); +//lcpp INF [0000] vec3: macro name but used as C declaration in:STATIC void skybox_sh_add_light(skybox_t *sky, vec3 light, vec3 dir, float strength); +//lcpp INF [0000] vec3: macro name but used as C declaration in:STATIC void skybox_sh_add_light(skybox_t *sky, vec3 light, vec3 dir, float strength); +//lcpp INF [0000] vec3: macro name but used as C declaration in: void skybox_sh_add_light(skybox_t *sky, vec3 light, vec3 dir, float strength); +//lcpp INF [0000] vec3: macro name but used as C declaration in: void skybox_sh_add_light(skybox_t *sky, vec3 light, vec3 dir, float strength); //lcpp INF [0000] vec3: macro name but used as C declaration in:API void viewport_color3(vec3 color); //lcpp INF [0000] vec3: macro name but used as C declaration in:STATIC void viewport_color3(vec3 color); //lcpp INF [0000] vec3: macro name but used as C declaration in: void viewport_color3(vec3 color); @@ -2532,7 +2538,9 @@ unsigned char *pixels; skybox_t skybox(const char *panorama_or_cubemap_folder, int flags); int skybox_render(skybox_t *sky, mat44 proj, mat44 view); void skybox_destroy(skybox_t *sky); - void skybox_mie_calc_sh(skybox_t *sky); + void skybox_mie_calc_sh(skybox_t *sky, float sky_intensity); + void skybox_sh_reset(skybox_t *sky); + void skybox_sh_add_light(skybox_t *sky, vec3 light, vec3 dir, float strength); int skybox_push_state(skybox_t *sky, mat44 proj, mat44 view); int skybox_pop_state(); void viewport_color(uint32_t color); diff --git a/engine/joint/v4k.h b/engine/joint/v4k.h index 182822d..3ad8397 100644 --- a/engine/joint/v4k.h +++ b/engine/joint/v4k.h @@ -16791,7 +16791,9 @@ typedef struct skybox_t { API skybox_t skybox(const char *panorama_or_cubemap_folder, int flags); API int skybox_render(skybox_t *sky, mat44 proj, mat44 view); API void skybox_destroy(skybox_t *sky); -API void skybox_mie_calc_sh(skybox_t *sky); +API void skybox_mie_calc_sh(skybox_t *sky, float sky_intensity); +API void skybox_sh_reset(skybox_t *sky); +API void skybox_sh_add_light(skybox_t *sky, vec3 light, vec3 dir, float strength); API int skybox_push_state(skybox_t *sky, mat44 proj, mat44 view); // @to deprecate API int skybox_pop_state(); // @to deprecate @@ -341727,15 +341729,19 @@ skybox_t skybox(const char *asset, int flags) { return sky; } -void skybox_mie_calc_sh(skybox_t *sky) { +void skybox_mie_calc_sh(skybox_t *sky, float sky_intensity) { unsigned WIDTH = 1024, HEIGHT = 1024; int last_fb; int vp[4]; glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &last_fb); glGetIntegerv(GL_VIEWPORT, vp); + if (!sky_intensity) { + sky_intensity = 1.0f; + } + if (!sky->pixels) - sky->pixels = MALLOC(WIDTH*HEIGHT*3); + sky->pixels = MALLOC(WIDTH*HEIGHT*12); if (!sky->framebuffers[0]) { for(int i = 0; i < 6; ++i) { @@ -341745,7 +341751,7 @@ void skybox_mie_calc_sh(skybox_t *sky) { glGenTextures(1, &sky->textures[i]); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, sky->textures[i]); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, WIDTH, HEIGHT, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, WIDTH, HEIGHT, 0, GL_RGB, GL_FLOAT, NULL); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glBindTexture(GL_TEXTURE_2D, 0); @@ -341767,7 +341773,7 @@ void skybox_mie_calc_sh(skybox_t *sky) { skybox_render(sky, proj, view); - glReadPixels(0, 0, WIDTH, HEIGHT, GL_RGB, GL_UNSIGNED_BYTE, sky->pixels); + glReadPixels(0, 0, WIDTH, HEIGHT, GL_RGB, GL_FLOAT, sky->pixels); // calculate SH coefficients (@ands) // copied from cubemap6 method @@ -341776,7 +341782,7 @@ void skybox_mie_calc_sh(skybox_t *sky) { const vec3 skyY[] = {{ 0, 1, 0},{ 0, 1, 0},{ 0, 0,-1},{ 0, 0, 1},{ 0, 1, 0},{ 0, 1, 0}}; int step = 16; for (int y = 0; y < HEIGHT; y += step) { - unsigned char *p = (unsigned char*)sky->pixels + y * WIDTH * 3; + unsigned float *p = (unsigned float*)sky->pixels + y * WIDTH * 3; for (int x = 0; x < WIDTH; x += step) { vec3 n = add3( add3( @@ -341784,7 +341790,7 @@ void skybox_mie_calc_sh(skybox_t *sky) { scale3(skyY[i], -2.0f * (y / (HEIGHT - 1.0f)) + 1.0f)), skyDir[i]); // texelDirection; float l = len3(n); - vec3 light = scale3(vec3(p[0], p[1], p[2]), 1 / (255.0f * l * l * l)); // texelSolidAngle * texel_radiance; + vec3 light = scale3(vec3(p[0], p[1], p[2]), (1 / (l * l * l)) * sky_intensity); // texelSolidAngle * texel_radiance; n = norm3(n); sky->cubemap.sh[0] = add3(sky->cubemap.sh[0], scale3(light, 0.282095f)); sky->cubemap.sh[1] = add3(sky->cubemap.sh[1], scale3(light, -0.488603f * n.y * 2.0 / 3.0)); @@ -341809,6 +341815,27 @@ void skybox_mie_calc_sh(skybox_t *sky) { glViewport(vp[0], vp[1], vp[2], vp[3]); } +void skybox_sh_reset(skybox_t *sky) { + for (int s = 0; s < 9; s++) { + sky->cubemap.sh[s] = vec3(0,0,0); + } +} + +void skybox_sh_add_light(skybox_t *sky, vec3 light, vec3 dir, float strength) { + // Normalize the direction + vec3 norm_dir = norm3(dir); + + // Scale the light color and intensity + vec3 scaled_light = scale3(light, strength); + + // Add light to the SH coefficients + sky->cubemap.sh[0] = add3(sky->cubemap.sh[0], scale3(scaled_light, 0.282095f)); + sky->cubemap.sh[1] = add3(sky->cubemap.sh[1], scale3(scaled_light, -0.488603f * norm_dir.y)); + sky->cubemap.sh[2] = add3(sky->cubemap.sh[2], scale3(scaled_light, 0.488603f * norm_dir.z)); + sky->cubemap.sh[3] = add3(sky->cubemap.sh[3], scale3(scaled_light, -0.488603f * norm_dir.x)); +} + + int skybox_push_state(skybox_t *sky, mat44 proj, mat44 view) { last_cubemap = &sky->cubemap; diff --git a/engine/split/v4k_render.c b/engine/split/v4k_render.c index 36bd292..b3c8a7e 100644 --- a/engine/split/v4k_render.c +++ b/engine/split/v4k_render.c @@ -2413,15 +2413,19 @@ skybox_t skybox(const char *asset, int flags) { return sky; } -void skybox_mie_calc_sh(skybox_t *sky) { +void skybox_mie_calc_sh(skybox_t *sky, float sky_intensity) { unsigned WIDTH = 1024, HEIGHT = 1024; int last_fb; int vp[4]; glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &last_fb); glGetIntegerv(GL_VIEWPORT, vp); + if (!sky_intensity) { + sky_intensity = 1.0f; + } + if (!sky->pixels) - sky->pixels = MALLOC(WIDTH*HEIGHT*3); + sky->pixels = MALLOC(WIDTH*HEIGHT*12); if (!sky->framebuffers[0]) { for(int i = 0; i < 6; ++i) { @@ -2431,7 +2435,7 @@ void skybox_mie_calc_sh(skybox_t *sky) { glGenTextures(1, &sky->textures[i]); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, sky->textures[i]); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, WIDTH, HEIGHT, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, WIDTH, HEIGHT, 0, GL_RGB, GL_FLOAT, NULL); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glBindTexture(GL_TEXTURE_2D, 0); @@ -2453,7 +2457,7 @@ void skybox_mie_calc_sh(skybox_t *sky) { skybox_render(sky, proj, view); - glReadPixels(0, 0, WIDTH, HEIGHT, GL_RGB, GL_UNSIGNED_BYTE, sky->pixels); + glReadPixels(0, 0, WIDTH, HEIGHT, GL_RGB, GL_FLOAT, sky->pixels); // calculate SH coefficients (@ands) // copied from cubemap6 method @@ -2462,7 +2466,7 @@ void skybox_mie_calc_sh(skybox_t *sky) { const vec3 skyY[] = {{ 0, 1, 0},{ 0, 1, 0},{ 0, 0,-1},{ 0, 0, 1},{ 0, 1, 0},{ 0, 1, 0}}; int step = 16; for (int y = 0; y < HEIGHT; y += step) { - unsigned char *p = (unsigned char*)sky->pixels + y * WIDTH * 3; + unsigned float *p = (unsigned float*)sky->pixels + y * WIDTH * 3; for (int x = 0; x < WIDTH; x += step) { vec3 n = add3( add3( @@ -2470,7 +2474,7 @@ void skybox_mie_calc_sh(skybox_t *sky) { scale3(skyY[i], -2.0f * (y / (HEIGHT - 1.0f)) + 1.0f)), skyDir[i]); // texelDirection; float l = len3(n); - vec3 light = scale3(vec3(p[0], p[1], p[2]), 1 / (255.0f * l * l * l)); // texelSolidAngle * texel_radiance; + vec3 light = scale3(vec3(p[0], p[1], p[2]), (1 / (l * l * l)) * sky_intensity); // texelSolidAngle * texel_radiance; n = norm3(n); sky->cubemap.sh[0] = add3(sky->cubemap.sh[0], scale3(light, 0.282095f)); sky->cubemap.sh[1] = add3(sky->cubemap.sh[1], scale3(light, -0.488603f * n.y * 2.0 / 3.0)); @@ -2495,6 +2499,27 @@ void skybox_mie_calc_sh(skybox_t *sky) { glViewport(vp[0], vp[1], vp[2], vp[3]); } +void skybox_sh_reset(skybox_t *sky) { + for (int s = 0; s < 9; s++) { + sky->cubemap.sh[s] = vec3(0,0,0); + } +} + +void skybox_sh_add_light(skybox_t *sky, vec3 light, vec3 dir, float strength) { + // Normalize the direction + vec3 norm_dir = norm3(dir); + + // Scale the light color and intensity + vec3 scaled_light = scale3(light, strength); + + // Add light to the SH coefficients + sky->cubemap.sh[0] = add3(sky->cubemap.sh[0], scale3(scaled_light, 0.282095f)); + sky->cubemap.sh[1] = add3(sky->cubemap.sh[1], scale3(scaled_light, -0.488603f * norm_dir.y)); + sky->cubemap.sh[2] = add3(sky->cubemap.sh[2], scale3(scaled_light, 0.488603f * norm_dir.z)); + sky->cubemap.sh[3] = add3(sky->cubemap.sh[3], scale3(scaled_light, -0.488603f * norm_dir.x)); +} + + int skybox_push_state(skybox_t *sky, mat44 proj, mat44 view) { last_cubemap = &sky->cubemap; diff --git a/engine/split/v4k_render.h b/engine/split/v4k_render.h index e627cd2..77b9ae6 100644 --- a/engine/split/v4k_render.h +++ b/engine/split/v4k_render.h @@ -635,7 +635,9 @@ typedef struct skybox_t { API skybox_t skybox(const char *panorama_or_cubemap_folder, int flags); API int skybox_render(skybox_t *sky, mat44 proj, mat44 view); API void skybox_destroy(skybox_t *sky); -API void skybox_mie_calc_sh(skybox_t *sky); +API void skybox_mie_calc_sh(skybox_t *sky, float sky_intensity); +API void skybox_sh_reset(skybox_t *sky); +API void skybox_sh_add_light(skybox_t *sky, vec3 light, vec3 dir, float strength); API int skybox_push_state(skybox_t *sky, mat44 proj, mat44 view); // @to deprecate API int skybox_pop_state(); // @to deprecate diff --git a/engine/v4k.c b/engine/v4k.c index fcd4a49..2663c31 100644 --- a/engine/v4k.c +++ b/engine/v4k.c @@ -12637,15 +12637,19 @@ skybox_t skybox(const char *asset, int flags) { return sky; } -void skybox_mie_calc_sh(skybox_t *sky) { +void skybox_mie_calc_sh(skybox_t *sky, float sky_intensity) { unsigned WIDTH = 1024, HEIGHT = 1024; int last_fb; int vp[4]; glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &last_fb); glGetIntegerv(GL_VIEWPORT, vp); + if (!sky_intensity) { + sky_intensity = 1.0f; + } + if (!sky->pixels) - sky->pixels = MALLOC(WIDTH*HEIGHT*3); + sky->pixels = MALLOC(WIDTH*HEIGHT*12); if (!sky->framebuffers[0]) { for(int i = 0; i < 6; ++i) { @@ -12655,7 +12659,7 @@ void skybox_mie_calc_sh(skybox_t *sky) { glGenTextures(1, &sky->textures[i]); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, sky->textures[i]); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, WIDTH, HEIGHT, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, WIDTH, HEIGHT, 0, GL_RGB, GL_FLOAT, NULL); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glBindTexture(GL_TEXTURE_2D, 0); @@ -12677,7 +12681,7 @@ void skybox_mie_calc_sh(skybox_t *sky) { skybox_render(sky, proj, view); - glReadPixels(0, 0, WIDTH, HEIGHT, GL_RGB, GL_UNSIGNED_BYTE, sky->pixels); + glReadPixels(0, 0, WIDTH, HEIGHT, GL_RGB, GL_FLOAT, sky->pixels); // calculate SH coefficients (@ands) // copied from cubemap6 method @@ -12686,7 +12690,7 @@ void skybox_mie_calc_sh(skybox_t *sky) { const vec3 skyY[] = {{ 0, 1, 0},{ 0, 1, 0},{ 0, 0,-1},{ 0, 0, 1},{ 0, 1, 0},{ 0, 1, 0}}; int step = 16; for (int y = 0; y < HEIGHT; y += step) { - unsigned char *p = (unsigned char*)sky->pixels + y * WIDTH * 3; + unsigned float *p = (unsigned float*)sky->pixels + y * WIDTH * 3; for (int x = 0; x < WIDTH; x += step) { vec3 n = add3( add3( @@ -12694,7 +12698,7 @@ void skybox_mie_calc_sh(skybox_t *sky) { scale3(skyY[i], -2.0f * (y / (HEIGHT - 1.0f)) + 1.0f)), skyDir[i]); // texelDirection; float l = len3(n); - vec3 light = scale3(vec3(p[0], p[1], p[2]), 1 / (255.0f * l * l * l)); // texelSolidAngle * texel_radiance; + vec3 light = scale3(vec3(p[0], p[1], p[2]), (1 / (l * l * l)) * sky_intensity); // texelSolidAngle * texel_radiance; n = norm3(n); sky->cubemap.sh[0] = add3(sky->cubemap.sh[0], scale3(light, 0.282095f)); sky->cubemap.sh[1] = add3(sky->cubemap.sh[1], scale3(light, -0.488603f * n.y * 2.0 / 3.0)); @@ -12719,6 +12723,27 @@ void skybox_mie_calc_sh(skybox_t *sky) { glViewport(vp[0], vp[1], vp[2], vp[3]); } +void skybox_sh_reset(skybox_t *sky) { + for (int s = 0; s < 9; s++) { + sky->cubemap.sh[s] = vec3(0,0,0); + } +} + +void skybox_sh_add_light(skybox_t *sky, vec3 light, vec3 dir, float strength) { + // Normalize the direction + vec3 norm_dir = norm3(dir); + + // Scale the light color and intensity + vec3 scaled_light = scale3(light, strength); + + // Add light to the SH coefficients + sky->cubemap.sh[0] = add3(sky->cubemap.sh[0], scale3(scaled_light, 0.282095f)); + sky->cubemap.sh[1] = add3(sky->cubemap.sh[1], scale3(scaled_light, -0.488603f * norm_dir.y)); + sky->cubemap.sh[2] = add3(sky->cubemap.sh[2], scale3(scaled_light, 0.488603f * norm_dir.z)); + sky->cubemap.sh[3] = add3(sky->cubemap.sh[3], scale3(scaled_light, -0.488603f * norm_dir.x)); +} + + int skybox_push_state(skybox_t *sky, mat44 proj, mat44 view) { last_cubemap = &sky->cubemap; diff --git a/engine/v4k.h b/engine/v4k.h index 1265529..5f52627 100644 --- a/engine/v4k.h +++ b/engine/v4k.h @@ -2874,7 +2874,9 @@ typedef struct skybox_t { API skybox_t skybox(const char *panorama_or_cubemap_folder, int flags); API int skybox_render(skybox_t *sky, mat44 proj, mat44 view); API void skybox_destroy(skybox_t *sky); -API void skybox_mie_calc_sh(skybox_t *sky); +API void skybox_mie_calc_sh(skybox_t *sky, float sky_intensity); +API void skybox_sh_reset(skybox_t *sky); +API void skybox_sh_add_light(skybox_t *sky, vec3 light, vec3 dir, float strength); API int skybox_push_state(skybox_t *sky, mat44 proj, mat44 view); // @to deprecate API int skybox_pop_state(); // @to deprecate