This repository has been archived by the owner on Aug 28, 2021. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 186
/
render.hh
185 lines (159 loc) · 6.42 KB
/
render.hh
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
// Copyright 2017-present, Facebook, Inc.
// All rights reserved.
//
// This source code is licensed under the license found in the
// LICENSE file in the root directory of this source tree.
//File: render.hh
#pragma once
#include <string>
#include <memory>
#include <utility>
#include <future>
#include <queue>
#include <glm/glm.hpp>
#define GLM_ENABLE_EXPERIMENTAL
#include <glm/gtx/component_wise.hpp>
#include "scene.hh"
#include "gl/fbScope.hh"
#include "gl/glContext.hh"
#include "gl/camera.hh"
#include "model/scenecache.hh"
#include "lib/executor.hh"
namespace render {
// An instance of this class has to be created and used in the same thread.
// If not, use SUNCGRenderAPIThread.
class SUNCGRenderAPI {
public:
SUNCGRenderAPI(int w, int h, int device)
: context_(render::createHeadlessContext(Geometry{w, h}, device)),
geo_{w, h}, fb_{geo_} {
// enable the common context options
glEnable(GL_DEPTH_TEST);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_CULL_FACE);
}
// Load the scene objects to GPU, and unload current scene if it exists.
// obj_file: house.obj in SUNCG
// model_category_file: path to ModelCategoryMapping.csv
// semantic_label_file: path to colormap_coarse.csv or colormap_fine.csv
void loadScene(
std::string obj_file, std::string model_category_file,
std::string semantic_label_file);
void setMode(SUNCGScene::RenderMode m) { scene_->set_mode(m); }
// Render the image. The return format depends on the rendering mode, which
// is set with the method above:
//
// For RGB mode, returns a 3-channel RGB image of the rendered scene.
//
// For SEMANTIC mode, returns a 3-channel image.
// The mapping from color to class is in the CSV.
//
// For INSTANCE mode, returns a 3-channel image.
// Each unique color means an instance, and the coloring of each instance
// is consistent within a scene across different views.
// You can use getNameFromInstanceColor(r, g, b) to know which object the
// instance color maps to.
//
// For DEPTH mode, returns a 2-channel image:
// The first channel contains depth values scaled to (0, 255), where
// pixel / 255.0 * 20.0 is the true depth in meters. Any pixels that are
// further than 20 meters away will be clipped to 20 meters.
// The second channel is an "infinity" mask. Each value is either 0 or 255.
// 255 means this pixel is at infinty depth, and the correspoding first
// channel is meaningless.
//
// INVDEPTH mode also returns a 2-channel image, of 16-bit inverse depth.
// It can be converted to a single uint16 inverse depth image as follows:
// img16 = img.astype(np.uint16)
// inverse_depth_16 = img16[:, :, 0] * 256 + img16[:, :, 1]
// To convert from inverse depth to float depth, you can use:
// PIXEL_MAX = np.iinfo(np.uint16).max
// NEAR = 0.3 # has to match minDepth parameter
// depth = NEAR * PIXEL_MAX / inverse_depth_16.astype(np.float)
//
Matuc render();
// Render a cube map of size 6w * h * c. See render() for rendering details.
// Cube map orientations are { BACK, LEFT, FORWARD, RIGHT, UP, DOWN }
Matuc renderCubeMap();
// Print OpenGL context info.
void printContextInfo() const { context_->printInfo(); }
// Get the camera. Caller doesn't own pointer
// Caller can use the returned camera to move around the scene.
// After the loading a new scene, you'll need to call getCamera() again
// to get the camera in the new scene.
Camera* getCamera() const { return camera_.get(); }
// Get the resolution.
Geometry resolution() const { return geo_; }
// r, g, b: integer in [0, 255]
// Returns: an object name defined in the obj file, or "" if not found.
// For SUNCG data, this object name is usually the "modelId" field
// in house.json. Note that each scene may have many objects with the same
// modelId.
std::string getNameFromInstanceColor(int r, int g, int b) const {
return scene_->get_name_from_instance_color(r, g, b);
}
private:
SceneCache scene_cache_;
SUNCGScene* scene_ = nullptr; // no ownership
std::unique_ptr<GLContext> context_;
std::unique_ptr<Camera> camera_;
Geometry geo_;
Framebuffer fb_;
// set camera "smartly" to some place in the scene
void init_camera_() {
auto range = scene_->get_range();
auto mid = scene_->get_min() + range * 0.5f;
mid.z += glm::compMax(range);
camera_.reset(new Camera{mid});
}
};
// Same as SUNCGRenderAPI, but delegates all methods to run on an independent thread, because OpenGL context is bound with thread.
// As a result, you can do the following which is not allowed in SUNCGRenderAPI:
// 1. Use the same instance in different threads.
// 2. Create multiple instances in one thread.
// Note that this class is still NOT thread-safe. You cannot call its methods concurrently.
class SUNCGRenderAPIThread {
public:
SUNCGRenderAPIThread(int w, int h, int device) {
exec_.execute_sync([=]() {
this->api_.reset(new SUNCGRenderAPI{w, h, device});
});
}
~SUNCGRenderAPIThread() {
// Destructor needs to run in a dedicated thread as well.
exec_.execute_sync([=]() { api_.reset(nullptr); });
exec_.stop();
}
void printContextInfo() {
exec_.execute_sync([=]() {
this->api_->printContextInfo();
} );
}
// caller doesn't own pointer
Camera* getCamera() const { return api_->getCamera(); }
void setMode(SUNCGScene::RenderMode m) { api_->setMode(m); }
Geometry resolution() const { return api_->resolution(); }
void loadScene(
std::string obj_file, std::string model_category_file,
std::string semantic_label_file) {
exec_.execute_sync([=]() {
this->api_->loadScene(obj_file, model_category_file, semantic_label_file);
});
}
Matuc render() {
return exec_.execute_sync<Matuc>([=]() { return this->api_->render(); });
}
Matuc renderCubeMap() {
return exec_.execute_sync<Matuc>([=]() {
return this->api_->renderCubeMap();
});
}
std::string getNameFromInstanceColor(int r, int g, int b) const {
return this->api_->getNameFromInstanceColor(r, g, b);
}
private:
std::unique_ptr<SUNCGRenderAPI> api_;
ExecutorInThread exec_;
};
}