Leviathan  0.8.0.0
Leviathan game engine
Leviathan::Graphics Class Reference

#include <Graphics.h>

Classes

struct  Private
 

Public Member Functions

DLLEXPORT Graphics ()
 
DLLEXPORT ~Graphics ()
 
DLLEXPORT bool Init (AppDef *appdef)
 
DLLEXPORT void Release ()
 
DLLEXPORT bool Frame ()
 
DLLEXPORT void UpdateShownOverlays (bs::RenderTarget &target, const std::vector< bs::SPtr< bs::Texture >> &overlays)
 
DLLEXPORT bool IsVerticalUVFlipped () const
 
DLLEXPORT bs::HShader LoadShaderByName (const std::string &name)
 Finds and loads a shader with the name. More...
 
DLLEXPORT bs::HTexture LoadTextureByName (const std::string &name)
 Works the same as LoadShaderByName. More...
 
DLLEXPORT bs::HMesh LoadMeshByName (const std::string &name)
 Works the same as LoadShaderByName. More...
 
DLLEXPORT bs::HAnimationClip LoadAnimationClipByName (const std::string &name)
 Works the same as LoadShaderByName. More...
 

Protected Member Functions

bs::SPtr< bs::RenderWindow > RegisterCreatedWindow (Window &window)
 Called when Window objects are created to register them with bsf and with the case of the first window this initializes the rest of bsf. More...
 
bool UnRegisterWindow (Window &window)
 Called just before a window is destroyed. This needs to stop rendering to it. More...
 

Detailed Description

Definition at line 12 of file Graphics.h.

Constructor & Destructor Documentation

◆ Graphics()

DLLEXPORT Graphics::Graphics ( )

Definition at line 160 of file Graphics.cpp.

160 {}

◆ ~Graphics()

Graphics::~Graphics ( )

Definition at line 162 of file Graphics.cpp.

163 {
164  LEVIATHAN_ASSERT(!Initialized, "Graphics not released before destructor");
165 }
#define LEVIATHAN_ASSERT(x, msg)
Definition: Define.h:100

Member Function Documentation

◆ Frame()

DLLEXPORT bool Graphics::Frame ( )

Definition at line 537 of file Graphics.cpp.

538 {
539  // Logic for this frame is already ready, just tell bsf to render once
540  Pimpl->OurApp->runMainLoopFrame();
541 
542  // At this point the frame render operation is happening on the BSF core thread, but it is
543  // safe to use non-core thread objects normally, only in special cases do we need to wait
544  // for a frame to end
545  return true;
546 }

◆ Init()

bool Graphics::Init ( AppDef appdef)

Definition at line 167 of file Graphics.cpp.

168 {
169  // StartUp SDL //
170  if(SDL_Init(SDL_INIT_VIDEO | SDL_INIT_GAMECONTROLLER) != 0) {
171 
172  LOG_ERROR("Graphics: Init: SDL init failed, error: " + std::string(SDL_GetError()));
173  return false;
174  }
175 
176  SDL_SetHint(SDL_HINT_VIDEO_MINIMIZE_ON_FOCUS_LOSS, "0");
177 
178  int displays = SDL_GetNumVideoDisplays();
179 
180  LOG_INFO("SDL: display count: " + Convert::ToString(displays));
181 
182  // Get display positions
183  std::vector<SDL_Rect> displayBounds;
184 
185  for(int i = 0; i < displays; i++) {
186 
187  displayBounds.push_back(SDL_Rect());
188 
189  SDL_GetDisplayBounds(i, &displayBounds.back());
190 
191  const char* nameptr = SDL_GetDisplayName(i);
192 
193  const auto name = nameptr ? std::string(nameptr) : std::string("unnamed");
194 
195  // Video modes //
196  int videomodecount = SDL_GetNumDisplayModes(i);
197 
198  std::vector<std::string> videomodes;
199 
200  for(int a = 0; a < videomodecount; a++) {
201 
202 
203  SDL_DisplayMode mode = {SDL_PIXELFORMAT_UNKNOWN, 0, 0, 0, 0};
204 
205  if(SDL_GetDisplayMode(i, a, &mode) == 0) {
206 
207  videomodes.push_back(Convert::ToString(SDL_BITSPERPIXEL(mode.format)) +
208  " bpp " + Convert::ToString(mode.w) + "x" +
209  Convert::ToString(mode.h) + " at " +
210  Convert::ToString(mode.refresh_rate) + "Hz");
211  }
212  }
213 
214 
215  LOG_INFO("Display(" + Convert::ToString(i) + ", " + name + "): top left: (" +
216  Convert::ToString(displayBounds.back().x) + ", " +
217  Convert::ToString(displayBounds.back().y) +
218  ") size: " + Convert::ToString(displayBounds.back().w) + "x" +
219  Convert::ToString(displayBounds.back().h));
220 
221  // LOG_INFO("Supported modes(" + Convert::ToString(videomodes.size()) + "): ");
222  // for(const auto& mode : videomodes){
223 
224  // LOG_WRITE(" " + mode);
225  // }
226  }
227 
228 
229  if(!InitializeBSF(appdef)) {
230 
231  Logger::Get()->Error("Graphics: Init: failed to create bs::framework renderer");
232  return false;
233  }
234 
235 #ifdef __linux
236  // Set X11 error handler to not crash on non-fatal errors
237  XSetErrorHandler(LeviathanX11ErrorHandler);
238 #endif
239 
240  Initialized = true;
241  return true;
242 }
#define LOG_INFO(x)
Definition: Define.h:90
#define LOG_ERROR(x)
Definition: Define.h:92
static std::string ToString(const T &val)
Definition: Convert.h:72
static DLLEXPORT Logger * Get()
Definition: Logger.cpp:106
DLLEXPORT void Error(const std::string &data) override
Definition: Logger.cpp:177

◆ IsVerticalUVFlipped()

DLLEXPORT bool Graphics::IsVerticalUVFlipped ( ) const

Definition at line 569 of file Graphics.cpp.

570 {
571  const auto capabilities = bs::ct::RenderAPI::instance().getCapabilities(0);
572 
573  return capabilities.conventions.ndcYAxis != bs::Conventions::Axis::Down;
574 }

◆ LoadAnimationClipByName()

DLLEXPORT bs::HAnimationClip Graphics::LoadAnimationClipByName ( const std::string &  name)

Works the same as LoadShaderByName.

Definition at line 627 of file Graphics.cpp.

628 {
630  // Leviathan::StringOperations::RemoveExtension(name, true),
632  // Leviathan::StringOperations::GetExtension(name)
633  "asset");
634 
635  if(file.empty()) {
636  LOG_ERROR(
637  "Graphics: LoadAnimationClipByName: could not find resource with name: " + name);
638  return nullptr;
639  }
640 
641  return Pimpl->LoadResource<bs::AnimationClip>(
642  std::filesystem::absolute(file).string().c_str());
643 }
static const StringTypeN RemovePath(const StringTypeN &filepath)
#define LOG_ERROR(x)
Definition: Define.h:92
static DLLEXPORT FileSystem * Get()
Definition: FileSystem.cpp:74
DLLEXPORT std::string SearchForFile(FILEGROUP which, const std::string &name, const std::string &extensions, bool searchall=true)
Searches for a file.
Definition: FileSystem.cpp:666

◆ LoadMeshByName()

DLLEXPORT bs::HMesh Graphics::LoadMeshByName ( const std::string &  name)

Works the same as LoadShaderByName.

Definition at line 611 of file Graphics.cpp.

612 {
614  // Leviathan::StringOperations::RemoveExtension(name, true),
616  // Leviathan::StringOperations::GetExtension(name)
617  "asset");
618 
619  if(file.empty()) {
620  LOG_ERROR("Graphics: LoadMeshByName: could not find resource with name: " + name);
621  return nullptr;
622  }
623 
624  return Pimpl->LoadResource<bs::Mesh>(std::filesystem::absolute(file).string().c_str());
625 }
static const StringTypeN RemovePath(const StringTypeN &filepath)
#define LOG_ERROR(x)
Definition: Define.h:92
static DLLEXPORT FileSystem * Get()
Definition: FileSystem.cpp:74
DLLEXPORT std::string SearchForFile(FILEGROUP which, const std::string &name, const std::string &extensions, bool searchall=true)
Searches for a file.
Definition: FileSystem.cpp:666

◆ LoadShaderByName()

DLLEXPORT bs::HShader Graphics::LoadShaderByName ( const std::string &  name)

Finds and loads a shader with the name.

If a full path or a valid relative path is specified a full search is not done. Unless a variant of the name with ".asset" is found, which is preferred to skip expensive importing.

Definition at line 577 of file Graphics.cpp.

578 {
579  // TODO: .asset detection
580 
582  // Leviathan::StringOperations::RemoveExtension(name, true),
584  // Leviathan::StringOperations::GetExtension(name)
585  "asset");
586 
587  if(file.empty()) {
588  LOG_ERROR("Graphics: LoadShaderByName: could not find resource with name: " + name);
589  return nullptr;
590  }
591 
592  return Pimpl->LoadResource<bs::Shader>(std::filesystem::absolute(file).string().c_str());
593 }
static const StringTypeN RemovePath(const StringTypeN &filepath)
#define LOG_ERROR(x)
Definition: Define.h:92
static DLLEXPORT FileSystem * Get()
Definition: FileSystem.cpp:74
DLLEXPORT std::string SearchForFile(FILEGROUP which, const std::string &name, const std::string &extensions, bool searchall=true)
Searches for a file.
Definition: FileSystem.cpp:666

◆ LoadTextureByName()

DLLEXPORT bs::HTexture Graphics::LoadTextureByName ( const std::string &  name)

Works the same as LoadShaderByName.

Definition at line 595 of file Graphics.cpp.

596 {
598  // Leviathan::StringOperations::RemoveExtension(name, true),
600  // Leviathan::StringOperations::GetExtension(name)
601  "asset");
602 
603  if(file.empty()) {
604  LOG_ERROR("Graphics: LoadTextureByName: could not find resource with name: " + name);
605  return nullptr;
606  }
607 
608  return Pimpl->LoadResource<bs::Texture>(std::filesystem::absolute(file).string().c_str());
609 }
static const StringTypeN RemovePath(const StringTypeN &filepath)
#define LOG_ERROR(x)
Definition: Define.h:92
static DLLEXPORT FileSystem * Get()
Definition: FileSystem.cpp:74
DLLEXPORT std::string SearchForFile(FILEGROUP which, const std::string &name, const std::string &extensions, bool searchall=true)
Searches for a file.
Definition: FileSystem.cpp:666

◆ RegisterCreatedWindow()

bs::SPtr< bs::RenderWindow > Graphics::RegisterCreatedWindow ( Window window)
protected

Called when Window objects are created to register them with bsf and with the case of the first window this initializes the rest of bsf.

Definition at line 379 of file Graphics.cpp.

380 {
381  if(FirstWindowCreated) {
382  // Register secondary window
383 
384  bs::RENDER_WINDOW_DESC windowDesc;
385 
386  windowDesc.depthBuffer = true;
387 
388  int multiSample;
389 
390  ObjectFileProcessor::LoadValueFromNamedVars<int>(
391  Engine::Get()->GetDefinition()->GetValues(), "WindowMultiSampleCount", multiSample,
392  1);
393 
394  windowDesc.multisampleCount = multiSample;
395  // windowDesc.multisampleHint = "";
396  // Not sure what all settings need to be copied
397  windowDesc.fullscreen = /* window.IsFullScreen() */ false;
398  windowDesc.vsync = false;
399 
400  int32_t width, height;
401  window.GetSize(width, height);
402  windowDesc.videoMode = bs::VideoMode(
403  width, height, Pimpl->Description.primaryWindowDesc.videoMode.refreshRate, 0);
404 
405 #ifdef _WIN32
406  windowDesc.platformSpecific["externalWindowHandle"] =
407  std::to_string((uint64_t)window.GetNativeHandle());
408 #else
409  windowDesc.platformSpecific["externalWindowHandle"] =
410  std::to_string(window.GetNativeHandle());
411 
412  windowDesc.platformSpecific["externalDisplay"] =
413  std::to_string(window.GetWindowXDisplay());
414 #endif
415 
416  auto window = bs::RenderWindow::create(windowDesc);
417 
418  if(!window)
419  LOG_FATAL("Failed to create additional BSF window");
420 
421  return window;
422 
423  } else {
424  // Finish initializing graphics
425  FirstWindowCreated = true;
426  LOG_INFO("Graphics: doing bs::framework initialization after creating first window");
427 
428  // Setup first window properties
429  auto& windowDesc = Pimpl->Description.primaryWindowDesc;
430  windowDesc.depthBuffer = true;
431 
432  int multiSample;
433 
434  ObjectFileProcessor::LoadValueFromNamedVars<int>(
435  Engine::Get()->GetDefinition()->GetValues(), "WindowMultiSampleCount", multiSample,
436  1);
437 
438  windowDesc.multisampleCount = multiSample;
439  // windowDesc.multisampleHint = "";
440  // Not sure what all settings need to be copied
441  windowDesc.fullscreen = /* window.IsFullScreen() */ false;
442  windowDesc.vsync = false;
443 
444  // Fill video mode info from SDL
445  SDL_DisplayMode dm;
446  if(SDL_GetDesktopDisplayMode(0, &dm) != 0) {
447  LOG_ERROR("Graphics: RegisterCreatedWindow: failed to get desktop display mode:" +
448  std::string(SDL_GetError()));
449  return nullptr;
450  }
451 
452  int32_t width, height;
453  window.GetSize(width, height);
454  windowDesc.videoMode = bs::VideoMode(width, height, dm.refresh_rate, 0);
455 
456 #ifdef _WIN32
457  windowDesc.platformSpecific["externalWindowHandle"] =
458  std::to_string((uint64_t)window.GetNativeHandle());
459 #else
460  windowDesc.platformSpecific["externalWindowHandle"] =
461  std::to_string(window.GetNativeHandle());
462 
463  windowDesc.platformSpecific["externalDisplay"] =
464  std::to_string(window.GetWindowXDisplay());
465 #endif
466 
467  bs::Application::startUp<LeviathanBSFApplication>(Pimpl->Description);
468 
469  Pimpl->OurApp =
470  static_cast<LeviathanBSFApplication*>(bs::CoreApplication::instancePtr());
471 
472  bs::SPtr<bs::RenderWindow> bsWindow =
473  bs::CoreApplication::instance().getPrimaryWindow();
474 
475  LEVIATHAN_ASSERT(bsWindow, "window creation failed");
476 
477  // Notify engine to register threads to work with Ogre //
478  // Engine::GetEngine()->_NotifyThreadsRegisterOgre();
479 
480  // TODO: loading this causes a failure in bs::Material::createParamsSet
481  // constexpr auto GUI_SHADER_PATH =
482  // "Data/Shaders/CoreShaders/ScreenSpaceGUI.bsl.asset";
483 
484  // LEVIATHAN_ASSERT(
485  // std::filesystem::exists(GUI_SHADER_PATH), "Core GUI shader asset is missing");
486 
487  // auto shader = Pimpl->LoadResource<bs::Shader>(
488  // std::filesystem::absolute(GUI_SHADER_PATH).string().c_str());
489 
490  // if(!shader)
491  // LEVIATHAN_ASSERT(false, "Loading Core GUI shader asset failed");
492 
493  auto shader =
494  bs::gImporter().import<bs::Shader>("Data/Shaders/CoreShaders/ScreenSpaceGUI.bsl");
495 
496  auto material = bs::Material::create(shader);
497 
498  Pimpl->OurApp->GUIRenderer =
499  bs::RendererExtension::create<GUIOverlayRenderer>(GUIOverlayInitializationData{
500  GeometryHelpers::CreateScreenSpaceQuad(-1, -1, 2, 2)->GetInternal()->getCore(),
501  material->getCore()});
502 
503  Pimpl->OurApp->beginMainLoop();
504  return bsWindow;
505  }
506 }
DLLEXPORT unsigned long GetNativeHandle() const
Definition: Window.cpp:917
static DLLEXPORT Mesh::pointer CreateScreenSpaceQuad(float x, float y, float width, float height, bool autoflipUV=true)
Creates a screen space plane with UV coordinates.
DLLEXPORT void GetSize(int32_t &width, int32_t &height) const
Definition: Window.cpp:896
#define LOG_INFO(x)
Definition: Define.h:90
#define LOG_ERROR(x)
Definition: Define.h:92
#define LOG_FATAL(x)
Definition: Define.h:94
#define LEVIATHAN_ASSERT(x, msg)
Definition: Define.h:100
static DLLEXPORT Engine * Get()
Definition: Engine.cpp:86

◆ Release()

DLLEXPORT void Graphics::Release ( )

Definition at line 244 of file Graphics.cpp.

245 {
246  if(Initialized) {
247 
248  ShutdownBSF();
249 
250  SDL_Quit();
251  }
252 
253  Initialized = false;
254  FirstWindowCreated = false;
255  Pimpl.reset();
256 }

◆ UnRegisterWindow()

bool Graphics::UnRegisterWindow ( Window window)
protected

Called just before a window is destroyed. This needs to stop rendering to it.

Returns
True if the window was primary and should only be hidden instead of destroyed

Definition at line 508 of file Graphics.cpp.

509 {
510  if(Pimpl) {
511  Pimpl->OurApp->waitUntilFrameFinished();
512  }
513 
514  if(window.GetBSFWindow() == bs::CoreApplication::instance().getPrimaryWindow()) {
515  LOG_INFO("Graphics: primary window is closing, hiding it instead until shutdown");
516  return true;
517  }
518 
519  // TODO: additional window unregister
520  return false;
521 }
#define LOG_INFO(x)
Definition: Define.h:90
DLLEXPORT const auto & GetBSFWindow() const
Definition: Window.h:166

◆ UpdateShownOverlays()

DLLEXPORT void Graphics::UpdateShownOverlays ( bs::RenderTarget &  target,
const std::vector< bs::SPtr< bs::Texture >> &  overlays 
)

Definition at line 548 of file Graphics.cpp.

550 {
551  const auto targetRenderTarget = reinterpret_cast<uint64_t>(target.getCore().get());
552 
553  std::vector<bs::SPtr<bs::ct::Texture>> coreVersion;
554  coreVersion.reserve(overlays.size());
555 
556  std::transform(overlays.begin(), overlays.end(), std::back_inserter(coreVersion),
557  [](const bs::SPtr<bs::Texture>& item) { return item->getCore(); });
558 
559  std::weak_ptr<GUIOverlayRenderer> rendererExtension = Pimpl->OurApp->GUIRenderer;
560 
561  bs::gCoreThread().queueCommand(
562  [rendererExtension, targetRenderTarget, coreVersion = std::move(coreVersion)]() {
563  const auto locked = rendererExtension.lock();
564  if(locked)
565  locked->UpdateShownOverlays(targetRenderTarget, coreVersion);
566  });
567 }

The documentation for this class was generated from the following files: