diff --git a/demos/09-shadows-scene.c b/demos/09-shadows-scene.c index 6917f0e..21b65f3 100644 --- a/demos/09-shadows-scene.c +++ b/demos/09-shadows-scene.c @@ -7,11 +7,11 @@ const char *skyboxes[][2] = { // reflection, env, metadata + {"hdr/GCanyon_C_YumaPoint_1k.hdr","hdr/GCanyon_C_YumaPoint_Env.hdr"}, {"hdr/Tokyo_BigSight_1k.hdr","hdr/Tokyo_BigSight_Env.hdr"}, {"hdr/graffiti_shelter_4k.hdr","hdr/graffiti_shelter_Env.hdr"}, {"hdr/music_hall_01_4k.hdr","hdr/music_hall_01_Env.hdr"}, {"hdr/the_sky_is_on_fire_2k.hdr","hdr/the_sky_is_on_fire_Env.hdr"}, - {"hdr/GCanyon_C_YumaPoint_1k.hdr","hdr/GCanyon_C_YumaPoint_Env.hdr"}, {"hdr/Factory_Catwalk_1k.hdr","hdr/Factory_Catwalk_Env.hdr"}, {"hdr/MonValley_G_DirtRoad_1k.hdr","hdr/MonValley_G_DirtRoad_Env.hdr"}, {"hdr/Shiodome_Stairs_1k.hdr","hdr/Shiodome_Stairs_Env.hdr"}, @@ -42,6 +42,7 @@ int main() { model_t m3 = model("damagedhelmet.gltf", MODEL_NO_ANIMATIONS|MODEL_PBR); // model_t m3 = model("Scutum_low.fbx", MODEL_NO_ANIMATIONS|MODEL_PBR); model_t m4 = model("cube.obj", MODEL_NO_ANIMATIONS); + model_t m6 = model("ShadowsTest.obj", MODEL_NO_ANIMATIONS); // model_t m4 = model("avp/scene.gltf", MODEL_NO_ANIMATIONS|MODEL_PBR); // model_t m3 = model("Cerberus_LP.FBX", MODEL_NO_ANIMATIONS|MODEL_PBR); @@ -95,12 +96,23 @@ int main() { object_move(obj5, vec3(-10+8*3,0,-10)); object_pivot(obj5, vec3(0,90,0)); + // spawn object6 + object_t* obj6 = scene_spawn(); + object_model(obj6, m6); + object_move(obj6, vec3(-9,-4,3)); + object_scale(obj6, vec3(3,3,3)); + // create point light // scene_spawn_light(); // sun - light_t* l = scene_spawn_light(); - light_type(l, LIGHT_POINT); + // light_t* l = scene_spawn_light(); + // light_type(l, LIGHT_POINT); // l->diffuse = vec3(0,0,0); + light_t* sun = scene_spawn_light(); + light_type(sun, LIGHT_DIRECTIONAL); + sun->dir = vec3(0.5,-1,-0.5); + + // load skybox scene_get_active()->skybox = skybox_pbr(skyboxes[0][0], skyboxes[0][0], skyboxes[0][1]); @@ -113,15 +125,15 @@ int main() { video_decode( v ); // update light position - light_teleport(l, cam.position); + // light_teleport(l, cam.position); // update shadertoy shadertoy_render(&sh, window_delta()); // draw scene - fx_begin(); - scene_render(SCENE_FOREGROUND|SCENE_BACKGROUND|SCENE_UPDATE_SH_COEF); - fx_end(); + // fx_begin(); + scene_render(SCENE_FOREGROUND|SCENE_BACKGROUND|SCENE_UPDATE_SH_COEF|SCENE_CAST_SHADOWS); + // fx_end(); // fps camera bool active = ui_active() || ui_hover() || gizmo_active() ? false : input(MOUSE_L) || input(MOUSE_M) || input(MOUSE_R); diff --git a/engine/joint/v4k.h b/engine/joint/v4k.h index 7cbf6aa..4c16446 100644 --- a/engine/joint/v4k.h +++ b/engine/joint/v4k.h @@ -385605,6 +385605,8 @@ shadertoy_t shadertoy( const char *shaderfile, unsigned flags ) { } shadertoy_t* shadertoy_render(shadertoy_t *s, float delta) { + int saved_vp[4]; + glGetIntegerv(GL_VIEWPORT, saved_vp); if( s->program && s->vao ) { if( s->dims.x && !(s->flags&SHADERTOY_IGNORE_FBO) && !texture_rec_begin(&s->tx, s->dims.x, s->dims.y) ) { return s; @@ -385645,6 +385647,7 @@ shadertoy_t* shadertoy_render(shadertoy_t *s, float delta) { if(s->dims.x && !(s->flags&SHADERTOY_IGNORE_FBO)) texture_rec_end(&s->tx); // texture_rec } + glViewport(saved_vp[0], saved_vp[1], saved_vp[2], saved_vp[3]); return s; } @@ -388969,8 +388972,9 @@ object_t object() { //obj.rot = idq(); obj.sca = vec3(1,1,1); //obj.bounds = aabb(vec3(0,0,0),vec3(1,1,1)); // defaults to small 1-unit cube -object_rotate(&obj, vec3(0,0,0)); + object_rotate(&obj, vec3(0,0,0)); //array_init(obj.textures); + obj.cast_shadows = true; return obj; } @@ -389161,6 +389165,16 @@ int scene_obj_distance_compare(const void *a, const void *b) { void scene_render(int flags) { camera_t *cam = camera_get_active(); + shadowmap_t *sm = &last_scene->shadowmap; + + if (flags & SCENE_CAST_SHADOWS) { + if (sm->vsm_texture_width == 0) { + *sm = shadowmap(512, 4096); + } + } else { + sm = NULL; + } + #if 1 mat44 projview; multiply44x2(projview, cam->proj, cam->view); frustum frustum_state = frustum_build(projview); @@ -389247,6 +389261,26 @@ void scene_render(int flags) { model->rs[p].polygon_mode_draw = flags&SCENE_WIREFRAME ? GL_LINE : GL_FILL; } } + + /* Build shadowmaps */ + if (flags & SCENE_CAST_SHADOWS) { + shadowmap_begin(sm); + for (unsigned j = 0; j < array_count(last_scene->lights); ++j) { + light_t *l = &last_scene->lights[j]; + while (shadowmap_step(sm)) { + shadowmap_light(sm, l, cam->proj, cam->view); + for(unsigned j = 0, obj_count = scene_count(); j < obj_count; ++j ) { + object_t *obj = scene_index(j); + model_t *model = &obj->model; + if (obj->cast_shadows) { + model_render(*model, cam->proj, cam->view, obj->transform, 0); + } + } + } + } + shadowmap_end(sm); + } + /* Collect all transparency enabled models and sort them by distance */ static array(object_t*) transparent_objects = 0; @@ -389270,6 +389304,11 @@ void scene_render(int flags) { model_t *model = &obj->model; if (obj->skip_draw) continue; + if (sm) { + shader_bind(model->program); + light_update(array_count(last_scene->lights), last_scene->lights); + } + model_shadow(model, sm); model_render_pass(*model, cam->proj, cam->view, obj->transform, model->program, RENDER_PASS_OPAQUE); } @@ -389279,6 +389318,11 @@ void scene_render(int flags) { model_t *model = &obj->model; if (obj->skip_draw) continue; + if (sm) { + shader_bind(model->program); + light_update(array_count(last_scene->lights), last_scene->lights); + } + model_shadow(model, sm); model_render_pass(*model, cam->proj, cam->view, obj->transform, model->program, RENDER_PASS_TRANSPARENT); } diff --git a/engine/split/v4k_render.c b/engine/split/v4k_render.c index e3b40ad..a29b7ae 100644 --- a/engine/split/v4k_render.c +++ b/engine/split/v4k_render.c @@ -3868,6 +3868,8 @@ shadertoy_t shadertoy( const char *shaderfile, unsigned flags ) { } shadertoy_t* shadertoy_render(shadertoy_t *s, float delta) { + int saved_vp[4]; + glGetIntegerv(GL_VIEWPORT, saved_vp); if( s->program && s->vao ) { if( s->dims.x && !(s->flags&SHADERTOY_IGNORE_FBO) && !texture_rec_begin(&s->tx, s->dims.x, s->dims.y) ) { return s; @@ -3908,6 +3910,7 @@ shadertoy_t* shadertoy_render(shadertoy_t *s, float delta) { if(s->dims.x && !(s->flags&SHADERTOY_IGNORE_FBO)) texture_rec_end(&s->tx); // texture_rec } + glViewport(saved_vp[0], saved_vp[1], saved_vp[2], saved_vp[3]); return s; } diff --git a/engine/split/v4k_scene.c b/engine/split/v4k_scene.c index 8450439..edc58f1 100644 --- a/engine/split/v4k_scene.c +++ b/engine/split/v4k_scene.c @@ -234,8 +234,9 @@ object_t object() { //obj.rot = idq(); obj.sca = vec3(1,1,1); //obj.bounds = aabb(vec3(0,0,0),vec3(1,1,1)); // defaults to small 1-unit cube -object_rotate(&obj, vec3(0,0,0)); + object_rotate(&obj, vec3(0,0,0)); //array_init(obj.textures); + obj.cast_shadows = true; return obj; } @@ -426,6 +427,16 @@ int scene_obj_distance_compare(const void *a, const void *b) { void scene_render(int flags) { camera_t *cam = camera_get_active(); + shadowmap_t *sm = &last_scene->shadowmap; + + if (flags & SCENE_CAST_SHADOWS) { + if (sm->vsm_texture_width == 0) { + *sm = shadowmap(512, 4096); + } + } else { + sm = NULL; + } + #if 1 mat44 projview; multiply44x2(projview, cam->proj, cam->view); frustum frustum_state = frustum_build(projview); @@ -512,6 +523,26 @@ void scene_render(int flags) { model->rs[p].polygon_mode_draw = flags&SCENE_WIREFRAME ? GL_LINE : GL_FILL; } } + + /* Build shadowmaps */ + if (flags & SCENE_CAST_SHADOWS) { + shadowmap_begin(sm); + for (unsigned j = 0; j < array_count(last_scene->lights); ++j) { + light_t *l = &last_scene->lights[j]; + while (shadowmap_step(sm)) { + shadowmap_light(sm, l, cam->proj, cam->view); + for(unsigned j = 0, obj_count = scene_count(); j < obj_count; ++j ) { + object_t *obj = scene_index(j); + model_t *model = &obj->model; + if (obj->cast_shadows) { + model_render(*model, cam->proj, cam->view, obj->transform, 0); + } + } + } + } + shadowmap_end(sm); + } + /* Collect all transparency enabled models and sort them by distance */ static array(object_t*) transparent_objects = 0; @@ -535,6 +566,11 @@ void scene_render(int flags) { model_t *model = &obj->model; if (obj->skip_draw) continue; + if (sm) { + shader_bind(model->program); + light_update(array_count(last_scene->lights), last_scene->lights); + } + model_shadow(model, sm); model_render_pass(*model, cam->proj, cam->view, obj->transform, model->program, RENDER_PASS_OPAQUE); } @@ -544,6 +580,11 @@ void scene_render(int flags) { model_t *model = &obj->model; if (obj->skip_draw) continue; + if (sm) { + shader_bind(model->program); + light_update(array_count(last_scene->lights), last_scene->lights); + } + model_shadow(model, sm); model_render_pass(*model, cam->proj, cam->view, obj->transform, model->program, RENDER_PASS_TRANSPARENT); } diff --git a/engine/v4k.c b/engine/v4k.c index 6178fbc..da3b04d 100644 --- a/engine/v4k.c +++ b/engine/v4k.c @@ -20667,6 +20667,8 @@ shadertoy_t shadertoy( const char *shaderfile, unsigned flags ) { } shadertoy_t* shadertoy_render(shadertoy_t *s, float delta) { + int saved_vp[4]; + glGetIntegerv(GL_VIEWPORT, saved_vp); if( s->program && s->vao ) { if( s->dims.x && !(s->flags&SHADERTOY_IGNORE_FBO) && !texture_rec_begin(&s->tx, s->dims.x, s->dims.y) ) { return s; @@ -20707,6 +20709,7 @@ shadertoy_t* shadertoy_render(shadertoy_t *s, float delta) { if(s->dims.x && !(s->flags&SHADERTOY_IGNORE_FBO)) texture_rec_end(&s->tx); // texture_rec } + glViewport(saved_vp[0], saved_vp[1], saved_vp[2], saved_vp[3]); return s; } @@ -24031,8 +24034,9 @@ object_t object() { //obj.rot = idq(); obj.sca = vec3(1,1,1); //obj.bounds = aabb(vec3(0,0,0),vec3(1,1,1)); // defaults to small 1-unit cube -object_rotate(&obj, vec3(0,0,0)); + object_rotate(&obj, vec3(0,0,0)); //array_init(obj.textures); + obj.cast_shadows = true; return obj; } @@ -24223,6 +24227,16 @@ int scene_obj_distance_compare(const void *a, const void *b) { void scene_render(int flags) { camera_t *cam = camera_get_active(); + shadowmap_t *sm = &last_scene->shadowmap; + + if (flags & SCENE_CAST_SHADOWS) { + if (sm->vsm_texture_width == 0) { + *sm = shadowmap(512, 4096); + } + } else { + sm = NULL; + } + #if 1 mat44 projview; multiply44x2(projview, cam->proj, cam->view); frustum frustum_state = frustum_build(projview); @@ -24309,6 +24323,26 @@ void scene_render(int flags) { model->rs[p].polygon_mode_draw = flags&SCENE_WIREFRAME ? GL_LINE : GL_FILL; } } + + /* Build shadowmaps */ + if (flags & SCENE_CAST_SHADOWS) { + shadowmap_begin(sm); + for (unsigned j = 0; j < array_count(last_scene->lights); ++j) { + light_t *l = &last_scene->lights[j]; + while (shadowmap_step(sm)) { + shadowmap_light(sm, l, cam->proj, cam->view); + for(unsigned j = 0, obj_count = scene_count(); j < obj_count; ++j ) { + object_t *obj = scene_index(j); + model_t *model = &obj->model; + if (obj->cast_shadows) { + model_render(*model, cam->proj, cam->view, obj->transform, 0); + } + } + } + } + shadowmap_end(sm); + } + /* Collect all transparency enabled models and sort them by distance */ static array(object_t*) transparent_objects = 0; @@ -24332,6 +24366,11 @@ void scene_render(int flags) { model_t *model = &obj->model; if (obj->skip_draw) continue; + if (sm) { + shader_bind(model->program); + light_update(array_count(last_scene->lights), last_scene->lights); + } + model_shadow(model, sm); model_render_pass(*model, cam->proj, cam->view, obj->transform, model->program, RENDER_PASS_OPAQUE); } @@ -24341,6 +24380,11 @@ void scene_render(int flags) { model_t *model = &obj->model; if (obj->skip_draw) continue; + if (sm) { + shader_bind(model->program); + light_update(array_count(last_scene->lights), last_scene->lights); + } + model_shadow(model, sm); model_render_pass(*model, cam->proj, cam->view, obj->transform, model->program, RENDER_PASS_TRANSPARENT); }