From 5c6cac4e53058c987ca3c065ae49670e9cd9edbc Mon Sep 17 00:00:00 2001 From: Juan Linietsky Date: Sat, 17 Jun 2017 23:26:49 -0300 Subject: Add normalmap support for drawing in all low level primitives. Only added support in Sprite so far. --- drivers/gles3/rasterizer_canvas_gles3.cpp | 76 +++++++++++++++++++++++-------- drivers/gles3/rasterizer_canvas_gles3.h | 3 +- drivers/gles3/shaders/canvas.glsl | 53 ++++++++++++++------- 3 files changed, 94 insertions(+), 38 deletions(-) (limited to 'drivers/gles3') diff --git a/drivers/gles3/rasterizer_canvas_gles3.cpp b/drivers/gles3/rasterizer_canvas_gles3.cpp index aad132a92d..0c07abb002 100644 --- a/drivers/gles3/rasterizer_canvas_gles3.cpp +++ b/drivers/gles3/rasterizer_canvas_gles3.cpp @@ -188,40 +188,74 @@ void RasterizerCanvasGLES3::canvas_end() { state.using_texture_rect = false; } -RasterizerStorageGLES3::Texture *RasterizerCanvasGLES3::_bind_canvas_texture(const RID &p_texture) { +RasterizerStorageGLES3::Texture *RasterizerCanvasGLES3::_bind_canvas_texture(const RID &p_texture, const RID &p_normal_map) { - if (p_texture == state.current_tex) { - return state.current_tex_ptr; - } + RasterizerStorageGLES3::Texture *tex_return = NULL; - if (p_texture.is_valid()) { + if (p_texture == state.current_tex) { + tex_return = state.current_tex_ptr; + } else if (p_texture.is_valid()) { RasterizerStorageGLES3::Texture *texture = storage->texture_owner.getornull(p_texture); if (!texture) { state.current_tex = RID(); state.current_tex_ptr = NULL; + glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, storage->resources.white_tex); - return NULL; - } - if (texture->render_target) - texture->render_target->used_in_frame = true; + } else { - glBindTexture(GL_TEXTURE_2D, texture->tex_id); - state.current_tex = p_texture; - state.current_tex_ptr = texture; + if (texture->render_target) + texture->render_target->used_in_frame = true; - return texture; + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, texture->tex_id); + state.current_tex = p_texture; + state.current_tex_ptr = texture; + + tex_return = texture; + } } else { + glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, storage->resources.white_tex); state.current_tex = RID(); state.current_tex_ptr = NULL; } - return NULL; + if (p_normal_map == state.current_normal) { + //do none + state.canvas_shader.set_uniform(CanvasShaderGLES3::USE_DEFAULT_NORMAL, state.current_normal.is_valid()); + + } else if (p_normal_map.is_valid()) { + + RasterizerStorageGLES3::Texture *normal_map = storage->texture_owner.getornull(p_normal_map); + + if (!normal_map) { + state.current_normal = RID(); + glActiveTexture(GL_TEXTURE1); + glBindTexture(GL_TEXTURE_2D, storage->resources.normal_tex); + state.canvas_shader.set_uniform(CanvasShaderGLES3::USE_DEFAULT_NORMAL, false); + + } else { + + glActiveTexture(GL_TEXTURE1); + glBindTexture(GL_TEXTURE_2D, normal_map->tex_id); + state.current_normal = p_normal_map; + state.canvas_shader.set_uniform(CanvasShaderGLES3::USE_DEFAULT_NORMAL, true); + } + + } else { + + state.current_normal = RID(); + glActiveTexture(GL_TEXTURE1); + glBindTexture(GL_TEXTURE_2D, storage->resources.normal_tex); + state.canvas_shader.set_uniform(CanvasShaderGLES3::USE_DEFAULT_NORMAL, false); + } + + return tex_return; } void RasterizerCanvasGLES3::_set_texture_rect_mode(bool p_enable) { @@ -372,7 +406,7 @@ void RasterizerCanvasGLES3::_canvas_item_render_commands(Item *p_item, Item *cur Item::CommandLine *line = static_cast(c); _set_texture_rect_mode(false); - _bind_canvas_texture(RID()); + _bind_canvas_texture(RID(), RID()); glVertexAttrib4f(VS::ARRAY_COLOR, line->color.r, line->color.g, line->color.b, line->color.a); @@ -403,7 +437,7 @@ void RasterizerCanvasGLES3::_canvas_item_render_commands(Item *p_item, Item *cur //set color glVertexAttrib4f(VS::ARRAY_COLOR, rect->modulate.r, rect->modulate.g, rect->modulate.b, rect->modulate.a); - RasterizerStorageGLES3::Texture *texture = _bind_canvas_texture(rect->texture); + RasterizerStorageGLES3::Texture *texture = _bind_canvas_texture(rect->texture, rect->normal_map); if (texture) { @@ -460,7 +494,7 @@ void RasterizerCanvasGLES3::_canvas_item_render_commands(Item *p_item, Item *cur glVertexAttrib4f(VS::ARRAY_COLOR, np->color.r, np->color.g, np->color.b, np->color.a); - RasterizerStorageGLES3::Texture *texture = _bind_canvas_texture(np->texture); + RasterizerStorageGLES3::Texture *texture = _bind_canvas_texture(np->texture, np->normal_map); if (!texture) { @@ -538,7 +572,7 @@ void RasterizerCanvasGLES3::_canvas_item_render_commands(Item *p_item, Item *cur ERR_CONTINUE(primitive->points.size() < 1); - RasterizerStorageGLES3::Texture *texture = _bind_canvas_texture(primitive->texture); + RasterizerStorageGLES3::Texture *texture = _bind_canvas_texture(primitive->texture, primitive->normal_map); if (texture) { Size2 texpixel_size(1.0 / texture->width, 1.0 / texture->height); @@ -561,7 +595,7 @@ void RasterizerCanvasGLES3::_canvas_item_render_commands(Item *p_item, Item *cur Item::CommandPolygon *polygon = static_cast(c); _set_texture_rect_mode(false); - RasterizerStorageGLES3::Texture *texture = _bind_canvas_texture(polygon->texture); + RasterizerStorageGLES3::Texture *texture = _bind_canvas_texture(polygon->texture, polygon->normal_map); if (texture) { Size2 texpixel_size(1.0 / texture->width, 1.0 / texture->height); @@ -588,6 +622,7 @@ void RasterizerCanvasGLES3::_canvas_item_render_commands(Item *p_item, Item *cur indices[i * 3 + 2] = numpoints; } + _bind_canvas_texture(RID(), RID()); _draw_polygon(indices, numpoints * 3, numpoints + 1, points, NULL, &circle->color, true); //_draw_polygon(numpoints*3,indices,points,NULL,&circle->color,RID(),true); @@ -705,6 +740,7 @@ void RasterizerCanvasGLES3::canvas_render_items(Item *p_item_list, int p_z, cons state.current_tex = RID(); state.current_tex_ptr = NULL; + state.current_normal = RID(); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, storage->resources.white_tex); @@ -812,7 +848,7 @@ void RasterizerCanvasGLES3::canvas_render_items(Item *p_item_list, int p_z, cons for (int i = 0; i < tc; i++) { - glActiveTexture(GL_TEXTURE1 + i); + glActiveTexture(GL_TEXTURE2 + i); RasterizerStorageGLES3::Texture *t = storage->texture_owner.getornull(textures[i]); if (!t) { diff --git a/drivers/gles3/rasterizer_canvas_gles3.h b/drivers/gles3/rasterizer_canvas_gles3.h index b4f491285d..4996f0a6b2 100644 --- a/drivers/gles3/rasterizer_canvas_gles3.h +++ b/drivers/gles3/rasterizer_canvas_gles3.h @@ -65,6 +65,7 @@ public: bool using_texture_rect; RID current_tex; + RID current_normal; RasterizerStorageGLES3::Texture *current_tex_ptr; Transform vp; @@ -107,7 +108,7 @@ public: virtual void canvas_end(); _FORCE_INLINE_ void _set_texture_rect_mode(bool p_enable); - _FORCE_INLINE_ RasterizerStorageGLES3::Texture *_bind_canvas_texture(const RID &p_texture); + _FORCE_INLINE_ RasterizerStorageGLES3::Texture *_bind_canvas_texture(const RID &p_texture, const RID &p_normal_map); _FORCE_INLINE_ void _draw_gui_primitive(int p_points, const Vector2 *p_vertices, const Color *p_colors, const Vector2 *p_uvs); _FORCE_INLINE_ void _draw_polygon(const int *p_indices, int p_index_count, int p_vertex_count, const Vector2 *p_vertices, const Vector2 *p_uvs, const Color *p_colors, bool p_singlecolor); diff --git a/drivers/gles3/shaders/canvas.glsl b/drivers/gles3/shaders/canvas.glsl index 68660b657f..b0ce38cb68 100644 --- a/drivers/gles3/shaders/canvas.glsl +++ b/drivers/gles3/shaders/canvas.glsl @@ -51,9 +51,9 @@ layout(std140) uniform LightData { //ubo:1 out vec4 light_uv_interp; -#if defined(NORMAL_USED) + out vec4 local_rot; -#endif + #ifdef USE_SHADOWS out highp vec2 pos; @@ -124,7 +124,7 @@ VERTEX_SHADER_CODE pos=outvec.xy; #endif -#if defined(NORMAL_USED) + local_rot.xy=normalize( (modelview_matrix * ( extra_matrix * vec4(1.0,0.0,0.0,0.0) )).xy ); local_rot.zw=normalize( (modelview_matrix * ( extra_matrix * vec4(0.0,1.0,0.0,0.0) )).xy ); #ifdef USE_TEXTURE_RECT @@ -132,7 +132,7 @@ VERTEX_SHADER_CODE local_rot.zw*=sign(src_rect.w); #endif -#endif + #endif @@ -144,6 +144,7 @@ VERTEX_SHADER_CODE uniform mediump sampler2D color_texture; // texunit:0 uniform highp vec2 color_texpixel_size; +uniform mediump sampler2D normal_texture; // texunit:1 in mediump vec2 uv_interp; in mediump vec4 color_interp; @@ -183,9 +184,8 @@ uniform lowp sampler2D light_texture; // texunit:-1 in vec4 light_uv_interp; -#if defined(NORMAL_USED) in vec4 local_rot; -#endif + #ifdef USE_SHADOWS @@ -228,20 +228,19 @@ LIGHT_SHADER_CODE } +uniform bool use_default_normal; void main() { vec4 color = color_interp; -#if defined(NORMAL_USED) - vec3 normal = vec3(0.0,0.0,1.0); -#endif + #if !defined(COLOR_USED) //default behavior, texture by color #ifdef USE_DISTANCE_FIELD const float smoothing = 1.0/32.0; - float distance = texture(color_texture, uv_interp).a; + float distance = textureLod(color_texture, uv_interp,0.0).a; color.a = smoothstep(0.5 - smoothing, 0.5 + smoothing, distance) * color.a; #else color *= texture( color_texture, uv_interp ); @@ -250,6 +249,25 @@ void main() { #endif + vec3 normal; + +#if defined(NORMAL_USED) + + bool normal_used = true; +#else + bool normal_used = false; +#endif + + if (use_default_normal) { + normal.xy = textureLod(normal_texture, uv_interp,0.0).xy * 2.0 - 1.0; + normal.z = sqrt(1.0-dot(normal.xy,normal.xy)); + normal_used=true; + } else { + normal = vec3(0.0,0.0,1.0); + } + + + #if defined(ENABLE_SCREEN_UV) vec2 screen_uv = gl_FragCoord.xy*screen_uv_mult; #endif @@ -284,9 +302,9 @@ FRAGMENT_SHADER_CODE vec2 light_vec = light_uv_interp.zw;; //for shadow and normal mapping -#if defined(NORMAL_USED) - normal.xy = mat2(local_rot.xy,local_rot.zw) * normal.xy; -#endif + if (normal_used) { + normal.xy = mat2(local_rot.xy,local_rot.zw) * normal.xy; + } float att=1.0; @@ -307,10 +325,11 @@ FRAGMENT_SHADER_CODE #else -#if defined(NORMAL_USED) - vec3 light_normal = normalize(vec3(light_vec,-light_height)); - light*=max(dot(-light_normal,normal),0.0); -#endif + if (normal_used) { + + vec3 light_normal = normalize(vec3(light_vec,-light_height)); + light*=max(dot(-light_normal,normal),0.0); + } color*=light; /* -- cgit v1.2.3