ezResult ezImage::SaveTo(const char* szFileName, ezLogInterface* pLog) { EZ_LOG_BLOCK(pLog, "Writing Image", szFileName); ezFileWriter writer; if (writer.Open(szFileName) == EZ_FAILURE) { ezLog::Warning(pLog, "Failed to open image file '%s'", szFileName); return EZ_FAILURE; } ezStringView it = ezPathUtils::GetFileExtension(szFileName); for (ezImageFileFormatBase* pFormat = ezImageFileFormatBase::GetFirstInstance(); pFormat; pFormat = pFormat->GetNextInstance()) { if (pFormat->CanWriteFileType(it.GetData())) { if (pFormat->WriteImage(writer, *this, pLog) != EZ_SUCCESS) { ezLog::Warning(pLog, "Failed to write image file '%s'", szFileName); return EZ_FAILURE; } return EZ_SUCCESS; } } ezLog::Warning(pLog, "No known image file format for extension '%s'", it.GetData()); return EZ_FAILURE; }
ezResourceLoadDesc ezCollectionResource::UpdateContent(ezStreamReader* Stream) { EZ_LOG_BLOCK("ezCollectionResource::UpdateContent", GetResourceDescription().GetData()); ezResourceLoadDesc res; res.m_uiQualityLevelsDiscardable = 0; res.m_uiQualityLevelsLoadable = 0; if (Stream == nullptr) { res.m_State = ezResourceState::LoadedResourceMissing; return res; } // skip the absolute file path data that the standard file reader writes into the stream { ezString sAbsFilePath; (*Stream) >> sAbsFilePath; } // skip the asset file header at the start of the file ezAssetFileHeader AssetHash; AssetHash.Read(*Stream); m_Collection.Load(*Stream); res.m_State = ezResourceState::Loaded; return res; }
ezResourceLoadDesc ezSurfaceResource::UpdateContent(ezStreamReader* Stream) { EZ_LOG_BLOCK("ezSurfaceResource::UpdateContent", GetResourceDescription().GetData()); m_Interactions.Clear(); ezResourceLoadDesc res; res.m_uiQualityLevelsDiscardable = 0; res.m_uiQualityLevelsLoadable = 0; if (Stream == nullptr) { res.m_State = ezResourceState::LoadedResourceMissing; return res; } // skip the absolute file path data that the standard file reader writes into the stream { ezString sAbsFilePath; (*Stream) >> sAbsFilePath; } ezAssetFileHeader AssetHash; AssetHash.Read(*Stream); { ezResourceHandleReadContext context; context.BeginReadingFromStream(Stream); context.BeginRestoringHandles(Stream); ezSurfaceResourceDescriptor dummy; dummy.Load(*Stream); context.EndReadingFromStream(Stream); context.EndRestoringHandles(); CreateResource(std::move(dummy)); } // configure the lookup table { m_Interactions.Reserve(m_Descriptor.m_Interactions.GetCount()); for (const auto& i : m_Descriptor.m_Interactions) { ezTempHashedString s(i.m_sInteractionType.GetData()); m_Interactions[s.GetHash()] = &i; } } res.m_State = ezResourceState::Loaded; return res; }
Scene::Scene(const RenderWindowGL& renderWindow) : m_pScreenAlignedTriangle(std::make_shared<gl::ScreenAlignedTriangle>()), m_pCamera(EZ_DEFAULT_NEW_UNIQUE(FreeCamera, ezAngle::Degree(70.0f), static_cast<float>(GeneralConfig::g_ResolutionWidth.GetValue()) / GeneralConfig::g_ResolutionHeight.GetValue())), m_pFont(EZ_DEFAULT_NEW_UNIQUE(gl::Font, "Arial", 20, renderWindow.GetDeviceContext())), m_ExtractGeometryTimer(EZ_DEFAULT_NEW_UNIQUE(gl::TimerQuery)), m_DrawTimer(EZ_DEFAULT_NEW_UNIQUE(gl::TimerQuery)), m_UserInterface(EZ_DEFAULT_NEW_UNIQUE(AntTweakBarInterface)) { EZ_LOG_BLOCK("Scene init"); m_pVoxelTerrain = EZ_DEFAULT_NEW(VoxelTerrain)(m_pScreenAlignedTriangle); m_pBackground = EZ_DEFAULT_NEW(Background)(m_pScreenAlignedTriangle); // global ubo init ezDynamicArray<const gl::ShaderObject*> cameraUBOusingShader; cameraUBOusingShader.PushBack(&m_pVoxelTerrain->GetShaderDirectVolVis()); cameraUBOusingShader.PushBack(&m_pBackground->GetShader()); cameraUBOusingShader.PushBack(&m_pVoxelTerrain->GetShaderVolumeRenderShader()); m_CameraUBO.Init(cameraUBOusingShader, "Camera"); ezDynamicArray<const gl::ShaderObject*> globalSceneInfoUBOusingShader; globalSceneInfoUBOusingShader.PushBack(&m_pVoxelTerrain->GetShaderDirectVolVis()); globalSceneInfoUBOusingShader.PushBack(&m_pVoxelTerrain->GetShaderVolumeRenderShader()); m_GlobalSceneInfo.Init(globalSceneInfoUBOusingShader, "GlobalSceneInfo"); /* ezDynamicArray<const gl::ShaderObject*> timeUBOusingShader; cameraUBOusingShader.PushBack(&m_DirectVolVisShader); m_TimeUBO.Init(cameraUBOusingShader, "Time"); */ m_GlobalSceneInfo["GlobalDirLightDirection"].Set(ezVec3(1,-2.0f,1).GetNormalized()); m_GlobalSceneInfo["GlobalDirLightColor"].Set(ezVec3(0.98f, 0.98f, 0.8f)); m_GlobalSceneInfo["GlobalAmbient"].Set(ezVec3(0.3f, 0.3f, 0.3f)); ezVec3 vCameraPos = m_pVoxelTerrain->GetWorldSize(); vCameraPos.x /=2; vCameraPos.z /=2; m_pCamera->SetPosition(vCameraPos); // user interface m_UserInterface->Init(); }
void ezGameApplicationBase::Init_ConfigureTags() { EZ_LOG_BLOCK("Reading Tags", "Tags.ddl"); ezFileReader file; if (file.Open(":project/Tags.ddl").Failed()) { ezLog::Dev("'Tags.ddl' does not exist"); return; } ezStringBuilder tmp; ezOpenDdlReader reader; if (reader.ParseDocument(file).Failed()) { ezLog::Error("Failed to parse DDL data in tags file"); return; } const ezOpenDdlReaderElement* pRoot = reader.GetRootElement(); for (const ezOpenDdlReaderElement* pTags = pRoot->GetFirstChild(); pTags != nullptr; pTags = pTags->GetSibling()) { if (!pTags->IsCustomType("Tag")) continue; const ezOpenDdlReaderElement* pName = pTags->FindChildOfType(ezOpenDdlPrimitiveType::String, "Name"); if (!pName) { ezLog::Error("Incomplete tag declaration!"); continue; } tmp = pName->GetPrimitivesString()[0]; ezTagRegistry::GetGlobalRegistry().RegisterTag(tmp); } }
ezResourceLoadDesc ezPropertyAnimResource::UpdateContent(ezStreamReader* Stream) { EZ_LOG_BLOCK("ezPropertyAnimResource::UpdateContent", GetResourceDescription().GetData()); ezResourceLoadDesc res; res.m_uiQualityLevelsDiscardable = 0; res.m_uiQualityLevelsLoadable = 0; if (Stream == nullptr) { res.m_State = ezResourceState::LoadedResourceMissing; return res; } // skip the absolute file path data that the standard file reader writes into the stream { ezString sAbsFilePath; (*Stream) >> sAbsFilePath; } // skip the asset file header at the start of the file ezAssetFileHeader AssetHash; AssetHash.Read(*Stream); { ezResourceHandleReadContext context; context.BeginReadingFromStream(Stream); context.BeginRestoringHandles(Stream); m_pDescriptor = EZ_DEFAULT_NEW(ezPropertyAnimResourceDescriptor); m_pDescriptor->Load(*Stream); context.EndReadingFromStream(Stream); context.EndRestoringHandles(); } res.m_State = ezResourceState::Loaded; return res; }
ezResourceLoadDesc ezPrefabResource::UpdateContent(ezStreamReader* Stream) { EZ_LOG_BLOCK("ezPrefabResource::UpdateContent", GetResourceDescription().GetData()); ezResourceLoadDesc res; res.m_uiQualityLevelsDiscardable = 0; res.m_uiQualityLevelsLoadable = 0; if (Stream == nullptr) { res.m_State = ezResourceState::LoadedResourceMissing; return res; } ezStreamReader& s = *Stream; // skip the absolute file path data that the standard file reader writes into the stream { ezString sAbsFilePath; s >> sAbsFilePath; } ezAssetFileHeader AssetHash; AssetHash.Read(s); char szSceneTag[16]; s.ReadBytes(szSceneTag, sizeof(char) * 16); EZ_ASSERT_DEV(ezStringUtils::IsEqualN(szSceneTag, "[ezBinaryScene]", 16), "The given file is not a valid prefab file"); if (!ezStringUtils::IsEqualN(szSceneTag, "[ezBinaryScene]", 16)) { res.m_State = ezResourceState::LoadedResourceMissing; return res; } m_WorldReader.ReadWorldDescription(s); if (AssetHash.GetFileVersion() >= 4) { ezUInt32 uiExposedParams = 0; s >> uiExposedParams; m_PrefabParamDescs.SetCount(uiExposedParams); for (ezUInt32 i = 0; i < uiExposedParams; ++i) { auto& ppd = m_PrefabParamDescs[i]; ppd.Load(s); // initialize the cached property path here once // so we can only apply it later as often as needed { if (ppd.m_uiComponentTypeHash == 0) ppd.m_CachedPropertyPath.InitializeFromPath(*ezGetStaticRTTI<ezGameObject>(), ppd.m_sProperty); else { for (const ezRTTI* pRtti = ezRTTI::GetFirstInstance(); pRtti != nullptr; pRtti = pRtti->GetNextInstance()) { if (pRtti->GetTypeNameHash() == ppd.m_uiComponentTypeHash) { ppd.m_CachedPropertyPath.InitializeFromPath(*pRtti, ppd.m_sProperty); break; } } } } } // sort exposed parameter descriptions by name hash for quicker access m_PrefabParamDescs.Sort([](const ezExposedPrefabParameterDesc& lhs, const ezExposedPrefabParameterDesc& rhs) -> bool { return lhs.m_sExposeName.GetHash() < rhs.m_sExposeName.GetHash(); }); }
ezShaderConstantBufferLayout* ezShaderCompilerHLSL::ReflectConstantBufferLayout( ezShaderStageBinary& pStageBinary, ID3D11ShaderReflectionConstantBuffer* pConstantBufferReflection) { D3D11_SHADER_BUFFER_DESC shaderBufferDesc; if (FAILED(pConstantBufferReflection->GetDesc(&shaderBufferDesc))) { return nullptr; } EZ_LOG_BLOCK("Constant Buffer Layout", shaderBufferDesc.Name); ezLog::Debug("Constant Buffer has {0} variables, Size is {1}", shaderBufferDesc.Variables, shaderBufferDesc.Size); ezShaderConstantBufferLayout* pLayout = pStageBinary.CreateConstantBufferLayout(); pLayout->m_uiTotalSize = shaderBufferDesc.Size; for (ezUInt32 var = 0; var < shaderBufferDesc.Variables; ++var) { ID3D11ShaderReflectionVariable* pVar = pConstantBufferReflection->GetVariableByIndex(var); D3D11_SHADER_VARIABLE_DESC svd; pVar->GetDesc(&svd); EZ_LOG_BLOCK("Constant", svd.Name); D3D11_SHADER_TYPE_DESC std; pVar->GetType()->GetDesc(&std); ezShaderConstantBufferLayout::Constant constant; constant.m_uiArrayElements = ezMath::Max(std.Elements, 1u); constant.m_uiOffset = svd.StartOffset; constant.m_sName.Assign(svd.Name); if (std.Class == D3D_SVC_SCALAR || std.Class == D3D_SVC_VECTOR) { switch (std.Type) { case D3D_SVT_FLOAT: constant.m_Type = (ezShaderConstantBufferLayout::Constant::Type::Enum)( (ezInt32)ezShaderConstantBufferLayout::Constant::Type::Float1 + std.Columns - 1); break; case D3D_SVT_INT: constant.m_Type = (ezShaderConstantBufferLayout::Constant::Type::Enum)( (ezInt32)ezShaderConstantBufferLayout::Constant::Type::Int1 + std.Columns - 1); break; case D3D_SVT_UINT: constant.m_Type = (ezShaderConstantBufferLayout::Constant::Type::Enum)( (ezInt32)ezShaderConstantBufferLayout::Constant::Type::UInt1 + std.Columns - 1); break; case D3D_SVT_BOOL: if (std.Columns == 1) { constant.m_Type = ezShaderConstantBufferLayout::Constant::Type::Bool; } break; default: break; } } else if (std.Class == D3D_SVC_MATRIX_COLUMNS) { if (std.Type != D3D_SVT_FLOAT) { ezLog::Error("Variable '{0}': Only float matrices are supported", svd.Name); continue; } if (std.Columns == 3 && std.Rows == 3) { constant.m_Type = ezShaderConstantBufferLayout::Constant::Type::Mat3x3; } else if (std.Columns == 4 && std.Rows == 4) { constant.m_Type = ezShaderConstantBufferLayout::Constant::Type::Mat4x4; } else { ezLog::Error("Variable '{0}': {1}x{2} matrices are not supported", svd.Name, std.Rows, std.Columns); continue; } } else if (std.Class == D3D_SVC_MATRIX_ROWS) { ezLog::Error("Variable '{0}': Row-Major matrices are not supported", svd.Name); continue; } else if (std.Class == D3D_SVC_STRUCT) { continue; } if (constant.m_Type == ezShaderConstantBufferLayout::Constant::Type::Default) { ezLog::Error("Variable '{0}': Variable type '{1}' is unknown / not supported", svd.Name, std.Class); continue; } pLayout->m_Constants.PushBack(constant); } return pLayout; }
ezResult CompileDXShader(const char* szFile, const char* szSource, bool bDebug, const char* szProfile, const char* szEntryPoint, ezDynamicArray<ezUInt8>& out_ByteCode) { out_ByteCode.Clear(); ID3DBlob* pResultBlob = nullptr; ID3DBlob* pErrorBlob = nullptr; const char* szCompileSource = szSource; ezStringBuilder sDebugSource; UINT flags1 = 0; if (bDebug) { flags1 = D3DCOMPILE_DEBUG | D3DCOMPILE_PREFER_FLOW_CONTROL | D3DCOMPILE_SKIP_OPTIMIZATION | D3DCOMPILE_ENABLE_STRICTNESS; // In debug mode we need to remove '#line' as any shader debugger won't work with them. sDebugSource = szSource; sDebugSource.ReplaceAll("#line ", "//ine "); szCompileSource = sDebugSource; } if (FAILED(D3DCompile( szCompileSource, strlen(szCompileSource), szFile, nullptr, nullptr, szEntryPoint, szProfile, flags1, 0, &pResultBlob, &pErrorBlob))) { if (bDebug) { // Try again with '#line' intact to get correct error messages with file and line info. pErrorBlob->Release(); pErrorBlob = nullptr; EZ_VERIFY(FAILED(D3DCompile( szSource, strlen(szSource), szFile, nullptr, nullptr, szEntryPoint, szProfile, flags1, 0, &pResultBlob, &pErrorBlob)), "Debug compilation with commented out '#line' failed but original version did not."); } const char* szError = static_cast<const char*>(pErrorBlob->GetBufferPointer()); EZ_LOG_BLOCK("Shader Compilation Failed", szFile); ezLog::Error("Could not compile shader '{0}' for profile '{1}'", szFile, szProfile); ezLog::Error("{0}", szError); pErrorBlob->Release(); return EZ_FAILURE; } if (pErrorBlob != nullptr) { const char* szError = static_cast<const char*>(pErrorBlob->GetBufferPointer()); EZ_LOG_BLOCK("Shader Compilation Error Message", szFile); ezLog::Dev("{0}", szError); pErrorBlob->Release(); } if (pResultBlob != nullptr) { out_ByteCode.SetCountUninitialized((ezUInt32)pResultBlob->GetBufferSize()); ezMemoryUtils::Copy(out_ByteCode.GetData(), static_cast<ezUInt8*>(pResultBlob->GetBufferPointer()), out_ByteCode.GetCount()); pResultBlob->Release(); } return EZ_SUCCESS; }
ezResourceLoadDesc ezDecalAtlasResource::UpdateContent(ezStreamReader* Stream) { EZ_LOG_BLOCK("ezDecalAtlasResource::UpdateContent", GetResourceDescription().GetData()); ezResourceLoadDesc res; res.m_uiQualityLevelsDiscardable = 0; res.m_uiQualityLevelsLoadable = 0; res.m_State = ezResourceState::LoadedResourceMissing; if (Stream == nullptr) return res; // skip the absolute file path data that the standard file reader writes into the stream { ezString sAbsFilePath; (*Stream) >> sAbsFilePath; } // skip the asset header { ezAssetFileHeader header; header.Read(*Stream); } { ezUInt8 uiVersion = 0; *Stream >> uiVersion; EZ_ASSERT_DEV(uiVersion == 1 || uiVersion == 2, "Invalid decal atlas version {0}", uiVersion); // this version is now incompatible if (uiVersion == 1) return res; } // read the textures { ezDdsFileFormat dds; ezImage baseColor, normal; if (dds.ReadImage(*Stream, baseColor, ezLog::GetThreadLocalLogSystem(), "dds").Failed()) { ezLog::Error("Failed to load baseColor image for decal atlas"); return res; } if (dds.ReadImage(*Stream, normal, ezLog::GetThreadLocalLogSystem(), "dds").Failed()) { ezLog::Error("Failed to load normal image for decal atlas"); return res; } CreateLayerTexture(baseColor, true, m_hBaseColor); CreateLayerTexture(normal, false, m_hNormal); m_BaseColorSize = ezVec2U32(baseColor.GetWidth(), baseColor.GetHeight()); m_NormalSize = ezVec2U32(normal.GetWidth(), normal.GetHeight()); } ReadDecalInfo(Stream); res.m_State = ezResourceState::Loaded; return res; }
void ezWorld::Update() { CheckForWriteAccess(); EZ_LOG_BLOCK(m_Data.m_sName.GetData()); { ezStringBuilder sStatName; sStatName.Format("World Update/{0}/Game Object Count", m_Data.m_sName); ezStringBuilder sStatValue; ezStats::SetStat(sStatName, GetObjectCount()); } m_Data.m_Clock.SetPaused(!m_Data.m_bSimulateWorld); m_Data.m_Clock.Update(); // initialize phase { EZ_PROFILE_SCOPE("Initialize Phase"); ProcessComponentsToInitialize(); ProcessUpdateFunctionsToRegister(); ProcessQueuedMessages(ezObjectMsgQueueType::AfterInitialized); } // pre-async phase { EZ_PROFILE_SCOPE("Pre-Async Phase"); ProcessQueuedMessages(ezObjectMsgQueueType::NextFrame); UpdateSynchronous(m_Data.m_UpdateFunctions[ezComponentManagerBase::UpdateFunctionDesc::Phase::PreAsync]); } // async phase { // remove write marker but keep the read marker. Thus no one can mark the world for writing now. Only reading is allowed in async phase. m_Data.m_WriteThreadID = (ezThreadID)0; EZ_PROFILE_SCOPE("Async Phase"); UpdateAsynchronous(); // restore write marker m_Data.m_WriteThreadID = ezThreadUtils::GetCurrentThreadID(); } // post-async phase { EZ_PROFILE_SCOPE("Post-Async Phase"); ProcessQueuedMessages(ezObjectMsgQueueType::PostAsync); UpdateSynchronous(m_Data.m_UpdateFunctions[ezComponentManagerBase::UpdateFunctionDesc::Phase::PostAsync]); } // delete dead objects and update the object hierarchy { EZ_PROFILE_SCOPE("Delete Dead Objects"); DeleteDeadObjects(); DeleteDeadComponents(); } // update transforms { float fInvDelta = 0.0f; // when the clock is paused just use zero const float fDelta = (float)m_Data.m_Clock.GetTimeDiff().GetSeconds(); if (fDelta > 0.0f) fInvDelta = 1.0f / fDelta; EZ_PROFILE_SCOPE("Update Transforms"); m_Data.UpdateGlobalTransforms(fInvDelta); } // post-transform phase { EZ_PROFILE_SCOPE("Post-Transform Phase"); ProcessQueuedMessages(ezObjectMsgQueueType::PostTransform); UpdateSynchronous(m_Data.m_UpdateFunctions[ezComponentManagerBase::UpdateFunctionDesc::Phase::PostTransform]); } // Process again so new component can receive render messages, otherwise we introduce a frame delay. { EZ_PROFILE_SCOPE("Initialize Phase 2"); ProcessComponentsToInitialize(); ProcessQueuedMessages(ezObjectMsgQueueType::AfterInitialized); } // Swap our double buffered stack allocator m_Data.m_StackAllocator.Swap(); }