render: add skybox_mie_calc_sh
parent
d6d0294ae5
commit
2d6ed9740d
|
@ -5,6 +5,7 @@
|
||||||
int main() {
|
int main() {
|
||||||
window_create(80, WINDOW_MSAA8);
|
window_create(80, WINDOW_MSAA8);
|
||||||
window_title(__FILE__);
|
window_title(__FILE__);
|
||||||
|
window_fps_unlock();
|
||||||
|
|
||||||
// load all fx files
|
// load all fx files
|
||||||
fx_load("fx**.fs");
|
fx_load("fx**.fs");
|
||||||
|
@ -23,6 +24,8 @@ int main() {
|
||||||
camera_t cam = camera();
|
camera_t cam = camera();
|
||||||
cam.speed = 0.2f;
|
cam.speed = 0.2f;
|
||||||
|
|
||||||
|
double sky_update_until = 0.0;
|
||||||
|
|
||||||
// demo loop
|
// demo loop
|
||||||
while (window_swap())
|
while (window_swap())
|
||||||
{
|
{
|
||||||
|
@ -33,6 +36,14 @@ int main() {
|
||||||
if( input_down(KEY_X) ) window_screenshot(__FILE__ ".png");
|
if( input_down(KEY_X) ) window_screenshot(__FILE__ ".png");
|
||||||
if( input_down(KEY_Z) ) window_record(__FILE__ ".mp4");
|
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
|
// fps camera
|
||||||
bool active = ui_active() || ui_hover() || gizmo_active() ? false : input(MOUSE_L) || input(MOUSE_M) || input(MOUSE_R);
|
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);
|
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;
|
float scale = 1.00;
|
||||||
mat44 M; copy44(M, sponza.pivot); translate44(M, 0,0,0); scale44(M, scale,scale,scale);
|
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);
|
model_render(sponza, cam.proj, cam.view, M, 0);
|
||||||
|
|
||||||
// post-fxs end here
|
// post-fxs end here
|
||||||
|
|
|
@ -27,7 +27,7 @@ void temp_calc(vec4 *pixels){
|
||||||
int main() {
|
int main() {
|
||||||
window_create(50, WINDOW_SQUARE|WINDOW_VSYNC_DISABLED);
|
window_create(50, WINDOW_SQUARE|WINDOW_VSYNC_DISABLED);
|
||||||
window_title(__FILE__);
|
window_title(__FILE__);
|
||||||
window_fps_lock(0);
|
window_fps_unlock();
|
||||||
|
|
||||||
texture_t tex;
|
texture_t tex;
|
||||||
|
|
||||||
|
|
|
@ -2520,10 +2520,14 @@ handle program;
|
||||||
mesh_t geometry;
|
mesh_t geometry;
|
||||||
cubemap_t cubemap;
|
cubemap_t cubemap;
|
||||||
int flags;
|
int flags;
|
||||||
|
unsigned framebuffers;
|
||||||
|
unsigned textures;
|
||||||
|
unsigned char *pixels;
|
||||||
} skybox_t;
|
} skybox_t;
|
||||||
skybox_t skybox(const char *panorama_or_cubemap_folder, int flags);
|
skybox_t skybox(const char *panorama_or_cubemap_folder, int flags);
|
||||||
int skybox_render(skybox_t *sky, mat44 proj, mat44 view);
|
int skybox_render(skybox_t *sky, mat44 proj, mat44 view);
|
||||||
void skybox_destroy(skybox_t *sky);
|
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_push_state(skybox_t *sky, mat44 proj, mat44 view);
|
||||||
int skybox_pop_state();
|
int skybox_pop_state();
|
||||||
void viewport_color(uint32_t color);
|
void viewport_color(uint32_t color);
|
||||||
|
|
|
@ -16767,11 +16767,17 @@ typedef struct skybox_t {
|
||||||
mesh_t geometry;
|
mesh_t geometry;
|
||||||
cubemap_t cubemap;
|
cubemap_t cubemap;
|
||||||
int flags;
|
int flags;
|
||||||
|
|
||||||
|
// mie
|
||||||
|
unsigned framebuffers;
|
||||||
|
unsigned textures;
|
||||||
|
unsigned char *pixels;
|
||||||
} skybox_t;
|
} skybox_t;
|
||||||
|
|
||||||
API skybox_t skybox(const char *panorama_or_cubemap_folder, int flags);
|
API skybox_t skybox(const char *panorama_or_cubemap_folder, int flags);
|
||||||
API int skybox_render(skybox_t *sky, mat44 proj, mat44 view);
|
API int skybox_render(skybox_t *sky, mat44 proj, mat44 view);
|
||||||
API void skybox_destroy(skybox_t *sky);
|
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_push_state(skybox_t *sky, mat44 proj, mat44 view); // @to deprecate
|
||||||
API int skybox_pop_state(); // @to deprecate
|
API int skybox_pop_state(); // @to deprecate
|
||||||
|
@ -339317,102 +339323,102 @@ const char *const fs_0_0_shadowmap_lit = "//" FILELINE "\n"
|
||||||
" vec4 diffuse;\n"
|
" vec4 diffuse;\n"
|
||||||
" vec4 specular;\n"
|
" vec4 specular;\n"
|
||||||
" float constantAttenuation, linearAttenuation, quadraticAttenuation;\n"
|
" float constantAttenuation, linearAttenuation, quadraticAttenuation;\n"
|
||||||
" };\n"
|
"};\n"
|
||||||
" light light0 = light(\n"
|
" \n"
|
||||||
|
"light light0 = light(\n"
|
||||||
" lightPos,\n"
|
" lightPos,\n"
|
||||||
" vec4(1,1,1,1), // diffuse\n"
|
" vec4(1,1,1,1), // diffuse\n"
|
||||||
" vec4(1,1,1,1), // specular\n"
|
" vec4(1,1,1,1), // specular\n"
|
||||||
" 1.0, 0.0, 0.0 // attenuation (const, linear, quad)\n"
|
" 1.0, 0.0, 0.0 // attenuation (const, linear, quad)\n"
|
||||||
" );\n"
|
");\n"
|
||||||
" \n"
|
" \n"
|
||||||
" // From http://fabiensanglard.net/shadowmappingVSM/index.php\n"
|
"// From http://fabiensanglard.net/shadowmappingVSM/index.php\n"
|
||||||
#if VSMCUBE
|
#if VSMCUBE
|
||||||
" float chebyshevUpperBound(float distance, vec3 dir) {\n"
|
"float chebyshevUpperBound(float distance, vec3 dir) {\n"
|
||||||
" distance = distance/20 ;\n"
|
" distance = distance/20 ;\n"
|
||||||
" vec2 moments = texture(shadowMap, dir).rg;\n"
|
" vec2 moments = texture(shadowMap, dir).rg;\n"
|
||||||
#else
|
#else
|
||||||
" float chebyshevUpperBound(float distance, vec4 scPostW) {\n"
|
"float chebyshevUpperBound(float distance, vec4 scPostW) {\n"
|
||||||
" vec2 moments = texture(shadowMap,scPostW.xy).rg;\n"
|
" vec2 moments = texture(shadowMap,scPostW.xy).rg;\n"
|
||||||
#endif
|
#endif
|
||||||
" // Surface is fully lit. as the current fragment is before the light occluder\n"
|
" // Surface is fully lit. as the current fragment is before the light occluder\n"
|
||||||
" if (distance <= moments.x)\n"
|
" if (distance <= moments.x)\n"
|
||||||
" return 1.0;\n"
|
" return 1.0;\n"
|
||||||
" \n"
|
" \n"
|
||||||
" // The fragment is either in shadow or penumbra. We now use chebyshev's upperBound to check\n"
|
" // The fragment is either in shadow or penumbra. We now use chebyshev's upperBound to check\n"
|
||||||
" // How likely this pixel is to be lit (p_max)\n"
|
" // How likely this pixel is to be lit (p_max)\n"
|
||||||
" float variance = moments.y - (moments.x*moments.x);\n"
|
" float variance = moments.y - (moments.x*moments.x);\n"
|
||||||
" //variance = max(variance, 0.000002);\n"
|
" //variance = max(variance, 0.000002);\n"
|
||||||
" variance = max(variance, 0.00002);\n"
|
" variance = max(variance, 0.00002);\n"
|
||||||
" \n"
|
" \n"
|
||||||
" float d = distance - moments.x;\n"
|
" float d = distance - moments.x;\n"
|
||||||
" float p_max = variance / (variance + d*d);\n"
|
" float p_max = variance / (variance + d*d);\n"
|
||||||
" \n"
|
" \n"
|
||||||
" return p_max;\n"
|
" return p_max;\n"
|
||||||
" }\n"
|
"}\n"
|
||||||
" \n"
|
"\n"
|
||||||
" vec4 shadowmap(in vec4 vpeye, in vec4 vneye, in vec2 uv, in vec4 sc) {\n"
|
"vec4 shadowmap(in vec4 vpeye, in vec4 vneye, in vec2 uv, in vec4 sc) {\n"
|
||||||
#ifndef VSMCUBE
|
#ifndef VSMCUBE
|
||||||
" return vec4(1.);\n"
|
" return vec4(1.);\n"
|
||||||
#else
|
#else
|
||||||
" \n"
|
" vec3 fragment = vec3(vpeye);\n"
|
||||||
" vec3 fragment = vec3(vpeye);\n"
|
" vec3 normal = vec3(normalize(vneye));\n"
|
||||||
" vec3 normal = vec3(normalize(vneye));\n"
|
" vec3 viewDir = normalize(-fragment);\n"
|
||||||
" vec3 viewDir = normalize(-fragment);\n"
|
" \n"
|
||||||
" \n"
|
" // Lighting\n"
|
||||||
" // Lighting\n"
|
" // Convert to eye-space\n"
|
||||||
" // Convert to eye-space\n"
|
" vec3 light = vec3(view * vec4(light0.position, 1.0));\n"
|
||||||
" vec3 light = vec3(view * vec4(light0.position, 1.0));\n"
|
" \n"
|
||||||
" \n"
|
#if VSMCUBE
|
||||||
#if VSMCUBE
|
" // Vectors\n"
|
||||||
" // Vectors\n"
|
" vec3 fragmentToLight = light - fragment;\n"
|
||||||
" vec3 fragmentToLight = light - fragment;\n"
|
" vec3 fragmentToLightDir = normalize(fragmentToLight);\n"
|
||||||
" vec3 fragmentToLightDir = normalize(fragmentToLight);\n"
|
" \n"
|
||||||
" \n"
|
" // Shadows\n"
|
||||||
" // Shadows\n"
|
" vec4 fragmentToLight_world = inverse(view) * vec4(fragmentToLightDir, 0.0);\n"
|
||||||
" vec4 fragmentToLight_world = inverse(view) * vec4(fragmentToLightDir, 0.0);\n"
|
" float shadowFactor = chebyshevUpperBound(length(fragmentToLight), -fragmentToLight_world.xyz);\n"
|
||||||
" float shadowFactor = chebyshevUpperBound(length(fragmentToLight), -fragmentToLight_world.xyz);\n"
|
#else
|
||||||
#else
|
" // Shadows\n"
|
||||||
" // Shadows\n"
|
" vec4 scPostW = sc / sc.w;\n"
|
||||||
" vec4 scPostW = sc / sc.w;\n"
|
" scPostW = scPostW * 0.5 + 0.5;\n"
|
||||||
" scPostW = scPostW * 0.5 + 0.5;\n"
|
" \n"
|
||||||
" \n"
|
" float shadowFactor = 1.0; // Not in shadow\n"
|
||||||
" float shadowFactor = 1.0; // Not in shadow\n"
|
" \n"
|
||||||
" \n"
|
" bool outsideShadowMap = sc.w <= 0.0f || (scPostW.x < 0 || scPostW.y < 0) || (scPostW.x >= 1 || scPostW.y >= 1);\n"
|
||||||
" bool outsideShadowMap = sc.w <= 0.0f || (scPostW.x < 0 || scPostW.y < 0) || (scPostW.x >= 1 || scPostW.y >= 1);\n"
|
" if (!outsideShadowMap) {\n"
|
||||||
" if (!outsideShadowMap) {\n"
|
" shadowFactor = chebyshevUpperBound(scPostW.z, scPostW);\n"
|
||||||
" shadowFactor = chebyshevUpperBound(scPostW.z, scPostW);\n"
|
" }\n"
|
||||||
" }\n"
|
#endif
|
||||||
#endif
|
" \n"
|
||||||
" \n"
|
" vec4 diffColor = vec4(1,1,1,1);\n"
|
||||||
" vec4 diffColor = vec4(1,1,1,1);\n"
|
#if VSMCUBE
|
||||||
#if VSMCUBE
|
" if(doTexture != 0) diffColor = vec4(vec3(texture(shadowMap, -fragmentToLight_world.xyz).r), 1.0);\n"
|
||||||
" if(doTexture != 0) diffColor = vec4(vec3(texture(shadowMap, -fragmentToLight_world.xyz).r), 1.0);\n"
|
#else
|
||||||
#else
|
" if(doTexture != 0) diffColor = vec4(vec3(texture(shadowMap, vec2(uv.x, 1.0 - uv.y)).r), 1.0);\n"
|
||||||
" if(doTexture != 0) diffColor = vec4(vec3(texture(shadowMap, vec2(uv.x, 1.0 - uv.y)).r), 1.0);\n"
|
#endif
|
||||||
#endif
|
" \n"
|
||||||
" \n"
|
#if 1
|
||||||
#if 1
|
" vec3 positionToLight = light - fragment;\n"
|
||||||
" vec3 positionToLight = light - fragment;\n"
|
" vec3 lightDir = normalize(positionToLight);\n"
|
||||||
" vec3 lightDir = normalize(positionToLight);\n"
|
" \n"
|
||||||
" \n"
|
" // Angle between fragment-normal and incoming light\n"
|
||||||
" // Angle between fragment-normal and incoming light\n"
|
" float cosAngIncidence = dot(lightDir, normal);\n"
|
||||||
" float cosAngIncidence = dot(lightDir, normal);\n"
|
" cosAngIncidence = clamp(cosAngIncidence, 0, 1);\n"
|
||||||
" cosAngIncidence = clamp(cosAngIncidence, 0, 1);\n"
|
" \n"
|
||||||
" \n"
|
" float attenuation = 1.0f;\n"
|
||||||
" float attenuation = 1.0f;\n"
|
" attenuation = 1.0 / (light0.constantAttenuation + light0.linearAttenuation * length(positionToLight) + light0.quadraticAttenuation * pow(length(positionToLight),2));\n"
|
||||||
" attenuation = 1.0 / (light0.constantAttenuation + light0.linearAttenuation * length(positionToLight) + light0.quadraticAttenuation * pow(length(positionToLight),2));\n"
|
" \n"
|
||||||
" \n"
|
" vec4 diffuse = diffColor * light0.diffuse * cosAngIncidence * attenuation;\n"
|
||||||
" vec4 diffuse = diffColor * light0.diffuse * cosAngIncidence * attenuation;\n"
|
" \n"
|
||||||
" \n"
|
" vec4 total_lighting;\n"
|
||||||
" vec4 total_lighting;\n"
|
" total_lighting += vec4(0.1, 0.1, 0.1, 1.0) * diffColor; // Ambient\n"
|
||||||
" total_lighting += vec4(0.1, 0.1, 0.1, 1.0) * diffColor; // Ambient\n"
|
" total_lighting += diffuse * shadowFactor; // Diffuse\n"
|
||||||
" total_lighting += diffuse * shadowFactor; // Diffuse\n"
|
#else
|
||||||
#else
|
" vec4 total_lighting = diffColor;\n"
|
||||||
" vec4 total_lighting = diffColor;\n"
|
#endif
|
||||||
#endif
|
" return vec4(clamp(vec3(total_lighting), 0., 1.), 1.0);\n"
|
||||||
" return vec4(clamp(vec3(total_lighting), 0., 1.), 1.0);\n"
|
#endif
|
||||||
#endif
|
"}\n";
|
||||||
" }\n";
|
|
||||||
|
|
||||||
const char *const fs_0_0_shadowmap_unlit = "//" FILELINE "\n"
|
const char *const fs_0_0_shadowmap_unlit = "//" FILELINE "\n"
|
||||||
"// uniform mat4 view = mat4(1.0);\n"
|
"// uniform mat4 view = mat4(1.0);\n"
|
||||||
|
@ -339422,7 +339428,7 @@ const char *const fs_0_0_shadowmap_unlit = "//" FILELINE "\n"
|
||||||
"\n"
|
"\n"
|
||||||
"vec4 shadowmap(in vec4 vpeye, in vec4 vneye, in vec2 Texcoord, in vec4 sc) {\n"
|
"vec4 shadowmap(in vec4 vpeye, in vec4 vneye, in vec2 Texcoord, in vec4 sc) {\n"
|
||||||
" return vec4(1.);\n"
|
" return vec4(1.);\n"
|
||||||
" };\n";
|
"};\n";
|
||||||
|
|
||||||
const char *const fs_24_4_sprite = "//" FILELINE "\n"
|
const char *const fs_24_4_sprite = "//" FILELINE "\n"
|
||||||
"uniform sampler2D u_texture;\n"
|
"uniform sampler2D u_texture;\n"
|
||||||
|
@ -339952,7 +339958,6 @@ const char *const vs_324_24_sprite = "//" FILELINE "\n"
|
||||||
"}\n";
|
"}\n";
|
||||||
|
|
||||||
const char *const vs_332_32 = "//" FILELINE "\n"
|
const char *const vs_332_32 = "//" FILELINE "\n"
|
||||||
"//uniform mat4 u_model, u_view, u_proj;\n"
|
|
||||||
"uniform mat4 u_mvp;\n"
|
"uniform mat4 u_mvp;\n"
|
||||||
"\n"
|
"\n"
|
||||||
"in vec3 att_position;\n"
|
"in vec3 att_position;\n"
|
||||||
|
@ -339977,7 +339982,6 @@ const char *const vs_332_32 = "//" FILELINE "\n"
|
||||||
"}\n"
|
"}\n"
|
||||||
"\n"
|
"\n"
|
||||||
"void main() {\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"
|
" gl_Position = u_mvp * vec4(att_position, 1.0);\n"
|
||||||
" v_normal = normalize(att_normal);\n"
|
" v_normal = normalize(att_normal);\n"
|
||||||
" v_normal_ws = normalize(vec3(model * vec4(att_normal, 0.))); // normal world/model space\n"
|
" v_normal_ws = normalize(vec3(model * vec4(att_normal, 0.))); // normal world/model space\n"
|
||||||
|
@ -342402,14 +342406,104 @@ skybox_t skybox(const char *asset, int flags) {
|
||||||
|
|
||||||
return sky;
|
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) {
|
int skybox_push_state(skybox_t *sky, mat44 proj, mat44 view) {
|
||||||
last_cubemap = &sky->cubemap;
|
last_cubemap = &sky->cubemap;
|
||||||
|
|
||||||
//glClear(GL_DEPTH_BUFFER_BIT);
|
//glClear(GL_DEPTH_BUFFER_BIT);
|
||||||
//glEnable(GL_DEPTH_TEST);
|
//glEnable(GL_DEPTH_TEST);
|
||||||
glDepthFunc(GL_LEQUAL);
|
glDepthFunc(GL_LEQUAL);
|
||||||
//glDisable(GL_CULL_FACE);
|
//glDisable(GL_CULL_FACE);
|
||||||
glDisable(GL_DEPTH_TEST);
|
glDisable(GL_DEPTH_TEST);
|
||||||
|
|
||||||
mat44 mvp; multiply44x2(mvp, proj, view);
|
mat44 mvp; multiply44x2(mvp, proj, view);
|
||||||
|
|
||||||
|
@ -342417,7 +342511,7 @@ glDisable(GL_DEPTH_TEST);
|
||||||
shader_bind(sky->program);
|
shader_bind(sky->program);
|
||||||
shader_mat44("u_mvp", mvp);
|
shader_mat44("u_mvp", mvp);
|
||||||
if( sky->flags ) {
|
if( sky->flags ) {
|
||||||
shader_cubemap("u_cubemap", sky->cubemap.id);
|
shader_cubemap("u_cubemap", sky->cubemap.id);
|
||||||
}
|
}
|
||||||
return 0; // @fixme: return sortable hash here?
|
return 0; // @fixme: return sortable hash here?
|
||||||
}
|
}
|
||||||
|
@ -342437,6 +342531,12 @@ void skybox_destroy(skybox_t *sky) {
|
||||||
glDeleteProgram(sky->program);
|
glDeleteProgram(sky->program);
|
||||||
cubemap_destroy(&sky->cubemap);
|
cubemap_destroy(&sky->cubemap);
|
||||||
mesh_destroy(&sky->geometry);
|
mesh_destroy(&sky->geometry);
|
||||||
|
|
||||||
|
if (sky->pixels) {
|
||||||
|
FREE(sky->pixels);
|
||||||
|
glDeleteFramebuffers(6, sky->framebuffers);
|
||||||
|
glDeleteTextures(6, sky->textures);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
|
|
@ -12,99 +12,99 @@ struct light {
|
||||||
vec4 diffuse;
|
vec4 diffuse;
|
||||||
vec4 specular;
|
vec4 specular;
|
||||||
float constantAttenuation, linearAttenuation, quadraticAttenuation;
|
float constantAttenuation, linearAttenuation, quadraticAttenuation;
|
||||||
};
|
};
|
||||||
light light0 = light(
|
|
||||||
|
light light0 = light(
|
||||||
lightPos,
|
lightPos,
|
||||||
vec4(1,1,1,1), // diffuse
|
vec4(1,1,1,1), // diffuse
|
||||||
vec4(1,1,1,1), // specular
|
vec4(1,1,1,1), // specular
|
||||||
1.0, 0.0, 0.0 // attenuation (const, linear, quad)
|
1.0, 0.0, 0.0 // attenuation (const, linear, quad)
|
||||||
);
|
);
|
||||||
|
|
||||||
// From http://fabiensanglard.net/shadowmappingVSM/index.php
|
// From http://fabiensanglard.net/shadowmappingVSM/index.php
|
||||||
#if VSMCUBE
|
#if VSMCUBE
|
||||||
float chebyshevUpperBound(float distance, vec3 dir) {
|
float chebyshevUpperBound(float distance, vec3 dir) {
|
||||||
distance = distance/20 ;
|
distance = distance/20 ;
|
||||||
vec2 moments = texture(shadowMap, dir).rg;
|
vec2 moments = texture(shadowMap, dir).rg;
|
||||||
#else
|
#else
|
||||||
float chebyshevUpperBound(float distance, vec4 scPostW) {
|
float chebyshevUpperBound(float distance, vec4 scPostW) {
|
||||||
vec2 moments = texture(shadowMap,scPostW.xy).rg;
|
vec2 moments = texture(shadowMap,scPostW.xy).rg;
|
||||||
#endif
|
#endif
|
||||||
// Surface is fully lit. as the current fragment is before the light occluder
|
// Surface is fully lit. as the current fragment is before the light occluder
|
||||||
if (distance <= moments.x)
|
if (distance <= moments.x)
|
||||||
return 1.0;
|
return 1.0;
|
||||||
|
|
||||||
// The fragment is either in shadow or penumbra. We now use chebyshev's upperBound to check
|
// The fragment is either in shadow or penumbra. We now use chebyshev's upperBound to check
|
||||||
// How likely this pixel is to be lit (p_max)
|
// How likely this pixel is to be lit (p_max)
|
||||||
float variance = moments.y - (moments.x*moments.x);
|
float variance = moments.y - (moments.x*moments.x);
|
||||||
//variance = max(variance, 0.000002);
|
//variance = max(variance, 0.000002);
|
||||||
variance = max(variance, 0.00002);
|
variance = max(variance, 0.00002);
|
||||||
|
|
||||||
float d = distance - moments.x;
|
float d = distance - moments.x;
|
||||||
float p_max = variance / (variance + d*d);
|
float p_max = variance / (variance + d*d);
|
||||||
|
|
||||||
return p_max;
|
return p_max;
|
||||||
}
|
}
|
||||||
|
|
||||||
vec4 shadowmap(in vec4 vpeye, in vec4 vneye, in vec2 uv, in vec4 sc) {
|
vec4 shadowmap(in vec4 vpeye, in vec4 vneye, in vec2 uv, in vec4 sc) {
|
||||||
#ifndef VSMCUBE
|
#ifndef VSMCUBE
|
||||||
return vec4(1.);
|
return vec4(1.);
|
||||||
#else
|
#else
|
||||||
|
vec3 fragment = vec3(vpeye);
|
||||||
vec3 fragment = vec3(vpeye);
|
vec3 normal = vec3(normalize(vneye));
|
||||||
vec3 normal = vec3(normalize(vneye));
|
vec3 viewDir = normalize(-fragment);
|
||||||
vec3 viewDir = normalize(-fragment);
|
|
||||||
|
// Lighting
|
||||||
// Lighting
|
// Convert to eye-space
|
||||||
// Convert to eye-space
|
vec3 light = vec3(view * vec4(light0.position, 1.0));
|
||||||
vec3 light = vec3(view * vec4(light0.position, 1.0));
|
|
||||||
|
#if VSMCUBE
|
||||||
#if VSMCUBE
|
// Vectors
|
||||||
// Vectors
|
vec3 fragmentToLight = light - fragment;
|
||||||
vec3 fragmentToLight = light - fragment;
|
vec3 fragmentToLightDir = normalize(fragmentToLight);
|
||||||
vec3 fragmentToLightDir = normalize(fragmentToLight);
|
|
||||||
|
// Shadows
|
||||||
// Shadows
|
vec4 fragmentToLight_world = inverse(view) * vec4(fragmentToLightDir, 0.0);
|
||||||
vec4 fragmentToLight_world = inverse(view) * vec4(fragmentToLightDir, 0.0);
|
float shadowFactor = chebyshevUpperBound(length(fragmentToLight), -fragmentToLight_world.xyz);
|
||||||
float shadowFactor = chebyshevUpperBound(length(fragmentToLight), -fragmentToLight_world.xyz);
|
#else
|
||||||
#else
|
// Shadows
|
||||||
// Shadows
|
vec4 scPostW = sc / sc.w;
|
||||||
vec4 scPostW = sc / sc.w;
|
scPostW = scPostW * 0.5 + 0.5;
|
||||||
scPostW = scPostW * 0.5 + 0.5;
|
|
||||||
|
float shadowFactor = 1.0; // Not in shadow
|
||||||
float shadowFactor = 1.0; // Not in shadow
|
|
||||||
|
bool outsideShadowMap = sc.w <= 0.0f || (scPostW.x < 0 || scPostW.y < 0) || (scPostW.x >= 1 || scPostW.y >= 1);
|
||||||
bool outsideShadowMap = sc.w <= 0.0f || (scPostW.x < 0 || scPostW.y < 0) || (scPostW.x >= 1 || scPostW.y >= 1);
|
if (!outsideShadowMap) {
|
||||||
if (!outsideShadowMap) {
|
shadowFactor = chebyshevUpperBound(scPostW.z, scPostW);
|
||||||
shadowFactor = chebyshevUpperBound(scPostW.z, scPostW);
|
}
|
||||||
}
|
#endif
|
||||||
#endif
|
|
||||||
|
vec4 diffColor = vec4(1,1,1,1);
|
||||||
vec4 diffColor = vec4(1,1,1,1);
|
#if VSMCUBE
|
||||||
#if VSMCUBE
|
if(doTexture != 0) diffColor = vec4(vec3(texture(shadowMap, -fragmentToLight_world.xyz).r), 1.0);
|
||||||
if(doTexture != 0) diffColor = vec4(vec3(texture(shadowMap, -fragmentToLight_world.xyz).r), 1.0);
|
#else
|
||||||
#else
|
if(doTexture != 0) diffColor = vec4(vec3(texture(shadowMap, vec2(uv.x, 1.0 - uv.y)).r), 1.0);
|
||||||
if(doTexture != 0) diffColor = vec4(vec3(texture(shadowMap, vec2(uv.x, 1.0 - uv.y)).r), 1.0);
|
#endif
|
||||||
#endif
|
|
||||||
|
#if 1
|
||||||
#if 1
|
vec3 positionToLight = light - fragment;
|
||||||
vec3 positionToLight = light - fragment;
|
vec3 lightDir = normalize(positionToLight);
|
||||||
vec3 lightDir = normalize(positionToLight);
|
|
||||||
|
// Angle between fragment-normal and incoming light
|
||||||
// Angle between fragment-normal and incoming light
|
float cosAngIncidence = dot(lightDir, normal);
|
||||||
float cosAngIncidence = dot(lightDir, normal);
|
cosAngIncidence = clamp(cosAngIncidence, 0, 1);
|
||||||
cosAngIncidence = clamp(cosAngIncidence, 0, 1);
|
|
||||||
|
float attenuation = 1.0f;
|
||||||
float attenuation = 1.0f;
|
attenuation = 1.0 / (light0.constantAttenuation + light0.linearAttenuation * length(positionToLight) + light0.quadraticAttenuation * pow(length(positionToLight),2));
|
||||||
attenuation = 1.0 / (light0.constantAttenuation + light0.linearAttenuation * length(positionToLight) + light0.quadraticAttenuation * pow(length(positionToLight),2));
|
|
||||||
|
vec4 diffuse = diffColor * light0.diffuse * cosAngIncidence * attenuation;
|
||||||
vec4 diffuse = diffColor * light0.diffuse * cosAngIncidence * attenuation;
|
|
||||||
|
vec4 total_lighting;
|
||||||
vec4 total_lighting;
|
total_lighting += vec4(0.1, 0.1, 0.1, 1.0) * diffColor; // Ambient
|
||||||
total_lighting += vec4(0.1, 0.1, 0.1, 1.0) * diffColor; // Ambient
|
total_lighting += diffuse * shadowFactor; // Diffuse
|
||||||
total_lighting += diffuse * shadowFactor; // Diffuse
|
#else
|
||||||
#else
|
vec4 total_lighting = diffColor;
|
||||||
vec4 total_lighting = diffColor;
|
#endif
|
||||||
#endif
|
return vec4(clamp(vec3(total_lighting), 0., 1.), 1.0);
|
||||||
return vec4(clamp(vec3(total_lighting), 0., 1.), 1.0);
|
#endif
|
||||||
#endif
|
}
|
||||||
}
|
|
|
@ -5,4 +5,4 @@ uniform sampler2D shadowMap;
|
||||||
|
|
||||||
vec4 shadowmap(in vec4 vpeye, in vec4 vneye, in vec2 Texcoord, in vec4 sc) {
|
vec4 shadowmap(in vec4 vpeye, in vec4 vneye, in vec2 Texcoord, in vec4 sc) {
|
||||||
return vec4(1.);
|
return vec4(1.);
|
||||||
};
|
};
|
|
@ -1,4 +1,3 @@
|
||||||
//uniform mat4 u_model, u_view, u_proj;
|
|
||||||
uniform mat4 u_mvp;
|
uniform mat4 u_mvp;
|
||||||
|
|
||||||
in vec3 att_position;
|
in vec3 att_position;
|
||||||
|
@ -23,7 +22,6 @@ void do_shadow() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
// gl_Position = proj * view * model * vec4(att_position, 1.0);
|
|
||||||
gl_Position = u_mvp * vec4(att_position, 1.0);
|
gl_Position = u_mvp * vec4(att_position, 1.0);
|
||||||
v_normal = normalize(att_normal);
|
v_normal = normalize(att_normal);
|
||||||
v_normal_ws = normalize(vec3(model * vec4(att_normal, 0.))); // normal world/model space
|
v_normal_ws = normalize(vec3(model * vec4(att_normal, 0.))); // normal world/model space
|
||||||
|
|
|
@ -2399,14 +2399,104 @@ skybox_t skybox(const char *asset, int flags) {
|
||||||
|
|
||||||
return sky;
|
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) {
|
int skybox_push_state(skybox_t *sky, mat44 proj, mat44 view) {
|
||||||
last_cubemap = &sky->cubemap;
|
last_cubemap = &sky->cubemap;
|
||||||
|
|
||||||
//glClear(GL_DEPTH_BUFFER_BIT);
|
//glClear(GL_DEPTH_BUFFER_BIT);
|
||||||
//glEnable(GL_DEPTH_TEST);
|
//glEnable(GL_DEPTH_TEST);
|
||||||
glDepthFunc(GL_LEQUAL);
|
glDepthFunc(GL_LEQUAL);
|
||||||
//glDisable(GL_CULL_FACE);
|
//glDisable(GL_CULL_FACE);
|
||||||
glDisable(GL_DEPTH_TEST);
|
glDisable(GL_DEPTH_TEST);
|
||||||
|
|
||||||
mat44 mvp; multiply44x2(mvp, proj, view);
|
mat44 mvp; multiply44x2(mvp, proj, view);
|
||||||
|
|
||||||
|
@ -2414,7 +2504,7 @@ glDisable(GL_DEPTH_TEST);
|
||||||
shader_bind(sky->program);
|
shader_bind(sky->program);
|
||||||
shader_mat44("u_mvp", mvp);
|
shader_mat44("u_mvp", mvp);
|
||||||
if( sky->flags ) {
|
if( sky->flags ) {
|
||||||
shader_cubemap("u_cubemap", sky->cubemap.id);
|
shader_cubemap("u_cubemap", sky->cubemap.id);
|
||||||
}
|
}
|
||||||
return 0; // @fixme: return sortable hash here?
|
return 0; // @fixme: return sortable hash here?
|
||||||
}
|
}
|
||||||
|
@ -2434,6 +2524,12 @@ void skybox_destroy(skybox_t *sky) {
|
||||||
glDeleteProgram(sky->program);
|
glDeleteProgram(sky->program);
|
||||||
cubemap_destroy(&sky->cubemap);
|
cubemap_destroy(&sky->cubemap);
|
||||||
mesh_destroy(&sky->geometry);
|
mesh_destroy(&sky->geometry);
|
||||||
|
|
||||||
|
if (sky->pixels) {
|
||||||
|
FREE(sky->pixels);
|
||||||
|
glDeleteFramebuffers(6, sky->framebuffers);
|
||||||
|
glDeleteTextures(6, sky->textures);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
|
|
@ -612,11 +612,17 @@ typedef struct skybox_t {
|
||||||
mesh_t geometry;
|
mesh_t geometry;
|
||||||
cubemap_t cubemap;
|
cubemap_t cubemap;
|
||||||
int flags;
|
int flags;
|
||||||
|
|
||||||
|
// mie
|
||||||
|
unsigned framebuffers;
|
||||||
|
unsigned textures;
|
||||||
|
unsigned char *pixels;
|
||||||
} skybox_t;
|
} skybox_t;
|
||||||
|
|
||||||
API skybox_t skybox(const char *panorama_or_cubemap_folder, int flags);
|
API skybox_t skybox(const char *panorama_or_cubemap_folder, int flags);
|
||||||
API int skybox_render(skybox_t *sky, mat44 proj, mat44 view);
|
API int skybox_render(skybox_t *sky, mat44 proj, mat44 view);
|
||||||
API void skybox_destroy(skybox_t *sky);
|
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_push_state(skybox_t *sky, mat44 proj, mat44 view); // @to deprecate
|
||||||
API int skybox_pop_state(); // @to deprecate
|
API int skybox_pop_state(); // @to deprecate
|
||||||
|
|
|
@ -13,102 +13,102 @@ const char *const fs_0_0_shadowmap_lit = "//" FILELINE "\n"
|
||||||
" vec4 diffuse;\n"
|
" vec4 diffuse;\n"
|
||||||
" vec4 specular;\n"
|
" vec4 specular;\n"
|
||||||
" float constantAttenuation, linearAttenuation, quadraticAttenuation;\n"
|
" float constantAttenuation, linearAttenuation, quadraticAttenuation;\n"
|
||||||
" };\n"
|
"};\n"
|
||||||
" light light0 = light(\n"
|
" \n"
|
||||||
|
"light light0 = light(\n"
|
||||||
" lightPos,\n"
|
" lightPos,\n"
|
||||||
" vec4(1,1,1,1), // diffuse\n"
|
" vec4(1,1,1,1), // diffuse\n"
|
||||||
" vec4(1,1,1,1), // specular\n"
|
" vec4(1,1,1,1), // specular\n"
|
||||||
" 1.0, 0.0, 0.0 // attenuation (const, linear, quad)\n"
|
" 1.0, 0.0, 0.0 // attenuation (const, linear, quad)\n"
|
||||||
" );\n"
|
");\n"
|
||||||
" \n"
|
" \n"
|
||||||
" // From http://fabiensanglard.net/shadowmappingVSM/index.php\n"
|
"// From http://fabiensanglard.net/shadowmappingVSM/index.php\n"
|
||||||
#if VSMCUBE
|
#if VSMCUBE
|
||||||
" float chebyshevUpperBound(float distance, vec3 dir) {\n"
|
"float chebyshevUpperBound(float distance, vec3 dir) {\n"
|
||||||
" distance = distance/20 ;\n"
|
" distance = distance/20 ;\n"
|
||||||
" vec2 moments = texture(shadowMap, dir).rg;\n"
|
" vec2 moments = texture(shadowMap, dir).rg;\n"
|
||||||
#else
|
#else
|
||||||
" float chebyshevUpperBound(float distance, vec4 scPostW) {\n"
|
"float chebyshevUpperBound(float distance, vec4 scPostW) {\n"
|
||||||
" vec2 moments = texture(shadowMap,scPostW.xy).rg;\n"
|
" vec2 moments = texture(shadowMap,scPostW.xy).rg;\n"
|
||||||
#endif
|
#endif
|
||||||
" // Surface is fully lit. as the current fragment is before the light occluder\n"
|
" // Surface is fully lit. as the current fragment is before the light occluder\n"
|
||||||
" if (distance <= moments.x)\n"
|
" if (distance <= moments.x)\n"
|
||||||
" return 1.0;\n"
|
" return 1.0;\n"
|
||||||
" \n"
|
" \n"
|
||||||
" // The fragment is either in shadow or penumbra. We now use chebyshev's upperBound to check\n"
|
" // The fragment is either in shadow or penumbra. We now use chebyshev's upperBound to check\n"
|
||||||
" // How likely this pixel is to be lit (p_max)\n"
|
" // How likely this pixel is to be lit (p_max)\n"
|
||||||
" float variance = moments.y - (moments.x*moments.x);\n"
|
" float variance = moments.y - (moments.x*moments.x);\n"
|
||||||
" //variance = max(variance, 0.000002);\n"
|
" //variance = max(variance, 0.000002);\n"
|
||||||
" variance = max(variance, 0.00002);\n"
|
" variance = max(variance, 0.00002);\n"
|
||||||
" \n"
|
" \n"
|
||||||
" float d = distance - moments.x;\n"
|
" float d = distance - moments.x;\n"
|
||||||
" float p_max = variance / (variance + d*d);\n"
|
" float p_max = variance / (variance + d*d);\n"
|
||||||
" \n"
|
" \n"
|
||||||
" return p_max;\n"
|
" return p_max;\n"
|
||||||
" }\n"
|
"}\n"
|
||||||
" \n"
|
"\n"
|
||||||
" vec4 shadowmap(in vec4 vpeye, in vec4 vneye, in vec2 uv, in vec4 sc) {\n"
|
"vec4 shadowmap(in vec4 vpeye, in vec4 vneye, in vec2 uv, in vec4 sc) {\n"
|
||||||
#ifndef VSMCUBE
|
#ifndef VSMCUBE
|
||||||
" return vec4(1.);\n"
|
" return vec4(1.);\n"
|
||||||
#else
|
#else
|
||||||
" \n"
|
" vec3 fragment = vec3(vpeye);\n"
|
||||||
" vec3 fragment = vec3(vpeye);\n"
|
" vec3 normal = vec3(normalize(vneye));\n"
|
||||||
" vec3 normal = vec3(normalize(vneye));\n"
|
" vec3 viewDir = normalize(-fragment);\n"
|
||||||
" vec3 viewDir = normalize(-fragment);\n"
|
" \n"
|
||||||
" \n"
|
" // Lighting\n"
|
||||||
" // Lighting\n"
|
" // Convert to eye-space\n"
|
||||||
" // Convert to eye-space\n"
|
" vec3 light = vec3(view * vec4(light0.position, 1.0));\n"
|
||||||
" vec3 light = vec3(view * vec4(light0.position, 1.0));\n"
|
" \n"
|
||||||
" \n"
|
#if VSMCUBE
|
||||||
#if VSMCUBE
|
" // Vectors\n"
|
||||||
" // Vectors\n"
|
" vec3 fragmentToLight = light - fragment;\n"
|
||||||
" vec3 fragmentToLight = light - fragment;\n"
|
" vec3 fragmentToLightDir = normalize(fragmentToLight);\n"
|
||||||
" vec3 fragmentToLightDir = normalize(fragmentToLight);\n"
|
" \n"
|
||||||
" \n"
|
" // Shadows\n"
|
||||||
" // Shadows\n"
|
" vec4 fragmentToLight_world = inverse(view) * vec4(fragmentToLightDir, 0.0);\n"
|
||||||
" vec4 fragmentToLight_world = inverse(view) * vec4(fragmentToLightDir, 0.0);\n"
|
" float shadowFactor = chebyshevUpperBound(length(fragmentToLight), -fragmentToLight_world.xyz);\n"
|
||||||
" float shadowFactor = chebyshevUpperBound(length(fragmentToLight), -fragmentToLight_world.xyz);\n"
|
#else
|
||||||
#else
|
" // Shadows\n"
|
||||||
" // Shadows\n"
|
" vec4 scPostW = sc / sc.w;\n"
|
||||||
" vec4 scPostW = sc / sc.w;\n"
|
" scPostW = scPostW * 0.5 + 0.5;\n"
|
||||||
" scPostW = scPostW * 0.5 + 0.5;\n"
|
" \n"
|
||||||
" \n"
|
" float shadowFactor = 1.0; // Not in shadow\n"
|
||||||
" float shadowFactor = 1.0; // Not in shadow\n"
|
" \n"
|
||||||
" \n"
|
" bool outsideShadowMap = sc.w <= 0.0f || (scPostW.x < 0 || scPostW.y < 0) || (scPostW.x >= 1 || scPostW.y >= 1);\n"
|
||||||
" bool outsideShadowMap = sc.w <= 0.0f || (scPostW.x < 0 || scPostW.y < 0) || (scPostW.x >= 1 || scPostW.y >= 1);\n"
|
" if (!outsideShadowMap) {\n"
|
||||||
" if (!outsideShadowMap) {\n"
|
" shadowFactor = chebyshevUpperBound(scPostW.z, scPostW);\n"
|
||||||
" shadowFactor = chebyshevUpperBound(scPostW.z, scPostW);\n"
|
" }\n"
|
||||||
" }\n"
|
#endif
|
||||||
#endif
|
" \n"
|
||||||
" \n"
|
" vec4 diffColor = vec4(1,1,1,1);\n"
|
||||||
" vec4 diffColor = vec4(1,1,1,1);\n"
|
#if VSMCUBE
|
||||||
#if VSMCUBE
|
" if(doTexture != 0) diffColor = vec4(vec3(texture(shadowMap, -fragmentToLight_world.xyz).r), 1.0);\n"
|
||||||
" if(doTexture != 0) diffColor = vec4(vec3(texture(shadowMap, -fragmentToLight_world.xyz).r), 1.0);\n"
|
#else
|
||||||
#else
|
" if(doTexture != 0) diffColor = vec4(vec3(texture(shadowMap, vec2(uv.x, 1.0 - uv.y)).r), 1.0);\n"
|
||||||
" if(doTexture != 0) diffColor = vec4(vec3(texture(shadowMap, vec2(uv.x, 1.0 - uv.y)).r), 1.0);\n"
|
#endif
|
||||||
#endif
|
" \n"
|
||||||
" \n"
|
#if 1
|
||||||
#if 1
|
" vec3 positionToLight = light - fragment;\n"
|
||||||
" vec3 positionToLight = light - fragment;\n"
|
" vec3 lightDir = normalize(positionToLight);\n"
|
||||||
" vec3 lightDir = normalize(positionToLight);\n"
|
" \n"
|
||||||
" \n"
|
" // Angle between fragment-normal and incoming light\n"
|
||||||
" // Angle between fragment-normal and incoming light\n"
|
" float cosAngIncidence = dot(lightDir, normal);\n"
|
||||||
" float cosAngIncidence = dot(lightDir, normal);\n"
|
" cosAngIncidence = clamp(cosAngIncidence, 0, 1);\n"
|
||||||
" cosAngIncidence = clamp(cosAngIncidence, 0, 1);\n"
|
" \n"
|
||||||
" \n"
|
" float attenuation = 1.0f;\n"
|
||||||
" float attenuation = 1.0f;\n"
|
" attenuation = 1.0 / (light0.constantAttenuation + light0.linearAttenuation * length(positionToLight) + light0.quadraticAttenuation * pow(length(positionToLight),2));\n"
|
||||||
" attenuation = 1.0 / (light0.constantAttenuation + light0.linearAttenuation * length(positionToLight) + light0.quadraticAttenuation * pow(length(positionToLight),2));\n"
|
" \n"
|
||||||
" \n"
|
" vec4 diffuse = diffColor * light0.diffuse * cosAngIncidence * attenuation;\n"
|
||||||
" vec4 diffuse = diffColor * light0.diffuse * cosAngIncidence * attenuation;\n"
|
" \n"
|
||||||
" \n"
|
" vec4 total_lighting;\n"
|
||||||
" vec4 total_lighting;\n"
|
" total_lighting += vec4(0.1, 0.1, 0.1, 1.0) * diffColor; // Ambient\n"
|
||||||
" total_lighting += vec4(0.1, 0.1, 0.1, 1.0) * diffColor; // Ambient\n"
|
" total_lighting += diffuse * shadowFactor; // Diffuse\n"
|
||||||
" total_lighting += diffuse * shadowFactor; // Diffuse\n"
|
#else
|
||||||
#else
|
" vec4 total_lighting = diffColor;\n"
|
||||||
" vec4 total_lighting = diffColor;\n"
|
#endif
|
||||||
#endif
|
" return vec4(clamp(vec3(total_lighting), 0., 1.), 1.0);\n"
|
||||||
" return vec4(clamp(vec3(total_lighting), 0., 1.), 1.0);\n"
|
#endif
|
||||||
#endif
|
"}\n";
|
||||||
" }\n";
|
|
||||||
|
|
||||||
const char *const fs_0_0_shadowmap_unlit = "//" FILELINE "\n"
|
const char *const fs_0_0_shadowmap_unlit = "//" FILELINE "\n"
|
||||||
"// uniform mat4 view = mat4(1.0);\n"
|
"// uniform mat4 view = mat4(1.0);\n"
|
||||||
|
@ -118,7 +118,7 @@ const char *const fs_0_0_shadowmap_unlit = "//" FILELINE "\n"
|
||||||
"\n"
|
"\n"
|
||||||
"vec4 shadowmap(in vec4 vpeye, in vec4 vneye, in vec2 Texcoord, in vec4 sc) {\n"
|
"vec4 shadowmap(in vec4 vpeye, in vec4 vneye, in vec2 Texcoord, in vec4 sc) {\n"
|
||||||
" return vec4(1.);\n"
|
" return vec4(1.);\n"
|
||||||
" };\n";
|
"};\n";
|
||||||
|
|
||||||
const char *const fs_24_4_sprite = "//" FILELINE "\n"
|
const char *const fs_24_4_sprite = "//" FILELINE "\n"
|
||||||
"uniform sampler2D u_texture;\n"
|
"uniform sampler2D u_texture;\n"
|
||||||
|
@ -648,7 +648,6 @@ const char *const vs_324_24_sprite = "//" FILELINE "\n"
|
||||||
"}\n";
|
"}\n";
|
||||||
|
|
||||||
const char *const vs_332_32 = "//" FILELINE "\n"
|
const char *const vs_332_32 = "//" FILELINE "\n"
|
||||||
"//uniform mat4 u_model, u_view, u_proj;\n"
|
|
||||||
"uniform mat4 u_mvp;\n"
|
"uniform mat4 u_mvp;\n"
|
||||||
"\n"
|
"\n"
|
||||||
"in vec3 att_position;\n"
|
"in vec3 att_position;\n"
|
||||||
|
@ -673,7 +672,6 @@ const char *const vs_332_32 = "//" FILELINE "\n"
|
||||||
"}\n"
|
"}\n"
|
||||||
"\n"
|
"\n"
|
||||||
"void main() {\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"
|
" gl_Position = u_mvp * vec4(att_position, 1.0);\n"
|
||||||
" v_normal = normalize(att_normal);\n"
|
" v_normal = normalize(att_normal);\n"
|
||||||
" v_normal_ws = normalize(vec3(model * vec4(att_normal, 0.))); // normal world/model space\n"
|
" v_normal_ws = normalize(vec3(model * vec4(att_normal, 0.))); // normal world/model space\n"
|
||||||
|
|
294
engine/v4k.c
294
engine/v4k.c
|
@ -10225,102 +10225,102 @@ const char *const fs_0_0_shadowmap_lit = "//" FILELINE "\n"
|
||||||
" vec4 diffuse;\n"
|
" vec4 diffuse;\n"
|
||||||
" vec4 specular;\n"
|
" vec4 specular;\n"
|
||||||
" float constantAttenuation, linearAttenuation, quadraticAttenuation;\n"
|
" float constantAttenuation, linearAttenuation, quadraticAttenuation;\n"
|
||||||
" };\n"
|
"};\n"
|
||||||
" light light0 = light(\n"
|
" \n"
|
||||||
|
"light light0 = light(\n"
|
||||||
" lightPos,\n"
|
" lightPos,\n"
|
||||||
" vec4(1,1,1,1), // diffuse\n"
|
" vec4(1,1,1,1), // diffuse\n"
|
||||||
" vec4(1,1,1,1), // specular\n"
|
" vec4(1,1,1,1), // specular\n"
|
||||||
" 1.0, 0.0, 0.0 // attenuation (const, linear, quad)\n"
|
" 1.0, 0.0, 0.0 // attenuation (const, linear, quad)\n"
|
||||||
" );\n"
|
");\n"
|
||||||
" \n"
|
" \n"
|
||||||
" // From http://fabiensanglard.net/shadowmappingVSM/index.php\n"
|
"// From http://fabiensanglard.net/shadowmappingVSM/index.php\n"
|
||||||
#if VSMCUBE
|
#if VSMCUBE
|
||||||
" float chebyshevUpperBound(float distance, vec3 dir) {\n"
|
"float chebyshevUpperBound(float distance, vec3 dir) {\n"
|
||||||
" distance = distance/20 ;\n"
|
" distance = distance/20 ;\n"
|
||||||
" vec2 moments = texture(shadowMap, dir).rg;\n"
|
" vec2 moments = texture(shadowMap, dir).rg;\n"
|
||||||
#else
|
#else
|
||||||
" float chebyshevUpperBound(float distance, vec4 scPostW) {\n"
|
"float chebyshevUpperBound(float distance, vec4 scPostW) {\n"
|
||||||
" vec2 moments = texture(shadowMap,scPostW.xy).rg;\n"
|
" vec2 moments = texture(shadowMap,scPostW.xy).rg;\n"
|
||||||
#endif
|
#endif
|
||||||
" // Surface is fully lit. as the current fragment is before the light occluder\n"
|
" // Surface is fully lit. as the current fragment is before the light occluder\n"
|
||||||
" if (distance <= moments.x)\n"
|
" if (distance <= moments.x)\n"
|
||||||
" return 1.0;\n"
|
" return 1.0;\n"
|
||||||
" \n"
|
" \n"
|
||||||
" // The fragment is either in shadow or penumbra. We now use chebyshev's upperBound to check\n"
|
" // The fragment is either in shadow or penumbra. We now use chebyshev's upperBound to check\n"
|
||||||
" // How likely this pixel is to be lit (p_max)\n"
|
" // How likely this pixel is to be lit (p_max)\n"
|
||||||
" float variance = moments.y - (moments.x*moments.x);\n"
|
" float variance = moments.y - (moments.x*moments.x);\n"
|
||||||
" //variance = max(variance, 0.000002);\n"
|
" //variance = max(variance, 0.000002);\n"
|
||||||
" variance = max(variance, 0.00002);\n"
|
" variance = max(variance, 0.00002);\n"
|
||||||
" \n"
|
" \n"
|
||||||
" float d = distance - moments.x;\n"
|
" float d = distance - moments.x;\n"
|
||||||
" float p_max = variance / (variance + d*d);\n"
|
" float p_max = variance / (variance + d*d);\n"
|
||||||
" \n"
|
" \n"
|
||||||
" return p_max;\n"
|
" return p_max;\n"
|
||||||
" }\n"
|
"}\n"
|
||||||
" \n"
|
"\n"
|
||||||
" vec4 shadowmap(in vec4 vpeye, in vec4 vneye, in vec2 uv, in vec4 sc) {\n"
|
"vec4 shadowmap(in vec4 vpeye, in vec4 vneye, in vec2 uv, in vec4 sc) {\n"
|
||||||
#ifndef VSMCUBE
|
#ifndef VSMCUBE
|
||||||
" return vec4(1.);\n"
|
" return vec4(1.);\n"
|
||||||
#else
|
#else
|
||||||
" \n"
|
" vec3 fragment = vec3(vpeye);\n"
|
||||||
" vec3 fragment = vec3(vpeye);\n"
|
" vec3 normal = vec3(normalize(vneye));\n"
|
||||||
" vec3 normal = vec3(normalize(vneye));\n"
|
" vec3 viewDir = normalize(-fragment);\n"
|
||||||
" vec3 viewDir = normalize(-fragment);\n"
|
" \n"
|
||||||
" \n"
|
" // Lighting\n"
|
||||||
" // Lighting\n"
|
" // Convert to eye-space\n"
|
||||||
" // Convert to eye-space\n"
|
" vec3 light = vec3(view * vec4(light0.position, 1.0));\n"
|
||||||
" vec3 light = vec3(view * vec4(light0.position, 1.0));\n"
|
" \n"
|
||||||
" \n"
|
#if VSMCUBE
|
||||||
#if VSMCUBE
|
" // Vectors\n"
|
||||||
" // Vectors\n"
|
" vec3 fragmentToLight = light - fragment;\n"
|
||||||
" vec3 fragmentToLight = light - fragment;\n"
|
" vec3 fragmentToLightDir = normalize(fragmentToLight);\n"
|
||||||
" vec3 fragmentToLightDir = normalize(fragmentToLight);\n"
|
" \n"
|
||||||
" \n"
|
" // Shadows\n"
|
||||||
" // Shadows\n"
|
" vec4 fragmentToLight_world = inverse(view) * vec4(fragmentToLightDir, 0.0);\n"
|
||||||
" vec4 fragmentToLight_world = inverse(view) * vec4(fragmentToLightDir, 0.0);\n"
|
" float shadowFactor = chebyshevUpperBound(length(fragmentToLight), -fragmentToLight_world.xyz);\n"
|
||||||
" float shadowFactor = chebyshevUpperBound(length(fragmentToLight), -fragmentToLight_world.xyz);\n"
|
#else
|
||||||
#else
|
" // Shadows\n"
|
||||||
" // Shadows\n"
|
" vec4 scPostW = sc / sc.w;\n"
|
||||||
" vec4 scPostW = sc / sc.w;\n"
|
" scPostW = scPostW * 0.5 + 0.5;\n"
|
||||||
" scPostW = scPostW * 0.5 + 0.5;\n"
|
" \n"
|
||||||
" \n"
|
" float shadowFactor = 1.0; // Not in shadow\n"
|
||||||
" float shadowFactor = 1.0; // Not in shadow\n"
|
" \n"
|
||||||
" \n"
|
" bool outsideShadowMap = sc.w <= 0.0f || (scPostW.x < 0 || scPostW.y < 0) || (scPostW.x >= 1 || scPostW.y >= 1);\n"
|
||||||
" bool outsideShadowMap = sc.w <= 0.0f || (scPostW.x < 0 || scPostW.y < 0) || (scPostW.x >= 1 || scPostW.y >= 1);\n"
|
" if (!outsideShadowMap) {\n"
|
||||||
" if (!outsideShadowMap) {\n"
|
" shadowFactor = chebyshevUpperBound(scPostW.z, scPostW);\n"
|
||||||
" shadowFactor = chebyshevUpperBound(scPostW.z, scPostW);\n"
|
" }\n"
|
||||||
" }\n"
|
#endif
|
||||||
#endif
|
" \n"
|
||||||
" \n"
|
" vec4 diffColor = vec4(1,1,1,1);\n"
|
||||||
" vec4 diffColor = vec4(1,1,1,1);\n"
|
#if VSMCUBE
|
||||||
#if VSMCUBE
|
" if(doTexture != 0) diffColor = vec4(vec3(texture(shadowMap, -fragmentToLight_world.xyz).r), 1.0);\n"
|
||||||
" if(doTexture != 0) diffColor = vec4(vec3(texture(shadowMap, -fragmentToLight_world.xyz).r), 1.0);\n"
|
#else
|
||||||
#else
|
" if(doTexture != 0) diffColor = vec4(vec3(texture(shadowMap, vec2(uv.x, 1.0 - uv.y)).r), 1.0);\n"
|
||||||
" if(doTexture != 0) diffColor = vec4(vec3(texture(shadowMap, vec2(uv.x, 1.0 - uv.y)).r), 1.0);\n"
|
#endif
|
||||||
#endif
|
" \n"
|
||||||
" \n"
|
#if 1
|
||||||
#if 1
|
" vec3 positionToLight = light - fragment;\n"
|
||||||
" vec3 positionToLight = light - fragment;\n"
|
" vec3 lightDir = normalize(positionToLight);\n"
|
||||||
" vec3 lightDir = normalize(positionToLight);\n"
|
" \n"
|
||||||
" \n"
|
" // Angle between fragment-normal and incoming light\n"
|
||||||
" // Angle between fragment-normal and incoming light\n"
|
" float cosAngIncidence = dot(lightDir, normal);\n"
|
||||||
" float cosAngIncidence = dot(lightDir, normal);\n"
|
" cosAngIncidence = clamp(cosAngIncidence, 0, 1);\n"
|
||||||
" cosAngIncidence = clamp(cosAngIncidence, 0, 1);\n"
|
" \n"
|
||||||
" \n"
|
" float attenuation = 1.0f;\n"
|
||||||
" float attenuation = 1.0f;\n"
|
" attenuation = 1.0 / (light0.constantAttenuation + light0.linearAttenuation * length(positionToLight) + light0.quadraticAttenuation * pow(length(positionToLight),2));\n"
|
||||||
" attenuation = 1.0 / (light0.constantAttenuation + light0.linearAttenuation * length(positionToLight) + light0.quadraticAttenuation * pow(length(positionToLight),2));\n"
|
" \n"
|
||||||
" \n"
|
" vec4 diffuse = diffColor * light0.diffuse * cosAngIncidence * attenuation;\n"
|
||||||
" vec4 diffuse = diffColor * light0.diffuse * cosAngIncidence * attenuation;\n"
|
" \n"
|
||||||
" \n"
|
" vec4 total_lighting;\n"
|
||||||
" vec4 total_lighting;\n"
|
" total_lighting += vec4(0.1, 0.1, 0.1, 1.0) * diffColor; // Ambient\n"
|
||||||
" total_lighting += vec4(0.1, 0.1, 0.1, 1.0) * diffColor; // Ambient\n"
|
" total_lighting += diffuse * shadowFactor; // Diffuse\n"
|
||||||
" total_lighting += diffuse * shadowFactor; // Diffuse\n"
|
#else
|
||||||
#else
|
" vec4 total_lighting = diffColor;\n"
|
||||||
" vec4 total_lighting = diffColor;\n"
|
#endif
|
||||||
#endif
|
" return vec4(clamp(vec3(total_lighting), 0., 1.), 1.0);\n"
|
||||||
" return vec4(clamp(vec3(total_lighting), 0., 1.), 1.0);\n"
|
#endif
|
||||||
#endif
|
"}\n";
|
||||||
" }\n";
|
|
||||||
|
|
||||||
const char *const fs_0_0_shadowmap_unlit = "//" FILELINE "\n"
|
const char *const fs_0_0_shadowmap_unlit = "//" FILELINE "\n"
|
||||||
"// uniform mat4 view = mat4(1.0);\n"
|
"// uniform mat4 view = mat4(1.0);\n"
|
||||||
|
@ -10330,7 +10330,7 @@ const char *const fs_0_0_shadowmap_unlit = "//" FILELINE "\n"
|
||||||
"\n"
|
"\n"
|
||||||
"vec4 shadowmap(in vec4 vpeye, in vec4 vneye, in vec2 Texcoord, in vec4 sc) {\n"
|
"vec4 shadowmap(in vec4 vpeye, in vec4 vneye, in vec2 Texcoord, in vec4 sc) {\n"
|
||||||
" return vec4(1.);\n"
|
" return vec4(1.);\n"
|
||||||
" };\n";
|
"};\n";
|
||||||
|
|
||||||
const char *const fs_24_4_sprite = "//" FILELINE "\n"
|
const char *const fs_24_4_sprite = "//" FILELINE "\n"
|
||||||
"uniform sampler2D u_texture;\n"
|
"uniform sampler2D u_texture;\n"
|
||||||
|
@ -10860,7 +10860,6 @@ const char *const vs_324_24_sprite = "//" FILELINE "\n"
|
||||||
"}\n";
|
"}\n";
|
||||||
|
|
||||||
const char *const vs_332_32 = "//" FILELINE "\n"
|
const char *const vs_332_32 = "//" FILELINE "\n"
|
||||||
"//uniform mat4 u_model, u_view, u_proj;\n"
|
|
||||||
"uniform mat4 u_mvp;\n"
|
"uniform mat4 u_mvp;\n"
|
||||||
"\n"
|
"\n"
|
||||||
"in vec3 att_position;\n"
|
"in vec3 att_position;\n"
|
||||||
|
@ -10885,7 +10884,6 @@ const char *const vs_332_32 = "//" FILELINE "\n"
|
||||||
"}\n"
|
"}\n"
|
||||||
"\n"
|
"\n"
|
||||||
"void main() {\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"
|
" gl_Position = u_mvp * vec4(att_position, 1.0);\n"
|
||||||
" v_normal = normalize(att_normal);\n"
|
" v_normal = normalize(att_normal);\n"
|
||||||
" v_normal_ws = normalize(vec3(model * vec4(att_normal, 0.))); // normal world/model space\n"
|
" v_normal_ws = normalize(vec3(model * vec4(att_normal, 0.))); // normal world/model space\n"
|
||||||
|
@ -13310,14 +13308,104 @@ skybox_t skybox(const char *asset, int flags) {
|
||||||
|
|
||||||
return sky;
|
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) {
|
int skybox_push_state(skybox_t *sky, mat44 proj, mat44 view) {
|
||||||
last_cubemap = &sky->cubemap;
|
last_cubemap = &sky->cubemap;
|
||||||
|
|
||||||
//glClear(GL_DEPTH_BUFFER_BIT);
|
//glClear(GL_DEPTH_BUFFER_BIT);
|
||||||
//glEnable(GL_DEPTH_TEST);
|
//glEnable(GL_DEPTH_TEST);
|
||||||
glDepthFunc(GL_LEQUAL);
|
glDepthFunc(GL_LEQUAL);
|
||||||
//glDisable(GL_CULL_FACE);
|
//glDisable(GL_CULL_FACE);
|
||||||
glDisable(GL_DEPTH_TEST);
|
glDisable(GL_DEPTH_TEST);
|
||||||
|
|
||||||
mat44 mvp; multiply44x2(mvp, proj, view);
|
mat44 mvp; multiply44x2(mvp, proj, view);
|
||||||
|
|
||||||
|
@ -13325,7 +13413,7 @@ glDisable(GL_DEPTH_TEST);
|
||||||
shader_bind(sky->program);
|
shader_bind(sky->program);
|
||||||
shader_mat44("u_mvp", mvp);
|
shader_mat44("u_mvp", mvp);
|
||||||
if( sky->flags ) {
|
if( sky->flags ) {
|
||||||
shader_cubemap("u_cubemap", sky->cubemap.id);
|
shader_cubemap("u_cubemap", sky->cubemap.id);
|
||||||
}
|
}
|
||||||
return 0; // @fixme: return sortable hash here?
|
return 0; // @fixme: return sortable hash here?
|
||||||
}
|
}
|
||||||
|
@ -13345,6 +13433,12 @@ void skybox_destroy(skybox_t *sky) {
|
||||||
glDeleteProgram(sky->program);
|
glDeleteProgram(sky->program);
|
||||||
cubemap_destroy(&sky->cubemap);
|
cubemap_destroy(&sky->cubemap);
|
||||||
mesh_destroy(&sky->geometry);
|
mesh_destroy(&sky->geometry);
|
||||||
|
|
||||||
|
if (sky->pixels) {
|
||||||
|
FREE(sky->pixels);
|
||||||
|
glDeleteFramebuffers(6, sky->framebuffers);
|
||||||
|
glDeleteTextures(6, sky->textures);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
|
|
@ -2850,11 +2850,17 @@ typedef struct skybox_t {
|
||||||
mesh_t geometry;
|
mesh_t geometry;
|
||||||
cubemap_t cubemap;
|
cubemap_t cubemap;
|
||||||
int flags;
|
int flags;
|
||||||
|
|
||||||
|
// mie
|
||||||
|
unsigned framebuffers;
|
||||||
|
unsigned textures;
|
||||||
|
unsigned char *pixels;
|
||||||
} skybox_t;
|
} skybox_t;
|
||||||
|
|
||||||
API skybox_t skybox(const char *panorama_or_cubemap_folder, int flags);
|
API skybox_t skybox(const char *panorama_or_cubemap_folder, int flags);
|
||||||
API int skybox_render(skybox_t *sky, mat44 proj, mat44 view);
|
API int skybox_render(skybox_t *sky, mat44 proj, mat44 view);
|
||||||
API void skybox_destroy(skybox_t *sky);
|
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_push_state(skybox_t *sky, mat44 proj, mat44 view); // @to deprecate
|
||||||
API int skybox_pop_state(); // @to deprecate
|
API int skybox_pop_state(); // @to deprecate
|
||||||
|
|
Loading…
Reference in New Issue