diff options
Diffstat (limited to 'servers/visual')
-rw-r--r-- | servers/visual/rasterizer/rasterizer.h | 43 | ||||
-rw-r--r-- | servers/visual/rasterizer/rasterizer_canvas_rd.cpp | 621 | ||||
-rw-r--r-- | servers/visual/rasterizer/rasterizer_canvas_rd.h | 142 | ||||
-rw-r--r-- | servers/visual/rasterizer/rasterizer_storage_rd.h | 9 | ||||
-rw-r--r-- | servers/visual/rasterizer/shaders/SCsub | 2 | ||||
-rw-r--r-- | servers/visual/rasterizer/shaders/canvas.glsl | 141 | ||||
-rw-r--r-- | servers/visual/rasterizer/shaders/canvas_occlusion.glsl | 38 | ||||
-rw-r--r-- | servers/visual/rasterizer/shaders/canvas_occlusion_fix.glsl | 56 | ||||
-rw-r--r-- | servers/visual/rasterizer/shaders/canvas_uniforms_inc.glsl | 48 | ||||
-rw-r--r-- | servers/visual/rendering_device.h | 2 | ||||
-rw-r--r-- | servers/visual/visual_server_canvas.cpp | 37 | ||||
-rw-r--r-- | servers/visual/visual_server_viewport.cpp | 13 |
12 files changed, 997 insertions, 155 deletions
diff --git a/servers/visual/rasterizer/rasterizer.h b/servers/visual/rasterizer/rasterizer.h index 853d02f7c3..88520a6a79 100644 --- a/servers/visual/rasterizer/rasterizer.h +++ b/servers/visual/rasterizer/rasterizer.h @@ -562,15 +562,6 @@ public: virtual void render_target_disable_clear_request(RID p_render_target) = 0; virtual void render_target_do_clear_request(RID p_render_target) = 0; - /* CANVAS SHADOW */ - - virtual RID canvas_light_shadow_buffer_create(int p_width) = 0; - - /* LIGHT SHADOW MAPPING */ - - virtual RID canvas_light_occluder_create() = 0; - virtual void canvas_light_occluder_set_polylines(RID p_occluder, const PoolVector<Vector2> &p_lines) = 0; - virtual VS::InstanceType get_base_type(RID p_rid) const = 0; virtual bool free(RID p_rid) = 0; @@ -625,21 +616,21 @@ public: RID texture; Vector2 texture_offset; RID canvas; - RID shadow_buffer; + bool use_shadow; int shadow_buffer_size; float shadow_gradient_length; VS::CanvasLightShadowFilter shadow_filter; Color shadow_color; float shadow_smooth; - void *texture_cache; // implementation dependent + //void *texture_cache; // implementation dependent Rect2 rect_cache; Transform2D xform_cache; float radius_cache; //used for shadow far plane - CameraMatrix shadow_matrix_cache; + //CameraMatrix shadow_matrix_cache; Transform2D light_shader_xform; - Vector2 light_shader_pos; + //Vector2 light_shader_pos; Light *shadows_next_ptr; Light *filter_next_ptr; @@ -648,6 +639,8 @@ public: RID light_internal; + int32_t render_index_cache; + Light() { enabled = true; color = Color(1, 1, 1); @@ -662,21 +655,19 @@ public: energy = 1.0; item_shadow_mask = -1; mode = VS::CANVAS_LIGHT_MODE_ADD; - texture_cache = NULL; + // texture_cache = NULL; next_ptr = NULL; mask_next_ptr = NULL; filter_next_ptr = NULL; + use_shadow = false; shadow_buffer_size = 2048; shadow_gradient_length = 0; shadow_filter = VS::CANVAS_LIGHT_FILTER_NONE; shadow_smooth = 0.0; + render_index_cache = -1; } }; - virtual RID light_internal_create() = 0; - virtual void light_internal_update(RID p_rid, Light *p_light) = 0; - virtual void light_internal_free(RID p_rid) = 0; - typedef uint64_t TextureBindingID; virtual TextureBindingID request_texture_binding(RID p_texture, RID p_normalmap, RID p_specular, VS::CanvasItemTextureFilter p_filter, VS::CanvasItemTextureRepeat p_repeat, RID p_multimesh) = 0; @@ -957,7 +948,7 @@ public: case Item::Command::TYPE_PRIMITIVE: { const Item::CommandPrimitive *primitive = static_cast<const Item::CommandPrimitive *>(c); - for (int j = 0; j < primitive->point_count; j++) { + for (uint32_t j = 0; j < primitive->point_count; j++) { if (j == 0) { r.position = primitive->points[0]; } else { @@ -1085,7 +1076,7 @@ public: c = n; } { - uint32_t cbc = MIN((current_block + 1), blocks.size()); + uint32_t cbc = MIN((current_block + 1), (uint32_t)blocks.size()); CommandBlock *blockptr = blocks.ptrw(); for (uint32_t i = 0; i < cbc; i++) { blockptr[i].usage = 0; @@ -1139,7 +1130,7 @@ public: bool enabled; RID canvas; RID polygon; - RID polygon_buffer; + RID occluder; Rect2 aabb_cache; Transform2D xform; Transform2D xform_cache; @@ -1156,12 +1147,18 @@ public: } }; - virtual void canvas_light_shadow_buffer_update(RID p_buffer, const Transform2D &p_light_xform, int p_light_mask, float p_near, float p_far, LightOccluderInstance *p_occluders, CameraMatrix *p_xform_cache) = 0; + virtual RID light_create() = 0; + virtual void light_set_texture(RID p_rid, RID p_texture) = 0; + virtual void light_set_use_shadow(RID p_rid, bool p_enable, int p_resolution) = 0; + virtual void light_update_shadow(RID p_rid, const Transform2D &p_light_xform, int p_light_mask, float p_near, float p_far, LightOccluderInstance *p_occluders) = 0; - virtual void reset_canvas() = 0; + virtual RID occluder_polygon_create() = 0; + virtual void occluder_polygon_set_shape_as_lines(RID p_occluder, const PoolVector<Vector2> &p_lines) = 0; + virtual void occluder_polygon_set_cull_mode(RID p_occluder, VS::CanvasOccluderPolygonCullMode p_mode) = 0; virtual void draw_window_margins(int *p_margins, RID *p_margin_textures) = 0; + virtual bool free(RID p_rid) = 0; virtual void update() = 0; RasterizerCanvas() { singleton = this; } diff --git a/servers/visual/rasterizer/rasterizer_canvas_rd.cpp b/servers/visual/rasterizer/rasterizer_canvas_rd.cpp index d72be70677..838e26ac73 100644 --- a/servers/visual/rasterizer/rasterizer_canvas_rd.cpp +++ b/servers/visual/rasterizer/rasterizer_canvas_rd.cpp @@ -63,6 +63,14 @@ void RasterizerCanvasRD::_update_transform_to_mat4(const Transform &p_transform, p_mat4[15] = 1; } +void RasterizerCanvasRD::_update_specular_shininess(const Color &p_transform, uint32_t *r_ss) { + + *r_ss = uint32_t(CLAMP(p_transform.a * 255.0, 0, 255)) << 24; + *r_ss |= uint32_t(CLAMP(p_transform.b * 255.0, 0, 255)) << 16; + *r_ss |= uint32_t(CLAMP(p_transform.g * 255.0, 0, 255)) << 8; + *r_ss |= uint32_t(CLAMP(p_transform.r * 255.0, 0, 255)); +} + RID RasterizerCanvasRD::_create_texture_binding(RID p_texture, RID p_normalmap, RID p_specular, VisualServer::CanvasItemTextureFilter p_filter, VisualServer::CanvasItemTextureRepeat p_repeat, RID p_multimesh) { Vector<RD::Uniform> uniform_set; @@ -472,12 +480,19 @@ void RasterizerCanvasRD::free_polygon(PolygonID p_polygon) { polygon_buffers.polygons.erase(p_polygon); } -Size2i RasterizerCanvasRD::_bind_texture_binding(TextureBindingID p_binding, RD::DrawListID p_draw_list) { +Size2i RasterizerCanvasRD::_bind_texture_binding(TextureBindingID p_binding, RD::DrawListID p_draw_list, uint32_t &flags) { TextureBinding **texture_binding_ptr = bindings.texture_bindings.getptr(p_binding); ERR_FAIL_COND_V(!texture_binding_ptr, Size2i()); TextureBinding *texture_binding = *texture_binding_ptr; + if (texture_binding->key.normalmap.is_valid()) { + flags |= FLAGS_DEFAULT_NORMAL_MAP_USED; + } + if (texture_binding->key.specular.is_valid()) { + flags |= FLAGS_DEFAULT_SPECULAR_MAP_USED; + } + if (!RD::get_singleton()->uniform_set_is_valid(texture_binding->uniform_set)) { //texture may have changed (erased or replaced, see if we can fix) texture_binding->uniform_set = _create_texture_binding(texture_binding->key.texture, texture_binding->key.normalmap, texture_binding->key.specular, texture_binding->key.texture_filter, texture_binding->key.texture_repeat, texture_binding->key.multimesh); @@ -493,12 +508,15 @@ Size2i RasterizerCanvasRD::_bind_texture_binding(TextureBindingID p_binding, RD: } //////////////////// -void RasterizerCanvasRD::_render_item(RD::DrawListID p_draw_list, const Item *p_item, RenderTargetFormat p_render_target_format, RD::TextureSamples p_samples, const Color &p_modulate, const Transform2D &p_canvas_transform_inverse, Item *¤t_clip) { +void RasterizerCanvasRD::_render_item(RD::DrawListID p_draw_list, const Item *p_item, RenderTargetFormat p_render_target_format, RD::TextureSamples p_samples, const Transform2D &p_canvas_transform_inverse, Item *¤t_clip, Light *p_lights) { //create an empty push constant PushConstant push_constant; Transform2D base_transform = p_canvas_transform_inverse * p_item->final_transform; _update_transform_2d_to_mat2x3(base_transform, push_constant.world); + + Color base_color = p_item->final_modulate; + for (int i = 0; i < 4; i++) { push_constant.modulation[i] = 0; push_constant.ninepatch_margins[i] = 0; @@ -506,7 +524,6 @@ void RasterizerCanvasRD::_render_item(RD::DrawListID p_draw_list, const Item *p_ push_constant.dst_rect[i] = 0; } push_constant.flags = 0; - push_constant.specular_shininess = 0xFFFFFFFF; push_constant.color_texture_pixel_size[0] = 0; push_constant.color_texture_pixel_size[1] = 0; @@ -514,6 +531,37 @@ void RasterizerCanvasRD::_render_item(RD::DrawListID p_draw_list, const Item *p_ push_constant.pad[2] = 0; push_constant.pad[3] = 0; + push_constant.lights[0] = 0; + push_constant.lights[1] = 0; + push_constant.lights[2] = 0; + push_constant.lights[3] = 0; + + uint32_t base_flags = 0; + + { + Light *light = p_lights; + + uint16_t light_count = 0; + while (light) { + + if (light->render_index_cache >= 0 && p_item->light_mask & light->item_mask && p_item->z_final >= light->z_min && p_item->z_final <= light->z_max && p_item->global_rect_cache.intersects_transformed(light->xform_cache, light->rect_cache)) { + + uint32_t light_index = light->render_index_cache; + push_constant.lights[light_count >> 2] |= light_index << ((light_count & 3) * 8); + light_count++; + if (light->mode == VS::CANVAS_LIGHT_MODE_MASK) { + base_flags |= FLAGS_USING_LIGHT_MASK; + } + if (light_count == MAX_LIGHTS_PER_ITEM) { + break; + } + } + light = light->next_ptr; + } + + base_flags |= light_count << FLAGS_LIGHT_COUNT_SHIFT; + } + PipelineVariants *pipeline_variants = &shader.pipeline_variants; bool reclip = false; @@ -521,7 +569,8 @@ void RasterizerCanvasRD::_render_item(RD::DrawListID p_draw_list, const Item *p_ const Item::Command *c = p_item->commands; while (c) { - push_constant.flags = 0; //reset on each command for sanity + push_constant.flags = base_flags; //reset on each command for sanity + push_constant.specular_shininess = 0xFFFFFFFF; switch (c->type) { case Item::Command::TYPE_RECT: { @@ -538,11 +587,17 @@ void RasterizerCanvasRD::_render_item(RD::DrawListID p_draw_list, const Item *p_ Size2 texpixel_size; { - texpixel_size = _bind_texture_binding(rect->texture_binding.binding_id, p_draw_list); + texpixel_size = _bind_texture_binding(rect->texture_binding.binding_id, p_draw_list, push_constant.flags); texpixel_size.x = 1.0 / texpixel_size.x; texpixel_size.y = 1.0 / texpixel_size.y; } + if (rect->specular_shininess.a < 0.999) { + push_constant.flags |= FLAGS_DEFAULT_SPECULAR_MAP_USED; + } + + _update_specular_shininess(rect->specular_shininess, &push_constant.specular_shininess); + Rect2 src_rect; Rect2 dst_rect; @@ -594,10 +649,10 @@ void RasterizerCanvasRD::_render_item(RD::DrawListID p_draw_list, const Item *p_ texpixel_size = Vector2(1, 1); } - push_constant.modulation[0] = rect->modulate.r * p_modulate.r; - push_constant.modulation[1] = rect->modulate.g * p_modulate.g; - push_constant.modulation[2] = rect->modulate.b * p_modulate.b; - push_constant.modulation[3] = rect->modulate.a; + push_constant.modulation[0] = rect->modulate.r * base_color.r; + push_constant.modulation[1] = rect->modulate.g * base_color.g; + push_constant.modulation[2] = rect->modulate.b * base_color.b; + push_constant.modulation[3] = rect->modulate.a * base_color.a; push_constant.src_rect[0] = src_rect.position.x; push_constant.src_rect[1] = src_rect.position.y; @@ -632,11 +687,17 @@ void RasterizerCanvasRD::_render_item(RD::DrawListID p_draw_list, const Item *p_ Size2 texpixel_size; { - texpixel_size = _bind_texture_binding(np->texture_binding.binding_id, p_draw_list); + texpixel_size = _bind_texture_binding(np->texture_binding.binding_id, p_draw_list, push_constant.flags); texpixel_size.x = 1.0 / texpixel_size.x; texpixel_size.y = 1.0 / texpixel_size.y; } + if (np->specular_shininess.a < 0.999) { + push_constant.flags |= FLAGS_DEFAULT_SPECULAR_MAP_USED; + } + + _update_specular_shininess(np->specular_shininess, &push_constant.specular_shininess); + Rect2 src_rect; Rect2 dst_rect(np->rect.position.x, np->rect.position.y, np->rect.size.x, np->rect.size.y); @@ -655,10 +716,10 @@ void RasterizerCanvasRD::_render_item(RD::DrawListID p_draw_list, const Item *p_ } } - push_constant.modulation[0] = np->color.r * p_modulate.r; - push_constant.modulation[1] = np->color.g * p_modulate.g; - push_constant.modulation[2] = np->color.b * p_modulate.b; - push_constant.modulation[3] = np->color.a * p_modulate.a; + push_constant.modulation[0] = np->color.r * base_color.r; + push_constant.modulation[1] = np->color.g * base_color.g; + push_constant.modulation[2] = np->color.b * base_color.b; + push_constant.modulation[3] = np->color.a * base_color.a; push_constant.src_rect[0] = src_rect.position.x; push_constant.src_rect[1] = src_rect.position.y; @@ -713,15 +774,21 @@ void RasterizerCanvasRD::_render_item(RD::DrawListID p_draw_list, const Item *p_ Size2 texpixel_size; { - texpixel_size = _bind_texture_binding(polygon->texture_binding.binding_id, p_draw_list); + texpixel_size = _bind_texture_binding(polygon->texture_binding.binding_id, p_draw_list, push_constant.flags); texpixel_size.x = 1.0 / texpixel_size.x; texpixel_size.y = 1.0 / texpixel_size.y; } - push_constant.modulation[0] = p_modulate.r; - push_constant.modulation[1] = p_modulate.g; - push_constant.modulation[2] = p_modulate.b; - push_constant.modulation[3] = p_modulate.a; + if (polygon->specular_shininess.a < 0.999) { + push_constant.flags |= FLAGS_DEFAULT_SPECULAR_MAP_USED; + } + + _update_specular_shininess(polygon->specular_shininess, &push_constant.specular_shininess); + + push_constant.modulation[0] = base_color.r; + push_constant.modulation[1] = base_color.g; + push_constant.modulation[2] = base_color.b; + push_constant.modulation[3] = base_color.a; for (int j = 0; j < 4; j++) { push_constant.src_rect[j] = 0; @@ -755,9 +822,15 @@ void RasterizerCanvasRD::_render_item(RD::DrawListID p_draw_list, const Item *p_ //bind textures { - _bind_texture_binding(primitive->texture_binding.binding_id, p_draw_list); + _bind_texture_binding(primitive->texture_binding.binding_id, p_draw_list, push_constant.flags); } + if (primitive->specular_shininess.a < 0.999) { + push_constant.flags |= FLAGS_DEFAULT_SPECULAR_MAP_USED; + } + + _update_specular_shininess(primitive->specular_shininess, &push_constant.specular_shininess); + RD::get_singleton()->draw_list_bind_index_array(p_draw_list, primitive_arrays.index_array[MIN(3, primitive->point_count) - 1]); for (uint32_t j = 0; j < MIN(3, primitive->point_count); j++) { @@ -765,7 +838,7 @@ void RasterizerCanvasRD::_render_item(RD::DrawListID p_draw_list, const Item *p_ push_constant.points[j * 2 + 1] = primitive->points[j].y; push_constant.uvs[j * 2 + 0] = primitive->uvs[j].x; push_constant.uvs[j * 2 + 1] = primitive->uvs[j].y; - Color col = primitive->colors[j] * p_modulate; + Color col = primitive->colors[j] * base_color; push_constant.colors[j * 2 + 0] = (uint32_t(Math::make_half_float(col.g)) << 16) | Math::make_half_float(col.r); push_constant.colors[j * 2 + 1] = (uint32_t(Math::make_half_float(col.a)) << 16) | Math::make_half_float(col.b); } @@ -779,7 +852,7 @@ void RasterizerCanvasRD::_render_item(RD::DrawListID p_draw_list, const Item *p_ push_constant.points[j * 2 + 1] = primitive->points[j + 1].y; push_constant.uvs[j * 2 + 0] = primitive->uvs[j + 1].x; push_constant.uvs[j * 2 + 1] = primitive->uvs[j + 1].y; - Color col = primitive->colors[j + 1] * p_modulate; + Color col = primitive->colors[j + 1] * base_color; push_constant.colors[j * 2 + 0] = (uint32_t(Math::make_half_float(col.g)) << 16) | Math::make_half_float(col.r); push_constant.colors[j * 2 + 1] = (uint32_t(Math::make_half_float(col.a)) << 16) | Math::make_half_float(col.b); } @@ -1107,12 +1180,12 @@ void RasterizerCanvasRD::_render_item(RD::DrawListID p_draw_list, const Item *p_ } } -void RasterizerCanvasRD::_render_items(RID p_to_render_target, int p_item_count, const Color &p_modulate, const Transform2D &p_transform) { +void RasterizerCanvasRD::_render_items(RID p_to_render_target, int p_item_count, const Transform2D &p_canvas_transform_inverse, Light *p_lights) { Item *current_clip = NULL; RenderTargetFormat render_target_format = RENDER_TARGET_FORMAT_8_BIT_INT; - Transform2D canvas_transform_inverse = p_transform.affine_inverse(); + Transform2D canvas_transform_inverse = p_canvas_transform_inverse; RID framebuffer = storage->render_target_get_rd_framebuffer(p_to_render_target); @@ -1153,7 +1226,7 @@ void RasterizerCanvasRD::_render_items(RID p_to_render_target, int p_item_count, RD::get_singleton()->draw_list_bind_uniform_set(draw_list, shader.default_skeleton_uniform_set, 1); } - _render_item(draw_list, ci, render_target_format, texture_samples, p_modulate, canvas_transform_inverse, current_clip); + _render_item(draw_list, ci, render_target_format, texture_samples, canvas_transform_inverse, current_clip, p_lights); } RD::get_singleton()->draw_list_end(); @@ -1167,11 +1240,67 @@ void RasterizerCanvasRD::_update_canvas_state_uniform_set() { Vector<RD::Uniform> uniforms; - RD::Uniform u; - u.type = RD::UNIFORM_TYPE_UNIFORM_BUFFER; - u.binding = 0; - u.ids.push_back(state.canvas_state_buffer); - uniforms.push_back(u); + { + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_UNIFORM_BUFFER; + u.binding = 0; + u.ids.push_back(state.canvas_state_buffer); + uniforms.push_back(u); + } + + { + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_UNIFORM_BUFFER; + u.binding = 1; + u.ids.push_back(state.lights_uniform_buffer); + uniforms.push_back(u); + } + + { + + RD::Uniform u_lights; + u_lights.type = RD::UNIFORM_TYPE_TEXTURE; + u_lights.binding = 2; + + RD::Uniform u_shadows; + u_shadows.type = RD::UNIFORM_TYPE_TEXTURE; + u_shadows.binding = 3; + + //lights + for (uint32_t i = 0; i < MAX_LIGHT_TEXTURES; i++) { + if (i < canvas_light_owner.get_rid_count()) { + CanvasLight *cl = canvas_light_owner.get_rid_by_index(i); + cl->texture_index = i; + RID rd_texture; + + if (cl->texture.is_valid()) { + rd_texture = storage->texture_get_rd_texture(cl->texture); + } + if (rd_texture.is_valid()) { + u_lights.ids.push_back(rd_texture); + } else { + u_lights.ids.push_back(default_textures.white_texture); + } + if (cl->shadow.texture.is_valid()) { + u_shadows.ids.push_back(cl->shadow.texture); + } else { + u_shadows.ids.push_back(default_textures.black_texture); + } + } else { + u_lights.ids.push_back(default_textures.white_texture); + u_shadows.ids.push_back(default_textures.black_texture); + } + } + + //in case there are more + for (uint32_t i = MAX_LIGHT_TEXTURES; i < canvas_light_owner.get_rid_count(); i++) { + CanvasLight *cl = canvas_light_owner.get_rid_by_index(i); + cl->texture_index = -1; //make invalid (no texture) + } + + uniforms.push_back(u_lights); + uniforms.push_back(u_shadows); + } state.canvas_state_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, shader.default_version_rd_shader, 3); // uses index 3 } @@ -1182,6 +1311,7 @@ void RasterizerCanvasRD::canvas_render_items(RID p_to_render_target, Item *p_ite //setup canvas state uniforms if needed _update_canvas_state_uniform_set(); + Transform2D canvas_transform_inverse = p_canvas_transform.affine_inverse(); { //update canvas state uniform buffer @@ -1194,9 +1324,77 @@ void RasterizerCanvasRD::canvas_render_items(RID p_to_render_target, Item *p_ite screen_transform.scale(Vector3(2.0f / ssize.width, 2.0f / ssize.height, 1.0f)); _update_transform_to_mat4(screen_transform, state_buffer.screen_transform); _update_transform_2d_to_mat4(p_canvas_transform, state_buffer.canvas_transform); + + Transform2D normal_transform = p_canvas_transform; + normal_transform.elements[0].normalize(); + normal_transform.elements[1].normalize(); + normal_transform.elements[2] = Vector2(); + _update_transform_2d_to_mat4(normal_transform, state_buffer.canvas_normal_transform); + + state_buffer.canvas_modulate[0] = p_modulate.r; + state_buffer.canvas_modulate[1] = p_modulate.g; + state_buffer.canvas_modulate[2] = p_modulate.b; + state_buffer.canvas_modulate[3] = p_modulate.a; + RD::get_singleton()->buffer_update(state.canvas_state_buffer, 0, sizeof(State::Buffer), &state_buffer, true); } + //setup lights if exist + + { + + Light *l = p_light_list; + uint32_t index = 0; + + while (l) { + + if (index == MAX_RENDER_LIGHTS) { + l->render_index_cache = -1; + l = l->next_ptr; + continue; + } + + CanvasLight *clight = canvas_light_owner.getornull(l->light_internal); + if (!clight || clight->texture_index < 0) { //unused or invalid texture + l->render_index_cache = -1; + l = l->next_ptr; + ERR_CONTINUE(!clight); + } + Transform2D to_light_xform = (p_canvas_transform * l->light_shader_xform).affine_inverse(); + + Vector2 canvas_light_pos = p_canvas_transform.xform(l->xform.get_origin()); //convert light position to canvas coordinates, as all computation is done in canvas coords to avoid precision loss + state.light_uniforms[index].position[0] = canvas_light_pos.x; + state.light_uniforms[index].position[1] = canvas_light_pos.y; + + _update_transform_2d_to_mat2x4(to_light_xform, state.light_uniforms[index].matrix); + + state.light_uniforms[index].height = l->height * (p_canvas_transform.elements[0].length() + p_canvas_transform.elements[1].length()) * 0.5; //approximate height conversion to the canvas size, since all calculations are done in canvas coords to avoid precision loss + for (int i = 0; i < 4; i++) { + state.light_uniforms[index].shadow_color[i] = l->shadow_color[i]; + state.light_uniforms[index].color[i] = l->color[i]; + } + + state.light_uniforms[index].color[3] = l->energy; //use alpha for energy, so base color can go separate + + if (clight->shadow.texture.is_valid()) { + state.light_uniforms[index].shadow_pixel_size = 1.0 / clight->shadow.size; + } else { + state.light_uniforms[index].shadow_pixel_size = 1.0; + } + state.light_uniforms[index].flags = clight->texture_index; + state.light_uniforms[index].flags |= l->mode << LIGHT_FLAGS_BLEND_SHIFT; + + l->render_index_cache = index; + + index++; + l = l->next_ptr; + } + + if (index > 0) { + RD::get_singleton()->buffer_update(state.lights_uniform_buffer, 0, sizeof(LightUniform) * index, &state.light_uniforms[0], true); + } + } + //fill the list until rendering is possible. Item *ci = p_item_list; while (ci) { @@ -1205,7 +1403,7 @@ void RasterizerCanvasRD::canvas_render_items(RID p_to_render_target, Item *p_ite bool backbuffer_copy = ci->copy_back_buffer; // || shader uses SCREEN_TEXTURE if (!ci->next || backbuffer_copy || item_count == MAX_RENDER_ITEMS - 1) { - _render_items(p_to_render_target, item_count, p_modulate, p_canvas_transform); + _render_items(p_to_render_target, item_count, canvas_transform_inverse, p_light_list); //then reset item_count = 0; } @@ -1224,6 +1422,292 @@ void RasterizerCanvasRD::canvas_render_items(RID p_to_render_target, Item *p_ite } } +RID RasterizerCanvasRD::light_create() { + + CanvasLight canvas_light; + canvas_light.shadow.size = 0; + canvas_light.texture_index = -1; + return canvas_light_owner.make_rid(canvas_light); +} + +void RasterizerCanvasRD::light_set_texture(RID p_rid, RID p_texture) { + CanvasLight *cl = canvas_light_owner.getornull(p_rid); + ERR_FAIL_COND(!cl); + if (cl->texture == p_texture) { + return; + } + + cl->texture = p_texture; + + //canvas state uniform set needs updating + if (state.canvas_state_uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(state.canvas_state_uniform_set)) { + RD::get_singleton()->free(state.canvas_state_uniform_set); + } +} +void RasterizerCanvasRD::light_set_use_shadow(RID p_rid, bool p_enable, int p_resolution) { + CanvasLight *cl = canvas_light_owner.getornull(p_rid); + ERR_FAIL_COND(!cl); + ERR_FAIL_COND(p_resolution < 64); + if (cl->shadow.texture.is_valid() == p_enable && p_resolution == cl->shadow.size) { + return; + } + + if (cl->shadow.texture.is_valid()) { + + RD::get_singleton()->free(cl->shadow.uniform_set); + cl->shadow.uniform_set = RID(); + + for (int i = 0; i < 4; i++) { + RD::get_singleton()->free(cl->shadow.render_fb[i]); + RD::get_singleton()->free(cl->shadow.render_textures[i]); + cl->shadow.render_fb[i] = RID(); + cl->shadow.render_textures[i] = RID(); + } + RD::get_singleton()->free(cl->shadow.fix_fb); + RD::get_singleton()->free(cl->shadow.texture); + + cl->shadow.fix_fb = RID(); + cl->shadow.texture = RID(); + } + + if (p_enable) { + + { //texture + RD::TextureFormat tf; + tf.type = RD::TEXTURE_TYPE_2D; + tf.width = p_resolution; + tf.height = 1; + tf.usage_bits = RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT; + tf.format = RD::DATA_FORMAT_R32_SFLOAT; + + cl->shadow.texture = RD::get_singleton()->texture_create(tf, RD::TextureView()); + + Vector<RID> fb_textures; + fb_textures.push_back(cl->shadow.texture); + cl->shadow.fix_fb = RD::get_singleton()->framebuffer_create(fb_textures); + } + { + RD::TextureFormat tf; + tf.type = RD::TEXTURE_TYPE_2D; + tf.width = p_resolution / 2; + tf.height = 1; + tf.usage_bits = RD::TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT; + tf.format = RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_X8_D24_UNORM_PACK32, RD::TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) ? RD::DATA_FORMAT_X8_D24_UNORM_PACK32 : RD::DATA_FORMAT_D32_SFLOAT; + //chunks to write + cl->shadow.render_depth = RD::get_singleton()->texture_create(tf, RD::TextureView()); + + RD::Uniform tex_uniforms; + tex_uniforms.type = RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE; + tex_uniforms.binding = 0; + + for (int i = 0; i < 4; i++) { + tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT; + tf.format = RD::DATA_FORMAT_R32_SFLOAT; + cl->shadow.render_textures[i] = RD::get_singleton()->texture_create(tf, RD::TextureView()); + Vector<RID> textures; + textures.push_back(cl->shadow.render_textures[i]); + textures.push_back(cl->shadow.render_depth); + cl->shadow.render_fb[i] = RD::get_singleton()->framebuffer_create(textures); + + tex_uniforms.ids.push_back(default_samplers.samplers[VS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST][VS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED]); + tex_uniforms.ids.push_back(cl->shadow.render_textures[i]); + } + + Vector<RD::Uniform> tex_uniforms_set; + tex_uniforms_set.push_back(tex_uniforms); + cl->shadow.uniform_set = RD::get_singleton()->uniform_set_create(tex_uniforms_set, shadow_render.shader_fix.version_get_shader(shadow_render.shader_fix_version, 0), 0); + } + } + + //canvas state uniform set needs updating + if (state.canvas_state_uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(state.canvas_state_uniform_set)) { + RD::get_singleton()->free(state.canvas_state_uniform_set); + } +} + +void RasterizerCanvasRD::light_update_shadow(RID p_rid, const Transform2D &p_light_xform, int p_light_mask, float p_near, float p_far, LightOccluderInstance *p_occluders) { + + CanvasLight *cl = canvas_light_owner.getornull(p_rid); + ERR_FAIL_COND(cl->shadow.texture.is_null()); + + for (int i = 0; i < 4; i++) { + + //make sure it remains orthogonal, makes easy to read angle later + + //light.basis.scale(Vector3(to_light.elements[0].length(),to_light.elements[1].length(),1)); + + Vector<Color> cc; + cc.push_back(Color(p_far, p_far, p_far, 1.0)); + RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(cl->shadow.render_fb[i], RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ_COLOR_DISCARD_DEPTH, cc); + + CameraMatrix projection; + { + real_t fov = 90; + real_t nearp = p_near; + real_t farp = p_far; + real_t aspect = 1.0; + + real_t ymax = nearp * Math::tan(Math::deg2rad(fov * 0.5)); + real_t ymin = -ymax; + real_t xmin = ymin * aspect; + real_t xmax = ymax * aspect; + + projection.set_frustum(xmin, xmax, ymin, ymax, nearp, farp); + } + + Vector3 cam_target = Basis(Vector3(0, 0, Math_PI * 2 * (i / 4.0))).xform(Vector3(0, 1, 0)); + projection = projection * CameraMatrix(Transform().looking_at(cam_target, Vector3(0, 0, -1)).affine_inverse()); + + ShadowRenderPushConstant push_constant; + for (int y = 0; y < 4; y++) { + for (int x = 0; x < 4; x++) { + push_constant.projection[y * 4 + x] = projection.matrix[y][x]; + } + } + + /*if (i == 0) + *p_xform_cache = projection;*/ + + LightOccluderInstance *instance = p_occluders; + + while (instance) { + + OccluderPolygon *co = occluder_polygon_owner.getornull(instance->polygon); + + if (!co || co->index_array.is_null() || !(p_light_mask & instance->light_mask)) { + + instance = instance->next; + continue; + } + + _update_transform_2d_to_mat4(p_light_xform * instance->xform_cache, push_constant.modelview); + + RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, shadow_render.render_pipelines[co->cull_mode]); + RD::get_singleton()->draw_list_bind_vertex_array(draw_list, co->vertex_array); + RD::get_singleton()->draw_list_bind_index_array(draw_list, co->index_array); + RD::get_singleton()->draw_list_set_push_constant(draw_list, &push_constant, sizeof(ShadowRenderPushConstant)); + + RD::get_singleton()->draw_list_draw(draw_list, true); + + instance = instance->next; + } + + RD::get_singleton()->draw_list_end(); + } + + Vector<Color> cc; + cc.push_back(Color(p_far, p_far, p_far, 1.0)); + RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(cl->shadow.fix_fb, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ_COLOR_DISCARD_DEPTH, cc); + RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, shadow_render.shader_fix_pipeline); + RD::get_singleton()->draw_list_bind_index_array(draw_list, primitive_arrays.index_array[3]); + RD::get_singleton()->draw_list_bind_uniform_set(draw_list, cl->shadow.uniform_set, 0); + RD::get_singleton()->draw_list_draw(draw_list, true); + RD::get_singleton()->draw_list_end(); +} + +RID RasterizerCanvasRD::occluder_polygon_create() { + + OccluderPolygon occluder; + occluder.point_count = 0; + occluder.cull_mode = VS::CANVAS_OCCLUDER_POLYGON_CULL_DISABLED; + return occluder_polygon_owner.make_rid(occluder); +} + +void RasterizerCanvasRD::occluder_polygon_set_shape_as_lines(RID p_occluder, const PoolVector<Vector2> &p_lines) { + + OccluderPolygon *oc = occluder_polygon_owner.getornull(p_occluder); + ERR_FAIL_COND(!oc); + + if (oc->point_count != p_lines.size() && oc->vertex_array.is_valid()) { + + RD::get_singleton()->free(oc->vertex_array); + RD::get_singleton()->free(oc->vertex_buffer); + RD::get_singleton()->free(oc->index_array); + RD::get_singleton()->free(oc->index_buffer); + + oc->vertex_array = RID(); + oc->vertex_buffer = RID(); + oc->index_array = RID(); + oc->index_buffer = RID(); + } + + if (p_lines.size()) { + + PoolVector<uint8_t> geometry; + PoolVector<uint8_t> indices; + int lc = p_lines.size(); + + geometry.resize(lc * 6 * sizeof(float)); + indices.resize(lc * 3 * sizeof(uint16_t)); + + { + PoolVector<uint8_t>::Write vw = geometry.write(); + float *vwptr = (float *)vw.ptr(); + PoolVector<uint8_t>::Write iw = indices.write(); + uint16_t *iwptr = (uint16_t *)iw.ptr(); + + PoolVector<Vector2>::Read lr = p_lines.read(); + + const int POLY_HEIGHT = 16384; + + for (int i = 0; i < lc / 2; i++) { + + vwptr[i * 12 + 0] = lr[i * 2 + 0].x; + vwptr[i * 12 + 1] = lr[i * 2 + 0].y; + vwptr[i * 12 + 2] = POLY_HEIGHT; + + vwptr[i * 12 + 3] = lr[i * 2 + 1].x; + vwptr[i * 12 + 4] = lr[i * 2 + 1].y; + vwptr[i * 12 + 5] = POLY_HEIGHT; + + vwptr[i * 12 + 6] = lr[i * 2 + 1].x; + vwptr[i * 12 + 7] = lr[i * 2 + 1].y; + vwptr[i * 12 + 8] = -POLY_HEIGHT; + + vwptr[i * 12 + 9] = lr[i * 2 + 0].x; + vwptr[i * 12 + 10] = lr[i * 2 + 0].y; + vwptr[i * 12 + 11] = -POLY_HEIGHT; + + iwptr[i * 6 + 0] = i * 4 + 0; + iwptr[i * 6 + 1] = i * 4 + 1; + iwptr[i * 6 + 2] = i * 4 + 2; + + iwptr[i * 6 + 3] = i * 4 + 2; + iwptr[i * 6 + 4] = i * 4 + 3; + iwptr[i * 6 + 5] = i * 4 + 0; + } + } + + //if same buffer len is being set, just use BufferSubData to avoid a pipeline flush + + if (oc->vertex_array.is_null()) { + //create from scratch + //vertices + oc->vertex_buffer = RD::get_singleton()->vertex_buffer_create(lc * 6 * sizeof(real_t), geometry); + + Vector<RID> buffer; + buffer.push_back(oc->vertex_buffer); + oc->vertex_array = RD::get_singleton()->vertex_array_create(4 * lc / 2, shadow_render.vertex_format, buffer); + //indices + + oc->index_buffer = RD::get_singleton()->index_buffer_create(3 * lc, RD::INDEX_BUFFER_FORMAT_UINT16, indices); + oc->index_array = RD::get_singleton()->index_array_create(oc->index_buffer, 0, 3 * lc); + + } else { + //update existing + PoolVector<uint8_t>::Read vr = geometry.read(); + RD::get_singleton()->buffer_update(oc->vertex_buffer, 0, geometry.size(), vr.ptr()); + PoolVector<uint8_t>::Read ir = indices.read(); + RD::get_singleton()->buffer_update(oc->index_buffer, 0, indices.size(), ir.ptr()); + } + } +} +void RasterizerCanvasRD::occluder_polygon_set_cull_mode(RID p_occluder, VS::CanvasOccluderPolygonCullMode p_mode) { + OccluderPolygon *oc = occluder_polygon_owner.getornull(p_occluder); + ERR_FAIL_COND(!oc); + oc->cull_mode = p_mode; +} + void RasterizerCanvasRD::update() { _dispose_bindings(); } @@ -1422,6 +1906,59 @@ RasterizerCanvasRD::RasterizerCanvasRD(RasterizerStorageRD *p_storage) { shader.default_version_rd_shader = shader.canvas_shader.version_get_shader(shader.default_version, 0); } + { //shadow rendering + Vector<String> versions; + versions.push_back(String()); //no versions + shadow_render.shader.initialize(versions); + + { + Vector<RD::AttachmentFormat> attachments; + + RD::AttachmentFormat af_color; + af_color.format = RD::DATA_FORMAT_R32_SFLOAT; + af_color.usage_flags = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT; + + attachments.push_back(af_color); + + shadow_render.framebuffer_fix_format = RD::get_singleton()->framebuffer_format_create(attachments); + + RD::AttachmentFormat af_depth; + af_depth.format = RD::DATA_FORMAT_D24_UNORM_S8_UINT; + af_depth.format = RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_X8_D24_UNORM_PACK32, RD::TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) ? RD::DATA_FORMAT_X8_D24_UNORM_PACK32 : RD::DATA_FORMAT_D32_SFLOAT; + af_depth.usage_flags = RD::TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT; + + attachments.push_back(af_depth); + + shadow_render.framebuffer_format = RD::get_singleton()->framebuffer_format_create(attachments); + } + + //pipelines + Vector<RD::VertexDescription> vf; + RD::VertexDescription vd; + vd.format = RD::DATA_FORMAT_R32G32B32_SFLOAT; + vd.location = 0; + vd.offset = 0; + vd.stride = sizeof(float) * 3; + vf.push_back(vd); + shadow_render.vertex_format = RD::get_singleton()->vertex_format_create(vf); + + shadow_render.shader_version = shadow_render.shader.version_create(); + + for (int i = 0; i < 3; i++) { + RD::PipelineRasterizationState rs; + rs.cull_mode = i == 0 ? RD::POLYGON_CULL_DISABLED : (i == 1 ? RD::POLYGON_CULL_FRONT : RD::POLYGON_CULL_BACK); + RD::PipelineDepthStencilState ds; + ds.enable_depth_write = true; + ds.enable_depth_test = true; + ds.depth_compare_operator = RD::COMPARE_OP_LESS; + shadow_render.render_pipelines[i] = RD::get_singleton()->render_pipeline_create(shadow_render.shader.version_get_shader(shadow_render.shader_version, 0), shadow_render.framebuffer_format, shadow_render.vertex_format, RD::RENDER_PRIMITIVE_TRIANGLES, rs, RD::PipelineMultisampleState(), ds, RD::PipelineColorBlendState::create_disabled(), 0); + } + + shadow_render.shader_fix.initialize(versions); + shadow_render.shader_fix_version = shadow_render.shader_fix.version_create(); + shadow_render.shader_fix_pipeline = RD::get_singleton()->render_pipeline_create(shadow_render.shader_fix.version_get_shader(shadow_render.shader_fix_version, 0), shadow_render.framebuffer_fix_format, RD::INVALID_ID, RD::RENDER_PRIMITIVE_TRIANGLES, RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), RD::PipelineDepthStencilState(), RD::PipelineColorBlendState::create_disabled(), 0); + } + { //bindings bindings.id_generator = 0; //generate for 0 @@ -1429,6 +1966,7 @@ RasterizerCanvasRD::RasterizerCanvasRD(RasterizerStorageRD *p_storage) { { //state allocate state.canvas_state_buffer = RD::get_singleton()->uniform_buffer_create(sizeof(State::Buffer)); + state.lights_uniform_buffer = RD::get_singleton()->uniform_buffer_create(sizeof(LightUniform) * MAX_RENDER_LIGHTS); } } @@ -1491,6 +2029,27 @@ RasterizerCanvasRD::RasterizerCanvasRD(RasterizerStorageRD *p_storage) { ERR_FAIL_COND(sizeof(PushConstant) != 128); } +bool RasterizerCanvasRD::free(RID p_rid) { + + if (canvas_light_owner.owns(p_rid)) { + CanvasLight *cl = canvas_light_owner.getornull(p_rid); + ERR_FAIL_COND_V(!cl, false); + light_set_use_shadow(p_rid, false, 64); + canvas_light_owner.free(p_rid); + //canvas state uniform set needs updating + if (state.canvas_state_uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(state.canvas_state_uniform_set)) { + RD::get_singleton()->free(state.canvas_state_uniform_set); + } + } else if (occluder_polygon_owner.owns(p_rid)) { + occluder_polygon_set_shape_as_lines(p_rid, PoolVector<Vector2>()); + occluder_polygon_owner.free(p_rid); + } else { + return false; + } + + return true; +} + RasterizerCanvasRD::~RasterizerCanvasRD() { //canvas state diff --git a/servers/visual/rasterizer/rasterizer_canvas_rd.h b/servers/visual/rasterizer/rasterizer_canvas_rd.h index 91870a20fd..59193f2a68 100644 --- a/servers/visual/rasterizer/rasterizer_canvas_rd.h +++ b/servers/visual/rasterizer/rasterizer_canvas_rd.h @@ -5,6 +5,8 @@ #include "servers/visual/rasterizer/rasterizer_storage_rd.h" #include "servers/visual/rasterizer/render_pipeline_vertex_format_cache_rd.h" #include "servers/visual/rasterizer/shaders/canvas.glsl.gen.h" +#include "servers/visual/rasterizer/shaders/canvas_occlusion.glsl.gen.h" +#include "servers/visual/rasterizer/shaders/canvas_occlusion_fix.glsl.gen.h" #include "servers/visual/rendering_device.h" class RasterizerCanvasRD : public RasterizerCanvas { @@ -37,13 +39,37 @@ class RasterizerCanvasRD : public RasterizerCanvas { FLAGS_CLIP_RECT_UV = (1 << 9), FLAGS_TRANSPOSE_RECT = (1 << 10), + FLAGS_USING_LIGHT_MASK = (1 << 11), + FLAGS_NINEPACH_DRAW_CENTER = (1 << 12), FLAGS_USING_PARTICLES = (1 << 13), FLAGS_USE_PIXEL_SNAP = (1 << 14), FLAGS_USE_SKELETON = (1 << 15), FLAGS_NINEPATCH_H_MODE_SHIFT = 16, - FLAGS_NINEPATCH_V_MODE_SHIFT = 18 + FLAGS_NINEPATCH_V_MODE_SHIFT = 18, + FLAGS_LIGHT_COUNT_SHIFT = 20, + + FLAGS_DEFAULT_NORMAL_MAP_USED = (1 << 26), + FLAGS_DEFAULT_SPECULAR_MAP_USED = (1 << 27) + + }; + + enum { + LIGHT_FLAGS_TEXTURE_MASK = 0xFFFF, + LIGHT_FLAGS_BLEND_SHIFT = 16, + LIGHT_FLAGS_BLEND_MASK = (3 << 16), + LIGHT_FLAGS_BLEND_MODE_ADD = (0 << 16), + LIGHT_FLAGS_BLEND_MODE_SUB = (1 << 16), + LIGHT_FLAGS_BLEND_MODE_MIX = (2 << 16), + LIGHT_FLAGS_BLEND_MODE_MASK = (3 << 16) + }; + + enum { + MAX_RENDER_ITEMS = 256 * 1024, + MAX_LIGHT_TEXTURES = 1024, + MAX_LIGHTS_PER_ITEM = 16, + MAX_RENDER_LIGHTS = 256 }; /****************/ @@ -183,18 +209,66 @@ class RasterizerCanvasRD : public RasterizerCanvas { /**** LIGHTING ****/ /******************/ - enum { - LIGHT_GRID_WIDTH = 16, - LIGHT_GRID_HEIGHT = 16, - MAX_LIGHTS = 128 + struct CanvasLight { + + int32_t texture_index; + RID texture; + struct { + int size; + RID texture; + + RID render_depth; + RID render_fb[4]; + RID render_textures[4]; + RID fix_fb; + RID uniform_set; + + } shadow; }; + RID_Owner<CanvasLight> canvas_light_owner; + + struct ShadowRenderPushConstant { + float projection[16]; + float modelview[16]; + }; + + struct OccluderPolygon { + + VS::CanvasOccluderPolygonCullMode cull_mode; + int point_count; + RID vertex_buffer; + RID vertex_array; + RID index_buffer; + RID index_array; + }; + + struct LightUniform { + float matrix[8]; //light to texture coordinate matrix + float color[4]; + float shadow_color[4]; + float position[2]; + uint32_t flags; //index to light texture + float height; + float shadow_softness; + float shadow_pixel_size; + float pad[2]; + }; + + RID_Owner<OccluderPolygon> occluder_polygon_owner; + struct { - RID grid_texture; - RID grid_buffer; - PoolVector<uint8_t> grid_texture_data; - PoolVector<uint8_t> grid_buffer_data; - } lighting; + CanvasOcclusionShaderRD shader; + RID shader_version; + RID render_pipelines[3]; + RD::VertexFormatID vertex_format; + RD::FramebufferFormatID framebuffer_format; + + CanvasOcclusionFixShaderRD shader_fix; + RD::FramebufferFormatID framebuffer_fix_format; + RID shader_fix_version; + RID shader_fix_pipeline; + } shadow_render; /***************/ /**** STATE ****/ @@ -208,12 +282,16 @@ class RasterizerCanvasRD : public RasterizerCanvas { struct Buffer { float canvas_transform[16]; float screen_transform[16]; + float canvas_normal_transform[16]; + float canvas_modulate[4]; //uint32_t light_count; //uint32_t pad[3]; }; + + LightUniform light_uniforms[MAX_RENDER_LIGHTS]; + + RID lights_uniform_buffer; RID canvas_state_buffer; - //light buffer - RID canvas_state_light_buffer; //uniform set for all the above RID canvas_state_uniform_set; @@ -234,8 +312,8 @@ class RasterizerCanvasRD : public RasterizerCanvas { }; //primitive struct { - float points[6]; // vec2 points[4] - float uvs[6]; // vec2 points[4] + float points[6]; // vec2 points[3] + float uvs[6]; // vec2 points[3] uint32_t colors[6]; // colors encoded as half }; }; @@ -248,21 +326,19 @@ class RasterizerCanvasRD : public RasterizerCanvas { float skeleton_inverse[16]; }; - enum { - MAX_RENDER_ITEMS = 256 * 1024 - }; - Item *items[MAX_RENDER_ITEMS]; - Size2i _bind_texture_binding(TextureBindingID p_binding, RenderingDevice::DrawListID p_draw_list); - void _render_item(RenderingDevice::DrawListID p_draw_list, const Item *p_item, RenderTargetFormat p_render_target_format, RenderingDevice::TextureSamples p_samples, const Color &p_modulate, const Transform2D &p_canvas_transform_inverse, Item *¤t_clip); - void _render_items(RID p_to_render_target, int p_item_count, const Color &p_modulate, const Transform2D &p_transform); + Size2i _bind_texture_binding(TextureBindingID p_binding, RenderingDevice::DrawListID p_draw_list, uint32_t &flags); + void _render_item(RenderingDevice::DrawListID p_draw_list, const Item *p_item, RenderTargetFormat p_render_target_format, RenderingDevice::TextureSamples p_samples, const Transform2D &p_canvas_transform_inverse, Item *¤t_clip, Light *p_lights); + void _render_items(RID p_to_render_target, int p_item_count, const Transform2D &p_canvas_transform_inverse, Light *p_lights); - void _update_transform_2d_to_mat2x4(const Transform2D &p_transform, float *p_mat2x4); - void _update_transform_2d_to_mat2x3(const Transform2D &p_transform, float *p_mat2x3); + _FORCE_INLINE_ void _update_transform_2d_to_mat2x4(const Transform2D &p_transform, float *p_mat2x4); + _FORCE_INLINE_ void _update_transform_2d_to_mat2x3(const Transform2D &p_transform, float *p_mat2x3); - void _update_transform_2d_to_mat4(const Transform2D &p_transform, float *p_mat4); - void _update_transform_to_mat4(const Transform &p_transform, float *p_mat4); + _FORCE_INLINE_ void _update_transform_2d_to_mat4(const Transform2D &p_transform, float *p_mat4); + _FORCE_INLINE_ void _update_transform_to_mat4(const Transform &p_transform, float *p_mat4); + + _FORCE_INLINE_ void _update_specular_shininess(const Color &p_transform, uint32_t *r_ss); void _update_canvas_state_uniform_set(); @@ -273,21 +349,23 @@ public: PolygonID request_polygon(const Vector<int> &p_indices, const Vector<Point2> &p_points, const Vector<Color> &p_colors, const Vector<Point2> &p_uvs = Vector<Point2>(), const Vector<int> &p_bones = Vector<int>(), const Vector<float> &p_weights = Vector<float>()); void free_polygon(PolygonID p_polygon); - RID light_internal_create() { return RID(); } - void light_internal_update(RID p_rid, Light *p_light) {} - void light_internal_free(RID p_rid) {} + RID light_create(); + void light_set_texture(RID p_rid, RID p_texture); + void light_set_use_shadow(RID p_rid, bool p_enable, int p_resolution); + void light_update_shadow(RID p_rid, const Transform2D &p_light_xform, int p_light_mask, float p_near, float p_far, LightOccluderInstance *p_occluders); + + RID occluder_polygon_create(); + void occluder_polygon_set_shape_as_lines(RID p_occluder, const PoolVector<Vector2> &p_lines); + void occluder_polygon_set_cull_mode(RID p_occluder, VS::CanvasOccluderPolygonCullMode p_mode); void canvas_render_items(RID p_to_render_target, Item *p_item_list, const Color &p_modulate, Light *p_light_list, const Transform2D &p_canvas_transform); void canvas_debug_viewport_shadows(Light *p_lights_with_shadow){}; - void canvas_light_shadow_buffer_update(RID p_buffer, const Transform2D &p_light_xform, int p_light_mask, float p_near, float p_far, LightOccluderInstance *p_occluders, CameraMatrix *p_xform_cache) {} - - void reset_canvas() {} - void draw_window_margins(int *p_margins, RID *p_margin_textures) {} void update(); + bool free(RID p_rid); RasterizerCanvasRD(RasterizerStorageRD *p_storage); ~RasterizerCanvasRD(); }; diff --git a/servers/visual/rasterizer/rasterizer_storage_rd.h b/servers/visual/rasterizer/rasterizer_storage_rd.h index 4f81a4cce9..bb9e20861f 100644 --- a/servers/visual/rasterizer/rasterizer_storage_rd.h +++ b/servers/visual/rasterizer/rasterizer_storage_rd.h @@ -647,15 +647,6 @@ public: Size2 render_target_get_size(RID p_render_target); RID render_target_get_rd_framebuffer(RID p_render_target); - /* CANVAS SHADOW */ - - RID canvas_light_shadow_buffer_create(int p_width) { return RID(); } - - /* LIGHT SHADOW MAPPING */ - - RID canvas_light_occluder_create() { return RID(); } - void canvas_light_occluder_set_polylines(RID p_occluder, const PoolVector<Vector2> &p_lines) {} - VS::InstanceType get_base_type(RID p_rid) const { if (mesh_owner.owns(p_rid)) { return VS::INSTANCE_MESH; diff --git a/servers/visual/rasterizer/shaders/SCsub b/servers/visual/rasterizer/shaders/SCsub index 62a4c2a0ba..ef1df0c203 100644 --- a/servers/visual/rasterizer/shaders/SCsub +++ b/servers/visual/rasterizer/shaders/SCsub @@ -4,3 +4,5 @@ Import('env') if 'RD_GLSL' in env['BUILDERS']: env.RD_GLSL('canvas.glsl'); + env.RD_GLSL('canvas_occlusion.glsl'); + env.RD_GLSL('canvas_occlusion_fix.glsl'); diff --git a/servers/visual/rasterizer/shaders/canvas.glsl b/servers/visual/rasterizer/shaders/canvas.glsl index 734974ba81..6b1485c86b 100644 --- a/servers/visual/rasterizer/shaders/canvas.glsl +++ b/servers/visual/rasterizer/shaders/canvas.glsl @@ -23,6 +23,7 @@ layout(location = 7) in vec4 bone_weights_attrib; layout(location=0) out vec2 uv_interp; layout(location=1) out vec4 color_interp; +layout(location=2) out vec2 vertex_interp; #ifdef USE_NINEPATCH @@ -206,12 +207,12 @@ VERTEX_SHADER_CODE #endif #endif + vertex = (canvas_data.canvas_transform * vec4(vertex,0.0,1.0)).xy; + + vertex_interp = vertex; uv_interp = uv; -#if !defined(SKIP_TRANSFORM_USED) - gl_Position = (canvas_data.screen_transform * canvas_data.canvas_transform) * vec4(vertex,0.0,1.0); -#else - gl_Position = vec4(vertex,0.0,1.0); -#endif + + gl_Position = canvas_data.screen_transform * vec4(vertex,0.0,1.0); #ifdef USE_POINT_SIZE gl_PointSize=point_size; @@ -232,6 +233,7 @@ VERSION_DEFINES layout(location=0) in vec2 uv_interp; layout(location=1) in vec4 color_interp; +layout(location=2) in vec2 vertex_interp; #ifdef USE_NINEPATCH @@ -315,6 +317,7 @@ void main() { vec4 color = color_interp; vec2 uv = uv_interp; + vec2 vertex = vertex_interp; #if !defined(USE_ATTRIBUTES) && !defined(USE_PRIMITIVE) @@ -347,6 +350,8 @@ void main() { #endif + uint light_count = (draw_data.flags>>FLAGS_LIGHT_COUNT_SHIFT)&0xF; //max 16 lights + vec3 normal; @@ -357,18 +362,33 @@ void main() { bool normal_used = false; #endif -#if 0 - if (false /*normal_used || canvas_data.light_count > 0*/ ) { - normal.xy = texture(sampler2D(normal_texture,texture_sampler ), uv).xy * 2.0 - 1.0; + + if (normal_used || (light_count > 0 && bool(draw_data.flags&FLAGS_DEFAULT_NORMAL_MAP_USED))) { + normal.xy = texture(sampler2D(normal_texture,texture_sampler), uv).xy * vec2(2.0,-2.0) - vec2(1.0,-1.0); normal.z = sqrt(1.0 - dot(normal.xy, normal.xy)); normal_used = true; } else { -#endif normal = vec3(0.0, 0.0, 1.0); -#if 0 } + + vec4 specular_shininess; + +#if defined(SPECULAR_SHININESS_USED) + + bool specular_shininess_used = true; +#else + bool specular_shininess_used = false; #endif + if (specular_shininess_used || (light_count > 0 && normal_used && bool(draw_data.flags&FLAGS_DEFAULT_SPECULAR_MAP_USED))) { + specular_shininess = texture(sampler2D(specular_texture,texture_sampler ), uv); + specular_shininess *= unpackUnorm4x8(draw_data.specular_shininess); + specular_shininess_used=true; + } else { + specular_shininess = vec4(1.0); + } + + #if defined(SCREEN_UV_USED) vec2 screen_uv = gl_FragCoord.xy * screen_pixel_size; #endif @@ -392,13 +412,104 @@ FRAGMENT_SHADER_CODE #endif } -#if 0 - if (canvas_data.light_count > 0 ) { - //do lighting + if (normal_used) { + //convert by item transform + normal.xy = mat2(normalize(draw_data.world_x), normalize(draw_data.world_y)) * normal.xy; + //convert by canvas transform + normal = normalize((canvas_data.canvas_normal_transform * vec4(normal,0.0)).xyz); + } + + vec4 base_color=color; + if (bool(draw_data.flags&FLAGS_USING_LIGHT_MASK)) { + color=vec4(0.0); //inivisible by default due to using light mask } -#endif - //color.rgb *= color.a; + + color*=canvas_data.canvas_modulation; + + for(uint i=0;i<light_count;i++) { + uint light_base; + if (i<8) { + if (i<4) { + light_base=draw_data.lights[0]; + } else { + light_base=draw_data.lights[1]; + } + } else { + if (i<12) { + light_base=draw_data.lights[2]; + } else { + light_base=draw_data.lights[3]; + } + } + light_base>>=(i&3)*8; + light_base&=0xFF; + +#define LIGHT_FLAGS_BLEND_MASK (3<<16) +#define LIGHT_FLAGS_BLEND_MODE_ADD (0<<16) +#define LIGHT_FLAGS_BLEND_MODE_SUB (1<<16) +#define LIGHT_FLAGS_BLEND_MODE_MIX (2<<16) +#define LIGHT_FLAGS_BLEND_MODE_MASK (3<<16) + + + vec2 tex_uv = (vec4(vertex,0.0,1.0) * mat4(light_array.data[light_base].matrix[0],light_array.data[light_base].matrix[1],vec4(0.0,0.0,1.0,0.0),vec4(0.0,0.0,0.0,1.0))).xy; //multiply inverse given its transposed. Optimizer removes useless operations. + uint texture_idx = light_array.data[light_base].flags&LIGHT_FLAGS_TEXTURE_MASK; + vec4 light_color = texture(sampler2D(light_textures[texture_idx],texture_sampler),tex_uv); + vec4 light_base_color = light_array.data[light_base].color; + light_color.rgb*=light_base_color.rgb*light_base_color.a; + + if (normal_used) { + + vec3 light_pos = vec3(light_array.data[light_base].position,light_array.data[light_base].height); + vec3 pos = vec3(vertex,0.0); + vec3 light_vec = normalize(light_pos-pos); + float cNdotL = max(0.0,dot(normal,light_vec)); + + if (specular_shininess_used) { + //blinn + vec3 view = vec3(0.0,0.0,1.0);// not great but good enough + vec3 half_vec = normalize(view+light_vec); + + float cNdotV = max(dot(normal, view), 0.0); + float cNdotH = max(dot(normal, half_vec), 0.0); + float cVdotH = max(dot(view, half_vec), 0.0); + float cLdotH = max(dot(light_vec, half_vec), 0.0); + float shininess = exp2(15.0 * specular_shininess.a + 1.0) * 0.25; + float blinn = pow(cNdotH, shininess); + blinn *= (shininess + 8.0) * (1.0 / (8.0 * M_PI)); + float s = (blinn) / max(4.0 * cNdotV * cNdotL, 0.75); + + light_color.rgb = specular_shininess.rgb * light_base_color.rgb * s + light_color.rgb * cNdotL; + } else { + light_color.rgb *= cNdotL; + } + + } + + if (any(lessThan(tex_uv, vec2(0.0, 0.0))) || any(greaterThanEqual(tex_uv, vec2(1.0, 1.0)))) { + //if outside the light texture, light color is zero + light_color.a = 0.0; + } + + uint blend_mode = light_array.data[light_base].flags&LIGHT_FLAGS_BLEND_MASK; + + switch(blend_mode) { + case LIGHT_FLAGS_BLEND_MODE_ADD: { + color.rgb+=light_color.rgb*light_color.a; + } break; + case LIGHT_FLAGS_BLEND_MODE_SUB: { + color.rgb-=light_color.rgb*light_color.a; + } break; + case LIGHT_FLAGS_BLEND_MODE_MIX: { + color.rgb=mix(color.rgb,light_color.rgb,light_color.a); + } break; + case LIGHT_FLAGS_BLEND_MODE_MASK: { + light_color.a*=base_color.a; + color.rgb=mix(color.rgb,light_color.rgb,light_color.a); + } break; + } + } + frag_color = color; } diff --git a/servers/visual/rasterizer/shaders/canvas_occlusion.glsl b/servers/visual/rasterizer/shaders/canvas_occlusion.glsl new file mode 100644 index 0000000000..fb35f16971 --- /dev/null +++ b/servers/visual/rasterizer/shaders/canvas_occlusion.glsl @@ -0,0 +1,38 @@ +/* clang-format off */ +[vertex] +/* clang-format on */ + +#version 450 + +layout(location = 0) in highp vec3 vertex; + +layout(push_constant, binding = 0, std430) uniform Constants { + + mat4 modelview; + mat4 projection; +} constants; + +layout(location = 0) out highp float depth; + +void main() { + + highp vec4 vtx = (constants.modelview * vec4(vertex, 1.0)); + depth = length(vtx.xy); + + gl_Position = constants.projection * vtx; + +} + +/* clang-format off */ +[fragment] +/* clang-format on */ + +#version 450 + +layout(location = 0) in highp float depth; +layout(location = 0) out highp float distance_buf; + +void main() { + + distance_buf=depth; +} diff --git a/servers/visual/rasterizer/shaders/canvas_occlusion_fix.glsl b/servers/visual/rasterizer/shaders/canvas_occlusion_fix.glsl new file mode 100644 index 0000000000..48757bb68a --- /dev/null +++ b/servers/visual/rasterizer/shaders/canvas_occlusion_fix.glsl @@ -0,0 +1,56 @@ +/* clang-format off */ +[vertex] +/* clang-format on */ + +#version 450 + +layout(location = 0) out highp float u; + +void main() { + + if (gl_VertexIndex==0) { + u=0.0; + gl_Position=vec4(-1.0,-1.0,0.0,1.0); + } else if (gl_VertexIndex==1) { + u=0.0; + gl_Position=vec4(-1.0,1.0,0.0,1.0); + } else if (gl_VertexIndex==2) { + u=1.0; + gl_Position=vec4(1.0,1.0,0.0,1.0); + } else { + u=1.0; + gl_Position=vec4(1.0,-1.0,0.0,1.0); + } +} + +/* clang-format off */ +[fragment] +/* clang-format on */ + +#version 450 + +#define PI 3.14159265359 + +layout(set=0, binding=0) uniform sampler2D textures[4]; +layout(location = 0) in highp float u; +layout(location = 0) out highp float distance; + +void main() { + + //0-1 in the texture we are writing to represents a circle, 0-2PI) + //obtain the quarter circle from the source textures + highp float sub_angle = ((mod(u,0.25)/0.25)*2.0-1.0)*(PI/4.0); + highp float x=tan(sub_angle)*0.5+0.5; + + float depth; + if (u<0.25) { + depth=texture(textures[0],vec2(x,0.0)).x; + } else if (u<0.50) { + depth=texture(textures[1],vec2(x,0.0)).x; + } else if (u<0.75) { + depth=texture(textures[2],vec2(x,0.0)).x; + } else { + depth=texture(textures[3],vec2(x,0.0)).x; + } + distance=depth; +} diff --git a/servers/visual/rasterizer/shaders/canvas_uniforms_inc.glsl b/servers/visual/rasterizer/shaders/canvas_uniforms_inc.glsl index e205170292..cf8a17ce1e 100644 --- a/servers/visual/rasterizer/shaders/canvas_uniforms_inc.glsl +++ b/servers/visual/rasterizer/shaders/canvas_uniforms_inc.glsl @@ -1,8 +1,10 @@ /* SET0: Per draw primitive settings */ +#define M_PI 3.14159265359 -#define MAX_LIGHTS 128 +#define MAX_LIGHT_TEXTURES 1024 +#define MAX_RENDER_LIGHTS 256 #define FLAGS_INSTANCING_STRIDE_MASK 0xF #define FLAGS_INSTANCING_ENABLED (1<<4) @@ -13,16 +15,19 @@ #define FLAGS_CLIP_RECT_UV (1 << 9) #define FLAGS_TRANSPOSE_RECT (1 << 10) +#define FLAGS_USING_LIGHT_MASK (1 << 11) #define FLAGS_NINEPACH_DRAW_CENTER (1 << 12) #define FLAGS_USING_PARTICLES (1 << 13) #define FLAGS_USE_PIXEL_SNAP (1 << 14) - #define FLAGS_NINEPATCH_H_MODE_SHIFT 16 #define FLAGS_NINEPATCH_V_MODE_SHIFT 18 #define FLAGS_LIGHT_COUNT_SHIFT 20 +#define FLAGS_DEFAULT_NORMAL_MAP_USED (1 << 26) +#define FLAGS_DEFAULT_SPECULAR_MAP_USED (1 << 27) + layout(push_constant, binding = 0, std430) uniform DrawData { vec2 world_x; vec2 world_y; @@ -77,26 +82,35 @@ layout(set = 2, binding = 1, std140) uniform SkeletonData { layout(set = 3, binding = 0, std140) uniform CanvasData { mat4 canvas_transform; mat4 screen_transform; + mat4 canvas_normal_transform; + vec4 canvas_modulation; //uint light_count; } canvas_data; +#define LIGHT_FLAGS_TEXTURE_MASK 0xFFFF +#define LIGHT_FLAGS_BLEND_MASK (3<<16) +#define LIGHT_FLAGS_BLEND_MODE_ADD (0<<16) +#define LIGHT_FLAGS_BLEND_MODE_SUB (1<<16) +#define LIGHT_FLAGS_BLEND_MODE_MIX (2<<16) +#define LIGHT_FLAGS_BLEND_MODE_MASK (3<<16) + + struct Light { - // light matrices - mat4 light_matrix; - mat4 light_local_matrix; - mat4 shadow_matrix; - vec4 light_color; - vec4 light_shadow_color; - vec2 light_pos; - float shadowpixel_size; - float shadow_gradient; - float light_height; - float light_outside_alpha; - float shadow_distance_mult; + mat2x4 matrix; //light to texture coordinate matrix + vec4 color; + vec4 shadow_color; + vec2 position; + uint flags; //index to light texture + float height; + float shadow_softness; + float shadow_pixel_size; + float pad0; + float pad1; }; layout(set = 3, binding = 1, std140) uniform LightData { - Light lights[MAX_LIGHTS]; -} light_data; + Light data[MAX_RENDER_LIGHTS]; +} light_array; -layout(set = 3, binding = 2) uniform texture2D light_textures[MAX_LIGHTS]; +layout(set = 3, binding = 2) uniform texture2D light_textures[MAX_LIGHT_TEXTURES]; +layout(set = 3, binding = 3) uniform texture2D shadow_textures[MAX_LIGHT_TEXTURES]; diff --git a/servers/visual/rendering_device.h b/servers/visual/rendering_device.h index 5c530b4b3e..8f0578b874 100644 --- a/servers/visual/rendering_device.h +++ b/servers/visual/rendering_device.h @@ -554,7 +554,7 @@ public: virtual RID uniform_set_create(const Vector<Uniform> &p_uniforms, RID p_shader, uint32_t p_shader_set) = 0; virtual bool uniform_set_is_valid(RID p_uniform_set) = 0; - virtual Error buffer_update(RID p_buffer, uint32_t p_offset, uint32_t p_size, void *p_data, bool p_sync_with_draw = false) = 0; //this function can be used from any thread and it takes effect at the begining of the frame, unless sync with draw is used, which is used to mix updates with draw calls + virtual Error buffer_update(RID p_buffer, uint32_t p_offset, uint32_t p_size,const void *p_data, bool p_sync_with_draw = false) = 0; //this function can be used from any thread and it takes effect at the begining of the frame, unless sync with draw is used, which is used to mix updates with draw calls /*************************/ /**** RENDER PIPELINE ****/ diff --git a/servers/visual/visual_server_canvas.cpp b/servers/visual/visual_server_canvas.cpp index 6701f12351..9854fa5491 100644 --- a/servers/visual/visual_server_canvas.cpp +++ b/servers/visual/visual_server_canvas.cpp @@ -502,7 +502,7 @@ void VisualServerCanvas::canvas_item_add_line(RID p_item, const Point2 &p_from, line->points[0] = p_from; line->points[1] = p_to; } - for (int i = 0; i < line->point_count; i++) { + for (uint32_t i = 0; i < line->point_count; i++) { line->colors[i] = p_color; } line->specular_shininess = Color(1, 1, 1, 1); @@ -1004,7 +1004,7 @@ void VisualServerCanvas::canvas_item_set_use_parent_material(RID p_item, bool p_ RID VisualServerCanvas::canvas_light_create() { RasterizerCanvas::Light *clight = memnew(RasterizerCanvas::Light); - clight->light_internal = VSG::canvas_render->light_internal_create(); + clight->light_internal = VSG::canvas_render->light_create(); return canvas_light_owner.make_rid(clight); } void VisualServerCanvas::canvas_light_attach_to_canvas(RID p_light, RID p_canvas) { @@ -1057,6 +1057,7 @@ void VisualServerCanvas::canvas_light_set_texture(RID p_light, RID p_texture) { ERR_FAIL_COND(!clight); clight->texture = p_texture; + VSG::canvas_render->light_set_texture(clight->light_internal, p_texture); } void VisualServerCanvas::canvas_light_set_texture_offset(RID p_light, const Vector2 &p_offset) { @@ -1129,15 +1130,14 @@ void VisualServerCanvas::canvas_light_set_shadow_enabled(RID p_light, bool p_ena RasterizerCanvas::Light *clight = canvas_light_owner.getornull(p_light); ERR_FAIL_COND(!clight); - if (clight->shadow_buffer.is_valid() == p_enabled) + if (clight->use_shadow == p_enabled) { return; - if (p_enabled) { - clight->shadow_buffer = VSG::storage->canvas_light_shadow_buffer_create(clight->shadow_buffer_size); - } else { - VSG::storage->free(clight->shadow_buffer); - clight->shadow_buffer = RID(); } + clight->use_shadow = p_enabled; + + VSG::canvas_render->light_set_use_shadow(clight->light_internal, clight->use_shadow, clight->shadow_buffer_size); } + void VisualServerCanvas::canvas_light_set_shadow_buffer_size(RID p_light, int p_size) { ERR_FAIL_COND(p_size < 32 || p_size > 16384); @@ -1151,10 +1151,7 @@ void VisualServerCanvas::canvas_light_set_shadow_buffer_size(RID p_light, int p_ clight->shadow_buffer_size = next_power_of_2(p_size); - if (clight->shadow_buffer.is_valid()) { - VSG::storage->free(clight->shadow_buffer); - clight->shadow_buffer = VSG::storage->canvas_light_shadow_buffer_create(clight->shadow_buffer_size); - } + VSG::canvas_render->light_set_use_shadow(clight->light_internal, clight->use_shadow, clight->shadow_buffer_size); } void VisualServerCanvas::canvas_light_set_shadow_gradient_length(RID p_light, float p_length) { @@ -1236,7 +1233,7 @@ void VisualServerCanvas::canvas_light_occluder_set_polygon(RID p_occluder, RID p } occluder->polygon = p_polygon; - occluder->polygon_buffer = RID(); + occluder->occluder = RID(); if (occluder->polygon.is_valid()) { LightOccluderPolygon *occluder_poly = canvas_light_occluder_polygon_owner.getornull(p_polygon); @@ -1245,7 +1242,7 @@ void VisualServerCanvas::canvas_light_occluder_set_polygon(RID p_occluder, RID p ERR_FAIL_COND(!occluder_poly); } else { occluder_poly->owners.insert(occluder); - occluder->polygon_buffer = occluder_poly->occluder; + occluder->occluder = occluder_poly->occluder; occluder->aabb_cache = occluder_poly->aabb; occluder->cull_cache = occluder_poly->cull_mode; } @@ -1269,7 +1266,7 @@ void VisualServerCanvas::canvas_light_occluder_set_light_mask(RID p_occluder, in RID VisualServerCanvas::canvas_occluder_polygon_create() { LightOccluderPolygon *occluder_poly = memnew(LightOccluderPolygon); - occluder_poly->occluder = VSG::storage->canvas_light_occluder_create(); + occluder_poly->occluder = VSG::canvas_render->occluder_polygon_create(); return canvas_light_occluder_polygon_owner.make_rid(occluder_poly); } void VisualServerCanvas::canvas_occluder_polygon_set_shape(RID p_occluder_polygon, const PoolVector<Vector2> &p_shape, bool p_closed) { @@ -1320,7 +1317,7 @@ void VisualServerCanvas::canvas_occluder_polygon_set_shape_as_lines(RID p_occlud } } - VSG::storage->canvas_light_occluder_set_polylines(occluder_poly->occluder, p_shape); + VSG::canvas_render->occluder_polygon_set_shape_as_lines(occluder_poly->occluder, p_shape); for (Set<RasterizerCanvas::LightOccluderInstance *>::Element *E = occluder_poly->owners.front(); E; E = E->next()) { E->get()->aabb_cache = occluder_poly->aabb; } @@ -1331,6 +1328,7 @@ void VisualServerCanvas::canvas_occluder_polygon_set_cull_mode(RID p_occluder_po LightOccluderPolygon *occluder_poly = canvas_light_occluder_polygon_owner.getornull(p_occluder_polygon); ERR_FAIL_COND(!occluder_poly); occluder_poly->cull_mode = p_mode; + VSG::canvas_render->occluder_polygon_set_cull_mode(occluder_poly->occluder, p_mode); for (Set<RasterizerCanvas::LightOccluderInstance *>::Element *E = occluder_poly->owners.front(); E; E = E->next()) { E->get()->cull_cache = p_mode; } @@ -1422,10 +1420,7 @@ bool VisualServerCanvas::free(RID p_rid) { canvas->lights.erase(canvas_light); } - if (canvas_light->shadow_buffer.is_valid()) - VSG::storage->free(canvas_light->shadow_buffer); - - VSG::canvas_render->light_internal_free(canvas_light->light_internal); + VSG::canvas_render->free(canvas_light->light_internal); canvas_light_owner.free(p_rid); memdelete(canvas_light); @@ -1456,7 +1451,7 @@ bool VisualServerCanvas::free(RID p_rid) { LightOccluderPolygon *occluder_poly = canvas_light_occluder_polygon_owner.getornull(p_rid); ERR_FAIL_COND_V(!occluder_poly, true); - VSG::storage->free(occluder_poly->occluder); + VSG::canvas_render->free(occluder_poly->occluder); while (occluder_poly->owners.size()) { diff --git a/servers/visual/visual_server_viewport.cpp b/servers/visual/visual_server_viewport.cpp index 3add544cf3..d96f7c3652 100644 --- a/servers/visual/visual_server_viewport.cpp +++ b/servers/visual/visual_server_viewport.cpp @@ -149,13 +149,13 @@ void VisualServerViewport::_draw_viewport(Viewport *p_viewport, ARVRInterface::E cl->filter_next_ptr = lights; lights = cl; - cl->texture_cache = NULL; + // 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->light_shader_xform = cl->xform * scale; + //cl->light_shader_pos = cl->xform_cache[2]; + if (cl->use_shadow) { cl->shadows_next_ptr = lights_with_shadow; if (lights_with_shadow == NULL) { @@ -174,7 +174,8 @@ void VisualServerViewport::_draw_viewport(Viewport *p_viewport, ARVRInterface::E light_count++; } - VSG::canvas_render->light_internal_update(cl->light_internal, cl); + //guess this is not needed, but keeping because it may be + //VSG::canvas_render->light_internal_update(cl->light_internal, cl); } } @@ -208,7 +209,7 @@ void VisualServerViewport::_draw_viewport(Viewport *p_viewport, ARVRInterface::E 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_shadow_mask, light->radius_cache / 1000.0, light->radius_cache * 1.1, occluders, &light->shadow_matrix_cache); + VSG::canvas_render->light_update_shadow(light->light_internal, light->xform_cache.affine_inverse(), light->item_shadow_mask, light->radius_cache / 1000.0, light->radius_cache * 1.1, occluders); light = light->shadows_next_ptr; } |