diff options
Diffstat (limited to 'drivers/gles3')
-rw-r--r-- | drivers/gles3/rasterizer_canvas_gles3.cpp | 113 | ||||
-rw-r--r-- | drivers/gles3/rasterizer_canvas_gles3.h | 7 | ||||
-rw-r--r-- | drivers/gles3/rasterizer_gles3.cpp | 50 | ||||
-rw-r--r-- | drivers/gles3/rasterizer_scene_gles3.cpp | 7 | ||||
-rw-r--r-- | drivers/gles3/rasterizer_storage_gles3.cpp | 67 | ||||
-rw-r--r-- | drivers/gles3/rasterizer_storage_gles3.h | 4 | ||||
-rw-r--r-- | drivers/gles3/shader_compiler_gles3.cpp | 1 | ||||
-rw-r--r-- | drivers/gles3/shaders/canvas.glsl | 58 | ||||
-rw-r--r-- | drivers/gles3/shaders/scene.glsl | 6 | ||||
-rw-r--r-- | drivers/gles3/shaders/tonemap.glsl | 4 |
10 files changed, 302 insertions, 15 deletions
diff --git a/drivers/gles3/rasterizer_canvas_gles3.cpp b/drivers/gles3/rasterizer_canvas_gles3.cpp index c33fdaa355..bb4c8ab4d7 100644 --- a/drivers/gles3/rasterizer_canvas_gles3.cpp +++ b/drivers/gles3/rasterizer_canvas_gles3.cpp @@ -160,6 +160,7 @@ void RasterizerCanvasGLES3::canvas_begin() { state.canvas_shader.set_conditional(CanvasShaderGLES3::SHADOW_FILTER_PCF13, false); state.canvas_shader.set_conditional(CanvasShaderGLES3::USE_DISTANCE_FIELD, false); state.canvas_shader.set_conditional(CanvasShaderGLES3::USE_NINEPATCH, false); + state.canvas_shader.set_conditional(CanvasShaderGLES3::USE_SKELETON, false); state.canvas_shader.set_custom_shader(0); state.canvas_shader.bind(); @@ -180,6 +181,7 @@ void RasterizerCanvasGLES3::canvas_begin() { glBindVertexArray(data.canvas_quad_array); state.using_texture_rect = true; state.using_ninepatch = false; + state.using_skeleton = false; } void RasterizerCanvasGLES3::canvas_end() { @@ -191,11 +193,11 @@ void RasterizerCanvasGLES3::canvas_end() { state.using_ninepatch = false; } -RasterizerStorageGLES3::Texture *RasterizerCanvasGLES3::_bind_canvas_texture(const RID &p_texture, const RID &p_normal_map) { +RasterizerStorageGLES3::Texture *RasterizerCanvasGLES3::_bind_canvas_texture(const RID &p_texture, const RID &p_normal_map, bool p_force) { RasterizerStorageGLES3::Texture *tex_return = NULL; - if (p_texture == state.current_tex) { + if (p_texture == state.current_tex && !p_force) { tex_return = state.current_tex_ptr; } else if (p_texture.is_valid()) { @@ -230,7 +232,7 @@ RasterizerStorageGLES3::Texture *RasterizerCanvasGLES3::_bind_canvas_texture(con state.current_tex_ptr = NULL; } - if (p_normal_map == state.current_normal) { + if (p_normal_map == state.current_normal && !p_force) { //do none state.canvas_shader.set_uniform(CanvasShaderGLES3::USE_DEFAULT_NORMAL, state.current_normal.is_valid()); @@ -284,6 +286,10 @@ void RasterizerCanvasGLES3::_set_texture_rect_mode(bool p_enable, bool p_ninepat state.canvas_shader.set_uniform(CanvasShaderGLES3::FINAL_MODULATE, state.canvas_item_modulate); state.canvas_shader.set_uniform(CanvasShaderGLES3::MODELVIEW_MATRIX, state.final_transform); state.canvas_shader.set_uniform(CanvasShaderGLES3::EXTRA_MATRIX, state.extra_matrix); + if (state.using_skeleton) { + state.canvas_shader.set_uniform(CanvasShaderGLES3::SKELETON_TRANSFORM, state.skeleton_transform); + state.canvas_shader.set_uniform(CanvasShaderGLES3::SKELETON_TRANSFORM_INVERSE, state.skeleton_transform_inverse); + } if (storage->frame.current_rt) { state.canvas_shader.set_uniform(CanvasShaderGLES3::SCREEN_PIXEL_SIZE, Vector2(1.0 / storage->frame.current_rt->width, 1.0 / storage->frame.current_rt->height)); } else { @@ -293,7 +299,7 @@ void RasterizerCanvasGLES3::_set_texture_rect_mode(bool p_enable, bool p_ninepat state.using_ninepatch = p_ninepatch; } -void RasterizerCanvasGLES3::_draw_polygon(const int *p_indices, int p_index_count, int p_vertex_count, const Vector2 *p_vertices, const Vector2 *p_uvs, const Color *p_colors, bool p_singlecolor) { +void RasterizerCanvasGLES3::_draw_polygon(const int *p_indices, int p_index_count, int p_vertex_count, const Vector2 *p_vertices, const Vector2 *p_uvs, const Color *p_colors, bool p_singlecolor, const int *p_bones, const float *p_weights) { glBindVertexArray(data.polygon_buffer_pointer_array); glBindBuffer(GL_ARRAY_BUFFER, data.polygon_buffer); @@ -301,11 +307,17 @@ void RasterizerCanvasGLES3::_draw_polygon(const int *p_indices, int p_index_coun uint32_t buffer_ofs = 0; //vertex +#ifdef DEBUG_ENABLED + ERR_FAIL_COND(buffer_ofs > data.polygon_buffer_size); +#endif glBufferSubData(GL_ARRAY_BUFFER, buffer_ofs, sizeof(Vector2) * p_vertex_count, p_vertices); glEnableVertexAttribArray(VS::ARRAY_VERTEX); glVertexAttribPointer(VS::ARRAY_VERTEX, 2, GL_FLOAT, false, sizeof(Vector2), ((uint8_t *)0) + buffer_ofs); buffer_ofs += sizeof(Vector2) * p_vertex_count; //color +#ifdef DEBUG_ENABLED + ERR_FAIL_COND(buffer_ofs > data.polygon_buffer_size); +#endif if (p_singlecolor) { glDisableVertexAttribArray(VS::ARRAY_COLOR); @@ -322,6 +334,10 @@ void RasterizerCanvasGLES3::_draw_polygon(const int *p_indices, int p_index_coun buffer_ofs += sizeof(Color) * p_vertex_count; } +#ifdef DEBUG_ENABLED + ERR_FAIL_COND(buffer_ofs > data.polygon_buffer_size); +#endif + if (p_uvs) { glBufferSubData(GL_ARRAY_BUFFER, buffer_ofs, sizeof(Vector2) * p_vertex_count, p_uvs); @@ -333,6 +349,32 @@ void RasterizerCanvasGLES3::_draw_polygon(const int *p_indices, int p_index_coun glDisableVertexAttribArray(VS::ARRAY_TEX_UV); } +#ifdef DEBUG_ENABLED + ERR_FAIL_COND(buffer_ofs > data.polygon_buffer_size); +#endif + + if (p_bones && p_weights) { + + glBufferSubData(GL_ARRAY_BUFFER, buffer_ofs, sizeof(int) * 4 * p_vertex_count, p_bones); + glEnableVertexAttribArray(VS::ARRAY_BONES); + //glVertexAttribPointer(VS::ARRAY_BONES, 4, GL_UNSIGNED_INT, false, sizeof(int) * 4, ((uint8_t *)0) + buffer_ofs); + glVertexAttribIPointer(VS::ARRAY_BONES, 4, GL_UNSIGNED_INT, sizeof(int) * 4, ((uint8_t *)0) + buffer_ofs); + buffer_ofs += sizeof(int) * 4 * p_vertex_count; + + glBufferSubData(GL_ARRAY_BUFFER, buffer_ofs, sizeof(float) * 4 * p_vertex_count, p_weights); + glEnableVertexAttribArray(VS::ARRAY_WEIGHTS); + glVertexAttribPointer(VS::ARRAY_WEIGHTS, 4, GL_FLOAT, false, sizeof(float) * 4, ((uint8_t *)0) + buffer_ofs); + buffer_ofs += sizeof(float) * 4 * p_vertex_count; + + } else if (state.using_skeleton) { + glVertexAttribI4ui(VS::ARRAY_BONES, 0, 0, 0, 0); + glVertexAttrib4f(VS::ARRAY_WEIGHTS, 0, 0, 0, 0); + } + +#ifdef DEBUG_ENABLED + ERR_FAIL_COND(buffer_ofs > data.polygon_buffer_size); +#endif + //bind the indices buffer. glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, data.polygon_index_buffer); glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, sizeof(int) * p_index_count, p_indices); @@ -342,6 +384,12 @@ void RasterizerCanvasGLES3::_draw_polygon(const int *p_indices, int p_index_coun storage->frame.canvas_draw_commands++; + if (p_bones && p_weights) { + //not used so often, so disable when used + glDisableVertexAttribArray(VS::ARRAY_BONES); + glDisableVertexAttribArray(VS::ARRAY_WEIGHTS); + } + glBindVertexArray(0); } @@ -735,7 +783,8 @@ void RasterizerCanvasGLES3::_canvas_item_render_commands(Item *p_item, Item *cur Size2 texpixel_size(1.0 / texture->width, 1.0 / texture->height); state.canvas_shader.set_uniform(CanvasShaderGLES3::COLOR_TEXPIXEL_SIZE, texpixel_size); } - _draw_polygon(polygon->indices.ptr(), polygon->count, polygon->points.size(), polygon->points.ptr(), polygon->uvs.ptr(), polygon->colors.ptr(), polygon->colors.size() == 1); + + _draw_polygon(polygon->indices.ptr(), polygon->count, polygon->points.size(), polygon->points.ptr(), polygon->uvs.ptr(), polygon->colors.ptr(), polygon->colors.size() == 1, polygon->bones.ptr(), polygon->weights.ptr()); #ifdef GLES_OVER_GL if (polygon->antialiased) { glEnable(GL_LINE_SMOOTH); @@ -921,7 +970,7 @@ void RasterizerCanvasGLES3::_canvas_item_render_commands(Item *p_item, Item *cur } _bind_canvas_texture(RID(), RID()); - _draw_polygon(indices, numpoints * 3, numpoints + 1, points, NULL, &circle->color, true); + _draw_polygon(indices, numpoints * 3, numpoints + 1, points, NULL, &circle->color, true, NULL, NULL); //_draw_polygon(numpoints*3,indices,points,NULL,&circle->color,RID(),true); //canvas_draw_circle(circle->indices.size(),circle->indices.ptr(),circle->points.ptr(),circle->uvs.ptr(),circle->colors.ptr(),circle->texture,circle->colors.size()==1); @@ -1037,7 +1086,7 @@ void RasterizerCanvasGLES3::_copy_texscreen(const Rect2 &p_rect) { state.using_texture_rect = true; _set_texture_rect_mode(false); - _bind_canvas_texture(state.current_tex, state.current_normal); + _bind_canvas_texture(state.current_tex, state.current_normal, true); glEnable(GL_BLEND); } @@ -1068,6 +1117,7 @@ void RasterizerCanvasGLES3::canvas_render_items(Item *p_item_list, int p_z, cons RID canvas_last_material; bool prev_distance_field = false; + bool prev_use_skeleton = false; while (p_item_list) { @@ -1106,6 +1156,36 @@ void RasterizerCanvasGLES3::canvas_render_items(Item *p_item_list, int p_z, cons } } + RasterizerStorageGLES3::Skeleton *skeleton = NULL; + + { + //skeleton handling + if (ci->skeleton.is_valid()) { + skeleton = storage->skeleton_owner.getornull(ci->skeleton); + if (!skeleton->use_2d) { + skeleton = NULL; + } else { + state.skeleton_transform = p_transform * skeleton->base_transform_2d; + state.skeleton_transform_inverse = state.skeleton_transform.affine_inverse(); + } + } + + bool use_skeleton = skeleton != NULL; + if (prev_use_skeleton != use_skeleton) { + rebind_shader = true; + state.canvas_shader.set_conditional(CanvasShaderGLES3::USE_SKELETON, use_skeleton); + prev_use_skeleton = use_skeleton; + } + + if (skeleton) { + glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 1); + glBindTexture(GL_TEXTURE_2D, skeleton->texture); + state.using_skeleton = true; + } else { + state.using_skeleton = false; + } + } + //begin rect Item *material_owner = ci->material_owner ? ci->material_owner : ci; @@ -1130,6 +1210,9 @@ void RasterizerCanvasGLES3::canvas_render_items(Item *p_item_list, int p_z, cons if (shader_ptr->canvas_item.uses_screen_texture && !state.canvas_texscreen_used) { //copy if not copied before _copy_texscreen(Rect2()); + + // blend mode will have been enabled so make sure we disable it again later on + last_blend_mode = last_blend_mode != RasterizerStorageGLES3::Shader::CanvasItem::BLEND_MODE_DISABLED ? last_blend_mode : -1; } if (shader_ptr != shader_cache) { @@ -1201,14 +1284,30 @@ void RasterizerCanvasGLES3::canvas_render_items(Item *p_item_list, int p_z, cons } int blend_mode = shader_cache ? shader_cache->canvas_item.blend_mode : RasterizerStorageGLES3::Shader::CanvasItem::BLEND_MODE_MIX; + if (blend_mode == RasterizerStorageGLES3::Shader::CanvasItem::BLEND_MODE_DISABLED && (!storage->frame.current_rt || !storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_TRANSPARENT])) { + blend_mode = RasterizerStorageGLES3::Shader::CanvasItem::BLEND_MODE_MIX; + } bool unshaded = shader_cache && (shader_cache->canvas_item.light_mode == RasterizerStorageGLES3::Shader::CanvasItem::LIGHT_MODE_UNSHADED || blend_mode != RasterizerStorageGLES3::Shader::CanvasItem::BLEND_MODE_MIX); bool reclip = false; if (last_blend_mode != blend_mode) { + if (last_blend_mode == RasterizerStorageGLES3::Shader::CanvasItem::BLEND_MODE_DISABLED) { + // re-enable it + glEnable(GL_BLEND); + } else if (blend_mode == RasterizerStorageGLES3::Shader::CanvasItem::BLEND_MODE_DISABLED) { + // disable it + glDisable(GL_BLEND); + } switch (blend_mode) { + case RasterizerStorageGLES3::Shader::CanvasItem::BLEND_MODE_DISABLED: { + + // nothing to do here + + } break; case RasterizerStorageGLES3::Shader::CanvasItem::BLEND_MODE_MIX: { + glBlendEquation(GL_FUNC_ADD); if (storage->frame.current_rt && storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_TRANSPARENT]) { glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA); diff --git a/drivers/gles3/rasterizer_canvas_gles3.h b/drivers/gles3/rasterizer_canvas_gles3.h index 1dc17f98d5..c7f2e54efb 100644 --- a/drivers/gles3/rasterizer_canvas_gles3.h +++ b/drivers/gles3/rasterizer_canvas_gles3.h @@ -84,6 +84,9 @@ public: Color canvas_item_modulate; Transform2D extra_matrix; Transform2D final_transform; + bool using_skeleton; + Transform2D skeleton_transform; + Transform2D skeleton_transform_inverse; } state; @@ -120,10 +123,10 @@ public: virtual void canvas_end(); _FORCE_INLINE_ void _set_texture_rect_mode(bool p_enable, bool p_ninepatch = false); - _FORCE_INLINE_ RasterizerStorageGLES3::Texture *_bind_canvas_texture(const RID &p_texture, const RID &p_normal_map); + _FORCE_INLINE_ RasterizerStorageGLES3::Texture *_bind_canvas_texture(const RID &p_texture, const RID &p_normal_map, bool p_force = false); _FORCE_INLINE_ void _draw_gui_primitive(int p_points, const Vector2 *p_vertices, const Color *p_colors, const Vector2 *p_uvs); - _FORCE_INLINE_ void _draw_polygon(const int *p_indices, int p_index_count, int p_vertex_count, const Vector2 *p_vertices, const Vector2 *p_uvs, const Color *p_colors, bool p_singlecolor); + _FORCE_INLINE_ void _draw_polygon(const int *p_indices, int p_index_count, int p_vertex_count, const Vector2 *p_vertices, const Vector2 *p_uvs, const Color *p_colors, bool p_singlecolor, const int *p_bones, const float *p_weights); _FORCE_INLINE_ void _draw_generic(GLuint p_primitive, int p_vertex_count, const Vector2 *p_vertices, const Vector2 *p_uvs, const Color *p_colors, bool p_singlecolor); _FORCE_INLINE_ void _canvas_item_render_commands(Item *p_item, Item *current_clip, bool &reclip); diff --git a/drivers/gles3/rasterizer_gles3.cpp b/drivers/gles3/rasterizer_gles3.cpp index ca39d9f966..1abdaa5f80 100644 --- a/drivers/gles3/rasterizer_gles3.cpp +++ b/drivers/gles3/rasterizer_gles3.cpp @@ -111,8 +111,6 @@ static void GLAPIENTRY _gl_debug_print(GLenum source, GLenum type, GLuint id, GL strcpy(debType, "Portability"); else if (type == _EXT_DEBUG_TYPE_PERFORMANCE_ARB) strcpy(debType, "Performance"); - else if (type == _EXT_DEBUG_TYPE_OTHER_ARB) - strcpy(debType, "Other"); if (severity == _EXT_DEBUG_SEVERITY_HIGH_ARB) strcpy(debSev, "High"); @@ -292,7 +290,11 @@ void RasterizerGLES3::set_boot_image(const Ref<Image> &p_image, const Color &p_c glViewport(0, 0, window_w, window_h); glDisable(GL_BLEND); glDepthMask(GL_FALSE); - glClearColor(p_color.r, p_color.g, p_color.b, 1.0); + if (OS::get_singleton()->get_window_per_pixel_transparency_enabled()) { + glClearColor(0.0, 0.0, 0.0, 0.0); + } else { + glClearColor(p_color.r, p_color.g, p_color.b, 1.0); + } glClear(GL_COLOR_BUFFER_BIT); canvas->canvas_begin(); @@ -331,6 +333,27 @@ void RasterizerGLES3::set_boot_image(const Ref<Image> &p_image, const Color &p_c storage->free(texture); // free since it's only one frame that stays there + if (OS::get_singleton()->is_layered_allowed()) { + if (OS::get_singleton()->get_window_per_pixel_transparency_enabled()) { +#if (defined WINDOWS_ENABLED) && !(defined UWP_ENABLED) + Size2 wndsize = OS::get_singleton()->get_layered_buffer_size(); + uint8_t *data = OS::get_singleton()->get_layered_buffer_data(); + if (data) { + glReadPixels(0, 0, wndsize.x, wndsize.y, GL_BGRA, GL_UNSIGNED_BYTE, data); + OS::get_singleton()->swap_layered_buffer(); + + return; + } +#endif + } else { + //clear alpha + glColorMask(false, false, false, true); + glClearColor(0, 0, 0, 1); + glClear(GL_COLOR_BUFFER_BIT); + glColorMask(true, true, true, true); + } + } + OS::get_singleton()->swap_buffers(); } @@ -367,6 +390,27 @@ void RasterizerGLES3::blit_render_target_to_screen(RID p_render_target, const Re void RasterizerGLES3::end_frame(bool p_swap_buffers) { + if (OS::get_singleton()->is_layered_allowed()) { + if (OS::get_singleton()->get_window_per_pixel_transparency_enabled()) { +#if (defined WINDOWS_ENABLED) && !(defined UWP_ENABLED) + Size2 wndsize = OS::get_singleton()->get_layered_buffer_size(); + uint8_t *data = OS::get_singleton()->get_layered_buffer_data(); + if (data) { + glReadPixels(0, 0, wndsize.x, wndsize.y, GL_BGRA, GL_UNSIGNED_BYTE, data); + OS::get_singleton()->swap_layered_buffer(); + + return; + } +#endif + } else { + //clear alpha + glColorMask(false, false, false, true); + glClearColor(0, 0, 0, 1); + glClear(GL_COLOR_BUFFER_BIT); + glColorMask(true, true, true, true); + } + } + if (p_swap_buffers) OS::get_singleton()->swap_buffers(); else diff --git a/drivers/gles3/rasterizer_scene_gles3.cpp b/drivers/gles3/rasterizer_scene_gles3.cpp index 5b6b3d44f2..8da2c2f9c2 100644 --- a/drivers/gles3/rasterizer_scene_gles3.cpp +++ b/drivers/gles3/rasterizer_scene_gles3.cpp @@ -2362,7 +2362,11 @@ void RasterizerSceneGLES3::_draw_sky(RasterizerStorageGLES3::Sky *p_sky, const C ERR_FAIL_COND(!tex); glActiveTexture(GL_TEXTURE0); - glBindTexture(tex->target, tex->tex_id); + + if (tex->proxy && tex->proxy->tex_id) + glBindTexture(tex->target, tex->proxy->tex_id); + else + glBindTexture(tex->target, tex->tex_id); if (storage->config.srgb_decode_supported && tex->srgb && !tex->using_srgb) { @@ -3906,6 +3910,7 @@ void RasterizerSceneGLES3::_post_process(Environment *env, const CameraMatrix &p state.tonemap_shader.set_conditional(TonemapShaderGLES3::USE_FILMIC_TONEMAPPER, env->tone_mapper == VS::ENV_TONE_MAPPER_FILMIC); state.tonemap_shader.set_conditional(TonemapShaderGLES3::USE_ACES_TONEMAPPER, env->tone_mapper == VS::ENV_TONE_MAPPER_ACES); state.tonemap_shader.set_conditional(TonemapShaderGLES3::USE_REINDHART_TONEMAPPER, env->tone_mapper == VS::ENV_TONE_MAPPER_REINHARDT); + state.tonemap_shader.set_conditional(TonemapShaderGLES3::KEEP_3D_LINEAR, storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_KEEP_3D_LINEAR]); state.tonemap_shader.set_conditional(TonemapShaderGLES3::USE_AUTO_EXPOSURE, env->auto_exposure); state.tonemap_shader.set_conditional(TonemapShaderGLES3::USE_GLOW_FILTER_BICUBIC, env->glow_bicubic_upscale); diff --git a/drivers/gles3/rasterizer_storage_gles3.cpp b/drivers/gles3/rasterizer_storage_gles3.cpp index f91ed35331..85ae69f8b8 100644 --- a/drivers/gles3/rasterizer_storage_gles3.cpp +++ b/drivers/gles3/rasterizer_storage_gles3.cpp @@ -828,6 +828,58 @@ void RasterizerStorageGLES3::texture_set_data(RID p_texture, const Ref<Image> &p //texture_set_flags(p_texture,texture->flags); } +// Uploads pixel data to a sub-region of a texture, for the specified mipmap. +// The texture pixels must have been allocated before, because most features seen in texture_set_data() make no sense in a partial update. +// TODO If we want this to be usable without pre-filling pixels with a full image, we have to call glTexImage2D() with null data. +void RasterizerStorageGLES3::texture_set_data_partial(RID p_texture, const Ref<Image> &p_image, int src_x, int src_y, int src_w, int src_h, int dst_x, int dst_y, int p_dst_mip, VS::CubeMapSide p_cube_side) { + + Texture *texture = texture_owner.get(p_texture); + + ERR_FAIL_COND(!texture); + ERR_FAIL_COND(!texture->active); + ERR_FAIL_COND(texture->render_target); + ERR_FAIL_COND(texture->format != p_image->get_format()); + ERR_FAIL_COND(p_image.is_null()); + ERR_FAIL_COND(src_w <= 0 || src_h <= 0); + ERR_FAIL_COND(src_x < 0 || src_y < 0 || src_x + src_w > p_image->get_width() || src_y + src_h > p_image->get_height()); + ERR_FAIL_COND(dst_x < 0 || dst_y < 0 || dst_x + src_w > texture->alloc_width || dst_y + src_h > texture->alloc_height); + ERR_FAIL_COND(p_dst_mip < 0 || p_dst_mip >= texture->mipmaps); + + GLenum type; + GLenum format; + GLenum internal_format; + bool compressed; + bool srgb; + + // Because OpenGL wants data as a dense array, we have to extract the sub-image if the source rect isn't the full image + Ref<Image> p_sub_img = p_image; + if (src_x > 0 || src_y > 0 || src_w != p_image->get_width() || src_h != p_image->get_height()) { + p_sub_img = p_image->get_rect(Rect2(src_x, src_y, src_w, src_h)); + } + + Ref<Image> img = _get_gl_image_and_format(p_sub_img, p_sub_img->get_format(), texture->flags, format, internal_format, type, compressed, srgb); + + GLenum blit_target = (texture->target == GL_TEXTURE_CUBE_MAP) ? _cube_side_enum[p_cube_side] : GL_TEXTURE_2D; + + PoolVector<uint8_t>::Read read = img->get_data().read(); + + glActiveTexture(GL_TEXTURE0); + glBindTexture(texture->target, texture->tex_id); + + int src_data_size = img->get_data().size(); + int src_ofs = 0; + + if (texture->compressed) { + glPixelStorei(GL_UNPACK_ALIGNMENT, 4); + glCompressedTexSubImage2D(blit_target, p_dst_mip, dst_x, dst_y, src_w, src_h, internal_format, src_data_size, &read[src_ofs]); + + } else { + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + // `format` has to match the internal_format used when the texture was created + glTexSubImage2D(blit_target, p_dst_mip, dst_x, dst_y, src_w, src_h, format, type, &read[src_ofs]); + } +} + Ref<Image> RasterizerStorageGLES3::texture_get_data(RID p_texture, VS::CubeMapSide p_cube_side) const { Texture *texture = texture_owner.get(p_texture); @@ -1615,6 +1667,7 @@ void RasterizerStorageGLES3::_update_shader(Shader *p_shader) const { shaders.actions_canvas.render_mode_values["blend_sub"] = Pair<int *, int>(&p_shader->canvas_item.blend_mode, Shader::CanvasItem::BLEND_MODE_SUB); shaders.actions_canvas.render_mode_values["blend_mul"] = Pair<int *, int>(&p_shader->canvas_item.blend_mode, Shader::CanvasItem::BLEND_MODE_MUL); shaders.actions_canvas.render_mode_values["blend_premul_alpha"] = Pair<int *, int>(&p_shader->canvas_item.blend_mode, Shader::CanvasItem::BLEND_MODE_PMALPHA); + shaders.actions_canvas.render_mode_values["blend_disabled"] = Pair<int *, int>(&p_shader->canvas_item.blend_mode, Shader::CanvasItem::BLEND_MODE_DISABLED); shaders.actions_canvas.render_mode_values["unshaded"] = Pair<int *, int>(&p_shader->canvas_item.light_mode, Shader::CanvasItem::LIGHT_MODE_UNSHADED); shaders.actions_canvas.render_mode_values["light_only"] = Pair<int *, int>(&p_shader->canvas_item.light_mode, Shader::CanvasItem::LIGHT_MODE_LIGHT_ONLY); @@ -1912,7 +1965,7 @@ void RasterizerStorageGLES3::material_set_param(RID p_material, const StringName Variant RasterizerStorageGLES3::material_get_param(RID p_material, const StringName &p_param) const { const Material *material = material_owner.get(p_material); - ERR_FAIL_COND_V(!material, RID()); + ERR_FAIL_COND_V(!material, Variant()); if (material->params.has(p_param)) return material->params[p_param]; @@ -4496,6 +4549,15 @@ Transform2D RasterizerStorageGLES3::skeleton_bone_get_transform_2d(RID p_skeleto return ret; } +void RasterizerStorageGLES3::skeleton_set_base_transform_2d(RID p_skeleton, const Transform2D &p_base_transform) { + + Skeleton *skeleton = skeleton_owner.getornull(p_skeleton); + + ERR_FAIL_COND(!skeleton->use_2d); + + skeleton->base_transform_2d = p_base_transform; +} + void RasterizerStorageGLES3::update_dirty_skeletons() { glActiveTexture(GL_TEXTURE0); @@ -5833,7 +5895,10 @@ void RasterizerStorageGLES3::update_particles() { tex = resources.white_tex; } break; } + } else if (t->proxy && t->proxy->tex_id) { + target = t->proxy->target; + tex = t->proxy->tex_id; } else { target = t->target; diff --git a/drivers/gles3/rasterizer_storage_gles3.h b/drivers/gles3/rasterizer_storage_gles3.h index ef2b247266..6b626cbd00 100644 --- a/drivers/gles3/rasterizer_storage_gles3.h +++ b/drivers/gles3/rasterizer_storage_gles3.h @@ -340,6 +340,7 @@ public: virtual RID texture_create(); virtual void texture_allocate(RID p_texture, int p_width, int p_height, Image::Format p_format, uint32_t p_flags = VS::TEXTURE_FLAGS_DEFAULT); virtual void texture_set_data(RID p_texture, const Ref<Image> &p_image, VS::CubeMapSide p_cube_side = VS::CUBEMAP_LEFT); + virtual void texture_set_data_partial(RID p_texture, const Ref<Image> &p_image, int src_x, int src_y, int src_w, int src_h, int dst_x, int dst_y, int p_dst_mip, VS::CubeMapSide p_cube_side = VS::CUBEMAP_LEFT); virtual Ref<Image> texture_get_data(RID p_texture, VS::CubeMapSide p_cube_side = VS::CUBEMAP_LEFT) const; virtual void texture_set_flags(RID p_texture, uint32_t p_flags); virtual uint32_t texture_get_flags(RID p_texture) const; @@ -420,6 +421,7 @@ public: BLEND_MODE_SUB, BLEND_MODE_MUL, BLEND_MODE_PMALPHA, + BLEND_MODE_DISABLED, }; int blend_mode; @@ -868,6 +870,7 @@ public: GLuint texture; SelfList<Skeleton> update_list; Set<RasterizerScene::InstanceBase *> instances; //instances using skeleton + Transform2D base_transform_2d; Skeleton() : update_list(this) { @@ -891,6 +894,7 @@ public: virtual Transform skeleton_bone_get_transform(RID p_skeleton, int p_bone) const; virtual void skeleton_bone_set_transform_2d(RID p_skeleton, int p_bone, const Transform2D &p_transform); virtual Transform2D skeleton_bone_get_transform_2d(RID p_skeleton, int p_bone) const; + virtual void skeleton_set_base_transform_2d(RID p_skeleton, const Transform2D &p_base_transform); /* Light API */ diff --git a/drivers/gles3/shader_compiler_gles3.cpp b/drivers/gles3/shader_compiler_gles3.cpp index 1f3b76f5cd..eb8d6c485b 100644 --- a/drivers/gles3/shader_compiler_gles3.cpp +++ b/drivers/gles3/shader_compiler_gles3.cpp @@ -911,6 +911,7 @@ ShaderCompilerGLES3::ShaderCompilerGLES3() { actions[VS::SHADER_SPATIAL].render_mode_defines["specular_phong"] = "#define SPECULAR_PHONG\n"; actions[VS::SHADER_SPATIAL].render_mode_defines["specular_toon"] = "#define SPECULAR_TOON\n"; actions[VS::SHADER_SPATIAL].render_mode_defines["specular_disabled"] = "#define SPECULAR_DISABLED\n"; + actions[VS::SHADER_SPATIAL].render_mode_defines["shadows_disabled"] = "#define SHADOWS_DISABLED\n"; /* PARTICLES SHADER */ diff --git a/drivers/gles3/shaders/canvas.glsl b/drivers/gles3/shaders/canvas.glsl index 3bbeb1149d..326aab4c7c 100644 --- a/drivers/gles3/shaders/canvas.glsl +++ b/drivers/gles3/shaders/canvas.glsl @@ -4,6 +4,11 @@ layout(location=0) in highp vec2 vertex; layout(location=3) in vec4 color_attrib; +#ifdef USE_SKELETON +layout(location=6) in uvec4 bone_indices; // attrib:6 +layout(location=7) in vec4 bone_weights; // attrib:7 +#endif + #ifdef USE_TEXTURE_RECT uniform vec4 dst_rect; @@ -51,6 +56,12 @@ out highp vec2 pixel_size_interp; #endif +#ifdef USE_SKELETON +uniform mediump sampler2D skeleton_texture; // texunit:-1 +uniform highp mat4 skeleton_transform; +uniform highp mat4 skeleton_transform_inverse; +#endif + #ifdef USE_LIGHTING layout(std140) uniform LightData { //ubo:1 @@ -75,7 +86,6 @@ out vec4 light_uv_interp; out vec4 local_rot; - #ifdef USE_SHADOWS out highp vec2 pos; #endif @@ -101,6 +111,7 @@ MATERIAL_UNIFORMS #endif + VERTEX_SHADER_GLOBALS void main() { @@ -146,6 +157,7 @@ void main() { #endif + #define extra_matrix extra_matrix2 { @@ -175,6 +187,49 @@ VERTEX_SHADER_CODE #endif +#ifdef USE_SKELETON + + if (bone_weights!=vec4(0.0)){ //must be a valid bone + //skeleton transform + + ivec4 bone_indicesi = ivec4(bone_indices); + + ivec2 tex_ofs = ivec2( bone_indicesi.x%256, (bone_indicesi.x/256)*2 ); + + highp mat2x4 m = mat2x4( + texelFetch(skeleton_texture,tex_ofs,0), + texelFetch(skeleton_texture,tex_ofs+ivec2(0,1),0) + ) * bone_weights.x; + + tex_ofs = ivec2( bone_indicesi.y%256, (bone_indicesi.y/256)*2 ); + + m+= mat2x4( + texelFetch(skeleton_texture,tex_ofs,0), + texelFetch(skeleton_texture,tex_ofs+ivec2(0,1),0) + ) * bone_weights.y; + + tex_ofs = ivec2( bone_indicesi.z%256, (bone_indicesi.z/256)*2 ); + + m+= mat2x4( + texelFetch(skeleton_texture,tex_ofs,0), + texelFetch(skeleton_texture,tex_ofs+ivec2(0,1),0) + ) * bone_weights.z; + + + tex_ofs = ivec2( bone_indicesi.w%256, (bone_indicesi.w/256)*2 ); + + m+= mat2x4( + texelFetch(skeleton_texture,tex_ofs,0), + texelFetch(skeleton_texture,tex_ofs+ivec2(0,1),0) + ) * bone_weights.w; + + mat4 bone_matrix = skeleton_transform * transpose(mat4(m[0],m[1],vec4(0.0,0.0,1.0,0.0),vec4(0.0,0.0,0.0,1.0))) * skeleton_transform_inverse; + + outvec = bone_matrix * outvec; + } + +#endif + gl_Position = projection_matrix * outvec; #ifdef USE_LIGHTING @@ -207,6 +262,7 @@ uniform mediump sampler2D color_texture; // texunit:0 uniform highp vec2 color_texpixel_size; uniform mediump sampler2D normal_texture; // texunit:1 + in highp vec2 uv_interp; in mediump vec4 color_interp; diff --git a/drivers/gles3/shaders/scene.glsl b/drivers/gles3/shaders/scene.glsl index d3644bffdd..f5481c597c 100644 --- a/drivers/gles3/shaders/scene.glsl +++ b/drivers/gles3/shaders/scene.glsl @@ -1206,6 +1206,7 @@ void light_process_omni(int idx, vec3 vertex, vec3 eye_vec,vec3 normal,vec3 bino float omni_attenuation = pow( max(1.0 - normalized_distance, 0.0), omni_lights[idx].light_direction_attenuation.w ); vec3 light_attenuation = vec3(omni_attenuation); +#if !defined(SHADOWS_DISABLED) if (omni_lights[idx].light_params.w>0.5) { //there is a shadowmap @@ -1252,6 +1253,7 @@ void light_process_omni(int idx, vec3 vertex, vec3 eye_vec,vec3 normal,vec3 bino #endif light_attenuation*=mix(omni_lights[idx].shadow_color_contact.rgb,vec3(1.0),shadow); } +#endif //SHADOWS_DISABLED light_compute(normal,normalize(light_rel_vec),eye_vec,binormal,tangent,omni_lights[idx].light_color_energy.rgb,light_attenuation,albedo,transmission,omni_lights[idx].light_params.z*p_blob_intensity,roughness,metallic,rim * omni_attenuation,rim_tint,clearcoat,clearcoat_gloss,anisotropy,diffuse_light,specular_light); @@ -1270,6 +1272,7 @@ void light_process_spot(int idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 bi spot_attenuation*= 1.0 - pow( spot_rim, spot_lights[idx].light_params.x); vec3 light_attenuation = vec3(spot_attenuation); +#if !defined(SHADOWS_DISABLED) if (spot_lights[idx].light_params.w>0.5) { //there is a shadowmap highp vec4 splane=(spot_lights[idx].shadow_matrix * vec4(vertex,1.0)); @@ -1287,6 +1290,7 @@ void light_process_spot(int idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 bi #endif light_attenuation*=mix(spot_lights[idx].shadow_color_contact.rgb,vec3(1.0),shadow); } +#endif //SHADOWS_DISABLED light_compute(normal,normalize(light_rel_vec),eye_vec,binormal,tangent,spot_lights[idx].light_color_energy.rgb,light_attenuation,albedo,transmission,spot_lights[idx].light_params.z*p_blob_intensity,roughness,metallic,rim * spot_attenuation,rim_tint,clearcoat,clearcoat_gloss,anisotropy,diffuse_light,specular_light); @@ -1785,6 +1789,7 @@ FRAGMENT_SHADER_CODE float depth_z = -vertex.z; #ifdef LIGHT_DIRECTIONAL_SHADOW +#if !defined(SHADOWS_DISABLED) #ifdef LIGHT_USE_PSSM4 if (depth_z < shadow_split_offsets.w) { @@ -1927,6 +1932,7 @@ FRAGMENT_SHADER_CODE } +#endif // !defined(SHADOWS_DISABLED) #endif //LIGHT_DIRECTIONAL_SHADOW #ifdef USE_VERTEX_LIGHTING diff --git a/drivers/gles3/shaders/tonemap.glsl b/drivers/gles3/shaders/tonemap.glsl index 2f671158b2..a75871f08e 100644 --- a/drivers/gles3/shaders/tonemap.glsl +++ b/drivers/gles3/shaders/tonemap.glsl @@ -258,9 +258,13 @@ void main() { #endif +#ifdef KEEP_3D_LINEAR + // leave color as is... +#else //regular Linear -> SRGB conversion vec3 a = vec3(0.055); 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 #if defined(USING_GLOW) glow = mix( (vec3(1.0)+a)*pow(glow,vec3(1.0/2.4))-a , 12.92*glow , lessThan(glow,vec3(0.0031308))); |