diff options
Diffstat (limited to 'drivers/gles3/rasterizer_canvas_gles3.cpp')
-rw-r--r-- | drivers/gles3/rasterizer_canvas_gles3.cpp | 265 |
1 files changed, 221 insertions, 44 deletions
diff --git a/drivers/gles3/rasterizer_canvas_gles3.cpp b/drivers/gles3/rasterizer_canvas_gles3.cpp index c71bf22965..268d6b44c6 100644 --- a/drivers/gles3/rasterizer_canvas_gles3.cpp +++ b/drivers/gles3/rasterizer_canvas_gles3.cpp @@ -28,10 +28,10 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ #include "rasterizer_canvas_gles3.h" -#include "servers/visual/visual_server_raster.h" - #include "global_config.h" #include "os/os.h" +#include "rasterizer_scene_gles3.h" +#include "servers/visual/visual_server_raster.h" #ifndef GLES_OVER_GL #define glClearDepth glClearDepthf #endif @@ -172,6 +172,11 @@ void RasterizerCanvasGLES3::canvas_begin() { state.canvas_shader.set_uniform(CanvasShaderGLES3::FINAL_MODULATE, Color(1, 1, 1, 1)); state.canvas_shader.set_uniform(CanvasShaderGLES3::MODELVIEW_MATRIX, Transform2D()); state.canvas_shader.set_uniform(CanvasShaderGLES3::EXTRA_MATRIX, Transform2D()); + 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 { + state.canvas_shader.set_uniform(CanvasShaderGLES3::SCREEN_PIXEL_SIZE, Vector2(1.0, 1.0)); + } //state.canvas_shader.set_uniform(CanvasShaderGLES3::PROJECTION_MATRIX,state.vp); //state.canvas_shader.set_uniform(CanvasShaderGLES3::MODELVIEW_MATRIX,Transform()); @@ -282,7 +287,11 @@ 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 (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 { + state.canvas_shader.set_uniform(CanvasShaderGLES3::SCREEN_PIXEL_SIZE, Vector2(1.0, 1.0)); + } state.using_texture_rect = p_enable; state.using_ninepatch = p_ninepatch; } @@ -339,6 +348,53 @@ void RasterizerCanvasGLES3::_draw_polygon(const int *p_indices, int p_index_coun glBindVertexArray(0); } +void RasterizerCanvasGLES3::_draw_generic(GLuint p_primitive, int p_vertex_count, const Vector2 *p_vertices, const Vector2 *p_uvs, const Color *p_colors, bool p_singlecolor) { + + glBindVertexArray(data.polygon_buffer_pointer_array); + glBindBuffer(GL_ARRAY_BUFFER, data.polygon_buffer); + + uint32_t buffer_ofs = 0; + + //vertex + 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 + + if (p_singlecolor) { + glDisableVertexAttribArray(VS::ARRAY_COLOR); + Color m = *p_colors; + glVertexAttrib4f(VS::ARRAY_COLOR, m.r, m.g, m.b, m.a); + } else if (!p_colors) { + glDisableVertexAttribArray(VS::ARRAY_COLOR); + glVertexAttrib4f(VS::ARRAY_COLOR, 1, 1, 1, 1); + } else { + + glBufferSubData(GL_ARRAY_BUFFER, buffer_ofs, sizeof(Color) * p_vertex_count, p_colors); + glEnableVertexAttribArray(VS::ARRAY_COLOR); + glVertexAttribPointer(VS::ARRAY_COLOR, 4, GL_FLOAT, false, sizeof(Color), ((uint8_t *)0) + buffer_ofs); + buffer_ofs += sizeof(Color) * p_vertex_count; + } + + if (p_uvs) { + + glBufferSubData(GL_ARRAY_BUFFER, buffer_ofs, sizeof(Vector2) * p_vertex_count, p_uvs); + glEnableVertexAttribArray(VS::ARRAY_TEX_UV); + glVertexAttribPointer(VS::ARRAY_TEX_UV, 2, GL_FLOAT, false, sizeof(Vector2), ((uint8_t *)0) + buffer_ofs); + buffer_ofs += sizeof(Vector2) * p_vertex_count; + + } else { + glDisableVertexAttribArray(VS::ARRAY_TEX_UV); + } + + glDrawArrays(p_primitive, 0, p_vertex_count); + + storage->frame.canvas_draw_commands++; + + glBindVertexArray(0); +} + void RasterizerCanvasGLES3::_draw_gui_primitive(int p_points, const Vector2 *p_vertices, const Color *p_colors, const Vector2 *p_uvs) { static const GLenum prim[5] = { GL_POINTS, GL_POINTS, GL_LINES, GL_TRIANGLES, GL_TRIANGLE_FAN }; @@ -416,22 +472,83 @@ void RasterizerCanvasGLES3::_canvas_item_render_commands(Item *p_item, Item *cur glVertexAttrib4f(VS::ARRAY_COLOR, line->color.r, line->color.g, line->color.b, line->color.a); - Vector2 verts[2] = { - Vector2(line->from.x, line->from.y), - Vector2(line->to.x, line->to.y) - }; + if (line->width <= 1) { + Vector2 verts[2] = { + Vector2(line->from.x, line->from.y), + Vector2(line->to.x, line->to.y) + }; #ifdef GLES_OVER_GL - if (line->antialiased) - glEnable(GL_LINE_SMOOTH); + if (line->antialiased) + glEnable(GL_LINE_SMOOTH); #endif - //glLineWidth(line->width); - _draw_gui_primitive(2, verts, NULL, NULL); + //glLineWidth(line->width); + _draw_gui_primitive(2, verts, NULL, NULL); + +#ifdef GLES_OVER_GL + if (line->antialiased) + glDisable(GL_LINE_SMOOTH); +#endif + } else { + //thicker line + + Vector2 t = (line->from - line->to).normalized().tangent() * line->width * 0.5; + + Vector2 verts[4] = { + line->from - t, + line->from + t, + line->to + t, + line->to - t, + }; + + //glLineWidth(line->width); + _draw_gui_primitive(4, verts, NULL, NULL); +#ifdef GLES_OVER_GL + if (line->antialiased) { + glEnable(GL_LINE_SMOOTH); + for (int i = 0; i < 4; i++) { + Vector2 vertsl[2] = { + verts[i], + verts[(i + 1) % 4], + }; + _draw_gui_primitive(2, vertsl, NULL, NULL); + } + glDisable(GL_LINE_SMOOTH); + } +#endif + } + + } break; + case Item::Command::TYPE_POLYLINE: { + Item::CommandPolyLine *pline = static_cast<Item::CommandPolyLine *>(c); + _set_texture_rect_mode(false); + + _bind_canvas_texture(RID(), RID()); + + if (pline->triangles.size()) { + + _draw_generic(GL_TRIANGLE_STRIP, pline->triangles.size(), pline->triangles.ptr(), NULL, pline->triangle_colors.ptr(), pline->triangle_colors.size() == 1); #ifdef GLES_OVER_GL - if (line->antialiased) + glEnable(GL_LINE_SMOOTH); + if (pline->lines.size()) { + _draw_generic(GL_LINE_LOOP, pline->lines.size(), pline->lines.ptr(), NULL, pline->line_colors.ptr(), pline->line_colors.size() == 1); + } glDisable(GL_LINE_SMOOTH); #endif + } else { + +#ifdef GLES_OVER_GL + if (pline->antialiased) + glEnable(GL_LINE_SMOOTH); +#endif + _draw_generic(GL_LINE_STRIP, pline->lines.size(), pline->lines.ptr(), NULL, pline->line_colors.ptr(), pline->line_colors.size() == 1); + +#ifdef GLES_OVER_GL + if (pline->antialiased) + glDisable(GL_LINE_SMOOTH); +#endif + } } break; case Item::Command::TYPE_RECT: { @@ -822,6 +939,78 @@ void RasterizerGLES2::_canvas_item_setup_shader_params(ShaderMaterial *material, #endif +void RasterizerCanvasGLES3::_copy_texscreen(const Rect2 &p_rect) { + + state.canvas_texscreen_used = true; + //blur diffuse into effect mipmaps using separatable convolution + //storage->shaders.copy.set_conditional(CopyShaderGLES3::GAUSSIAN_HORIZONTAL,true); + + Vector2 wh(storage->frame.current_rt->width, storage->frame.current_rt->height); + + Color blur_section(p_rect.position.x / wh.x, p_rect.position.y / wh.y, p_rect.size.x / wh.x, p_rect.size.y / wh.y); + + if (p_rect != Rect2()) { + + scene_render->state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::USE_BLUR_SECTION, true); + storage->shaders.copy.set_conditional(CopyShaderGLES3::USE_COPY_SECTION, true); + } + + glBindFramebuffer(GL_FRAMEBUFFER, storage->frame.current_rt->effects.mip_maps[0].sizes[0].fbo); + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->color); + + storage->shaders.copy.bind(); + storage->shaders.copy.set_uniform(CopyShaderGLES3::COPY_SECTION, blur_section); + + scene_render->_copy_screen(); + + for (int i = 0; i < storage->frame.current_rt->effects.mip_maps[1].sizes.size(); i++) { + + int vp_w = storage->frame.current_rt->effects.mip_maps[1].sizes[i].width; + int vp_h = storage->frame.current_rt->effects.mip_maps[1].sizes[i].height; + glViewport(0, 0, vp_w, vp_h); + //horizontal pass + scene_render->state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::GAUSSIAN_HORIZONTAL, true); + scene_render->state.effect_blur_shader.bind(); + scene_render->state.effect_blur_shader.set_uniform(EffectBlurShaderGLES3::PIXEL_SIZE, Vector2(1.0 / vp_w, 1.0 / vp_h)); + scene_render->state.effect_blur_shader.set_uniform(EffectBlurShaderGLES3::LOD, float(i)); + scene_render->state.effect_blur_shader.set_uniform(EffectBlurShaderGLES3::BLUR_SECTION, blur_section); + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->effects.mip_maps[0].color); //previous level, since mipmaps[0] starts one level bigger + glBindFramebuffer(GL_FRAMEBUFFER, storage->frame.current_rt->effects.mip_maps[1].sizes[i].fbo); + + scene_render->_copy_screen(); + + scene_render->state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::GAUSSIAN_HORIZONTAL, false); + + //vertical pass + scene_render->state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::GAUSSIAN_VERTICAL, true); + scene_render->state.effect_blur_shader.bind(); + scene_render->state.effect_blur_shader.set_uniform(EffectBlurShaderGLES3::PIXEL_SIZE, Vector2(1.0 / vp_w, 1.0 / vp_h)); + scene_render->state.effect_blur_shader.set_uniform(EffectBlurShaderGLES3::LOD, float(i)); + scene_render->state.effect_blur_shader.set_uniform(EffectBlurShaderGLES3::BLUR_SECTION, blur_section); + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->effects.mip_maps[1].color); + glBindFramebuffer(GL_FRAMEBUFFER, storage->frame.current_rt->effects.mip_maps[0].sizes[i + 1].fbo); //next level, since mipmaps[0] starts one level bigger + + scene_render->_copy_screen(); + + scene_render->state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::GAUSSIAN_VERTICAL, false); + } + + scene_render->state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::USE_BLUR_SECTION, false); + storage->shaders.copy.set_conditional(CopyShaderGLES3::USE_COPY_SECTION, false); + + glBindFramebuffer(GL_FRAMEBUFFER, storage->frame.current_rt->fbo); //back to front + glViewport(0, 0, storage->frame.current_rt->width, storage->frame.current_rt->height); + state.canvas_shader.bind(); //back to canvas + + if (state.using_texture_rect) { + state.using_texture_rect = false; + _set_texture_rect_mode(state.using_texture_rect, state.using_ninepatch); + } +} + void RasterizerCanvasGLES3::canvas_render_items(Item *p_item_list, int p_z, const Color &p_modulate, Light *p_light) { Item *current_clip = NULL; @@ -875,44 +1064,17 @@ void RasterizerCanvasGLES3::canvas_render_items(Item *p_item_list, int p_z, cons glDisable(GL_SCISSOR_TEST); } } -#if 0 - if (ci->copy_back_buffer && framebuffer.active && framebuffer.scale==1) { - Rect2 rect; - int x,y; + if (ci->copy_back_buffer) { if (ci->copy_back_buffer->full) { - x = viewport.x; - y = window_size.height-(viewport.height+viewport.y); - } else { - x = viewport.x+ci->copy_back_buffer->screen_rect.pos.x; - y = window_size.height-(viewport.y+ci->copy_back_buffer->screen_rect.pos.y+ci->copy_back_buffer->screen_rect.size.y); - } - glActiveTexture(GL_TEXTURE0+max_texture_units-1); - glBindTexture(GL_TEXTURE_2D,framebuffer.sample_color); - -#ifdef GLEW_ENABLED - if (current_rt) { - glReadBuffer(GL_COLOR_ATTACHMENT0); + _copy_texscreen(Rect2()); } else { - glReadBuffer(GL_BACK); + _copy_texscreen(ci->copy_back_buffer->rect); } -#endif - if (current_rt) { - glCopyTexSubImage2D(GL_TEXTURE_2D,0,viewport.x,viewport.y,viewport.x,viewport.y,viewport.width,viewport.height); - //window_size.height-(viewport.height+viewport.y) - } else { - glCopyTexSubImage2D(GL_TEXTURE_2D,0,x,y,x,y,viewport.width,viewport.height); - } - - canvas_texscreen_used=true; - glActiveTexture(GL_TEXTURE0); - } -#endif - //begin rect Item *material_owner = ci->material_owner ? ci->material_owner : ci; @@ -934,6 +1096,11 @@ void RasterizerCanvasGLES3::canvas_render_items(Item *p_item_list, int p_z, cons if (shader_ptr && shader_ptr != shader_cache) { + if (shader_ptr->canvas_item.uses_screen_texture && !state.canvas_texscreen_used) { + //copy if not copied before + _copy_texscreen(Rect2()); + } + state.canvas_shader.set_custom_shader(shader_ptr->custom_code_id); state.canvas_shader.bind(); @@ -1046,7 +1213,11 @@ void RasterizerCanvasGLES3::canvas_render_items(Item *p_item_list, int p_z, cons 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 (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 { + state.canvas_shader.set_uniform(CanvasShaderGLES3::SCREEN_PIXEL_SIZE, Vector2(1.0, 1.0)); + } if (unshaded || (state.canvas_item_modulate.a > 0.001 && (!shader_cache || shader_cache->canvas_item.light_mode != RasterizerStorageGLES3::Shader::CanvasItem::LIGHT_MODE_LIGHT_ONLY) && !ci->light_masked)) _canvas_item_render_commands(ci, current_clip, reclip); @@ -1376,6 +1547,12 @@ void RasterizerCanvasGLES3::reset_canvas() { glBindBuffer(GL_ARRAY_BUFFER, 0); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); + //use for reading from screen + if (storage->frame.current_rt) { + glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 3); + glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->effects.mip_maps[0].color); + } + glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, storage->resources.white_tex); @@ -1543,7 +1720,7 @@ void RasterizerCanvasGLES3::initialize() { glBindBuffer(GL_UNIFORM_BUFFER, 0); state.canvas_shader.init(); - state.canvas_shader.set_base_material_tex_index(1); + state.canvas_shader.set_base_material_tex_index(2); state.canvas_shadow_shader.init(); state.canvas_shader.set_conditional(CanvasShaderGLES3::USE_RGBA_SHADOWS, storage->config.use_rgba_2d_shadows); |