GP: Fix render glitch when have collision with mesh
[blender.git] / source / blender / draw / engines / gpencil / gpencil_render.c
1 /*
2  * Copyright 2017, Blender Foundation.
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * Contributor(s): Antonio Vazquez
19  *
20  */
21
22 /** \file blender/draw/engines/gpencil/gpencil_render.c
23  *  \ingroup draw
24  */
25 #include "BLI_rect.h"
26
27 #include "DRW_engine.h"
28 #include "DRW_render.h"
29
30 #include "BKE_camera.h"
31 #include "BKE_object.h"
32
33 #include "DNA_gpencil_types.h"
34
35 #include "DEG_depsgraph_query.h"
36
37 #include "draw_mode_engines.h"
38
39 #include "RE_pipeline.h"
40
41 #include "gpencil_engine.h"
42
43 /* Get pixel size for render
44  * This function uses the same calculation used for viewport, because if use
45  * camera pixelsize, the result is not correct.
46  */
47 static float get_render_pixelsize(float persmat[4][4], int winx, int winy)
48 {
49         float v1[3], v2[3];
50         float len_px, len_sc;
51
52         v1[0] = persmat[0][0];
53         v1[1] = persmat[1][0];
54         v1[2] = persmat[2][0];
55
56         v2[0] = persmat[0][1];
57         v2[1] = persmat[1][1];
58         v2[2] = persmat[2][1];
59
60         len_px = 2.0f / sqrtf(min_ff(len_squared_v3(v1), len_squared_v3(v2)));
61         len_sc = (float)MAX2(winx, winy);
62
63         return len_px / len_sc;
64 }
65
66 /* init render data */
67 void GPENCIL_render_init(GPENCIL_Data *ved, RenderEngine *engine, struct Depsgraph *depsgraph)
68 {
69         GPENCIL_Data *vedata = (GPENCIL_Data *)ved;
70         GPENCIL_StorageList *stl = vedata->stl;
71         GPENCIL_FramebufferList *fbl = vedata->fbl;
72
73         Scene *scene = DEG_get_evaluated_scene(depsgraph);
74         const float *viewport_size = DRW_viewport_size_get();
75         const int size[2] = { (int)viewport_size[0], (int)viewport_size[1] };
76
77         /* In render mode the default framebuffer is not generated
78          * because there is no viewport. So we need to manually create one
79          * NOTE : use 32 bit format for precision in render mode.
80          */
81         /* create multiframe framebuffer for AA */
82         if (U.gpencil_multisamples > 0) {
83                 int rect_w = (int)viewport_size[0];
84                 int rect_h = (int)viewport_size[1];
85                 DRW_gpencil_multisample_ensure(vedata, rect_w, rect_h);
86         }
87
88         vedata->render_depth_tx = DRW_texture_pool_query_2D(
89                 size[0], size[1], GPU_DEPTH_COMPONENT24,
90                 &draw_engine_gpencil_type);
91         vedata->render_color_tx = DRW_texture_pool_query_2D(
92                 size[0], size[1], GPU_RGBA32F,
93                 &draw_engine_gpencil_type);
94         GPU_framebuffer_ensure_config(
95                 &fbl->main, {
96                     GPU_ATTACHMENT_TEXTURE(vedata->render_depth_tx),
97                     GPU_ATTACHMENT_TEXTURE(vedata->render_color_tx)
98                 });
99
100         /* Alloc transient data. */
101         if (!stl->g_data) {
102                 stl->g_data = MEM_callocN(sizeof(*stl->g_data), __func__);
103         }
104
105         /* Set the pers & view matrix. */
106         struct Object *camera = DEG_get_evaluated_object(depsgraph, RE_GetCamera(engine->re));
107         float frame = BKE_scene_frame_get(scene);
108         RE_GetCameraWindow(engine->re, camera, frame, stl->storage->winmat);
109         RE_GetCameraModelMatrix(engine->re, camera, stl->storage->viewinv);
110
111         invert_m4_m4(stl->storage->viewmat, stl->storage->viewinv);
112         mul_m4_m4m4(stl->storage->persmat, stl->storage->winmat, stl->storage->viewmat);
113         invert_m4_m4(stl->storage->persinv, stl->storage->persmat);
114         invert_m4_m4(stl->storage->wininv, stl->storage->winmat);
115
116         DRW_viewport_matrix_override_set(stl->storage->persmat, DRW_MAT_PERS);
117         DRW_viewport_matrix_override_set(stl->storage->persinv, DRW_MAT_PERSINV);
118         DRW_viewport_matrix_override_set(stl->storage->winmat, DRW_MAT_WIN);
119         DRW_viewport_matrix_override_set(stl->storage->wininv, DRW_MAT_WININV);
120         DRW_viewport_matrix_override_set(stl->storage->viewmat, DRW_MAT_VIEW);
121         DRW_viewport_matrix_override_set(stl->storage->viewinv, DRW_MAT_VIEWINV);
122
123         /* calculate pixel size for render */
124         stl->storage->render_pixsize = get_render_pixelsize(stl->storage->persmat, viewport_size[0], viewport_size[1]);
125         /* INIT CACHE */
126         GPENCIL_cache_init(vedata);
127 }
128
129 /* render all objects and select only grease pencil */
130 static void GPENCIL_render_cache(
131         void *vedata, struct Object *ob,
132         struct RenderEngine *UNUSED(engine), struct Depsgraph *UNUSED(depsgraph))
133 {
134         if (ob && ob->type == OB_GPENCIL) {
135                 if (DRW_object_visibility_in_active_context(ob) & OB_VISIBLE_SELF) {
136                         GPENCIL_cache_populate(vedata, ob);
137                 }
138         }
139 }
140
141 /* TODO: Reuse Eevee code in shared module instead to duplicate here */
142 static void GPENCIL_render_update_viewvecs(float invproj[4][4], float winmat[4][4], float(*r_viewvecs)[4])
143 {
144         /* view vectors for the corners of the view frustum.
145          * Can be used to recreate the world space position easily */
146         float view_vecs[4][4] = {
147                 {-1.0f, -1.0f, -1.0f, 1.0f},
148                 {1.0f, -1.0f, -1.0f, 1.0f},
149                 {-1.0f,  1.0f, -1.0f, 1.0f},
150                 {-1.0f, -1.0f,  1.0f, 1.0f}
151         };
152
153         /* convert the view vectors to view space */
154         const bool is_persp = (winmat[3][3] == 0.0f);
155         for (int i = 0; i < 4; i++) {
156                 mul_project_m4_v3(invproj, view_vecs[i]);
157                 /* normalized trick see:
158                  * http://www.derschmale.com/2014/01/26/reconstructing-positions-from-the-depth-buffer */
159                 if (is_persp) {
160                         /* Divide XY by Z. */
161                         mul_v2_fl(view_vecs[i], 1.0f / view_vecs[i][2]);
162                 }
163         }
164
165         /**
166          * If ortho : view_vecs[0] is the near-bottom-left corner of the frustum and
167          *            view_vecs[1] is the vector going from the near-bottom-left corner to
168          *            the far-top-right corner.
169          * If Persp : view_vecs[0].xy and view_vecs[1].xy are respectively the bottom-left corner
170          *            when Z = 1, and top-left corner if Z = 1.
171          *            view_vecs[0].z the near clip distance and view_vecs[1].z is the (signed)
172          *            distance from the near plane to the far clip plane.
173          */
174         copy_v4_v4(r_viewvecs[0], view_vecs[0]);
175
176         /* we need to store the differences */
177         r_viewvecs[1][0] = view_vecs[1][0] - view_vecs[0][0];
178         r_viewvecs[1][1] = view_vecs[2][1] - view_vecs[0][1];
179         r_viewvecs[1][2] = view_vecs[3][2] - view_vecs[0][2];
180 }
181
182 /* Update view_vecs */
183 static void GPENCIL_render_update_vecs(GPENCIL_Data *vedata)
184 {
185         GPENCIL_StorageList *stl = vedata->stl;
186
187         float invproj[4][4], winmat[4][4];
188         DRW_viewport_matrix_get(winmat, DRW_MAT_WIN);
189         DRW_viewport_matrix_get(invproj, DRW_MAT_WININV);
190
191         /* this is separated to keep function equal to Eevee for future reuse of same code */
192         GPENCIL_render_update_viewvecs(invproj, winmat, stl->storage->view_vecs);
193 }
194
195 /* read z-depth render result */
196 static void GPENCIL_render_result_z(struct RenderLayer *rl, const char *viewname, GPENCIL_Data *vedata, const rcti *rect)
197 {
198         const DRWContextState *draw_ctx = DRW_context_state_get();
199         ViewLayer *view_layer = draw_ctx->view_layer;
200         GPENCIL_StorageList *stl = vedata->stl;
201
202         if ((view_layer->passflag & SCE_PASS_Z) != 0) {
203                 RenderPass *rp = RE_pass_find_by_name(rl, RE_PASSNAME_Z, viewname);
204
205                 GPU_framebuffer_read_depth(vedata->fbl->main, rect->xmin, rect->ymin, BLI_rcti_size_x(rect), BLI_rcti_size_y(rect), rp->rect);
206
207                 bool is_persp = DRW_viewport_is_persp_get();
208
209                 GPENCIL_render_update_vecs(vedata);
210
211                 /* Convert ogl depth [0..1] to view Z [near..far] */
212                 for (int i = 0; i < BLI_rcti_size_x(rect) * BLI_rcti_size_y(rect); i++) {
213                         if (rp->rect[i] == 1.0f) {
214                                 rp->rect[i] = 1e10f; /* Background */
215                         }
216                         else {
217                                 if (is_persp) {
218                                         rp->rect[i] = rp->rect[i] * 2.0f - 1.0f;
219                                         rp->rect[i] = stl->storage->winmat[3][2] / (rp->rect[i] + stl->storage->winmat[2][2]);
220                                 }
221                                 else {
222                                         rp->rect[i] = -stl->storage->view_vecs[0][2] + rp->rect[i] * -stl->storage->view_vecs[1][2];
223                                 }
224                         }
225                 }
226         }
227 }
228
229 /* read combined render result */
230 static void GPENCIL_render_result_combined(struct RenderLayer *rl, const char *viewname, GPENCIL_Data *vedata, const rcti *rect)
231 {
232         RenderPass *rp = RE_pass_find_by_name(rl, RE_PASSNAME_COMBINED, viewname);
233         GPENCIL_FramebufferList *fbl = ((GPENCIL_Data *)vedata)->fbl;
234
235         GPU_framebuffer_bind(fbl->main);
236         GPU_framebuffer_read_color(vedata->fbl->main, rect->xmin, rect->ymin, BLI_rcti_size_x(rect), BLI_rcti_size_y(rect), 4, 0, rp->rect);
237 }
238
239 /* helper to blend pixels */
240 static void blend_pixel(float src[4], float dst[4])
241 {
242         float alpha = src[3];
243
244         /* use blend: GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA */
245         dst[0] = (src[0] * alpha) + (dst[0] * (1.0f - alpha));
246         dst[1] = (src[1] * alpha) + (dst[1] * (1.0f - alpha));
247         dst[2] = (src[2] * alpha) + (dst[2] * (1.0f - alpha));
248 }
249
250 /* render grease pencil to image */
251 void GPENCIL_render_to_image(void *vedata, RenderEngine *engine, struct RenderLayer *render_layer, const rcti *rect)
252 {
253         const char *viewname = RE_GetActiveRenderView(engine->re);
254         const DRWContextState *draw_ctx = DRW_context_state_get();
255         int imgsize = BLI_rcti_size_x(rect) * BLI_rcti_size_y(rect);
256
257         /* save previous render data */
258         RenderPass *rpass_color_src = RE_pass_find_by_name(render_layer, RE_PASSNAME_COMBINED, viewname);
259         RenderPass *rpass_depth_src = RE_pass_find_by_name(render_layer, RE_PASSNAME_Z, viewname);
260         float *src_rect_color_data = NULL;
261         float *src_rect_depth_data = NULL;
262         if ((rpass_color_src) && (rpass_depth_src) && (rpass_color_src->rect) && (rpass_depth_src->rect)) {
263                 src_rect_color_data = MEM_dupallocN(rpass_color_src->rect);
264                 src_rect_depth_data = MEM_dupallocN(rpass_depth_src->rect);
265         }
266         else {
267                 /* TODO: put this message in a better place */
268                 printf("Warning: To render grease pencil, enable Combined and Z passes.\n");
269         }
270
271         GPENCIL_engine_init(vedata);
272         GPENCIL_render_init(vedata, engine, draw_ctx->depsgraph);
273
274         GPENCIL_StorageList *stl = ((GPENCIL_Data *)vedata)->stl;
275         Object *camera = DEG_get_evaluated_object(draw_ctx->depsgraph, RE_GetCamera(engine->re));
276         stl->storage->camera = camera; /* save current camera */
277
278         GPENCIL_FramebufferList *fbl = ((GPENCIL_Data *)vedata)->fbl;
279         if (fbl->main) {
280                 GPU_framebuffer_texture_attach(fbl->main, ((GPENCIL_Data *)vedata)->render_depth_tx, 0, 0);
281                 GPU_framebuffer_texture_attach(fbl->main, ((GPENCIL_Data *)vedata)->render_color_tx, 0, 0);
282                 /* clean first time the buffer */
283                 float clearcol[4] = { 0.0f, 0.0f, 0.0f, 0.0f };
284                 GPU_framebuffer_bind(fbl->main);
285                 GPU_framebuffer_clear_color_depth(fbl->main, clearcol, 1.0f);
286         }
287
288         /* loop all objects and draw */
289         DRW_render_object_iter(vedata, engine, draw_ctx->depsgraph, GPENCIL_render_cache);
290
291         GPENCIL_cache_finish(vedata);
292         GPENCIL_draw_scene(vedata);
293
294         /* combined data */
295         GPENCIL_render_result_combined(render_layer, viewname, vedata, rect);
296         /* z-depth data */
297         GPENCIL_render_result_z(render_layer, viewname, vedata, rect);
298
299         /* detach textures */
300          if (fbl->main) {
301                 GPU_framebuffer_texture_detach(fbl->main, ((GPENCIL_Data *)vedata)->render_depth_tx);
302                 GPU_framebuffer_texture_detach(fbl->main, ((GPENCIL_Data *)vedata)->render_color_tx);
303          }
304
305         /* merge previous render image with new GP image */
306         if (src_rect_color_data) {
307                 RenderPass *rpass_color_gp = RE_pass_find_by_name(render_layer, RE_PASSNAME_COMBINED, viewname);
308                 RenderPass *rpass_depth_gp = RE_pass_find_by_name(render_layer, RE_PASSNAME_Z, viewname);
309                 float *gp_rect_color_data = rpass_color_gp->rect;
310                 float *gp_rect_depth_data = rpass_depth_gp->rect;
311                 float *gp_pixel_rgba;
312                 float *gp_pixel_depth;
313                 float *src_pixel_rgba;
314                 float *src_pixel_depth;
315                 float tmp[4];
316
317                 for (int i = 0; i < imgsize; i++) {
318                         gp_pixel_rgba = &gp_rect_color_data[i * 4];
319                         gp_pixel_depth = &gp_rect_depth_data[i];
320
321                         src_pixel_rgba = &src_rect_color_data[i * 4];
322                         src_pixel_depth = &src_rect_depth_data[i];
323
324                         /* check grease pencil render transparency */
325                         if (gp_pixel_rgba[3] > 0.0f) {
326                                 copy_v4_v4(tmp, gp_pixel_rgba);
327                                 if (src_pixel_rgba[3] > 0.0f) {
328                                         /* copy source color on back */
329                                         copy_v4_v4(gp_pixel_rgba, src_pixel_rgba);
330                                         /* check z-depth */
331                                         if (gp_pixel_depth[0] > src_pixel_depth[0]) {
332                                                 /* copy source z-depth */
333                                                 gp_pixel_depth[0] = src_pixel_depth[0];
334                                                 /* blend gp render */
335                                                 blend_pixel(tmp, gp_pixel_rgba);
336                                                 /* blend object on top */
337                                                 blend_pixel(src_pixel_rgba, gp_pixel_rgba);
338                                         }
339                                         else {
340                                                 /* blend gp render */
341                                                 if (tmp[3] < 1.0f) {
342                                                         blend_pixel(tmp, gp_pixel_rgba);
343                                                 }
344                                                 else {
345                                                         copy_v4_v4(gp_pixel_rgba, tmp);
346                                                 }
347                                         }
348                                 }
349                         }
350                         else {
351                                 copy_v4_v4(gp_pixel_rgba, src_pixel_rgba);
352                                 gp_pixel_depth[0] = src_pixel_depth[0];
353                         }
354                 }
355
356                 /* free memory */
357                 MEM_SAFE_FREE(src_rect_color_data);
358                 MEM_SAFE_FREE(src_rect_depth_data);
359         }
360 }