Subsurface scattering material param is now working!

This commit is contained in:
Juan Linietsky 2016-12-02 22:23:16 -03:00
parent 8c6a586b75
commit 27a46d78ec
17 changed files with 378 additions and 49 deletions

View file

@ -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(){

View file

@ -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;

View file

@ -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<int*,int>(&p_shader->spatial.blend_mode,Shader::Spatial::BLEND_MODE_ADD);
shaders.actions_scene.render_mode_values["blend_mix"]=Pair<int*,int>(&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);

View file

@ -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 {

View file

@ -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";

View file

@ -58,6 +58,7 @@ private:
StringName time_name;
Set<StringName> used_name_defines;
Set<StringName> used_flag_pointers;
Set<StringName> used_rmode_defines;
Set<StringName> internal_functions;

View file

@ -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');

View file

@ -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);
}

View file

@ -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

View file

@ -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

View file

@ -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;
}
}

View file

@ -218,7 +218,7 @@ void Light::_bind_methods() {
ADD_PROPERTY( PropertyInfo( Variant::INT, "light/cull_mask",PROPERTY_HINT_ALL_FLAGS), _SCS("set_cull_mask"), _SCS("get_cull_mask"));
ADD_PROPERTY( PropertyInfo( Variant::BOOL, "shadow/enabled"), _SCS("set_shadow"), _SCS("has_shadow"));
ADD_PROPERTY( PropertyInfo( Variant::COLOR, "shadow/color",PROPERTY_HINT_COLOR_NO_ALPHA), _SCS("set_shadow_color"), _SCS("get_shadow_color"));
ADD_PROPERTYI( PropertyInfo( Variant::REAL, "shadow/bias",PROPERTY_HINT_RANGE,"0,16,0.01"), _SCS("set_param"), _SCS("get_param"), PARAM_SHADOW_BIAS);
ADD_PROPERTYI( PropertyInfo( Variant::REAL, "shadow/bias",PROPERTY_HINT_RANGE,"-16,16,0.01"), _SCS("set_param"), _SCS("get_param"), PARAM_SHADOW_BIAS);
ADD_PROPERTYI( PropertyInfo( Variant::REAL, "shadow/max_distance",PROPERTY_HINT_RANGE,"0,65536,0.1"), _SCS("set_param"), _SCS("get_param"), PARAM_SHADOW_MAX_DISTANCE);
ADD_PROPERTY( PropertyInfo( Variant::BOOL, "editor/editor_only"), _SCS("set_editor_only"), _SCS("is_editor_only"));

View file

@ -72,7 +72,7 @@ void FixedSpatialMaterial::init_shaders() {
shader_names->clearcoat_gloss="clearcoat_gloss";
shader_names->anisotropy="anisotropy_ratio";
shader_names->height_scale="height_scale";
shader_names->subsurface_scattering="subsurface_scattering";
shader_names->subsurface_scattering_strength="subsurface_scattering_strength";
shader_names->refraction="refraction";
shader_names->refraction_roughness="refraction_roughness";
shader_names->point_size="point_size";
@ -217,6 +217,14 @@ void FixedSpatialMaterial::_update_shader() {
code+="uniform sampler2D texture_detail_mask : hint_white;\n";
}
if (features[FEATURE_SUBSURACE_SCATTERING]) {
code+="uniform float subsurface_scattering_strength : hint_range(0,1);\n";
code+="uniform sampler2D texture_subsurface_scattering : hint_white;\n";
}
code+="\n\n";
code+="void vertex() {\n";
@ -230,7 +238,7 @@ void FixedSpatialMaterial::_update_shader() {
code+="\tPOINT_SIZE=point_size;\n";
}
code+="\tUV=UV*uv1_scale+uv1_offset;\n";
if (detail_blend_mode==DETAIL_UV_2) {
if (detail_uv==DETAIL_UV_2) {
code+="\tUV2=UV2*uv2_scale+uv2_offset;\n";
}
@ -284,6 +292,12 @@ void FixedSpatialMaterial::_update_shader() {
code+="\tAO = texture(texture_ambient_occlusion,UV).r;\n";
}
if (features[FEATURE_SUBSURACE_SCATTERING]) {
code+="\tfloat sss_tex = texture(texture_subsurface_scattering,UV).r;\n";
code+="\tSSS_STRENGTH=subsurface_scattering_strength*sss_tex;\n";
}
if (features[FEATURE_DETAIL]) {
String det_uv=detail_uv==DETAIL_UV_1?"UV":"UV2";
code+="\tvec4 detail_tex = texture(texture_detail_albedo,"+det_uv+");\n";
@ -512,17 +526,18 @@ float FixedSpatialMaterial::get_height_scale() const{
return height_scale;
}
void FixedSpatialMaterial::set_subsurface_scattering(float p_subsurface_scattering){
subsurface_scattering=p_subsurface_scattering;
VS::get_singleton()->material_set_param(_get_material(),shader_names->subsurface_scattering,subsurface_scattering);
void FixedSpatialMaterial::set_subsurface_scattering_strength(float p_subsurface_scattering_strength){
subsurface_scattering_strength=p_subsurface_scattering_strength;
VS::get_singleton()->material_set_param(_get_material(),shader_names->subsurface_scattering_strength,subsurface_scattering_strength);
}
float FixedSpatialMaterial::get_subsurface_scattering() const{
float FixedSpatialMaterial::get_subsurface_scattering_strength() const{
return subsurface_scattering;
return subsurface_scattering_strength;
}
void FixedSpatialMaterial::set_refraction(float p_refraction){
@ -806,8 +821,8 @@ void FixedSpatialMaterial::_bind_methods() {
ObjectTypeDB::bind_method(_MD("set_height_scale","height_scale"),&FixedSpatialMaterial::set_height_scale);
ObjectTypeDB::bind_method(_MD("get_height_scale"),&FixedSpatialMaterial::get_height_scale);
ObjectTypeDB::bind_method(_MD("set_subsurface_scattering","subsurface_scattering"),&FixedSpatialMaterial::set_subsurface_scattering);
ObjectTypeDB::bind_method(_MD("get_subsurface_scattering"),&FixedSpatialMaterial::get_subsurface_scattering);
ObjectTypeDB::bind_method(_MD("set_subsurface_scattering_strength","strength"),&FixedSpatialMaterial::set_subsurface_scattering_strength);
ObjectTypeDB::bind_method(_MD("get_subsurface_scattering_strength"),&FixedSpatialMaterial::get_subsurface_scattering_strength);
ObjectTypeDB::bind_method(_MD("set_refraction","refraction"),&FixedSpatialMaterial::set_refraction);
ObjectTypeDB::bind_method(_MD("get_refraction"),&FixedSpatialMaterial::get_refraction);
@ -912,7 +927,7 @@ void FixedSpatialMaterial::_bind_methods() {
ADD_PROPERTYI(PropertyInfo(Variant::OBJECT,"height/texture",PROPERTY_HINT_RESOURCE_TYPE,"Texture"),_SCS("set_texture"),_SCS("get_texture"),TEXTURE_HEIGHT);
ADD_PROPERTYI(PropertyInfo(Variant::BOOL,"subsurf_scatter/enabled"),_SCS("set_feature"),_SCS("get_feature"),FEATURE_SUBSURACE_SCATTERING);
ADD_PROPERTY(PropertyInfo(Variant::REAL,"subsurf_scatter/amount",PROPERTY_HINT_RANGE,"0,1,0.01"),_SCS("set_subsurface_scattering"),_SCS("get_subsurface_scattering"));
ADD_PROPERTY(PropertyInfo(Variant::REAL,"subsurf_scatter/strength",PROPERTY_HINT_RANGE,"0,1,0.01"),_SCS("set_subsurface_scattering_strength"),_SCS("get_subsurface_scattering_strength"));
ADD_PROPERTYI(PropertyInfo(Variant::OBJECT,"subsurf_scatter/texture",PROPERTY_HINT_RESOURCE_TYPE,"Texture"),_SCS("set_texture"),_SCS("get_texture"),TEXTURE_SUBSURFACE_SCATTERING);
ADD_PROPERTYI(PropertyInfo(Variant::BOOL,"refraction/enabled"),_SCS("set_feature"),_SCS("get_feature"),FEATURE_REFRACTION);
@ -1011,7 +1026,7 @@ FixedSpatialMaterial::FixedSpatialMaterial() : element(this) {
set_clearcoat_gloss(0.5);
set_anisotropy(0);
set_height_scale(1);
set_subsurface_scattering(0);
set_subsurface_scattering_strength(0);
set_refraction(0);
set_refraction_roughness(0);
set_line_width(1);

View file

@ -213,7 +213,7 @@ private:
StringName clearcoat_gloss;
StringName anisotropy;
StringName height_scale;
StringName subsurface_scattering;
StringName subsurface_scattering_strength;
StringName refraction;
StringName refraction_roughness;
StringName point_size;
@ -247,7 +247,7 @@ private:
float clearcoat_gloss;
float anisotropy;
float height_scale;
float subsurface_scattering;
float subsurface_scattering_strength;
float refraction;
float refraction_roughness;
float line_width;
@ -318,8 +318,8 @@ public:
void set_height_scale(float p_height_scale);
float get_height_scale() const;
void set_subsurface_scattering(float p_subsurface_scattering);
float get_subsurface_scattering() const;
void set_subsurface_scattering_strength(float p_strength);
float get_subsurface_scattering_strength() const;
void set_refraction(float p_refraction);
float get_refraction() const;

View file

@ -66,6 +66,7 @@ ShaderTypes::ShaderTypes()
shader_modes[VS::SHADER_SPATIAL].functions["fragment"]["CLEARCOAT_GLOSS"]=ShaderLanguage::TYPE_FLOAT;
shader_modes[VS::SHADER_SPATIAL].functions["fragment"]["ANISOTROPY"]=ShaderLanguage::TYPE_FLOAT;
shader_modes[VS::SHADER_SPATIAL].functions["fragment"]["ANISOTROPY_FLOW"]=ShaderLanguage::TYPE_VEC2;
shader_modes[VS::SHADER_SPATIAL].functions["fragment"]["SSS_STRENGTH"]=ShaderLanguage::TYPE_FLOAT;
shader_modes[VS::SHADER_SPATIAL].functions["fragment"]["AO"]=ShaderLanguage::TYPE_FLOAT;
shader_modes[VS::SHADER_SPATIAL].functions["fragment"]["EMISSION"]=ShaderLanguage::TYPE_VEC3;
shader_modes[VS::SHADER_SPATIAL].functions["fragment"]["SPECIAL"]=ShaderLanguage::TYPE_FLOAT;

View file

@ -1555,7 +1555,7 @@ void VisualServerScene::_light_instance_update_shadow(Instance *p_instance,const
float angle = VSG::storage->light_get_param( p_instance->base, VS::LIGHT_PARAM_SPOT_ANGLE);
CameraMatrix cm;
cm.set_perspective( angle, 1.0, 0.01, radius );
cm.set_perspective( angle*2.0, 1.0, 0.01, radius );
Vector<Plane> planes = cm.get_projection_planes(p_instance->transform);

View file

@ -556,6 +556,7 @@ public:
virtual void environment_set_adjustment(RID p_env,bool p_enable,float p_brightness,float p_contrast,float p_saturation,RID p_ramp)=0;
virtual void environment_set_ssr(RID p_env,bool p_enable, int p_max_steps,float p_accel,float p_fade,float p_depth_tolerance,bool p_smooth,bool p_roughness)=0;
/* SCENARIO API */