doxygen: add newline after \file
[blender.git] / source / blender / draw / engines / workbench / workbench_render.c
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  *
16  * Copyright 2016, Blender Foundation.
17  */
18
19 /** \file
20  * \ingroup draw_engine
21  *
22  * Render functions for final render output.
23  */
24
25 #include "BLI_rect.h"
26
27 #include "BKE_report.h"
28
29 #include "DRW_render.h"
30
31 #include "GPU_shader.h"
32
33 #include "DEG_depsgraph.h"
34 #include "DEG_depsgraph_query.h"
35
36 #include "RE_pipeline.h"
37
38 #include "workbench_private.h"
39
40 static void workbench_render_deferred_cache(
41         void *vedata, struct Object *ob,
42         struct RenderEngine *UNUSED(engine), struct Depsgraph *UNUSED(depsgraph))
43 {
44         workbench_deferred_solid_cache_populate(vedata, ob);
45 }
46
47 static void workbench_render_forward_cache(
48         void *vedata, struct Object *ob,
49         struct RenderEngine *UNUSED(engine), struct Depsgraph *UNUSED(depsgraph))
50 {
51         workbench_forward_cache_populate(vedata, ob);
52 }
53
54 static void workbench_render_matrices_init(RenderEngine *engine, Depsgraph *depsgraph)
55 {
56         /* TODO(sergey): Shall render hold pointer to an evaluated camera instead? */
57         Scene *scene = DEG_get_evaluated_scene(depsgraph);
58         struct Object *ob_camera_eval = DEG_get_evaluated_object(depsgraph, RE_GetCamera(engine->re));
59         float frame = BKE_scene_frame_get(scene);
60
61         /* Set the persective, view and window matrix. */
62         float winmat[4][4], wininv[4][4];
63         float viewmat[4][4], viewinv[4][4];
64         float persmat[4][4], persinv[4][4];
65
66         RE_GetCameraWindow(engine->re, ob_camera_eval, frame, winmat);
67         RE_GetCameraModelMatrix(engine->re, ob_camera_eval, viewinv);
68
69         invert_m4_m4(viewmat, viewinv);
70         mul_m4_m4m4(persmat, winmat, viewmat);
71         invert_m4_m4(persinv, persmat);
72         invert_m4_m4(wininv, winmat);
73
74         DRW_viewport_matrix_override_set(persmat, DRW_MAT_PERS);
75         DRW_viewport_matrix_override_set(persinv, DRW_MAT_PERSINV);
76         DRW_viewport_matrix_override_set(winmat, DRW_MAT_WIN);
77         DRW_viewport_matrix_override_set(wininv, DRW_MAT_WININV);
78         DRW_viewport_matrix_override_set(viewmat, DRW_MAT_VIEW);
79         DRW_viewport_matrix_override_set(viewinv, DRW_MAT_VIEWINV);
80 }
81
82 static bool workbench_render_framebuffers_init(void)
83 {
84         /* For image render, allocate own buffers because we don't have a viewport. */
85         const float *viewport_size = DRW_viewport_size_get();
86         const int size[2] = {(int)viewport_size[0], (int)viewport_size[1]};
87
88         DefaultTextureList *dtxl = DRW_viewport_texture_list_get();
89         dtxl->color = GPU_texture_create_2D(size[0], size[1], GPU_RGBA8, NULL, NULL);
90         dtxl->depth = GPU_texture_create_2D(size[0], size[1], GPU_DEPTH24_STENCIL8, NULL, NULL);
91
92         if (!(dtxl->depth && dtxl->color)) {
93                 return false;
94         }
95
96         DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get();
97
98         GPU_framebuffer_ensure_config(&dfbl->default_fb, {
99                 GPU_ATTACHMENT_TEXTURE(dtxl->depth),
100                 GPU_ATTACHMENT_TEXTURE(dtxl->color)
101         });
102
103         GPU_framebuffer_ensure_config(&dfbl->depth_only_fb, {
104                 GPU_ATTACHMENT_TEXTURE(dtxl->depth),
105                 GPU_ATTACHMENT_NONE
106         });
107
108         GPU_framebuffer_ensure_config(&dfbl->color_only_fb, {
109                 GPU_ATTACHMENT_NONE,
110                 GPU_ATTACHMENT_TEXTURE(dtxl->color)
111         });
112
113         bool ok = true;
114         ok = ok && GPU_framebuffer_check_valid(dfbl->default_fb, NULL);
115         ok = ok && GPU_framebuffer_check_valid(dfbl->color_only_fb, NULL);
116         ok = ok && GPU_framebuffer_check_valid(dfbl->depth_only_fb, NULL);
117
118         return ok;
119 }
120
121 static void workbench_render_framebuffers_finish(void)
122 {
123 }
124
125 void workbench_render(WORKBENCH_Data *data, RenderEngine *engine, RenderLayer *render_layer, const rcti *rect)
126 {
127         const DRWContextState *draw_ctx = DRW_context_state_get();
128         const Scene *scene = draw_ctx->scene;
129         Depsgraph *depsgraph = draw_ctx->depsgraph;
130         workbench_render_matrices_init(engine, depsgraph);
131
132         if (!workbench_render_framebuffers_init()) {
133                 RE_engine_report(engine, RPT_ERROR, "Failed to allocate OpenGL buffers");
134                 return;
135         }
136
137         const bool deferred = (scene->display.shading.flag & XRAY_FLAG(&scene->display)) == 0;
138
139         if (deferred) {
140                 /* Init engine. */
141                 workbench_deferred_engine_init(data);
142
143                 /* Init objects. */
144                 workbench_deferred_cache_init(data);
145                 DRW_render_object_iter(data, engine, depsgraph, workbench_render_deferred_cache);
146                 workbench_deferred_cache_finish(data);
147                 DRW_render_instance_buffer_finish();
148
149                 /* Draw. */
150                 int num_samples = workbench_taa_calculate_num_iterations(data);
151                 for (int sample = 0; sample < num_samples; sample++) {
152                         if (RE_engine_test_break(engine)) {
153                                 break;
154                         }
155                         /* TODO: Save matrices instead of recomputing them for each samples. */
156                         workbench_render_matrices_init(engine, depsgraph);
157
158                         workbench_deferred_draw_background(data);
159                         workbench_deferred_draw_scene(data);
160                 }
161
162                 workbench_deferred_draw_finish(data);
163         }
164         else {
165                 /* Init engine. */
166                 workbench_forward_engine_init(data);
167
168                 /* Init objects. */
169                 workbench_forward_cache_init(data);
170                 DRW_render_object_iter(data, engine, depsgraph, workbench_render_forward_cache);
171                 workbench_forward_cache_finish(data);
172                 DRW_render_instance_buffer_finish();
173
174                 /* Draw. */
175                 int num_samples = workbench_taa_calculate_num_iterations(data);
176                 for (int sample = 0; sample < num_samples; sample++) {
177                         if (RE_engine_test_break(engine)) {
178                                 break;
179                         }
180
181                         workbench_forward_draw_background(data);
182                         workbench_forward_draw_scene(data);
183                 }
184
185                 workbench_forward_draw_finish(data);
186         }
187
188         /* Write render output. */
189         const char *viewname = RE_GetActiveRenderView(engine->re);
190         RenderPass *rp = RE_pass_find_by_name(render_layer, RE_PASSNAME_COMBINED, viewname);
191
192         DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get();
193         GPU_framebuffer_bind(dfbl->color_only_fb);
194         GPU_framebuffer_read_color(dfbl->color_only_fb,
195                                    rect->xmin, rect->ymin,
196                                    BLI_rcti_size_x(rect), BLI_rcti_size_y(rect),
197                                    4, 0, rp->rect);
198
199         workbench_render_framebuffers_finish();
200 }
201
202 void workbench_render_update_passes(RenderEngine *engine, Scene *scene, ViewLayer *view_layer)
203 {
204         RE_engine_register_pass(engine, scene, view_layer, RE_PASSNAME_COMBINED, 4, "RGBA", SOCK_RGBA);
205 }