render: add skybox_mie_calc_sh

main
Dominik Madarász 2023-09-10 15:03:01 +02:00
parent d6d0294ae5
commit 2d6ed9740d
12 changed files with 712 additions and 395 deletions

View File

@ -5,6 +5,7 @@
int main() {
window_create(80, WINDOW_MSAA8);
window_title(__FILE__);
window_fps_unlock();
// load all fx files
fx_load("fx**.fs");
@ -23,6 +24,8 @@ int main() {
camera_t cam = camera();
cam.speed = 0.2f;
double sky_update_until = 0.0;
// demo loop
while (window_swap())
{
@ -33,6 +36,14 @@ int main() {
if( input_down(KEY_X) ) window_screenshot(__FILE__ ".png");
if( input_down(KEY_Z) ) window_record(__FILE__ ".mp4");
// initialize SH coefficients from rayleigh skybox
if (flag("--mie") && sky_update_until <= window_time()) {
shader_bind(sky.program);
shader_vec3("uSunPos", cam.position);
skybox_mie_calc_sh(&sky);
sky_update_until = window_time() + 0.02;
}
// 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);
@ -52,6 +63,10 @@ int main() {
float scale = 1.00;
mat44 M; copy44(M, sponza.pivot); translate44(M, 0,0,0); scale44(M, scale,scale,scale);
shader_bind(sponza.program);
shader_vec3v("u_coefficients_sh", 9, sky.cubemap.sh);
model_render(sponza, cam.proj, cam.view, M, 0);
// post-fxs end here

View File

@ -27,7 +27,7 @@ void temp_calc(vec4 *pixels){
int main() {
window_create(50, WINDOW_SQUARE|WINDOW_VSYNC_DISABLED);
window_title(__FILE__);
window_fps_lock(0);
window_fps_unlock();
texture_t tex;

View File

@ -2520,10 +2520,14 @@ handle program;
mesh_t geometry;
cubemap_t cubemap;
int flags;
unsigned framebuffers;
unsigned textures;
unsigned char *pixels;
} skybox_t;
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);
int skybox_push_state(skybox_t *sky, mat44 proj, mat44 view);
int skybox_pop_state();
void viewport_color(uint32_t color);

View File

@ -16767,11 +16767,17 @@ typedef struct skybox_t {
mesh_t geometry;
cubemap_t cubemap;
int flags;
// mie
unsigned framebuffers;
unsigned textures;
unsigned char *pixels;
} 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 int skybox_push_state(skybox_t *sky, mat44 proj, mat44 view); // @to deprecate
API int skybox_pop_state(); // @to deprecate
@ -339318,6 +339324,7 @@ const char *const fs_0_0_shadowmap_lit = "//" FILELINE "\n"
" vec4 specular;\n"
" float constantAttenuation, linearAttenuation, quadraticAttenuation;\n"
"};\n"
" \n"
"light light0 = light(\n"
" lightPos,\n"
" vec4(1,1,1,1), // diffuse\n"
@ -339354,7 +339361,6 @@ const char *const fs_0_0_shadowmap_lit = "//" FILELINE "\n"
#ifndef VSMCUBE
" return vec4(1.);\n"
#else
" \n"
" vec3 fragment = vec3(vpeye);\n"
" vec3 normal = vec3(normalize(vneye));\n"
" vec3 viewDir = normalize(-fragment);\n"
@ -339952,7 +339958,6 @@ const char *const vs_324_24_sprite = "//" FILELINE "\n"
"}\n";
const char *const vs_332_32 = "//" FILELINE "\n"
"//uniform mat4 u_model, u_view, u_proj;\n"
"uniform mat4 u_mvp;\n"
"\n"
"in vec3 att_position;\n"
@ -339977,7 +339982,6 @@ const char *const vs_332_32 = "//" FILELINE "\n"
"}\n"
"\n"
"void main() {\n"
" // gl_Position = proj * view * model * vec4(att_position, 1.0);\n"
" gl_Position = u_mvp * vec4(att_position, 1.0);\n"
" v_normal = normalize(att_normal);\n"
" v_normal_ws = normalize(vec3(model * vec4(att_normal, 0.))); // normal world/model space\n"
@ -342402,6 +342406,96 @@ skybox_t skybox(const char *asset, int flags) {
return sky;
}
void skybox_mie_calc_sh(skybox_t *sky) {
unsigned WIDTH = 512, HEIGHT = 512;
unsigned last_fb;
int vp[4];
glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &last_fb);
glGetIntegerv(GL_VIEWPORT, vp);
if (!sky->pixels)
sky->pixels = MALLOC(WIDTH*HEIGHT*3);
if (!sky->framebuffers[0]) {
for(int i = 0; i < 6; ++i) {
glGenFramebuffers(1, &sky->framebuffers[i]);
glBindFramebuffer(GL_FRAMEBUFFER, sky->framebuffers[i]);
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);
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);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, sky->textures[i], 0);
}
}
static vec3 directions[6] = {
{1.0f, 0.0f, 0.0f},
{-1.0f, 0.0f, 0.0f},
{0.0f, 1.0f, 0.0f},
{0.0f, -1.0f, 0.0f},
{0.0f, 0.0f, 1.0f},
{0.0f, 0.0f, -1.0f}
};
int samples = 0;
for(int i = 0; i < 6; ++i) {
glBindFramebuffer(GL_FRAMEBUFFER, sky->framebuffers[i]);
glViewport(0, 0, WIDTH, HEIGHT);
glUseProgram(sky->program);
mat44 proj; perspective44(proj, 90.0f, WIDTH / (float)HEIGHT, 0.01f, 1000.f);
mat44 view; lookat44(view, vec3(0,0,0), directions[i], vec3(0,1,0));
skybox_render(sky, proj, view);
glReadPixels(0, 0, WIDTH, HEIGHT, GL_RGB, GL_UNSIGNED_BYTE, sky->pixels);
// calculate SH coefficients (@ands)
// copied from cubemap6 method
const vec3 skyDir[] = {{ 1, 0, 0},{-1, 0, 0},{ 0, 1, 0},{ 0,-1, 0},{ 0, 0, 1},{ 0, 0,-1}};
const vec3 skyX[] = {{ 0, 0,-1},{ 0, 0, 1},{ 1, 0, 0},{ 1, 0, 0},{ 1, 0, 0},{-1, 0, 0}};
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;
for (int x = 0; x < WIDTH; x += step) {
vec3 n = add3(
add3(
scale3(skyX[i], 2.0f * (x / (WIDTH - 1.0f)) - 1.0f),
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;
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));
sky->cubemap.sh[2] = add3(sky->cubemap.sh[2], scale3(light, 0.488603f * n.z * 2.0 / 3.0));
sky->cubemap.sh[3] = add3(sky->cubemap.sh[3], scale3(light, -0.488603f * n.x * 2.0 / 3.0));
sky->cubemap.sh[4] = add3(sky->cubemap.sh[4], scale3(light, 1.092548f * n.x * n.y / 4.0));
sky->cubemap.sh[5] = add3(sky->cubemap.sh[5], scale3(light, -1.092548f * n.y * n.z / 4.0));
sky->cubemap.sh[6] = add3(sky->cubemap.sh[6], scale3(light, 0.315392f * (3.0f * n.z * n.z - 1.0f) / 4.0));
sky->cubemap.sh[7] = add3(sky->cubemap.sh[7], scale3(light, -1.092548f * n.x * n.z / 4.0));
sky->cubemap.sh[8] = add3(sky->cubemap.sh[8], scale3(light, 0.546274f * (n.x * n.x - n.y * n.y) / 4.0));
p += 3 * step;
samples++;
}
}
}
for (int s = 0; s < 9; s++) {
sky->cubemap.sh[s] = scale3(sky->cubemap.sh[s], 32.f / samples);
}
glBindFramebuffer(GL_FRAMEBUFFER, last_fb);
glViewport(vp[0], vp[1], vp[2], vp[3]);
}
int skybox_push_state(skybox_t *sky, mat44 proj, mat44 view) {
last_cubemap = &sky->cubemap;
@ -342437,6 +342531,12 @@ void skybox_destroy(skybox_t *sky) {
glDeleteProgram(sky->program);
cubemap_destroy(&sky->cubemap);
mesh_destroy(&sky->geometry);
if (sky->pixels) {
FREE(sky->pixels);
glDeleteFramebuffers(6, sky->framebuffers);
glDeleteTextures(6, sky->textures);
}
}
// -----------------------------------------------------------------------------

View File

@ -13,6 +13,7 @@ struct light {
vec4 specular;
float constantAttenuation, linearAttenuation, quadraticAttenuation;
};
light light0 = light(
lightPos,
vec4(1,1,1,1), // diffuse
@ -49,7 +50,6 @@ struct light {
#ifndef VSMCUBE
return vec4(1.);
#else
vec3 fragment = vec3(vpeye);
vec3 normal = vec3(normalize(vneye));
vec3 viewDir = normalize(-fragment);

View File

@ -1,4 +1,3 @@
//uniform mat4 u_model, u_view, u_proj;
uniform mat4 u_mvp;
in vec3 att_position;
@ -23,7 +22,6 @@ void do_shadow() {
}
void main() {
// gl_Position = proj * view * model * vec4(att_position, 1.0);
gl_Position = u_mvp * vec4(att_position, 1.0);
v_normal = normalize(att_normal);
v_normal_ws = normalize(vec3(model * vec4(att_normal, 0.))); // normal world/model space

View File

@ -2399,6 +2399,96 @@ skybox_t skybox(const char *asset, int flags) {
return sky;
}
void skybox_mie_calc_sh(skybox_t *sky) {
unsigned WIDTH = 512, HEIGHT = 512;
unsigned last_fb;
int vp[4];
glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &last_fb);
glGetIntegerv(GL_VIEWPORT, vp);
if (!sky->pixels)
sky->pixels = MALLOC(WIDTH*HEIGHT*3);
if (!sky->framebuffers[0]) {
for(int i = 0; i < 6; ++i) {
glGenFramebuffers(1, &sky->framebuffers[i]);
glBindFramebuffer(GL_FRAMEBUFFER, sky->framebuffers[i]);
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);
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);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, sky->textures[i], 0);
}
}
static vec3 directions[6] = {
{1.0f, 0.0f, 0.0f},
{-1.0f, 0.0f, 0.0f},
{0.0f, 1.0f, 0.0f},
{0.0f, -1.0f, 0.0f},
{0.0f, 0.0f, 1.0f},
{0.0f, 0.0f, -1.0f}
};
int samples = 0;
for(int i = 0; i < 6; ++i) {
glBindFramebuffer(GL_FRAMEBUFFER, sky->framebuffers[i]);
glViewport(0, 0, WIDTH, HEIGHT);
glUseProgram(sky->program);
mat44 proj; perspective44(proj, 90.0f, WIDTH / (float)HEIGHT, 0.01f, 1000.f);
mat44 view; lookat44(view, vec3(0,0,0), directions[i], vec3(0,1,0));
skybox_render(sky, proj, view);
glReadPixels(0, 0, WIDTH, HEIGHT, GL_RGB, GL_UNSIGNED_BYTE, sky->pixels);
// calculate SH coefficients (@ands)
// copied from cubemap6 method
const vec3 skyDir[] = {{ 1, 0, 0},{-1, 0, 0},{ 0, 1, 0},{ 0,-1, 0},{ 0, 0, 1},{ 0, 0,-1}};
const vec3 skyX[] = {{ 0, 0,-1},{ 0, 0, 1},{ 1, 0, 0},{ 1, 0, 0},{ 1, 0, 0},{-1, 0, 0}};
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;
for (int x = 0; x < WIDTH; x += step) {
vec3 n = add3(
add3(
scale3(skyX[i], 2.0f * (x / (WIDTH - 1.0f)) - 1.0f),
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;
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));
sky->cubemap.sh[2] = add3(sky->cubemap.sh[2], scale3(light, 0.488603f * n.z * 2.0 / 3.0));
sky->cubemap.sh[3] = add3(sky->cubemap.sh[3], scale3(light, -0.488603f * n.x * 2.0 / 3.0));
sky->cubemap.sh[4] = add3(sky->cubemap.sh[4], scale3(light, 1.092548f * n.x * n.y / 4.0));
sky->cubemap.sh[5] = add3(sky->cubemap.sh[5], scale3(light, -1.092548f * n.y * n.z / 4.0));
sky->cubemap.sh[6] = add3(sky->cubemap.sh[6], scale3(light, 0.315392f * (3.0f * n.z * n.z - 1.0f) / 4.0));
sky->cubemap.sh[7] = add3(sky->cubemap.sh[7], scale3(light, -1.092548f * n.x * n.z / 4.0));
sky->cubemap.sh[8] = add3(sky->cubemap.sh[8], scale3(light, 0.546274f * (n.x * n.x - n.y * n.y) / 4.0));
p += 3 * step;
samples++;
}
}
}
for (int s = 0; s < 9; s++) {
sky->cubemap.sh[s] = scale3(sky->cubemap.sh[s], 32.f / samples);
}
glBindFramebuffer(GL_FRAMEBUFFER, last_fb);
glViewport(vp[0], vp[1], vp[2], vp[3]);
}
int skybox_push_state(skybox_t *sky, mat44 proj, mat44 view) {
last_cubemap = &sky->cubemap;
@ -2434,6 +2524,12 @@ void skybox_destroy(skybox_t *sky) {
glDeleteProgram(sky->program);
cubemap_destroy(&sky->cubemap);
mesh_destroy(&sky->geometry);
if (sky->pixels) {
FREE(sky->pixels);
glDeleteFramebuffers(6, sky->framebuffers);
glDeleteTextures(6, sky->textures);
}
}
// -----------------------------------------------------------------------------

View File

@ -612,11 +612,17 @@ typedef struct skybox_t {
mesh_t geometry;
cubemap_t cubemap;
int flags;
// mie
unsigned framebuffers;
unsigned textures;
unsigned char *pixels;
} 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 int skybox_push_state(skybox_t *sky, mat44 proj, mat44 view); // @to deprecate
API int skybox_pop_state(); // @to deprecate

View File

@ -14,6 +14,7 @@ const char *const fs_0_0_shadowmap_lit = "//" FILELINE "\n"
" vec4 specular;\n"
" float constantAttenuation, linearAttenuation, quadraticAttenuation;\n"
"};\n"
" \n"
"light light0 = light(\n"
" lightPos,\n"
" vec4(1,1,1,1), // diffuse\n"
@ -50,7 +51,6 @@ const char *const fs_0_0_shadowmap_lit = "//" FILELINE "\n"
#ifndef VSMCUBE
" return vec4(1.);\n"
#else
" \n"
" vec3 fragment = vec3(vpeye);\n"
" vec3 normal = vec3(normalize(vneye));\n"
" vec3 viewDir = normalize(-fragment);\n"
@ -648,7 +648,6 @@ const char *const vs_324_24_sprite = "//" FILELINE "\n"
"}\n";
const char *const vs_332_32 = "//" FILELINE "\n"
"//uniform mat4 u_model, u_view, u_proj;\n"
"uniform mat4 u_mvp;\n"
"\n"
"in vec3 att_position;\n"
@ -673,7 +672,6 @@ const char *const vs_332_32 = "//" FILELINE "\n"
"}\n"
"\n"
"void main() {\n"
" // gl_Position = proj * view * model * vec4(att_position, 1.0);\n"
" gl_Position = u_mvp * vec4(att_position, 1.0);\n"
" v_normal = normalize(att_normal);\n"
" v_normal_ws = normalize(vec3(model * vec4(att_normal, 0.))); // normal world/model space\n"

View File

@ -10226,6 +10226,7 @@ const char *const fs_0_0_shadowmap_lit = "//" FILELINE "\n"
" vec4 specular;\n"
" float constantAttenuation, linearAttenuation, quadraticAttenuation;\n"
"};\n"
" \n"
"light light0 = light(\n"
" lightPos,\n"
" vec4(1,1,1,1), // diffuse\n"
@ -10262,7 +10263,6 @@ const char *const fs_0_0_shadowmap_lit = "//" FILELINE "\n"
#ifndef VSMCUBE
" return vec4(1.);\n"
#else
" \n"
" vec3 fragment = vec3(vpeye);\n"
" vec3 normal = vec3(normalize(vneye));\n"
" vec3 viewDir = normalize(-fragment);\n"
@ -10860,7 +10860,6 @@ const char *const vs_324_24_sprite = "//" FILELINE "\n"
"}\n";
const char *const vs_332_32 = "//" FILELINE "\n"
"//uniform mat4 u_model, u_view, u_proj;\n"
"uniform mat4 u_mvp;\n"
"\n"
"in vec3 att_position;\n"
@ -10885,7 +10884,6 @@ const char *const vs_332_32 = "//" FILELINE "\n"
"}\n"
"\n"
"void main() {\n"
" // gl_Position = proj * view * model * vec4(att_position, 1.0);\n"
" gl_Position = u_mvp * vec4(att_position, 1.0);\n"
" v_normal = normalize(att_normal);\n"
" v_normal_ws = normalize(vec3(model * vec4(att_normal, 0.))); // normal world/model space\n"
@ -13310,6 +13308,96 @@ skybox_t skybox(const char *asset, int flags) {
return sky;
}
void skybox_mie_calc_sh(skybox_t *sky) {
unsigned WIDTH = 512, HEIGHT = 512;
unsigned last_fb;
int vp[4];
glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &last_fb);
glGetIntegerv(GL_VIEWPORT, vp);
if (!sky->pixels)
sky->pixels = MALLOC(WIDTH*HEIGHT*3);
if (!sky->framebuffers[0]) {
for(int i = 0; i < 6; ++i) {
glGenFramebuffers(1, &sky->framebuffers[i]);
glBindFramebuffer(GL_FRAMEBUFFER, sky->framebuffers[i]);
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);
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);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, sky->textures[i], 0);
}
}
static vec3 directions[6] = {
{1.0f, 0.0f, 0.0f},
{-1.0f, 0.0f, 0.0f},
{0.0f, 1.0f, 0.0f},
{0.0f, -1.0f, 0.0f},
{0.0f, 0.0f, 1.0f},
{0.0f, 0.0f, -1.0f}
};
int samples = 0;
for(int i = 0; i < 6; ++i) {
glBindFramebuffer(GL_FRAMEBUFFER, sky->framebuffers[i]);
glViewport(0, 0, WIDTH, HEIGHT);
glUseProgram(sky->program);
mat44 proj; perspective44(proj, 90.0f, WIDTH / (float)HEIGHT, 0.01f, 1000.f);
mat44 view; lookat44(view, vec3(0,0,0), directions[i], vec3(0,1,0));
skybox_render(sky, proj, view);
glReadPixels(0, 0, WIDTH, HEIGHT, GL_RGB, GL_UNSIGNED_BYTE, sky->pixels);
// calculate SH coefficients (@ands)
// copied from cubemap6 method
const vec3 skyDir[] = {{ 1, 0, 0},{-1, 0, 0},{ 0, 1, 0},{ 0,-1, 0},{ 0, 0, 1},{ 0, 0,-1}};
const vec3 skyX[] = {{ 0, 0,-1},{ 0, 0, 1},{ 1, 0, 0},{ 1, 0, 0},{ 1, 0, 0},{-1, 0, 0}};
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;
for (int x = 0; x < WIDTH; x += step) {
vec3 n = add3(
add3(
scale3(skyX[i], 2.0f * (x / (WIDTH - 1.0f)) - 1.0f),
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;
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));
sky->cubemap.sh[2] = add3(sky->cubemap.sh[2], scale3(light, 0.488603f * n.z * 2.0 / 3.0));
sky->cubemap.sh[3] = add3(sky->cubemap.sh[3], scale3(light, -0.488603f * n.x * 2.0 / 3.0));
sky->cubemap.sh[4] = add3(sky->cubemap.sh[4], scale3(light, 1.092548f * n.x * n.y / 4.0));
sky->cubemap.sh[5] = add3(sky->cubemap.sh[5], scale3(light, -1.092548f * n.y * n.z / 4.0));
sky->cubemap.sh[6] = add3(sky->cubemap.sh[6], scale3(light, 0.315392f * (3.0f * n.z * n.z - 1.0f) / 4.0));
sky->cubemap.sh[7] = add3(sky->cubemap.sh[7], scale3(light, -1.092548f * n.x * n.z / 4.0));
sky->cubemap.sh[8] = add3(sky->cubemap.sh[8], scale3(light, 0.546274f * (n.x * n.x - n.y * n.y) / 4.0));
p += 3 * step;
samples++;
}
}
}
for (int s = 0; s < 9; s++) {
sky->cubemap.sh[s] = scale3(sky->cubemap.sh[s], 32.f / samples);
}
glBindFramebuffer(GL_FRAMEBUFFER, last_fb);
glViewport(vp[0], vp[1], vp[2], vp[3]);
}
int skybox_push_state(skybox_t *sky, mat44 proj, mat44 view) {
last_cubemap = &sky->cubemap;
@ -13345,6 +13433,12 @@ void skybox_destroy(skybox_t *sky) {
glDeleteProgram(sky->program);
cubemap_destroy(&sky->cubemap);
mesh_destroy(&sky->geometry);
if (sky->pixels) {
FREE(sky->pixels);
glDeleteFramebuffers(6, sky->framebuffers);
glDeleteTextures(6, sky->textures);
}
}
// -----------------------------------------------------------------------------

View File

@ -2850,11 +2850,17 @@ typedef struct skybox_t {
mesh_t geometry;
cubemap_t cubemap;
int flags;
// mie
unsigned framebuffers;
unsigned textures;
unsigned char *pixels;
} 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 int skybox_push_state(skybox_t *sky, mat44 proj, mat44 view); // @to deprecate
API int skybox_pop_state(); // @to deprecate