NzString NzInputStream::ReadLine(unsigned int lineSize) { NzString line; if (lineSize == 0) // Taille maximale indéterminée { const unsigned int bufferSize = 64; char buffer[bufferSize+1]; buffer[bufferSize] = '\0'; unsigned int readSize; do { readSize = Read(buffer, bufferSize); const char* ptr = std::strchr(buffer, '\n'); if (ptr) { unsigned int pos = ptr-buffer; if (m_streamOptions & nzStreamOption_Text && pos > 0 && buffer[pos-1] == '\r') line.Append(buffer, pos-1); else line.Append(buffer, pos); if (!SetCursorPos(GetCursorPos() - readSize + pos + 1)) NazaraWarning("Failed to reset cursos pos"); break; } else line.Append(buffer, readSize); } while (readSize == bufferSize); } else { line.Set(lineSize, '\0'); unsigned int readSize = Read(&line[0], lineSize); unsigned int pos = line.Find('\n'); if (pos <= readSize) // Faux uniquement si le caractère n'est pas présent (npos étant le plus grand entier) { if (m_streamOptions & nzStreamOption_Text && pos > 0 && line[pos-1] == '\r') line.Resize(pos); else line.Resize(pos+1); if (!SetCursorPos(GetCursorPos() - readSize + pos + 1)) NazaraWarning("Failed to reset cursos pos"); } else line.Resize(readSize); } return line; }
void TcpClient::OnOpened() { AbstractSocket::OnOpened(); SocketError errorCode; if (!SocketImpl::SetNoDelay(m_handle, m_isLowDelayEnabled, &errorCode)) NazaraWarning("Failed to set socket no delay mode (0x" + String::Number(errorCode, 16) + ')'); if (!SocketImpl::SetKeepAlive(m_handle, m_isKeepAliveEnabled, m_keepAliveTime, m_keepAliveInterval, &errorCode)) NazaraWarning("Failed to set socket keep alive mode (0x" + String::Number(errorCode, 16) + ')'); m_peerAddress = IpAddress::Invalid; m_openMode = OpenMode_ReadWrite; }
bool RenderWindow::OnWindowCreated() { m_parameters.doubleBuffered = true; m_parameters.window = GetHandle(); std::unique_ptr<Context> context(new Context); if (!context->Create(m_parameters)) { NazaraError("Failed to create context"); return false; } m_context = context.release(); if (!SetActive(true)) // Les fenêtres s'activent à la création NazaraWarning("Failed to activate window"); EnableVerticalSync(false); Vector2ui size = GetSize(); // Le scissorBox/viewport (à la création) est de la taille de la fenêtre // https://www.opengl.org/sdk/docs/man/xhtml/glGet.xml OpenGL::SetScissorBox(Recti(0, 0, size.x, size.y)); OpenGL::SetViewport(Recti(0, 0, size.x, size.y)); OnRenderTargetParametersChange(this); OnRenderTargetSizeChange(this); m_clock.Restart(); return true; }
void Skeleton::UpdateJointMap() const { #ifdef NAZARA_DEBUG if (!m_impl) { NazaraError("Invalid skeleton"); return; } #endif m_impl->jointMap.clear(); for (std::size_t i = 0; i < m_impl->joints.size(); ++i) { String name = m_impl->joints[i].GetName(); if (!name.IsEmpty()) { #if NAZARA_UTILITY_SAFE auto it = m_impl->jointMap.find(name); if (it != m_impl->jointMap.end()) { NazaraWarning("Joint name \"" + name + "\" is already present in joint map for joint #" + String::Number(it->second)); continue; } #endif m_impl->jointMap[name] = i; } } m_impl->jointMapUpdated = true; }
void SocketImpl::Close(SocketHandle handle) { NazaraAssert(handle != InvalidHandle, "Invalid handle"); if (closesocket(handle) == SOCKET_ERROR) NazaraWarning("Failed to close socket: " + Error::GetLastSystemError(WSAGetLastError())); }
void SocketImpl::ClearErrorCode(SocketHandle handle) { NazaraAssert(handle != InvalidHandle, "Invalid handle"); if (GetLastError(handle, nullptr) < 0) NazaraWarning("Failed to clear socket error code: " + Error::GetLastSystemError(WSAGetLastError())); }
void NzUberShaderLibrary::Uninitialize() { for (auto it : s_library) NazaraWarning("UberShader \"" + it.first + "\" has not been unregistred"); s_library.clear(); }
void ListenerSystem::OnUpdate(float /*elapsedTime*/) { std::size_t activeListenerCount = 0; for (const Ndk::EntityHandle& entity : GetEntities()) { // Is the listener actif ? const ListenerComponent& listener = entity->GetComponent<ListenerComponent>(); if (!listener.IsActive()) continue; // We get the position and the rotation to affect these to the listener const NodeComponent& node = entity->GetComponent<NodeComponent>(); Nz::Audio::SetListenerPosition(node.GetPosition(Nz::CoordSys_Global)); Nz::Audio::SetListenerRotation(node.GetRotation(Nz::CoordSys_Global)); // We verify the presence of a component of velocity // (The listener'speed does not move it, but disturbs the sound like Doppler effect) if (entity->HasComponent<VelocityComponent>()) { const VelocityComponent& velocity = entity->GetComponent<VelocityComponent>(); Nz::Audio::SetListenerVelocity(velocity.linearVelocity); } activeListenerCount++; } if (activeListenerCount > 1) NazaraWarning(Nz::String::Number(activeListenerCount) + " listeners were active in the same update loop"); }
void NzRenderTexture::Unlock() const { #if NAZARA_RENDERER_SAFE if (!m_impl) { NazaraError("Render texture not created"); return; } if (NzContext::GetCurrent() != m_impl->context) { NazaraError("RenderTexture cannot be used with this context"); return; } if (lockedLevel == 0) { NazaraWarning("Unlock called on non-locked texture"); return; } #endif if (--lockedLevel == 0 && lockedPrevious != m_impl->fbo) // Ici, il est important qu'un FBO soit débindé si l'ancien était 0 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, lockedPrevious); }
void Mesh::SetMaterialCount(unsigned int matCount) { #if NAZARA_UTILITY_SAFE if (!m_impl) { NazaraError("Mesh not created"); return; } if (matCount == 0) { NazaraError("A mesh should have at least a material"); return; } #endif m_impl->materials.resize(matCount); #ifdef NAZARA_DEBUG for (SubMesh* subMesh : m_impl->subMeshes) { unsigned int matIndex = subMesh->GetMaterialIndex(); if (matIndex >= matCount) { subMesh->SetMaterialIndex(0); // Pour empêcher un crash NazaraWarning("SubMesh " + String::Pointer(subMesh) + " material index is over mesh new material count (" + String::Number(matIndex) + " >= " + String::Number(matCount) + "), setting it to first material"); } } #endif }
void Buffer::Unmap() const { NazaraAssert(m_impl, "Invalid buffer"); if (!m_impl->Unmap()) NazaraWarning("Failed to unmap buffer (it's content may be undefined)"); ///TODO: Unexpected ? }
void ListenerSystem::OnUpdate(float elapsedTime) { std::size_t activeListenerCount = 0; for (const Ndk::EntityHandle& entity : GetEntities()) { // Is the listener actif ? const ListenerComponent& listener = entity->GetComponent<ListenerComponent>(); if (!listener.IsActive()) continue; Nz::Vector3f oldPos = Nz::Audio::GetListenerPosition(); // We get the position and the rotation to affect these to the listener const NodeComponent& node = entity->GetComponent<NodeComponent>(); Nz::Vector3f newPos = node.GetPosition(Nz::CoordSys_Global); Nz::Audio::SetListenerPosition(newPos); Nz::Audio::SetListenerRotation(node.GetRotation(Nz::CoordSys_Global)); // Compute listener velocity based on their old/new position Nz::Vector3f velocity = (newPos - oldPos) / elapsedTime; Nz::Audio::SetListenerVelocity(velocity); activeListenerCount++; } if (activeListenerCount > 1) NazaraWarning(Nz::String::Number(activeListenerCount) + " listeners were active in the same update loop"); }
void Node::RemoveChild(Node* node) const { auto it = std::find(m_childs.begin(), m_childs.end(), node); if (it != m_childs.end()) m_childs.erase(it); else NazaraWarning("Child not found"); }
void NzGraphics::Uninitialize() { if (s_moduleReferenceCounter != 1) { // Le module est soit encore utilisé, soit pas initialisé if (s_moduleReferenceCounter > 1) s_moduleReferenceCounter--; return; } // Libération du module s_moduleReferenceCounter = 0; // Libération de l'atlas s'il vient de nous std::shared_ptr<NzAbstractAtlas> defaultAtlas = NzFont::GetDefaultAtlas(); if (defaultAtlas && defaultAtlas->GetStorage() & nzDataStorage_Hardware) { NzFont::SetDefaultAtlas(nullptr); // La police par défaut peut faire vivre un atlas hardware après la libération du module (ce qui va être problématique) // du coup, si la police par défaut utilise un atlas hardware, on lui enlève. // Je n'aime pas cette solution mais je n'en ai pas de meilleure sous la main pour l'instant if (!defaultAtlas.unique()) { // Encore au moins une police utilise l'atlas NzFont* defaultFont = NzFont::GetDefault(); defaultFont->SetAtlas(nullptr); if (!defaultAtlas.unique()) { // Toujours pas seuls propriétaires ? Ah ben zut. NazaraWarning("Default font atlas uses hardware storage and is still used"); } } } defaultAtlas.reset(); // Loaders NzLoaders_Mesh_Unregister(); NzLoaders_OBJ_Unregister(); NzLoaders_Texture_Unregister(); NzDeferredRenderTechnique::Uninitialize(); NzForwardRenderTechnique::Uninitialize(); NzSkinningManager::Uninitialize(); NzParticleRenderer::Uninitialize(); NzParticleGenerator::Uninitialize(); NzParticleDeclaration::Uninitialize(); NzParticleController::Uninitialize(); NzMaterial::Uninitialize(); NazaraNotice("Uninitialized: Graphics module"); // Libération des dépendances NzRenderer::Uninitialize(); }
/*! * Write bits to the stream (if any) and reset the current bit cursor * \see ResetBitPosition */ void SerializationContext::FlushBits() { if (currentBitPos != 8) { ResetBitPosition(); // Serialize will reset the bit position if (!Serialize<UInt8>(*this, currentByte)) NazaraWarning("Failed to flush bits"); } }
void NzClock::Pause() { NazaraLock(m_mutex); if (!m_paused) { m_elapsedTime += NzGetMicroseconds()-m_refTime; m_paused = true; } else NazaraWarning("Clock is already paused, ignoring..."); }
void Node::AddChild(Node* node) const { #ifdef NAZARA_DEBUG if (std::find(m_childs.begin(), m_childs.end(), node) != m_childs.end()) { NazaraWarning("Child node is already a child of parent node"); return; } #endif m_childs.push_back(node); }
void NzClock::Unpause() { NazaraLock(m_mutex); if (m_paused) { m_refTime = NzGetMicroseconds(); m_paused = false; } else NazaraWarning("Clock is not paused, ignoring..."); }
void TextSprite::OnAtlasInvalidated(const AbstractAtlas* atlas) { #ifdef NAZARA_DEBUG if (m_atlases.find(atlas) == m_atlases.end()) { NazaraInternalError("Not listening to " + String::Pointer(atlas)); return; } #endif NazaraWarning("TextSprite " + String::Pointer(this) + " has been cleared because atlas " + String::Pointer(atlas) + " has been invalidated (cleared or released)"); Clear(); }
void Buffer::Unmap() const { #if NAZARA_UTILITY_SAFE if (!m_impl) { NazaraError("Buffer not valid"); return; } #endif if (!m_impl->Unmap()) NazaraWarning("Failed to unmap buffer (it's content may be undefined)"); ///TODO: Unexpected ? }
bool UdpSocket::ReceivePacket(NetPacket* packet, IpAddress* from) { NazaraAssert(packet, "Invalid packet"); // I'm not sure what's the best between having a 65k bytes buffer ready for any datagram size // or querying the next datagram size every time, for now I'll leave it as is packet->Reset(NetCode_Invalid, std::numeric_limits<UInt16>::max()); packet->Resize(std::numeric_limits<UInt16>::max()); std::size_t received; if (!Receive(packet->GetData(), static_cast<std::size_t>(packet->GetSize()), from, &received)) return false; if (received == 0) return false; //< No datagram received Nz::UInt16 netCode; Nz::UInt32 packetSize; if (!NetPacket::DecodeHeader(packet->GetConstData(), &packetSize, &netCode)) { m_lastError = SocketError_Packet; NazaraWarning("Invalid header data"); return false; } if (packetSize != received) { m_lastError = SocketError_Packet; NazaraWarning("Invalid packet size (packet size is " + String::Number(packetSize) + " bytes, received " + Nz::String::Number(received) + " bytes)"); return false; } packet->Resize(received); packet->SetNetCode(netCode); return true; }
void GuillotineImageAtlas::Free(SparsePtr<const Rectui> rects, SparsePtr<unsigned int> layers, unsigned int count) { for (unsigned int i = 0; i < count; ++i) { #ifdef NAZARA_DEBUG if (layers[i] >= m_layers.size()) { NazaraWarning("Rectangle #" + String::Number(i) + " belong to an out-of-bounds layer (" + String::Number(i) + " >= " + String::Number(m_layers.size()) + ")"); continue; } #endif m_layers[layers[i]].binPack.FreeRectangle(rects[i]); m_layers[layers[i]].freedRectangles++; } }
void OpenAL::CloseDevice() { if (s_device) { if (s_context) { alcMakeContextCurrent(nullptr); alcDestroyContext(s_context); s_context = nullptr; } if (!alcCloseDevice(s_device)) // We could not close the close, this means that it's still in use NazaraWarning("Failed to close device"); s_device = nullptr; } }
void NzSkeletalModel::SetMesh(NzMesh* mesh) { #if NAZARA_GRAPHICS_SAFE if (mesh && mesh->GetAnimationType() != nzAnimationType_Skeletal) { NazaraError("Mesh animation type must be skeletal"); return; } #endif NzModel::SetMesh(mesh); if (m_mesh) { if (m_animation && m_animation->GetJointCount() != m_mesh->GetJointCount()) { NazaraWarning("Animation joint count is not matching new mesh joint count, disabling animation..."); SetAnimation(nullptr); } m_skeleton = *m_mesh->GetSkeleton(); // Copie du squelette template } }
void NzRenderTexture::Destroy() { if (m_impl) { bool canFreeFBO = true; #if NAZARA_RENDERER_SAFE if (NzContext::GetCurrent() != m_impl->context) { NazaraWarning("RenderTexture should be destroyed by it's creation context, this will cause leaks"); canFreeFBO = false; } #endif m_impl->context->RemoveResourceListener(this); for (const Attachment& attachment : m_impl->attachements) { if (attachment.isUsed) { if (attachment.isBuffer) glDeleteRenderbuffers(1, &attachment.buffer); // Les Renderbuffers sont partagés entre les contextes: Ne posera pas de problème else { attachment.texture->SetRenderTexture(nullptr); attachment.texture->RemoveResourceListener(this); } } } if (canFreeFBO) glDeleteFramebuffers(1, &m_impl->fbo); delete m_impl; m_impl = nullptr; } }
void NzOBJParser::Warning(const NzString& message) { NazaraWarning(message + " at line #" + NzString::Number(m_lineCount)); }
NzDeferredRenderTechnique::NzDeferredRenderTechnique() : m_renderQueue(static_cast<NzForwardRenderQueue*>(m_forwardTechnique.GetRenderQueue())), m_GBufferSize(0U) { m_depthStencilBuffer = new NzRenderBuffer; m_depthStencilBuffer->SetPersistent(false); for (unsigned int i = 0; i < 2; ++i) { m_workTextures[i] = new NzTexture; m_workTextures[i]->SetPersistent(false); } for (unsigned int i = 0; i < 3; ++i) { m_GBuffer[i] = new NzTexture; m_GBuffer[i]->SetPersistent(false); } try { NzErrorFlags errFlags(nzErrorFlag_ThrowException); ResetPass(nzRenderPassType_Final, 0); ResetPass(nzRenderPassType_Geometry, 0); ResetPass(nzRenderPassType_Lighting, 0); } catch (const std::exception& e) { NazaraUnused(e); NzErrorFlags errFlags(nzErrorFlag_ThrowExceptionDisabled); NazaraError("Failed to add geometry and/or phong lighting pass"); throw; } try { NzErrorFlags errFlags(nzErrorFlag_ThrowException); ResetPass(nzRenderPassType_AA, 0); } catch (const std::exception& e) { NazaraUnused(e); NazaraWarning("Failed to add FXAA pass"); } try { NzErrorFlags errFlags(nzErrorFlag_ThrowException); ResetPass(nzRenderPassType_Bloom, 0); } catch (const std::exception& e) { NazaraUnused(e); NazaraWarning("Failed to add bloom pass"); } try { NzErrorFlags errFlags(nzErrorFlag_ThrowException); NzDeferredRenderPass* dofPass = ResetPass(nzRenderPassType_DOF, 0); dofPass->Enable(false); } catch (const std::exception& e) { NazaraUnused(e); NazaraWarning("Failed to add DOF pass"); } try { NzErrorFlags errFlags(nzErrorFlag_ThrowException); NzDeferredRenderPass* fogPass = ResetPass(nzRenderPassType_Fog, 0); fogPass->Enable(false); } catch (const std::exception& e) { NazaraUnused(e); NazaraWarning("Failed to add fog pass"); } try { NzErrorFlags errFlags(nzErrorFlag_ThrowException); ResetPass(nzRenderPassType_Forward, 0); } catch (const std::exception& e) { NazaraUnused(e); NazaraWarning("Failed to add forward pass"); } try { NzErrorFlags errFlags(nzErrorFlag_ThrowException); ResetPass(nzRenderPassType_SSAO, 0); } catch (const std::exception& e) { NazaraUnused(e); NazaraWarning("Failed to add SSAO pass"); } }
bool NzDeferredRenderTechnique::Initialize() { const nzUInt8 fragmentSource_BloomBright[] = { #include <Nazara/Graphics/Resources/DeferredShading/Shaders/BloomBright.frag.h> }; const nzUInt8 fragmentSource_BloomFinal[] = { #include <Nazara/Graphics/Resources/DeferredShading/Shaders/BloomFinal.frag.h> }; const nzUInt8 fragmentSource_DirectionalLight[] = { #include <Nazara/Graphics/Resources/DeferredShading/Shaders/DirectionalLight.frag.h> }; const nzUInt8 fragmentSource_FXAA[] = { #include <Nazara/Graphics/Resources/DeferredShading/Shaders/FXAA.frag.h> }; const nzUInt8 fragmentSource_GBufferClear[] = { #include <Nazara/Graphics/Resources/DeferredShading/Shaders/GBufferClear.frag.h> }; const nzUInt8 fragmentSource_GaussianBlur[] = { #include <Nazara/Graphics/Resources/DeferredShading/Shaders/GaussianBlur.frag.h> }; const nzUInt8 fragmentSource_PointSpotLight[] = { #include <Nazara/Graphics/Resources/DeferredShading/Shaders/PointSpotLight.frag.h> }; const char vertexSource_Basic[] = "#version 140\n" "in vec3 VertexPosition;\n" "uniform mat4 WorldViewProjMatrix;\n" "void main()\n" "{\n" "gl_Position = WorldViewProjMatrix * vec4(VertexPosition, 1.0);\n" "}\n"; const char vertexSource_PostProcess[] = "#version 140\n" "in vec3 VertexPosition;\n" "void main()\n" "{\n" "gl_Position = vec4(VertexPosition, 1.0);" "}\n"; NzShaderStage basicVertexStage(nzShaderStage_Vertex); if (!basicVertexStage.IsValid()) { NazaraError("Failed to create basic vertex shader"); return false; } basicVertexStage.SetSource(vertexSource_Basic, sizeof(vertexSource_Basic)); if (!basicVertexStage.Compile()) { NazaraError("Failed to compile basic vertex shader"); return false; } NzShaderStage ppVertexStage(nzShaderStage_Vertex); if (!ppVertexStage.IsValid()) { NazaraError("Failed to create vertex shader"); return false; } ppVertexStage.SetSource(vertexSource_PostProcess, sizeof(vertexSource_PostProcess)); if (!ppVertexStage.Compile()) { NazaraError("Failed to compile vertex shader"); return false; } NzString error; NzShader* shader; // Shaders critiques (Nécessaires pour le Deferred Shading minimal) shader = RegisterDeferredShader("DeferredGBufferClear", fragmentSource_GBufferClear, sizeof(fragmentSource_GBufferClear), ppVertexStage, &error); if (!shader) { NazaraError("Failed to register critical shader: " + error); return false; } shader = RegisterDeferredShader("DeferredDirectionnalLight", fragmentSource_DirectionalLight, sizeof(fragmentSource_DirectionalLight), ppVertexStage, &error); if (!shader) { NazaraError("Failed to register critical shader: " + error); return false; } shader->SendInteger(shader->GetUniformLocation("GBuffer0"), 0); shader->SendInteger(shader->GetUniformLocation("GBuffer1"), 1); shader->SendInteger(shader->GetUniformLocation("GBuffer2"), 2); shader = RegisterDeferredShader("DeferredPointSpotLight", fragmentSource_PointSpotLight, sizeof(fragmentSource_PointSpotLight), basicVertexStage, &error); if (!shader) { NazaraError("Failed to register critical shader: " + error); return false; } shader->SendInteger(shader->GetUniformLocation("GBuffer0"), 0); shader->SendInteger(shader->GetUniformLocation("GBuffer1"), 1); shader->SendInteger(shader->GetUniformLocation("GBuffer2"), 2); // Shaders optionnels (S'ils ne sont pas présents, le rendu minimal sera quand même assuré) shader = RegisterDeferredShader("DeferredBloomBright", fragmentSource_BloomBright, sizeof(fragmentSource_BloomBright), ppVertexStage, &error); if (shader) shader->SendInteger(shader->GetUniformLocation("ColorTexture"), 0); else { NazaraWarning("Failed to register bloom (bright pass) shader, certain features will not work: " + error); } shader = RegisterDeferredShader("DeferredBloomFinal", fragmentSource_BloomFinal, sizeof(fragmentSource_BloomFinal), ppVertexStage, &error); if (shader) { shader->SendInteger(shader->GetUniformLocation("ColorTexture"), 0); shader->SendInteger(shader->GetUniformLocation("BloomTexture"), 1); } else { NazaraWarning("Failed to register bloom (final pass) shader, certain features will not work: " + error); } shader = RegisterDeferredShader("DeferredFXAA", fragmentSource_FXAA, sizeof(fragmentSource_FXAA), ppVertexStage, &error); if (shader) shader->SendInteger(shader->GetUniformLocation("ColorTexture"), 0); else { NazaraWarning("Failed to register FXAA shader, certain features will not work: " + error); } shader = RegisterDeferredShader("DeferredGaussianBlur", fragmentSource_GaussianBlur, sizeof(fragmentSource_GaussianBlur), ppVertexStage, &error); if (shader) shader->SendInteger(shader->GetUniformLocation("ColorTexture"), 0); else { NazaraWarning("Failed to register gaussian blur shader, certain features will not work: " + error); } return true; }
bool Graphics::Initialize() { if (IsInitialized()) { s_moduleReferenceCounter++; return true; // Already initialized } // Initialisation of dependances if (!Renderer::Initialize()) { NazaraError("Failed to initialize Renderer module"); return false; } s_moduleReferenceCounter++; // Initialisation of the module CallOnExit onExit(Graphics::Uninitialize); // Materials if (!MaterialPipeline::Initialize()) { NazaraError("Failed to initialize material pipelines"); return false; } if (!Material::Initialize()) { NazaraError("Failed to initialize materials"); return false; } // Renderables if (!ParticleController::Initialize()) { NazaraError("Failed to initialize particle controllers"); return false; } if (!ParticleDeclaration::Initialize()) { NazaraError("Failed to initialize particle declarations"); return false; } if (!ParticleGenerator::Initialize()) { NazaraError("Failed to initialize particle generators"); return false; } if (!ParticleRenderer::Initialize()) { NazaraError("Failed to initialize particle renderers"); return false; } if (!SkinningManager::Initialize()) { NazaraError("Failed to initialize skinning manager"); return false; } if (!SkyboxBackground::Initialize()) { NazaraError("Failed to initialize skybox backgrounds"); return false; } if (!Sprite::Initialize()) { NazaraError("Failed to initialize sprites"); return false; } if (!TileMap::Initialize()) { NazaraError("Failed to initialize tilemaps"); return false; } // Generic loaders Loaders::RegisterMesh(); Loaders::RegisterTexture(); // Render techniques if (!DepthRenderTechnique::Initialize()) { NazaraError("Failed to initialize Depth Rendering"); return false; } if (!ForwardRenderTechnique::Initialize()) { NazaraError("Failed to initialize Forward Rendering"); return false; } RenderTechniques::Register(RenderTechniques::ToString(RenderTechniqueType_BasicForward), 0, []() -> AbstractRenderTechnique* { return new ForwardRenderTechnique; }); if (DeferredRenderTechnique::IsSupported()) { if (DeferredRenderTechnique::Initialize()) RenderTechniques::Register(RenderTechniques::ToString(RenderTechniqueType_DeferredShading), 20, []() -> AbstractRenderTechnique* { return new DeferredRenderTechnique; }); else { NazaraWarning("Failed to initialize Deferred Rendering"); } } Font::SetDefaultAtlas(std::make_shared<GuillotineTextureAtlas>()); // Textures std::array<UInt8, 6> whitePixels = { { 255, 255, 255, 255, 255, 255 } }; Nz::TextureRef whiteTexture = Nz::Texture::New(); whiteTexture->Create(ImageType_2D, PixelFormatType_L8, 1, 1); whiteTexture->Update(whitePixels.data()); TextureLibrary::Register("White2D", std::move(whiteTexture)); Nz::TextureRef whiteCubemap = Nz::Texture::New(); whiteCubemap->Create(ImageType_Cubemap, PixelFormatType_L8, 1, 1); whiteCubemap->Update(whitePixels.data()); TextureLibrary::Register("WhiteCubemap", std::move(whiteCubemap)); onExit.Reset(); NazaraNotice("Initialized: Graphics module"); return true; }
void Graphics::Uninitialize() { if (s_moduleReferenceCounter != 1) { // The module is still in use, or can not be uninitialized if (s_moduleReferenceCounter > 1) s_moduleReferenceCounter--; return; } // Free of module s_moduleReferenceCounter = 0; // Free of atlas if it is ours std::shared_ptr<AbstractAtlas> defaultAtlas = Font::GetDefaultAtlas(); if (defaultAtlas && defaultAtlas->GetStorage() == DataStorage_Hardware) { Font::SetDefaultAtlas(nullptr); // The default police can make live one hardware atlas after the free of a module (which could be problematic) // So, if the default police use a hardware atlas, we stole it. // I don't like this solution, but I don't have any better if (!defaultAtlas.unique()) { // Still at least one police use the atlas Font* defaultFont = Font::GetDefault(); defaultFont->SetAtlas(nullptr); if (!defaultAtlas.unique()) { // Still not the only one to own it ? Then crap. NazaraWarning("Default font atlas uses hardware storage and is still used"); } } } defaultAtlas.reset(); // Textures TextureLibrary::Unregister("White2D"); TextureLibrary::Unregister("WhiteCubemap"); // Loaders Loaders::UnregisterMesh(); Loaders::UnregisterTexture(); // Renderables ParticleRenderer::Uninitialize(); ParticleGenerator::Uninitialize(); ParticleDeclaration::Uninitialize(); ParticleController::Uninitialize(); SkyboxBackground::Uninitialize(); Sprite::Uninitialize(); TileMap::Uninitialize(); // Render techniques DeferredRenderTechnique::Uninitialize(); DepthRenderTechnique::Uninitialize(); ForwardRenderTechnique::Uninitialize(); SkinningManager::Uninitialize(); // Materials Material::Uninitialize(); MaterialPipeline::Uninitialize(); NazaraNotice("Uninitialized: Graphics module"); // Free of dependances Renderer::Uninitialize(); }