From 13b1756394006a60eb7e9fc59ed9fd3017a3b7f9 Mon Sep 17 00:00:00 2001 From: Oleksandr Shcherbina Date: Tue, 10 Nov 2015 15:10:09 -0800 Subject: [PATCH] evas: add possibility to render current 3D scene to texture in Evas.Canvas3d Summary: Refactoring code of functions e3d_drawable_scene_render, e3d_drawable_scene_render_to_texture,_shadowmap_render to have possibility render in scene to additional texture See T2761 Reviewers: Hermet, cedric Subscribers: cedric Differential Revision: https://phab.enlightenment.org/D3142 Signed-off-by: Cedric BAIL --- src/lib/evas/canvas/evas_canvas3d_scene.c | 1 + src/lib/evas/include/evas_private.h | 1 + .../evas/engines/gl_common/evas_gl_3d.c | 142 ++++++++++-------- .../engines/gl_common/evas_gl_3d_private.h | 1 + .../engines/gl_common/evas_gl_3d_renderer.c | 19 +++ 5 files changed, 100 insertions(+), 64 deletions(-) diff --git a/src/lib/evas/canvas/evas_canvas3d_scene.c b/src/lib/evas/canvas/evas_canvas3d_scene.c index 6bc4487bd7..d0634d4bc2 100644 --- a/src/lib/evas/canvas/evas_canvas3d_scene.c +++ b/src/lib/evas/canvas/evas_canvas3d_scene.c @@ -11,6 +11,7 @@ evas_canvas3d_scene_data_init(Evas_Canvas3D_Scene_Public_Data *data) data->mesh_nodes = NULL; data->node_mesh_colors = NULL; data->colors_node_mesh = NULL; + data->render_to_texture = EINA_FALSE; } void diff --git a/src/lib/evas/include/evas_private.h b/src/lib/evas/include/evas_private.h index f237a2e66f..92c4444d15 100644 --- a/src/lib/evas/include/evas_private.h +++ b/src/lib/evas/include/evas_private.h @@ -447,6 +447,7 @@ struct _Evas_Canvas3D_Scene_Public_Data /*sets constant for shadow rendering*/ Evas_Real depth_offset; Evas_Real depth_constant; + Eina_Bool render_to_texture; }; struct _Evas_Canvas3D_Pick_Data diff --git a/src/modules/evas/engines/gl_common/evas_gl_3d.c b/src/modules/evas/engines/gl_common/evas_gl_3d.c index 93c2e85815..357039cc24 100644 --- a/src/modules/evas/engines/gl_common/evas_gl_3d.c +++ b/src/modules/evas/engines/gl_common/evas_gl_3d.c @@ -1200,11 +1200,21 @@ void _shadowmap_render(E3D_Drawable *drawable, E3D_Renderer *renderer, glDisable(GL_POLYGON_OFFSET_FILL); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, drawable->tex, 0); + if (data->render_to_texture) + { + data->render_to_texture = EINA_FALSE; + e3d_renderer_color_pick_target_set(renderer, drawable); + } + else + { + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, + drawable->tex, 0); + e3d_renderer_clear(renderer, &data->bg_color); + } } void -e3d_drawable_scene_render(E3D_Drawable *drawable, E3D_Renderer *renderer, Evas_Canvas3D_Scene_Public_Data *data) +_scene_render(E3D_Drawable *drawable, E3D_Renderer *renderer, Evas_Canvas3D_Scene_Public_Data *data) { Eina_List *l; Evas_Canvas3D_Node *n; @@ -1232,12 +1242,9 @@ e3d_drawable_scene_render(E3D_Drawable *drawable, E3D_Renderer *renderer, Evas_C _shadowmap_render(drawable, renderer, data, &matrix_light_eye, light); } - /* Set up render target. */ - e3d_renderer_target_set(renderer, drawable); - e3d_renderer_clear(renderer, &data->bg_color); - eina_matrix4_multiply(&matrix_vp, &pd->projection, matrix_eye); evas_frustum_calculate(planes, &matrix_vp); + EINA_LIST_FOREACH(data->mesh_nodes, l, n) { Eina_Matrix4 matrix_mv; @@ -1282,6 +1289,17 @@ e3d_drawable_scene_render(E3D_Drawable *drawable, E3D_Renderer *renderer, Evas_C e3d_renderer_flush(renderer); } +void +e3d_drawable_scene_render(E3D_Drawable *drawable, E3D_Renderer *renderer, Evas_Canvas3D_Scene_Public_Data *data) +{ + /* Set up render target. */ + e3d_renderer_target_set(renderer, drawable); + e3d_renderer_clear(renderer, &data->bg_color); + + /*Render scene data*/ + _scene_render(drawable, renderer, data); +} + Eina_Bool e3d_drawable_scene_render_to_texture(E3D_Drawable *drawable, E3D_Renderer *renderer, Evas_Canvas3D_Scene_Public_Data *data) @@ -1294,71 +1312,67 @@ e3d_drawable_scene_render_to_texture(E3D_Drawable *drawable, E3D_Renderer *rende Eina_List *repeat_node = NULL; Evas_Color c = {0.0, 0.0, 0.0, 0.0}, *unic_color = NULL; - glBindFramebuffer(GL_FRAMEBUFFER, drawable->color_pick_fb_id); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, - GL_TEXTURE_2D, drawable->texcolorpick, 0); -#ifdef GL_GLES - glBindRenderbuffer(GL_RENDERBUFFER, drawable->depth_stencil_buf); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, - GL_TEXTURE_2D, drawable->depth_stencil_buf, 0); -#else - glBindRenderbuffer(GL_RENDERBUFFER, drawable->depth_stencil_buf); - glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, - GL_RENDERBUFFER, drawable->depth_stencil_buf); -#endif - + e3d_renderer_color_pick_target_set(renderer, drawable); e3d_renderer_clear(renderer, &c); - Evas_Canvas3D_Node_Data *pd_camera_node = eo_data_scope_get(data->camera_node, EVAS_CANVAS3D_NODE_CLASS); - matrix_eye = &pd_camera_node->data.camera.matrix_world_to_eye; - Evas_Canvas3D_Camera_Data *pd = eo_data_scope_get(pd_camera_node->data.camera.camera, EVAS_CANVAS3D_CAMERA_CLASS); - - itmn = eina_hash_iterator_data_new(data->colors_node_mesh); - - while (eina_iterator_next(itmn, &ptrmn)) + if (data->color_pick_enabled) //Use rendering to texture in color pick mechanism { - Evas_Canvas3D_Node *n; - Eina_Array *arr = NULL; + Evas_Canvas3D_Node_Data *pd_camera_node = eo_data_scope_get(data->camera_node, EVAS_CANVAS3D_NODE_CLASS); + matrix_eye = &pd_camera_node->data.camera.matrix_world_to_eye; + Evas_Canvas3D_Camera_Data *pd = eo_data_scope_get(pd_camera_node->data.camera.camera, EVAS_CANVAS3D_CAMERA_CLASS); - arr = (Eina_Array *)ptrmn; - n = (Evas_Canvas3D_Node *)eina_array_data_get(arr, 0); - /*To avoid repeatedly render mesh*/ - if (!repeat_node) - repeat_node = eina_list_append(repeat_node, (void*)n); - else - { - if (eina_list_data_find(repeat_node, (void *)n)) - continue; - else - repeat_node = eina_list_append(repeat_node, (void *)n); - } - Evas_Canvas3D_Node_Data *pd_mesh_node = eo_data_scope_get(n, EVAS_CANVAS3D_NODE_CLASS); - RENDER_MESH_NODE_ITERATE_BEGIN(eye) - { - if (pdmesh->color_pick_enabled) - { - tmp = eina_stringshare_printf("%p %p", n, nm->mesh); - unic_color = (Evas_Color *)eina_hash_find(data->node_mesh_colors, tmp); - if (unic_color) - { - pdmesh->color_pick_key.r = unic_color->r; - pdmesh->color_pick_key.g = unic_color->g; - pdmesh->color_pick_key.b = unic_color->b; - shade_mode = pdmesh->shade_mode; - pdmesh->shade_mode = EVAS_CANVAS3D_SHADE_MODE_COLOR_PICK; - _mesh_draw(renderer, nm->mesh, nm->frame, NULL, matrix_eye, &matrix_mv, - &matrix_mvp, NULL); - pdmesh->shade_mode = shade_mode; - } - eina_stringshare_del(tmp); - } - } - RENDER_MESH_NODE_ITERATE_END + itmn = eina_hash_iterator_data_new(data->colors_node_mesh); + + while (eina_iterator_next(itmn, &ptrmn)) + { + Evas_Canvas3D_Node *n; + Eina_Array *arr = NULL; + + arr = (Eina_Array *)ptrmn; + n = (Evas_Canvas3D_Node *)eina_array_data_get(arr, 0); + /*To avoid repeatedly render mesh*/ + if (!repeat_node) + repeat_node = eina_list_append(repeat_node, (void*)n); + else + { + if (eina_list_data_find(repeat_node, (void *)n)) + continue; + else + repeat_node = eina_list_append(repeat_node, (void *)n); + } + Evas_Canvas3D_Node_Data *pd_mesh_node = eo_data_scope_get(n, EVAS_CANVAS3D_NODE_CLASS); + RENDER_MESH_NODE_ITERATE_BEGIN(eye) + { + if (pdmesh->color_pick_enabled) + { + tmp = eina_stringshare_printf("%p %p", n, nm->mesh); + unic_color = (Evas_Color *)eina_hash_find(data->node_mesh_colors, tmp); + if (unic_color) + { + pdmesh->color_pick_key.r = unic_color->r; + pdmesh->color_pick_key.g = unic_color->g; + pdmesh->color_pick_key.b = unic_color->b; + shade_mode = pdmesh->shade_mode; + pdmesh->shade_mode = EVAS_CANVAS3D_SHADE_MODE_COLOR_PICK; + _mesh_draw(renderer, nm->mesh, nm->frame, NULL, matrix_eye, &matrix_mv, + &matrix_mvp, NULL); + pdmesh->shade_mode = shade_mode; + } + eina_stringshare_del(tmp); + } + } + RENDER_MESH_NODE_ITERATE_END + } + eina_iterator_free(itmn); + eina_list_free(repeat_node); + } + else + { + _scene_render(drawable, renderer, data); //Just render scene in texture } - eina_iterator_free(itmn); - eina_list_free(repeat_node); glBindFramebuffer(GL_FRAMEBUFFER, drawable->fbo); + return EINA_TRUE; } diff --git a/src/modules/evas/engines/gl_common/evas_gl_3d_private.h b/src/modules/evas/engines/gl_common/evas_gl_3d_private.h index 387eafedfe..56f98c17cd 100644 --- a/src/modules/evas/engines/gl_common/evas_gl_3d_private.h +++ b/src/modules/evas/engines/gl_common/evas_gl_3d_private.h @@ -170,5 +170,6 @@ void e3d_renderer_viewport_set(E3D_Renderer *renderer, int x, in void e3d_renderer_clear(E3D_Renderer *renderer, const Evas_Color *color); void e3d_renderer_draw(E3D_Renderer *renderer, E3D_Draw_Data *data); void e3d_renderer_flush(E3D_Renderer *renderer); +void e3d_renderer_color_pick_target_set(E3D_Renderer *renderer, E3D_Drawable *drawable); #endif /* EVAS_GL_3D_PRIVATE_H */ diff --git a/src/modules/evas/engines/gl_common/evas_gl_3d_renderer.c b/src/modules/evas/engines/gl_common/evas_gl_3d_renderer.c index 2b0e7aed3f..aff604caa3 100644 --- a/src/modules/evas/engines/gl_common/evas_gl_3d_renderer.c +++ b/src/modules/evas/engines/gl_common/evas_gl_3d_renderer.c @@ -271,6 +271,25 @@ e3d_renderer_target_set(E3D_Renderer *renderer, E3D_Drawable *target) renderer->texDepth = target->texDepth; } +void +e3d_renderer_color_pick_target_set(E3D_Renderer *renderer, E3D_Drawable *drawable) +{ + glBindFramebuffer(GL_FRAMEBUFFER, drawable->color_pick_fb_id); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, + GL_TEXTURE_2D, drawable->texcolorpick, 0); +#ifdef GL_GLES + glBindRenderbuffer(GL_RENDERBUFFER, drawable->depth_stencil_buf); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, + GL_TEXTURE_2D, drawable->depth_stencil_buf, 0); +#else + glBindRenderbuffer(GL_RENDERBUFFER, drawable->depth_stencil_buf); + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, + GL_RENDERBUFFER, drawable->depth_stencil_buf); +#endif + glViewport(0, 0, drawable->w, drawable->h); + renderer->texDepth = drawable->texDepth; +} + void e3d_renderer_clear(E3D_Renderer *renderer EINA_UNUSED, const Evas_Color *color) {