From 27a46d78ec43b69a70a1d84c540353e3cb3b04c0 Mon Sep 17 00:00:00 2001 From: Juan Linietsky Date: Fri, 2 Dec 2016 22:23:16 -0300 Subject: Subsurface scattering material param is now working! --- drivers/gles3/rasterizer_scene_gles3.cpp | 91 +++++++++-- drivers/gles3/rasterizer_scene_gles3.h | 12 ++ drivers/gles3/rasterizer_storage_gles3.cpp | 21 ++- drivers/gles3/rasterizer_storage_gles3.h | 5 +- drivers/gles3/shader_compiler_gles3.cpp | 11 +- drivers/gles3/shader_compiler_gles3.h | 1 + drivers/gles3/shaders/SCsub | 2 + drivers/gles3/shaders/resolve.glsl | 12 +- drivers/gles3/shaders/scene.glsl | 42 +++++ drivers/gles3/shaders/screen_space_reflection.glsl | 7 +- drivers/gles3/shaders/subsurf_scattering.glsl | 172 +++++++++++++++++++++ 11 files changed, 344 insertions(+), 32 deletions(-) create mode 100644 drivers/gles3/shaders/subsurf_scattering.glsl (limited to 'drivers/gles3') diff --git a/drivers/gles3/rasterizer_scene_gles3.cpp b/drivers/gles3/rasterizer_scene_gles3.cpp index 16784246f6..c4c7d4409d 100644 --- a/drivers/gles3/rasterizer_scene_gles3.cpp +++ b/drivers/gles3/rasterizer_scene_gles3.cpp @@ -1809,6 +1809,10 @@ void RasterizerSceneGLES3::_add_geometry( RasterizerStorageGLES3::Geometry* p_g mirror=!mirror; } + if (m->shader->spatial.uses_sss) { + state.used_sss=true; + } + if (p_shadow) { if (has_blend_alpha || (has_base_alpha && m->shader->spatial.depth_draw_mode!=RasterizerStorageGLES3::Shader::Spatial::DEPTH_DRAW_ALPHA_PREPASS)) @@ -1827,6 +1831,7 @@ void RasterizerSceneGLES3::_add_geometry( RasterizerStorageGLES3::Geometry* p_g } + RenderList::Element *e = has_alpha ? render_list.add_alpha_element() : render_list.add_element(); if (!e) @@ -2620,6 +2625,7 @@ void RasterizerSceneGLES3::_fill_render_list(InstanceBase** p_cull_result,int p_ current_geometry_index=0; current_material_index=0; + state.used_sss=false; //fill list @@ -2683,6 +2689,50 @@ void RasterizerSceneGLES3::_render_mrts(Environment *env,const CameraMatrix &p_c glDisable(GL_CULL_FACE); glDisable(GL_BLEND); + if (state.used_sss) {//sss enabled + //copy diffuse while performing sss + + state.sss_shader.set_conditional(SubsurfScatteringShaderGLES3::USE_11_SAMPLES,subsurface_scatter_quality==SSS_QUALITY_LOW); + state.sss_shader.set_conditional(SubsurfScatteringShaderGLES3::USE_17_SAMPLES,subsurface_scatter_quality==SSS_QUALITY_MEDIUM); + state.sss_shader.set_conditional(SubsurfScatteringShaderGLES3::USE_25_SAMPLES,subsurface_scatter_quality==SSS_QUALITY_HIGH); + state.sss_shader.set_conditional(SubsurfScatteringShaderGLES3::ENABLE_FOLLOW_SURFACE,subsurface_scatter_follow_surface); + state.sss_shader.bind(); + state.sss_shader.set_uniform(SubsurfScatteringShaderGLES3::MAX_RADIUS,subsurface_scatter_size); + state.sss_shader.set_uniform(SubsurfScatteringShaderGLES3::FOVY,p_cam_projection.get_fov()); + state.sss_shader.set_uniform(SubsurfScatteringShaderGLES3::CAMERA_Z_NEAR,p_cam_projection.get_z_near()); + state.sss_shader.set_uniform(SubsurfScatteringShaderGLES3::CAMERA_Z_FAR,p_cam_projection.get_z_far()); + state.sss_shader.set_uniform(SubsurfScatteringShaderGLES3::DIR,Vector2(1,0)); + + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D,storage->frame.current_rt->buffers.diffuse); + glActiveTexture(GL_TEXTURE1); + glBindTexture(GL_TEXTURE_2D,storage->frame.current_rt->buffers.motion_sss); + glActiveTexture(GL_TEXTURE2); + glBindTexture(GL_TEXTURE_2D,storage->frame.current_rt->depth); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_NONE); + + glBindFramebuffer(GL_FRAMEBUFFER,storage->frame.current_rt->fbo); //copy to front first + + _copy_screen(); + + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D,storage->frame.current_rt->color); + state.sss_shader.set_uniform(SubsurfScatteringShaderGLES3::DIR,Vector2(0,1)); + glBindFramebuffer(GL_FRAMEBUFFER,storage->frame.current_rt->effects.mip_maps[0].sizes[0].fbo); // copy to base level + _copy_screen(); + + } else { + // just copy diffuse + storage->shaders.copy.bind(); + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D,storage->frame.current_rt->buffers.diffuse); + glBindFramebuffer(GL_FRAMEBUFFER,storage->frame.current_rt->effects.mip_maps[0].sizes[0].fbo); // copy to base level + _copy_screen(); + + } + + + if (env->ssr_enabled) { //blur diffuse into effect mipmaps using separatable convolution //storage->shaders.copy.set_conditional(CopyShaderGLES3::GAUSSIAN_HORIZONTAL,true); @@ -2698,11 +2748,7 @@ void RasterizerSceneGLES3::_render_mrts(Environment *env,const CameraMatrix &p_c state.effect_blur_shader.set_uniform(EffectBlurShaderGLES3::PIXEL_SIZE,Vector2(1.0/vp_w,1.0/vp_h)); state.effect_blur_shader.set_uniform(EffectBlurShaderGLES3::LOD,float(i)); glActiveTexture(GL_TEXTURE0); - if (i==0) { - glBindTexture(GL_TEXTURE_2D,storage->frame.current_rt->buffers.diffuse); - } else { - glBindTexture(GL_TEXTURE_2D,storage->frame.current_rt->effects.mip_maps[0].color); //previous level, since mipmaps[0] starts one level bigger - } + 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); _copy_screen(); state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::GAUSSIAN_HORIZONTAL,false); @@ -2748,7 +2794,7 @@ void RasterizerSceneGLES3::_render_mrts(Environment *env,const CameraMatrix &p_c glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D,storage->frame.current_rt->buffers.diffuse); glActiveTexture(GL_TEXTURE1); - glBindTexture(GL_TEXTURE_2D,storage->frame.current_rt->buffers.normal_sr); + glBindTexture(GL_TEXTURE_2D,storage->frame.current_rt->buffers.normal_rough); glActiveTexture(GL_TEXTURE2); glBindTexture(GL_TEXTURE_2D,storage->frame.current_rt->depth); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_NONE); @@ -2764,22 +2810,26 @@ void RasterizerSceneGLES3::_render_mrts(Environment *env,const CameraMatrix &p_c } + //copy reflection over diffuse, resolving SSR if needed state.resolve_shader.set_conditional(ResolveShaderGLES3::USE_SSR,env->ssr_enabled); state.resolve_shader.bind(); glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D,storage->frame.current_rt->buffers.diffuse); - glActiveTexture(GL_TEXTURE1); glBindTexture(GL_TEXTURE_2D,storage->frame.current_rt->buffers.specular); if (env->ssr_enabled) { - glActiveTexture(GL_TEXTURE2); + glActiveTexture(GL_TEXTURE1); 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[0].fbo); - //glBindFramebuffer(GL_FRAMEBUFFER,storage->frame.current_rt->fbo); + glEnable(GL_BLEND); + glBlendEquation(GL_FUNC_ADD); + glBlendFunc(GL_ONE,GL_ONE); //use additive to accumulate one over the other + _copy_screen(); + glDisable(GL_BLEND); //end additive + state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::SIMPLE_COPY,true); state.effect_blur_shader.bind(); state.effect_blur_shader.set_uniform(EffectBlurShaderGLES3::LOD,float(0)); @@ -2839,6 +2889,7 @@ void RasterizerSceneGLES3::render_scene(const Transform& p_cam_transform,const C bool use_mrt=true; + _fill_render_list(p_cull_result,p_cull_count,false); // @@ -2893,11 +2944,17 @@ void RasterizerSceneGLES3::render_scene(const Transform& p_cam_transform,const C draw_buffers.push_back(GL_COLOR_ATTACHMENT0); draw_buffers.push_back(GL_COLOR_ATTACHMENT1); draw_buffers.push_back(GL_COLOR_ATTACHMENT2); + if (state.used_sss) { + draw_buffers.push_back(GL_COLOR_ATTACHMENT3); + } glDrawBuffers(draw_buffers.size(),draw_buffers.ptr()); Color black(0,0,0,0); glClearBufferfv(GL_COLOR,1,black.components); // specular glClearBufferfv(GL_COLOR,2,black.components); // normal metal rough + if (state.used_sss) { + glClearBufferfv(GL_COLOR,3,black.components); // normal metal rough + } } else { @@ -3968,11 +4025,25 @@ void RasterizerSceneGLES3::initialize() { state.resolve_shader.init(); state.ssr_shader.init(); state.effect_blur_shader.init(); + state.sss_shader.init(); + + + { + GLOBAL_DEF("rendering/gles3/subsurface_scattering/quality",1); + Globals::get_singleton()->set_custom_property_info("rendering/gles3/subsurface_scattering/quality",PropertyInfo(Variant::INT,"rendering/gles3/subsurface_scattering/quality",PROPERTY_HINT_ENUM,"Low,Medium,High")); + GLOBAL_DEF("rendering/gles3/subsurface_scattering/max_size",1.0); + Globals::get_singleton()->set_custom_property_info("rendering/gles3/subsurface_scattering/max_size",PropertyInfo(Variant::INT,"rendering/gles3/subsurface_scattering/max_size",PROPERTY_HINT_RANGE,"0.01,8,0.01")); + GLOBAL_DEF("rendering/gles3/subsurface_scattering/follow_surface",false); + } + } void RasterizerSceneGLES3::iteration() { shadow_filter_mode=ShadowFilterMode(int(Globals::get_singleton()->get("rendering/gles3/shadow_filter_mode"))); + subsurface_scatter_follow_surface=Globals::get_singleton()->get("rendering/gles3/subsurface_scattering/follow_surface"); + subsurface_scatter_quality=SubSurfaceScatterQuality(int(Globals::get_singleton()->get("rendering/gles3/subsurface_scattering/quality"))); + subsurface_scatter_size=Globals::get_singleton()->get("rendering/gles3/subsurface_scattering/max_size"); } void RasterizerSceneGLES3::finalize(){ diff --git a/drivers/gles3/rasterizer_scene_gles3.h b/drivers/gles3/rasterizer_scene_gles3.h index 0b934085ed..21711292a0 100644 --- a/drivers/gles3/rasterizer_scene_gles3.h +++ b/drivers/gles3/rasterizer_scene_gles3.h @@ -7,6 +7,7 @@ #include "drivers/gles3/shaders/resolve.glsl.h" #include "drivers/gles3/shaders/screen_space_reflection.glsl.h" #include "drivers/gles3/shaders/effect_blur.glsl.h" +#include "drivers/gles3/shaders/subsurf_scattering.glsl.h" class RasterizerSceneGLES3 : public RasterizerScene { public: @@ -22,6 +23,15 @@ public: uint64_t shadow_atlas_realloc_tolerance_msec; + enum SubSurfaceScatterQuality { + SSS_QUALITY_LOW, + SSS_QUALITY_MEDIUM, + SSS_QUALITY_HIGH, + }; + + SubSurfaceScatterQuality subsurface_scatter_quality; + float subsurface_scatter_size; + bool subsurface_scatter_follow_surface; uint64_t render_pass; uint64_t scene_pass; @@ -51,6 +61,7 @@ public: ResolveShaderGLES3 resolve_shader; ScreenSpaceReflectionShaderGLES3 ssr_shader; EffectBlurShaderGLES3 effect_blur_shader; + SubsurfScatteringShaderGLES3 sss_shader; struct SceneDataUBO { @@ -118,6 +129,7 @@ public: int reflection_probe_count; bool cull_front; + bool used_sss; } state; diff --git a/drivers/gles3/rasterizer_storage_gles3.cpp b/drivers/gles3/rasterizer_storage_gles3.cpp index 01668e728c..7b9a3f2af1 100644 --- a/drivers/gles3/rasterizer_storage_gles3.cpp +++ b/drivers/gles3/rasterizer_storage_gles3.cpp @@ -1456,6 +1456,7 @@ void RasterizerStorageGLES3::_update_shader(Shader* p_shader) const { p_shader->spatial.uses_alpha=false; p_shader->spatial.unshaded=false; p_shader->spatial.ontop=false; + p_shader->spatial.uses_sss=false; shaders.actions_scene.render_mode_values["blend_add"]=Pair(&p_shader->spatial.blend_mode,Shader::Spatial::BLEND_MODE_ADD); shaders.actions_scene.render_mode_values["blend_mix"]=Pair(&p_shader->spatial.blend_mode,Shader::Spatial::BLEND_MODE_MIX); @@ -1477,6 +1478,8 @@ void RasterizerStorageGLES3::_update_shader(Shader* p_shader) const { shaders.actions_scene.usage_flag_pointers["ALPHA"]=&p_shader->spatial.uses_alpha; shaders.actions_scene.usage_flag_pointers["VERTEX"]=&p_shader->spatial.uses_vertex; + shaders.actions_scene.usage_flag_pointers["SSS_STRENGTH"]=&p_shader->spatial.uses_sss; + actions=&shaders.actions_scene; actions->uniforms=&p_shader->uniforms; @@ -4771,7 +4774,8 @@ void RasterizerStorageGLES3::_render_target_clear(RenderTarget *rt) { glDeleteFramebuffers(1,&rt->buffers.alpha_fbo); glDeleteTextures(1,&rt->buffers.diffuse); glDeleteTextures(1,&rt->buffers.specular); - glDeleteTextures(1,&rt->buffers.normal_sr); + glDeleteTextures(1,&rt->buffers.normal_rough); + glDeleteTextures(1,&rt->buffers.motion_sss); rt->buffers.fbo=0; rt->buffers.alpha_fbo=0; } @@ -4923,14 +4927,23 @@ void RasterizerStorageGLES3::_render_target_allocate(RenderTarget *rt){ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, rt->buffers.specular, 0); - glGenTextures(1, &rt->buffers.normal_sr); - glBindTexture(GL_TEXTURE_2D, rt->buffers.normal_sr); + glGenTextures(1, &rt->buffers.normal_rough); + glBindTexture(GL_TEXTURE_2D, rt->buffers.normal_rough); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, rt->width, rt->height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT2, GL_TEXTURE_2D, rt->buffers.normal_sr, 0); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT2, GL_TEXTURE_2D, rt->buffers.normal_rough, 0); + + glGenTextures(1, &rt->buffers.motion_sss); + glBindTexture(GL_TEXTURE_2D, rt->buffers.motion_sss); + glTexImage2D(GL_TEXTURE_2D, 0, GL_R32UI, rt->width, rt->height, 0, GL_RED_INTEGER, GL_UNSIGNED_INT, NULL); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT3, GL_TEXTURE_2D, rt->buffers.motion_sss, 0); GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER); diff --git a/drivers/gles3/rasterizer_storage_gles3.h b/drivers/gles3/rasterizer_storage_gles3.h index 1eba8b42c9..e6b89eb66c 100644 --- a/drivers/gles3/rasterizer_storage_gles3.h +++ b/drivers/gles3/rasterizer_storage_gles3.h @@ -369,6 +369,7 @@ public: bool ontop; bool uses_vertex; bool uses_discard; + bool uses_sss; } spatial; @@ -886,8 +887,8 @@ public: GLuint alpha_fbo; //single buffer, just diffuse (for alpha pass) GLuint specular; GLuint diffuse; - GLuint normal_sr; - GLuint temporal; + GLuint normal_rough; + GLuint motion_sss; } buffers; struct Effects { diff --git a/drivers/gles3/shader_compiler_gles3.cpp b/drivers/gles3/shader_compiler_gles3.cpp index c54fc011e9..5c7a72ab17 100644 --- a/drivers/gles3/shader_compiler_gles3.cpp +++ b/drivers/gles3/shader_compiler_gles3.cpp @@ -422,9 +422,9 @@ String ShaderCompilerGLES3::_dump_node_code(SL::Node *p_node, int p_level, Gener used_name_defines.insert(vnode->name); } - if (p_actions.usage_flag_pointers.has(vnode->name) && !used_name_defines.has(vnode->name)) { + if (p_actions.usage_flag_pointers.has(vnode->name) && !used_flag_pointers.has(vnode->name)) { *p_actions.usage_flag_pointers[vnode->name]=true; - used_name_defines.insert(vnode->name); + used_flag_pointers.insert(vnode->name); } if (p_default_actions.renames.has(vnode->name)) @@ -670,6 +670,8 @@ ShaderCompilerGLES3::ShaderCompilerGLES3() { actions[VS::SHADER_SPATIAL].renames["CLEARCOAT_GLOSS"]="clearcoat_gloss"; actions[VS::SHADER_SPATIAL].renames["ANISOTROPY"]="anisotropy"; actions[VS::SHADER_SPATIAL].renames["ANISOTROPY_FLOW"]="anisotropy_flow"; + actions[VS::SHADER_SPATIAL].renames["SSS_SPREAD"]="sss_spread"; + actions[VS::SHADER_SPATIAL].renames["SSS_STRENGTH"]="sss_strength"; actions[VS::SHADER_SPATIAL].renames["AO"]="ao"; actions[VS::SHADER_SPATIAL].renames["EMISSION"]="emission"; actions[VS::SHADER_SPATIAL].renames["DISCARD"]="_discard"; @@ -692,6 +694,11 @@ ShaderCompilerGLES3::ShaderCompilerGLES3() { actions[VS::SHADER_SPATIAL].usage_defines["NORMALMAP_DEPTH"]="@NORMALMAP"; actions[VS::SHADER_SPATIAL].usage_defines["COLOR"]="#define ENABLE_COLOR_INTERP\n"; + actions[VS::SHADER_SPATIAL].usage_defines["SSS_STRENGTH"]="#define ENABLE_SSS_MOTION\n"; + + actions[VS::SHADER_SPATIAL].renames["SSS_STRENGTH"]="sss_strength"; + + actions[VS::SHADER_SPATIAL].render_mode_defines["skip_transform"]="#define SKIP_TRANSFORM_USED\n"; diff --git a/drivers/gles3/shader_compiler_gles3.h b/drivers/gles3/shader_compiler_gles3.h index 3549526808..1beee66ad7 100644 --- a/drivers/gles3/shader_compiler_gles3.h +++ b/drivers/gles3/shader_compiler_gles3.h @@ -58,6 +58,7 @@ private: StringName time_name; Set used_name_defines; + Set used_flag_pointers; Set used_rmode_defines; Set internal_functions; diff --git a/drivers/gles3/shaders/SCsub b/drivers/gles3/shaders/SCsub index 66a19eefd1..b5797e78b8 100644 --- a/drivers/gles3/shaders/SCsub +++ b/drivers/gles3/shaders/SCsub @@ -11,4 +11,6 @@ if env['BUILDERS'].has_key('GLES3_GLSL'): env.GLES3_GLSL('blend_shape.glsl'); env.GLES3_GLSL('screen_space_reflection.glsl'); env.GLES3_GLSL('effect_blur.glsl'); + env.GLES3_GLSL('subsurf_scattering.glsl'); + diff --git a/drivers/gles3/shaders/resolve.glsl b/drivers/gles3/shaders/resolve.glsl index 4ca6297303..6acc712299 100644 --- a/drivers/gles3/shaders/resolve.glsl +++ b/drivers/gles3/shaders/resolve.glsl @@ -17,11 +17,8 @@ void main() { in vec2 uv_interp; -uniform sampler2D source_diffuse; //texunit:0 -uniform sampler2D source_specular; //texunit:1 - - -uniform sampler2D source_ssr_ssao; //texunit:2 +uniform sampler2D source_specular; //texunit:0 +uniform sampler2D source_ssr; //texunit:1 uniform float stuff; @@ -31,15 +28,14 @@ layout(location = 0) out vec4 frag_color; void main() { - vec4 diffuse = texture( source_diffuse, uv_interp ); vec4 specular = texture( source_specular, uv_interp ); #ifdef USE_SSR - vec4 ssr = textureLod(source_ssr_ssao,uv_interp,0.0); + vec4 ssr = textureLod(source_ssr,uv_interp,0.0); specular.rgb = mix(specular.rgb,ssr.rgb*specular.a,ssr.a); #endif - frag_color = vec4(diffuse.rgb,1.0)+vec4(specular.rgb,1.0); + frag_color = vec4(specular.rgb,1.0); } diff --git a/drivers/gles3/shaders/scene.glsl b/drivers/gles3/shaders/scene.glsl index 192042192e..230544c1c3 100644 --- a/drivers/gles3/shaders/scene.glsl +++ b/drivers/gles3/shaders/scene.glsl @@ -75,6 +75,7 @@ layout(std140) uniform SceneData { //ubo:0 vec2 directional_shadow_pixel_size; float reflection_multiplier; + float subsurface_scatter_width; }; @@ -385,6 +386,7 @@ layout(std140) uniform SceneData { vec2 directional_shadow_pixel_size; float reflection_multiplier; + float subsurface_scatter_width; }; @@ -479,6 +481,9 @@ uniform int reflection_count; layout(location=0) out vec4 diffuse_buffer; layout(location=1) out vec4 specular_buffer; layout(location=2) out vec4 normal_mr_buffer; +#if defined (ENABLE_SSS_MOTION) +layout(location=3) out uint motion_ssr_buffer; +#endif #else @@ -621,6 +626,35 @@ in highp float dp_clip; #endif +#if 0 +//need to save texture depth for this + +vec3 light_transmittance(float translucency,vec3 light_vec, vec3 normal, vec3 pos, float distance) { + + float scale = 8.25 * (1.0 - translucency) / subsurface_scatter_width; + float d = scale * distance; + + /** + * Armed with the thickness, we can now calculate the color by means of the + * precalculated transmittance profile. + * (It can be precomputed into a texture, for maximum performance): + */ + float dd = -d * d; + vec3 profile = vec3(0.233, 0.455, 0.649) * exp(dd / 0.0064) + + vec3(0.1, 0.336, 0.344) * exp(dd / 0.0484) + + vec3(0.118, 0.198, 0.0) * exp(dd / 0.187) + + vec3(0.113, 0.007, 0.007) * exp(dd / 0.567) + + vec3(0.358, 0.004, 0.0) * exp(dd / 1.99) + + vec3(0.078, 0.0, 0.0) * exp(dd / 7.41); + + /** + * Using the profile, we finally approximate the transmitted lighting from + * the back of the object: + */ + return profile * clamp(0.3 + dot(light_vec, normal),0.0,1.0); +} +#endif + void light_process_omni(int idx, vec3 vertex, vec3 eye_vec,vec3 normal,vec3 binormal, vec3 tangent, vec3 albedo, vec3 specular, float roughness, float rim, float rim_tint, float clearcoat, float clearcoat_gloss,float anisotropy,inout vec3 diffuse_light, inout vec3 specular_light) { vec3 light_rel_vec = omni_lights[idx].light_pos_inv_radius.xyz-vertex; @@ -870,6 +904,10 @@ void main() { bool discard_=false; #endif +#if defined (ENABLE_SSS_MOTION) + float sss_strength=0.0; +#endif + { @@ -1194,6 +1232,10 @@ LIGHT_SHADER_CODE normal_mr_buffer=vec4(normalize(normal)*0.5+0.5,roughness); +#if defined (ENABLE_SSS_MOTION) + motion_ssr_buffer = uint(clamp(sqrt(sss_strength)*255.0,0.0,255))<<24; +#endif + #else diff --git a/drivers/gles3/shaders/screen_space_reflection.glsl b/drivers/gles3/shaders/screen_space_reflection.glsl index 5b24013c07..ec4bdf86c9 100644 --- a/drivers/gles3/shaders/screen_space_reflection.glsl +++ b/drivers/gles3/shaders/screen_space_reflection.glsl @@ -23,7 +23,6 @@ in vec2 pos_interp; uniform sampler2D source_diffuse; //texunit:0 uniform sampler2D source_normal_roughness; //texunit:1 uniform sampler2D source_depth; //texunit:2 -uniform sampler2D source_diffuse_mipmaps; //texunit:3 uniform float camera_z_near; uniform float camera_z_far; @@ -295,11 +294,7 @@ void main() { vec4 sample_color; { - sample_color = textureLod(source_diffuse_mipmaps,sample_pos,max(1.0,mipmap)); - if (mipmap<1.0) { //we use another image as base to avoid copying all the screen unnecesarily - vec4 base_sample_color = textureLod(source_diffuse,sample_pos,0.0); - sample_color = mix(base_sample_color,sample_color,mipmap); - } + sample_color = textureLod(source_diffuse,sample_pos,mipmap); } //multiply by gloss diff --git a/drivers/gles3/shaders/subsurf_scattering.glsl b/drivers/gles3/shaders/subsurf_scattering.glsl new file mode 100644 index 0000000000..89e618b66c --- /dev/null +++ b/drivers/gles3/shaders/subsurf_scattering.glsl @@ -0,0 +1,172 @@ +[vertex] + + +layout(location=0) in highp vec4 vertex_attrib; +layout(location=4) in vec2 uv_in; + +out vec2 uv_interp; + + +void main() { + + uv_interp = uv_in; + gl_Position = vertex_attrib; +} + +[fragment] + +//#define QUALIFIER uniform // some guy on the interweb says it may be faster with this +#define QUALIFIER const + +#ifdef USE_25_SAMPLES + +const int kernel_size=25; +QUALIFIER vec4 kernel[25] = vec4[] ( + vec4(0.530605, 0.613514, 0.739601, 0.0), + vec4(0.000973794, 1.11862e-005, 9.43437e-007, -3.0), + vec4(0.00333804, 7.85443e-005, 1.2945e-005, -2.52083), + vec4(0.00500364, 0.00020094, 5.28848e-005, -2.08333), + vec4(0.00700976, 0.00049366, 0.000151938, -1.6875), + vec4(0.0094389, 0.00139119, 0.000416598, -1.33333), + vec4(0.0128496, 0.00356329, 0.00132016, -1.02083), + vec4(0.017924, 0.00711691, 0.00347194, -0.75), + vec4(0.0263642, 0.0119715, 0.00684598, -0.520833), + vec4(0.0410172, 0.0199899, 0.0118481, -0.333333), + vec4(0.0493588, 0.0367726, 0.0219485, -0.1875), + vec4(0.0402784, 0.0657244, 0.04631, -0.0833333), + vec4(0.0211412, 0.0459286, 0.0378196, -0.0208333), + vec4(0.0211412, 0.0459286, 0.0378196, 0.0208333), + vec4(0.0402784, 0.0657244, 0.04631, 0.0833333), + vec4(0.0493588, 0.0367726, 0.0219485, 0.1875), + vec4(0.0410172, 0.0199899, 0.0118481, 0.333333), + vec4(0.0263642, 0.0119715, 0.00684598, 0.520833), + vec4(0.017924, 0.00711691, 0.00347194, 0.75), + vec4(0.0128496, 0.00356329, 0.00132016, 1.02083), + vec4(0.0094389, 0.00139119, 0.000416598, 1.33333), + vec4(0.00700976, 0.00049366, 0.000151938, 1.6875), + vec4(0.00500364, 0.00020094, 5.28848e-005, 2.08333), + vec4(0.00333804, 7.85443e-005, 1.2945e-005, 2.52083), + vec4(0.000973794, 1.11862e-005, 9.43437e-007, 3.0) +); + +#endif //USE_25_SAMPLES + +#ifdef USE_17_SAMPLES + +const int kernel_size=17; + +QUALIFIER vec4 kernel[17] = vec4[]( + vec4(0.536343, 0.624624, 0.748867, 0.0), + vec4(0.00317394, 0.000134823, 3.77269e-005, -2.0), + vec4(0.0100386, 0.000914679, 0.000275702, -1.53125), + vec4(0.0144609, 0.00317269, 0.00106399, -1.125), + vec4(0.0216301, 0.00794618, 0.00376991, -0.78125), + vec4(0.0347317, 0.0151085, 0.00871983, -0.5), + vec4(0.0571056, 0.0287432, 0.0172844, -0.28125), + vec4(0.0582416, 0.0659959, 0.0411329, -0.125), + vec4(0.0324462, 0.0656718, 0.0532821, -0.03125), + vec4(0.0324462, 0.0656718, 0.0532821, 0.03125), + vec4(0.0582416, 0.0659959, 0.0411329, 0.125), + vec4(0.0571056, 0.0287432, 0.0172844, 0.28125), + vec4(0.0347317, 0.0151085, 0.00871983, 0.5), + vec4(0.0216301, 0.00794618, 0.00376991, 0.78125), + vec4(0.0144609, 0.00317269, 0.00106399, 1.125), + vec4(0.0100386, 0.000914679, 0.000275702, 1.53125), + vec4(0.00317394, 0.000134823, 3.77269e-005, 2.0) +); + +#endif //USE_17_SAMPLES + + +#ifdef USE_11_SAMPLES + +const int kernel_size=11; + +QUALIFIER vec4 kernel[11] = vec4[]( + vec4(0.560479, 0.669086, 0.784728, 0.0), + vec4(0.00471691, 0.000184771, 5.07566e-005, -2.0), + vec4(0.0192831, 0.00282018, 0.00084214, -1.28), + vec4(0.03639, 0.0130999, 0.00643685, -0.72), + vec4(0.0821904, 0.0358608, 0.0209261, -0.32), + vec4(0.0771802, 0.113491, 0.0793803, -0.08), + vec4(0.0771802, 0.113491, 0.0793803, 0.08), + vec4(0.0821904, 0.0358608, 0.0209261, 0.32), + vec4(0.03639, 0.0130999, 0.00643685, 0.72), + vec4(0.0192831, 0.00282018, 0.00084214, 1.28), + vec4(0.00471691, 0.000184771, 5.07565e-005, 2.0) +); + +#endif //USE_11_SAMPLES + + +uniform float max_radius; +uniform float fovy; +uniform float camera_z_far; +uniform float camera_z_near; +uniform vec2 dir; +in vec2 uv_interp; + +uniform sampler2D source_diffuse; //texunit:0 +uniform highp usampler2D source_motion_ss; //texunit:1 +uniform sampler2D source_depth; //texunit:2 + +layout(location = 0) out vec4 frag_color; + +void main() { + + float strength = float(texture(source_motion_ss,uv_interp).r>>24)*(1.0/255.0); + strength*=strength; //stored as sqrt + + // Fetch color of current pixel: + vec4 base_color = texture(source_diffuse, uv_interp); + + if (strength>0.0) { + + + // Fetch linear depth of current pixel: + float depth = texture(source_depth, uv_interp).r * 2.0 - 1.0; + depth = 2.0 * camera_z_near * camera_z_far / (camera_z_far + camera_z_near - depth * (camera_z_far - camera_z_near)); + depth=-depth; + + + // Calculate the radius scale (1.0 for a unit plane sitting on the + // projection window): + float distance = 1.0 / tan(0.5 * fovy); + float scale = distance / -depth; //remember depth is negative by default in OpenGL + + // Calculate the final step to fetch the surrounding pixels: + vec2 step = max_radius * scale * dir; + step *= strength; // Modulate it using the alpha channel. + step *= 1.0 / 3.0; // Divide by 3 as the kernels range from -3 to 3. + + // Accumulate the center sample: + vec3 color_accum = base_color.rgb; + color_accum *= kernel[0].rgb; + + // Accumulate the other samples: + for (int i = 1; i < kernel_size; i++) { + // Fetch color and depth for current sample: + vec2 offset = uv_interp + kernel[i].a * step; + vec3 color = texture(source_diffuse, offset).rgb; + +#ifdef ENABLE_FOLLOW_SURFACE + // If the difference in depth is huge, we lerp color back to "colorM": + float depth_cmp = texture(source_depth, offset).r *2.0 - 1.0; + depth_cmp = 2.0 * camera_z_near * camera_z_far / (camera_z_far + camera_z_near - depth_cmp * (camera_z_far - camera_z_near)); + depth_cmp=-depth_cmp; + + float s = clamp(300.0f * distance * + max_radius * abs(depth - depth_cmp),0.0,1.0); + color = mix(color, base_color.rgb, s); +#endif + + // Accumulate: + color_accum += kernel[i].rgb * color; + } + + frag_color = vec4(color_accum,base_color.a); //keep alpha (used for SSAO) + } else { + frag_color = base_color; + } +} + -- cgit v1.2.3