diff options
-rw-r--r-- | drivers/gles3/rasterizer_scene_gles3.cpp | 62 | ||||
-rw-r--r-- | drivers/gles3/rasterizer_scene_gles3.h | 5 | ||||
-rw-r--r-- | drivers/gles3/shaders/copy.glsl | 5 | ||||
-rw-r--r-- | scene/3d/scenario_fx.cpp | 35 | ||||
-rw-r--r-- | scene/3d/scenario_fx.h | 4 | ||||
-rw-r--r-- | scene/main/viewport.cpp | 11 | ||||
-rw-r--r-- | servers/visual/rasterizer.h | 4 | ||||
-rw-r--r-- | servers/visual/visual_server_scene.cpp | 12 | ||||
-rw-r--r-- | servers/visual/visual_server_scene.h | 1 | ||||
-rw-r--r-- | servers/visual/visual_server_viewport.cpp | 68 |
10 files changed, 152 insertions, 55 deletions
diff --git a/drivers/gles3/rasterizer_scene_gles3.cpp b/drivers/gles3/rasterizer_scene_gles3.cpp index 913aa62452..96c3da99f0 100644 --- a/drivers/gles3/rasterizer_scene_gles3.cpp +++ b/drivers/gles3/rasterizer_scene_gles3.cpp @@ -977,6 +977,27 @@ void RasterizerSceneGLES3::environment_set_fog_height(RID p_env, bool p_enable, env->fog_height_curve = p_height_curve; } +bool RasterizerSceneGLES3::is_environment(RID p_env) { + + return environment_owner.owns(p_env); +} + +VS::EnvironmentBG RasterizerSceneGLES3::environment_get_background(RID p_env) { + + const Environment *env = environment_owner.getornull(p_env); + ERR_FAIL_COND_V(!env, VS::ENV_BG_MAX); + + return env->bg_mode; +} + +int RasterizerSceneGLES3::environment_get_canvas_max_layer(RID p_env) { + + const Environment *env = environment_owner.getornull(p_env); + ERR_FAIL_COND_V(!env, -1); + + return env->canvas_max_layer; +} + RID RasterizerSceneGLES3::light_instance_create(RID p_light) { LightInstance *light_instance = memnew(LightInstance); @@ -3561,7 +3582,7 @@ void RasterizerSceneGLES3::_post_process(Environment *env, const CameraMatrix &p glUniform2iv(state.exposure_shader.get_uniform(ExposureShaderGLES3::SOURCE_RENDER_SIZE), 1, ss); glUniform2iv(state.exposure_shader.get_uniform(ExposureShaderGLES3::TARGET_SIZE), 1, ds); glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->buffers.diffuse); + glBindTexture(GL_TEXTURE_2D, composite_from); glBindFramebuffer(GL_FRAMEBUFFER, exposure_shrink[0].fbo); glViewport(0, 0, exposure_shrink_size, exposure_shrink_size); @@ -3957,6 +3978,7 @@ void RasterizerSceneGLES3::render_scene(const Transform &p_cam_transform, const use_mrt = use_mrt && !storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_TRANSPARENT]; use_mrt = use_mrt && !storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_NO_3D_EFFECTS]; use_mrt = use_mrt && state.debug_draw != VS::VIEWPORT_DEBUG_DRAW_OVERDRAW; + use_mrt = use_mrt && env && (env->bg_mode != VS::ENV_BG_KEEP && env->bg_mode != VS::ENV_BG_CANVAS); glViewport(0, 0, storage->frame.current_rt->width, storage->frame.current_rt->height); @@ -4020,6 +4042,10 @@ void RasterizerSceneGLES3::render_scene(const Transform &p_cam_transform, const storage->frame.clear_request = false; } + } else if (env->bg_mode == VS::ENV_BG_CANVAS) { + + clear_color = env->bg_color.to_linear(); + storage->frame.clear_request = false; } else if (env->bg_mode == VS::ENV_BG_COLOR) { clear_color = env->bg_color.to_linear(); @@ -4037,7 +4063,39 @@ void RasterizerSceneGLES3::render_scene(const Transform &p_cam_transform, const storage->frame.clear_request = false; } - glClearBufferfv(GL_COLOR, 0, clear_color.components); // specular + if (!env || env->bg_mode != VS::ENV_BG_KEEP) { + glClearBufferfv(GL_COLOR, 0, clear_color.components); // specular + } + + if (env && env->bg_mode == VS::ENV_BG_CANVAS) { + //copy canvas to 3d buffer and convert it to linear + + glDisable(GL_BLEND); + glDepthMask(GL_FALSE); + glDisable(GL_DEPTH_TEST); + glDisable(GL_CULL_FACE); + + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->color); + + storage->shaders.copy.set_conditional(CopyShaderGLES3::DISABLE_ALPHA, true); + + storage->shaders.copy.set_conditional(CopyShaderGLES3::SRGB_TO_LINEAR, true); + + storage->shaders.copy.bind(); + + _copy_screen(); + + //turn off everything used + storage->shaders.copy.set_conditional(CopyShaderGLES3::SRGB_TO_LINEAR, false); + storage->shaders.copy.set_conditional(CopyShaderGLES3::DISABLE_ALPHA, false); + + //restore + glEnable(GL_BLEND); + glDepthMask(GL_TRUE); + glEnable(GL_DEPTH_TEST); + glEnable(GL_CULL_FACE); + } state.texscreen_copied = false; diff --git a/drivers/gles3/rasterizer_scene_gles3.h b/drivers/gles3/rasterizer_scene_gles3.h index 3e15da52ab..c52a00bf17 100644 --- a/drivers/gles3/rasterizer_scene_gles3.h +++ b/drivers/gles3/rasterizer_scene_gles3.h @@ -536,6 +536,11 @@ public: virtual void environment_set_fog_depth(RID p_env, bool p_enable, float p_depth_begin, float p_depth_curve, bool p_transmit, float p_transmit_curve); virtual void environment_set_fog_height(RID p_env, bool p_enable, float p_min_height, float p_max_height, float p_height_curve); + virtual bool is_environment(RID p_env); + + virtual VS::EnvironmentBG environment_get_background(RID p_env); + virtual int environment_get_canvas_max_layer(RID p_env); + /* LIGHT INSTANCE */ struct LightDataUBO { diff --git a/drivers/gles3/shaders/copy.glsl b/drivers/gles3/shaders/copy.glsl index 4c8648903e..b0fb525e20 100644 --- a/drivers/gles3/shaders/copy.glsl +++ b/drivers/gles3/shaders/copy.glsl @@ -129,6 +129,11 @@ void main() { color.rgb = mix( (vec3(1.0)+a)*pow(color.rgb,vec3(1.0/2.4))-a , 12.92*color.rgb , lessThan(color.rgb,vec3(0.0031308))); #endif +#ifdef SRGB_TO_LINEAR + + color.rgb = mix(pow((color.rgb + vec3(0.055)) * (1.0 / (1 + 0.055)),vec3(2.4)),color.rgb * (1.0 / 12.92),lessThan(color.rgb,vec3(0.04045))); +#endif + #ifdef DEBUG_GRADIENT color.rg=uv_interp; color.b=0.0; diff --git a/scene/3d/scenario_fx.cpp b/scene/3d/scenario_fx.cpp index 874c21546d..abc7766ecb 100644 --- a/scene/3d/scenario_fx.cpp +++ b/scene/3d/scenario_fx.cpp @@ -28,43 +28,44 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ #include "scenario_fx.h" +#include "scene/main/viewport.h" void WorldEnvironment::_notification(int p_what) { - if (p_what == NOTIFICATION_ENTER_WORLD) { + if (p_what == Spatial::NOTIFICATION_ENTER_WORLD || p_what == Spatial::NOTIFICATION_ENTER_TREE) { if (environment.is_valid()) { - if (get_world()->get_environment().is_valid()) { + if (get_viewport()->find_world()->get_environment().is_valid()) { WARN_PRINT("World already has an environment (Another WorldEnvironment?), overriding."); } - get_world()->set_environment(environment); - add_to_group("_world_environment_" + itos(get_world()->get_scenario().get_id())); + get_viewport()->find_world()->set_environment(environment); + add_to_group("_world_environment_" + itos(get_viewport()->find_world()->get_scenario().get_id())); } - } else if (p_what == NOTIFICATION_EXIT_WORLD) { + } else if (p_what == Spatial::NOTIFICATION_EXIT_WORLD || p_what == Spatial::NOTIFICATION_EXIT_TREE) { - if (environment.is_valid() && get_world()->get_environment() == environment) { - get_world()->set_environment(Ref<Environment>()); - remove_from_group("_world_environment_" + itos(get_world()->get_scenario().get_id())); + if (environment.is_valid() && get_viewport()->find_world()->get_environment() == environment) { + get_viewport()->find_world()->set_environment(Ref<Environment>()); + remove_from_group("_world_environment_" + itos(get_viewport()->find_world()->get_scenario().get_id())); } } } void WorldEnvironment::set_environment(const Ref<Environment> &p_environment) { - if (is_inside_world() && environment.is_valid() && get_world()->get_environment() == environment) { - get_world()->set_environment(Ref<Environment>()); - remove_from_group("_world_environment_" + itos(get_world()->get_scenario().get_id())); + if (is_inside_tree() && environment.is_valid() && get_viewport()->find_world()->get_environment() == environment) { + get_viewport()->find_world()->set_environment(Ref<Environment>()); + remove_from_group("_world_environment_" + itos(get_viewport()->find_world()->get_scenario().get_id())); //clean up } environment = p_environment; - if (is_inside_world() && environment.is_valid()) { - if (get_world()->get_environment().is_valid()) { + if (is_inside_tree() && environment.is_valid()) { + if (get_viewport()->find_world()->get_environment().is_valid()) { WARN_PRINT("World already has an environment (Another WorldEnvironment?), overriding."); } - get_world()->set_environment(environment); - add_to_group("_world_environment_" + itos(get_world()->get_scenario().get_id())); + get_viewport()->find_world()->set_environment(environment); + add_to_group("_world_environment_" + itos(get_viewport()->find_world()->get_scenario().get_id())); } update_configuration_warning(); @@ -77,11 +78,11 @@ Ref<Environment> WorldEnvironment::get_environment() const { String WorldEnvironment::get_configuration_warning() const { - if (!is_visible_in_tree() || !is_inside_tree() || !environment.is_valid()) + if (/*!is_visible_in_tree() ||*/ !is_inside_tree() || !environment.is_valid()) return String(); List<Node *> nodes; - get_tree()->get_nodes_in_group("_world_environment_" + itos(get_world()->get_scenario().get_id()), &nodes); + get_tree()->get_nodes_in_group("_world_environment_" + itos(get_viewport()->find_world()->get_scenario().get_id()), &nodes); if (nodes.size() > 1) { return TTR("Only one WorldEnvironment is allowed per scene (or set of instanced scenes)."); diff --git a/scene/3d/scenario_fx.h b/scene/3d/scenario_fx.h index b2a4bc5472..d1e0a63130 100644 --- a/scene/3d/scenario_fx.h +++ b/scene/3d/scenario_fx.h @@ -36,9 +36,9 @@ @author Juan Linietsky <reduzio@gmail.com> */ -class WorldEnvironment : public Spatial { +class WorldEnvironment : public Node { - GDCLASS(WorldEnvironment, Spatial); + GDCLASS(WorldEnvironment, Node); Ref<Environment> environment; diff --git a/scene/main/viewport.cpp b/scene/main/viewport.cpp index 714327c5b7..a87c83f17c 100644 --- a/scene/main/viewport.cpp +++ b/scene/main/viewport.cpp @@ -49,6 +49,7 @@ #include "scene/scene_string_names.h" #include "global_config.h" +#include "scene/3d/scenario_fx.h" void ViewportTexture::setup_local_to_scene() { @@ -1017,10 +1018,9 @@ void Viewport::_propagate_enter_world(Node *p_node) { if (!p_node->is_inside_tree()) //may not have entered scene yet return; - Spatial *s = p_node->cast_to<Spatial>(); - if (s) { + if (p_node->cast_to<Spatial>() || p_node->cast_to<WorldEnvironment>()) { - s->notification(Spatial::NOTIFICATION_ENTER_WORLD); + p_node->notification(Spatial::NOTIFICATION_ENTER_WORLD); } else { Viewport *v = p_node->cast_to<Viewport>(); if (v) { @@ -1055,10 +1055,9 @@ void Viewport::_propagate_exit_world(Node *p_node) { if (!p_node->is_inside_tree()) //may have exited scene already return; - Spatial *s = p_node->cast_to<Spatial>(); - if (s) { + if (p_node->cast_to<Spatial>() || p_node->cast_to<WorldEnvironment>()) { - s->notification(Spatial::NOTIFICATION_EXIT_WORLD, true); + p_node->notification(Spatial::NOTIFICATION_EXIT_WORLD); } else { Viewport *v = p_node->cast_to<Viewport>(); if (v) { diff --git a/servers/visual/rasterizer.h b/servers/visual/rasterizer.h index 43452b714c..2ce83e6c64 100644 --- a/servers/visual/rasterizer.h +++ b/servers/visual/rasterizer.h @@ -75,6 +75,10 @@ public: virtual void environment_set_fog_depth(RID p_env, bool p_enable, float p_depth_begin, float p_depth_curve, bool p_transmit, float p_transmit_curve) = 0; virtual void environment_set_fog_height(RID p_env, bool p_enable, float p_min_height, float p_max_height, float p_height_curve) = 0; + virtual bool is_environment(RID p_env) = 0; + virtual VS::EnvironmentBG environment_get_background(RID p_env) = 0; + virtual int environment_get_canvas_max_layer(RID p_env) = 0; + struct InstanceBase : RID_Data { VS::InstanceType base_type; diff --git a/servers/visual/visual_server_scene.cpp b/servers/visual/visual_server_scene.cpp index 6d1f698a5c..fb1c66d0b9 100644 --- a/servers/visual/visual_server_scene.cpp +++ b/servers/visual/visual_server_scene.cpp @@ -2162,6 +2162,18 @@ void VisualServerScene::_render_scene(const Transform p_cam_transform, const Cam VSG::scene_render->render_scene(p_cam_transform, p_cam_projection, p_cam_orthogonal, (RasterizerScene::InstanceBase **)instance_cull_result, cull_count, light_instance_cull_result, light_cull_count + directional_light_count, reflection_probe_instance_cull_result, reflection_probe_cull_count, environment, p_shadow_atlas, scenario->reflection_atlas, p_reflection_probe, p_reflection_probe_pass); } +void VisualServerScene::render_empty_scene(RID p_scenario, RID p_shadow_atlas) { + + Scenario *scenario = scenario_owner.getornull(p_scenario); + + RID environment; + if (scenario->environment.is_valid()) + environment = scenario->environment; + else + environment = scenario->fallback_environment; + VSG::scene_render->render_scene(Transform(), CameraMatrix(), true, NULL, 0, NULL, 0, NULL, 0, environment, p_shadow_atlas, scenario->reflection_atlas, RID(), 0); +} + bool VisualServerScene::_render_reflection_probe_step(Instance *p_instance, int p_step) { InstanceReflectionProbeData *reflection_probe = static_cast<InstanceReflectionProbeData *>(p_instance->base_data); diff --git a/servers/visual/visual_server_scene.h b/servers/visual/visual_server_scene.h index 92c6421987..d13c24ae24 100644 --- a/servers/visual/visual_server_scene.h +++ b/servers/visual/visual_server_scene.h @@ -519,6 +519,7 @@ public: _FORCE_INLINE_ void _light_instance_update_shadow(Instance *p_instance, const Transform p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, RID p_shadow_atlas, Scenario *p_scenario); void _render_scene(const Transform p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, RID p_force_environment, uint32_t p_visible_layers, RID p_scenario, RID p_shadow_atlas, RID p_reflection_probe, int p_reflection_probe_pass); + void render_empty_scene(RID p_scenario, RID p_shadow_atlas); void render_camera(RID p_camera, RID p_scenario, Size2 p_viewport_size, RID p_shadow_atlas); void update_dirty_instances(); diff --git a/servers/visual/visual_server_viewport.cpp b/servers/visual/visual_server_viewport.cpp index 2fbbcd225f..2c2bd2b167 100644 --- a/servers/visual/visual_server_viewport.cpp +++ b/servers/visual/visual_server_viewport.cpp @@ -35,23 +35,24 @@ void VisualServerViewport::_draw_viewport(Viewport *p_viewport) { -/* Camera should always be BEFORE any other 3D */ -#if 0 - bool scenario_draw_canvas_bg=false; - int scenario_canvas_max_layer=0; + /* Camera should always be BEFORE any other 3D */ - if (!p_viewport->hide_canvas && !p_viewport->disable_environment && scenario_owner.owns(p_viewport->scenario)) { + bool scenario_draw_canvas_bg = false; //draw canvas, or some layer of it, as BG for 3D instead of in front + int scenario_canvas_max_layer = 0; - Scenario *scenario=scenario_owner.get(p_viewport->scenario); - if (scenario->environment.is_valid()) { - if (rasterizer->is_environment(scenario->environment)) { - scenario_draw_canvas_bg=rasterizer->environment_get_background(scenario->environment)==VS::ENV_BG_CANVAS; - scenario_canvas_max_layer=rasterizer->environment_get_background_param(scenario->environment,VS::ENV_BG_PARAM_CANVAS_MAX_LAYER); - } + if (!p_viewport->hide_canvas && !p_viewport->disable_environment && VSG::scene->scenario_owner.owns(p_viewport->scenario)) { + + VisualServerScene::Scenario *scenario = VSG::scene->scenario_owner.get(p_viewport->scenario); + if (VSG::scene_render->is_environment(scenario->environment)) { + scenario_draw_canvas_bg = VSG::scene_render->environment_get_background(scenario->environment) == VS::ENV_BG_CANVAS; + + scenario_canvas_max_layer = VSG::scene_render->environment_get_canvas_max_layer(scenario->environment); } } - bool can_draw_3d=!p_viewport->hide_scenario && camera_owner.owns(p_viewport->camera) && scenario_owner.owns(p_viewport->scenario); + bool can_draw_3d = !p_viewport->disable_3d && !p_viewport->disable_3d_by_usage && VSG::scene->camera_owner.owns(p_viewport->camera); +#if 0 + if (scenario_draw_canvas_bg) { @@ -88,7 +89,7 @@ void VisualServerViewport::_draw_viewport(Viewport *p_viewport) { } } - if (!p_viewport->disable_3d && !p_viewport->disable_3d_by_usage && p_viewport->camera.is_valid()) { + if (!scenario_draw_canvas_bg && can_draw_3d) { VSG::scene->render_camera(p_viewport->camera, p_viewport->scenario, p_viewport->size, p_viewport->shadow_atlas); } @@ -199,14 +200,15 @@ void VisualServerViewport::_draw_viewport(Viewport *p_viewport) { VSG::rasterizer->restore_render_target(); -#if 0 - if (scenario_draw_canvas_bg && canvas_map.front() && canvas_map.front()->key().layer>scenario_canvas_max_layer) { - - _draw_viewport_camera(p_viewport,!can_draw_3d); - scenario_draw_canvas_bg=false; + if (scenario_draw_canvas_bg && canvas_map.front() && canvas_map.front()->key().layer > scenario_canvas_max_layer) { + if (can_draw_3d) { + VSG::scene->render_camera(p_viewport->camera, p_viewport->scenario, p_viewport->size, p_viewport->shadow_atlas); + } else { + VSG::scene->render_empty_scene(p_viewport->scenario, p_viewport->shadow_atlas); + } + scenario_draw_canvas_bg = false; } -#endif for (Map<Viewport::CanvasKey, Viewport::CanvasData *>::Element *E = canvas_map.front(); E; E = E->next()) { @@ -229,19 +231,29 @@ void VisualServerViewport::_draw_viewport(Viewport *p_viewport) { VSG::canvas->render_canvas(canvas, xform, canvas_lights, lights_with_mask, clip_rect); i++; -#if 0 - if (scenario_draw_canvas_bg && E->key().layer>=scenario_canvas_max_layer) { - _draw_viewport_camera(p_viewport,!can_draw_3d); - scenario_draw_canvas_bg=false; + + if (scenario_draw_canvas_bg && E->key().layer >= scenario_canvas_max_layer) { + + if (can_draw_3d) { + VSG::scene->render_camera(p_viewport->camera, p_viewport->scenario, p_viewport->size, p_viewport->shadow_atlas); + } else { + VSG::scene->render_empty_scene(p_viewport->scenario, p_viewport->shadow_atlas); + } + + scenario_draw_canvas_bg = false; } -#endif } -#if 0 + if (scenario_draw_canvas_bg) { - _draw_viewport_camera(p_viewport,!can_draw_3d); - scenario_draw_canvas_bg=false; + + if (can_draw_3d) { + VSG::scene->render_camera(p_viewport->camera, p_viewport->scenario, p_viewport->size, p_viewport->shadow_atlas); + } else { + VSG::scene->render_empty_scene(p_viewport->scenario, p_viewport->shadow_atlas); + } + + scenario_draw_canvas_bg = false; } -#endif //VSG::canvas_render->canvas_debug_viewport_shadows(lights_with_shadow); } |