Blender V4.3
viewport_engine.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2011-2022 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
5#include "viewport_engine.hh"
6#include "camera.hh"
7
8#include <pxr/base/gf/camera.h>
9#include <pxr/imaging/glf/drawTarget.h>
10#include <pxr/usd/usdGeom/camera.h>
11
12#include "DNA_scene_types.h"
13#include "DNA_screen_types.h"
14#include "DNA_vec_types.h" /* This include must be before `BKE_camera.h` due to `rctf` type. */
15#include "DNA_view3d_types.h"
16
17#include "BLI_math_matrix.h"
18#include "BLI_time.h"
19#include "BLI_timecode.h"
20
21#include "BKE_camera.h"
22#include "BKE_context.hh"
23
24#include "GPU_matrix.hh"
25
26#include "RE_engine.h"
27
28namespace blender::render::hydra {
29
33 pxr::GfVec4i border;
34 pxr::GfCamera camera;
35
36 ViewSettings(bContext *context);
37
38 int width();
39 int height();
40};
41
43{
44 View3D *view3d = CTX_wm_view3d(context);
45 RegionView3D *region_data = static_cast<RegionView3D *>(CTX_wm_region_data(context));
46 ARegion *region = CTX_wm_region(context);
47
48 screen_width = region->winx;
49 screen_height = region->winy;
50
51 Scene *scene = CTX_data_scene(context);
52
53 /* Getting render border. */
54 int x1 = 0, y1 = 0;
55 int x2 = screen_width, y2 = screen_height;
56
57 if (region_data->persp == RV3D_CAMOB) {
58 if (scene->r.mode & R_BORDER) {
59 Object *camera_obj = scene->camera;
60
61 float camera_points[4][3];
62 BKE_camera_view_frame(scene, static_cast<Camera *>(camera_obj->data), camera_points);
63
64 float screen_points[4][2];
65 for (int i = 0; i < 4; i++) {
66 float world_location[] = {
67 camera_points[i][0], camera_points[i][1], camera_points[i][2], 1.0f};
68 mul_m4_v4(camera_obj->object_to_world().ptr(), world_location);
69 mul_m4_v4(region_data->persmat, world_location);
70
71 if (world_location[3] > 0.0) {
72 screen_points[i][0] = screen_width * 0.5f +
73 screen_width * 0.5f * (world_location[0] / world_location[3]);
74 screen_points[i][1] = screen_height * 0.5f +
75 screen_height * 0.5f * (world_location[1] / world_location[3]);
76 }
77 }
78
79 /* Getting camera view region. */
80 float x1_f = std::min(
81 {screen_points[0][0], screen_points[1][0], screen_points[2][0], screen_points[3][0]});
82 float x2_f = std::max(
83 {screen_points[0][0], screen_points[1][0], screen_points[2][0], screen_points[3][0]});
84 float y1_f = std::min(
85 {screen_points[0][1], screen_points[1][1], screen_points[2][1], screen_points[3][1]});
86 float y2_f = std::max(
87 {screen_points[0][1], screen_points[1][1], screen_points[2][1], screen_points[3][1]});
88
89 /* Adjusting region to border. */
90 float x = x1_f, y = y1_f;
91 float dx = x2_f - x1_f, dy = y2_f - y1_f;
92
93 x1 = x + scene->r.border.xmin * dx;
94 x2 = x + scene->r.border.xmax * dx;
95 y1 = y + scene->r.border.ymin * dy;
96 y2 = y + scene->r.border.ymax * dy;
97
98 /* Adjusting to region screen resolution. */
99 x1 = std::max(std::min(x1, screen_width), 0);
100 x2 = std::max(std::min(x2, screen_width), 0);
101 y1 = std::max(std::min(y1, screen_height), 0);
102 y2 = std::max(std::min(y2, screen_height), 0);
103 }
104 }
105 else {
106 if (view3d->flag2 & V3D_RENDER_BORDER) {
107 x1 = view3d->render_border.xmin * screen_width;
108 x2 = view3d->render_border.xmax * screen_width;
109 y1 = view3d->render_border.ymin * screen_height;
110 y2 = view3d->render_border.ymax * screen_height;
111 }
112 }
113
114 border = pxr::GfVec4i(x1, y1, x2, y2);
115
117 view3d,
118 region,
119 pxr::GfVec4f(float(border[0]) / screen_width,
120 float(border[1]) / screen_height,
121 float(width()) / screen_width,
122 float(height()) / screen_height));
123}
124
126{
127 return border[2] - border[0];
128}
129
131{
132 return border[3] - border[1];
133}
134
136{
137 float coords[8] = {0.0, 0.0, 1.0, 0.0, 1.0, 1.0, 0.0, 1.0};
138
139 GPUVertFormat format = {0};
143 GPU_vertbuf_data_alloc(*vbo, 4);
144 GPU_vertbuf_attr_fill(vbo, 0, coords);
145 GPU_vertbuf_attr_fill(vbo, 1, coords);
146
148}
149
151{
152 if (texture_) {
153 GPU_texture_free(texture_);
154 }
155 GPU_batch_discard(batch_);
156}
157
158void DrawTexture::write_data(int width, int height, const void *data)
159{
160 if (texture_ && width == GPU_texture_width(texture_) && height == GPU_texture_height(texture_)) {
161 if (data) {
162 GPU_texture_update(texture_, GPU_DATA_FLOAT, data);
163 }
164 return;
165 }
166
167 if (texture_) {
168 GPU_texture_free(texture_);
169 }
170
171 texture_ = GPU_texture_create_2d("tex_hydra_render_viewport",
172 width,
173 height,
174 1,
177 (float *)data);
178}
179
180void DrawTexture::draw(GPUShader *shader, const pxr::GfVec4d &viewport, GPUTexture *tex)
181{
182 if (!tex) {
183 tex = texture_;
184 }
185 int slot = GPU_shader_get_sampler_binding(shader, "image");
186 GPU_texture_bind(tex, slot);
187 GPU_shader_uniform_1i(shader, "image", slot);
188
190 GPU_matrix_translate_2f(viewport[0], viewport[1]);
191 GPU_matrix_scale_2f(viewport[2] - viewport[0], viewport[3] - viewport[1]);
192 GPU_batch_set_shader(batch_, shader);
193 GPU_batch_draw(batch_);
195}
196
197GPUTexture *DrawTexture::texture() const
198{
199 return texture_;
200}
201
203{
204 ViewSettings view_settings(context_);
205 if (view_settings.width() * view_settings.height() == 0) {
206 return;
207 };
208
209 free_camera_delegate_->SetCamera(view_settings.camera);
210
211 pxr::GfVec4d viewport(0.0, 0.0, view_settings.width(), view_settings.height());
212 render_task_delegate_->set_viewport(viewport);
214 light_tasks_delegate_->set_viewport(viewport);
215 }
216
217 render_task_delegate_->add_aov(pxr::HdAovTokens->color);
218 render_task_delegate_->add_aov(pxr::HdAovTokens->depth);
219
220 GPUFrameBuffer *view_framebuffer = GPU_framebuffer_active_get();
221 render_task_delegate_->bind();
222
223 auto t = tasks();
224 engine_->Execute(render_index_.get(), &t);
225
226 render_task_delegate_->unbind();
227
228 GPU_framebuffer_bind(view_framebuffer);
230 GPU_shader_bind(shader);
231
232 pxr::GfVec4d draw_viewport(view_settings.border[0],
233 view_settings.border[1],
234 view_settings.border[2],
235 view_settings.border[3]);
236 GPURenderTaskDelegate *gpu_task = dynamic_cast<GPURenderTaskDelegate *>(
238 if (gpu_task) {
239 draw_texture_.draw(shader, draw_viewport, gpu_task->aov_texture(pxr::HdAovTokens->color));
240 }
241 else {
242 draw_texture_.write_data(view_settings.width(), view_settings.height(), nullptr);
243 render_task_delegate_->read_aov(pxr::HdAovTokens->color, draw_texture_.texture());
244 draw_texture_.draw(shader, draw_viewport);
245 }
246
248
249 if (renderer_percent_done() == 0.0f) {
250 time_begin_ = BLI_time_now_seconds();
251 }
252
253 char elapsed_time[32];
254
256 elapsed_time, sizeof(elapsed_time), BLI_time_now_seconds() - time_begin_);
257
258 float percent_done = renderer_percent_done();
259 if (!render_task_delegate_->is_converged()) {
260 notify_status(percent_done / 100.0,
261 std ::string("Time: ") + elapsed_time +
262 " | Done: " + std::to_string(int(percent_done)) + "%",
263 "Render");
265 }
266 else {
267 notify_status(percent_done / 100.0, std::string("Time: ") + elapsed_time, "Rendering Done");
268 }
269}
270
272{
273 context_ = context;
274 render();
275}
276
277void ViewportEngine::notify_status(float /*progress*/,
278 const std::string &info,
279 const std::string &status)
280{
281 RE_engine_update_stats(bl_engine_, status.c_str(), info.c_str());
282}
283
284} // namespace blender::render::hydra
Camera data-block and utility functions.
void BKE_camera_view_frame(const struct Scene *scene, const struct Camera *camera, float r_vec[4][3])
void * CTX_wm_region_data(const bContext *C)
Depsgraph * CTX_data_ensure_evaluated_depsgraph(const bContext *C)
Scene * CTX_data_scene(const bContext *C)
ARegion * CTX_wm_region(const bContext *C)
View3D * CTX_wm_view3d(const bContext *C)
void mul_m4_v4(const float mat[4][4], float r[4])
Platform independent time functions.
double BLI_time_now_seconds(void)
Definition time.c:65
size_t BLI_timecode_string_from_time_simple(char *str, size_t maxncpy, double time_seconds) ATTR_NONNULL()
Definition timecode.c:171
@ R_BORDER
@ RV3D_CAMOB
@ V3D_RENDER_BORDER
blender::gpu::Batch * GPU_batch_create_ex(GPUPrimType primitive_type, blender::gpu::VertBuf *vertex_buf, blender::gpu::IndexBuf *index_buf, eGPUBatchFlag owns_flag)
Definition gpu_batch.cc:56
void GPU_batch_discard(blender::gpu::Batch *batch)
void GPU_batch_set_shader(blender::gpu::Batch *batch, GPUShader *shader)
void GPU_batch_draw(blender::gpu::Batch *batch)
@ GPU_BATCH_OWNS_VBO
Definition GPU_batch.hh:42
GPUFrameBuffer * GPU_framebuffer_active_get()
void GPU_framebuffer_bind(GPUFrameBuffer *framebuffer)
void GPU_matrix_scale_2f(float x, float y)
void GPU_matrix_push()
void GPU_matrix_pop()
void GPU_matrix_translate_2f(float x, float y)
@ GPU_PRIM_TRI_FAN
int GPU_shader_get_sampler_binding(GPUShader *shader, const char *name)
void GPU_shader_uniform_1i(GPUShader *sh, const char *name, int value)
void GPU_shader_bind(GPUShader *shader)
void GPU_shader_unbind()
GPUShader * GPU_shader_get_builtin_shader(eGPUBuiltinShader shader)
@ GPU_SHADER_3D_IMAGE
int GPU_texture_height(const GPUTexture *texture)
void GPU_texture_bind(GPUTexture *texture, int unit)
GPUTexture * GPU_texture_create_2d(const char *name, int width, int height, int mip_len, eGPUTextureFormat format, eGPUTextureUsage usage, const float *data)
void GPU_texture_free(GPUTexture *texture)
int GPU_texture_width(const GPUTexture *texture)
@ GPU_DATA_FLOAT
@ GPU_TEXTURE_USAGE_GENERAL
void GPU_texture_update(GPUTexture *texture, eGPUDataFormat data_format, const void *data)
#define GPU_vertbuf_create_with_format(format)
void GPU_vertbuf_attr_fill(blender::gpu::VertBuf *, uint a_idx, const void *data)
void GPU_vertbuf_data_alloc(blender::gpu::VertBuf &verts, uint v_len)
@ GPU_FETCH_FLOAT
uint GPU_vertformat_attr_add(GPUVertFormat *, const char *name, GPUVertCompType, uint comp_len, GPUVertFetchMode)
@ GPU_COMP_F32
@ RE_ENGINE_DO_DRAW
Definition RE_engine.h:65
struct GPUShader GPUShader
void write_data(int width, int height, const void *data)
void draw(GPUShader *shader, const pxr::GfVec4d &viewport, GPUTexture *tex=nullptr)
RenderEngine * bl_engine_
Definition engine.hh:36
std::unique_ptr< pxr::HdxFreeCameraSceneDelegate > free_camera_delegate_
Definition engine.hh:51
pxr::HdTaskSharedPtrVector tasks()
std::unique_ptr< RenderTaskDelegate > render_task_delegate_
Definition engine.hh:50
std::unique_ptr< pxr::HdRenderIndex > render_index_
Definition engine.hh:45
std::unique_ptr< LightTasksDelegate > light_tasks_delegate_
Definition engine.hh:52
std::unique_ptr< pxr::HdEngine > engine_
Definition engine.hh:53
GPUTexture * aov_texture(pxr::TfToken const &aov_key)
void notify_status(float progress, const std::string &title, const std::string &info) override
additional_info("compositor_sum_float_shared") .push_constant(Type additional_info("compositor_sum_float_shared") .push_constant(Type GPU_RGBA32F
void RE_engine_update_stats(RenderEngine *engine, const char *stats, const char *info)
format
static pxr::GfCamera gf_camera(const CameraParams &params, const pxr::GfVec2i &res, const pxr::GfVec4f &border)
float persmat[4][4]
rctf render_border
float xmax
float xmin
float ymax
float ymin