evas.canvas3d: Add FXAA post processing render.

Summary:
Add post processing render function as rendering full screen quard after
rendering to texture.
Add possibility use size of current frame in shader.
Add FXAA shader source files

Reviewers: raster, cedric, Hermet

Subscribers: jpeg

Differential Revision: https://phab.enlightenment.org/D3847
This commit is contained in:
Oleksandr Shcherbina 2016-04-12 00:50:46 +09:00 committed by Hermet Park
parent 5f9e73b966
commit 1f66a9e731
13 changed files with 282 additions and 32 deletions

View File

@ -785,6 +785,8 @@ modules/evas/engines/gl_common/shader_3d/color_pick_vert.shd \
modules/evas/engines/gl_common/shader_3d/color_pick_frag.shd \
modules/evas/engines/gl_common/shader_3d/parallax_occlusion_vert.shd \
modules/evas/engines/gl_common/shader_3d/parallax_occlusion_frag.shd \
modules/evas/engines/gl_common/shader_3d/post_processing_fxaa_vert.shd \
modules/evas/engines/gl_common/shader_3d/post_processing_fxaa_frag.shd \
$(NULL)
EXTRA_DIST += \

View File

@ -29,7 +29,7 @@ _efl_canvas_scene3d_scene3d_get(Eo *eo_obj, void *pd EINA_UNUSED)
}
void
_evas_image_3d_render(Evas *eo_e, Evas_Object *eo_obj EINA_UNUSED,
_evas_image_3d_render(Evas *eo_e, Evas_Object *eo_obj,
Evas_Object_Protected_Data *obj, Evas_Image_Data *o EINA_UNUSED,
Evas_Canvas3D_Scene *scene)
{
@ -107,7 +107,14 @@ _evas_image_3d_render(Evas *eo_e, Evas_Object *eo_obj EINA_UNUSED,
scene_data.camera_node = pd_scene->camera_node;
scene_data.depth_offset = pd_scene->depth_offset;
scene_data.depth_constant = pd_scene->depth_constant;
if (evas_object_anti_alias_get(eo_obj))
{
/*Use post processing render*/
scene_data.post_processing = EINA_TRUE;
scene_data.color_pick_enabled = EINA_FALSE;
scene_data.render_to_texture = EINA_TRUE;
scene_data.post_processing_type = EVAS_CANVAS3D_SHADE_MODE_POST_PROCESSING_FXAA;
}
/* Phase 1 - Update scene graph tree. */
evas_canvas3d_object_update(scene);

View File

@ -13,6 +13,8 @@ evas_canvas3d_scene_data_init(Evas_Canvas3D_Scene_Public_Data *data)
data->colors_node_mesh = NULL;
data->render_to_texture = EINA_FALSE;
data->lod_distance = 0;
data->post_processing = EINA_FALSE;
data->post_processing_type = EVAS_CANVAS3D_SHADE_MODE_POST_PROCESSING_FXAA;
}
void
@ -78,7 +80,6 @@ _evas_canvas3d_scene_eo_base_constructor(Eo *obj, Evas_Canvas3D_Scene_Data *pd)
pd->colors_node_mesh = NULL;
pd->depth_offset = 4.0;
pd->depth_constant = 100.0;
return obj;
}
@ -635,6 +636,7 @@ _evas_canvas3d_scene_pick(const Eo *obj, Evas_Canvas3D_Scene_Data *pd, Evas_Real
scene_data.camera_node = pd->camera_node;
scene_data.color_pick_enabled = pd->color_pick_enabled;
update_scene = evas_canvas3d_object_dirty_get(obj, EVAS_CANVAS3D_STATE_SCENE_UPDATED);
scene_data.post_processing = EINA_FALSE;
if (update_scene)
{
if (pd->node_mesh_colors)

View File

@ -160,7 +160,7 @@ class Evas.Canvas3D.Scene (Evas.Canvas3D.Object, Evas.Common_Interface)
depth offset]]
}
}
}
}
implements {
Eo.Base.constructor;
Evas.Canvas3D.Object.update_notify;

View File

@ -297,6 +297,7 @@ enum Evas.Canvas3D.State
scene_shadows_enabled,
scene_updated, [[@since 1.14]]
scene_shadows_depth,
scene_render_to_texture,
texture_data = 1,
texture_wrap,
@ -487,14 +488,15 @@ enum Evas.Canvas3D.Shade_Mode
[[Shader shade modes
@since 1.10]]
vertex_color = 0, [[Shaded using vertex color attribute]]
diffuse, [[Shaded using material diffuse term]]
flat, [[Per-vertex flat lighting]]
phong, [[Per-pixel phong shading]]
normal_map, [[Per-pixel normal map shading]]
shadow_map_render, [[Fragment color is defined by its z-coord]]
color_pick, [[Rendering to additional frame bufer]]
parallax_occlusion [[Per-pixel parallax occlusion map shading]]
vertex_color = 0, [[Shaded using vertex color attribute]]
diffuse, [[Shaded using material diffuse term]]
flat, [[Per-vertex flat lighting]]
phong, [[Per-pixel phong shading]]
normal_map, [[Per-pixel normal map shading]]
shadow_map_render, [[Fragment color is defined by its z-coord]]
color_pick, [[Rendering to additional frame bufer]]
parallax_occlusion, [[Per-pixel parallax occlusion map shading]]
post_processing_FXAA [[Render full screen quard]]
}
enum Evas.Canvas3D.Vertex_Attrib

View File

@ -458,6 +458,9 @@ struct _Evas_Canvas3D_Scene_Public_Data
Eina_Bool render_to_texture;
unsigned int lod_distance;
Eina_Bool post_processing :1;
Evas_Canvas3D_Shade_Mode post_processing_type;
};
struct _Evas_Canvas3D_Pick_Data

View File

@ -1167,7 +1167,6 @@ void _shadowmap_render(E3D_Drawable *drawable, E3D_Renderer *renderer,
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
drawable->texDepth, 0);
e3d_renderer_target_set(renderer, drawable);
e3d_renderer_clear(renderer, &c);
Evas_Canvas3D_Node_Data *pd_light_node = eo_data_scope_get(light, EVAS_CANVAS3D_NODE_CLASS);
@ -1199,19 +1198,20 @@ void _shadowmap_render(E3D_Drawable *drawable, E3D_Renderer *renderer,
}
}
glDisable(GL_POLYGON_OFFSET_FILL);
glDisable(GL_POLYGON_OFFSET_FILL);
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);
}
if (data->render_to_texture)
{
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
drawable->texcolorpick, 0);
e3d_renderer_clear(renderer, &data->bg_color);
}
else
{
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
drawable->tex, 0);
e3d_renderer_clear(renderer, &data->bg_color);
}
}
void
@ -1301,8 +1301,49 @@ e3d_drawable_scene_render(E3D_Drawable *drawable, E3D_Renderer *renderer, Evas_C
e3d_renderer_target_set(renderer, drawable);
e3d_renderer_clear(renderer, &data->bg_color);
/*Render scene data*/
_scene_render(drawable, renderer, data);
if (data->post_processing)
e3d_drawable_scene_render_to_texture(drawable, renderer, data);//Render to additional texture
else
_scene_render(drawable, renderer, data);//Common main render
}
void
_scene_post_render(E3D_Drawable *drawable, E3D_Renderer *renderer, Evas_Canvas3D_Scene_Public_Data *data)
{
E3D_Draw_Data drawable_data;
float vertices_of_square[] = {-1.0, 1.0, 0.0, 1.0, 1.0, 0.0,
-1.0, -1.0, 0.0, 1.0, -1.0, 0.0};
unsigned short indices_of_square[] = {0, 1, 2, 2, 1, 3};
memset(&drawable_data, 0x00, sizeof(E3D_Draw_Data));
drawable_data.flags |= E3D_SHADER_FLAG_VERTEX_POSITION;
drawable_data.mode = data->post_processing_type;
drawable_data.assembly = EVAS_CANVAS3D_VERTEX_ASSEMBLY_TRIANGLES;
drawable_data.indices = indices_of_square;
drawable_data.vertex_count = 4;
drawable_data.index_count = 6;
drawable_data.index_format = EVAS_CANVAS3D_INDEX_FORMAT_UNSIGNED_SHORT;
eina_matrix4_identity(&drawable_data.matrix_mv);
eina_matrix4_identity(&drawable_data.matrix_mvp);
drawable_data.frame_size_h = (Evas_Real)drawable->h;
drawable_data.frame_size_w = (Evas_Real)drawable->w;
/*Initialize Evas_Canvas3D_Vertex_Buffer for full screen quard*/
drawable_data.vertices[EVAS_CANVAS3D_VERTEX_ATTRIB_POSITION].vertex0.data = (void *)vertices_of_square;
drawable_data.vertices[EVAS_CANVAS3D_VERTEX_ATTRIB_POSITION].vertex0.element_count = 3;
drawable_data.vertices[EVAS_CANVAS3D_VERTEX_ATTRIB_POSITION].vertex0.stride = 3 * sizeof(float);
drawable_data.vertices[EVAS_CANVAS3D_VERTEX_ATTRIB_POSITION].vertex0.owns_data = EINA_FALSE;
drawable_data.vertices[EVAS_CANVAS3D_VERTEX_ATTRIB_POSITION].vertex0.size = 0;
e3d_renderer_clear(renderer, &data->bg_color);
/*Initialize texture units*/
drawable_data.smap_sampler = e3d_renderer_sampler_shadowmap_get(renderer);
drawable_data.colortex_sampler = e3d_renderer_sampler_colortexture_get(renderer);
/*Render full screen quard with color pick texture unit*/
e3d_renderer_draw(renderer, &drawable_data);
e3d_renderer_flush(renderer);
}
Eina_Bool
@ -1315,10 +1356,10 @@ e3d_drawable_scene_render_to_texture(E3D_Drawable *drawable, E3D_Renderer *rende
Eina_Iterator *itmn;
void *ptrmn;
Eina_List *repeat_node = NULL;
Evas_Color c = {0.0, 0.0, 0.0, 0.0}, *unic_color = NULL;
Evas_Color *unic_color = NULL;
e3d_renderer_color_pick_target_set(renderer, drawable);
e3d_renderer_clear(renderer, &c);
e3d_renderer_clear(renderer, &data->bg_color);
if (data->color_pick_enabled) //Use rendering to texture in color pick mechanism
{
@ -1374,10 +1415,12 @@ e3d_drawable_scene_render_to_texture(E3D_Drawable *drawable, E3D_Renderer *rende
else
{
_scene_render(drawable, renderer, data); //Just render scene in texture
glBindFramebuffer(GL_FRAMEBUFFER, drawable->fbo);
/*Render full screen quard*/
if (data->post_processing)
_scene_post_render(drawable, renderer, data);
}
glBindFramebuffer(GL_FRAMEBUFFER, drawable->fbo);
return EINA_TRUE;
}

View File

@ -114,6 +114,9 @@ struct _E3D_Draw_Data
Evas_Real constant_bias;
Eina_Bool render_to_texture;
Evas_Real frame_size_h;
Evas_Real frame_size_w;
};
struct _E3D_Texture
@ -175,4 +178,6 @@ void e3d_renderer_draw(E3D_Renderer *renderer, E3D_Draw_Data *da
void e3d_renderer_flush(E3D_Renderer *renderer);
void e3d_renderer_color_pick_target_set(E3D_Renderer *renderer, E3D_Drawable *drawable);
Eina_Bool e3d_renderer_rendering_to_texture_get(E3D_Renderer *renderer);
GLint e3d_renderer_sampler_colortexture_get(E3D_Renderer *renderer);
GLint e3d_renderer_sampler_shadowmap_get(E3D_Renderer *renderer);
#endif /* EVAS_GL_3D_PRIVATE_H */

View File

@ -414,3 +414,15 @@ e3d_renderer_flush(E3D_Renderer *renderer EINA_UNUSED)
{
glFlush();
}
GLint
e3d_renderer_sampler_colortexture_get(E3D_Renderer *renderer)
{
return renderer->colortex_sampler;
}
GLint
e3d_renderer_sampler_shadowmap_get(E3D_Renderer *renderer)
{
return renderer->smap_sampler;
}

View File

@ -69,7 +69,8 @@ typedef enum _E3D_Uniform
E3D_UNIFORM_ALPHATEST_COMPARISON,
E3D_UNIFORM_ALPHATEST_REFVALUE,
E3D_UNIFORM_RENDER_TO_TEXTURE,
E3D_UNIFORM_FRAME_SIZE_H,
E3D_UNIFORM_FRAME_SIZE_W,
E3D_UNIFORM_COUNT,
} E3D_Uniform;
@ -363,6 +364,8 @@ static const char *uniform_names[] =
"uAlphaTestComparison",
"uAlphaTestRefValue",
"uColorTexture",
"uFrameSizeH",
"uFrameSizeW"
};
static inline void
@ -635,6 +638,12 @@ _uniform_upload(E3D_Uniform u, GLint loc, const E3D_Draw_Data *data)
case E3D_UNIFORM_RENDER_TO_TEXTURE:
glUniform1i(loc, data->colortex_sampler);
break;
case E3D_UNIFORM_FRAME_SIZE_H:
glUniform1f(loc, data->frame_size_h);
break;
case E3D_UNIFORM_FRAME_SIZE_W:
glUniform1f(loc, data->frame_size_w);
break;
default:
ERR("Invalid uniform ID.");
break;

View File

@ -2112,6 +2112,94 @@ static const char parallax_occlusion_frag_glsl[] =
"#endif //FOG_ENABLED\n"
"}\n";
static const char post_processing_fxaa_vert_glsl[] =
"#ifdef GL_ES\n"
"precision mediump float;\n"
"precision mediump int;\n"
"precision lowp sampler2D;\n"
"#endif\n"
"uniform mat4 uMatrixMvp;\n"
"#ifdef VERTEX_POSITION\n"
"attribute vec4 aPosition0;\n"
"#endif //VERTEX_POSITION\n"
"#ifdef VERTEX_POSITION_BLEND\n"
"attribute vec4 aPosition1;\n"
"uniform float uPositionWeight;\n"
"#endif //VERTEX_POSITION_BLEND\n"
"varying vec2 tc0;\n"
"void main()\n"
"{\n"
" #ifdef VERTEX_POSITION_BLEND\n"
" vec4 position = mix(aPosition1, aPosition0, uPositionWeight);\n"
" position = vec4(position.xyz, 1.0);\n"
"#else\n"
"#ifdef VERTEX_POSITION\n"
" vec4 position = vec4(aPosition0.xyz, 1.0);\n"
"#endif // VERTEX_POSITION\n"
"#endif //VERTEX_POSITION_BLEND\n"
" gl_Position = uMatrixMvp * position;\n"
" tc0 = position.xy * 0.5 + 0.5;\n"
"}\n";
static const char post_processing_fxaa_frag_glsl[] =
"#ifdef GL_ES\n"
"precision mediump float;\n"
"precision mediump int;\n"
"precision lowp sampler2D;\n"
"#endif\n"
"//FXAA fragment shader by Timothy Lottes\n"
"//http://developer.download.nvidia.com/assets/gamedev/files/sdk/11/FXAA_WhitePaper.pdf\n"
"//modified and adapted to www.enlightenment.org by Oleksander Shcherbina\n"
"uniform sampler2D uColorTexture;\n"
"uniform float uFrameSizeH;\n"
"uniform float uFrameSizeW;\n"
"varying vec2 tc0;\n"
"vec4 fxaa()\n"
"{\n"
" float _SPAN_MAX_ = 8.0;\n"
" float _REDUCE_MUL_ = (1.0/8.0);\n"
" float _REDUCE_MIN_ = (1.0/128.0);\n"
" vec4 l = vec4(0.299, 0.587, 0.114, 0.0);\n"
" vec2 frameBufSize = vec2(uFrameSizeW, uFrameSizeH);\n"
" vec2 direction;\n"
" vec4 colorNW = texture2D(uColorTexture, tc0 + (vec2(-1.0, -1.0)/frameBufSize));\n"
" vec4 colorNE = texture2D(uColorTexture, tc0 + (vec2(1.0, -1.0)/frameBufSize));\n"
" vec4 colorSW = texture2D(uColorTexture, tc0 + (vec2(-1.0, 1.0)/frameBufSize));\n"
" vec4 colorSE = texture2D(uColorTexture, tc0 + (vec2(1.0, 1.0)/frameBufSize));\n"
" vec4 colorM = texture2D(uColorTexture,tc0);\n"
" float lNW = dot(colorNW, l);\n"
" float lNE = dot(colorNE, l);\n"
" float lSW = dot(colorSW, l);\n"
" float lSE = dot(colorSE, l);\n"
" float lM = dot(colorM, l);\n"
" float lMin = min(lM, min(min(lNW, lNE), min(lSW, lSE)));\n"
" float lMax = max(lM, max(max(lNW, lNE), max(lSW, lSE)));\n"
" direction.x = -((lNW + lNE) - (lSW + lSE));\n"
" direction.y = ((lNW + lSW) - (lNE + lSE));\n"
" float directionReduce = max(\n"
" (lNW + lNE + lSW + lSE) * (0.25 * _REDUCE_MUL_),\n"
" _REDUCE_MIN_);\n"
" float rcpDirMin = 1.0/(min(abs(direction.x), abs(direction.y)) + directionReduce);\n"
" direction = min(vec2(_SPAN_MAX_, _SPAN_MAX_),\n"
" max(vec2(-_SPAN_MAX_, -_SPAN_MAX_),\n"
" direction * rcpDirMin)) / frameBufSize;\n"
" vec4 colorA = 0.5 * (\n"
" texture2D(uColorTexture, tc0.xy + direction * (1.0/3.0 - 0.5)) +\n"
" texture2D(uColorTexture, tc0.xy + direction * (2.0/3.0 - 0.5)));\n"
" vec4 colorB = colorA * 0.5 + 0.25 * (\n"
" texture2D(uColorTexture, tc0.xy + direction * (- 0.5)) +\n"
" texture2D(uColorTexture, tc0.xy + direction * 0.5));\n"
" float lB = dot(colorB, l);\n"
" if((lB < lMin) || (lB > lMax))\n"
" return colorA;\n"
" else\n"
" return colorB;\n"
"}\n"
"void main()\n"
"{\n"
" gl_FragColor = fxaa();\n"
"}\n";
static const char *vertex_shaders[] =
{
vertex_color_vert_glsl,
@ -2122,6 +2210,7 @@ static const char *vertex_shaders[] =
shadow_map_vert_glsl,
color_pick_vert_glsl,
parallax_occlusion_vert_glsl,
post_processing_fxaa_vert_glsl,
};
static const char *fragment_shaders[] =
@ -2134,4 +2223,5 @@ static const char *fragment_shaders[] =
shadow_map_frag_glsl,
color_pick_frag_glsl,
parallax_occlusion_frag_glsl,
post_processing_fxaa_frag_glsl,
};

View File

@ -0,0 +1,63 @@
//FXAA fragment shader by Timothy Lottes
//http://developer.download.nvidia.com/assets/gamedev/files/sdk/11/FXAA_WhitePaper.pdf
//modified and adapted to www.enlightenment.org by Oleksander Shcherbina
uniform sampler2D uColorTexture;
uniform float uFrameSizeH;
uniform float uFrameSizeW;
varying vec2 tc0;
vec4 fxaa()
{
float _SPAN_MAX_ = 8.0;
float _REDUCE_MUL_ = (1.0/8.0);
float _REDUCE_MIN_ = (1.0/128.0);
vec4 l = vec4(0.299, 0.587, 0.114, 0.0);
vec2 frameBufSize = vec2(uFrameSizeW, uFrameSizeH);
vec2 direction;
vec4 colorNW = texture2D(uColorTexture, tc0 + (vec2(-1.0, -1.0)/frameBufSize));
vec4 colorNE = texture2D(uColorTexture, tc0 + (vec2(1.0, -1.0)/frameBufSize));
vec4 colorSW = texture2D(uColorTexture, tc0 + (vec2(-1.0, 1.0)/frameBufSize));
vec4 colorSE = texture2D(uColorTexture, tc0 + (vec2(1.0, 1.0)/frameBufSize));
vec4 colorM = texture2D(uColorTexture,tc0);
float lNW = dot(colorNW, l);
float lNE = dot(colorNE, l);
float lSW = dot(colorSW, l);
float lSE = dot(colorSE, l);
float lM = dot(colorM, l);
float lMin = min(lM, min(min(lNW, lNE), min(lSW, lSE)));
float lMax = max(lM, max(max(lNW, lNE), max(lSW, lSE)));
direction.x = -((lNW + lNE) - (lSW + lSE));
direction.y = ((lNW + lSW) - (lNE + lSE));
float directionReduce = max(
(lNW + lNE + lSW + lSE) * (0.25 * _REDUCE_MUL_),
_REDUCE_MIN_);
float rcpDirMin = 1.0/(min(abs(direction.x), abs(direction.y)) + directionReduce);
direction = min(vec2(_SPAN_MAX_, _SPAN_MAX_),
max(vec2(-_SPAN_MAX_, -_SPAN_MAX_),
direction * rcpDirMin)) / frameBufSize;
vec4 colorA = 0.5 * (
texture2D(uColorTexture, tc0.xy + direction * (1.0/3.0 - 0.5)) +
texture2D(uColorTexture, tc0.xy + direction * (2.0/3.0 - 0.5)));
vec4 colorB = colorA * 0.5 + 0.25 * (
texture2D(uColorTexture, tc0.xy + direction * (- 0.5)) +
texture2D(uColorTexture, tc0.xy + direction * 0.5));
float lB = dot(colorB, l);
if((lB < lMin) || (lB > lMax))
return colorA;
else
return colorB;
}
void main()
{
gl_FragColor = fxaa();
}

View File

@ -0,0 +1,12 @@
uniform mat4 uMatrixMvp;
VERTEX_SHADER_USE_POSITION
varying vec2 tc0;
void main()
{
VERTEX_SHADER_POSITION
gl_Position = uMatrixMvp * position;
tc0 = position.xy * 0.5 + 0.5;
}