Support for SSAO
This commit is contained in:
parent
27a46d78ec
commit
a299c3ebf1
|
@ -534,6 +534,15 @@ float CameraMatrix::get_aspect() const {
|
|||
return w/h;
|
||||
}
|
||||
|
||||
int CameraMatrix::get_pixels_per_meter(int p_for_pixel_width) const {
|
||||
|
||||
|
||||
Vector3 result = xform(Vector3(1,0,-1));
|
||||
|
||||
return int((result.x * 0.5 + 0.5) * p_for_pixel_width);
|
||||
|
||||
}
|
||||
|
||||
float CameraMatrix::get_fov() const {
|
||||
const float * matrix = (const float*)this->matrix;
|
||||
|
||||
|
|
|
@ -87,6 +87,7 @@ struct CameraMatrix {
|
|||
|
||||
void scale_translate_to_fit(const AABB& p_aabb);
|
||||
void make_scale(const Vector3 &p_scale);
|
||||
int get_pixels_per_meter(int p_for_pixel_width) const;
|
||||
operator Transform() const;
|
||||
|
||||
CameraMatrix();
|
||||
|
|
|
@ -872,6 +872,25 @@ void RasterizerSceneGLES3::environment_set_ssr(RID p_env,bool p_enable, int p_ma
|
|||
|
||||
}
|
||||
|
||||
|
||||
void RasterizerSceneGLES3::environment_set_ssao(RID p_env,bool p_enable, float p_radius, float p_intensity, float p_radius2, float p_intensity2, float p_bias, float p_light_affect,const Color &p_color,bool p_blur) {
|
||||
|
||||
Environment *env=environment_owner.getornull(p_env);
|
||||
ERR_FAIL_COND(!env);
|
||||
|
||||
env->ssao_enabled=p_enable;
|
||||
env->ssao_radius=p_radius;
|
||||
env->ssao_intensity=p_intensity;
|
||||
env->ssao_radius2=p_radius2;
|
||||
env->ssao_intensity2=p_intensity2;
|
||||
env->ssao_bias=p_bias;
|
||||
env->ssao_light_affect=p_light_affect;
|
||||
env->ssao_color=p_color;
|
||||
env->ssao_filter=p_blur;
|
||||
|
||||
}
|
||||
|
||||
|
||||
void RasterizerSceneGLES3::environment_set_tonemap(RID p_env, bool p_enable, float p_exposure, float p_white, float p_min_luminance, float p_max_luminance, float p_auto_exp_speed, float p_auto_exp_scale, VS::EnvironmentToneMapper p_tone_mapper){
|
||||
|
||||
}
|
||||
|
@ -1460,7 +1479,7 @@ void RasterizerSceneGLES3::_setup_transform(InstanceBase *p_instance,const Trans
|
|||
}
|
||||
}
|
||||
|
||||
if (p_instance->billboard) {
|
||||
if (p_instance->billboard && storage->frame.current_rt) {
|
||||
|
||||
Vector3 scale = xf.basis.get_scale();
|
||||
|
||||
|
@ -1473,7 +1492,7 @@ void RasterizerSceneGLES3::_setup_transform(InstanceBase *p_instance,const Trans
|
|||
xf.basis.scale(scale);
|
||||
}
|
||||
|
||||
if (p_instance->billboard_y) {
|
||||
if (p_instance->billboard_y && storage->frame.current_rt) {
|
||||
|
||||
Vector3 scale = xf.basis.get_scale();
|
||||
Vector3 look_at = p_view_transform.get_origin();
|
||||
|
@ -2020,6 +2039,7 @@ void RasterizerSceneGLES3::_setup_environment(Environment *env,const CameraMatri
|
|||
state.ubo_data.bg_color[3]=bg_color.a;
|
||||
|
||||
state.env_radiance_data.ambient_contribution=env->ambient_skybox_contribution;
|
||||
state.ubo_data.ambient_occlusion_affect_light=env->ssao_light_affect;
|
||||
} else {
|
||||
state.ubo_data.bg_energy=1.0;
|
||||
state.ubo_data.ambient_energy=1.0;
|
||||
|
@ -2036,6 +2056,7 @@ void RasterizerSceneGLES3::_setup_environment(Environment *env,const CameraMatri
|
|||
state.ubo_data.bg_color[3]=linear_ambient_color.a;
|
||||
|
||||
state.env_radiance_data.ambient_contribution=0;
|
||||
state.ubo_data.ambient_occlusion_affect_light=0;
|
||||
|
||||
}
|
||||
|
||||
|
@ -2549,7 +2570,7 @@ void RasterizerSceneGLES3::_setup_reflections(RID *p_reflection_probe_cull_resul
|
|||
|
||||
void RasterizerSceneGLES3::_copy_screen() {
|
||||
|
||||
glBindVertexArray(storage->resources.quadie_array);
|
||||
glBindVertexArray( storage->resources.quadie_array);
|
||||
glDrawArrays(GL_TRIANGLE_FAN,0,4);
|
||||
glBindVertexArray(0);
|
||||
|
||||
|
@ -2689,6 +2710,141 @@ void RasterizerSceneGLES3::_render_mrts(Environment *env,const CameraMatrix &p_c
|
|||
glDisable(GL_CULL_FACE);
|
||||
glDisable(GL_BLEND);
|
||||
|
||||
bool diffuse_copied=false;
|
||||
|
||||
if (env->ssao_enabled) {
|
||||
//ssao
|
||||
|
||||
//copy from depth, convert to linear
|
||||
GLint ss[2];
|
||||
ss[0]=storage->frame.current_rt->width;
|
||||
ss[1]=storage->frame.current_rt->height;
|
||||
|
||||
for(int i=0;i<storage->frame.current_rt->effects.ssao.depth_mipmap_fbos.size();i++) {
|
||||
|
||||
state.ssao_minify_shader.set_conditional(SsaoMinifyShaderGLES3::MINIFY_START,i==0);
|
||||
state.ssao_minify_shader.bind();
|
||||
state.ssao_minify_shader.set_uniform(SsaoMinifyShaderGLES3::CAMERA_Z_FAR,p_cam_projection.get_z_far());
|
||||
state.ssao_minify_shader.set_uniform(SsaoMinifyShaderGLES3::CAMERA_Z_NEAR,p_cam_projection.get_z_near());
|
||||
state.ssao_minify_shader.set_uniform(SsaoMinifyShaderGLES3::SOURCE_MIPMAP,MAX(0,i-1));
|
||||
glUniform2iv(state.ssao_minify_shader.get_uniform(SsaoMinifyShaderGLES3::FROM_SIZE),1,ss);
|
||||
ss[0]>>=1;
|
||||
ss[1]>>=1;
|
||||
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
if (i==0) {
|
||||
glBindTexture(GL_TEXTURE_2D,storage->frame.current_rt->depth);
|
||||
} else {
|
||||
glBindTexture(GL_TEXTURE_2D,storage->frame.current_rt->effects.ssao.linear_depth);
|
||||
}
|
||||
|
||||
glBindFramebuffer(GL_FRAMEBUFFER,storage->frame.current_rt->effects.ssao.depth_mipmap_fbos[i]); //copy to front first
|
||||
glViewport(0,0,ss[0],ss[1]);
|
||||
|
||||
_copy_screen();
|
||||
|
||||
}
|
||||
ss[0]=storage->frame.current_rt->width;
|
||||
ss[1]=storage->frame.current_rt->height;
|
||||
|
||||
glViewport(0,0,ss[0],ss[1]);
|
||||
|
||||
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
glDepthFunc(GL_GREATER);
|
||||
// do SSAO!
|
||||
state.ssao_shader.set_conditional(SsaoShaderGLES3::ENABLE_RADIUS2,env->ssao_radius2>0.001);
|
||||
state.ssao_shader.bind();
|
||||
state.ssao_shader.set_uniform(SsaoShaderGLES3::CAMERA_Z_FAR,p_cam_projection.get_z_far());
|
||||
state.ssao_shader.set_uniform(SsaoShaderGLES3::CAMERA_Z_NEAR,p_cam_projection.get_z_near());
|
||||
glUniform2iv(state.ssao_shader.get_uniform(SsaoShaderGLES3::SCREEN_SIZE),1,ss);
|
||||
float radius = env->ssao_radius;
|
||||
state.ssao_shader.set_uniform(SsaoShaderGLES3::RADIUS,radius);
|
||||
float intensity = env->ssao_intensity;
|
||||
state.ssao_shader.set_uniform(SsaoShaderGLES3::INTENSITY_DIV_R6,intensity / pow(radius, 6.0f));
|
||||
|
||||
if (env->ssao_radius2>0.001) {
|
||||
|
||||
float radius2 = env->ssao_radius2;
|
||||
state.ssao_shader.set_uniform(SsaoShaderGLES3::RADIUS2,radius2);
|
||||
float intensity2 = env->ssao_intensity2;
|
||||
state.ssao_shader.set_uniform(SsaoShaderGLES3::INTENSITY_DIV_R62,intensity2 / pow(radius2, 6.0f));
|
||||
|
||||
}
|
||||
|
||||
float proj_info[4]={
|
||||
-2.0f / (ss[0]*p_cam_projection.matrix[0][0]),
|
||||
-2.0f / (ss[1]*p_cam_projection.matrix[1][1]),
|
||||
( 1.0f - p_cam_projection.matrix[0][2]) / p_cam_projection.matrix[0][0],
|
||||
( 1.0f + p_cam_projection.matrix[1][2]) / p_cam_projection.matrix[1][1]
|
||||
};
|
||||
|
||||
glUniform4fv(state.ssao_shader.get_uniform(SsaoShaderGLES3::PROJ_INFO),1,proj_info);
|
||||
float pixels_per_meter = float(p_cam_projection.get_pixels_per_meter(ss[0]));
|
||||
|
||||
state.ssao_shader.set_uniform(SsaoShaderGLES3::PROJ_SCALE,pixels_per_meter);
|
||||
state.ssao_shader.set_uniform(SsaoShaderGLES3::BIAS,env->ssao_bias);
|
||||
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glBindTexture(GL_TEXTURE_2D,storage->frame.current_rt->depth);
|
||||
glActiveTexture(GL_TEXTURE1);
|
||||
glBindTexture(GL_TEXTURE_2D,storage->frame.current_rt->effects.ssao.linear_depth);
|
||||
glActiveTexture(GL_TEXTURE2);
|
||||
glBindTexture(GL_TEXTURE_2D,storage->frame.current_rt->buffers.normal_rough);
|
||||
|
||||
glBindFramebuffer(GL_FRAMEBUFFER,storage->frame.current_rt->effects.ssao.blur_fbo[0]); //copy to front first
|
||||
Color white(1,1,1,1);
|
||||
glClearBufferfv(GL_COLOR,0,white.components); // specular
|
||||
|
||||
_copy_screen();
|
||||
|
||||
//do the batm, i mean blur
|
||||
|
||||
state.ssao_blur_shader.bind();
|
||||
|
||||
if (env->ssao_filter) {
|
||||
for(int i=0;i<2;i++) {
|
||||
|
||||
state.ssao_blur_shader.set_uniform(SsaoBlurShaderGLES3::CAMERA_Z_FAR,p_cam_projection.get_z_far());
|
||||
state.ssao_blur_shader.set_uniform(SsaoBlurShaderGLES3::CAMERA_Z_NEAR,p_cam_projection.get_z_near());
|
||||
GLint axis[2]={i,1-i};
|
||||
glUniform2iv(state.ssao_blur_shader.get_uniform(SsaoBlurShaderGLES3::AXIS),1,axis);
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glBindTexture(GL_TEXTURE_2D,storage->frame.current_rt->effects.ssao.blur_red[i]);
|
||||
glActiveTexture(GL_TEXTURE1);
|
||||
glBindTexture(GL_TEXTURE_2D,storage->frame.current_rt->depth);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER,storage->frame.current_rt->effects.ssao.blur_fbo[1-i]);
|
||||
if (i==0) {
|
||||
glClearBufferfv(GL_COLOR,0,white.components); // specular
|
||||
}
|
||||
_copy_screen();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
glDepthFunc(GL_LEQUAL);
|
||||
|
||||
// just copy diffuse while applying SSAO
|
||||
|
||||
state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::SSAO_MERGE,true);
|
||||
state.effect_blur_shader.bind();
|
||||
state.effect_blur_shader.set_uniform(EffectBlurShaderGLES3::SSAO_COLOR,env->ssao_color);
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glBindTexture(GL_TEXTURE_2D,storage->frame.current_rt->buffers.diffuse); //previous level, since mipmaps[0] starts one level bigger
|
||||
glActiveTexture(GL_TEXTURE1);
|
||||
glBindTexture(GL_TEXTURE_2D,storage->frame.current_rt->effects.ssao.blur_red[0]); //previous level, since mipmaps[0] starts one level bigger
|
||||
glBindFramebuffer(GL_FRAMEBUFFER,storage->frame.current_rt->effects.mip_maps[0].sizes[0].fbo); // copy to base level
|
||||
_copy_screen();
|
||||
state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::SSAO_MERGE,false);
|
||||
|
||||
|
||||
|
||||
|
||||
diffuse_copied=true;
|
||||
}
|
||||
|
||||
|
||||
if (state.used_sss) {//sss enabled
|
||||
//copy diffuse while performing sss
|
||||
|
||||
|
@ -2704,7 +2860,13 @@ void RasterizerSceneGLES3::_render_mrts(Environment *env,const CameraMatrix &p_c
|
|||
state.sss_shader.set_uniform(SubsurfScatteringShaderGLES3::DIR,Vector2(1,0));
|
||||
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glBindTexture(GL_TEXTURE_2D,storage->frame.current_rt->buffers.diffuse);
|
||||
if (diffuse_copied) {
|
||||
glBindTexture(GL_TEXTURE_2D,storage->frame.current_rt->effects.mip_maps[0].color);
|
||||
} else {
|
||||
glBindTexture(GL_TEXTURE_2D,storage->frame.current_rt->buffers.diffuse);
|
||||
diffuse_copied=true;
|
||||
}
|
||||
|
||||
glActiveTexture(GL_TEXTURE1);
|
||||
glBindTexture(GL_TEXTURE_2D,storage->frame.current_rt->buffers.motion_sss);
|
||||
glActiveTexture(GL_TEXTURE2);
|
||||
|
@ -2721,7 +2883,10 @@ void RasterizerSceneGLES3::_render_mrts(Environment *env,const CameraMatrix &p_c
|
|||
glBindFramebuffer(GL_FRAMEBUFFER,storage->frame.current_rt->effects.mip_maps[0].sizes[0].fbo); // copy to base level
|
||||
_copy_screen();
|
||||
|
||||
} else {
|
||||
}
|
||||
|
||||
|
||||
if (!diffuse_copied) {
|
||||
// just copy diffuse
|
||||
storage->shaders.copy.bind();
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
|
@ -2826,7 +2991,7 @@ void RasterizerSceneGLES3::_render_mrts(Environment *env,const CameraMatrix &p_c
|
|||
glBlendEquation(GL_FUNC_ADD);
|
||||
glBlendFunc(GL_ONE,GL_ONE); //use additive to accumulate one over the other
|
||||
|
||||
_copy_screen();
|
||||
//_copy_screen();
|
||||
|
||||
glDisable(GL_BLEND); //end additive
|
||||
|
||||
|
@ -2878,6 +3043,11 @@ void RasterizerSceneGLES3::render_scene(const Transform& p_cam_transform,const C
|
|||
} else {
|
||||
state.ubo_data.reflection_multiplier=1.0;
|
||||
}
|
||||
|
||||
state.ubo_data.subsurface_scatter_width=subsurface_scatter_size;
|
||||
|
||||
|
||||
|
||||
_setup_environment(env,p_cam_projection,p_cam_transform);
|
||||
|
||||
_setup_lights(p_light_cull_result,p_light_cull_count,p_cam_transform.affine_inverse(),p_cam_projection,p_shadow_atlas);
|
||||
|
@ -4026,6 +4196,9 @@ void RasterizerSceneGLES3::initialize() {
|
|||
state.ssr_shader.init();
|
||||
state.effect_blur_shader.init();
|
||||
state.sss_shader.init();
|
||||
state.ssao_minify_shader.init();
|
||||
state.ssao_shader.init();
|
||||
state.ssao_blur_shader.init();
|
||||
|
||||
|
||||
{
|
||||
|
|
|
@ -8,6 +8,9 @@
|
|||
#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"
|
||||
#include "drivers/gles3/shaders/ssao_minify.glsl.h"
|
||||
#include "drivers/gles3/shaders/ssao.glsl.h"
|
||||
#include "drivers/gles3/shaders/ssao_blur.glsl.h"
|
||||
|
||||
class RasterizerSceneGLES3 : public RasterizerScene {
|
||||
public:
|
||||
|
@ -62,6 +65,9 @@ public:
|
|||
ScreenSpaceReflectionShaderGLES3 ssr_shader;
|
||||
EffectBlurShaderGLES3 effect_blur_shader;
|
||||
SubsurfScatteringShaderGLES3 sss_shader;
|
||||
SsaoMinifyShaderGLES3 ssao_minify_shader;
|
||||
SsaoShaderGLES3 ssao_shader;
|
||||
SsaoBlurShaderGLES3 ssao_blur_shader;
|
||||
|
||||
|
||||
struct SceneDataUBO {
|
||||
|
@ -81,6 +87,8 @@ public:
|
|||
float shadow_atlas_pixel_size[2];
|
||||
float shadow_directional_pixel_size[2];
|
||||
float reflection_multiplier;
|
||||
float subsurface_scatter_width;
|
||||
float ambient_occlusion_affect_light;
|
||||
|
||||
} ubo_data;
|
||||
|
||||
|
@ -316,6 +324,15 @@ public:
|
|||
bool ssr_roughness;
|
||||
|
||||
|
||||
bool ssao_enabled;
|
||||
float ssao_intensity;
|
||||
float ssao_radius;
|
||||
float ssao_intensity2;
|
||||
float ssao_radius2;
|
||||
float ssao_bias;
|
||||
float ssao_light_affect;
|
||||
Color ssao_color;
|
||||
bool ssao_filter;
|
||||
|
||||
Environment() {
|
||||
bg_mode=VS::ENV_BG_CLEAR_COLOR;
|
||||
|
@ -334,6 +351,16 @@ public:
|
|||
ssr_smooth=true;
|
||||
ssr_roughness=true;
|
||||
|
||||
ssao_enabled=false;
|
||||
ssao_intensity=1.0;
|
||||
ssao_radius=1.0;
|
||||
ssao_intensity2=1.0;
|
||||
ssao_radius2=0.0;
|
||||
ssao_bias=0.01;
|
||||
ssao_light_affect=0;
|
||||
ssao_filter=true;
|
||||
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -353,6 +380,7 @@ public:
|
|||
virtual void environment_set_fog(RID p_env,bool p_enable,float p_begin,float p_end,RID p_gradient_texture);
|
||||
|
||||
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);
|
||||
virtual void environment_set_ssao(RID p_env,bool p_enable, float p_radius, float p_radius2, float p_intensity2, float p_intensity, float p_bias, float p_light_affect,const Color &p_color,bool p_blur);
|
||||
|
||||
virtual void environment_set_tonemap(RID p_env,bool p_enable,float p_exposure,float p_white,float p_min_luminance,float p_max_luminance,float p_auto_exp_speed,float p_auto_exp_scale,VS::EnvironmentToneMapper p_tone_mapper);
|
||||
virtual void environment_set_adjustment(RID p_env,bool p_enable,float p_brightness,float p_contrast,float p_saturation,RID p_ramp);
|
||||
|
|
|
@ -4785,6 +4785,20 @@ void RasterizerStorageGLES3::_render_target_clear(RenderTarget *rt) {
|
|||
rt->depth=0;
|
||||
}
|
||||
|
||||
if (rt->effects.ssao.blur_fbo[0]) {
|
||||
glDeleteFramebuffers(1,&rt->effects.ssao.blur_fbo[0]);
|
||||
glDeleteTextures(1,&rt->effects.ssao.blur_red[0]);
|
||||
glDeleteFramebuffers(1,&rt->effects.ssao.blur_fbo[1]);
|
||||
glDeleteTextures(1,&rt->effects.ssao.blur_red[1]);
|
||||
for(int i=0;i<rt->effects.ssao.depth_mipmap_fbos.size();i++) {
|
||||
glDeleteFramebuffers(1,&rt->effects.ssao.depth_mipmap_fbos[i]);
|
||||
}
|
||||
|
||||
rt->effects.ssao.depth_mipmap_fbos.clear();
|
||||
|
||||
glDeleteTextures(1,&rt->effects.ssao.linear_depth);
|
||||
}
|
||||
|
||||
Texture *tex = texture_owner.get(rt->texture);
|
||||
tex->alloc_height=0;
|
||||
tex->alloc_width=0;
|
||||
|
@ -5043,6 +5057,67 @@ void RasterizerStorageGLES3::_render_target_allocate(RenderTarget *rt){
|
|||
//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);
|
||||
|
||||
|
||||
}
|
||||
///////////////// ssao
|
||||
|
||||
//AO strength textures
|
||||
for(int i=0;i<2;i++) {
|
||||
|
||||
glGenFramebuffers(1, &rt->effects.ssao.blur_fbo[i]);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, rt->effects.ssao.blur_fbo[i]);
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
|
||||
GL_TEXTURE_2D, rt->depth, 0);
|
||||
|
||||
glGenTextures(1, &rt->effects.ssao.blur_red[i]);
|
||||
glBindTexture(GL_TEXTURE_2D, rt->effects.ssao.blur_red[i]);
|
||||
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_R8, rt->width, rt->height, 0, GL_RED, 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_ATTACHMENT0, GL_TEXTURE_2D, rt->effects.ssao.blur_red[i], 0);
|
||||
|
||||
status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
|
||||
if (status != GL_FRAMEBUFFER_COMPLETE) {
|
||||
_render_target_clear(rt);
|
||||
ERR_FAIL_COND( status != GL_FRAMEBUFFER_COMPLETE );
|
||||
}
|
||||
|
||||
}
|
||||
//5 mip levels for depth texture, but base is read separately
|
||||
|
||||
glGenTextures(1, &rt->effects.ssao.linear_depth);
|
||||
glBindTexture(GL_TEXTURE_2D, rt->effects.ssao.linear_depth);
|
||||
|
||||
int ssao_w=rt->width/2;
|
||||
int ssao_h=rt->height/2;
|
||||
|
||||
|
||||
for(int i=0;i<4;i++) { //5, but 4 mips, base is read directly to save bw
|
||||
|
||||
glTexImage2D(GL_TEXTURE_2D, i, GL_R16UI, ssao_w, ssao_h, 0, GL_RED_INTEGER, GL_UNSIGNED_SHORT, NULL);
|
||||
ssao_w>>=1;
|
||||
ssao_h>>=1;
|
||||
}
|
||||
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_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);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 3);
|
||||
|
||||
for(int i=0;i<4;i++) { //5, but 4 mips, base is read directly to save bw
|
||||
|
||||
GLuint fbo;
|
||||
glGenFramebuffers(1, &fbo);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, rt->effects.ssao.linear_depth, i);
|
||||
rt->effects.ssao.depth_mipmap_fbos.push_back(fbo);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -5653,6 +5728,7 @@ void RasterizerStorageGLES3::initialize() {
|
|||
glBindBuffer(GL_ARRAY_BUFFER,0); //unbind
|
||||
}
|
||||
|
||||
//generic quadie for copying without touching skybox
|
||||
|
||||
{
|
||||
//transform feedback buffers
|
||||
|
|
|
@ -911,6 +911,17 @@ public:
|
|||
MipMaps mip_maps[2]; //first mipmap chain starts from full-screen
|
||||
//GLuint depth2; //depth for the second mipmap chain, in case of desiring upsampling
|
||||
|
||||
struct SSAO {
|
||||
GLuint blur_fbo[2]; // blur fbo
|
||||
GLuint blur_red[2]; // 8 bits red buffer
|
||||
|
||||
GLuint linear_depth;
|
||||
|
||||
Vector<GLuint> depth_mipmap_fbos; //fbos for depth mipmapsla ver
|
||||
|
||||
SSAO() { blur_fbo[0]=0; blur_fbo[1]=0; linear_depth=0; }
|
||||
} ssao;
|
||||
|
||||
Effects() {
|
||||
|
||||
}
|
||||
|
|
|
@ -12,5 +12,8 @@ if env['BUILDERS'].has_key('GLES3_GLSL'):
|
|||
env.GLES3_GLSL('screen_space_reflection.glsl');
|
||||
env.GLES3_GLSL('effect_blur.glsl');
|
||||
env.GLES3_GLSL('subsurf_scattering.glsl');
|
||||
env.GLES3_GLSL('ssao.glsl');
|
||||
env.GLES3_GLSL('ssao_minify.glsl');
|
||||
env.GLES3_GLSL('ssao_blur.glsl');
|
||||
|
||||
|
||||
|
|
|
@ -19,12 +19,22 @@ void main() {
|
|||
in vec2 uv_interp;
|
||||
uniform sampler2D source_color; //texunit:0
|
||||
|
||||
#ifdef SSAO_MERGE
|
||||
uniform sampler2D source_ssao; //texunit:1
|
||||
#endif
|
||||
|
||||
uniform float lod;
|
||||
uniform vec2 pixel_size;
|
||||
|
||||
|
||||
layout(location = 0) out vec4 frag_color;
|
||||
|
||||
#ifdef SSAO_MERGE
|
||||
|
||||
uniform vec4 ssao_color;
|
||||
|
||||
#endif
|
||||
|
||||
void main() {
|
||||
|
||||
|
||||
|
@ -52,6 +62,13 @@ void main() {
|
|||
frag_color = color;
|
||||
#endif
|
||||
|
||||
#ifdef SSAO_MERGE
|
||||
|
||||
vec4 color =textureLod( source_color, uv_interp,0.0);
|
||||
float ssao =textureLod( source_ssao, uv_interp,0.0).r;
|
||||
|
||||
frag_color = vec4( mix(color.rgb,color.rgb*mix(ssao_color.rgb,vec3(1.0),ssao),color.a), 1.0 );
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
|
@ -76,6 +76,7 @@ layout(std140) uniform SceneData { //ubo:0
|
|||
|
||||
float reflection_multiplier;
|
||||
float subsurface_scatter_width;
|
||||
float ambient_occlusion_affect_light;
|
||||
|
||||
};
|
||||
|
||||
|
@ -387,6 +388,7 @@ layout(std140) uniform SceneData {
|
|||
|
||||
float reflection_multiplier;
|
||||
float subsurface_scatter_width;
|
||||
float ambient_occlusion_affect_light;
|
||||
|
||||
};
|
||||
|
||||
|
@ -1223,7 +1225,7 @@ LIGHT_SHADER_CODE
|
|||
float max_ambient=max(ambient_light.r,max(ambient_light.g,ambient_light.b));
|
||||
float max_diffuse=max(diffuse_light.r,max(diffuse_light.g,diffuse_light.b));
|
||||
float total_ambient = max_ambient+max_diffuse+max_emission;
|
||||
float ambient_scale = (total_ambient>0.0) ? max_ambient/total_ambient : 0.0;
|
||||
float ambient_scale = (total_ambient>0.0) ? (max_ambient+ambient_occlusion_affect_light*max_diffuse)/total_ambient : 0.0;
|
||||
#endif //ENABLE_AO
|
||||
|
||||
diffuse_buffer=vec4(emission+diffuse_light+ambient_light,ambient_scale);
|
||||
|
|
|
@ -0,0 +1,247 @@
|
|||
[vertex]
|
||||
|
||||
|
||||
layout(location=0) in highp vec4 vertex_attrib;
|
||||
|
||||
void main() {
|
||||
|
||||
gl_Position = vertex_attrib;
|
||||
gl_Position.z=1.0;
|
||||
}
|
||||
|
||||
[fragment]
|
||||
|
||||
|
||||
#define NUM_SAMPLES (11)
|
||||
|
||||
// If using depth mip levels, the log of the maximum pixel offset before we need to switch to a lower
|
||||
// miplevel to maintain reasonable spatial locality in the cache
|
||||
// If this number is too small (< 3), too many taps will land in the same pixel, and we'll get bad variance that manifests as flashing.
|
||||
// If it is too high (> 5), we'll get bad performance because we're not using the MIP levels effectively
|
||||
#define LOG_MAX_OFFSET (3)
|
||||
|
||||
// This must be less than or equal to the MAX_MIP_LEVEL defined in SSAO.cpp
|
||||
#define MAX_MIP_LEVEL (4)
|
||||
|
||||
// This is the number of turns around the circle that the spiral pattern makes. This should be prime to prevent
|
||||
// taps from lining up. This particular choice was tuned for NUM_SAMPLES == 9
|
||||
#define NUM_SPIRAL_TURNS (7)
|
||||
|
||||
|
||||
uniform sampler2D source_depth; //texunit:0
|
||||
uniform usampler2D source_depth_mipmaps; //texunit:1
|
||||
uniform sampler2D source_normal; //texunit:2
|
||||
|
||||
uniform ivec2 screen_size;
|
||||
uniform float camera_z_far;
|
||||
uniform float camera_z_near;
|
||||
|
||||
uniform float intensity_div_r6;
|
||||
uniform float radius;
|
||||
|
||||
#ifdef ENABLE_RADIUS2
|
||||
uniform float intensity_div_r62;
|
||||
uniform float radius2;
|
||||
#endif
|
||||
|
||||
uniform float bias;
|
||||
uniform float proj_scale;
|
||||
|
||||
layout(location = 0) out float visibility;
|
||||
|
||||
uniform vec4 proj_info;
|
||||
|
||||
vec3 reconstructCSPosition(vec2 S, float z) {
|
||||
return vec3((S.xy * proj_info.xy + proj_info.zw) * z, z);
|
||||
}
|
||||
|
||||
vec3 getPosition(ivec2 ssP) {
|
||||
vec3 P;
|
||||
P.z = texelFetch(source_depth, ssP, 0).r;
|
||||
|
||||
P.z = P.z * 2.0 - 1.0;
|
||||
P.z = 2.0 * camera_z_near * camera_z_far / (camera_z_far + camera_z_near - P.z * (camera_z_far - camera_z_near));
|
||||
P.z = -P.z;
|
||||
|
||||
// Offset to pixel center
|
||||
P = reconstructCSPosition(vec2(ssP) + vec2(0.5), P.z);
|
||||
return P;
|
||||
}
|
||||
|
||||
/** Reconstructs screen-space unit normal from screen-space position */
|
||||
vec3 reconstructCSFaceNormal(vec3 C) {
|
||||
return normalize(cross(dFdy(C), dFdx(C)));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/** Returns a unit vector and a screen-space radius for the tap on a unit disk (the caller should scale by the actual disk radius) */
|
||||
vec2 tapLocation(int sampleNumber, float spinAngle, out float ssR){
|
||||
// Radius relative to ssR
|
||||
float alpha = float(sampleNumber + 0.5) * (1.0 / NUM_SAMPLES);
|
||||
float angle = alpha * (NUM_SPIRAL_TURNS * 6.28) + spinAngle;
|
||||
|
||||
ssR = alpha;
|
||||
return vec2(cos(angle), sin(angle));
|
||||
}
|
||||
|
||||
|
||||
/** Read the camera-space position of the point at screen-space pixel ssP + unitOffset * ssR. Assumes length(unitOffset) == 1 */
|
||||
vec3 getOffsetPosition(ivec2 ssC, vec2 unitOffset, float ssR) {
|
||||
// Derivation:
|
||||
// mipLevel = floor(log(ssR / MAX_OFFSET));
|
||||
int mipLevel = clamp(int(floor(log2(ssR))) - LOG_MAX_OFFSET, 0, MAX_MIP_LEVEL);
|
||||
|
||||
ivec2 ssP = ivec2(ssR * unitOffset) + ssC;
|
||||
|
||||
vec3 P;
|
||||
|
||||
// We need to divide by 2^mipLevel to read the appropriately scaled coordinate from a MIP-map.
|
||||
// Manually clamp to the texture size because texelFetch bypasses the texture unit
|
||||
ivec2 mipP = clamp(ssP >> mipLevel, ivec2(0), (screen_size >> mipLevel) - ivec2(1));
|
||||
|
||||
|
||||
if (mipLevel < 1) {
|
||||
//read from depth buffer
|
||||
P.z = texelFetch(source_depth, mipP, 0).r;
|
||||
P.z = P.z * 2.0 - 1.0;
|
||||
P.z = 2.0 * camera_z_near * camera_z_far / (camera_z_far + camera_z_near - P.z * (camera_z_far - camera_z_near));
|
||||
P.z = -P.z;
|
||||
|
||||
} else {
|
||||
//read from mipmaps
|
||||
uint d = texelFetch(source_depth_mipmaps, mipP, mipLevel-1).r;
|
||||
P.z = -(float(d)/65535.0)*camera_z_far;
|
||||
}
|
||||
|
||||
|
||||
// Offset to pixel center
|
||||
P = reconstructCSPosition(vec2(ssP) + vec2(0.5), P.z);
|
||||
|
||||
return P;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/** Compute the occlusion due to sample with index \a i about the pixel at \a ssC that corresponds
|
||||
to camera-space point \a C with unit normal \a n_C, using maximum screen-space sampling radius \a ssDiskRadius
|
||||
|
||||
Note that units of H() in the HPG12 paper are meters, not
|
||||
unitless. The whole falloff/sampling function is therefore
|
||||
unitless. In this implementation, we factor out (9 / radius).
|
||||
|
||||
Four versions of the falloff function are implemented below
|
||||
*/
|
||||
float sampleAO(in ivec2 ssC, in vec3 C, in vec3 n_C, in float ssDiskRadius,in float p_radius, in int tapIndex, in float randomPatternRotationAngle) {
|
||||
// Offset on the unit disk, spun for this pixel
|
||||
float ssR;
|
||||
vec2 unitOffset = tapLocation(tapIndex, randomPatternRotationAngle, ssR);
|
||||
ssR *= ssDiskRadius;
|
||||
|
||||
// The occluding point in camera space
|
||||
vec3 Q = getOffsetPosition(ssC, unitOffset, ssR);
|
||||
|
||||
vec3 v = Q - C;
|
||||
|
||||
float vv = dot(v, v);
|
||||
float vn = dot(v, n_C);
|
||||
|
||||
const float epsilon = 0.01;
|
||||
float radius2 = p_radius*p_radius;
|
||||
|
||||
// A: From the HPG12 paper
|
||||
// Note large epsilon to avoid overdarkening within cracks
|
||||
//return float(vv < radius2) * max((vn - bias) / (epsilon + vv), 0.0) * radius2 * 0.6;
|
||||
|
||||
// B: Smoother transition to zero (lowers contrast, smoothing out corners). [Recommended]
|
||||
float f=max(radius2 - vv, 0.0);
|
||||
return f * f * f * max((vn - bias) / (epsilon + vv), 0.0);
|
||||
|
||||
// C: Medium contrast (which looks better at high radii), no division. Note that the
|
||||
// contribution still falls off with radius^2, but we've adjusted the rate in a way that is
|
||||
// more computationally efficient and happens to be aesthetically pleasing.
|
||||
// return 4.0 * max(1.0 - vv * invRadius2, 0.0) * max(vn - bias, 0.0);
|
||||
|
||||
// D: Low contrast, no division operation
|
||||
// return 2.0 * float(vv < radius * radius) * max(vn - bias, 0.0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void main() {
|
||||
|
||||
|
||||
// Pixel being shaded
|
||||
ivec2 ssC = ivec2(gl_FragCoord.xy);
|
||||
|
||||
// World space point being shaded
|
||||
vec3 C = getPosition(ssC);
|
||||
|
||||
/* if (C.z <= -camera_z_far*0.999) {
|
||||
// We're on the skybox
|
||||
visibility=1.0;
|
||||
return;
|
||||
}*/
|
||||
|
||||
//visibility=-C.z/camera_z_far;
|
||||
//return;
|
||||
|
||||
//vec3 n_C = texelFetch(source_normal,ssC,0).rgb * 2.0 - 1.0;
|
||||
|
||||
vec3 n_C = reconstructCSFaceNormal(C);
|
||||
n_C = -n_C;
|
||||
|
||||
|
||||
// Hash function used in the HPG12 AlchemyAO paper
|
||||
float randomPatternRotationAngle = (3 * ssC.x ^ ssC.y + ssC.x * ssC.y) * 10;
|
||||
|
||||
// Reconstruct normals from positions. These will lead to 1-pixel black lines
|
||||
// at depth discontinuities, however the blur will wipe those out so they are not visible
|
||||
// in the final image.
|
||||
|
||||
// Choose the screen-space sample radius
|
||||
// proportional to the projected area of the sphere
|
||||
float ssDiskRadius = -proj_scale * radius / C.z;
|
||||
|
||||
float sum = 0.0;
|
||||
for (int i = 0; i < NUM_SAMPLES; ++i) {
|
||||
sum += sampleAO(ssC, C, n_C, ssDiskRadius, radius,i, randomPatternRotationAngle);
|
||||
}
|
||||
|
||||
float A = max(0.0, 1.0 - sum * intensity_div_r6 * (5.0 / NUM_SAMPLES));
|
||||
|
||||
#ifdef ENABLE_RADIUS2
|
||||
|
||||
//go again for radius2
|
||||
randomPatternRotationAngle = (5 * ssC.x ^ ssC.y + ssC.x * ssC.y) * 11;
|
||||
|
||||
// Reconstruct normals from positions. These will lead to 1-pixel black lines
|
||||
// at depth discontinuities, however the blur will wipe those out so they are not visible
|
||||
// in the final image.
|
||||
|
||||
// Choose the screen-space sample radius
|
||||
// proportional to the projected area of the sphere
|
||||
ssDiskRadius = -proj_scale * radius2 / C.z;
|
||||
|
||||
sum = 0.0;
|
||||
for (int i = 0; i < NUM_SAMPLES; ++i) {
|
||||
sum += sampleAO(ssC, C, n_C, ssDiskRadius,radius2, i, randomPatternRotationAngle);
|
||||
}
|
||||
|
||||
A= min(A,max(0.0, 1.0 - sum * intensity_div_r62 * (5.0 / NUM_SAMPLES)));
|
||||
#endif
|
||||
// Bilateral box-filter over a quad for free, respecting depth edges
|
||||
// (the difference that this makes is subtle)
|
||||
if (abs(dFdx(C.z)) < 0.02) {
|
||||
A -= dFdx(A) * ((ssC.x & 1) - 0.5);
|
||||
}
|
||||
if (abs(dFdy(C.z)) < 0.02) {
|
||||
A -= dFdy(A) * ((ssC.y & 1) - 0.5);
|
||||
}
|
||||
|
||||
visibility = A;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,113 @@
|
|||
[vertex]
|
||||
|
||||
|
||||
layout(location=0) in highp vec4 vertex_attrib;
|
||||
|
||||
|
||||
void main() {
|
||||
|
||||
gl_Position = vertex_attrib;
|
||||
gl_Position.z=1.0;
|
||||
}
|
||||
|
||||
[fragment]
|
||||
|
||||
|
||||
uniform sampler2D source_ssao; //texunit:0
|
||||
uniform sampler2D source_depth; //texunit:1
|
||||
|
||||
|
||||
layout(location = 0) out float visibility;
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Tunable Parameters:
|
||||
|
||||
/** Increase to make depth edges crisper. Decrease to reduce flicker. */
|
||||
#define EDGE_SHARPNESS (1.0)
|
||||
|
||||
/** Step in 2-pixel intervals since we already blurred against neighbors in the
|
||||
first AO pass. This constant can be increased while R decreases to improve
|
||||
performance at the expense of some dithering artifacts.
|
||||
|
||||
Morgan found that a scale of 3 left a 1-pixel checkerboard grid that was
|
||||
unobjectionable after shading was applied but eliminated most temporal incoherence
|
||||
from using small numbers of sample taps.
|
||||
*/
|
||||
#define SCALE (3)
|
||||
|
||||
/** Filter radius in pixels. This will be multiplied by SCALE. */
|
||||
#define R (4)
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
// Gaussian coefficients
|
||||
const float gaussian[R + 1] =
|
||||
// float[](0.356642, 0.239400, 0.072410, 0.009869);
|
||||
// float[](0.398943, 0.241971, 0.053991, 0.004432, 0.000134); // stddev = 1.0
|
||||
float[](0.153170, 0.144893, 0.122649, 0.092902, 0.062970); // stddev = 2.0
|
||||
// float[](0.111220, 0.107798, 0.098151, 0.083953, 0.067458, 0.050920, 0.036108); // stddev = 3.0
|
||||
|
||||
/** (1, 0) or (0, 1)*/
|
||||
uniform ivec2 axis;
|
||||
|
||||
uniform float camera_z_far;
|
||||
uniform float camera_z_near;
|
||||
|
||||
void main() {
|
||||
|
||||
ivec2 ssC = ivec2(gl_FragCoord.xy);
|
||||
|
||||
float depth = texelFetch(source_depth, ssC, 0).r;
|
||||
|
||||
depth = depth * 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));
|
||||
|
||||
float depth_divide = 1.0 / camera_z_far;
|
||||
|
||||
depth*=depth_divide;
|
||||
|
||||
//if (depth > camera_z_far*0.999) {
|
||||
// discard;//skybox
|
||||
//}
|
||||
|
||||
float sum = texelFetch(source_ssao, ssC, 0).r;
|
||||
|
||||
// Base weight for depth falloff. Increase this for more blurriness,
|
||||
// decrease it for better edge discrimination
|
||||
float BASE = gaussian[0];
|
||||
float totalWeight = BASE;
|
||||
sum *= totalWeight;
|
||||
|
||||
|
||||
for (int r = -R; r <= R; ++r) {
|
||||
// We already handled the zero case above. This loop should be unrolled and the static branch optimized out,
|
||||
// so the IF statement has no runtime cost
|
||||
if (r != 0) {
|
||||
|
||||
ivec2 ppos = ssC + axis * (r * SCALE);
|
||||
float value = texelFetch(source_ssao, ppos, 0).r;
|
||||
float temp_depth = texelFetch(source_depth, ssC, 0).r;
|
||||
|
||||
temp_depth = temp_depth * 2.0 - 1.0;
|
||||
temp_depth = 2.0 * camera_z_near * camera_z_far / (camera_z_far + camera_z_near - temp_depth * (camera_z_far - camera_z_near));
|
||||
temp_depth *= depth_divide;
|
||||
|
||||
// spatial domain: offset gaussian tap
|
||||
float weight = 0.3 + gaussian[abs(r)];
|
||||
|
||||
// range domain (the "bilateral" weight). As depth difference increases, decrease weight.
|
||||
weight *= max(0.0, 1.0
|
||||
- (EDGE_SHARPNESS * 2000.0) * abs(temp_depth - depth)
|
||||
);
|
||||
|
||||
sum += value * weight;
|
||||
totalWeight += weight;
|
||||
}
|
||||
}
|
||||
|
||||
const float epsilon = 0.0001;
|
||||
visibility = sum / (totalWeight + epsilon);
|
||||
}
|
|
@ -0,0 +1,55 @@
|
|||
[vertex]
|
||||
|
||||
|
||||
layout(location=0) in highp vec4 vertex_attrib;
|
||||
|
||||
void main() {
|
||||
|
||||
gl_Position = vertex_attrib;
|
||||
}
|
||||
|
||||
[fragment]
|
||||
|
||||
|
||||
#ifdef MINIFY_START
|
||||
|
||||
#define SDEPTH_TYPE highp sampler2D
|
||||
uniform float camera_z_far;
|
||||
uniform float camera_z_near;
|
||||
|
||||
#else
|
||||
|
||||
#define SDEPTH_TYPE mediump usampler2D
|
||||
|
||||
#endif
|
||||
|
||||
uniform SDEPTH_TYPE source_depth; //texunit:0
|
||||
|
||||
uniform ivec2 from_size;
|
||||
uniform int source_mipmap;
|
||||
|
||||
layout(location = 0) out mediump uint depth;
|
||||
|
||||
void main() {
|
||||
|
||||
|
||||
ivec2 ssP = ivec2(gl_FragCoord.xy);
|
||||
|
||||
// Rotated grid subsampling to avoid XY directional bias or Z precision bias while downsampling.
|
||||
// On DX9, the bit-and can be implemented with floating-point modulo
|
||||
|
||||
#ifdef MINIFY_START
|
||||
float fdepth = texelFetch(source_depth, clamp(ssP * 2 + ivec2(ssP.y & 1, ssP.x & 1), ivec2(0), from_size - ivec2(1)), source_mipmap).r;
|
||||
fdepth = fdepth * 2.0 - 1.0;
|
||||
fdepth = 2.0 * camera_z_near * camera_z_far / (camera_z_far + camera_z_near - fdepth * (camera_z_far - camera_z_near));
|
||||
fdepth /= camera_z_far;
|
||||
depth = uint(clamp(fdepth*65535,0.0,65535.0));
|
||||
|
||||
#else
|
||||
depth = texelFetch(source_depth, clamp(ssP * 2 + ivec2(ssP.y & 1, ssP.x & 1), ivec2(0), from_size - ivec2(1)), source_mipmap).r;
|
||||
#endif
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -377,6 +377,102 @@ bool Environment::is_ssr_rough() const {
|
|||
return ssr_roughness;
|
||||
}
|
||||
|
||||
void Environment::set_ssao_enabled(bool p_enable) {
|
||||
|
||||
ssao_enabled=p_enable;
|
||||
VS::get_singleton()->environment_set_ssao(environment,ssao_enabled,ssao_radius,ssao_intensity,ssao_radius2,ssao_intensity2,ssao_bias,ssao_direct_light_affect,ssao_color,ssao_blur);
|
||||
|
||||
}
|
||||
|
||||
bool Environment::is_ssao_enabled() const{
|
||||
|
||||
return ssao_enabled;
|
||||
}
|
||||
|
||||
void Environment::set_ssao_radius(float p_radius){
|
||||
|
||||
ssao_radius=p_radius;
|
||||
VS::get_singleton()->environment_set_ssao(environment,ssao_enabled,ssao_radius,ssao_intensity,ssao_radius2,ssao_intensity2,ssao_bias,ssao_direct_light_affect,ssao_color,ssao_blur);
|
||||
}
|
||||
float Environment::get_ssao_radius() const{
|
||||
|
||||
return ssao_radius;
|
||||
}
|
||||
|
||||
|
||||
void Environment::set_ssao_intensity(float p_intensity){
|
||||
|
||||
ssao_intensity=p_intensity;
|
||||
VS::get_singleton()->environment_set_ssao(environment,ssao_enabled,ssao_radius,ssao_intensity,ssao_radius2,ssao_intensity2,ssao_bias,ssao_direct_light_affect,ssao_color,ssao_blur);
|
||||
}
|
||||
|
||||
float Environment::get_ssao_intensity() const{
|
||||
|
||||
return ssao_intensity;
|
||||
}
|
||||
|
||||
void Environment::set_ssao_radius2(float p_radius){
|
||||
|
||||
ssao_radius2=p_radius;
|
||||
VS::get_singleton()->environment_set_ssao(environment,ssao_enabled,ssao_radius,ssao_intensity,ssao_radius2,ssao_intensity2,ssao_bias,ssao_direct_light_affect,ssao_color,ssao_blur);
|
||||
}
|
||||
float Environment::get_ssao_radius2() const{
|
||||
|
||||
return ssao_radius2;
|
||||
}
|
||||
|
||||
|
||||
void Environment::set_ssao_intensity2(float p_intensity){
|
||||
|
||||
ssao_intensity2=p_intensity;
|
||||
VS::get_singleton()->environment_set_ssao(environment,ssao_enabled,ssao_radius,ssao_intensity,ssao_radius2,ssao_intensity2,ssao_bias,ssao_direct_light_affect,ssao_color,ssao_blur);
|
||||
}
|
||||
float Environment::get_ssao_intensity2() const{
|
||||
|
||||
return ssao_intensity2;
|
||||
}
|
||||
|
||||
void Environment::set_ssao_bias(float p_bias){
|
||||
|
||||
ssao_bias=p_bias;
|
||||
VS::get_singleton()->environment_set_ssao(environment,ssao_enabled,ssao_radius,ssao_intensity,ssao_radius2,ssao_intensity2,ssao_bias,ssao_direct_light_affect,ssao_color,ssao_blur);
|
||||
}
|
||||
float Environment::get_ssao_bias() const{
|
||||
|
||||
return ssao_bias;
|
||||
}
|
||||
|
||||
void Environment::set_ssao_direct_light_affect(float p_direct_light_affect){
|
||||
|
||||
ssao_direct_light_affect=p_direct_light_affect;
|
||||
VS::get_singleton()->environment_set_ssao(environment,ssao_enabled,ssao_radius,ssao_intensity,ssao_radius2,ssao_intensity2,ssao_bias,ssao_direct_light_affect,ssao_color,ssao_blur);
|
||||
}
|
||||
float Environment::get_ssao_direct_light_affect() const{
|
||||
|
||||
return ssao_direct_light_affect;
|
||||
}
|
||||
|
||||
|
||||
void Environment::set_ssao_color(const Color& p_color) {
|
||||
|
||||
ssao_color=p_color;
|
||||
VS::get_singleton()->environment_set_ssao(environment,ssao_enabled,ssao_radius,ssao_intensity,ssao_radius2,ssao_intensity2,ssao_bias,ssao_direct_light_affect,ssao_color,ssao_blur);
|
||||
}
|
||||
|
||||
Color Environment::get_ssao_color() const {
|
||||
|
||||
return ssao_color;
|
||||
}
|
||||
|
||||
void Environment::set_ssao_blur(bool p_enable) {
|
||||
|
||||
ssao_blur=p_enable;
|
||||
VS::get_singleton()->environment_set_ssao(environment,ssao_enabled,ssao_radius,ssao_intensity,ssao_radius2,ssao_intensity2,ssao_bias,ssao_direct_light_affect,ssao_color,ssao_blur);
|
||||
}
|
||||
bool Environment::is_ssao_blur_enabled() const {
|
||||
|
||||
return ssao_blur;
|
||||
}
|
||||
|
||||
void Environment::_bind_methods() {
|
||||
|
||||
|
@ -442,6 +538,43 @@ void Environment::_bind_methods() {
|
|||
ADD_PROPERTY(PropertyInfo(Variant::BOOL,"ss_reflections/accel_smooth"),_SCS("set_ssr_smooth"),_SCS("is_ssr_smooth") );
|
||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL,"ss_reflections/roughness"),_SCS("set_ssr_rough"),_SCS("is_ssr_rough") );
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("set_ssao_enabled","enabled"),&Environment::set_ssao_enabled);
|
||||
ObjectTypeDB::bind_method(_MD("is_ssao_enabled"),&Environment::is_ssao_enabled);
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("set_ssao_radius","radius"),&Environment::set_ssao_radius);
|
||||
ObjectTypeDB::bind_method(_MD("get_ssao_radius"),&Environment::get_ssao_radius);
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("set_ssao_intensity","intensity"),&Environment::set_ssao_intensity);
|
||||
ObjectTypeDB::bind_method(_MD("get_ssao_intensity"),&Environment::get_ssao_intensity);
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("set_ssao_radius2","radius"),&Environment::set_ssao_radius2);
|
||||
ObjectTypeDB::bind_method(_MD("get_ssao_radius2"),&Environment::get_ssao_radius2);
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("set_ssao_intensity2","intensity"),&Environment::set_ssao_intensity2);
|
||||
ObjectTypeDB::bind_method(_MD("get_ssao_intensity2"),&Environment::get_ssao_intensity2);
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("set_ssao_bias","bias"),&Environment::set_ssao_bias);
|
||||
ObjectTypeDB::bind_method(_MD("get_ssao_bias"),&Environment::get_ssao_bias);
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("set_ssao_direct_light_affect","amount"),&Environment::set_ssao_direct_light_affect);
|
||||
ObjectTypeDB::bind_method(_MD("get_ssao_direct_light_affect"),&Environment::get_ssao_direct_light_affect);
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("set_ssao_color","color"),&Environment::set_ssao_color);
|
||||
ObjectTypeDB::bind_method(_MD("get_ssao_color"),&Environment::get_ssao_color);
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("set_ssao_blur","enabled"),&Environment::set_ssao_blur);
|
||||
ObjectTypeDB::bind_method(_MD("is_ssao_blur_enabled"),&Environment::is_ssao_blur_enabled);
|
||||
|
||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL,"ambient_occlusion/enable"),_SCS("set_ssao_enabled"),_SCS("is_ssao_enabled") );
|
||||
ADD_PROPERTY(PropertyInfo(Variant::REAL,"ambient_occlusion/radius",PROPERTY_HINT_RANGE,"0.1,16,0.1"),_SCS("set_ssao_radius"),_SCS("get_ssao_radius") );
|
||||
ADD_PROPERTY(PropertyInfo(Variant::REAL,"ambient_occlusion/intensity",PROPERTY_HINT_RANGE,"0.0,9,0.1"),_SCS("set_ssao_intensity"),_SCS("get_ssao_intensity") );
|
||||
ADD_PROPERTY(PropertyInfo(Variant::REAL,"ambient_occlusion/radius2",PROPERTY_HINT_RANGE,"0.0,16,0.1"),_SCS("set_ssao_radius2"),_SCS("get_ssao_radius2") );
|
||||
ADD_PROPERTY(PropertyInfo(Variant::REAL,"ambient_occlusion/intensity2",PROPERTY_HINT_RANGE,"0.0,9,0.1"),_SCS("set_ssao_intensity2"),_SCS("get_ssao_intensity2") );
|
||||
ADD_PROPERTY(PropertyInfo(Variant::REAL,"ambient_occlusion/bias",PROPERTY_HINT_RANGE,"0.001,8,0.001"),_SCS("set_ssao_bias"),_SCS("get_ssao_bias") );
|
||||
ADD_PROPERTY(PropertyInfo(Variant::REAL,"ambient_occlusion/light_affect",PROPERTY_HINT_RANGE,"0.00,1,0.01"),_SCS("set_ssao_direct_light_affect"),_SCS("get_ssao_direct_light_affect") );
|
||||
ADD_PROPERTY(PropertyInfo(Variant::COLOR,"ambient_occlusion/color",PROPERTY_HINT_COLOR_NO_ALPHA),_SCS("set_ssao_color"),_SCS("get_ssao_color") );
|
||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL,"ambient_occlusion/blur"),_SCS("set_ssao_blur"),_SCS("is_ssao_blur_enabled") );
|
||||
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("set_tonemapper","mode"),&Environment::set_tonemapper);
|
||||
ObjectTypeDB::bind_method(_MD("get_tonemapper"),&Environment::get_tonemapper);
|
||||
|
@ -561,6 +694,15 @@ Environment::Environment() {
|
|||
ssr_smooth=true;
|
||||
ssr_roughness=true;
|
||||
|
||||
ssao_enabled=false;
|
||||
ssao_radius=1;
|
||||
ssao_intensity=1;
|
||||
ssao_radius2=0;
|
||||
ssao_intensity2=1;
|
||||
ssao_bias=0.01;
|
||||
ssao_direct_light_affect=false;
|
||||
ssao_blur=true;
|
||||
|
||||
}
|
||||
|
||||
Environment::~Environment() {
|
||||
|
|
|
@ -102,6 +102,17 @@ private:
|
|||
bool ssr_smooth;
|
||||
bool ssr_roughness;
|
||||
|
||||
bool ssao_enabled;
|
||||
float ssao_radius;
|
||||
float ssao_intensity;
|
||||
float ssao_radius2;
|
||||
float ssao_intensity2;
|
||||
float ssao_bias;
|
||||
float ssao_direct_light_affect;
|
||||
Color ssao_color;
|
||||
bool ssao_blur;
|
||||
|
||||
|
||||
protected:
|
||||
|
||||
static void _bind_methods();
|
||||
|
@ -191,6 +202,34 @@ public:
|
|||
void set_ssr_rough(bool p_enable);
|
||||
bool is_ssr_rough() const;
|
||||
|
||||
void set_ssao_enabled(bool p_enable);
|
||||
bool is_ssao_enabled() const;
|
||||
|
||||
void set_ssao_radius(float p_radius);
|
||||
float get_ssao_radius() const;
|
||||
|
||||
void set_ssao_intensity(float p_intensity);
|
||||
float get_ssao_intensity() const;
|
||||
|
||||
void set_ssao_radius2(float p_radius);
|
||||
float get_ssao_radius2() const;
|
||||
|
||||
void set_ssao_intensity2(float p_intensity);
|
||||
float get_ssao_intensity2() const;
|
||||
|
||||
void set_ssao_bias(float p_bias);
|
||||
float get_ssao_bias() const;
|
||||
|
||||
void set_ssao_direct_light_affect(float p_direct_light_affect);
|
||||
float get_ssao_direct_light_affect() const;
|
||||
|
||||
void set_ssao_color(const Color& p_color);
|
||||
Color get_ssao_color() const;
|
||||
|
||||
void set_ssao_blur(bool p_enable);
|
||||
bool is_ssao_blur_enabled() const;
|
||||
|
||||
|
||||
|
||||
virtual RID get_rid() const;
|
||||
|
||||
|
|
|
@ -65,6 +65,7 @@ public:
|
|||
virtual void environment_set_fog(RID p_env,bool p_enable,float p_begin,float p_end,RID p_gradient_texture)=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;
|
||||
virtual void environment_set_ssao(RID p_env,bool p_enable, float p_radius, float p_intensity, float p_radius2, float p_intensity2, float p_bias, float p_light_affect,const Color &p_color,bool p_blur)=0;
|
||||
|
||||
virtual void environment_set_tonemap(RID p_env,bool p_enable,float p_exposure,float p_white,float p_min_luminance,float p_max_luminance,float p_auto_exp_speed,float p_auto_exp_scale,VS::EnvironmentToneMapper p_tone_mapper)=0;
|
||||
virtual void environment_set_adjustment(RID p_env,bool p_enable,float p_brightness,float p_contrast,float p_saturation,RID p_ramp)=0;
|
||||
|
|
|
@ -876,6 +876,8 @@ public:
|
|||
BIND2(environment_set_canvas_max_layer,RID,int )
|
||||
BIND4(environment_set_ambient_light,RID,const Color& ,float,float )
|
||||
BIND8(environment_set_ssr,RID,bool,int,float,float,float,bool,bool )
|
||||
BIND10(environment_set_ssao,RID ,bool , float , float , float,float,float , float ,const Color &,bool )
|
||||
|
||||
|
||||
BIND7(environment_set_glow,RID,bool ,int ,float ,float ,float ,EnvironmentGlowBlendMode )
|
||||
BIND5(environment_set_fog,RID,bool ,float ,float ,RID )
|
||||
|
|
|
@ -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;
|
||||
virtual void environment_set_ssao(RID p_env,bool p_enable, float p_radius, float p_intensity, float p_radius2, float p_intensity2, float p_bias, float p_light_affect,const Color &p_color,bool p_blur)=0;
|
||||
|
||||
/* SCENARIO API */
|
||||
|
||||
|
|
Loading…
Reference in New Issue