diff options
author | Antony Riakiotakis <kalast@gmail.com> | 2015-02-17 20:08:28 +0300 |
---|---|---|
committer | Antony Riakiotakis <kalast@gmail.com> | 2015-02-17 20:11:22 +0300 |
commit | ff7220349d32e747c7559809d68de7d835c0c1cd (patch) | |
tree | c6955f0b86bcf12ab6dc5d87b4a48300375d3da3 | |
parent | a0d7db503d82c1a5b56a5723da90364f11569b37 (diff) |
Compositing works with X-Ray.
Basically, before drawing X-Rays, we now bind a second depth buffer.
After drawing XRays, we do an extra resolve pass where we overwrite the
non-XRay depth buffer in pixels where the depth is not maximum (which
means background pixel, since depth is cleared before drawing X-Ray
objects).
This ensures both scene and X-Rays keep their depth values and are ready
for compositing. Well, the odd effect due to depth discontinuities can be
expected, and X-Rays are a bit more expensive (extra buffer + resolve pass)
but at least X-Rays won't invalidate depth values anymore. Whee!
-rw-r--r-- | SConstruct | 1 | ||||
-rw-r--r-- | source/blender/editors/space_view3d/view3d_draw.c | 20 | ||||
-rw-r--r-- | source/blender/gpu/CMakeLists.txt | 2 | ||||
-rw-r--r-- | source/blender/gpu/GPU_compositing.h | 10 | ||||
-rw-r--r-- | source/blender/gpu/intern/gpu_compositing.c | 89 | ||||
-rw-r--r-- | source/blender/gpu/intern/gpu_extensions.c | 4 | ||||
-rw-r--r-- | source/blender/gpu/shaders/gpu_shader_fx_depth_resolve.glsl | 14 |
7 files changed, 135 insertions, 5 deletions
diff --git a/SConstruct b/SConstruct index 225b532c8a0..29e22cb32a7 100644 --- a/SConstruct +++ b/SConstruct @@ -765,6 +765,7 @@ if B.targets != ['cudakernels']: data_to_c_simple("source/blender/gpu/shaders/gpu_shader_fx_dof_frag.glsl") data_to_c_simple("source/blender/gpu/shaders/gpu_shader_fx_dof_vert.glsl") data_to_c_simple("source/blender/gpu/shaders/gpu_shader_fx_lib.glsl") + data_to_c_simple("source/blender/gpu/shaders/gpu_shader_fx_depth_resolve.glsl") data_to_c_simple("source/blender/gpu/shaders/gpu_shader_fx_vert.glsl") data_to_c_simple("intern/opencolorio/gpu_shader_display_transform.glsl") diff --git a/source/blender/editors/space_view3d/view3d_draw.c b/source/blender/editors/space_view3d/view3d_draw.c index f552d5ca3db..b2aef64a702 100644 --- a/source/blender/editors/space_view3d/view3d_draw.c +++ b/source/blender/editors/space_view3d/view3d_draw.c @@ -2666,7 +2666,7 @@ static void view3d_draw_objects( const bContext *C, Scene *scene, View3D *v3d, ARegion *ar, const char **grid_unit, - const bool do_bgpic, const bool draw_offscreen) + const bool do_bgpic, const bool draw_offscreen, bool do_compositing) { RegionView3D *rv3d = ar->regiondata; Base *base; @@ -2675,6 +2675,7 @@ static void view3d_draw_objects( const bool draw_floor = (rv3d->view == RV3D_VIEW_USER) || (rv3d->persp != RV3D_ORTHO); /* only draw grids after in solid modes, else it hovers over mesh wires */ const bool draw_grids_after = draw_grids && draw_floor && (v3d->drawtype > OB_WIRE); + bool do_composite_xray = false; bool xrayclear = true; if (!draw_offscreen) { @@ -2814,9 +2815,20 @@ static void view3d_draw_objects( /* transp and X-ray afterdraw stuff */ if (v3d->afterdraw_transp.first) view3d_draw_transp(scene, ar, v3d); + + /* always do that here to cleanup depth buffers if none needed */ + if (do_compositing) { + do_composite_xray = v3d->zbuf && (v3d->afterdraw_xray.first || v3d->afterdraw_xraytransp.first); + GPU_fx_compositor_setup_XRay_pass(rv3d->compositor, do_composite_xray); + } + if (v3d->afterdraw_xray.first) view3d_draw_xray(scene, ar, v3d, &xrayclear); if (v3d->afterdraw_xraytransp.first) view3d_draw_xraytransp(scene, ar, v3d, xrayclear); + if (do_compositing && do_composite_xray) { + GPU_fx_compositor_XRay_resolve(rv3d->compositor); + } + if (!draw_offscreen) { ED_region_draw_cb_draw(C, ar, REGION_DRAW_POST_VIEW); } @@ -3117,11 +3129,11 @@ void ED_view3d_draw_offscreen( } else { glClearColor(0.0f, 0.0f, 0.0f, 0.0f); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); } /* main drawing call */ - view3d_draw_objects(NULL, scene, v3d, ar, NULL, do_bgpic, true); + view3d_draw_objects(NULL, scene, v3d, ar, NULL, do_bgpic, true, do_compositing); /* post process */ if (do_compositing) { @@ -3551,7 +3563,7 @@ static void view3d_main_area_draw_objects(const bContext *C, Scene *scene, View3 } /* main drawing call */ - view3d_draw_objects(C, scene, v3d, ar, grid_unit, true, false); + view3d_draw_objects(C, scene, v3d, ar, grid_unit, true, false, do_compositing); /* post process */ if (do_compositing) { diff --git a/source/blender/gpu/CMakeLists.txt b/source/blender/gpu/CMakeLists.txt index 7e32105a916..12b7f864469 100644 --- a/source/blender/gpu/CMakeLists.txt +++ b/source/blender/gpu/CMakeLists.txt @@ -69,6 +69,7 @@ set(SRC shaders/gpu_shader_vertex.glsl shaders/gpu_shader_vsm_store_frag.glsl shaders/gpu_shader_vsm_store_vert.glsl + shaders/gpu_shader_fx_depth_resolve.glsl GPU_buffers.h GPU_draw.h @@ -96,6 +97,7 @@ data_to_c_simple(shaders/gpu_shader_fx_vert.glsl SRC) data_to_c_simple(shaders/gpu_shader_fx_ssao_frag.glsl SRC) data_to_c_simple(shaders/gpu_shader_fx_dof_frag.glsl SRC) data_to_c_simple(shaders/gpu_shader_fx_dof_vert.glsl SRC) +data_to_c_simple(shaders/gpu_shader_fx_depth_resolve.glsl SRC) data_to_c_simple(shaders/gpu_shader_fx_lib.glsl SRC) if(WITH_GAMEENGINE) diff --git a/source/blender/gpu/GPU_compositing.h b/source/blender/gpu/GPU_compositing.h index 796341d4830..93f1bc64922 100644 --- a/source/blender/gpu/GPU_compositing.h +++ b/source/blender/gpu/GPU_compositing.h @@ -60,10 +60,12 @@ typedef enum GPUFXShaderEffect { GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_THREE = 4, GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_FOUR = 5, GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_FIVE = 6, + + GPU_SHADER_FX_DEPTH_RESOLVE = 7, } GPUFXShaderEffect; /* keep in synch with enum above! */ -#define MAX_FX_SHADERS 11 +#define MAX_FX_SHADERS 8 /* generate a new FX compositor */ GPUFX *GPU_fx_compositor_create(void); @@ -79,6 +81,12 @@ bool GPU_fx_compositor_initialize_passes( /* do compositing on the fx passes that have been initialized */ bool GPU_fx_do_composite_pass(GPUFX *fx, float projmat[4][4], bool is_persp, struct Scene *scene, struct GPUOffScreen *ofs); +/* bind new depth buffer for XRay pass */ +void GPU_fx_compositor_setup_XRay_pass(GPUFX *fx, bool do_xray); + +/* resolve a final depth buffer by compositing the XRay and normal depth buffers */ +void GPU_fx_compositor_XRay_resolve(GPUFX *fx); + void GPU_fx_compositor_init_dof_settings(struct GPUDOFSettings *dof); void GPU_fx_compositor_init_ssao_settings(struct GPUSSAOSettings *ssao); #ifdef __cplusplus diff --git a/source/blender/gpu/intern/gpu_compositing.c b/source/blender/gpu/intern/gpu_compositing.c index cf288070126..32d805035d4 100644 --- a/source/blender/gpu/intern/gpu_compositing.c +++ b/source/blender/gpu/intern/gpu_compositing.c @@ -89,6 +89,7 @@ struct GPUFX { /* texture bound to the depth attachment of the gbuffer */ GPUTexture *depth_buffer; + GPUTexture *depth_buffer_xray; /* texture used for jittering for various effects */ GPUTexture *jitter_buffer; @@ -213,6 +214,12 @@ static void cleanup_fx_gl_data(GPUFX *fx, bool do_fbo) fx->depth_buffer = NULL; } + if (fx->depth_buffer_xray) { + GPU_framebuffer_texture_detach(fx->depth_buffer_xray); + GPU_texture_free(fx->depth_buffer_xray); + fx->depth_buffer_xray = NULL; + } + cleanup_fx_dof_buffers(fx); if (fx->ssao_concentric_samples_tex) { @@ -452,6 +459,88 @@ static void gpu_fx_bind_render_target(int *passes_left, GPUFX *fx, struct GPUOff } } +void GPU_fx_compositor_setup_XRay_pass(GPUFX *fx, bool do_xray) +{ + char err_out[256]; + + if (do_xray) { + if (!fx->depth_buffer_xray && !(fx->depth_buffer_xray = GPU_texture_create_depth(fx->gbuffer_dim[0], fx->gbuffer_dim[1], err_out))) { + printf("%.256s\n", err_out); + cleanup_fx_gl_data(fx, true); + return; + } + } + else { + if (fx->depth_buffer_xray) { + GPU_framebuffer_texture_detach(fx->depth_buffer_xray); + GPU_texture_free(fx->depth_buffer_xray); + fx->depth_buffer_xray = NULL; + } + return; + } + + GPU_framebuffer_texture_detach(fx->depth_buffer); + + /* first depth buffer, because system assumes read/write buffers */ + if(!GPU_framebuffer_texture_attach(fx->gbuffer, fx->depth_buffer_xray, 0, err_out)) + printf("%.256s\n", err_out); +} + + +void GPU_fx_compositor_XRay_resolve(GPUFX *fx) +{ + GPUShader *depth_resolve_shader; + GPU_framebuffer_texture_detach(fx->depth_buffer_xray); + + /* attach regular framebuffer */ + GPU_framebuffer_texture_attach(fx->gbuffer, fx->depth_buffer, 0, NULL); + + /* full screen quad where we will always write to depth buffer */ + glPushAttrib(GL_DEPTH_BUFFER_BIT | GL_SCISSOR_BIT); + glDepthFunc(GL_ALWAYS); + /* disable scissor from sculpt if any */ + glDisable(GL_SCISSOR_TEST); + /* disable writing to color buffer, it's depth only pass */ + glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); + + /* set up quad buffer */ + glVertexPointer(2, GL_FLOAT, 0, fullscreencos); + glTexCoordPointer(2, GL_FLOAT, 0, fullscreenuvs); + glEnableClientState(GL_VERTEX_ARRAY); + glEnableClientState(GL_TEXTURE_COORD_ARRAY); + + depth_resolve_shader = GPU_shader_get_builtin_fx_shader(GPU_SHADER_FX_DEPTH_RESOLVE, false); + + if (depth_resolve_shader) { + int depth_uniform; + + depth_uniform = GPU_shader_get_uniform(depth_resolve_shader, "depthbuffer"); + + GPU_shader_bind(depth_resolve_shader); + + GPU_texture_bind(fx->depth_buffer_xray, 0); + GPU_depth_texture_mode(fx->depth_buffer_xray, false, true); + GPU_shader_uniform_texture(depth_resolve_shader, depth_uniform, fx->depth_buffer_xray); + + /* draw */ + glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); + + /* disable bindings */ + GPU_depth_texture_mode(fx->depth_buffer_xray, true, false); + GPU_texture_unbind(fx->depth_buffer_xray); + + GPU_shader_unbind(); + } + + glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); + + glDisableClientState(GL_VERTEX_ARRAY); + glDisableClientState(GL_TEXTURE_COORD_ARRAY); + + glPopAttrib(); +} + + bool GPU_fx_do_composite_pass(GPUFX *fx, float projmat[4][4], bool is_persp, struct Scene *scene, struct GPUOffScreen *ofs) { GPUTexture *src, *target; diff --git a/source/blender/gpu/intern/gpu_extensions.c b/source/blender/gpu/intern/gpu_extensions.c index 4d1a9770c78..1d081875c9b 100644 --- a/source/blender/gpu/intern/gpu_extensions.c +++ b/source/blender/gpu/intern/gpu_extensions.c @@ -83,6 +83,7 @@ extern char datatoc_gpu_shader_fx_vert_glsl[]; extern char datatoc_gpu_shader_fx_ssao_frag_glsl[]; extern char datatoc_gpu_shader_fx_dof_frag_glsl[]; extern char datatoc_gpu_shader_fx_dof_vert_glsl[]; +extern char datatoc_gpu_shader_fx_depth_resolve_glsl[]; extern char datatoc_gpu_shader_fx_lib_glsl[]; typedef struct GPUShaders { @@ -1776,6 +1777,9 @@ GPUShader *GPU_shader_get_builtin_fx_shader(int effects, bool persp) strcat(defines, "#define FIFTH_PASS\n"); GG.shaders.fx_shaders[offset] = GPU_shader_create(datatoc_gpu_shader_fx_dof_vert_glsl, datatoc_gpu_shader_fx_dof_frag_glsl, datatoc_gpu_shader_fx_lib_glsl, defines); break; + + case GPU_SHADER_FX_DEPTH_RESOLVE: + GG.shaders.fx_shaders[offset] = GPU_shader_create(datatoc_gpu_shader_fx_vert_glsl, datatoc_gpu_shader_fx_depth_resolve_glsl, NULL, defines); } } diff --git a/source/blender/gpu/shaders/gpu_shader_fx_depth_resolve.glsl b/source/blender/gpu/shaders/gpu_shader_fx_depth_resolve.glsl new file mode 100644 index 00000000000..e04cd7d3306 --- /dev/null +++ b/source/blender/gpu/shaders/gpu_shader_fx_depth_resolve.glsl @@ -0,0 +1,14 @@ +uniform sampler2D depthbuffer; +varying vec4 uvcoordsvar; + +void main(void) +{ + float depth = texture2D(depthbuffer, uvcoordsvar.xy).r; + + /* XRay background, discard */ + if (depth >= 1.0) { + discard; + } + + gl_FragDepth = depth; +} |