cedric pushed a commit to branch master. http://git.enlightenment.org/core/efl.git/commit/?id=00c2451656167dc4a42dfa1ef84fa7f21e5dc48e
commit 00c2451656167dc4a42dfa1ef84fa7f21e5dc48e Author: Oleksandr Shcherbina <o.shcherb...@samsung.com> Date: Thu Feb 5 15:34:25 2015 +0100 evas: Evas_3D - ColorPick mechanism finding node and mesh in scene. Summary: Added additional texture and framebuffer for rendering meshes to it. Added function that return OpenGL id additional texture Added function that return color from target texture by mouse pick coordinates Added function that render need meshes to target texture Added engine wrappers for possibility force render to texture @feature Reviewers: Hermet, raster, cedric Subscribers: cedric Differential Revision: https://phab.enlightenment.org/D1811 Signed-off-by: Cedric BAIL <ced...@osg.samsung.com> --- src/lib/evas/Evas_Eo.h | 4 +- src/lib/evas/include/evas_private.h | 10 ++ src/modules/evas/engines/gl_common/evas_gl_3d.c | 166 ++++++++++++++++++--- .../evas/engines/gl_common/evas_gl_3d_common.h | 3 + .../evas/engines/gl_common/evas_gl_3d_private.h | 6 +- .../evas/engines/gl_common/evas_gl_3d_shader.c | 15 +- src/modules/evas/engines/gl_generic/evas_engine.c | 33 ++++ 7 files changed, 216 insertions(+), 21 deletions(-) diff --git a/src/lib/evas/Evas_Eo.h b/src/lib/evas/Evas_Eo.h index 39c568b..8fa89b3 100644 --- a/src/lib/evas/Evas_Eo.h +++ b/src/lib/evas/Evas_Eo.h @@ -487,6 +487,7 @@ typedef enum _Evas_3D_State EVAS_3D_STATE_MESH_SHADE_MODE, EVAS_3D_STATE_MESH_FOG, EVAS_3D_STATE_MESH_BLENDING, + EVAS_3D_STATE_MESH_COLOR_PICK, EVAS_3D_STATE_CAMERA_PROJECTION = 1, @@ -777,7 +778,8 @@ typedef enum _Evas_3D_Shade_Mode EVAS_3D_SHADE_MODE_NORMAL_MAP, /**< fragment color is defined by its z-coord*/ EVAS_3D_SHADE_MODE_SHADOW_MAP_RENDER, - + /**< rendering to additional frame bufer*/ + EVAS_3D_SHADE_MODE_COLOR_PICK, } Evas_3D_Shade_Mode; /** diff --git a/src/lib/evas/include/evas_private.h b/src/lib/evas/include/evas_private.h index 673b6aa..e0f8171 100644 --- a/src/lib/evas/include/evas_private.h +++ b/src/lib/evas/include/evas_private.h @@ -340,6 +340,9 @@ struct _Evas_3D_Mesh Evas_Color fog_color; Eina_Bool fog_enabled :1; + + double color_pick_key; + Eina_Bool color_pick_enabled :1; }; struct _Evas_3D_Texture @@ -376,6 +379,9 @@ struct _Evas_3D_Scene_Public_Data Eina_List *light_nodes; Eina_List *mesh_nodes; Eina_Bool shadows_enabled :1; + Eina_Bool color_pick_enabled :1; + Eina_Hash *node_mesh_colors; + Eina_Hash *colors_node_mesh; }; struct _Evas_3D_Pick_Data @@ -1319,6 +1325,10 @@ struct _Evas_Func void *(*image_drawable_set) (void *data, void *image, void *drawable); void (*drawable_scene_render) (void *data, void *drawable, void *scene_data); + Eina_Bool (*drawable_scene_render_to_texture) (void *data, void *drawable, void *scene_data); + + int (*drawable_texture_color_pick_id_get) (void *drawable); + double (*drawable_texture_pixel_color_get) (unsigned int tex EINA_UNUSED, int x, int y, void *drawable); void *(*texture_new) (void *data); void (*texture_free) (void *data, void *texture); 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 4f045d2..ee464f4 100644 --- a/src/modules/evas/engines/gl_common/evas_gl_3d.c +++ b/src/modules/evas/engines/gl_common/evas_gl_3d.c @@ -1,6 +1,23 @@ #include "evas_gl_private.h" #include "evas_gl_3d_private.h" +#define RENDER_MESH_NODE_ITERATE_BEGIN(param) \ + Evas_Mat4 matrix_mv; \ + Evas_Mat4 matrix_mvp; \ + Eina_Iterator *it; \ + void *ptr; \ + evas_mat4_multiply(&matrix_mv, matrix_##param, &pd_mesh_node->data.mesh.matrix_local_to_world); \ + evas_mat4_multiply(&matrix_mvp, &pd->projection, &matrix_mv); \ + it = eina_hash_iterator_data_new(pd_mesh_node->data.mesh.node_meshes); \ + while (eina_iterator_next(it, &ptr)) \ + { \ + Evas_3D_Node_Mesh *nm = (Evas_3D_Node_Mesh *)ptr; \ + Evas_3D_Mesh_Data *pdmesh = eo_data_scope_get(nm->mesh, EVAS_3D_MESH_CLASS); + +#define RENDER_MESH_NODE_ITERATE_END \ + } \ + eina_iterator_free(it); + void e3d_texture_param_update(E3D_Texture *texture) { @@ -407,7 +424,7 @@ E3D_Drawable * e3d_drawable_new(int w, int h, int alpha, GLenum depth_format, GLenum stencil_format) { E3D_Drawable *drawable = NULL; - GLuint tex, fbo, texDepth; + GLuint tex, fbo, texDepth, texcolorpick, color_pick_fb_id; GLuint depth_stencil_buf = 0; GLuint depth_buf = 0; GLuint stencil_buf = 0; @@ -435,6 +452,18 @@ e3d_drawable_new(int w, int h, int alpha, GLenum depth_format, GLenum stencil_fo glTexImage2D(GL_TEXTURE_2D, 0, GL_R16, w, h, 0, GL_RED, GL_UNSIGNED_SHORT, 0); #endif + glGenTextures(1, &texcolorpick); + glBindTexture(GL_TEXTURE_2D, texcolorpick); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); +#ifndef GL_GLES + glTexImage2D(GL_TEXTURE_2D, 0, GL_R16, w, h, 0, GL_RED, GL_UNSIGNED_SHORT, 0); +#endif + + glGenFramebuffers(1, &color_pick_fb_id); + glGenFramebuffers(1, &fbo); glBindFramebuffer(GL_FRAMEBUFFER, fbo); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, 0); @@ -511,6 +540,8 @@ e3d_drawable_new(int w, int h, int alpha, GLenum depth_format, GLenum stencil_fo drawable->tex = tex; drawable->fbo = fbo; drawable->depth_stencil_buf = depth_stencil_buf; + drawable->texcolorpick = texcolorpick; + drawable->color_pick_fb_id = color_pick_fb_id; drawable->depth_buf = depth_buf; drawable->stencil_buf = stencil_buf; drawable->texDepth = texDepth; @@ -522,9 +553,13 @@ error: if (tex) glDeleteTextures(1, &tex); + if (texcolorpick) + glDeleteTextures(1, &texcolorpick); if (fbo) glDeleteFramebuffers(1, &fbo); + if (color_pick_fb_id) + glDeleteFramebuffers(1, &color_pick_fb_id); if (depth_stencil_buf) { @@ -595,6 +630,12 @@ e3d_drawable_texture_id_get(E3D_Drawable *drawable) return drawable->tex; } +GLuint +e3d_drawable_texture_color_pick_id_get(E3D_Drawable *drawable) +{ + return drawable->texcolorpick; +} + GLenum e3d_drawable_format_get(E3D_Drawable *drawable) { @@ -1105,6 +1146,12 @@ _mesh_draw_data_build(E3D_Draw_Data *data, if (pdmesh->shadowed) data->flags |= E3D_SHADER_FLAG_SHADOWED; + if (pdmesh->color_pick_enabled) + { + data->flags |= E3D_SHADER_FLAG_COLOR_PICK_ENABLED; + data->color_pick_key = pdmesh->color_pick_key; + } + data->blending = pdmesh->blending; data->blend_sfactor = pdmesh->blend_sfactor; data->blend_dfactor = pdmesh->blend_dfactor; @@ -1141,6 +1188,10 @@ _mesh_draw_data_build(E3D_Draw_Data *data, { BUILD(vertex_attrib, VERTEX_POSITION, EINA_TRUE); } + else if (pdmesh->shade_mode == EVAS_3D_SHADE_MODE_COLOR_PICK) + { + BUILD(vertex_attrib, VERTEX_POSITION, EINA_TRUE); + } else if (pdmesh->shade_mode == EVAS_3D_SHADE_MODE_DIFFUSE) { BUILD(vertex_attrib, VERTEX_POSITION, EINA_TRUE); @@ -1256,32 +1307,18 @@ void _shadowmap_render(E3D_Drawable *drawable, E3D_Renderer *renderer, Evas_3D_S EINA_LIST_FOREACH(data->mesh_nodes, l, n) { - Evas_Mat4 matrix_mv; - Evas_Mat4 matrix_mvp; - Eina_Iterator *it; - void *ptr; - Evas_3D_Node_Data *pd_mesh_node = eo_data_scope_get(n, EVAS_3D_NODE_CLASS); if (evas_is_sphere_in_frustum(&pd_mesh_node->bsphere, planes)) { - - evas_mat4_multiply(&matrix_mv, matrix_light_eye, &pd_mesh_node->data.mesh.matrix_local_to_world); - evas_mat4_multiply(&matrix_mvp, &pd->projection, - &matrix_mv); - - it = eina_hash_iterator_data_new(pd_mesh_node->data.mesh.node_meshes); - - while (eina_iterator_next(it, &ptr)) + RENDER_MESH_NODE_ITERATE_BEGIN(light_eye) { - Evas_3D_Node_Mesh *nm = (Evas_3D_Node_Mesh *)ptr; - Evas_3D_Mesh_Data *pdmesh = eo_data_scope_get(nm->mesh, EVAS_3D_MESH_CLASS); shade_mode = pdmesh->shade_mode; pdmesh->shade_mode = EVAS_3D_SHADE_MODE_SHADOW_MAP_RENDER; _mesh_draw(renderer, nm->mesh, nm->frame, light, matrix_light_eye, &matrix_mv, &matrix_mvp, &matrix_mvp); pdmesh->shade_mode = shade_mode; } - eina_iterator_free(it); + RENDER_MESH_NODE_ITERATE_END } } @@ -1367,3 +1404,98 @@ e3d_drawable_scene_render(E3D_Drawable *drawable, E3D_Renderer *renderer, Evas_3 } e3d_renderer_flush(renderer); } + +Eina_Bool +e3d_drawable_scene_render_to_texture(E3D_Drawable *drawable, E3D_Renderer *renderer, + Evas_3D_Scene_Public_Data *data) +{ + const Evas_Mat4 *matrix_eye; + Evas_3D_Shade_Mode shade_mode; + Eina_Stringshare *tmp; + Eina_Iterator *itmn; + void *ptrmn; + Eina_List *repeat_node = NULL; + Evas_Color c = {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 + glBindTexture(GL_TEXTURE_2D, 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_clear(renderer, &c); + + Evas_3D_Node_Data *pd_camera_node = eo_data_scope_get(data->camera_node, EVAS_3D_NODE_CLASS); + matrix_eye = &pd_camera_node->data.camera.matrix_world_to_eye; + Evas_3D_Camera_Data *pd = eo_data_scope_get(pd_camera_node->data.camera.camera, EVAS_3D_CAMERA_CLASS); + + itmn = eina_hash_iterator_data_new(data->colors_node_mesh); + + while (eina_iterator_next(itmn, &ptrmn)) + { + Evas_3D_Node *n; + Eina_Array *arr = NULL; + + arr = (Eina_Array *)ptrmn; + n = (Evas_3D_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_3D_Node_Data *pd_mesh_node = eo_data_scope_get(n, EVAS_3D_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 = unic_color->r; + shade_mode = pdmesh->shade_mode; + pdmesh->shade_mode = EVAS_3D_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); + glBindFramebuffer(GL_FRAMEBUFFER, drawable->fbo); + return EINA_TRUE; +} + +double +e3d_drawable_texture_pixel_color_get(GLuint tex EINA_UNUSED, int x, int y, + void *drawable) +{ + E3D_Drawable *d = (E3D_Drawable *)drawable; + GLuint pixel; + + glBindFramebuffer(GL_FRAMEBUFFER, d->color_pick_fb_id); + /*TODO Bottle neck - get more effective getting pixels from openGL*/ + glReadPixels(x, y, 1, 1, GL_RED, GL_UNSIGNED_SHORT, &pixel); + glBindFramebuffer(GL_FRAMEBUFFER, d->fbo); + return (double)pixel / USHRT_MAX; +} + +#undef RENDER_MESH_NODE_ITERATE_BEGIN +#undef RENDER_MESH_NODE_ITERATE_END diff --git a/src/modules/evas/engines/gl_common/evas_gl_3d_common.h b/src/modules/evas/engines/gl_common/evas_gl_3d_common.h index ceba63e..f119b40 100644 --- a/src/modules/evas/engines/gl_common/evas_gl_3d_common.h +++ b/src/modules/evas/engines/gl_common/evas_gl_3d_common.h @@ -28,8 +28,11 @@ void e3d_texture_filter_get(const E3D_Texture *texture, Evas_3D_ E3D_Drawable *e3d_drawable_new(int w, int h, int alpha, GLenum depth_format, GLenum stencil_format); void e3d_drawable_free(E3D_Drawable *drawable); void e3d_drawable_scene_render(E3D_Drawable *drawable, E3D_Renderer *renderer, Evas_3D_Scene_Public_Data *data); +Eina_Bool e3d_drawable_scene_render_to_texture(E3D_Drawable *drawable, E3D_Renderer *renderer, Evas_3D_Scene_Public_Data *data); void e3d_drawable_size_get(E3D_Drawable *drawable, int *w, int *h); GLuint e3d_drawable_texture_id_get(E3D_Drawable *drawable); +GLuint e3d_drawable_texture_color_pick_id_get(E3D_Drawable *drawable); +double e3d_drawable_texture_pixel_color_get(GLuint tex EINA_UNUSED, int x, int y, void *drawable); GLenum e3d_drawable_format_get(E3D_Drawable *drawable); /* Renderer */ 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 75a76ac..6d956f5 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 @@ -37,7 +37,7 @@ typedef unsigned long E3D_Shader_Flag; #define E3D_SHADER_FLAG_NORMAL_TEXTURE_BLEND (1 << 28) #define E3D_SHADER_FLAG_FOG_ENABLED (1 << 29) #define E3D_SHADER_FLAG_SHADOWED (1 << 30) - +#define E3D_SHADER_FLAG_COLOR_PICK_ENABLED (1 << 31) static inline Eina_Bool _flags_need_tex_coord(E3D_Shader_Flag flags) @@ -100,6 +100,7 @@ struct _E3D_Draw_Data Evas_Color specular; } light; Evas_Color fog_color; + double color_pick_key; }; struct _E3D_Texture @@ -126,13 +127,14 @@ struct _E3D_Drawable GLenum format; GLenum depth_format; GLenum stencil_format; - GLuint tex; GLuint fbo; GLuint depth_stencil_buf; GLuint depth_buf; GLuint stencil_buf; GLuint texDepth; + GLuint texcolorpick; + GLuint color_pick_fb_id; }; /* Texture internal functions. */ diff --git a/src/modules/evas/engines/gl_common/evas_gl_3d_shader.c b/src/modules/evas/engines/gl_common/evas_gl_3d_shader.c index c036aa1..e042c83 100644 --- a/src/modules/evas/engines/gl_common/evas_gl_3d_shader.c +++ b/src/modules/evas/engines/gl_common/evas_gl_3d_shader.c @@ -49,6 +49,7 @@ typedef enum _E3D_Uniform E3D_UNIFORM_MATERIAL_SHININESS, E3D_UNIFORM_FOG_FACTOR, E3D_UNIFORM_FOG_COLOR, + E3D_UNIFORM_COLOR_PICK, E3D_UNIFORM_COUNT, } E3D_Uniform; @@ -526,6 +527,9 @@ _fragment_shader_string_variable_add(E3D_Shader_String *shader, ADD_LINE("uniform sampler2D uShadowMap;"); } + if (flags & E3D_SHADER_FLAG_COLOR_PICK_ENABLED) + ADD_LINE("uniform float uColorPick;"); + /* Materials. */ if (flags & E3D_SHADER_FLAG_DIFFUSE) { @@ -1151,6 +1155,11 @@ _fragment_shader_string_get(E3D_Shader_String *shader, ADD_LINE("gl_FragColor = mix(uFogColor, gl_FragColor, fogFactor );"); } + if (mode == EVAS_3D_SHADE_MODE_COLOR_PICK) + { + ADD_LINE("gl_FragColor = vec4(uColorPick);"); + } + ADD_LINE("}"); } @@ -1321,7 +1330,8 @@ static const char *uniform_names[] = "uMaterialEmission", "uMaterialShininess", "uFogFactor", - "uFogColor" + "uFogColor", + "uColorPick" }; static inline void @@ -1498,6 +1508,9 @@ _uniform_upload(E3D_Uniform u, GLint loc, const E3D_Draw_Data *data) case E3D_UNIFORM_FOG_COLOR: glUniform4f(loc, data->fog_color.r, data->fog_color.g, data->fog_color.b, 1); break; + case E3D_UNIFORM_COLOR_PICK: + glUniform1f(loc, data->color_pick_key); + break; default: ERR("Invalid uniform ID."); break; diff --git a/src/modules/evas/engines/gl_generic/evas_engine.c b/src/modules/evas/engines/gl_generic/evas_engine.c index e280fdd..082ac0d 100644 --- a/src/modules/evas/engines/gl_generic/evas_engine.c +++ b/src/modules/evas/engines/gl_generic/evas_engine.c @@ -1836,6 +1836,35 @@ eng_drawable_scene_render(void *data, void *drawable, void *scene_data) e3d_drawable_scene_render(drawable, renderer, scene_data); } +static int +eng_drawable_texture_color_pick_id_get(void *drawable) +{ + return e3d_drawable_texture_color_pick_id_get((E3D_Drawable *)drawable); +} + +static double +eng_drawable_texture_pixel_color_get(GLuint tex EINA_UNUSED, int x, int y, void *drawable) +{ + return e3d_drawable_texture_pixel_color_get(tex, x, y, drawable); +} + +static Eina_Bool +eng_drawable_scene_render_to_texture(void *data, void *drawable, void *scene_data) +{ + Evas_Engine_GL_Context *gl_context; + Render_Engine_GL_Generic *re = data; + E3D_Renderer *renderer = NULL; + + re->window_use(re->software.ob); + gl_context = re->window_gl_context_get(re->software.ob); + evas_gl_common_context_flush(gl_context); + + eng_context_3d_use(data); + renderer = eng_renderer_3d_get(data); + + return e3d_drawable_scene_render_to_texture((E3D_Drawable *)drawable, renderer, scene_data); +} + static void * eng_texture_new(void *data EINA_UNUSED) { @@ -2045,6 +2074,10 @@ module_open(Evas_Module *em) ORD(drawable_scene_render); + ORD(drawable_texture_color_pick_id_get); + ORD(drawable_texture_pixel_color_get); + ORD(drawable_scene_render_to_texture); + ORD(texture_new); ORD(texture_free); ORD(texture_data_set); --