Blender V5.0
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#include "GPU_texture.hh"
26
28
29#include "RE_engine.h"
30
31namespace blender::render::hydra {
32
36 pxr::GfVec4i border;
37 pxr::GfCamera camera;
38
39 ViewSettings(bContext *context);
40
41 int width();
42 int height();
43};
44
46{
47 View3D *view3d = CTX_wm_view3d(context);
48 RegionView3D *region_data = static_cast<RegionView3D *>(CTX_wm_region_data(context));
49 ARegion *region = CTX_wm_region(context);
52
53 screen_width = region->winx;
54 screen_height = region->winy;
55
56 /* Getting render border. */
57 int x1 = 0, y1 = 0;
58 int x2 = screen_width, y2 = screen_height;
59
60 if (region_data->persp == RV3D_CAMOB) {
61 Object *camera_obj = scene->camera;
62 if ((scene->r.mode & R_BORDER) && camera_obj && camera_obj->type == OB_CAMERA) {
63 float camera_points[4][3];
64 BKE_camera_view_frame(scene, static_cast<Camera *>(camera_obj->data), camera_points);
65
66 float screen_points[4][2];
67 for (int i = 0; i < 4; i++) {
68 float world_location[] = {
69 camera_points[i][0], camera_points[i][1], camera_points[i][2], 1.0f};
70 mul_m4_v4(camera_obj->object_to_world().ptr(), world_location);
71 mul_m4_v4(region_data->persmat, world_location);
72
73 if (world_location[3] > 0.0) {
74 screen_points[i][0] = screen_width * 0.5f +
75 screen_width * 0.5f * (world_location[0] / world_location[3]);
76 screen_points[i][1] = screen_height * 0.5f +
77 screen_height * 0.5f * (world_location[1] / world_location[3]);
78 }
79 }
80
81 /* Getting camera view region. */
82 float x1_f = std::min(
83 {screen_points[0][0], screen_points[1][0], screen_points[2][0], screen_points[3][0]});
84 float x2_f = std::max(
85 {screen_points[0][0], screen_points[1][0], screen_points[2][0], screen_points[3][0]});
86 float y1_f = std::min(
87 {screen_points[0][1], screen_points[1][1], screen_points[2][1], screen_points[3][1]});
88 float y2_f = std::max(
89 {screen_points[0][1], screen_points[1][1], screen_points[2][1], screen_points[3][1]});
90
91 /* Adjusting region to border. */
92 float x = x1_f, y = y1_f;
93 float dx = x2_f - x1_f, dy = y2_f - y1_f;
94
95 x1 = x + scene->r.border.xmin * dx;
96 x2 = x + scene->r.border.xmax * dx;
97 y1 = y + scene->r.border.ymin * dy;
98 y2 = y + scene->r.border.ymax * dy;
99
100 /* Adjusting to region screen resolution. */
101 x1 = std::max(std::min(x1, screen_width), 0);
102 x2 = std::max(std::min(x2, screen_width), 0);
103 y1 = std::max(std::min(y1, screen_height), 0);
104 y2 = std::max(std::min(y2, screen_height), 0);
105 }
106 }
107 else {
108 if (view3d->flag2 & V3D_RENDER_BORDER) {
109 x1 = view3d->render_border.xmin * screen_width;
110 x2 = view3d->render_border.xmax * screen_width;
111 y1 = view3d->render_border.ymin * screen_height;
112 y2 = view3d->render_border.ymax * screen_height;
113 }
114 }
115
116 border = pxr::GfVec4i(x1, y1, x2, y2);
117
119 view3d,
120 region,
121 pxr::GfVec4f(float(border[0]) / screen_width,
122 float(border[1]) / screen_height,
123 float(width()) / screen_width,
124 float(height()) / screen_height));
125}
126
128{
129 return border[2] - border[0];
130}
131
133{
134 return border[3] - border[1];
135}
136
138{
139 float coords[8] = {0.0, 0.0, 1.0, 0.0, 1.0, 1.0, 0.0, 1.0};
140
141 GPUVertFormat format = {0};
142 GPU_vertformat_attr_add(&format, "pos", gpu::VertAttrType::SFLOAT_32_32);
143 GPU_vertformat_attr_add(&format, "texCoord", gpu::VertAttrType::SFLOAT_32_32);
145 GPU_vertbuf_data_alloc(*vbo, 4);
146 GPU_vertbuf_attr_fill(vbo, 0, coords);
147 GPU_vertbuf_attr_fill(vbo, 1, coords);
148
150}
151
153{
154 if (texture_) {
155 GPU_texture_free(texture_);
156 }
157 GPU_batch_discard(batch_);
158}
159
160void DrawTexture::create_from_buffer(pxr::HdRenderBuffer *buffer)
161{
162 if (buffer == nullptr) {
163 return;
164 }
165
166 blender::gpu::TextureFormat texture_format;
167 eGPUDataFormat data_format;
168
169 if (buffer->GetFormat() == pxr::HdFormat::HdFormatFloat16Vec4) {
170 texture_format = blender::gpu::TextureFormat::SFLOAT_16_16_16_16;
171 data_format = GPU_DATA_HALF_FLOAT;
172 }
173 else {
174 texture_format = blender::gpu::TextureFormat::SFLOAT_32_32_32_32;
175 data_format = GPU_DATA_FLOAT;
176 }
177
178 if (texture_ && (GPU_texture_width(texture_) != buffer->GetWidth() ||
179 GPU_texture_height(texture_) != buffer->GetHeight() ||
180 GPU_texture_format(texture_) != texture_format))
181 {
182 GPU_texture_free(texture_);
183 texture_ = nullptr;
184 }
185
186 if (texture_ == nullptr) {
187 texture_ = GPU_texture_create_2d("tex_hydra_render_viewport",
188 buffer->GetWidth(),
189 buffer->GetHeight(),
190 1,
191 texture_format,
193 nullptr);
194 }
195
196 void *data = buffer->Map();
197 GPU_texture_update(texture_, data_format, data);
198 buffer->Unmap();
199}
200
202 const pxr::GfVec4d &viewport,
204{
205 if (!tex) {
206 tex = texture_;
207 }
208 int slot = GPU_shader_get_sampler_binding(shader, "image");
209 GPU_texture_bind(tex, slot);
210 GPU_shader_uniform_1i(shader, "image", slot);
211
213 GPU_matrix_translate_2f(viewport[0], viewport[1]);
214 GPU_matrix_scale_2f(viewport[2] - viewport[0], viewport[3] - viewport[1]);
215 GPU_batch_set_shader(batch_, shader);
216 GPU_batch_draw(batch_);
218}
219
221{
222 return texture_;
223}
224
226{
227 ViewSettings view_settings(context_);
228 if (view_settings.width() * view_settings.height() == 0) {
229 return;
230 };
231
232 free_camera_delegate_->SetCamera(view_settings.camera);
233
234 pxr::GfVec4d viewport(0.0, 0.0, view_settings.width(), view_settings.height());
235 render_task_delegate_->set_viewport(viewport);
237 light_tasks_delegate_->set_viewport(viewport);
238 }
239
240 render_task_delegate_->add_aov(pxr::HdAovTokens->color);
241 render_task_delegate_->add_aov(pxr::HdAovTokens->depth);
242
244 render_task_delegate_->bind();
245
246 auto t = tasks();
247 engine_->Execute(render_index_.get(), &t);
248
249 render_task_delegate_->unbind();
250
251 GPU_framebuffer_bind(view_framebuffer);
253 GPU_shader_bind(shader);
254
255 pxr::GfVec4d draw_viewport(view_settings.border[0],
256 view_settings.border[1],
257 view_settings.border[2],
258 view_settings.border[3]);
259 GPURenderTaskDelegate *gpu_task = dynamic_cast<GPURenderTaskDelegate *>(
261 if (gpu_task) {
262 draw_texture_.draw(shader, draw_viewport, gpu_task->get_aov_texture(pxr::HdAovTokens->color));
263 }
264 else {
265 draw_texture_.create_from_buffer(
266 render_task_delegate_->get_aov_buffer(pxr::HdAovTokens->color));
267 draw_texture_.draw(shader, draw_viewport);
268 }
269
271
272 if (renderer_percent_done() == 0.0f) {
273 time_begin_ = BLI_time_now_seconds();
274 }
275
276 char elapsed_time[32];
277
279 elapsed_time, sizeof(elapsed_time), BLI_time_now_seconds() - time_begin_);
280
281 float percent_done = renderer_percent_done();
282 if (!render_task_delegate_->is_converged()) {
283 notify_status(percent_done / 100.0,
284 std ::string("Time: ") + elapsed_time +
285 " | Done: " + std::to_string(int(percent_done)) + "%",
286 "Render");
288 }
289 else {
290 notify_status(percent_done / 100.0, std::string("Time: ") + elapsed_time, "Rendering Done");
291 }
292}
293
295{
296 context_ = context;
297 render();
298}
299
300void ViewportEngine::notify_status(float /*progress*/,
301 const std::string &info,
302 const std::string &status)
303{
304 RE_engine_update_stats(bl_engine_, status.c_str(), info.c_str());
305}
306
307} // 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)
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.cc:113
size_t BLI_timecode_string_from_time_simple(char *str, size_t maxncpy, double time_seconds) ATTR_NONNULL()
Definition timecode.cc:170
Scene * DEG_get_evaluated_scene(const Depsgraph *graph)
@ OB_CAMERA
@ R_BORDER
@ V3D_RENDER_BORDER
@ RV3D_CAMOB
void GPU_batch_discard(blender::gpu::Batch *batch)
blender::gpu::Batch * GPU_batch_create_ex(GPUPrimType primitive_type, blender::gpu::VertBuf *vertex_buf, blender::gpu::IndexBuf *index_buf, GPUBatchFlag owns_flag)
Definition gpu_batch.cc:51
@ GPU_BATCH_OWNS_VBO
Definition GPU_batch.hh:42
void GPU_batch_draw(blender::gpu::Batch *batch)
void GPU_batch_set_shader(blender::gpu::Batch *batch, blender::gpu::Shader *shader, const blender::gpu::shader::SpecializationConstants *constants_state=nullptr)
void GPU_framebuffer_bind(blender::gpu::FrameBuffer *fb)
blender::gpu::FrameBuffer * GPU_framebuffer_active_get()
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(blender::gpu::Shader *shader, const char *name)
void GPU_shader_bind(blender::gpu::Shader *shader, const blender::gpu::shader::SpecializationConstants *constants_state=nullptr)
void GPU_shader_uniform_1i(blender::gpu::Shader *sh, const char *name, int value)
void GPU_shader_unbind()
blender::gpu::Shader * GPU_shader_get_builtin_shader(GPUBuiltinShader shader)
@ GPU_SHADER_3D_IMAGE
int GPU_texture_height(const blender::gpu::Texture *texture)
blender::gpu::TextureFormat GPU_texture_format(const blender::gpu::Texture *texture)
int GPU_texture_width(const blender::gpu::Texture *texture)
eGPUDataFormat
@ GPU_DATA_HALF_FLOAT
@ GPU_DATA_FLOAT
@ GPU_TEXTURE_USAGE_GENERAL
blender::gpu::Texture * GPU_texture_create_2d(const char *name, int width, int height, int mip_len, blender::gpu::TextureFormat format, eGPUTextureUsage usage, const float *data)
void GPU_texture_bind(blender::gpu::Texture *texture, int unit)
void GPU_texture_free(blender::gpu::Texture *texture)
void GPU_texture_update(blender::gpu::Texture *texture, eGPUDataFormat data_format, const void *data)
void GPU_vertbuf_attr_fill(blender::gpu::VertBuf *, uint a_idx, const void *data)
static blender::gpu::VertBuf * GPU_vertbuf_create_with_format(const GPUVertFormat &format)
void GPU_vertbuf_data_alloc(blender::gpu::VertBuf &verts, uint v_len)
uint GPU_vertformat_attr_add(GPUVertFormat *format, blender::StringRef name, blender::gpu::VertAttrType type)
@ RE_ENGINE_DO_DRAW
Definition RE_engine.h:60
BMesh const char void * data
BPy_StructRNA * depsgraph
void draw(gpu::Shader *shader, const pxr::GfVec4d &viewport, blender::gpu::Texture *tex=nullptr)
blender::gpu::Texture * texture() const
void create_from_buffer(pxr::HdRenderBuffer *buffer)
RenderEngine * bl_engine_
Definition engine.hh:36
pxr::HdTaskSharedPtrVector tasks()
std::unique_ptr< RenderTaskDelegate > render_task_delegate_
Definition engine.hh:51
std::unique_ptr< io::hydra::CameraDelegate > free_camera_delegate_
Definition engine.hh:47
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
blender::gpu::Texture * get_aov_texture(pxr::TfToken const &aov_key)
void notify_status(float progress, const std::string &info, const std::string &status) override
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)
const int status
float persmat[4][4]
struct RenderData r
struct Object * camera
rctf render_border
float xmax
float xmin
float ymax
float ymin
i
Definition text_draw.cc:230