void VisualServerViewport::_draw_viewport(Viewport *p_viewport, ARVRInterface::Eyes p_eye) { /* Camera should always be BEFORE any other 3D */ 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; 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->disable_3d && !p_viewport->disable_3d_by_usage && VSG::scene->camera_owner.owns(p_viewport->camera); if (p_viewport->clear_mode != VS::VIEWPORT_CLEAR_NEVER) { VSG::rasterizer->clear_render_target(clear_color); if (p_viewport->clear_mode == VS::VIEWPORT_CLEAR_ONLY_NEXT_FRAME) { p_viewport->clear_mode = VS::VIEWPORT_CLEAR_NEVER; } } if (!scenario_draw_canvas_bg && can_draw_3d) { Ref<ARVRInterface> arvr_interface = ARVRServer::get_singleton()->get_primary_interface(); if (p_viewport->use_arvr && arvr_interface.is_valid()) { VSG::scene->render_camera(arvr_interface, p_eye, p_viewport->camera, p_viewport->scenario, p_viewport->size, p_viewport->shadow_atlas); } else { VSG::scene->render_camera(p_viewport->camera, p_viewport->scenario, p_viewport->size, p_viewport->shadow_atlas); } } if (!p_viewport->hide_canvas) { int i = 0; Map<Viewport::CanvasKey, Viewport::CanvasData *> canvas_map; Rect2 clip_rect(0, 0, p_viewport->size.x, p_viewport->size.y); RasterizerCanvas::Light *lights = NULL; RasterizerCanvas::Light *lights_with_shadow = NULL; RasterizerCanvas::Light *lights_with_mask = NULL; Rect2 shadow_rect; int light_count = 0; for (Map<RID, Viewport::CanvasData>::Element *E = p_viewport->canvas_map.front(); E; E = E->next()) { Transform2D xf = p_viewport->global_transform * E->get().transform; VisualServerCanvas::Canvas *canvas = static_cast<VisualServerCanvas::Canvas *>(E->get().canvas); //find lights in canvas for (Set<RasterizerCanvas::Light *>::Element *F = canvas->lights.front(); F; F = F->next()) { RasterizerCanvas::Light *cl = F->get(); if (cl->enabled && cl->texture.is_valid()) { //not super efficient.. Size2 tsize(VSG::storage->texture_get_width(cl->texture), VSG::storage->texture_get_height(cl->texture)); tsize *= cl->scale; Vector2 offset = tsize / 2.0; cl->rect_cache = Rect2(-offset + cl->texture_offset, tsize); cl->xform_cache = xf * cl->xform; if (clip_rect.intersects_transformed(cl->xform_cache, cl->rect_cache)) { cl->filter_next_ptr = lights; lights = cl; cl->texture_cache = NULL; Transform2D scale; scale.scale(cl->rect_cache.size); scale.elements[2] = cl->rect_cache.position; cl->light_shader_xform = (cl->xform_cache * scale).affine_inverse(); cl->light_shader_pos = cl->xform_cache[2]; if (cl->shadow_buffer.is_valid()) { cl->shadows_next_ptr = lights_with_shadow; if (lights_with_shadow == NULL) { shadow_rect = cl->xform_cache.xform(cl->rect_cache); } else { shadow_rect = shadow_rect.merge(cl->xform_cache.xform(cl->rect_cache)); } lights_with_shadow = cl; cl->radius_cache = cl->rect_cache.size.length(); } if (cl->mode == VS::CANVAS_LIGHT_MODE_MASK) { cl->mask_next_ptr = lights_with_mask; lights_with_mask = cl; } light_count++; } VSG::canvas_render->light_internal_update(cl->light_internal, cl); } } //print_line("lights: "+itos(light_count)); canvas_map[Viewport::CanvasKey(E->key(), E->get().layer)] = &E->get(); } if (lights_with_shadow) { //update shadows if any RasterizerCanvas::LightOccluderInstance *occluders = NULL; //make list of occluders for (Map<RID, Viewport::CanvasData>::Element *E = p_viewport->canvas_map.front(); E; E = E->next()) { VisualServerCanvas::Canvas *canvas = static_cast<VisualServerCanvas::Canvas *>(E->get().canvas); Transform2D xf = p_viewport->global_transform * E->get().transform; for (Set<RasterizerCanvas::LightOccluderInstance *>::Element *F = canvas->occluders.front(); F; F = F->next()) { if (!F->get()->enabled) continue; F->get()->xform_cache = xf * F->get()->xform; if (shadow_rect.intersects_transformed(F->get()->xform_cache, F->get()->aabb_cache)) { F->get()->next = occluders; occluders = F->get(); } } } //update the light shadowmaps with them RasterizerCanvas::Light *light = lights_with_shadow; while (light) { VSG::canvas_render->canvas_light_shadow_buffer_update(light->shadow_buffer, light->xform_cache.affine_inverse(), light->item_mask, light->radius_cache / 1000.0, light->radius_cache * 1.1, occluders, &light->shadow_matrix_cache); light = light->shadows_next_ptr; } //VSG::canvas_render->reset_canvas(); } VSG::rasterizer->restore_render_target(); 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; } for (Map<Viewport::CanvasKey, Viewport::CanvasData *>::Element *E = canvas_map.front(); E; E = E->next()) { VisualServerCanvas::Canvas *canvas = static_cast<VisualServerCanvas::Canvas *>(E->get()->canvas); //print_line("canvas "+itos(i)+" size: "+itos(I->get()->canvas->child_items.size())); //print_line("GT "+p_viewport->global_transform+". CT: "+E->get()->transform); Transform2D xform = p_viewport->global_transform * E->get()->transform; RasterizerCanvas::Light *canvas_lights = NULL; RasterizerCanvas::Light *ptr = lights; while (ptr) { if (E->get()->layer >= ptr->layer_min && E->get()->layer <= ptr->layer_max) { ptr->next_ptr = canvas_lights; canvas_lights = ptr; } ptr = ptr->filter_next_ptr; } VSG::canvas->render_canvas(canvas, xform, canvas_lights, lights_with_mask, clip_rect); i++; 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; } } if (scenario_draw_canvas_bg) { 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; } //VSG::canvas_render->canvas_debug_viewport_shadows(lights_with_shadow); } }
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; if (!p_viewport->hide_canvas && !p_viewport->disable_environment && scenario_owner.owns(p_viewport->scenario)) { 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); } } } bool can_draw_3d=!p_viewport->hide_scenario && camera_owner.owns(p_viewport->camera) && scenario_owner.owns(p_viewport->scenario); if (scenario_draw_canvas_bg) { rasterizer->begin_canvas_bg(); } if (!scenario_draw_canvas_bg && can_draw_3d) { _draw_viewport_camera(p_viewport,false); } else if (true /*|| !p_viewport->canvas_list.empty()*/){ //clear the viewport black because of no camera? i seriously should.. if (p_viewport->render_target_clear_on_new_frame || p_viewport->render_target_clear) { if (p_viewport->transparent_bg) { rasterizer->clear_viewport(Color(0,0,0,0)); } else { Color cc=clear_color; if (scenario_draw_canvas_bg) cc.a=0; rasterizer->clear_viewport(cc); } p_viewport->render_target_clear=false; } } #endif if (p_viewport->clear_mode != VS::VIEWPORT_CLEAR_NEVER) { VSG::rasterizer->clear_render_target(clear_color); if (p_viewport->clear_mode == VS::VIEWPORT_CLEAR_ONLY_NEXT_FRAME) { p_viewport->clear_mode = VS::VIEWPORT_CLEAR_NEVER; } } if (!p_viewport->disable_3d && p_viewport->camera.is_valid()) { VSG::scene->render_camera(p_viewport->camera, p_viewport->scenario, p_viewport->size, p_viewport->shadow_atlas); } if (!p_viewport->hide_canvas) { int i = 0; Map<Viewport::CanvasKey, Viewport::CanvasData *> canvas_map; Rect2 clip_rect(0, 0, p_viewport->size.x, p_viewport->size.y); RasterizerCanvas::Light *lights = NULL; RasterizerCanvas::Light *lights_with_shadow = NULL; RasterizerCanvas::Light *lights_with_mask = NULL; Rect2 shadow_rect; int light_count = 0; for (Map<RID, Viewport::CanvasData>::Element *E = p_viewport->canvas_map.front(); E; E = E->next()) { Transform2D xf = p_viewport->global_transform * E->get().transform; VisualServerCanvas::Canvas *canvas = static_cast<VisualServerCanvas::Canvas *>(E->get().canvas); //find lights in canvas for (Set<RasterizerCanvas::Light *>::Element *F = canvas->lights.front(); F; F = F->next()) { RasterizerCanvas::Light *cl = F->get(); if (cl->enabled && cl->texture.is_valid()) { //not super efficient.. Size2 tsize(VSG::storage->texture_get_width(cl->texture), VSG::storage->texture_get_height(cl->texture)); tsize *= cl->scale; Vector2 offset = tsize / 2.0; cl->rect_cache = Rect2(-offset + cl->texture_offset, tsize); cl->xform_cache = xf * cl->xform; if (clip_rect.intersects_transformed(cl->xform_cache, cl->rect_cache)) { cl->filter_next_ptr = lights; lights = cl; cl->texture_cache = NULL; Transform2D scale; scale.scale(cl->rect_cache.size); scale.elements[2] = cl->rect_cache.pos; cl->light_shader_xform = (cl->xform_cache * scale).affine_inverse(); cl->light_shader_pos = cl->xform_cache[2]; if (cl->shadow_buffer.is_valid()) { cl->shadows_next_ptr = lights_with_shadow; if (lights_with_shadow == NULL) { shadow_rect = cl->xform_cache.xform(cl->rect_cache); } else { shadow_rect = shadow_rect.merge(cl->xform_cache.xform(cl->rect_cache)); } lights_with_shadow = cl; cl->radius_cache = cl->rect_cache.size.length(); } if (cl->mode == VS::CANVAS_LIGHT_MODE_MASK) { cl->mask_next_ptr = lights_with_mask; lights_with_mask = cl; } light_count++; } VSG::canvas_render->light_internal_update(cl->light_internal, cl); } } //print_line("lights: "+itos(light_count)); canvas_map[Viewport::CanvasKey(E->key(), E->get().layer)] = &E->get(); } if (lights_with_shadow) { //update shadows if any RasterizerCanvas::LightOccluderInstance *occluders = NULL; //make list of occluders for (Map<RID, Viewport::CanvasData>::Element *E = p_viewport->canvas_map.front(); E; E = E->next()) { VisualServerCanvas::Canvas *canvas = static_cast<VisualServerCanvas::Canvas *>(E->get().canvas); Transform2D xf = p_viewport->global_transform * E->get().transform; for (Set<RasterizerCanvas::LightOccluderInstance *>::Element *F = canvas->occluders.front(); F; F = F->next()) { if (!F->get()->enabled) continue; F->get()->xform_cache = xf * F->get()->xform; if (shadow_rect.intersects_transformed(F->get()->xform_cache, F->get()->aabb_cache)) { F->get()->next = occluders; occluders = F->get(); } } } //update the light shadowmaps with them RasterizerCanvas::Light *light = lights_with_shadow; while (light) { VSG::canvas_render->canvas_light_shadow_buffer_update(light->shadow_buffer, light->xform_cache.affine_inverse(), light->item_mask, light->radius_cache / 1000.0, light->radius_cache * 1.1, occluders, &light->shadow_matrix_cache); light = light->shadows_next_ptr; } //VSG::canvas_render->reset_canvas(); } 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; } #endif for (Map<Viewport::CanvasKey, Viewport::CanvasData *>::Element *E = canvas_map.front(); E; E = E->next()) { VisualServerCanvas::Canvas *canvas = static_cast<VisualServerCanvas::Canvas *>(E->get()->canvas); //print_line("canvas "+itos(i)+" size: "+itos(I->get()->canvas->child_items.size())); //print_line("GT "+p_viewport->global_transform+". CT: "+E->get()->transform); Transform2D xform = p_viewport->global_transform * E->get()->transform; RasterizerCanvas::Light *canvas_lights = NULL; RasterizerCanvas::Light *ptr = lights; while (ptr) { if (E->get()->layer >= ptr->layer_min && E->get()->layer <= ptr->layer_max) { ptr->next_ptr = canvas_lights; canvas_lights = ptr; } ptr = ptr->filter_next_ptr; } 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; } #endif } #if 0 if (scenario_draw_canvas_bg) { _draw_viewport_camera(p_viewport,!can_draw_3d); scenario_draw_canvas_bg=false; } #endif //VSG::canvas_render->canvas_debug_viewport_shadows(lights_with_shadow); } }