diff options
Diffstat (limited to 'drivers/gles3')
-rw-r--r-- | drivers/gles3/rasterizer_canvas_gles3.cpp | 6 | ||||
-rw-r--r-- | drivers/gles3/rasterizer_scene_gles3.cpp | 6 | ||||
-rw-r--r-- | drivers/gles3/rasterizer_scene_gles3.h | 2 | ||||
-rw-r--r-- | drivers/gles3/rasterizer_storage_gles3.cpp | 79 | ||||
-rw-r--r-- | drivers/gles3/rasterizer_storage_gles3.h | 6 | ||||
-rw-r--r-- | drivers/gles3/shaders/canvas.glsl | 26 |
6 files changed, 74 insertions, 51 deletions
diff --git a/drivers/gles3/rasterizer_canvas_gles3.cpp b/drivers/gles3/rasterizer_canvas_gles3.cpp index edffe852a2..e09ba755ea 100644 --- a/drivers/gles3/rasterizer_canvas_gles3.cpp +++ b/drivers/gles3/rasterizer_canvas_gles3.cpp @@ -548,8 +548,10 @@ void RasterizerCanvasGLES3::_canvas_item_render_commands(Item *p_item, Item *cur if (line->width <= 1) { Vector2 verts[2] = { - Vector2(line->from.x, line->from.y), - Vector2(line->to.x, line->to.y) + // Offset the line slightly to make sure we always draw the pixel at the from coordinate. + // Without this, corners of rectangles might be missing a pixel. (See diamond exit rule and #32657) + Vector2(Math::floor(line->from.x) + 0.5, Math::floor(line->from.y) + 0.5), + Vector2(Math::floor(line->to.x) + 0.5, Math::floor(line->to.y) + 0.5) }; #ifdef GLES_OVER_GL diff --git a/drivers/gles3/rasterizer_scene_gles3.cpp b/drivers/gles3/rasterizer_scene_gles3.cpp index 35f414cf09..519fdf2b3b 100644 --- a/drivers/gles3/rasterizer_scene_gles3.cpp +++ b/drivers/gles3/rasterizer_scene_gles3.cpp @@ -1093,7 +1093,7 @@ void RasterizerSceneGLES3::gi_probe_instance_set_bounds(RID p_probe, const Vecto //////////////////////////// //////////////////////////// -bool RasterizerSceneGLES3::_setup_material(RasterizerStorageGLES3::Material *p_material, bool p_alpha_pass) { +bool RasterizerSceneGLES3::_setup_material(RasterizerStorageGLES3::Material *p_material, bool p_depth_pass, bool p_alpha_pass) { /* this is handled outside if (p_material->shader->spatial.cull_mode == RasterizerStorageGLES3::Shader::Spatial::CULL_MODE_DISABLED) { @@ -1121,7 +1121,7 @@ bool RasterizerSceneGLES3::_setup_material(RasterizerStorageGLES3::Material *p_m if (state.current_depth_draw != p_material->shader->spatial.depth_draw_mode) { switch (p_material->shader->spatial.depth_draw_mode) { case RasterizerStorageGLES3::Shader::Spatial::DEPTH_DRAW_ALPHA_PREPASS: { - glDepthMask(GL_TRUE); + glDepthMask(p_depth_pass); // If some transparent objects write to depth, we need to re-copy depth texture when we need it if (p_alpha_pass && !state.used_depth_prepass) { state.prepared_depth_texture = false; @@ -2241,7 +2241,7 @@ void RasterizerSceneGLES3::_render_list(RenderList::Element **p_elements, int p_ storage->info.render.material_switch_count++; - rebind = _setup_material(material, p_alpha_pass); + rebind = _setup_material(material, use_opaque_prepass, p_alpha_pass); if (rebind) { storage->info.render.shader_rebind_count++; diff --git a/drivers/gles3/rasterizer_scene_gles3.h b/drivers/gles3/rasterizer_scene_gles3.h index 3d09adcfeb..e6d2449653 100644 --- a/drivers/gles3/rasterizer_scene_gles3.h +++ b/drivers/gles3/rasterizer_scene_gles3.h @@ -832,7 +832,7 @@ public: _FORCE_INLINE_ void _set_cull(bool p_front, bool p_disabled, bool p_reverse_cull); - _FORCE_INLINE_ bool _setup_material(RasterizerStorageGLES3::Material *p_material, bool p_alpha_pass); + _FORCE_INLINE_ bool _setup_material(RasterizerStorageGLES3::Material *p_material, bool p_depth_pass, bool p_alpha_pass); _FORCE_INLINE_ void _setup_geometry(RenderList::Element *e, const Transform &p_view_transform); _FORCE_INLINE_ void _render_geometry(RenderList::Element *e); _FORCE_INLINE_ void _setup_light(RenderList::Element *e, const Transform &p_view_transform); diff --git a/drivers/gles3/rasterizer_storage_gles3.cpp b/drivers/gles3/rasterizer_storage_gles3.cpp index a29831e3f5..f94020b918 100644 --- a/drivers/gles3/rasterizer_storage_gles3.cpp +++ b/drivers/gles3/rasterizer_storage_gles3.cpp @@ -135,13 +135,13 @@ void glTexStorage2DCustom(GLenum target, GLsizei levels, GLenum internalformat, GLuint RasterizerStorageGLES3::system_fbo = 0; -Ref<Image> RasterizerStorageGLES3::_get_gl_image_and_format(const Ref<Image> &p_image, Image::Format p_format, uint32_t p_flags, Image::Format &r_real_format, GLenum &r_gl_format, GLenum &r_gl_internal_format, GLenum &r_gl_type, bool &r_compressed, bool &srgb) const { +Ref<Image> RasterizerStorageGLES3::_get_gl_image_and_format(const Ref<Image> &p_image, Image::Format p_format, uint32_t p_flags, Image::Format &r_real_format, GLenum &r_gl_format, GLenum &r_gl_internal_format, GLenum &r_gl_type, bool &r_compressed, bool &r_srgb, bool p_force_decompress) const { r_compressed = false; r_gl_format = 0; r_real_format = p_format; Ref<Image> image = p_image; - srgb = false; + r_srgb = false; bool need_decompress = false; @@ -188,7 +188,7 @@ Ref<Image> RasterizerStorageGLES3::_get_gl_image_and_format(const Ref<Image> &p_ r_gl_internal_format = (config.srgb_decode_supported || (p_flags & VS::TEXTURE_FLAG_CONVERT_TO_LINEAR)) ? GL_SRGB8 : GL_RGB8; r_gl_format = GL_RGB; r_gl_type = GL_UNSIGNED_BYTE; - srgb = true; + r_srgb = true; } break; case Image::FORMAT_RGBA8: { @@ -196,7 +196,7 @@ Ref<Image> RasterizerStorageGLES3::_get_gl_image_and_format(const Ref<Image> &p_ r_gl_format = GL_RGBA; r_gl_internal_format = (config.srgb_decode_supported || (p_flags & VS::TEXTURE_FLAG_CONVERT_TO_LINEAR)) ? GL_SRGB8_ALPHA8 : GL_RGBA8; r_gl_type = GL_UNSIGNED_BYTE; - srgb = true; + r_srgb = true; } break; case Image::FORMAT_RGBA4444: { @@ -278,7 +278,7 @@ Ref<Image> RasterizerStorageGLES3::_get_gl_image_and_format(const Ref<Image> &p_ r_gl_format = GL_RGBA; r_gl_type = GL_UNSIGNED_BYTE; r_compressed = true; - srgb = true; + r_srgb = true; } else { @@ -294,7 +294,7 @@ Ref<Image> RasterizerStorageGLES3::_get_gl_image_and_format(const Ref<Image> &p_ r_gl_format = GL_RGBA; r_gl_type = GL_UNSIGNED_BYTE; r_compressed = true; - srgb = true; + r_srgb = true; } else { @@ -310,7 +310,7 @@ Ref<Image> RasterizerStorageGLES3::_get_gl_image_and_format(const Ref<Image> &p_ r_gl_format = GL_RGBA; r_gl_type = GL_UNSIGNED_BYTE; r_compressed = true; - srgb = true; + r_srgb = true; } else { @@ -355,7 +355,7 @@ Ref<Image> RasterizerStorageGLES3::_get_gl_image_and_format(const Ref<Image> &p_ r_gl_format = GL_RGBA; r_gl_type = GL_UNSIGNED_BYTE; r_compressed = true; - srgb = true; + r_srgb = true; } else { @@ -395,7 +395,7 @@ Ref<Image> RasterizerStorageGLES3::_get_gl_image_and_format(const Ref<Image> &p_ r_gl_format = GL_RGBA; r_gl_type = GL_UNSIGNED_BYTE; r_compressed = true; - srgb = true; + r_srgb = true; } else { @@ -410,7 +410,7 @@ Ref<Image> RasterizerStorageGLES3::_get_gl_image_and_format(const Ref<Image> &p_ r_gl_format = GL_RGBA; r_gl_type = GL_UNSIGNED_BYTE; r_compressed = true; - srgb = true; + r_srgb = true; } else { @@ -426,7 +426,7 @@ Ref<Image> RasterizerStorageGLES3::_get_gl_image_and_format(const Ref<Image> &p_ r_gl_format = GL_RGBA; r_gl_type = GL_UNSIGNED_BYTE; r_compressed = true; - srgb = true; + r_srgb = true; } else { @@ -442,7 +442,7 @@ Ref<Image> RasterizerStorageGLES3::_get_gl_image_and_format(const Ref<Image> &p_ r_gl_format = GL_RGBA; r_gl_type = GL_UNSIGNED_BYTE; r_compressed = true; - srgb = true; + r_srgb = true; } else { @@ -527,7 +527,7 @@ Ref<Image> RasterizerStorageGLES3::_get_gl_image_and_format(const Ref<Image> &p_ r_gl_format = GL_RGB; r_gl_type = GL_UNSIGNED_BYTE; r_compressed = true; - srgb = true; + r_srgb = true; } else { @@ -542,7 +542,7 @@ Ref<Image> RasterizerStorageGLES3::_get_gl_image_and_format(const Ref<Image> &p_ r_gl_format = GL_RGBA; r_gl_type = GL_UNSIGNED_BYTE; r_compressed = true; - srgb = true; + r_srgb = true; } else { @@ -557,7 +557,7 @@ Ref<Image> RasterizerStorageGLES3::_get_gl_image_and_format(const Ref<Image> &p_ r_gl_format = GL_RGBA; r_gl_type = GL_UNSIGNED_BYTE; r_compressed = true; - srgb = true; + r_srgb = true; } else { @@ -570,7 +570,7 @@ Ref<Image> RasterizerStorageGLES3::_get_gl_image_and_format(const Ref<Image> &p_ } } - if (need_decompress) { + if (need_decompress || p_force_decompress) { if (!image.is_null()) { image = image->duplicate(); @@ -584,7 +584,7 @@ Ref<Image> RasterizerStorageGLES3::_get_gl_image_and_format(const Ref<Image> &p_ r_gl_type = GL_UNSIGNED_BYTE; r_compressed = false; r_real_format = Image::FORMAT_RGBA8; - srgb = true; + r_srgb = true; return image; } @@ -677,8 +677,22 @@ void RasterizerStorageGLES3::texture_allocate(RID p_texture, int p_width, int p_ } break; } + texture->is_npot_repeat_mipmap = false; +#ifdef JAVASCRIPT_ENABLED + // WebGL 2.0 on browsers does not seem to properly support compressed non power-of-two (NPOT) + // textures with repeat/mipmaps, even though NPOT textures should be supported as per the spec. + // Force decompressing them to work it around on WebGL 2.0 at a performance cost (GH-33058). + int po2_width = next_power_of_2(p_width); + int po2_height = next_power_of_2(p_height); + bool is_po2 = p_width == po2_width && p_height == po2_height; + + if (!is_po2 && (p_flags & VS::TEXTURE_FLAG_REPEAT || p_flags & VS::TEXTURE_FLAG_MIPMAPS)) { + texture->is_npot_repeat_mipmap = true; + } +#endif // JAVASCRIPT_ENABLED + Image::Format real_format; - _get_gl_image_and_format(Ref<Image>(), texture->format, texture->flags, real_format, format, internal_format, type, compressed, srgb); + _get_gl_image_and_format(Ref<Image>(), texture->format, texture->flags, real_format, format, internal_format, type, compressed, srgb, texture->is_npot_repeat_mipmap); texture->alloc_width = texture->width; texture->alloc_height = texture->height; @@ -753,13 +767,9 @@ void RasterizerStorageGLES3::texture_set_data(RID p_texture, const Ref<Image> &p if (config.keep_original_textures && !(texture->flags & VS::TEXTURE_FLAG_USED_FOR_STREAMING)) { texture->images.write[p_layer] = p_image; } -#ifndef GLES_OVER_GL - if (p_image->is_compressed() && p_image->has_mipmaps() && !p_image->is_size_po2()) { - ERR_PRINTS("Texuture '" + texture->path + "' is compressed, has mipmaps but is not of powerf-of-2 size. This does not work on OpenGL ES 3.0."); - } -#endif + Image::Format real_format; - Ref<Image> img = _get_gl_image_and_format(p_image, p_image->get_format(), texture->flags, real_format, format, internal_format, type, compressed, srgb); + Ref<Image> img = _get_gl_image_and_format(p_image, p_image->get_format(), texture->flags, real_format, format, internal_format, type, compressed, srgb, texture->is_npot_repeat_mipmap); if (config.shrink_textures_x2 && (p_image->has_mipmaps() || !p_image->is_compressed()) && !(texture->flags & VS::TEXTURE_FLAG_USED_FOR_STREAMING)) { @@ -795,6 +805,7 @@ void RasterizerStorageGLES3::texture_set_data(RID p_texture, const Ref<Image> &p texture->data_size = img->get_data().size(); PoolVector<uint8_t>::Read read = img->get_data().read(); + ERR_FAIL_COND(!read.ptr()); glActiveTexture(GL_TEXTURE0); glBindTexture(texture->target, texture->tex_id); @@ -992,7 +1003,7 @@ void RasterizerStorageGLES3::texture_set_data_partial(RID p_texture, const Ref<I } Image::Format real_format; - Ref<Image> img = _get_gl_image_and_format(p_sub_img, p_sub_img->get_format(), texture->flags, real_format, format, internal_format, type, compressed, srgb); + Ref<Image> img = _get_gl_image_and_format(p_sub_img, p_sub_img->get_format(), texture->flags, real_format, format, internal_format, type, compressed, srgb, texture->is_npot_repeat_mipmap); GLenum blit_target = GL_TEXTURE_2D; @@ -1091,7 +1102,8 @@ Ref<Image> RasterizerStorageGLES3::texture_get_data(RID p_texture, int p_layer) gl_internal_format, gl_type, compressed, - srgb); + srgb, + texture->is_npot_repeat_mipmap); PoolVector<uint8_t> data; @@ -1197,7 +1209,7 @@ Ref<Image> RasterizerStorageGLES3::texture_get_data(RID p_texture, int p_layer) GLenum gl_type; bool compressed; bool srgb; - _get_gl_image_and_format(Ref<Image>(), texture->format, texture->flags, real_format, gl_format, gl_internal_format, gl_type, compressed, srgb); + _get_gl_image_and_format(Ref<Image>(), texture->format, texture->flags, real_format, gl_format, gl_internal_format, gl_type, compressed, srgb, false); PoolVector<uint8_t> data; @@ -1267,7 +1279,7 @@ Ref<Image> RasterizerStorageGLES3::texture_get_data(RID p_texture, int p_layer) GLenum gl_type; bool compressed; bool srgb; - _get_gl_image_and_format(Ref<Image>(), texture->format, texture->flags, real_format, gl_format, gl_internal_format, gl_type, compressed, srgb); + _get_gl_image_and_format(Ref<Image>(), texture->format, texture->flags, real_format, gl_format, gl_internal_format, gl_type, compressed, srgb, texture->is_npot_repeat_mipmap); PoolVector<uint8_t> data; @@ -2168,8 +2180,9 @@ void RasterizerStorageGLES3::_update_shader(Shader *p_shader) const { } Error err = shaders.compiler.compile(p_shader->mode, p_shader->code, actions, p_shader->path, gen_code); - - ERR_FAIL_COND(err != OK); + if (err != OK) { + return; + } p_shader->shader->set_custom_shader_code(p_shader->custom_code_id, gen_code.vertex, gen_code.vertex_global, gen_code.fragment, gen_code.light, gen_code.fragment_global, gen_code.uniforms, gen_code.texture_uniforms, gen_code.defines); @@ -4717,6 +4730,7 @@ void RasterizerStorageGLES3::multimesh_set_as_bulk_array(RID p_multimesh, const MultiMesh *multimesh = multimesh_owner.getornull(p_multimesh); ERR_FAIL_COND(!multimesh); + ERR_FAIL_COND(!multimesh->data.ptr()); int dsize = multimesh->data.size(); @@ -4853,15 +4867,16 @@ RID RasterizerStorageGLES3::immediate_create() { return immediate_owner.make_rid(im); } -void RasterizerStorageGLES3::immediate_begin(RID p_immediate, VS::PrimitiveType p_rimitive, RID p_texture) { +void RasterizerStorageGLES3::immediate_begin(RID p_immediate, VS::PrimitiveType p_primitive, RID p_texture) { + ERR_FAIL_INDEX(p_primitive, (int)VS::PRIMITIVE_MAX); Immediate *im = immediate_owner.get(p_immediate); ERR_FAIL_COND(!im); ERR_FAIL_COND(im->building); Immediate::Chunk ic; ic.texture = p_texture; - ic.primitive = p_rimitive; + ic.primitive = p_primitive; im->chunks.push_back(ic); im->mask = 0; im->building = true; diff --git a/drivers/gles3/rasterizer_storage_gles3.h b/drivers/gles3/rasterizer_storage_gles3.h index 84632308b4..3b1021d0e1 100644 --- a/drivers/gles3/rasterizer_storage_gles3.h +++ b/drivers/gles3/rasterizer_storage_gles3.h @@ -266,6 +266,8 @@ public: int mipmaps; + bool is_npot_repeat_mipmap; + bool active; GLuint tex_id; @@ -342,7 +344,7 @@ public: mutable RID_Owner<Texture> texture_owner; - Ref<Image> _get_gl_image_and_format(const Ref<Image> &p_image, Image::Format p_format, uint32_t p_flags, Image::Format &r_real_format, GLenum &r_gl_format, GLenum &r_gl_internal_format, GLenum &r_gl_type, bool &r_compressed, bool &srgb) const; + Ref<Image> _get_gl_image_and_format(const Ref<Image> &p_image, Image::Format p_format, uint32_t p_flags, Image::Format &r_real_format, GLenum &r_gl_format, GLenum &r_gl_internal_format, GLenum &r_gl_type, bool &r_compressed, bool &r_srgb, bool p_force_decompress) const; virtual RID texture_create(); virtual void texture_allocate(RID p_texture, int p_width, int p_height, int p_depth_3d, Image::Format p_format, VS::TextureType p_type, uint32_t p_flags = VS::TEXTURE_FLAGS_DEFAULT); @@ -869,7 +871,7 @@ public: mutable RID_Owner<Immediate> immediate_owner; virtual RID immediate_create(); - virtual void immediate_begin(RID p_immediate, VS::PrimitiveType p_rimitive, RID p_texture = RID()); + virtual void immediate_begin(RID p_immediate, VS::PrimitiveType p_primitive, RID p_texture = RID()); virtual void immediate_vertex(RID p_immediate, const Vector3 &p_vertex); virtual void immediate_normal(RID p_immediate, const Vector3 &p_normal); virtual void immediate_tangent(RID p_immediate, const Plane &p_tangent); diff --git a/drivers/gles3/shaders/canvas.glsl b/drivers/gles3/shaders/canvas.glsl index e83f53d648..7255b0425c 100644 --- a/drivers/gles3/shaders/canvas.glsl +++ b/drivers/gles3/shaders/canvas.glsl @@ -380,14 +380,16 @@ uniform bool np_draw_center; // left top right bottom in pixel coordinates uniform vec4 np_margins; -float map_ninepatch_axis(float pixel, float draw_size, float tex_pixel_size, float margin_begin, float margin_end, int np_repeat, inout int draw_center) { +float map_ninepatch_axis(float pixel, float draw_size, float tex_pixel_size, float margin_begin, float margin_end, float s_ratio, int np_repeat, inout int draw_center) { float tex_size = 1.0 / tex_pixel_size; - if (pixel < margin_begin) { - return pixel * tex_pixel_size; - } else if (pixel >= draw_size - margin_end) { - return (tex_size - (draw_size - pixel)) * tex_pixel_size; + float screen_margin_begin = margin_begin / s_ratio; + float screen_margin_end = margin_end / s_ratio; + if (pixel < screen_margin_begin) { + return pixel * s_ratio * tex_pixel_size; + } else if (pixel >= draw_size - screen_margin_end) { + return (tex_size - (draw_size - pixel) * s_ratio) * tex_pixel_size; } else { if (!np_draw_center) { draw_center--; @@ -395,22 +397,22 @@ float map_ninepatch_axis(float pixel, float draw_size, float tex_pixel_size, flo if (np_repeat == 0) { //stretch //convert to ratio - float ratio = (pixel - margin_begin) / (draw_size - margin_begin - margin_end); + float ratio = (pixel - screen_margin_begin) / (draw_size - screen_margin_begin - screen_margin_end); //scale to source texture return (margin_begin + ratio * (tex_size - margin_begin - margin_end)) * tex_pixel_size; } else if (np_repeat == 1) { //tile //convert to ratio - float ofs = mod((pixel - margin_begin), tex_size - margin_begin - margin_end); + float ofs = mod((pixel - screen_margin_begin), tex_size - margin_begin - margin_end); //scale to source texture return (margin_begin + ofs) * tex_pixel_size; } else if (np_repeat == 2) { //tile fit //convert to ratio - float src_area = draw_size - margin_begin - margin_end; + float src_area = draw_size - screen_margin_begin - screen_margin_end; float dst_area = tex_size - margin_begin - margin_end; float scale = max(1.0, floor(src_area / max(dst_area, 0.0000001) + 0.5)); //convert to ratio - float ratio = (pixel - margin_begin) / src_area; + float ratio = (pixel - screen_margin_begin) / src_area; ratio = mod(ratio * scale, 1.0); return (margin_begin + ratio * dst_area) * tex_pixel_size; } @@ -432,9 +434,11 @@ void main() { #ifdef USE_NINEPATCH int draw_center = 2; + float s_ratio = max((1.0 / color_texpixel_size.x) / abs(dst_rect.z), (1.0 / color_texpixel_size.y) / abs(dst_rect.w)); + s_ratio = max(1.0, s_ratio); uv = vec2( - map_ninepatch_axis(pixel_size_interp.x, abs(dst_rect.z), color_texpixel_size.x, np_margins.x, np_margins.z, np_repeat_h, draw_center), - map_ninepatch_axis(pixel_size_interp.y, abs(dst_rect.w), color_texpixel_size.y, np_margins.y, np_margins.w, np_repeat_v, draw_center)); + map_ninepatch_axis(pixel_size_interp.x, abs(dst_rect.z), color_texpixel_size.x, np_margins.x, np_margins.z, s_ratio, np_repeat_h, draw_center), + map_ninepatch_axis(pixel_size_interp.y, abs(dst_rect.w), color_texpixel_size.y, np_margins.y, np_margins.w, s_ratio, np_repeat_v, draw_center)); if (draw_center == 0) { color.a = 0.0; |