Screen space reflection effect

This commit is contained in:
Juan Linietsky 2016-11-29 19:55:12 -03:00
parent 3f40701002
commit a47c78aed1
21 changed files with 1285 additions and 82 deletions

View File

@ -71,6 +71,11 @@ uniform sampler2D source;
#endif
varying vec2 uv2_interp;
#ifdef USE_DEPTH
uniform highp sampler2D source_depth; //texunit:1
#endif
#ifdef USE_GLOW
uniform sampler2D glow_source;
@ -547,5 +552,10 @@ void main() {
gl_FragColor = color;
#ifdef USE_DEPTH
gl_FragDepth = texture(source_depth,uv_interp).r;
#endif
}

View File

@ -1349,7 +1349,7 @@ void RasterizerCanvasGLES3::reset_canvas() {
if (storage->frame.current_rt) {
glBindFramebuffer(GL_FRAMEBUFFER, storage->frame.current_rt->front.fbo);
glBindFramebuffer(GL_FRAMEBUFFER, storage->frame.current_rt->fbo);
glColorMask(1,1,1,1); //don't touch alpha
}

View File

@ -178,7 +178,7 @@ void RasterizerGLES3::set_current_render_target(RID p_render_target){
if (!p_render_target.is_valid() && storage->frame.current_rt && storage->frame.clear_request) {
//handle pending clear request, if the framebuffer was not cleared
glBindFramebuffer(GL_FRAMEBUFFER,storage->frame.current_rt->front.fbo);
glBindFramebuffer(GL_FRAMEBUFFER,storage->frame.current_rt->fbo);
print_line("unbind clear of: "+storage->frame.clear_request_color);
glClearColor(
storage->frame.clear_request_color.r,
@ -213,7 +213,7 @@ void RasterizerGLES3::restore_render_target() {
ERR_FAIL_COND(storage->frame.current_rt==NULL);
RasterizerStorageGLES3::RenderTarget * rt = storage->frame.current_rt;
glBindFramebuffer(GL_FRAMEBUFFER,rt->front.fbo);
glBindFramebuffer(GL_FRAMEBUFFER,rt->fbo);
glViewport(0,0,rt->width,rt->height);
}
@ -238,7 +238,7 @@ void RasterizerGLES3::blit_render_target_to_screen(RID p_render_target,const Rec
glDisable(GL_BLEND);
glBindFramebuffer(GL_FRAMEBUFFER,storage->config.system_fbo);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D,rt->front.color);
glBindTexture(GL_TEXTURE_2D,rt->color);
canvas->draw_generic_textured_rect(p_screen_rect,Rect2(0,0,1,-1));
glBindTexture(GL_TEXTURE_2D,0);
canvas->canvas_end();

View File

@ -857,6 +857,21 @@ void RasterizerSceneGLES3::environment_set_fog(RID p_env,bool p_enable,float p_b
}
void RasterizerSceneGLES3::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) {
Environment *env=environment_owner.getornull(p_env);
ERR_FAIL_COND(!env);
env->ssr_enabled=p_enable;
env->ssr_max_steps=p_max_steps;
env->ssr_accel=p_accel;
env->ssr_fade=p_fade;
env->ssr_depth_tolerance=p_depth_tolerance;
env->ssr_smooth=p_smooth;
env->ssr_roughness=p_roughness;
}
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){
}
@ -2538,7 +2553,7 @@ void RasterizerSceneGLES3::_copy_screen() {
void RasterizerSceneGLES3::_copy_to_front_buffer(Environment *env) {
//copy to front buffer
glBindFramebuffer(GL_FRAMEBUFFER,storage->frame.current_rt->front.fbo);
glBindFramebuffer(GL_FRAMEBUFFER,storage->frame.current_rt->fbo);
glDepthMask(GL_FALSE);
glDisable(GL_DEPTH_TEST);
@ -2575,7 +2590,7 @@ void RasterizerSceneGLES3::_copy_to_front_buffer(Environment *env) {
void RasterizerSceneGLES3::_copy_texture_to_front_buffer(GLuint p_texture) {
//copy to front buffer
glBindFramebuffer(GL_FRAMEBUFFER,storage->frame.current_rt->front.fbo);
glBindFramebuffer(GL_FRAMEBUFFER,storage->frame.current_rt->fbo);
glDepthMask(GL_FALSE);
glDisable(GL_DEPTH_TEST);
@ -2660,6 +2675,127 @@ void RasterizerSceneGLES3::_fill_render_list(InstanceBase** p_cull_result,int p_
}
void RasterizerSceneGLES3::_render_mrts(Environment *env,const CameraMatrix &p_cam_projection) {
glDepthMask(GL_FALSE);
glDisable(GL_DEPTH_TEST);
glDisable(GL_CULL_FACE);
glDisable(GL_BLEND);
if (env->ssr_enabled) {
//blur diffuse into effect mipmaps using separatable convolution
//storage->shaders.copy.set_conditional(CopyShaderGLES3::GAUSSIAN_HORIZONTAL,true);
for(int i=0;i<storage->frame.current_rt->effects.mip_maps[1].sizes.size();i++) {
int vp_w = storage->frame.current_rt->effects.mip_maps[1].sizes[i].width;
int vp_h = storage->frame.current_rt->effects.mip_maps[1].sizes[i].height;
glViewport(0,0,vp_w,vp_h);
//horizontal pass
state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::GAUSSIAN_HORIZONTAL,true);
state.effect_blur_shader.bind();
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
}
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);
//vertical pass
state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::GAUSSIAN_VERTICAL,true);
state.effect_blur_shader.bind();
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);
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[i+1].fbo); //next level, since mipmaps[0] starts one level bigger
_copy_screen();
state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::GAUSSIAN_VERTICAL,false);
}
//perform SSR
state.ssr_shader.set_conditional(ScreenSpaceReflectionShaderGLES3::SMOOTH_ACCEL,env->ssr_accel>0 && env->ssr_smooth);
state.ssr_shader.set_conditional(ScreenSpaceReflectionShaderGLES3::REFLECT_ROUGHNESS,env->ssr_accel>0 && env->ssr_roughness);
state.ssr_shader.bind();
int ssr_w = storage->frame.current_rt->effects.mip_maps[1].sizes[0].width;
int ssr_h = storage->frame.current_rt->effects.mip_maps[1].sizes[0].height;
state.ssr_shader.set_uniform(ScreenSpaceReflectionShaderGLES3::PIXEL_SIZE,Vector2(1.0/(ssr_w*0.5),1.0/(ssr_h*0.5)));
state.ssr_shader.set_uniform(ScreenSpaceReflectionShaderGLES3::CAMERA_Z_NEAR,p_cam_projection.get_z_near());
state.ssr_shader.set_uniform(ScreenSpaceReflectionShaderGLES3::CAMERA_Z_FAR,p_cam_projection.get_z_far());
state.ssr_shader.set_uniform(ScreenSpaceReflectionShaderGLES3::PROJECTION,p_cam_projection);
state.ssr_shader.set_uniform(ScreenSpaceReflectionShaderGLES3::INVERSE_PROJECTION,p_cam_projection.inverse());
state.ssr_shader.set_uniform(ScreenSpaceReflectionShaderGLES3::VIEWPORT_SIZE,Size2(ssr_w,ssr_h));
//state.ssr_shader.set_uniform(ScreenSpaceReflectionShaderGLES3::FRAME_INDEX,int(render_pass));
state.ssr_shader.set_uniform(ScreenSpaceReflectionShaderGLES3::FILTER_MIPMAP_LEVELS,float(storage->frame.current_rt->effects.mip_maps[0].sizes.size()));
state.ssr_shader.set_uniform(ScreenSpaceReflectionShaderGLES3::NUM_STEPS,env->ssr_max_steps);
state.ssr_shader.set_uniform(ScreenSpaceReflectionShaderGLES3::ACCELERATION,env->ssr_accel);
state.ssr_shader.set_uniform(ScreenSpaceReflectionShaderGLES3::DEPTH_TOLERANCE,env->ssr_depth_tolerance);
state.ssr_shader.set_uniform(ScreenSpaceReflectionShaderGLES3::DISTANCE_FADE,env->ssr_fade);
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);
glActiveTexture(GL_TEXTURE2);
glBindTexture(GL_TEXTURE_2D,storage->frame.current_rt->depth);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_NONE);
glActiveTexture(GL_TEXTURE3);
glBindTexture(GL_TEXTURE_2D,storage->frame.current_rt->effects.mip_maps[0].color);
glBindFramebuffer(GL_FRAMEBUFFER,storage->frame.current_rt->effects.mip_maps[1].sizes[0].fbo);
glViewport(0,0,ssr_w,ssr_h);
_copy_screen();
glViewport(0,0,storage->frame.current_rt->width,storage->frame.current_rt->height);
}
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);
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);
_copy_screen();
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));
glBindFramebuffer(GL_FRAMEBUFFER,storage->frame.current_rt->buffers.alpha_fbo);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D,storage->frame.current_rt->effects.mip_maps[0].color);
_copy_screen();
state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::SIMPLE_COPY,false);
}
void RasterizerSceneGLES3::render_scene(const Transform& p_cam_transform,const CameraMatrix& p_cam_projection,bool p_cam_ortogonal,InstanceBase** p_cull_result,int p_cull_count,RID* p_light_cull_result,int p_light_cull_count,RID* p_reflection_probe_cull_result,int p_reflection_probe_cull_count,RID p_environment,RID p_shadow_atlas,RID p_reflection_atlas,RID p_reflection_probe,int p_reflection_probe_pass){
//first of all, make a new render pass
@ -2700,7 +2836,7 @@ void RasterizerSceneGLES3::render_scene(const Transform& p_cam_transform,const C
render_list.clear();
bool use_mrt=false;
bool use_mrt=true;
_fill_render_list(p_cull_result,p_cull_count,false);
@ -2712,10 +2848,11 @@ void RasterizerSceneGLES3::render_scene(const Transform& p_cam_transform,const C
glEnable(GL_DEPTH_TEST);
glDisable(GL_SCISSOR_TEST);
//rendering to a probe cubemap side
ReflectionProbeInstance *probe = reflection_probe_instance_owner.getornull(p_reflection_probe);
GLuint current_fbo;
if (probe) {
ReflectionAtlas *ref_atlas = reflection_atlas_owner.getptr(probe->atlas);
@ -2739,6 +2876,7 @@ void RasterizerSceneGLES3::render_scene(const Transform& p_cam_transform,const C
glViewport(0,0,reflection_cubemaps[cubemap_index].size,reflection_cubemaps[cubemap_index].size);
glBindFramebuffer(GL_FRAMEBUFFER,current_fbo);
} else {
glViewport(0,0,storage->frame.current_rt->width,storage->frame.current_rt->height);
@ -2750,6 +2888,13 @@ void RasterizerSceneGLES3::render_scene(const Transform& p_cam_transform,const C
glBindFramebuffer(GL_FRAMEBUFFER,storage->frame.current_rt->buffers.fbo);
state.scene_shader.set_conditional(SceneShaderGLES3::USE_MULTIPLE_RENDER_TARGETS,true);
Vector<GLenum> draw_buffers;
draw_buffers.push_back(GL_COLOR_ATTACHMENT0);
draw_buffers.push_back(GL_COLOR_ATTACHMENT1);
draw_buffers.push_back(GL_COLOR_ATTACHMENT2);
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
@ -2760,6 +2905,7 @@ void RasterizerSceneGLES3::render_scene(const Transform& p_cam_transform,const C
glBindFramebuffer(GL_FRAMEBUFFER,storage->frame.current_rt->buffers.alpha_fbo);
state.scene_shader.set_conditional(SceneShaderGLES3::USE_MULTIPLE_RENDER_TARGETS,false);
}
}
@ -2841,6 +2987,11 @@ void RasterizerSceneGLES3::render_scene(const Transform& p_cam_transform,const C
state.scene_shader.set_conditional(SceneShaderGLES3::USE_MULTIPLE_RENDER_TARGETS,false);
if (use_mrt) {
GLenum gldb = GL_COLOR_ATTACHMENT0;
glDrawBuffers(1,&gldb);
}
if (env && env->bg_mode==VS::ENV_BG_SKYBOX) {
if (use_mrt) {
@ -2859,16 +3010,17 @@ void RasterizerSceneGLES3::render_scene(const Transform& p_cam_transform,const C
// state.scene_shader.set_conditional( SceneShaderGLES3::USE_FOG,false);
if (use_mrt) {
_render_mrts(env,p_cam_projection);
}
glPolygonMode(GL_FRONT_AND_BACK,GL_FILL);
glEnable(GL_BLEND);
glDepthMask(GL_TRUE);
glEnable(GL_DEPTH_TEST);
glDisable(GL_SCISSOR_TEST);
if (use_mrt) {
glBindFramebuffer(GL_FRAMEBUFFER,storage->frame.current_rt->buffers.alpha_fbo);
}
render_list.sort_by_depth(true);
if (state.directional_light_count==0) {
@ -3812,6 +3964,10 @@ void RasterizerSceneGLES3::initialize() {
glEnable(GL_PROGRAM_POINT_SIZE);
#endif
state.resolve_shader.init();
state.ssr_shader.init();
state.effect_blur_shader.init();
}
void RasterizerSceneGLES3::iteration() {

View File

@ -4,6 +4,9 @@
#include "rasterizer_storage_gles3.h"
#include "drivers/gles3/shaders/scene.glsl.h"
#include "drivers/gles3/shaders/cube_to_dp.glsl.h"
#include "drivers/gles3/shaders/resolve.glsl.h"
#include "drivers/gles3/shaders/screen_space_reflection.glsl.h"
#include "drivers/gles3/shaders/effect_blur.glsl.h"
class RasterizerSceneGLES3 : public RasterizerScene {
public:
@ -45,6 +48,9 @@ public:
SceneShaderGLES3 scene_shader;
CubeToDpShaderGLES3 cube_to_dp_shader;
ResolveShaderGLES3 resolve_shader;
ScreenSpaceReflectionShaderGLES3 ssr_shader;
EffectBlurShaderGLES3 effect_blur_shader;
struct SceneDataUBO {
@ -289,6 +295,15 @@ public:
int canvas_max_layer;
bool ssr_enabled;
int ssr_max_steps;
float ssr_accel;
float ssr_fade;
float ssr_depth_tolerance;
bool ssr_smooth;
bool ssr_roughness;
Environment() {
bg_mode=VS::ENV_BG_CLEAR_COLOR;
@ -298,6 +313,15 @@ public:
ambient_energy=1.0;
ambient_skybox_contribution=0.0;
canvas_max_layer=0;
ssr_enabled=false;
ssr_max_steps=64;
ssr_accel=0.04;
ssr_fade=2.0;
ssr_depth_tolerance=0.2;
ssr_smooth=true;
ssr_roughness=true;
}
};
@ -316,6 +340,8 @@ public:
virtual void environment_set_glow(RID p_env,bool p_enable,int p_radius,float p_intensity,float p_strength,float p_bloom_treshold,VS::EnvironmentGlowBlendMode p_blend_mode);
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_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);
@ -551,6 +577,7 @@ public:
void _fill_render_list(InstanceBase** p_cull_result,int p_cull_count,bool p_shadow);
void _render_mrts(Environment *env, const CameraMatrix &p_cam_projection);
virtual void render_scene(const Transform& p_cam_transform,const CameraMatrix& p_cam_projection,bool p_cam_ortogonal,InstanceBase** p_cull_result,int p_cull_count,RID* p_light_cull_result,int p_light_cull_count,RID* p_reflection_probe_cull_result,int p_reflection_probe_cull_count,RID p_environment,RID p_shadow_atlas,RID p_reflection_atlas,RID p_reflection_probe,int p_reflection_probe_pass);
virtual void render_shadow(RID p_light,RID p_shadow_atlas,int p_pass,InstanceBase** p_cull_result,int p_cull_count);
virtual bool free(RID p_rid);

View File

@ -4760,16 +4760,10 @@ void RasterizerStorageGLES3::instance_remove_dependency(RID p_base,RasterizerSce
void RasterizerStorageGLES3::_render_target_clear(RenderTarget *rt) {
if (rt->front.fbo) {
glDeleteFramebuffers(1,&rt->front.fbo);
glDeleteTextures(1,&rt->front.color);
rt->front.fbo=0;
}
if (rt->back.fbo) {
glDeleteFramebuffers(1,&rt->back.fbo);
glDeleteTextures(1,&rt->back.color);
rt->back.fbo=0;
if (rt->fbo) {
glDeleteFramebuffers(1,&rt->fbo);
glDeleteTextures(1,&rt->color);
rt->fbo=0;
}
if (rt->buffers.fbo) {
@ -4783,7 +4777,7 @@ void RasterizerStorageGLES3::_render_target_clear(RenderTarget *rt) {
}
if (rt->depth) {
glDeleteRenderbuffers(1,&rt->depth);
glDeleteTextures(1,&rt->depth);
rt->depth=0;
}
@ -4793,6 +4787,22 @@ void RasterizerStorageGLES3::_render_target_clear(RenderTarget *rt) {
tex->width=0;
tex->height=0;
for(int i=0;i<2;i++) {
for(int j=0;j<rt->effects.mip_maps[i].sizes.size();j++) {
glDeleteFramebuffers(1,&rt->effects.mip_maps[i].sizes[j].fbo);
}
glDeleteTextures(1,&rt->effects.mip_maps[i].color);
rt->effects.mip_maps[i].sizes.clear();
rt->effects.mip_maps[i].levels=0;
}
/*
if (rt->effects.screen_space_depth) {
glDeleteTextures(1,&rt->effects.screen_space_depth);
rt->effects.screen_space_depth=0;
}
*/
}
void RasterizerStorageGLES3::_render_target_allocate(RenderTarget *rt){
@ -4833,21 +4843,24 @@ void RasterizerStorageGLES3::_render_target_allocate(RenderTarget *rt){
glActiveTexture(GL_TEXTURE0);
glGenFramebuffers(1, &rt->front.fbo);
glBindFramebuffer(GL_FRAMEBUFFER, rt->front.fbo);
glGenFramebuffers(1, &rt->fbo);
glBindFramebuffer(GL_FRAMEBUFFER, rt->fbo);
glGenRenderbuffers(1, &rt->depth);
glBindRenderbuffer(GL_RENDERBUFFER, rt->depth );
glGenTextures(1, &rt->depth);
glBindTexture(GL_TEXTURE_2D, rt->depth);
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, rt->width, rt->height, 0,
GL_DEPTH_COMPONENT, 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_DEPTH_ATTACHMENT,
GL_TEXTURE_2D, rt->depth, 0);
glRenderbufferStorage(GL_RENDERBUFFER,GL_DEPTH24_STENCIL8, rt->width, rt->height);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rt->depth);
glBindRenderbuffer(GL_RENDERBUFFER, 0 );
glGenTextures(1, &rt->front.color);
glBindTexture(GL_TEXTURE_2D, rt->front.color);
glGenTextures(1, &rt->color);
glBindTexture(GL_TEXTURE_2D, rt->color);
glTexImage2D(GL_TEXTURE_2D, 0, color_internal_format, rt->width, rt->height, 0, color_format, color_type, NULL);
@ -4855,7 +4868,7 @@ 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);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, rt->front.color, 0);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, rt->color, 0);
GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
glBindFramebuffer(GL_FRAMEBUFFER, config.system_fbo);
@ -4867,7 +4880,7 @@ void RasterizerStorageGLES3::_render_target_allocate(RenderTarget *rt){
tex->gl_format_cache=color_format;
tex->gl_type_cache=color_type;
tex->gl_internal_format_cache=color_internal_format;
tex->tex_id=rt->front.color;
tex->tex_id=rt->color;
tex->width=rt->width;
tex->alloc_width=rt->width;
tex->height=rt->height;
@ -4881,32 +4894,6 @@ void RasterizerStorageGLES3::_render_target_allocate(RenderTarget *rt){
/* BACK FBO */
if (!rt->flags[RENDER_TARGET_NO_SAMPLING]) {
glGenFramebuffers(1, &rt->back.fbo);
glBindFramebuffer(GL_FRAMEBUFFER, rt->back.fbo);
glBindRenderbuffer(GL_RENDERBUFFER, rt->depth );
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rt->depth);
glGenTextures(1, &rt->back.color);
glBindTexture(GL_TEXTURE_2D, rt->back.color);
glTexImage2D(GL_TEXTURE_2D, 0, color_internal_format, rt->width, rt->height, 0, color_format, color_type, 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->back.color, 0);
GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
glBindFramebuffer(GL_FRAMEBUFFER, config.system_fbo);
if (status != GL_FRAMEBUFFER_COMPLETE) {
_render_target_clear(rt);
ERR_FAIL_COND( status != GL_FRAMEBUFFER_COMPLETE );
}
}
if (config.render_arch==RENDER_ARCH_DESKTOP && !rt->flags[RENDER_TARGET_NO_3D]) {
@ -4915,11 +4902,12 @@ void RasterizerStorageGLES3::_render_target_allocate(RenderTarget *rt){
glGenFramebuffers(1, &rt->buffers.fbo);
glBindFramebuffer(GL_FRAMEBUFFER, rt->buffers.fbo);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rt->depth);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
GL_TEXTURE_2D, rt->depth, 0);
glGenTextures(1, &rt->buffers.diffuse);
glBindTexture(GL_TEXTURE_2D, rt->buffers.diffuse);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, rt->width, rt->height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, rt->width, rt->height, 0, GL_RGBA, GL_HALF_FLOAT, 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);
@ -4958,7 +4946,9 @@ void RasterizerStorageGLES3::_render_target_allocate(RenderTarget *rt){
glGenFramebuffers(1, &rt->buffers.alpha_fbo);
glBindFramebuffer(GL_FRAMEBUFFER, rt->buffers.alpha_fbo);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rt->depth);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
GL_TEXTURE_2D, rt->depth, 0);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, rt->buffers.diffuse, 0);
status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
@ -4969,9 +4959,80 @@ void RasterizerStorageGLES3::_render_target_allocate(RenderTarget *rt){
ERR_FAIL_COND( status != GL_FRAMEBUFFER_COMPLETE );
}
for(int i=0;i<2;i++) {
ERR_FAIL_COND( rt->effects.mip_maps[i].sizes.size() );
int w=rt->width;
int h=rt->height;
if (i>0) {
w>>=1;
h>>=1;
}
glGenTextures(1, &rt->effects.mip_maps[i].color);
glBindTexture(GL_TEXTURE_2D, rt->effects.mip_maps[i].color);
int level=0;
while(true) {
RenderTarget::Effects::MipMaps::Size mm;
glTexImage2D(GL_TEXTURE_2D, level, GL_RGBA16F, w, h, 0, GL_RGBA, GL_HALF_FLOAT, NULL);
mm.width=w;
mm.height=h;
rt->effects.mip_maps[i].sizes.push_back(mm);
w>>=1;
h>>=1;
if (w<32 || h<32)
break; //going less than 32 is pointless
level++;
}
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, level);
for(int j=0;j<rt->effects.mip_maps[i].sizes.size();j++) {
RenderTarget::Effects::MipMaps::Size &mm=rt->effects.mip_maps[i].sizes[j];
glGenFramebuffers(1, &mm.fbo);
glBindFramebuffer(GL_FRAMEBUFFER, mm.fbo);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,rt->effects.mip_maps[i].color ,j);
status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
if (status != GL_FRAMEBUFFER_COMPLETE) {
_render_target_clear(rt);
ERR_FAIL_COND( status != GL_FRAMEBUFFER_COMPLETE );
}
float zero[4]={1,0,1,0};
glClearBufferfv(GL_COLOR,0,zero);
}
glBindFramebuffer(GL_FRAMEBUFFER, config.system_fbo);
rt->effects.mip_maps[i].levels=level;
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
//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);
}
}
}

View File

@ -877,11 +877,8 @@ public:
struct RenderTarget : public RID_Data {
struct Color {
GLuint fbo;
GLuint color;
} front,back;
GLuint fbo;
GLuint color;
GLuint depth;
struct Buffers {
@ -890,8 +887,35 @@ public:
GLuint specular;
GLuint diffuse;
GLuint normal_sr;
GLuint temporal;
} buffers;
struct Effects {
struct MipMaps {
struct Size {
GLuint fbo;
int width;
int height;
};
Vector<Size> sizes;
GLuint color;
int levels;
MipMaps() { color=0; levels=0;}
};
MipMaps mip_maps[2]; //first mipmap chain starts from full-screen
//GLuint depth2; //depth for the second mipmap chain, in case of desiring upsampling
Effects() {
}
} effects;
int width,height;
bool flags[RENDER_TARGET_FLAG_MAX];
@ -905,8 +929,7 @@ public:
width=0;
height=0;
depth=0;
front.fbo=0;
back.fbo=0;
fbo=0;
buffers.fbo=0;
buffers.alpha_fbo=0;
used_in_frame=false;

View File

@ -393,8 +393,8 @@ ShaderGLES3::Version* ShaderGLES3::get_current_version() {
strings.resize(strings_base_size);
//fragment precision is medium
strings.push_back("precision mediump float;\n");
strings.push_back("precision mediump int;\n");
strings.push_back("precision highp float;\n");
strings.push_back("precision highp int;\n");
#if 0
if (cc) {

View File

@ -2,10 +2,13 @@ Import('env')
if env['BUILDERS'].has_key('GLES3_GLSL'):
env.GLES3_GLSL('copy.glsl');
env.GLES3_GLSL('resolve.glsl');
env.GLES3_GLSL('canvas.glsl');
env.GLES3_GLSL('canvas_shadow.glsl');
env.GLES3_GLSL('scene.glsl');
env.GLES3_GLSL('cubemap_filter.glsl');
env.GLES3_GLSL('cube_to_dp.glsl');
env.GLES3_GLSL('blend_shape.glsl');
env.GLES3_GLSL('screen_space_reflection.glsl');
env.GLES3_GLSL('effect_blur.glsl');

View File

@ -50,6 +50,7 @@ float sRGB_gamma_correct(float c){
uniform float stuff;
uniform vec2 pixel_size;
in vec2 uv2_interp;
@ -81,6 +82,24 @@ void main() {
color.a=1.0;
#endif
#ifdef GAUSSIAN_HORIZONTAL
color*=0.38774;
color+=texture( source, uv_interp+vec2( 1.0, 0.0)*pixel_size )*0.24477;
color+=texture( source, uv_interp+vec2( 2.0, 0.0)*pixel_size )*0.06136;
color+=texture( source, uv_interp+vec2(-1.0, 0.0)*pixel_size )*0.24477;
color+=texture( source, uv_interp+vec2(-2.0, 0.0)*pixel_size )*0.06136;
#endif
#ifdef GAUSSIAN_VERTICAL
color*=0.38774;
color+=texture( source, uv_interp+vec2( 0.0, 1.0)*pixel_size )*0.24477;
color+=texture( source, uv_interp+vec2( 0.0, 2.0)*pixel_size )*0.06136;
color+=texture( source, uv_interp+vec2( 0.0,-1.0)*pixel_size )*0.24477;
color+=texture( source, uv_interp+vec2( 0.0,-2.0)*pixel_size )*0.06136;
#endif
frag_color = color;
}

View File

@ -0,0 +1,45 @@
[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]
in vec2 uv_interp;
uniform sampler2D source_diffuse; //texunit:0
uniform sampler2D source_specular; //texunit:1
uniform sampler2D source_ssr_ssao; //texunit:2
uniform float stuff;
in vec2 uv2_interp;
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);
specular.rgb = mix(specular.rgb,ssr.rgb*specular.a,ssr.a);
#endif
frag_color = vec4(diffuse.rgb,1.0)+vec4(specular.rgb,1.0);
}

View File

@ -0,0 +1,166 @@
/* WARNING, THIS FILE WAS GENERATED, DO NOT EDIT */
#ifndef RESOLVE_GLSL_HGLES3_120
#define RESOLVE_GLSL_HGLES3_120
#include "drivers/gles3/shader_gles3.h"
class ResolveShaderGLES3 : public ShaderGLES3 {
virtual String get_shader_name() const { return "ResolveShaderGLES3"; }
public:
enum Conditionals {
USE_SSR,
};
enum Uniforms {
STUFF,
};
_FORCE_INLINE_ int get_uniform(Uniforms p_uniform) const { return _get_uniform(p_uniform); }
_FORCE_INLINE_ void set_conditional(Conditionals p_conditional,bool p_enable) { _set_conditional(p_conditional,p_enable); }
#define _FU if (get_uniform(p_uniform)<0) return; ERR_FAIL_COND( get_active()!=this );
_FORCE_INLINE_ void set_uniform(Uniforms p_uniform, float p_value) { _FU glUniform1f(get_uniform(p_uniform),p_value); }
_FORCE_INLINE_ void set_uniform(Uniforms p_uniform, double p_value) { _FU glUniform1f(get_uniform(p_uniform),p_value); }
_FORCE_INLINE_ void set_uniform(Uniforms p_uniform, uint8_t p_value) { _FU glUniform1i(get_uniform(p_uniform),p_value); }
_FORCE_INLINE_ void set_uniform(Uniforms p_uniform, int8_t p_value) { _FU glUniform1i(get_uniform(p_uniform),p_value); }
_FORCE_INLINE_ void set_uniform(Uniforms p_uniform, uint16_t p_value) { _FU glUniform1i(get_uniform(p_uniform),p_value); }
_FORCE_INLINE_ void set_uniform(Uniforms p_uniform, int16_t p_value) { _FU glUniform1i(get_uniform(p_uniform),p_value); }
_FORCE_INLINE_ void set_uniform(Uniforms p_uniform, uint32_t p_value) { _FU glUniform1i(get_uniform(p_uniform),p_value); }
_FORCE_INLINE_ void set_uniform(Uniforms p_uniform, int32_t p_value) { _FU glUniform1i(get_uniform(p_uniform),p_value); }
_FORCE_INLINE_ void set_uniform(Uniforms p_uniform, const Color& p_color) { _FU GLfloat col[4]={p_color.r,p_color.g,p_color.b,p_color.a}; glUniform4fv(get_uniform(p_uniform),1,col); }
_FORCE_INLINE_ void set_uniform(Uniforms p_uniform, const Vector2& p_vec2) { _FU GLfloat vec2[2]={p_vec2.x,p_vec2.y}; glUniform2fv(get_uniform(p_uniform),1,vec2); }
_FORCE_INLINE_ void set_uniform(Uniforms p_uniform, const Vector3& p_vec3) { _FU GLfloat vec3[3]={p_vec3.x,p_vec3.y,p_vec3.z}; glUniform3fv(get_uniform(p_uniform),1,vec3); }
_FORCE_INLINE_ void set_uniform(Uniforms p_uniform, float p_a, float p_b) { _FU glUniform2f(get_uniform(p_uniform),p_a,p_b); }
_FORCE_INLINE_ void set_uniform(Uniforms p_uniform, float p_a, float p_b, float p_c) { _FU glUniform3f(get_uniform(p_uniform),p_a,p_b,p_c); }
_FORCE_INLINE_ void set_uniform(Uniforms p_uniform, float p_a, float p_b, float p_c, float p_d) { _FU glUniform4f(get_uniform(p_uniform),p_a,p_b,p_c,p_d); }
_FORCE_INLINE_ void set_uniform(Uniforms p_uniform, const Transform& p_transform) { _FU
const Transform &tr = p_transform;
GLfloat matrix[16]={ /* build a 16x16 matrix */
tr.basis.elements[0][0],
tr.basis.elements[1][0],
tr.basis.elements[2][0],
0,
tr.basis.elements[0][1],
tr.basis.elements[1][1],
tr.basis.elements[2][1],
0,
tr.basis.elements[0][2],
tr.basis.elements[1][2],
tr.basis.elements[2][2],
0,
tr.origin.x,
tr.origin.y,
tr.origin.z,
1
};
glUniformMatrix4fv(get_uniform(p_uniform),1,false,matrix);
}
_FORCE_INLINE_ void set_uniform(Uniforms p_uniform, const Matrix32& p_transform) { _FU
const Matrix32 &tr = p_transform;
GLfloat matrix[16]={ /* build a 16x16 matrix */
tr.elements[0][0],
tr.elements[0][1],
0,
0,
tr.elements[1][0],
tr.elements[1][1],
0,
0,
0,
0,
1,
0,
tr.elements[2][0],
tr.elements[2][1],
0,
1
};
glUniformMatrix4fv(get_uniform(p_uniform),1,false,matrix);
}
_FORCE_INLINE_ void set_uniform(Uniforms p_uniform, const CameraMatrix& p_matrix) { _FU
GLfloat matrix[16];
for (int i=0;i<4;i++) {
for (int j=0;j<4;j++) {
matrix[i*4+j]=p_matrix.matrix[i][j];
}
}
glUniformMatrix4fv(get_uniform(p_uniform),1,false,matrix);
};
#undef _FU
virtual void init() {
static const Enum *_enums=NULL;
static const EnumValue *_enum_values=NULL;
static const char* _conditional_strings[]={
"#define USE_SSR\n",
};
static const char* _uniform_strings[]={
"stuff",
};
static AttributePair *_attribute_pairs=NULL;
static const Feedback* _feedbacks=NULL;
static TexUnitPair _texunit_pairs[]={
{"source_diffuse",0},
{"source_specular",1},
{"source_ssr_ssao",2},
};
static UBOPair *_ubo_pairs=NULL;
static const char _vertex_code[]={
10,10,108,97,121,111,117,116,40,108,111,99,97,116,105,111,110,61,48,41,32,105,110,32,104,105,103,104,112,32,118,101,99,52,32,118,101,114,116,101,120,95,97,116,116,114,105,98,59,10,108,97,121,111,117,116,40,108,111,99,97,116,105,111,110,61,52,41,32,105,110,32,118,101,99,50,32,117,118,95,105,110,59,10,10,111,117,116,32,118,101,99,50,32,117,118,95,105,110,116,101,114,112,59,10,10,10,118,111,105,100,32,109,97,105,110,40,41,32,123,10,10,9,117,118,95,105,110,116,101,114,112,32,61,32,117,118,95,105,110,59,10,9,103,108,95,80,111,115,105,116,105,111,110,32,61,32,118,101,114,116,101,120,95,97,116,116,114,105,98,59,10,125,10,10, 0};
static const int _vertex_code_start=1;
static const char _fragment_code[]={
10,10,105,110,32,118,101,99,50,32,117,118,95,105,110,116,101,114,112,59,10,117,110,105,102,111,114,109,32,115,97,109,112,108,101,114,50,68,32,115,111,117,114,99,101,95,100,105,102,102,117,115,101,59,32,47,47,116,101,120,117,110,105,116,58,48,10,117,110,105,102,111,114,109,32,115,97,109,112,108,101,114,50,68,32,115,111,117,114,99,101,95,115,112,101,99,117,108,97,114,59,32,47,47,116,101,120,117,110,105,116,58,49,10,10,10,117,110,105,102,111,114,109,32,115,97,109,112,108,101,114,50,68,32,115,111,117,114,99,101,95,115,115,114,95,115,115,97,111,59,32,47,47,116,101,120,117,110,105,116,58,50,10,10,117,110,105,102,111,114,109,32,102,108,111,97,116,32,115,116,117,102,102,59,10,10,105,110,32,118,101,99,50,32,117,118,50,95,105,110,116,101,114,112,59,10,10,108,97,121,111,117,116,40,108,111,99,97,116,105,111,110,32,61,32,48,41,32,111,117,116,32,118,101,99,52,32,102,114,97,103,95,99,111,108,111,114,59,10,10,118,111,105,100,32,109,97,105,110,40,41,32,123,10,10,9,118,101,99,52,32,100,105,102,102,117,115,101,32,61,32,116,101,120,116,117,114,101,40,32,115,111,117,114,99,101,95,100,105,102,102,117,115,101,44,32,32,117,118,95,105,110,116,101,114,112,32,41,59,10,9,118,101,99,52,32,115,112,101,99,117,108,97,114,32,61,32,116,101,120,116,117,114,101,40,32,115,111,117,114,99,101,95,115,112,101,99,117,108,97,114,44,32,32,117,118,95,105,110,116,101,114,112,32,41,59,10,10,35,105,102,100,101,102,32,85,83,69,95,83,83,82,10,10,9,118,101,99,52,32,115,115,114,32,61,32,116,101,120,116,117,114,101,76,111,100,40,115,111,117,114,99,101,95,115,115,114,95,115,115,97,111,44,117,118,95,105,110,116,101,114,112,44,48,46,48,41,59,10,9,115,112,101,99,117,108,97,114,46,114,103,98,32,61,32,109,105,120,40,115,112,101,99,117,108,97,114,46,114,103,98,44,115,115,114,46,114,103,98,42,115,112,101,99,117,108,97,114,46,97,44,115,115,114,46,97,41,59,10,35,101,110,100,105,102,10,10,9,102,114,97,103,95,99,111,108,111,114,32,61,32,118,101,99,52,40,100,105,102,102,117,115,101,46,114,103,98,44,49,46,48,41,43,118,101,99,52,40,115,112,101,99,117,108,97,114,46,114,103,98,44,49,46,48,41,59,10,125,10,10, 0};
static const int _fragment_code_start=16;
setup(_conditional_strings,1,_uniform_strings,1,_attribute_pairs,0, _texunit_pairs,3,_ubo_pairs,0,_feedbacks,0,_vertex_code,_fragment_code,_vertex_code_start,_fragment_code_start);
};
};
#endif

View File

@ -1189,8 +1189,10 @@ LIGHT_SHADER_CODE
#endif //ENABLE_AO
diffuse_buffer=vec4(emission+diffuse_light+ambient_light,ambient_scale);
specular_buffer=vec4(specular_light,0.0);
normal_mr_buffer=vec4(normal.x,normal.y,max(specular.r,max(specular.g,specular.b)),roughness);
specular_buffer=vec4(specular_light,max(specular.r,max(specular.g,specular.b)));
normal_mr_buffer=vec4(normalize(normal)*0.5+0.5,roughness);
#else

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,350 @@
[vertex]
layout(location=0) in highp vec4 vertex_attrib;
layout(location=4) in vec2 uv_in;
out vec2 uv_interp;
out vec2 pos_interp;
void main() {
uv_interp = uv_in;
gl_Position = vertex_attrib;
pos_interp.xy=gl_Position.xy;
}
[fragment]
in vec2 uv_interp;
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;
uniform vec2 viewport_size;
uniform vec2 pixel_size;
uniform float filter_mipmap_levels;
uniform mat4 inverse_projection;
uniform mat4 projection;
uniform int num_steps;
uniform float depth_tolerance;
uniform float distance_fade;
uniform float acceleration;
layout(location = 0) out vec4 frag_color;
vec2 view_to_screen(vec3 view_pos,out float w) {
vec4 projected = projection * vec4(view_pos, 1.0);
projected.xyz /= projected.w;
projected.xy = projected.xy * 0.5 + 0.5;
w=projected.w;
return projected.xy;
}
#define M_PI 3.14159265359
void main() {
////
vec4 diffuse = texture( source_diffuse, uv_interp );
vec4 normal_roughness = texture( source_normal_roughness, uv_interp);
vec3 normal;
normal = normal_roughness.xyz*2.0-1.0;
float roughness = normal_roughness.w;
float depth_tex = texture(source_depth,uv_interp).r;
vec4 world_pos = inverse_projection * vec4( uv_interp*2.0-1.0, depth_tex*2.0-1.0, 1.0 );
vec3 vertex = world_pos.xyz/world_pos.w;
vec3 view_dir = normalize(vertex);
vec3 ray_dir = normalize(reflect(view_dir, normal));
if (dot(ray_dir,normal)<0.001) {
frag_color=vec4(0.0);
return;
}
//ray_dir = normalize(view_dir - normal * dot(normal,view_dir) * 2.0);
//ray_dir = normalize(vec3(1,1,-1));
////////////////
//make ray length and clip it against the near plane (don't want to trace beyond visible)
float ray_len = (vertex.z + ray_dir.z * camera_z_far) > -camera_z_near ? (-camera_z_near - vertex.z) / ray_dir.z : camera_z_far;
vec3 ray_end = vertex + ray_dir*ray_len;
float w_begin;
vec2 vp_line_begin = view_to_screen(vertex,w_begin);
float w_end;
vec2 vp_line_end = view_to_screen( ray_end, w_end);
vec2 vp_line_dir = vp_line_end-vp_line_begin;
//we need to interpolate w along the ray, to generate perspective correct reflections
w_begin = 1.0/w_begin;
w_end = 1.0/w_end;
float z_begin = vertex.z*w_begin;
float z_end = ray_end.z*w_end;
vec2 line_begin = vp_line_begin/pixel_size;
vec2 line_dir = vp_line_dir/pixel_size;
float z_dir = z_end - z_begin;
float w_dir = w_end - w_begin;
// clip the line to the viewport edges
float scale_max_x = min(1, 0.99 * (1.0 - vp_line_begin.x) / max(1e-5, vp_line_dir.x));
float scale_max_y = min(1, 0.99 * (1.0 - vp_line_begin.y) / max(1e-5, vp_line_dir.y));
float scale_min_x = min(1, 0.99 * vp_line_begin.x / max(1e-5, -vp_line_dir.x));
float scale_min_y = min(1, 0.99 * vp_line_begin.y / max(1e-5, -vp_line_dir.y));
float line_clip = min(scale_max_x, scale_max_y) * min(scale_min_x, scale_min_y);
line_dir *= line_clip;
z_dir *= line_clip;
w_dir *=line_clip;
//clip z and w advance to line advance
vec2 line_advance = normalize(line_dir); //down to pixel
float step_size = length(line_advance)/length(line_dir);
float z_advance = z_dir*step_size; // adapt z advance to line advance
float w_advance = w_dir*step_size; // adapt w advance to line advance
//make line advance faster if direction is closer to pixel edges (this avoids sampling the same pixel twice)
float advance_angle_adj = 1.0/max(abs(line_advance.x),abs(line_advance.y));
line_advance*=advance_angle_adj; // adapt z advance to line advance
z_advance*=advance_angle_adj;
w_advance*=advance_angle_adj;
vec2 pos = line_begin;
float z = z_begin;
float w = w_begin;
float z_from=z/w;
float z_to=z_from;
float depth;
vec2 prev_pos=pos;
bool found=false;
//if acceleration > 0, distance between pixels gets larger each step. This allows covering a larger area
float accel=1.0+acceleration;
float steps_taken=0;
for(float i=0;i<num_steps;i++) {
pos+=line_advance;
z+=z_advance;
w+=w_advance;
//convert to linear depth
depth = texture(source_depth, pos*pixel_size).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;
z_from = z_to;
z_to = z/w;
if (depth>z_to) {
//if depth was surpassed
if (depth<=max(z_to,z_from)+depth_tolerance) {
//check the depth tolerance
found=true;
}
break;
}
steps_taken+=1.0;
prev_pos=pos;
z_advance*=accel;
w_advance*=accel;
line_advance*=accel;
}
if (found) {
float margin_blend=1.0;
vec2 margin = vec2((viewport_size.x+viewport_size.y)*0.5*0.05); //make a uniform margin
if (any(bvec4(lessThan(pos,-margin),greaterThan(pos,viewport_size+margin)))) {
//clip outside screen + margin
frag_color=vec4(0.0);
return;
}
{
//blend fading out towards external margin
vec2 margin_grad = mix(pos-viewport_size,-pos,lessThan(pos,vec2(0.0)));
margin_blend = 1.0-smoothstep(0.0,margin.x,max(margin_grad.x,margin_grad.y));
//margin_blend=1.0;
}
vec2 final_pos;
float grad;
#ifdef SMOOTH_ACCEL
//if the distance between point and prev point is >1, then take some samples in the middle for smoothing out the image
vec2 blend_dir = pos - prev_pos;
float steps = min(8.0,length(blend_dir));
if (steps>2.0) {
vec2 blend_step = blend_dir/steps;
float blend_z = (z_to-z_from)/steps;
vec2 new_pos;
float subgrad=0.0;
for(float i=0.0;i<steps;i++) {
new_pos = (prev_pos+blend_step*i);
float z = z_from+blend_z*i;
depth = texture(source_depth, new_pos*pixel_size).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;
subgrad=i/steps;
if (depth>z)
break;
}
final_pos = new_pos;
grad=(steps_taken+subgrad)/num_steps;
} else {
#endif
grad=steps_taken/num_steps;
final_pos=pos;
#ifdef SMOOTH_ACCEL
}
#endif
#ifdef REFLECT_ROUGHNESS
vec4 final_color;
//if roughness is enabled, do screen space cone tracing
if (roughness > 0.001) {
///////////////////////////////////////////////////////////////////////////////////////
//use a blurred version (in consecutive mipmaps) of the screen to simulate roughness
float gloss = 1.0-roughness;
float cone_angle = roughness * M_PI * 0.5;
vec2 cone_dir = final_pos - line_begin;
float cone_len = length(cone_dir);
cone_dir = normalize(cone_dir); //will be used normalized from now on
float max_mipmap = filter_mipmap_levels -1;
float gloss_mult=gloss;
float rem_alpha=1.0;
final_color = vec4(0.0);
for(int i=0;i<7;i++) {
float op_len = 2.0 * tan(cone_angle) * cone_len; //oposite side of iso triangle
float radius;
{
//fit to sphere inside cone (sphere ends at end of cone), something like this:
// ___
// \O/
// V
//
// as it avoids bleeding from beyond the reflection as much as possible. As a plus
// it also makes the rough reflection more elongated.
float a = op_len;
float h = cone_len;
float a2 = a * a;
float fh2 = 4.0f * h * h;
radius = (a * (sqrt(a2 + fh2) - a)) / (4.0f * h);
}
//find the place where screen must be sampled
vec2 sample_pos = ( line_begin + cone_dir * (cone_len - radius) ) * pixel_size;
//radius is in pixels, so it's natural that log2(radius) maps to the right mipmap for the amount of pixels
float mipmap = clamp( log2( radius ), 0.0, max_mipmap );
//mipmap = max(mipmap-1.0,0.0);
//do sampling
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);
}
}
//multiply by gloss
sample_color.rgb*=gloss_mult;
sample_color.a=gloss_mult;
rem_alpha -= sample_color.a;
if(rem_alpha < 0.0) {
sample_color.rgb *= (1.0 - abs(rem_alpha));
}
final_color+=sample_color;
if (final_color.a>=0.95) {
// This code of accumulating gloss and aborting on near one
// makes sense when you think of cone tracing.
// Think of it as if roughness was 0, then we could abort on the first
// iteration. For lesser roughness values, we need more iterations, but
// each needs to have less influence given the sphere is smaller
break;
}
cone_len-=radius*2.0; //go to next (smaller) circle.
gloss_mult*=gloss;
}
} else {
final_color = textureLod(source_diffuse,final_pos*pixel_size,0.0);
}
frag_color = vec4(final_color.rgb,pow(clamp(1.0-grad,0.0,1.0),distance_fade)*margin_blend);
#else
frag_color = vec4(textureLod(source_diffuse,final_pos*pixel_size,0.0).rgb,pow(clamp(1.0-grad,0.0,1.0),distance_fade)*margin_blend);
#endif
} else {
frag_color = vec4(0.0,0.0,0.0,0.0);
}
}

View File

@ -300,6 +300,84 @@ void Environment::_validate_property(PropertyInfo& property) const {
}
void Environment::set_ssr_enabled(bool p_enable) {
ssr_enabled=p_enable;
VS::get_singleton()->environment_set_ssr(environment,ssr_enabled,ssr_max_steps,ssr_accel,ssr_fade,ssr_depth_tolerance,ssr_smooth,ssr_roughness);
}
bool Environment::is_ssr_enabled() const{
return ssr_enabled;
}
void Environment::set_ssr_max_steps(int p_steps){
ssr_max_steps=p_steps;
VS::get_singleton()->environment_set_ssr(environment,ssr_enabled,ssr_max_steps,ssr_accel,ssr_fade,ssr_depth_tolerance,ssr_smooth,ssr_roughness);
}
int Environment::get_ssr_max_steps() const {
return ssr_max_steps;
}
void Environment::set_ssr_accel(float p_accel) {
ssr_accel=p_accel;
VS::get_singleton()->environment_set_ssr(environment,ssr_enabled,ssr_max_steps,ssr_accel,ssr_fade,ssr_depth_tolerance,ssr_smooth,ssr_roughness);
}
float Environment::get_ssr_accel() const {
return ssr_accel;
}
void Environment::set_ssr_fade(float p_fade) {
ssr_fade=p_fade;
VS::get_singleton()->environment_set_ssr(environment,ssr_enabled,ssr_max_steps,ssr_accel,ssr_fade,ssr_depth_tolerance,ssr_smooth,ssr_roughness);
}
float Environment::get_ssr_fade() const {
return ssr_fade;
}
void Environment::set_ssr_depth_tolerance(float p_depth_tolerance) {
ssr_depth_tolerance=p_depth_tolerance;
VS::get_singleton()->environment_set_ssr(environment,ssr_enabled,ssr_max_steps,ssr_accel,ssr_fade,ssr_depth_tolerance,ssr_smooth,ssr_roughness);
}
float Environment::get_ssr_depth_tolerance() const {
return ssr_depth_tolerance;
}
void Environment::set_ssr_smooth(bool p_enable) {
ssr_smooth=p_enable;
VS::get_singleton()->environment_set_ssr(environment,ssr_enabled,ssr_max_steps,ssr_accel,ssr_fade,ssr_depth_tolerance,ssr_smooth,ssr_roughness);
}
bool Environment::is_ssr_smooth() const {
return ssr_smooth;
}
void Environment::set_ssr_rough(bool p_enable) {
ssr_roughness=p_enable;
VS::get_singleton()->environment_set_ssr(environment,ssr_enabled,ssr_max_steps,ssr_accel,ssr_fade,ssr_depth_tolerance,ssr_smooth,ssr_roughness);
}
bool Environment::is_ssr_rough() const {
return ssr_roughness;
}
void Environment::_bind_methods() {
ObjectTypeDB::bind_method(_MD("set_background","mode"),&Environment::set_background);
@ -334,6 +412,37 @@ void Environment::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::REAL,"ambient_light/energy",PROPERTY_HINT_RANGE,"0,16,0.01"),_SCS("set_ambient_light_energy"),_SCS("get_ambient_light_energy") );
ADD_PROPERTY(PropertyInfo(Variant::REAL,"ambient_light/skybox_contribution",PROPERTY_HINT_RANGE,"0,1,0.01"),_SCS("set_ambient_light_skybox_contribution"),_SCS("get_ambient_light_skybox_contribution") );
ObjectTypeDB::bind_method(_MD("set_ssr_enabled","enabled"),&Environment::set_ssr_enabled);
ObjectTypeDB::bind_method(_MD("is_ssr_enabled"),&Environment::is_ssr_enabled);
ObjectTypeDB::bind_method(_MD("set_ssr_max_steps","max_steps"),&Environment::set_ssr_max_steps);
ObjectTypeDB::bind_method(_MD("get_ssr_max_steps"),&Environment::get_ssr_max_steps);
ObjectTypeDB::bind_method(_MD("set_ssr_accel","accel"),&Environment::set_ssr_accel);
ObjectTypeDB::bind_method(_MD("get_ssr_accel"),&Environment::get_ssr_accel);
ObjectTypeDB::bind_method(_MD("set_ssr_fade","fade"),&Environment::set_ssr_fade);
ObjectTypeDB::bind_method(_MD("get_ssr_fade"),&Environment::get_ssr_fade);
ObjectTypeDB::bind_method(_MD("set_ssr_depth_tolerance","depth_tolerance"),&Environment::set_ssr_depth_tolerance);
ObjectTypeDB::bind_method(_MD("get_ssr_depth_tolerance"),&Environment::get_ssr_depth_tolerance);
ObjectTypeDB::bind_method(_MD("set_ssr_smooth","smooth"),&Environment::set_ssr_smooth);
ObjectTypeDB::bind_method(_MD("is_ssr_smooth"),&Environment::is_ssr_smooth);
ObjectTypeDB::bind_method(_MD("set_ssr_rough","rough"),&Environment::set_ssr_rough);
ObjectTypeDB::bind_method(_MD("is_ssr_rough"),&Environment::is_ssr_rough);
ADD_PROPERTY(PropertyInfo(Variant::BOOL,"ss_reflections/enable"),_SCS("set_ssr_enabled"),_SCS("is_ssr_enabled") );
ADD_PROPERTY(PropertyInfo(Variant::INT,"ss_reflections/max_steps",PROPERTY_HINT_RANGE,"1,512,1"),_SCS("set_ssr_max_steps"),_SCS("get_ssr_max_steps") );
ADD_PROPERTY(PropertyInfo(Variant::REAL,"ss_reflections/accel",PROPERTY_HINT_RANGE,"0,4,0.01"),_SCS("set_ssr_accel"),_SCS("get_ssr_accel") );
ADD_PROPERTY(PropertyInfo(Variant::REAL,"ss_reflections/fade",PROPERTY_HINT_EXP_EASING),_SCS("set_ssr_fade"),_SCS("get_ssr_fade") );
ADD_PROPERTY(PropertyInfo(Variant::REAL,"ss_reflections/depth_tolerance",PROPERTY_HINT_RANGE,"0.1,128,0.1"),_SCS("set_ssr_depth_tolerance"),_SCS("get_ssr_depth_tolerance") );
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_tonemapper","mode"),&Environment::set_tonemapper);
ObjectTypeDB::bind_method(_MD("get_tonemapper"),&Environment::get_tonemapper);
@ -358,6 +467,9 @@ void Environment::_bind_methods() {
ObjectTypeDB::bind_method(_MD("set_tonemap_auto_exposure_scale","exposure_scale"),&Environment::set_tonemap_auto_exposure_scale);
ObjectTypeDB::bind_method(_MD("get_tonemap_auto_exposure_scale"),&Environment::get_tonemap_auto_exposure_scale);
ADD_PROPERTY(PropertyInfo(Variant::INT,"tonemap/mode",PROPERTY_HINT_ENUM,"Linear,Log,Reindhart,Filmic,Aces"),_SCS("set_tonemapper"),_SCS("get_tonemapper") );
ADD_PROPERTY(PropertyInfo(Variant::REAL,"tonemap/exposure",PROPERTY_HINT_RANGE,"0,16,0.01"),_SCS("set_tonemap_exposure"),_SCS("get_tonemap_exposure") );
ADD_PROPERTY(PropertyInfo(Variant::REAL,"tonemap/white",PROPERTY_HINT_RANGE,"0,16,0.01"),_SCS("set_tonemap_white"),_SCS("get_tonemap_white") );
@ -441,6 +553,14 @@ Environment::Environment() {
environment = VS::get_singleton()->environment_create();
ssr_enabled=false;
ssr_max_steps=64;
ssr_accel=0.04;
ssr_fade=2.0;
ssr_depth_tolerance=0.2;
ssr_smooth=true;
ssr_roughness=true;
}
Environment::~Environment() {

View File

@ -94,6 +94,14 @@ private:
float adjustment_brightness;
Ref<Texture> adjustment_color_correction;
bool ssr_enabled;
int ssr_max_steps;
float ssr_accel;
float ssr_fade;
float ssr_depth_tolerance;
bool ssr_smooth;
bool ssr_roughness;
protected:
static void _bind_methods();
@ -162,6 +170,27 @@ public:
void set_adjustment_color_correction(const Ref<Texture>& p_ramp);
Ref<Texture> get_adjustment_color_correction() const;
void set_ssr_enabled(bool p_enable);
bool is_ssr_enabled() const;
void set_ssr_max_steps(int p_steps);
int get_ssr_max_steps() const;
void set_ssr_accel(float p_accel);
float get_ssr_accel() const;
void set_ssr_fade(float p_fade);
float get_ssr_fade() const;
void set_ssr_depth_tolerance(float p_depth_tolerance);
float get_ssr_depth_tolerance() const;
void set_ssr_smooth(bool p_enable);
bool is_ssr_smooth() const;
void set_ssr_rough(bool p_enable);
bool is_ssr_rough() const;
virtual RID get_rid() const;

View File

@ -64,6 +64,8 @@ public:
virtual void environment_set_glow(RID p_env,bool p_enable,int p_radius,float p_intensity,float p_strength,float p_bloom_treshold,VS::EnvironmentGlowBlendMode p_blend_mode)=0;
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_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;

View File

@ -875,6 +875,7 @@ public:
BIND2(environment_set_bg_energy,RID,float )
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 )
BIND7(environment_set_glow,RID,bool ,int ,float ,float ,float ,EnvironmentGlowBlendMode )
BIND5(environment_set_fog,RID,bool ,float ,float ,RID )

View File

@ -555,7 +555,7 @@ public:
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,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;
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 */

View File

@ -463,7 +463,7 @@ Transform Collada::_read_transform(XMLParser& parser) {
if (parser.is_empty())
return Transform();
Vector<float> array;
Vector<String> array;
while(parser.read()==OK) {
// TODO: check for comments inside the element
// and ignore them.
@ -471,7 +471,7 @@ Transform Collada::_read_transform(XMLParser& parser) {
if (parser.get_node_type() == XMLParser::NODE_TEXT) {
// parse float data
String str = parser.get_node_data();
array=str.split_floats(" ",false);
array=str.split_spaces();
}
else
if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END)
@ -479,7 +479,13 @@ Transform Collada::_read_transform(XMLParser& parser) {
}
ERR_FAIL_COND_V(array.size()!=16,Transform());
return _read_transform_from_array(array);
Vector<float> farr;
farr.resize(16);
for(int i=0;i<16;i++) {
farr[i]=array[i].to_double();
}
return _read_transform_from_array(farr);
}
String Collada::_read_empty_draw_type(XMLParser& parser) {