Clay Engine: Replace Manual depth test by depth copy.

This avoid glitches due to float comparison precision.
This commit is contained in:
Clément Foucault 2017-02-15 15:15:42 +01:00
parent bdd3fd64e9
commit f9e4d8e93a
6 changed files with 67 additions and 20 deletions

View File

@ -105,7 +105,7 @@ typedef struct CLAY_FramebufferList{
/* default */
struct GPUFrameBuffer *default_fb;
/* engine specific */
struct GPUFrameBuffer *downsample_depth;
struct GPUFrameBuffer *dupli_depth;
} CLAY_FramebufferList;
/* keep it under MAX_TEXTURES */
@ -114,14 +114,14 @@ typedef struct CLAY_TextureList{
struct GPUTexture *color;
struct GPUTexture *depth;
/* engine specific */
struct GPUTexture *depth_low;
struct GPUTexture *depth_dup;
} CLAY_TextureList;
/* for clarity follow the same layout as CLAY_TextureList */
enum {
SCENE_COLOR,
SCENE_DEPTH,
SCENE_DEPTH_LOW,
SCENE_DEPTH_DUP,
};
/* keep it under MAX_PASSES */
@ -283,7 +283,7 @@ MaterialEngineSettings *CLAY_material_settings_create(void)
return (MaterialEngineSettings *)settings;
}
static void CLAY_engine_init(CLAY_StorageList *stl)
static void CLAY_engine_init(CLAY_StorageList *stl, CLAY_TextureList *txl, CLAY_FramebufferList *fbl)
{
/* Create Texture Array */
if (!data.matcap_array) {
@ -373,6 +373,14 @@ static void CLAY_engine_init(CLAY_StorageList *stl)
ubo_mat_idxs[i] = i;
}
}
{
float *viewport_size = DRW_viewport_size_get();
DRWFboTexture tex = {&txl->depth_dup, DRW_BUF_DEPTH_24};
DRW_framebuffer_init(&fbl->dupli_depth,
(int)viewport_size[0], (int)viewport_size[1],
&tex, 1);
}
}
static void CLAY_ssao_setup(void)
@ -434,7 +442,7 @@ static DRWShadingGroup *CLAY_shgroup_create(DRWPass *pass, int *material_id)
DRWShadingGroup *grp = DRW_shgroup_create(data.clay_sh, pass);
DRW_shgroup_uniform_vec2(grp, "screenres", DRW_viewport_size_get(), 1);
DRW_shgroup_uniform_buffer(grp, "depthtex", SCENE_DEPTH, depthloc);
DRW_shgroup_uniform_buffer(grp, "depthtex", SCENE_DEPTH_DUP, depthloc);
DRW_shgroup_uniform_texture(grp, "matcaps", data.matcap_array, matcaploc);
DRW_shgroup_uniform_mat4(grp, "WinMatrix", (float *)data.winmat);
DRW_shgroup_uniform_vec4(grp, "viewvecs", (float *)data.viewvecs, 3);
@ -609,7 +617,7 @@ static void CLAY_create_cache(CLAY_PassList *passes, CLAY_StorageList *stl, cons
/* Clay Pass */
{
passes->clay_pass = DRW_pass_create("Clay Pass", DRW_STATE_WRITE_COLOR);
passes->clay_pass = DRW_pass_create("Clay Pass", DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_EQUAL);
stl->storage->ubo_current_id = 0;
}
@ -629,7 +637,7 @@ static void CLAY_create_cache(CLAY_PassList *passes, CLAY_StorageList *stl, cons
}
struct Batch *geom;
//bool do_outlines;
bool do_outlines;
switch (ob->type) {
case OB_MESH:
@ -644,8 +652,8 @@ static void CLAY_create_cache(CLAY_PassList *passes, CLAY_StorageList *stl, cons
//DRW_shgroup_wire_overlay(passes->wire_overlay_pass, ob);
//do_outlines = ((ob->base_flag & BASE_SELECTED) != 0);
//DRW_shgroup_wire_outline(passes->wire_outline_pass, ob, false, false, do_outlines);
do_outlines = ((ob->base_flag & BASE_SELECTED) != 0);
DRW_shgroup_wire_outline(passes->wire_outline_pass, ob, false, false, do_outlines);
/* When encountering a new material :
* - Create new Batch
@ -683,7 +691,8 @@ static void CLAY_view_draw(RenderEngine *UNUSED(engine), const bContext *context
DRW_viewport_init(context, (void **)&buffers, (void **)&textures, (void **)&passes, (void **)&storage);
CLAY_engine_init(storage);
CLAY_engine_init(storage, textures, buffers);
/* TODO : tag to refresh by the deps graph */
/* ideally only refresh when objects are added/removed */
@ -708,20 +717,18 @@ static void CLAY_view_draw(RenderEngine *UNUSED(engine), const bContext *context
/* Pass 1 : Depth pre-pass */
DRW_draw_pass(passes->depth_pass);
/* Pass 2 (Optionnal) : Separated Downsampled AO */
DRW_framebuffer_texture_detach(textures->depth);
/* TODO */
/* Pass 2 : Duplicate depth */
/* Unless we go for deferred shading we need this to avoid manual depth test and artifacts */
DRW_framebuffer_blit(buffers->default_fb, buffers->dupli_depth, true);
/* Pass 3 : Shading */
CLAY_ssao_setup();
DRW_draw_pass(passes->clay_pass);
/* Pass 4 : Overlays */
DRW_framebuffer_texture_attach(buffers->default_fb, textures->depth, 0);
DRW_draw_grid();
//DRW_draw_pass(passes->wire_overlay_pass);
//DRW_draw_pass(passes->wire_outline_pass);
DRW_draw_pass(passes->wire_outline_pass);
DRW_draw_pass(passes->non_meshes_pass);
DRW_draw_pass(passes->ob_center_pass);

View File

@ -160,10 +160,6 @@ void main() {
vec2 screenco = vec2(gl_FragCoord.xy) / screenres;
float depth = texture(depthtex, screenco).r;
/* Manual Depth test */
if (gl_FragCoord.z > depth + 1e-5)
discard;
vec3 position = get_view_space_from_depth(screenco, depth);
#ifdef USE_ROTATION

View File

@ -135,6 +135,7 @@ void DRW_framebuffer_init(struct GPUFrameBuffer **fb, int width, int height, DRW
void DRW_framebuffer_bind(struct GPUFrameBuffer *fb);
void DRW_framebuffer_texture_attach(struct GPUFrameBuffer *fb, struct GPUTexture *tex, int slot);
void DRW_framebuffer_texture_detach(struct GPUTexture *tex);
void DRW_framebuffer_blit(struct GPUFrameBuffer *fb_read, struct GPUFrameBuffer *fb_write, bool depth);
/* Shaders */
struct GPUShader *DRW_shader_create(const char *vert, const char *geom, const char *frag, const char *defines);
struct GPUShader *DRW_shader_create_2D(const char *frag, const char *defines);

View File

@ -1133,6 +1133,11 @@ void DRW_framebuffer_texture_detach(GPUTexture *tex)
GPU_framebuffer_texture_detach(tex);
}
void DRW_framebuffer_blit(struct GPUFrameBuffer *fb_read, struct GPUFrameBuffer *fb_write, bool depth)
{
GPU_framebuffer_blit(fb_read, 0, fb_write, 0, depth);
}
/* ****************************************** Viewport ******************************************/
float *DRW_viewport_size_get(void)

View File

@ -67,6 +67,10 @@ void GPU_framebuffer_blur(
GPUFrameBuffer *fb, struct GPUTexture *tex,
GPUFrameBuffer *blurfb, struct GPUTexture *blurtex);
void GPU_framebuffer_blit(
GPUFrameBuffer *fb_read, int read_slot,
GPUFrameBuffer *fb_write, int write_slot, bool use_depth);
/* GPU OffScreen
* - wrapper around framebuffer and texture for simple offscreen drawing
* - changes size if graphics card can't support it */

View File

@ -448,6 +448,40 @@ void GPU_framebuffer_blur(
GPU_shader_unbind();
}
void GPU_framebuffer_blit(GPUFrameBuffer *fb_read, int read_slot, GPUFrameBuffer *fb_write, int write_slot, bool use_depth)
{
GPUTexture *read_tex = (use_depth) ? fb_read->depthtex : fb_read->colortex[read_slot];
GPUTexture *write_tex = (use_depth) ? fb_write->depthtex : fb_write->colortex[write_slot];
int read_attach = (use_depth) ? GL_DEPTH_ATTACHMENT : GL_COLOR_ATTACHMENT0 + GPU_texture_framebuffer_attachment(read_tex);
int write_attach = (use_depth) ? GL_DEPTH_ATTACHMENT : GL_COLOR_ATTACHMENT0 + GPU_texture_framebuffer_attachment(write_tex);
int read_bind = GPU_texture_opengl_bindcode(read_tex);
int write_bind = GPU_texture_opengl_bindcode(write_tex);
const int read_w = GPU_texture_width(read_tex);
const int read_h = GPU_texture_height(read_tex);
const int write_w = GPU_texture_width(write_tex);
const int write_h = GPU_texture_height(write_tex);
/* read from multi-sample buffer */
glBindFramebuffer(GL_READ_FRAMEBUFFER, fb_read->object);
glFramebufferTexture2D(
GL_READ_FRAMEBUFFER, read_attach,
GL_TEXTURE_2D, read_bind, 0);
BLI_assert(glCheckFramebufferStatusEXT(GL_READ_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE);
/* write into new single-sample buffer */
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fb_write->object);
glFramebufferTexture2D(
GL_DRAW_FRAMEBUFFER, write_attach,
GL_TEXTURE_2D, write_bind, 0);
BLI_assert(glCheckFramebufferStatusEXT(GL_DRAW_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE);
glBlitFramebuffer(0, 0, read_w, read_h, 0, 0, write_w, write_h, (use_depth) ? GL_DEPTH_BUFFER_BIT : GL_COLOR_BUFFER_BIT, GL_NEAREST);
/* Restore previous framebuffer */
glBindFramebuffer(GL_FRAMEBUFFER, GG.currentfb);
glDrawBuffer(GL_COLOR_ATTACHMENT0);
}
/* GPUOffScreen */
struct GPUOffScreen {