| 31 #include "src/gl/partrenderer.h" |
31 #include "src/gl/partrenderer.h" |
| 32 #include "src/gl/compiler.h" |
32 #include "src/gl/compiler.h" |
| 33 |
33 |
| 34 static constexpr double MIN_ZOOM = -3.0; |
34 static constexpr double MIN_ZOOM = -3.0; |
| 35 static constexpr double MAX_ZOOM = 3.0; |
35 static constexpr double MAX_ZOOM = 3.0; |
| |
36 const gl::RenderPreferences PartRenderer::default_render_preferences{}; |
| |
37 const gl::build_preferences PartRenderer::default_build_preferences{}; |
| 36 |
38 |
| 37 PartRenderer::PartRenderer( |
39 PartRenderer::PartRenderer( |
| 38 QTextDocument* model, |
40 QTextDocument* model, |
| 39 DocumentManager* documents, |
41 DocumentManager* documents, |
| 40 const ColorTable& colorTable, |
42 const ColorTable& colorTable, |
| 118 |
120 |
| 119 void PartRenderer::renderScene() |
121 void PartRenderer::renderScene() |
| 120 { |
122 { |
| 121 if (this->needBuild) |
123 if (this->needBuild) |
| 122 { |
124 { |
| 123 gl::build(&this->shaders, this->model, this->colorTable, this->documents, this->renderPreferences); |
125 gl::build(&this->shaders, this->model, this->colorTable, this->documents, this->build_preferences); |
| 124 this->boundingBox = gl::boundingBoxForModel(this->model, this->documents); |
126 this->boundingBox = gl::boundingBoxForModel(this->model, this->documents); |
| 125 this->needBuild = false; |
127 this->needBuild = false; |
| 126 } |
128 } |
| 127 this->checkForGLErrors(); |
129 this->checkForGLErrors(); |
| 128 if (true |
130 if (this->render_preferences->lineAntiAliasing) |
| 129 and this->renderPreferences.lineAntiAliasing |
131 { |
| 130 and this->renderPreferences.style != gl::RenderStyle::PickScene |
|
| 131 ) { |
|
| 132 glEnable(GL_LINE_SMOOTH); |
132 glEnable(GL_LINE_SMOOTH); |
| 133 glHint(GL_LINE_SMOOTH_HINT, GL_NICEST); |
133 glHint(GL_LINE_SMOOTH_HINT, GL_NICEST); |
| 134 } |
134 } |
| 135 else { |
135 else { |
| 136 glDisable(GL_LINE_SMOOTH); |
136 glDisable(GL_LINE_SMOOTH); |
| 137 } |
137 } |
| 138 if (this->renderPreferences.style != gl::RenderStyle::PickScene) |
138 if (this->render_preferences->style != gl::RenderStyle::PickScene) |
| 139 { |
139 { |
| 140 const QColor& backgroundColor = this->renderPreferences.backgroundColor; |
140 const QColor& backgroundColor = this->build_preferences->backgroundColor; |
| 141 glClearColor( |
141 glClearColor( |
| 142 static_cast<float>(backgroundColor.redF()), |
142 static_cast<float>(backgroundColor.redF()), |
| 143 static_cast<float>(backgroundColor.greenF()), |
143 static_cast<float>(backgroundColor.greenF()), |
| 144 static_cast<float>(backgroundColor.blueF()), |
144 static_cast<float>(backgroundColor.blueF()), |
| 145 1.0f); |
145 1.0f); |
| 149 { |
149 { |
| 150 glClearColor(1.0f, 1.0f, 1.0f, 1.0f); |
150 glClearColor(1.0f, 1.0f, 1.0f, 1.0f); |
| 151 gl::setShaderUniform(&this->shaders, "useLighting", GL_FALSE); |
151 gl::setShaderUniform(&this->shaders, "useLighting", GL_FALSE); |
| 152 } |
152 } |
| 153 this->checkForGLErrors(); |
153 this->checkForGLErrors(); |
| 154 const QColor qs = this->renderPreferences.selectedColor; |
154 const QColor qs = this->render_preferences->selectedColor; |
| 155 const glm::vec4 selectedColor{qs.redF(), qs.greenF(), qs.blueF(), 1.0f}; |
155 const glm::vec4 selectedColor{qs.redF(), qs.greenF(), qs.blueF(), 1.0f}; |
| 156 gl::setShaderUniformVector(&this->shaders, "selectedColor", selectedColor); |
156 gl::setShaderUniformVector(&this->shaders, "selectedColor", selectedColor); |
| 157 gl::setShaderUniform(&this->shaders, "highlighted", this->highlighted.value); |
157 gl::setShaderUniform(&this->shaders, "highlighted", this->highlighted.value); |
| 158 this->checkForGLErrors(); |
158 this->checkForGLErrors(); |
| 159 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); |
159 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); |
| 160 glEnable(GL_DEPTH_TEST); |
160 glEnable(GL_DEPTH_TEST); |
| 161 glEnable(GL_POLYGON_OFFSET_FILL); |
161 glEnable(GL_POLYGON_OFFSET_FILL); |
| 162 glPolygonOffset(1.0f, 1.0f); |
162 glPolygonOffset(1.0f, 1.0f); |
| 163 glLineWidth(this->renderPreferences.lineThickness); |
163 glLineWidth(this->render_preferences->lineThickness); |
| 164 const auto renderAllArrays = [this](){ |
164 const auto renderAllArrays = [this](){ |
| 165 // Lines need to be rendered last so that anti-aliasing does not interfere with polygon rendering. |
165 // Lines need to be rendered last so that anti-aliasing does not interfere with polygon rendering. |
| 166 this->renderVao<gl::ArrayClass::Triangles>(); |
166 this->renderVao<gl::ArrayClass::Triangles>(); |
| 167 this->renderVao<gl::ArrayClass::Quads>(); |
167 this->renderVao<gl::ArrayClass::Quads>(); |
| 168 this->renderVao<gl::ArrayClass::Lines>(); |
168 this->renderVao<gl::ArrayClass::Lines>(); |
| 169 }; |
169 }; |
| 170 if (this->renderPreferences.wireframe and this->renderPreferences.style != gl::RenderStyle::PickScene) { |
170 if (this->render_preferences->wireframe) |
| |
171 { |
| 171 glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); |
172 glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); |
| 172 } |
173 } |
| 173 switch (this->renderPreferences.style) |
174 switch (this->render_preferences->style) |
| 174 { |
175 { |
| 175 case gl::RenderStyle::Normal: |
176 case gl::RenderStyle::Normal: |
| 176 this->setFragmentStyle(gl::FragmentStyle::Normal); |
177 this->setFragmentStyle(gl::FragmentStyle::Normal); |
| 177 renderAllArrays(); |
178 renderAllArrays(); |
| 178 break; |
179 break; |
| 393 return toQPointF(glm::vec2{projected.x, static_cast<float>(this->height()) - projected.y}); |
393 return toQPointF(glm::vec2{projected.x, static_cast<float>(this->height()) - projected.y}); |
| 394 } |
394 } |
| 395 |
395 |
| 396 bool PartRenderer::isDark() const |
396 bool PartRenderer::isDark() const |
| 397 { |
397 { |
| 398 return luma(this->renderPreferences.backgroundColor) < 0.25; |
398 return luma(this->build_preferences->backgroundColor) < 0.25; |
| 399 } |
399 } |
| 400 |
400 |
| 401 Line<3> PartRenderer::cameraLine(const QPointF& point) const |
401 Line<3> PartRenderer::cameraLine(const QPointF& point) const |
| 402 { |
402 { |
| 403 const glm::vec3 p1 = this->unproject({point.x(), point.y(), 0}); |
403 const glm::vec3 p1 = this->unproject({point.x(), point.y(), 0}); |
| 431 where.setY(this->height() - where.y()); |
431 where.setY(this->height() - where.y()); |
| 432 // Since we are dealing with pixel data right from the framebuffer, its size |
432 // Since we are dealing with pixel data right from the framebuffer, its size |
| 433 // will be affected by High DPI scaling. We need to take this into account |
433 // will be affected by High DPI scaling. We need to take this into account |
| 434 // and multiply the pixel positions by the screen pixel scaling factor. |
434 // and multiply the pixel positions by the screen pixel scaling factor. |
| 435 where *= this->devicePixelRatioF(); |
435 where *= this->devicePixelRatioF(); |
| 436 const gl::RenderStyle oldRenderStyle = this->renderPreferences.style; |
436 static const gl::RenderPreferences pick_scene_preferences { |
| 437 this->renderPreferences.style = gl::RenderStyle::PickScene; |
437 .style = gl::RenderStyle::PickScene, |
| |
438 .selectedColor = {}, |
| |
439 .lineThickness = 3.0f, |
| |
440 .lineAntiAliasing = false, |
| |
441 .drawAxes = false, |
| |
442 .wireframe = false, |
| |
443 }; |
| |
444 const gl::RenderPreferences* old_render_preferences = this->render_preferences; |
| |
445 this->render_preferences = &pick_scene_preferences; |
| 438 this->makeCurrent(); |
446 this->makeCurrent(); |
| 439 QOpenGLFramebufferObject fbo{this->width(), this->height(), QOpenGLFramebufferObject::CombinedDepthStencil}; |
447 QOpenGLFramebufferObject fbo{this->width(), this->height(), QOpenGLFramebufferObject::CombinedDepthStencil}; |
| 440 fbo.bind(); |
448 fbo.bind(); |
| 441 this->renderScene(); |
449 this->renderScene(); |
| 442 std::array<GLubyte, 3> data; |
450 std::array<GLubyte, 3> data; |
| 443 this->checkForGLErrors(); |
451 this->checkForGLErrors(); |
| 444 glReadPixels(where.x(), where.y(), 1, 1, GL_RGB, GL_UNSIGNED_BYTE, &data[0]); |
452 glReadPixels(where.x(), where.y(), 1, 1, GL_RGB, GL_UNSIGNED_BYTE, &data[0]); |
| 445 this->checkForGLErrors(); |
453 this->checkForGLErrors(); |
| 446 fbo.release(); |
454 fbo.release(); |
| 447 this->renderPreferences.style = oldRenderStyle; |
455 this->render_preferences = old_render_preferences; |
| 448 return gl::idFromUcharColor(data); |
456 return gl::idFromUcharColor(data); |
| 449 } |
457 } |
| 450 |
458 |
| 451 /** |
459 /** |
| 452 * @brief Changes the color of rendered fragments |
460 * @brief Changes the color of rendered fragments |
| 453 * @param newFragmentStyle new fragment style to use |
461 * @param newFragmentStyle new fragment style to use |
| 454 */ |
462 */ |
| 455 void PartRenderer::setFragmentStyle(gl::FragmentStyle newFragmentStyle) |
463 void PartRenderer::setFragmentStyle(gl::FragmentStyle newFragmentStyle) |
| 456 { |
464 { |
| 457 gl::setShaderUniform(&this->shaders, "fragmentStyle", static_cast<int>(newFragmentStyle)); |
465 gl::setShaderUniform(&this->shaders, "fragmentStyle", static_cast<int>(newFragmentStyle)); |
| 458 } |
|
| 459 |
|
| 460 /** |
|
| 461 * @brief Changes the way the scene is rendered |
|
| 462 * @param newStyle new render style to use |
|
| 463 */ |
|
| 464 void PartRenderer::setRenderPreferences(const gl::RenderPreferences& newPreferences) |
|
| 465 { |
|
| 466 bool mainColorChanged = this->renderPreferences.mainColor != newPreferences.mainColor; |
|
| 467 bool backgroundColorChanged = this->renderPreferences.backgroundColor != newPreferences.backgroundColor; |
|
| 468 this->renderPreferences = newPreferences; |
|
| 469 if (mainColorChanged or backgroundColorChanged) |
|
| 470 { |
|
| 471 this->build(); |
|
| 472 } |
|
| 473 Q_EMIT this->renderPreferencesChanged(); |
|
| 474 this->update(); |
|
| 475 } |
466 } |
| 476 |
467 |
| 477 /** |
468 /** |
| 478 * @return the currently highlighted object |
469 * @return the currently highlighted object |
| 479 */ |
470 */ |