Commit: d9cc3f50682302ca12e3a4fa0390c857f2013c25 Author: Campbell Barton Date: Tue Oct 13 22:36:02 2015 +1100 Branches: experimental-build https://developer.blender.org/rBd9cc3f50682302ca12e3a4fa0390c857f2013c25
Support for multi-sample off-screen buffers Currently only used for OpenGL render, replaces slower accumulation buffer which simply did multiple renders. Reviewers: psy-fi, brecht, sergey Differential Revision: https://developer.blender.org/D1556 =================================================================== M source/blender/editors/render/render_opengl.c M source/blender/editors/space_view3d/view3d_draw.c M source/blender/gpu/GPU_extensions.h M source/blender/gpu/intern/gpu_extensions.c =================================================================== diff --git a/source/blender/editors/render/render_opengl.c b/source/blender/editors/render/render_opengl.c index 954fcde..c8ced55 100644 --- a/source/blender/editors/render/render_opengl.c +++ b/source/blender/editors/render/render_opengl.c @@ -375,54 +375,11 @@ static void screen_opengl_render_doit(OGLRender *oglrender, RenderResult *rr) rect = MEM_mallocN(sizex * sizey * sizeof(unsigned char) * 4, "offscreen rect"); - if ((scene->r.mode & R_OSA) == 0) { - ED_view3d_draw_offscreen( - scene, v3d, ar, sizex, sizey, NULL, winmat, - draw_bgpic, draw_sky, is_persp, - oglrender->ofs, oglrender->fx, &fx_settings, viewname); - GPU_offscreen_read_pixels(oglrender->ofs, GL_UNSIGNED_BYTE, rect); - } - else { - /* simple accumulation, less hassle then FSAA FBO's */ - static float jit_ofs[32][2]; - float winmat_jitter[4][4]; - int *accum_buffer = MEM_mallocN(sizex * sizey * sizeof(int) * 4, "accum1"); - int i, j; - - BLI_jitter_init(jit_ofs, scene->r.osa); - - /* first sample buffer, also initializes 'rv3d->persmat' */ - ED_view3d_draw_offscreen( - scene, v3d, ar, sizex, sizey, NULL, winmat, - draw_bgpic, draw_sky, is_persp, - oglrender->ofs, oglrender->fx, &fx_settings, viewname); - GPU_offscreen_read_pixels(oglrender->ofs, GL_UNSIGNED_BYTE, rect); - - for (i = 0; i < sizex * sizey * 4; i++) - accum_buffer[i] = rect[i]; - - /* skip the first sample */ - for (j = 1; j < scene->r.osa; j++) { - copy_m4_m4(winmat_jitter, winmat); - window_translate_m4(winmat_jitter, rv3d->persmat, - (jit_ofs[j][0] * 2.0f) / sizex, - (jit_ofs[j][1] * 2.0f) / sizey); - - ED_view3d_draw_offscreen( - scene, v3d, ar, sizex, sizey, NULL, winmat_jitter, - draw_bgpic, draw_sky, is_persp, - oglrender->ofs, oglrender->fx, &fx_settings, viewname); - GPU_offscreen_read_pixels(oglrender->ofs, GL_UNSIGNED_BYTE, rect); - - for (i = 0; i < sizex * sizey * 4; i++) - accum_buffer[i] += rect[i]; - } - - for (i = 0; i < sizex * sizey * 4; i++) - rect[i] = accum_buffer[i] / scene->r.osa; - - MEM_freeN(accum_buffer); - } + ED_view3d_draw_offscreen( + scene, v3d, ar, sizex, sizey, NULL, winmat, + draw_bgpic, draw_sky, is_persp, + oglrender->ofs, oglrender->fx, &fx_settings, viewname); + GPU_offscreen_read_pixels(oglrender->ofs, GL_UNSIGNED_BYTE, rect); GPU_offscreen_unbind(oglrender->ofs, true); /* unbind */ } @@ -546,6 +503,7 @@ static bool screen_opengl_render_init(bContext *C, wmOperator *op) const bool is_sequencer = RNA_boolean_get(op->ptr, "sequencer"); const bool is_write_still = RNA_boolean_get(op->ptr, "write_still"); char err_out[256] = "unknown"; + int samples = (scene->r.mode & R_OSA) ? scene->r.osa : 0; if (G.background) { BKE_report(op->reports, RPT_ERROR, "Cannot use OpenGL render in background mode (no opengl context)"); @@ -585,7 +543,7 @@ static bool screen_opengl_render_init(bContext *C, wmOperator *op) sizey = (scene->r.size * scene->r.ysch) / 100; /* corrects render size with actual size, not every card supports non-power-of-two dimensions */ - ofs = GPU_offscreen_create(sizex, sizey, err_out); + ofs = GPU_offscreen_create(sizex, sizey, samples, err_out); if (!ofs) { BKE_reportf(op->reports, RPT_ERROR, "Failed to create OpenGL off-screen buffer, %s", err_out); diff --git a/source/blender/editors/space_view3d/view3d_draw.c b/source/blender/editors/space_view3d/view3d_draw.c index 18c178f..bb34497 100644 --- a/source/blender/editors/space_view3d/view3d_draw.c +++ b/source/blender/editors/space_view3d/view3d_draw.c @@ -1381,7 +1381,7 @@ static void backdrawview3d(Scene *scene, ARegion *ar, View3D *v3d) } if (!rv3d->gpuoffscreen) { - rv3d->gpuoffscreen = GPU_offscreen_create(w, h, error); + rv3d->gpuoffscreen = GPU_offscreen_create(w, h, 0, error); if (!rv3d->gpuoffscreen) fprintf(stderr, "Failed to create offscreen selection buffer for multisample: %s\n", error); @@ -3263,7 +3263,7 @@ ImBuf *ED_view3d_draw_offscreen_imbuf(Scene *scene, View3D *v3d, ARegion *ar, in glPushAttrib(GL_LIGHTING_BIT); /* bind */ - ofs = GPU_offscreen_create(sizex, sizey, err_out); + ofs = GPU_offscreen_create(sizex, sizey, 4, err_out); if (ofs == NULL) { glPopAttrib(); return NULL; diff --git a/source/blender/gpu/GPU_extensions.h b/source/blender/gpu/GPU_extensions.h index 0e8d204..2dadd38 100644 --- a/source/blender/gpu/GPU_extensions.h +++ b/source/blender/gpu/GPU_extensions.h @@ -130,6 +130,8 @@ GPUTexture *GPU_texture_create_depth(int w, int h, char err_out[256]); GPUTexture *GPU_texture_create_vsm_shadow_map(int size, char err_out[256]); GPUTexture *GPU_texture_create_2D_procedural(int w, int h, const float *pixels, bool repeat, char err_out[256]); GPUTexture *GPU_texture_create_1D_procedural(int w, const float *pixels, char err_out[256]); +GPUTexture *GPU_texture_create_2D_multisample(int w, int h, const float *pixels, GPUHDRType hdr, int samples, char err_out[256]); +GPUTexture *GPU_texture_create_depth_multisample(int w, int h, int samples, char err_out[256]); GPUTexture *GPU_texture_from_blender(struct Image *ima, struct ImageUser *iuser, bool is_data, double time, int mipmap); GPUTexture *GPU_texture_from_preview(struct PreviewImage *prv, int mipmap); @@ -179,7 +181,7 @@ void GPU_framebuffer_blur(GPUFrameBuffer *fb, GPUTexture *tex, GPUFrameBuffer *b * - wrapper around framebuffer and texture for simple offscreen drawing * - changes size if graphics card can't support it */ -GPUOffScreen *GPU_offscreen_create(int width, int height, char err_out[256]); +GPUOffScreen *GPU_offscreen_create(int width, int height, int samples, char err_out[256]); void GPU_offscreen_free(GPUOffScreen *ofs); void GPU_offscreen_bind(GPUOffScreen *ofs, bool save); void GPU_offscreen_unbind(GPUOffScreen *ofs, bool restore); diff --git a/source/blender/gpu/intern/gpu_extensions.c b/source/blender/gpu/intern/gpu_extensions.c index e30eeeb..fc3a8d2 100644 --- a/source/blender/gpu/intern/gpu_extensions.c +++ b/source/blender/gpu/intern/gpu_extensions.c @@ -110,6 +110,7 @@ static struct GPUGlobal { int glslsupport; int extdisabled; int colordepth; + int samples_max; int npotdisabled; /* ATI 3xx-5xx (and more) chipsets support NPoT partially (== not enough) */ int dlistsdisabled; /* Legacy ATI driver does not support display lists well */ GPUDeviceType device; @@ -179,6 +180,7 @@ void gpu_extensions_init(void) glGetIntegerv(GL_GREEN_BITS, &g); glGetIntegerv(GL_BLUE_BITS, &b); GG.colordepth = r + g + b; /* assumes same depth for RGB */ + glGetIntegerv(GL_MAX_SAMPLES, &GG.samples_max); vendor = (const char *)glGetString(GL_VENDOR); renderer = (const char *)glGetString(GL_RENDERER); @@ -384,6 +386,7 @@ struct GPUTexture { int number; /* number for multitexture binding */ int refcount; /* reference count */ GLenum target; /* GL_TEXTURE_* */ + GLenum target_simple; /* same as target, (but no multisample) */ GLuint bindcode; /* opengl identifier for texture */ int fromblender; /* we got the texture from Blender */ @@ -421,7 +424,7 @@ static void GPU_glTexSubImageEmpty(GLenum target, GLenum format, int x, int y, i } static GPUTexture *GPU_texture_create_nD( - int w, int h, int n, const float *fpixels, int depth, GPUHDRType hdr_type, int components, + int w, int h, int n, const float *fpixels, int depth, GPUHDRType hdr_type, int components, int samples, char err_out[256]) { GPUTexture *tex; @@ -431,12 +434,17 @@ static GPUTexture *GPU_texture_create_nD( if (depth && !GLEW_ARB_depth_texture) return NULL; + if (samples) { + CLAMP_MAX(samples, GG.samples_max); + } + tex = MEM_callocN(sizeof(GPUTexture), "GPUTexture"); tex->w = tex->w_orig = w; tex->h = tex->h_orig = h; tex->number = -1; tex->refcount = 1; - tex->target = (n == 1)? GL_TEXTURE_1D: GL_TEXTURE_2D; + tex->target = (n == 1) ? GL_TEXTURE_1D : (samples ? GL_TEXTURE_2D_MULTISAMPLE : GL_TEXTURE_2D); + tex->target_simple = (n == 1) ? GL_TEXTURE_1D : GL_TEXTURE_2D; tex->depth = tex->depth_orig = depth; tex->fb_attachment = -1; @@ -523,8 +531,13 @@ static GPUTexture *GPU_texture_create_nD( } } else { - glTexImage2D(tex->target, 0, internalformat, tex->w, tex->h, 0, - format, type, NULL); + if (samples) { + glTexImage2DMultisample(tex->target, samples, internalformat, tex->w, tex->h, true); + } + else { + glTexImage2D(tex->target, 0, internalformat, tex->w, tex->h, 0, + format, type, NULL); + } if (fpixels) { glTexSubImage2D(tex->target, 0, 0, 0, w, h, @@ -541,23 +554,23 @@ static GPUTexture *GPU_texture_create_nD( MEM_freeN(pixels); if (depth) { - glTexParameteri(tex->target, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(tex->target, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri(tex->target, GL_TEXTURE_COMPARE_MODE_ARB, GL_COMPARE_R_TO_TEXTURE); - glTexParameteri(tex->target, GL_TEXTURE_COMPARE_FUNC_ARB, GL_LEQUAL); - glTexParameteri(tex->target, GL_DEPTH_TEXTURE_MODE_ARB, GL_INTENSITY); + glTexParameteri(tex->target_simple, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(tex->target_simple, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(tex->target_simple, GL_TEXTURE_COMPARE_MODE_ARB, GL_COMPARE_R_TO_TEXTURE); + glTexParameteri(tex->target_simple, GL_TEXTURE_COMPARE_FUNC_ARB, GL_LEQUAL); + glTexParameteri(tex->target_simple, GL_DEPTH_TEXTURE_MODE_ARB, GL_INTENSITY); } else { - glTexParameteri(tex->target, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(tex->target, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(tex->target_simple, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(tex->target_simple, GL_TEXTURE_MAG_FILTER, GL_LINEAR); } - if (tex->target != GL_TEXTURE_1D) { - glTexParameteri(tex->target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(tex->target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + if (tex->target_simple != GL_TEXTURE_1D) { + glTexParameteri(tex->target_simple, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE) @@ Diff output truncated at 10240 characters. @@ _______________________________________________ Bf-blender-cvs mailing list [email protected] http://lists.blender.org/mailman/listinfo/bf-blender-cvs
