Added citybuilder and cloud pass.
@@ -1,6 +1,6 @@
|
|||||||
DewmAAS "1.07"
|
DewmAAS "1.07"
|
||||||
|
|
||||||
3369270893
|
207147058
|
||||||
|
|
||||||
settings
|
settings
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
DewmAAS "1.07"
|
DewmAAS "1.07"
|
||||||
|
|
||||||
3369270893
|
207147058
|
||||||
|
|
||||||
settings
|
settings
|
||||||
{
|
{
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 1.0 MiB After Width: | Height: | Size: 1.0 MiB |
|
Before Width: | Height: | Size: 1.0 MiB After Width: | Height: | Size: 1.0 MiB |
|
Before Width: | Height: | Size: 1.0 MiB After Width: | Height: | Size: 1.0 MiB |
|
Before Width: | Height: | Size: 1.0 MiB After Width: | Height: | Size: 1.0 MiB |
|
Before Width: | Height: | Size: 1.0 MiB After Width: | Height: | Size: 1.0 MiB |
@@ -0,0 +1,2 @@
|
|||||||
|
worldDecals 1 {
|
||||||
|
}
|
||||||
@@ -0,0 +1,57 @@
|
|||||||
|
// Auto-generated Mars city builder materials for Doom 3 / Radiant.
|
||||||
|
|
||||||
|
textures/mars_citybuilder/mars_dirt
|
||||||
|
{
|
||||||
|
qer_editorimage textures/mars_citybuilder/mars_dirt_d.tga
|
||||||
|
diffusemap textures/mars_citybuilder/mars_dirt_d.tga
|
||||||
|
specularmap textures/mars_citybuilder/mars_dirt_s.tga
|
||||||
|
bumpmap textures/mars_citybuilder/mars_dirt_local.tga
|
||||||
|
}
|
||||||
|
|
||||||
|
textures/mars_citybuilder/mars_road_dusty_center
|
||||||
|
{
|
||||||
|
qer_editorimage textures/mars_citybuilder/mars_road_dusty_center_d.tga
|
||||||
|
diffusemap textures/mars_citybuilder/mars_road_dusty_center_d.tga
|
||||||
|
specularmap textures/mars_citybuilder/mars_road_dusty_center_s.tga
|
||||||
|
bumpmap textures/mars_citybuilder/mars_road_dusty_center_local.tga
|
||||||
|
}
|
||||||
|
|
||||||
|
textures/mars_citybuilder/mars_sidewalk_dusty
|
||||||
|
{
|
||||||
|
qer_editorimage textures/mars_citybuilder/mars_sidewalk_dusty_d.tga
|
||||||
|
diffusemap textures/mars_citybuilder/mars_sidewalk_dusty_d.tga
|
||||||
|
specularmap textures/mars_citybuilder/mars_sidewalk_dusty_s.tga
|
||||||
|
bumpmap textures/mars_citybuilder/mars_sidewalk_dusty_local.tga
|
||||||
|
}
|
||||||
|
|
||||||
|
textures/mars_citybuilder/mars_building_dark_01
|
||||||
|
{
|
||||||
|
qer_editorimage textures/mars_citybuilder/mars_building_dark_01_d.tga
|
||||||
|
diffusemap textures/mars_citybuilder/mars_building_dark_01_d.tga
|
||||||
|
specularmap textures/mars_citybuilder/mars_building_dark_01_s.tga
|
||||||
|
bumpmap textures/mars_citybuilder/mars_building_dark_01_local.tga
|
||||||
|
}
|
||||||
|
|
||||||
|
textures/mars_citybuilder/mars_building_dark_02
|
||||||
|
{
|
||||||
|
qer_editorimage textures/mars_citybuilder/mars_building_dark_02_d.tga
|
||||||
|
diffusemap textures/mars_citybuilder/mars_building_dark_02_d.tga
|
||||||
|
specularmap textures/mars_citybuilder/mars_building_dark_02_s.tga
|
||||||
|
bumpmap textures/mars_citybuilder/mars_building_dark_02_local.tga
|
||||||
|
}
|
||||||
|
|
||||||
|
textures/mars_citybuilder/mars_road_dusty_center_east_west
|
||||||
|
{
|
||||||
|
qer_editorimage textures/mars_citybuilder/mars_road_dusty_center_east_west_d.tga
|
||||||
|
diffusemap textures/mars_citybuilder/mars_road_dusty_center_east_west_d.tga
|
||||||
|
specularmap textures/mars_citybuilder/mars_road_dusty_center_east_west_s.tga
|
||||||
|
bumpmap textures/mars_citybuilder/mars_road_dusty_center_east_west_local.tga
|
||||||
|
}
|
||||||
|
|
||||||
|
textures/mars_citybuilder/mars_road_dusty_intersection
|
||||||
|
{
|
||||||
|
qer_editorimage textures/mars_citybuilder/mars_road_dusty_intersection_d.tga
|
||||||
|
diffusemap textures/mars_citybuilder/mars_road_dusty_intersection_d.tga
|
||||||
|
specularmap textures/mars_citybuilder/mars_road_dusty_intersection_s.tga
|
||||||
|
bumpmap textures/mars_citybuilder/mars_road_dusty_intersection_local.tga
|
||||||
|
}
|
||||||
@@ -9,7 +9,7 @@
|
|||||||
|
|
||||||
1204 constants
|
1204 constants
|
||||||
135 enums
|
135 enums
|
||||||
621 classes/structs/unions
|
622 classes/structs/unions
|
||||||
38 templates
|
38 templates
|
||||||
7 max inheritance level for 'idAI_Vagary'
|
7 max inheritance level for 'idAI_Vagary'
|
||||||
|
|
||||||
@@ -4174,6 +4174,24 @@ static classVariableInfo_t glScreenSpaceParticleVertex_t_typeInfo[] = {
|
|||||||
{ NULL, 0 }
|
{ NULL, 0 }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static classVariableInfo_t glSkyClouds_t_typeInfo[] = {
|
||||||
|
{ "float[3]", "skyColor", (intptr_t)(&((glSkyClouds_t *)0)->skyColor), sizeof( ((glSkyClouds_t *)0)->skyColor ) },
|
||||||
|
{ "float", "opacity", (intptr_t)(&((glSkyClouds_t *)0)->opacity), sizeof( ((glSkyClouds_t *)0)->opacity ) },
|
||||||
|
{ "float[3]", "viewOrigin", (intptr_t)(&((glSkyClouds_t *)0)->viewOrigin), sizeof( ((glSkyClouds_t *)0)->viewOrigin ) },
|
||||||
|
{ "float", "zMin", (intptr_t)(&((glSkyClouds_t *)0)->zMin), sizeof( ((glSkyClouds_t *)0)->zMin ) },
|
||||||
|
{ "float[3]", "viewForward", (intptr_t)(&((glSkyClouds_t *)0)->viewForward), sizeof( ((glSkyClouds_t *)0)->viewForward ) },
|
||||||
|
{ "float", "zMax", (intptr_t)(&((glSkyClouds_t *)0)->zMax), sizeof( ((glSkyClouds_t *)0)->zMax ) },
|
||||||
|
{ "float[3]", "viewRight", (intptr_t)(&((glSkyClouds_t *)0)->viewRight), sizeof( ((glSkyClouds_t *)0)->viewRight ) },
|
||||||
|
{ "float", "tanHalfFovX", (intptr_t)(&((glSkyClouds_t *)0)->tanHalfFovX), sizeof( ((glSkyClouds_t *)0)->tanHalfFovX ) },
|
||||||
|
{ "float[3]", "viewUp", (intptr_t)(&((glSkyClouds_t *)0)->viewUp), sizeof( ((glSkyClouds_t *)0)->viewUp ) },
|
||||||
|
{ "float", "tanHalfFovY", (intptr_t)(&((glSkyClouds_t *)0)->tanHalfFovY), sizeof( ((glSkyClouds_t *)0)->tanHalfFovY ) },
|
||||||
|
{ "float", "noiseScale", (intptr_t)(&((glSkyClouds_t *)0)->noiseScale), sizeof( ((glSkyClouds_t *)0)->noiseScale ) },
|
||||||
|
{ "float", "coverage", (intptr_t)(&((glSkyClouds_t *)0)->coverage), sizeof( ((glSkyClouds_t *)0)->coverage ) },
|
||||||
|
{ "float", "density", (intptr_t)(&((glSkyClouds_t *)0)->density), sizeof( ((glSkyClouds_t *)0)->density ) },
|
||||||
|
{ "float", "seedOffset", (intptr_t)(&((glSkyClouds_t *)0)->seedOffset), sizeof( ((glSkyClouds_t *)0)->seedOffset ) },
|
||||||
|
{ NULL, 0 }
|
||||||
|
};
|
||||||
|
|
||||||
static classVariableInfo_t QD3D12NeuralPOMImageRGBA8_typeInfo[] = {
|
static classVariableInfo_t QD3D12NeuralPOMImageRGBA8_typeInfo[] = {
|
||||||
{ "uint32_t", "width", (intptr_t)(&((QD3D12NeuralPOMImageRGBA8 *)0)->width), sizeof( ((QD3D12NeuralPOMImageRGBA8 *)0)->width ) },
|
{ "uint32_t", "width", (intptr_t)(&((QD3D12NeuralPOMImageRGBA8 *)0)->width), sizeof( ((QD3D12NeuralPOMImageRGBA8 *)0)->width ) },
|
||||||
{ "uint32_t", "height", (intptr_t)(&((QD3D12NeuralPOMImageRGBA8 *)0)->height), sizeof( ((QD3D12NeuralPOMImageRGBA8 *)0)->height ) },
|
{ "uint32_t", "height", (intptr_t)(&((QD3D12NeuralPOMImageRGBA8 *)0)->height), sizeof( ((QD3D12NeuralPOMImageRGBA8 *)0)->height ) },
|
||||||
@@ -5294,11 +5312,11 @@ static classVariableInfo_t frameLookup_t_typeInfo[] = {
|
|||||||
{ NULL, 0 }
|
{ NULL, 0 }
|
||||||
};
|
};
|
||||||
|
|
||||||
static classVariableInfo_t class_289_class_289_typeInfo[] = {
|
static classVariableInfo_t class_290_class_290_typeInfo[] = {
|
||||||
// { "const idSoundShader *", "soundShader", (intptr_t)(&((class_289::class_289 *)0)->soundShader), sizeof( ((class_289::class_289 *)0)->soundShader ) },
|
// { "const idSoundShader *", "soundShader", (intptr_t)(&((class_290::class_290 *)0)->soundShader), sizeof( ((class_290::class_290 *)0)->soundShader ) },
|
||||||
// { "const function_t *", "function", (intptr_t)(&((class_289::class_289 *)0)->function), sizeof( ((class_289::class_289 *)0)->function ) },
|
// { "const function_t *", "function", (intptr_t)(&((class_290::class_290 *)0)->function), sizeof( ((class_290::class_290 *)0)->function ) },
|
||||||
// { "const idDeclSkin *", "skin", (intptr_t)(&((class_289::class_289 *)0)->skin), sizeof( ((class_289::class_289 *)0)->skin ) },
|
// { "const idDeclSkin *", "skin", (intptr_t)(&((class_290::class_290 *)0)->skin), sizeof( ((class_290::class_290 *)0)->skin ) },
|
||||||
// { "int", "index", (intptr_t)(&((class_289::class_289 *)0)->index), sizeof( ((class_289::class_289 *)0)->index ) },
|
// { "int", "index", (intptr_t)(&((class_290::class_290 *)0)->index), sizeof( ((class_290::class_290 *)0)->index ) },
|
||||||
{ NULL, 0 }
|
{ NULL, 0 }
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -9222,6 +9240,7 @@ static classTypeInfo_t classTypeInfo[] = {
|
|||||||
{ "glRaytracingProfileCounters_t", "", sizeof(glRaytracingProfileCounters_t), glRaytracingProfileCounters_t_typeInfo },
|
{ "glRaytracingProfileCounters_t", "", sizeof(glRaytracingProfileCounters_t), glRaytracingProfileCounters_t_typeInfo },
|
||||||
{ "glScreenSpaceDecal_t", "", sizeof(glScreenSpaceDecal_t), glScreenSpaceDecal_t_typeInfo },
|
{ "glScreenSpaceDecal_t", "", sizeof(glScreenSpaceDecal_t), glScreenSpaceDecal_t_typeInfo },
|
||||||
{ "glScreenSpaceParticleVertex_t", "", sizeof(glScreenSpaceParticleVertex_t), glScreenSpaceParticleVertex_t_typeInfo },
|
{ "glScreenSpaceParticleVertex_t", "", sizeof(glScreenSpaceParticleVertex_t), glScreenSpaceParticleVertex_t_typeInfo },
|
||||||
|
{ "glSkyClouds_t", "", sizeof(glSkyClouds_t), glSkyClouds_t_typeInfo },
|
||||||
{ "QD3D12NeuralPOMImageRGBA8", "", sizeof(QD3D12NeuralPOMImageRGBA8), QD3D12NeuralPOMImageRGBA8_typeInfo },
|
{ "QD3D12NeuralPOMImageRGBA8", "", sizeof(QD3D12NeuralPOMImageRGBA8), QD3D12NeuralPOMImageRGBA8_typeInfo },
|
||||||
{ "QD3D12NeuralPOMTrainDesc", "", sizeof(QD3D12NeuralPOMTrainDesc), QD3D12NeuralPOMTrainDesc_typeInfo },
|
{ "QD3D12NeuralPOMTrainDesc", "", sizeof(QD3D12NeuralPOMTrainDesc), QD3D12NeuralPOMTrainDesc_typeInfo },
|
||||||
{ "QD3D12NeuralPOMTrainStats", "", sizeof(QD3D12NeuralPOMTrainStats), QD3D12NeuralPOMTrainStats_typeInfo },
|
{ "QD3D12NeuralPOMTrainStats", "", sizeof(QD3D12NeuralPOMTrainStats), QD3D12NeuralPOMTrainStats_typeInfo },
|
||||||
@@ -9332,7 +9351,7 @@ static classTypeInfo_t classTypeInfo[] = {
|
|||||||
{ "jointAnimInfo_t", "", sizeof(jointAnimInfo_t), jointAnimInfo_t_typeInfo },
|
{ "jointAnimInfo_t", "", sizeof(jointAnimInfo_t), jointAnimInfo_t_typeInfo },
|
||||||
{ "jointMod_t", "", sizeof(jointMod_t), jointMod_t_typeInfo },
|
{ "jointMod_t", "", sizeof(jointMod_t), jointMod_t_typeInfo },
|
||||||
{ "frameLookup_t", "", sizeof(frameLookup_t), frameLookup_t_typeInfo },
|
{ "frameLookup_t", "", sizeof(frameLookup_t), frameLookup_t_typeInfo },
|
||||||
// { "class_289::class_289", "", sizeof(class_289::class_289), class_289_class_289_typeInfo },
|
// { "class_290::class_290", "", sizeof(class_290::class_290), class_290_class_290_typeInfo },
|
||||||
{ "frameCommand_t", "", sizeof(frameCommand_t), frameCommand_t_typeInfo },
|
{ "frameCommand_t", "", sizeof(frameCommand_t), frameCommand_t_typeInfo },
|
||||||
{ "animFlags_t", "", sizeof(animFlags_t), animFlags_t_typeInfo },
|
{ "animFlags_t", "", sizeof(animFlags_t), animFlags_t_typeInfo },
|
||||||
{ "idModelExport", "", sizeof(idModelExport), idModelExport_typeInfo },
|
{ "idModelExport", "", sizeof(idModelExport), idModelExport_typeInfo },
|
||||||
|
|||||||
@@ -1071,6 +1071,11 @@
|
|||||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Dedicated Debug|x64'">true</ExcludedFromBuild>
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Dedicated Debug|x64'">true</ExcludedFromBuild>
|
||||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Dedicated Release|x64'">true</ExcludedFromBuild>
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Dedicated Release|x64'">true</ExcludedFromBuild>
|
||||||
</CustomBuildStep>
|
</CustomBuildStep>
|
||||||
|
<CustomBuildStep Include="tools\radiant\CityBuilder.h">
|
||||||
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Dedicated Debug with inlines|x64'">true</ExcludedFromBuild>
|
||||||
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Dedicated Debug|x64'">true</ExcludedFromBuild>
|
||||||
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Dedicated Release|x64'">true</ExcludedFromBuild>
|
||||||
|
</CustomBuildStep>
|
||||||
<CustomBuildStep Include="tools\radiant\CameraTargetDlg.h">
|
<CustomBuildStep Include="tools\radiant\CameraTargetDlg.h">
|
||||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Dedicated Debug with inlines|x64'">true</ExcludedFromBuild>
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Dedicated Debug with inlines|x64'">true</ExcludedFromBuild>
|
||||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Dedicated Debug|x64'">true</ExcludedFromBuild>
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Dedicated Debug|x64'">true</ExcludedFromBuild>
|
||||||
@@ -2609,6 +2614,11 @@
|
|||||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Dedicated Debug|x64'">true</ExcludedFromBuild>
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Dedicated Debug|x64'">true</ExcludedFromBuild>
|
||||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Dedicated Release|x64'">true</ExcludedFromBuild>
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Dedicated Release|x64'">true</ExcludedFromBuild>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="tools\radiant\CityBuilder.cpp">
|
||||||
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Dedicated Debug with inlines|x64'">true</ExcludedFromBuild>
|
||||||
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Dedicated Debug|x64'">true</ExcludedFromBuild>
|
||||||
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Dedicated Release|x64'">true</ExcludedFromBuild>
|
||||||
|
</ClCompile>
|
||||||
<ClCompile Include="tools\radiant\CameraTargetDlg.cpp">
|
<ClCompile Include="tools\radiant\CameraTargetDlg.cpp">
|
||||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Dedicated Debug with inlines|x64'">true</ExcludedFromBuild>
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Dedicated Debug with inlines|x64'">true</ExcludedFromBuild>
|
||||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Dedicated Debug|x64'">true</ExcludedFromBuild>
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Dedicated Debug|x64'">true</ExcludedFromBuild>
|
||||||
@@ -3184,4 +3194,4 @@
|
|||||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||||
<ImportGroup Label="ExtensionTargets">
|
<ImportGroup Label="ExtensionTargets">
|
||||||
</ImportGroup>
|
</ImportGroup>
|
||||||
</Project>
|
</Project>
|
||||||
|
|||||||
@@ -1388,6 +1388,9 @@
|
|||||||
<ClCompile Include="tools\radiant\autocaulk.cpp">
|
<ClCompile Include="tools\radiant\autocaulk.cpp">
|
||||||
<Filter>Tools\Radiant</Filter>
|
<Filter>Tools\Radiant</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="tools\radiant\CityBuilder.cpp">
|
||||||
|
<Filter>Tools\Radiant</Filter>
|
||||||
|
</ClCompile>
|
||||||
<ClCompile Include="tools\radiant\CameraTargetDlg.cpp">
|
<ClCompile Include="tools\radiant\CameraTargetDlg.cpp">
|
||||||
<Filter>Tools\Radiant</Filter>
|
<Filter>Tools\Radiant</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
@@ -2354,6 +2357,9 @@
|
|||||||
<CustomBuildStep Include="tools\radiant\autocaulk.h">
|
<CustomBuildStep Include="tools\radiant\autocaulk.h">
|
||||||
<Filter>Tools\Radiant</Filter>
|
<Filter>Tools\Radiant</Filter>
|
||||||
</CustomBuildStep>
|
</CustomBuildStep>
|
||||||
|
<CustomBuildStep Include="tools\radiant\CityBuilder.h">
|
||||||
|
<Filter>Tools\Radiant</Filter>
|
||||||
|
</CustomBuildStep>
|
||||||
<CustomBuildStep Include="tools\radiant\CameraTargetDlg.h">
|
<CustomBuildStep Include="tools\radiant\CameraTargetDlg.h">
|
||||||
<Filter>Tools\Radiant</Filter>
|
<Filter>Tools\Radiant</Filter>
|
||||||
</CustomBuildStep>
|
</CustomBuildStep>
|
||||||
@@ -2537,4 +2543,4 @@
|
|||||||
<Filter>Sys\RC\res</Filter>
|
<Filter>Sys\RC\res</Filter>
|
||||||
</Image>
|
</Image>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
||||||
|
|||||||
@@ -1582,7 +1582,8 @@ static int glRaytracingUploadMeshBuffers(glRaytracingMeshRecord_t* mesh);
|
|||||||
|
|
||||||
static int glRaytracingBuildDirtyMeshesInternal(void)
|
static int glRaytracingBuildDirtyMeshesInternal(void)
|
||||||
{
|
{
|
||||||
std::vector<glRaytracingMeshRecord_t*> dirtyMeshes;
|
static thread_local std::vector<glRaytracingMeshRecord_t*> dirtyMeshes;
|
||||||
|
dirtyMeshes.clear();
|
||||||
dirtyMeshes.reserve(g_glRaytracingScene.meshes.size());
|
dirtyMeshes.reserve(g_glRaytracingScene.meshes.size());
|
||||||
|
|
||||||
for (size_t i = 0; i < g_glRaytracingScene.meshes.size(); ++i)
|
for (size_t i = 0; i < g_glRaytracingScene.meshes.size(); ++i)
|
||||||
@@ -1608,7 +1609,8 @@ static int glRaytracingBuildDirtyMeshesInternal(void)
|
|||||||
int newBlasIndex;
|
int newBlasIndex;
|
||||||
};
|
};
|
||||||
|
|
||||||
std::vector<glRaytracingMeshBuildInfo_t> builds;
|
static thread_local std::vector<glRaytracingMeshBuildInfo_t> builds;
|
||||||
|
builds.clear();
|
||||||
builds.resize(dirtyMeshes.size());
|
builds.resize(dirtyMeshes.size());
|
||||||
|
|
||||||
for (size_t i = 0; i < dirtyMeshes.size(); ++i)
|
for (size_t i = 0; i < dirtyMeshes.size(); ++i)
|
||||||
@@ -2570,6 +2572,11 @@ struct glRaytracingLightingConstants_t
|
|||||||
uint32_t secondaryCorrectionBudget;
|
uint32_t secondaryCorrectionBudget;
|
||||||
float secondaryLightCompensation;
|
float secondaryLightCompensation;
|
||||||
uint32_t historyReset;
|
uint32_t historyReset;
|
||||||
|
|
||||||
|
uint32_t externalDenoiser;
|
||||||
|
float giAmount;
|
||||||
|
float worldGrimeAmount;
|
||||||
|
uint32_t pad2;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct glRaytracingMeshMetadata_t
|
struct glRaytracingMeshMetadata_t
|
||||||
@@ -2853,6 +2860,10 @@ cbuffer LightingCB : register(b0)
|
|||||||
uint gSecondaryCorrectionBudget;
|
uint gSecondaryCorrectionBudget;
|
||||||
float gSecondaryLightCompensation;
|
float gSecondaryLightCompensation;
|
||||||
uint gHistoryReset;
|
uint gHistoryReset;
|
||||||
|
uint gExternalDenoiser;
|
||||||
|
float gGiAmount;
|
||||||
|
float gWorldGrimeAmount;
|
||||||
|
uint gPadding2;
|
||||||
};
|
};
|
||||||
|
|
||||||
StructuredBuffer<Light> gLights : register(t0);
|
StructuredBuffer<Light> gLights : register(t0);
|
||||||
@@ -3338,6 +3349,53 @@ float Hash12(float2 p)
|
|||||||
return frac((p3.x + p3.y) * p3.z);
|
return frac((p3.x + p3.y) * p3.z);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
float Hash13(float3 p)
|
||||||
|
{
|
||||||
|
p = frac(p * 0.1031);
|
||||||
|
p += dot(p, p.yzx + 33.33);
|
||||||
|
return frac((p.x + p.y) * p.z);
|
||||||
|
}
|
||||||
|
|
||||||
|
float ValueNoise3D(float3 p)
|
||||||
|
{
|
||||||
|
float3 i = floor(p);
|
||||||
|
float3 f = frac(p);
|
||||||
|
f = f * f * (3.0 - 2.0 * f);
|
||||||
|
|
||||||
|
float n000 = Hash13(i + float3(0, 0, 0));
|
||||||
|
float n100 = Hash13(i + float3(1, 0, 0));
|
||||||
|
float n010 = Hash13(i + float3(0, 1, 0));
|
||||||
|
float n110 = Hash13(i + float3(1, 1, 0));
|
||||||
|
float n001 = Hash13(i + float3(0, 0, 1));
|
||||||
|
float n101 = Hash13(i + float3(1, 0, 1));
|
||||||
|
float n011 = Hash13(i + float3(0, 1, 1));
|
||||||
|
float n111 = Hash13(i + float3(1, 1, 1));
|
||||||
|
|
||||||
|
float nx00 = lerp(n000, n100, f.x);
|
||||||
|
float nx10 = lerp(n010, n110, f.x);
|
||||||
|
float nx01 = lerp(n001, n101, f.x);
|
||||||
|
float nx11 = lerp(n011, n111, f.x);
|
||||||
|
float nxy0 = lerp(nx00, nx10, f.y);
|
||||||
|
float nxy1 = lerp(nx01, nx11, f.y);
|
||||||
|
return lerp(nxy0, nxy1, f.z);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ApplyWorldGrime(float3 worldPos, float cavity, float ao, bool isSkeletal, inout float3 baseAlbedo, inout float3 specularAlbedo)
|
||||||
|
{
|
||||||
|
if (isSkeletal || gWorldGrimeAmount <= 0.0001)
|
||||||
|
return;
|
||||||
|
|
||||||
|
float crevice = saturate((1.0 - cavity) * 1.35 + (1.0 - ao) * 0.55);
|
||||||
|
float largeNoise = ValueNoise3D(worldPos * 0.025);
|
||||||
|
float fineNoise = ValueNoise3D(worldPos * 0.11 + float3(17.0, 41.0, 9.0));
|
||||||
|
float grimeMask = saturate(crevice * (0.65 + 0.55 * largeNoise) + fineNoise * 0.18);
|
||||||
|
float amount = saturate(grimeMask * gWorldGrimeAmount);
|
||||||
|
|
||||||
|
float3 dirtTint = float3(0.36, 0.31, 0.24);
|
||||||
|
baseAlbedo = lerp(baseAlbedo, baseAlbedo * dirtTint, amount);
|
||||||
|
specularAlbedo *= lerp(1.0, 0.55, amount);
|
||||||
|
}
|
||||||
|
|
||||||
float2 Hammersley2D(uint i, uint N, float rand)
|
float2 Hammersley2D(uint i, uint N, float rand)
|
||||||
{
|
{
|
||||||
float e1 = frac((float)i / (float)N + rand);
|
float e1 = frac((float)i / (float)N + rand);
|
||||||
@@ -4346,6 +4404,24 @@ uint InitSpatialRng(uint2 pixel, float3 worldPos, uint salt)
|
|||||||
return PcgHash(seed) | 1u;
|
return PcgHash(seed) | 1u;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint InitSurfaceStableRng(uint2 pixel, float3 worldPos, float3 normal, uint sampleIndex, uint frameIndex)
|
||||||
|
{
|
||||||
|
if (gExternalDenoiser == 0u)
|
||||||
|
return InitRng(pixel, frameIndex, sampleIndex);
|
||||||
|
|
||||||
|
uint3 cell = (uint3)floor(abs(worldPos) * 16.0 + 0.5);
|
||||||
|
uint3 ncell = (uint3)floor(saturate(normal * 0.5 + 0.5) * 255.0 + 0.5);
|
||||||
|
uint seed =
|
||||||
|
cell.x * 73856093u ^
|
||||||
|
cell.y * 19349663u ^
|
||||||
|
cell.z * 83492791u ^
|
||||||
|
ncell.x * 1597334677u ^
|
||||||
|
ncell.y * 3812015801u ^
|
||||||
|
ncell.z * 2798796415u ^
|
||||||
|
sampleIndex * 0x9E3779B9u;
|
||||||
|
return PcgHash(seed) | 1u;
|
||||||
|
}
|
||||||
|
|
||||||
float Rand(inout uint rng)
|
float Rand(inout uint rng)
|
||||||
{
|
{
|
||||||
rng = PcgHash(rng);
|
rng = PcgHash(rng);
|
||||||
@@ -5587,7 +5663,8 @@ float2 GetStratifiedBounceXi(uint2 pixel, float3 worldPos, float3 pathNormal, ui
|
|||||||
{
|
{
|
||||||
uint spp = max(gSamplesPerPixel, 1u);
|
uint spp = max(gSamplesPerPixel, 1u);
|
||||||
uint sequenceLength = max(spp * 64u, 64u);
|
uint sequenceLength = max(spp * 64u, 64u);
|
||||||
uint sequenceIndex = (sampleIndex + (gFrameIndex & 63u) * spp) % sequenceLength;
|
uint rngFrameIndex = (gEnableDenoiser != 0u && gExternalDenoiser == 0u) ? gFrameIndex : 0u;
|
||||||
|
uint sequenceIndex = (sampleIndex + (rngFrameIndex & 63u) * spp) % sequenceLength;
|
||||||
|
|
||||||
float rand = Hash12(
|
float rand = Hash12(
|
||||||
(float2)pixel +
|
(float2)pixel +
|
||||||
@@ -6212,21 +6289,24 @@ void RayGen()
|
|||||||
|
|
||||||
// All four of these are deterministic for this pixel. Compute them once,
|
// All four of these are deterministic for this pixel. Compute them once,
|
||||||
// then reuse them for every stochastic GI sample.
|
// then reuse them for every stochastic GI sample.
|
||||||
float cavity = ComputeCavity(pixel, worldPos, N);
|
const bool externalCharacterPixel = (gExternalDenoiser != 0u) && isSkeletal;
|
||||||
|
float cavity = externalCharacterPixel ? 1.0 : ComputeCavity(pixel, worldPos, N);
|
||||||
if (isSkeletal)
|
if (isSkeletal)
|
||||||
cavity = lerp(cavity, 1.0, 0.65);
|
cavity = lerp(cavity, 1.0, 0.65);
|
||||||
float ao = ComputeAmbientOcclusion(worldPos, N, pixel, isSkeletal);
|
float ao = externalCharacterPixel ? 1.0 : ComputeAmbientOcclusion(worldPos, N, pixel, isSkeletal);
|
||||||
float skyVis = 0; //ComputeSkyVisibility(worldPos, N, pixel);
|
float skyVis = 0; //ComputeSkyVisibility(worldPos, N, pixel);
|
||||||
float ambientSkyVis = 0; //TraceStraightUpToSky(worldPos, N);
|
float ambientSkyVis = 0; //TraceStraightUpToSky(worldPos, N);
|
||||||
float microShadow = lerp(0.75, 1.0, cavity);
|
float microShadow = lerp(0.75, 1.0, cavity);
|
||||||
|
ApplyWorldGrime(worldPos, cavity, ao, isSkeletal, baseAlbedo, specularAlbedo);
|
||||||
|
|
||||||
float3 reactiveFinalGather = 0.0;
|
float3 reactiveFinalGather = 0.0;
|
||||||
|
uint rngFrameIndex = (gEnableDenoiser != 0u && gExternalDenoiser == 0u) ? gFrameIndex : 0u;
|
||||||
if (gMaxBounces > 1u)
|
if (gMaxBounces > 1u)
|
||||||
{
|
{
|
||||||
// Evaluate this deterministic screen-space irradiance reuse once per
|
// Evaluate this deterministic screen-space irradiance reuse once per
|
||||||
// pixel, not once per SPP. That makes the GI more responsive without
|
// pixel, not once per SPP. That makes the GI more responsive without
|
||||||
// multiplying the light-list work inside the stochastic sample loop.
|
// multiplying the light-list work inside the stochastic sample loop.
|
||||||
uint gatherRng = InitRng(pixel, gFrameIndex, 1337u);
|
uint gatherRng = InitSurfaceStableRng(pixel, worldPos, N, 1337u, rngFrameIndex);
|
||||||
reactiveFinalGather = EstimateReactiveScreenSpaceFinalGather(
|
reactiveFinalGather = EstimateReactiveScreenSpaceFinalGather(
|
||||||
pixel,
|
pixel,
|
||||||
worldPos,
|
worldPos,
|
||||||
@@ -6257,17 +6337,17 @@ void RayGen()
|
|||||||
// Only the indirect bounce path uses per-SPP randomness now. Direct lights,
|
// Only the indirect bounce path uses per-SPP randomness now. Direct lights,
|
||||||
// AO, sky visibility, cavity, and final gather are deterministic and should
|
// AO, sky visibility, cavity, and final gather are deterministic and should
|
||||||
// not be re-traced spp times.
|
// not be re-traced spp times.
|
||||||
if (gMaxBounces > 1u)
|
if (gMaxBounces > 1u && !externalCharacterPixel)
|
||||||
{
|
{
|
||||||
float3 indirectAccum = 0.0;
|
float3 indirectAccum = 0.0;
|
||||||
|
|
||||||
[loop]
|
[loop]
|
||||||
for (uint s = 0; s < spp; ++s)
|
for (uint s = 0; s < spp; ++s)
|
||||||
{
|
{
|
||||||
// Frame-vary the GI path now that a temporal accumulator is present.
|
// Frame-vary only when the internal temporal accumulator is active.
|
||||||
// This lets the stochastic light subset, sky sample, and diffuse path
|
// External denoisers get a surface-stable raw GI pattern so texture
|
||||||
// converge instead of staying locked to one noisy sample pattern.
|
// detail does not boil under reconstruction.
|
||||||
uint rng = InitRng(pixel, gFrameIndex, s);
|
uint rng = InitSurfaceStableRng(pixel, worldPos, N, s, rngFrameIndex);
|
||||||
indirectAccum += EstimatePathTracedIndirectBounce(
|
indirectAccum += EstimatePathTracedIndirectBounce(
|
||||||
pixel,
|
pixel,
|
||||||
worldPos,
|
worldPos,
|
||||||
@@ -6279,7 +6359,7 @@ void RayGen()
|
|||||||
}
|
}
|
||||||
|
|
||||||
float3 indirectLighting = indirectAccum / (float)spp;
|
float3 indirectLighting = indirectAccum / (float)spp;
|
||||||
lightingAccum += ApplyPrimaryDiffusePost(indirectLighting, ao, microShadow, isSkeletal);
|
lightingAccum += ApplyPrimaryDiffusePost(indirectLighting, ao, microShadow, isSkeletal) * gGiAmount;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint reflectionRng = InitRng(pixel, 0u, 0x5EECu);
|
uint reflectionRng = InitRng(pixel, 0u, 0x5EECu);
|
||||||
@@ -6301,11 +6381,10 @@ void RayGen()
|
|||||||
{
|
{
|
||||||
// reactiveFinalGather is incoming indirect radiance. Apply the primary
|
// reactiveFinalGather is incoming indirect radiance. Apply the primary
|
||||||
// diffuse albedo here, matching the regular lighting path.
|
// diffuse albedo here, matching the regular lighting path.
|
||||||
finalColor += baseAlbedo * reactiveFinalGather;
|
finalColor += baseAlbedo * reactiveFinalGather * gGiAmount;
|
||||||
}
|
}
|
||||||
|
|
||||||
float outputAo = isSkeletal ? lerp(ao, 1.0, 0.55) : ao;
|
float outputAo = isSkeletal ? lerp(ao, 1.0, 0.55) : ao;
|
||||||
finalColor *= clamp(outputAo + 0.3, 0.0, 1.0);
|
|
||||||
finalColor += subsurfaceAccum;
|
finalColor += subsurfaceAccum;
|
||||||
|
|
||||||
// Volumetric light scattering is radiance in the camera ray, not surface
|
// Volumetric light scattering is radiance in the camera ray, not surface
|
||||||
@@ -6321,7 +6400,7 @@ void RayGen()
|
|||||||
// the eventual swap-chain/backbuffer is LDR.
|
// the eventual swap-chain/backbuffer is LDR.
|
||||||
finalColor += emissiveSurface + emissiveBloom;
|
finalColor += emissiveSurface + emissiveBloom;
|
||||||
|
|
||||||
gOutputTex[pixel] = float4(PreparePathTraceOutputColor(finalColor), primaryHitDistance);
|
gOutputTex[pixel] = float4(PreparePathTraceOutputColor(finalColor) * outputAo, primaryHitDistance);
|
||||||
}
|
}
|
||||||
)";
|
)";
|
||||||
|
|
||||||
@@ -6354,6 +6433,10 @@ cbuffer LightingCB : register(b0)
|
|||||||
uint gSecondaryCorrectionBudget;
|
uint gSecondaryCorrectionBudget;
|
||||||
float gSecondaryLightCompensation;
|
float gSecondaryLightCompensation;
|
||||||
uint gHistoryReset;
|
uint gHistoryReset;
|
||||||
|
uint gExternalDenoiser;
|
||||||
|
float gGiAmount;
|
||||||
|
float gWorldGrimeAmount;
|
||||||
|
uint gPadding2;
|
||||||
};
|
};
|
||||||
|
|
||||||
Texture2D<float4> gAlbedoTex : register(t1);
|
Texture2D<float4> gAlbedoTex : register(t1);
|
||||||
@@ -6640,6 +6723,10 @@ cbuffer LightingCB : register(b0)
|
|||||||
uint gSecondaryCorrectionBudget;
|
uint gSecondaryCorrectionBudget;
|
||||||
float gSecondaryLightCompensation;
|
float gSecondaryLightCompensation;
|
||||||
uint gHistoryReset;
|
uint gHistoryReset;
|
||||||
|
uint gExternalDenoiser;
|
||||||
|
float gGiAmount;
|
||||||
|
float gWorldGrimeAmount;
|
||||||
|
uint gPadding2;
|
||||||
};
|
};
|
||||||
|
|
||||||
Texture2D<float4> gAlbedoTex : register(t1);
|
Texture2D<float4> gAlbedoTex : register(t1);
|
||||||
@@ -8059,6 +8146,7 @@ static bool glRaytracingLightingExecuteInternal(
|
|||||||
g_glRaytracingLighting.constants.screenSize[2] = 1.0f / (float)pass->width;
|
g_glRaytracingLighting.constants.screenSize[2] = 1.0f / (float)pass->width;
|
||||||
g_glRaytracingLighting.constants.screenSize[3] = 1.0f / (float)pass->height;
|
g_glRaytracingLighting.constants.screenSize[3] = 1.0f / (float)pass->height;
|
||||||
g_glRaytracingLighting.constants.frameIndex = g_glRaytracingLighting.frameCounter;
|
g_glRaytracingLighting.constants.frameIndex = g_glRaytracingLighting.frameCounter;
|
||||||
|
g_glRaytracingLighting.constants.externalDenoiser = g_glRaytracingLighting.externalDenoiser ? 1u : 0u;
|
||||||
g_glRaytracingLighting.constants.lightCount =
|
g_glRaytracingLighting.constants.lightCount =
|
||||||
(uint32_t)glRaytracingClamp<size_t>(g_glRaytracingLighting.cpuLights.size(), 0, GL_RAYTRACING_MAX_LIGHTS);
|
(uint32_t)glRaytracingClamp<size_t>(g_glRaytracingLighting.cpuLights.size(), 0, GL_RAYTRACING_MAX_LIGHTS);
|
||||||
|
|
||||||
@@ -8424,6 +8512,9 @@ bool glRaytracingLightingInit(void)
|
|||||||
g_glRaytracingLighting.constants.secondaryCorrectionBudget = 0;
|
g_glRaytracingLighting.constants.secondaryCorrectionBudget = 0;
|
||||||
g_glRaytracingLighting.constants.secondaryLightCompensation = 0.62f;
|
g_glRaytracingLighting.constants.secondaryLightCompensation = 0.62f;
|
||||||
g_glRaytracingLighting.constants.historyReset = 1u;
|
g_glRaytracingLighting.constants.historyReset = 1u;
|
||||||
|
g_glRaytracingLighting.constants.externalDenoiser = 0u;
|
||||||
|
g_glRaytracingLighting.constants.giAmount = 1.0f;
|
||||||
|
g_glRaytracingLighting.constants.worldGrimeAmount = 0.35f;
|
||||||
glRaytracingLightingResetDenoiseHistory();
|
glRaytracingLightingResetDenoiseHistory();
|
||||||
|
|
||||||
glRaytracingLightingUpdateConstants();
|
glRaytracingLightingUpdateConstants();
|
||||||
@@ -8653,6 +8744,30 @@ void glRaytracingLightingSetPathTracingOptions(uint32_t samplesPerPixel, uint32_
|
|||||||
glRaytracingLightingUpdateConstants();
|
glRaytracingLightingUpdateConstants();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void glRaytracingLightingSetGIAmount(float amount)
|
||||||
|
{
|
||||||
|
std::lock_guard<std::mutex> lock(g_glRaytracingMutex);
|
||||||
|
|
||||||
|
amount = glRaytracingClamp<float>(amount, 0.0f, 8.0f);
|
||||||
|
if (g_glRaytracingLighting.constants.giAmount != amount)
|
||||||
|
glRaytracingLightingResetDenoiseHistory();
|
||||||
|
|
||||||
|
g_glRaytracingLighting.constants.giAmount = amount;
|
||||||
|
glRaytracingLightingUpdateConstants();
|
||||||
|
}
|
||||||
|
|
||||||
|
void glRaytracingLightingSetWorldGrime(float amount)
|
||||||
|
{
|
||||||
|
std::lock_guard<std::mutex> lock(g_glRaytracingMutex);
|
||||||
|
|
||||||
|
amount = glRaytracingClamp<float>(amount, 0.0f, 4.0f);
|
||||||
|
if (g_glRaytracingLighting.constants.worldGrimeAmount != amount)
|
||||||
|
glRaytracingLightingResetDenoiseHistory();
|
||||||
|
|
||||||
|
g_glRaytracingLighting.constants.worldGrimeAmount = amount;
|
||||||
|
glRaytracingLightingUpdateConstants();
|
||||||
|
}
|
||||||
|
|
||||||
void glRaytracingLightingSetSecondaryLightBudget(int budget, float compensation)
|
void glRaytracingLightingSetSecondaryLightBudget(int budget, float compensation)
|
||||||
{
|
{
|
||||||
std::lock_guard<std::mutex> lock(g_glRaytracingMutex);
|
std::lock_guard<std::mutex> lock(g_glRaytracingMutex);
|
||||||
@@ -8717,6 +8832,8 @@ void glRaytracingLightingSetExternalDenoiser(int enabled)
|
|||||||
glRaytracingLightingResetDenoiseHistory();
|
glRaytracingLightingResetDenoiseHistory();
|
||||||
|
|
||||||
g_glRaytracingLighting.externalDenoiser = newValue;
|
g_glRaytracingLighting.externalDenoiser = newValue;
|
||||||
|
g_glRaytracingLighting.constants.externalDenoiser = newValue ? 1u : 0u;
|
||||||
|
glRaytracingLightingUpdateConstants();
|
||||||
}
|
}
|
||||||
|
|
||||||
void glRaytracingLightingUseExternalDenoiser(int enabled)
|
void glRaytracingLightingUseExternalDenoiser(int enabled)
|
||||||
|
|||||||
@@ -542,7 +542,7 @@ static const UINT QD3D12_UploadBufferSize = 128 * 1024 * 1024;
|
|||||||
static const UINT QD3D12_RequestedGBufferSampleCount = 1;
|
static const UINT QD3D12_RequestedGBufferSampleCount = 1;
|
||||||
static constexpr UINT QD3D12_PostSrvCount = 16;
|
static constexpr UINT QD3D12_PostSrvCount = 16;
|
||||||
static constexpr UINT QD3D12_PostRootConstants = QD3D12_PostSrvCount;
|
static constexpr UINT QD3D12_PostRootConstants = QD3D12_PostSrvCount;
|
||||||
static constexpr UINT QD3D12_PostConstantDwords = 28;
|
static constexpr UINT QD3D12_PostConstantDwords = 48;
|
||||||
static constexpr UINT QD3D12_ToneMapTileDim = 64;
|
static constexpr UINT QD3D12_ToneMapTileDim = 64;
|
||||||
static constexpr UINT QD3D12_MaxScreenSpaceDecals = 64;
|
static constexpr UINT QD3D12_MaxScreenSpaceDecals = 64;
|
||||||
static constexpr UINT QD3D12_MaxScreenSpaceParticleLights = GL_RAYTRACING_MAX_LIGHTS;
|
static constexpr UINT QD3D12_MaxScreenSpaceParticleLights = GL_RAYTRACING_MAX_LIGHTS;
|
||||||
@@ -1798,6 +1798,7 @@ struct GLState
|
|||||||
ComPtr<ID3D12PipelineState> postScreenParticlePSO;
|
ComPtr<ID3D12PipelineState> postScreenParticlePSO;
|
||||||
ComPtr<ID3D12PipelineState> postScreenParticleAdditivePSO;
|
ComPtr<ID3D12PipelineState> postScreenParticleAdditivePSO;
|
||||||
ComPtr<ID3D12PipelineState> postScreenParticleEmissivePSO;
|
ComPtr<ID3D12PipelineState> postScreenParticleEmissivePSO;
|
||||||
|
ComPtr<ID3D12PipelineState> postSkyCloudsPSO;
|
||||||
|
|
||||||
ComPtr<ID3DBlob> vsMainBlob;
|
ComPtr<ID3DBlob> vsMainBlob;
|
||||||
ComPtr<ID3DBlob> hsMainBlob;
|
ComPtr<ID3DBlob> hsMainBlob;
|
||||||
@@ -1822,6 +1823,7 @@ struct GLState
|
|||||||
ComPtr<ID3DBlob> postPsScreenDecalBlob;
|
ComPtr<ID3DBlob> postPsScreenDecalBlob;
|
||||||
ComPtr<ID3DBlob> postVsScreenParticleBlob;
|
ComPtr<ID3DBlob> postVsScreenParticleBlob;
|
||||||
ComPtr<ID3DBlob> postPsScreenParticleBlob;
|
ComPtr<ID3DBlob> postPsScreenParticleBlob;
|
||||||
|
ComPtr<ID3DBlob> postPsSkyCloudsBlob;
|
||||||
|
|
||||||
TextureResource whiteTexture;
|
TextureResource whiteTexture;
|
||||||
|
|
||||||
@@ -4778,6 +4780,11 @@ cbuffer PostCB : register(b0)
|
|||||||
float4 gPostFogColor;
|
float4 gPostFogColor;
|
||||||
float4 gPostFogCameraWorldPos;
|
float4 gPostFogCameraWorldPos;
|
||||||
float4 gPostParticleParams;
|
float4 gPostParticleParams;
|
||||||
|
float4 gSkyCloudColorOpacity;
|
||||||
|
float4 gSkyCloudForwardZMax;
|
||||||
|
float4 gSkyCloudRightTanX;
|
||||||
|
float4 gSkyCloudUpTanY;
|
||||||
|
float4 gSkyCloudParams;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define gPostSharpness gPostParams0.x
|
#define gPostSharpness gPostParams0.x
|
||||||
@@ -4799,6 +4806,20 @@ cbuffer PostCB : register(b0)
|
|||||||
#define gScreenParticleEmissiveScale gPostParticleParams.x
|
#define gScreenParticleEmissiveScale gPostParticleParams.x
|
||||||
#define gScreenParticleOutputMode gPostParticleParams.y
|
#define gScreenParticleOutputMode gPostParticleParams.y
|
||||||
#define gScreenParticleDepthScale gPostParticleParams.zw
|
#define gScreenParticleDepthScale gPostParticleParams.zw
|
||||||
|
#define gSkyCloudColor gSkyCloudColorOpacity.rgb
|
||||||
|
#define gSkyCloudOpacity gSkyCloudColorOpacity.a
|
||||||
|
#define gSkyCloudViewOrigin gPostFogCameraWorldPos.xyz
|
||||||
|
#define gSkyCloudZMin gPostFogCameraWorldPos.w
|
||||||
|
#define gSkyCloudForward gSkyCloudForwardZMax.xyz
|
||||||
|
#define gSkyCloudZMax gSkyCloudForwardZMax.w
|
||||||
|
#define gSkyCloudRight gSkyCloudRightTanX.xyz
|
||||||
|
#define gSkyCloudTanX gSkyCloudRightTanX.w
|
||||||
|
#define gSkyCloudUp gSkyCloudUpTanY.xyz
|
||||||
|
#define gSkyCloudTanY gSkyCloudUpTanY.w
|
||||||
|
#define gSkyCloudScale gSkyCloudParams.x
|
||||||
|
#define gSkyCloudCoverage gSkyCloudParams.y
|
||||||
|
#define gSkyCloudDensity gSkyCloudParams.z
|
||||||
|
#define gSkyCloudSeed gSkyCloudParams.w
|
||||||
#define QD3D12_TONEMAP_TILE_DIM 64u
|
#define QD3D12_TONEMAP_TILE_DIM 64u
|
||||||
|
|
||||||
static const uint GL_RAYTRACING_LIGHT_TYPE_POINT = 0u;
|
static const uint GL_RAYTRACING_LIGHT_TYPE_POINT = 0u;
|
||||||
@@ -5134,12 +5155,124 @@ float4 PSCopy(VSOut i) : SV_Target0
|
|||||||
{
|
{
|
||||||
return QD3D12_ApplyPostFog(gTex0.Sample(gSamp0, i.uv), i.uv);
|
return QD3D12_ApplyPostFog(gTex0.Sample(gSamp0, i.uv), i.uv);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
float QD3D12_SkyCloudFade(float t)
|
||||||
|
{
|
||||||
|
t = saturate(t);
|
||||||
|
return t * t * (3.0 - 2.0 * t);
|
||||||
|
}
|
||||||
|
|
||||||
|
float QD3D12_SkyCloudHash(int3 p)
|
||||||
|
{
|
||||||
|
uint h = (uint)p.x * 374761393u + (uint)p.y * 668265263u + (uint)p.z * 2147483647u;
|
||||||
|
h = (h ^ (h >> 13)) * 1274126177u;
|
||||||
|
h ^= h >> 16;
|
||||||
|
return (float)(h & 0xffffu) * (1.0 / 65535.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
float QD3D12_SkyCloudNoise(float3 p)
|
||||||
|
{
|
||||||
|
int3 ip = int3(floor(p));
|
||||||
|
float3 f = float3(
|
||||||
|
QD3D12_SkyCloudFade(p.x - (float)ip.x),
|
||||||
|
QD3D12_SkyCloudFade(p.y - (float)ip.y),
|
||||||
|
QD3D12_SkyCloudFade(p.z - (float)ip.z));
|
||||||
|
|
||||||
|
float x00 = lerp(QD3D12_SkyCloudHash(ip + int3(0, 0, 0)), QD3D12_SkyCloudHash(ip + int3(1, 0, 0)), f.x);
|
||||||
|
float x10 = lerp(QD3D12_SkyCloudHash(ip + int3(0, 1, 0)), QD3D12_SkyCloudHash(ip + int3(1, 1, 0)), f.x);
|
||||||
|
float x01 = lerp(QD3D12_SkyCloudHash(ip + int3(0, 0, 1)), QD3D12_SkyCloudHash(ip + int3(1, 0, 1)), f.x);
|
||||||
|
float x11 = lerp(QD3D12_SkyCloudHash(ip + int3(0, 1, 1)), QD3D12_SkyCloudHash(ip + int3(1, 1, 1)), f.x);
|
||||||
|
|
||||||
|
return lerp(lerp(x00, x10, f.y), lerp(x01, x11, f.y), f.z);
|
||||||
|
}
|
||||||
|
|
||||||
|
float QD3D12_SkyCloudFBm(float3 p)
|
||||||
|
{
|
||||||
|
float sum = 0.0;
|
||||||
|
float amp = 0.56;
|
||||||
|
float norm = 0.0;
|
||||||
|
|
||||||
|
[unroll]
|
||||||
|
for (int octave = 0; octave < 5; ++octave)
|
||||||
|
{
|
||||||
|
sum += QD3D12_SkyCloudNoise(p) * amp;
|
||||||
|
norm += amp;
|
||||||
|
p *= 2.06;
|
||||||
|
amp *= 0.52;
|
||||||
|
}
|
||||||
|
|
||||||
|
return sum / max(norm, 1.0e-4);
|
||||||
|
}
|
||||||
|
|
||||||
|
float QD3D12_SkyCloudBillow(float3 p)
|
||||||
|
{
|
||||||
|
return 1.0 - abs(QD3D12_SkyCloudFBm(p) * 2.0 - 1.0);
|
||||||
|
}
|
||||||
|
)HLSL"
|
||||||
|
R"HLSL(
|
||||||
|
float4 PSSkyClouds(VSOut i) : SV_Target0
|
||||||
|
{
|
||||||
|
float2 ndc = float2(i.uv.x * 2.0 - 1.0, 1.0 - i.uv.y * 2.0);
|
||||||
|
float3 ray = normalize(gSkyCloudForward + gSkyCloudRight * (ndc.x * gSkyCloudTanX) + gSkyCloudUp * (ndc.y * gSkyCloudTanY));
|
||||||
|
float horizonMask = smoothstep(-0.015, 0.18, ray.z);
|
||||||
|
if (horizonMask <= 0.0001)
|
||||||
|
discard;
|
||||||
|
|
||||||
|
float zMin = gSkyCloudZMin;
|
||||||
|
float zMax = max(gSkyCloudZMax, zMin + 64.0);
|
||||||
|
float slabDepth = zMax - zMin;
|
||||||
|
float cloudZ = zMin + slabDepth * 0.55;
|
||||||
|
float rayZ = max(ray.z, 0.10);
|
||||||
|
float baseT = (cloudZ - gSkyCloudViewOrigin.z) / rayZ;
|
||||||
|
if (baseT <= 0.0)
|
||||||
|
discard;
|
||||||
|
|
||||||
|
float2 baseWorld = (gSkyCloudViewOrigin + ray * baseT).xy;
|
||||||
|
float alpha = 0.0;
|
||||||
|
float shade = 0.0;
|
||||||
|
float scale = max(gSkyCloudScale, 0.00001);
|
||||||
|
float seed = gSkyCloudSeed;
|
||||||
|
float3 seedVec = float3(11.7 + seed * 0.00011, 3.4 - seed * 0.00007, 9.1);
|
||||||
|
|
||||||
|
[unroll]
|
||||||
|
for (int layer = 0; layer < 7; ++layer)
|
||||||
|
{
|
||||||
|
float l = ((float)layer + 0.5) * (1.0 / 7.0);
|
||||||
|
float heightFade = smoothstep(0.02, 0.34, l) * (1.0 - smoothstep(0.70, 1.0, l));
|
||||||
|
float2 layerDrift = float2(0.62, -0.28) * (seed * 0.00003 + l * 310.0);
|
||||||
|
float2 parallax = ray.xy * ((l - 0.5) * slabDepth * 0.16);
|
||||||
|
float2 cloudXY = (baseWorld + parallax + layerDrift) * scale;
|
||||||
|
float3 p = float3(cloudXY, seed * 0.00009 + l * 2.7);
|
||||||
|
|
||||||
|
float broad = QD3D12_SkyCloudFBm(p * 0.48 + seedVec);
|
||||||
|
float warpA = QD3D12_SkyCloudFBm(p * 0.82 + broad * 0.85 + seedVec.yzx);
|
||||||
|
float billowA = smoothstep(0.18, 0.96, QD3D12_SkyCloudBillow(p * 1.35 + warpA * 1.20));
|
||||||
|
float billowB = smoothstep(0.42, 0.96, QD3D12_SkyCloudBillow(p * 2.05 + seedVec.zxy));
|
||||||
|
|
||||||
|
float anvil = smoothstep(0.20, 0.76, broad);
|
||||||
|
float shape = anvil * (billowA * 0.88 + billowB * 0.12);
|
||||||
|
shape = smoothstep(saturate(gSkyCloudCoverage) * 0.66, 0.94, shape);
|
||||||
|
|
||||||
|
float density = shape * heightFade * max(gSkyCloudDensity, 0.0);
|
||||||
|
alpha += (1.0 - alpha) * density * 0.36;
|
||||||
|
shade += density * (0.66 + l * 0.22 + broad * 0.12);
|
||||||
|
}
|
||||||
|
|
||||||
|
alpha = saturate(alpha * saturate(gSkyCloudOpacity) * horizonMask);
|
||||||
|
if (alpha <= 0.001)
|
||||||
|
discard;
|
||||||
|
|
||||||
|
float skyLum = dot(saturate(gSkyCloudColor), float3(0.299, 0.587, 0.114));
|
||||||
|
float3 brightCloud = lerp(saturate(gSkyCloudColor * 1.28), float3(1.0, 0.985, 0.94), 0.76);
|
||||||
|
brightCloud *= 0.92 + saturate(shade) * 0.16 + saturate(skyLum) * 0.16;
|
||||||
|
return float4(saturate(brightCloud), alpha);
|
||||||
|
}
|
||||||
)HLSL"
|
)HLSL"
|
||||||
R"HLSL(
|
R"HLSL(
|
||||||
float4 PSSharpen(VSOut i) : SV_Target0
|
float4 PSSharpen(VSOut i) : SV_Target0
|
||||||
{
|
{
|
||||||
float4 center = gTex0.Sample(gSamp0, i.uv);
|
float4 center = gTex0.Sample(gSamp0, i.uv);
|
||||||
float amount = saturate(gPostSharpness);
|
float amount = saturate(gPostSharpness) * 2.35;
|
||||||
if (amount <= 0.0001)
|
if (amount <= 0.0001)
|
||||||
return center;
|
return center;
|
||||||
|
|
||||||
@@ -5151,11 +5284,23 @@ float4 PSSharpen(VSOut i) : SV_Target0
|
|||||||
float3 s = gTex0.Sample(gSamp0, saturate(i.uv + float2(0.0, texel.y))).rgb;
|
float3 s = gTex0.Sample(gSamp0, saturate(i.uv + float2(0.0, texel.y))).rgb;
|
||||||
float3 e = gTex0.Sample(gSamp0, saturate(i.uv + float2( texel.x, 0.0))).rgb;
|
float3 e = gTex0.Sample(gSamp0, saturate(i.uv + float2( texel.x, 0.0))).rgb;
|
||||||
float3 w = gTex0.Sample(gSamp0, saturate(i.uv + float2(-texel.x, 0.0))).rgb;
|
float3 w = gTex0.Sample(gSamp0, saturate(i.uv + float2(-texel.x, 0.0))).rgb;
|
||||||
float3 blur = (n + s + e + w) * 0.25;
|
float3 ne = gTex0.Sample(gSamp0, saturate(i.uv + float2( texel.x, -texel.y))).rgb;
|
||||||
|
float3 nw = gTex0.Sample(gSamp0, saturate(i.uv + float2(-texel.x, -texel.y))).rgb;
|
||||||
|
float3 se = gTex0.Sample(gSamp0, saturate(i.uv + float2( texel.x, texel.y))).rgb;
|
||||||
|
float3 sw = gTex0.Sample(gSamp0, saturate(i.uv + float2(-texel.x, texel.y))).rgb;
|
||||||
|
float3 blur = (n + s + e + w) * 0.18 + (ne + nw + se + sw) * 0.07;
|
||||||
|
|
||||||
|
float3 albedoC = gScreenDecalNormal.Sample(gSamp0, i.uv).rgb;
|
||||||
|
float3 albedoN = gScreenDecalNormal.Sample(gSamp0, saturate(i.uv + float2(0.0, -texel.y))).rgb;
|
||||||
|
float3 albedoS = gScreenDecalNormal.Sample(gSamp0, saturate(i.uv + float2(0.0, texel.y))).rgb;
|
||||||
|
float3 albedoE = gScreenDecalNormal.Sample(gSamp0, saturate(i.uv + float2( texel.x, 0.0))).rgb;
|
||||||
|
float3 albedoW = gScreenDecalNormal.Sample(gSamp0, saturate(i.uv + float2(-texel.x, 0.0))).rgb;
|
||||||
|
float3 albedoBlur = (albedoN + albedoS + albedoE + albedoW) * 0.25;
|
||||||
|
float3 albedoDetail = clamp(albedoC - albedoBlur, -0.18, 0.18);
|
||||||
|
|
||||||
// Sharpen strictly after temporal reconstruction. Keep it conservative so
|
// Sharpen strictly after temporal reconstruction. Keep it conservative so
|
||||||
// the TAA resolve is not undone by ringing on high-contrast UI/geometry edges.
|
// the TAA resolve is not undone by ringing on high-contrast UI/geometry edges.
|
||||||
float3 sharp = center.rgb + (center.rgb - blur) * amount;
|
float3 sharp = center.rgb + (center.rgb - blur) * amount + albedoDetail * (amount * 0.38);
|
||||||
return QD3D12_ApplyPostFog(float4(saturate(sharp), center.a), i.uv);
|
return QD3D12_ApplyPostFog(float4(saturate(sharp), center.a), i.uv);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -5226,7 +5371,7 @@ float4 PSToneMapFinalMax(VSOut i) : SV_Target0
|
|||||||
R"HLSL(
|
R"HLSL(
|
||||||
float3 QD3D12_PostSharpenHDR(float2 uv, float3 center)
|
float3 QD3D12_PostSharpenHDR(float2 uv, float3 center)
|
||||||
{
|
{
|
||||||
float amount = saturate(gPostSharpness);
|
float amount = saturate(gPostSharpness) * 2.35;
|
||||||
if (amount <= 0.0001)
|
if (amount <= 0.0001)
|
||||||
return center;
|
return center;
|
||||||
|
|
||||||
@@ -5238,11 +5383,23 @@ float3 QD3D12_PostSharpenHDR(float2 uv, float3 center)
|
|||||||
float3 s = max(gTex0.Sample(gSamp0, saturate(uv + float2(0.0, texel.y))).rgb, 0.0);
|
float3 s = max(gTex0.Sample(gSamp0, saturate(uv + float2(0.0, texel.y))).rgb, 0.0);
|
||||||
float3 e = max(gTex0.Sample(gSamp0, saturate(uv + float2( texel.x, 0.0))).rgb, 0.0);
|
float3 e = max(gTex0.Sample(gSamp0, saturate(uv + float2( texel.x, 0.0))).rgb, 0.0);
|
||||||
float3 w = max(gTex0.Sample(gSamp0, saturate(uv + float2(-texel.x, 0.0))).rgb, 0.0);
|
float3 w = max(gTex0.Sample(gSamp0, saturate(uv + float2(-texel.x, 0.0))).rgb, 0.0);
|
||||||
float3 blur = (n + s + e + w) * 0.25;
|
float3 ne = max(gTex0.Sample(gSamp0, saturate(uv + float2( texel.x, -texel.y))).rgb, 0.0);
|
||||||
|
float3 nw = max(gTex0.Sample(gSamp0, saturate(uv + float2(-texel.x, -texel.y))).rgb, 0.0);
|
||||||
|
float3 se = max(gTex0.Sample(gSamp0, saturate(uv + float2( texel.x, texel.y))).rgb, 0.0);
|
||||||
|
float3 sw = max(gTex0.Sample(gSamp0, saturate(uv + float2(-texel.x, texel.y))).rgb, 0.0);
|
||||||
|
float3 blur = (n + s + e + w) * 0.18 + (ne + nw + se + sw) * 0.07;
|
||||||
|
|
||||||
|
float3 albedoC = max(gScreenDecalNormal.Sample(gSamp0, uv).rgb, 0.0);
|
||||||
|
float3 albedoN = max(gScreenDecalNormal.Sample(gSamp0, saturate(uv + float2(0.0, -texel.y))).rgb, 0.0);
|
||||||
|
float3 albedoS = max(gScreenDecalNormal.Sample(gSamp0, saturate(uv + float2(0.0, texel.y))).rgb, 0.0);
|
||||||
|
float3 albedoE = max(gScreenDecalNormal.Sample(gSamp0, saturate(uv + float2( texel.x, 0.0))).rgb, 0.0);
|
||||||
|
float3 albedoW = max(gScreenDecalNormal.Sample(gSamp0, saturate(uv + float2(-texel.x, 0.0))).rgb, 0.0);
|
||||||
|
float3 albedoBlur = (albedoN + albedoS + albedoE + albedoW) * 0.25;
|
||||||
|
float3 albedoDetail = clamp(albedoC - albedoBlur, -0.18, 0.18);
|
||||||
|
|
||||||
// Sharpen before tone mapping so highlights keep their shoulder instead of
|
// Sharpen before tone mapping so highlights keep their shoulder instead of
|
||||||
// ringing after they have already been compressed to display range.
|
// ringing after they have already been compressed to display range.
|
||||||
return min(max(center + (center - blur) * amount, 0.0), 65504.0);
|
return min(max(center + (center - blur) * amount + albedoDetail * (amount * 0.38), 0.0), 65504.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
float3 QD3D12_ExtendedReinhard(float3 hdr, float whitePoint)
|
float3 QD3D12_ExtendedReinhard(float3 hdr, float whitePoint)
|
||||||
@@ -8531,7 +8688,8 @@ static void QD3D12_SetPostConstants(
|
|||||||
float screenParticleEmissiveScale = 0.0f,
|
float screenParticleEmissiveScale = 0.0f,
|
||||||
float screenParticleOutputMode = 0.0f,
|
float screenParticleOutputMode = 0.0f,
|
||||||
float screenParticleDepthScaleX = 1.0f,
|
float screenParticleDepthScaleX = 1.0f,
|
||||||
float screenParticleDepthScaleY = 1.0f)
|
float screenParticleDepthScaleY = 1.0f,
|
||||||
|
const glSkyClouds_t* skyClouds = nullptr)
|
||||||
{
|
{
|
||||||
if (!cl)
|
if (!cl)
|
||||||
return;
|
return;
|
||||||
@@ -8574,12 +8732,48 @@ static void QD3D12_SetPostConstants(
|
|||||||
constants[25] = screenParticleOutputMode;
|
constants[25] = screenParticleOutputMode;
|
||||||
constants[26] = screenParticleDepthScaleX;
|
constants[26] = screenParticleDepthScaleX;
|
||||||
constants[27] = screenParticleDepthScaleY;
|
constants[27] = screenParticleDepthScaleY;
|
||||||
|
if (skyClouds)
|
||||||
|
{
|
||||||
|
constants[20] = skyClouds->viewOrigin[0];
|
||||||
|
constants[21] = skyClouds->viewOrigin[1];
|
||||||
|
constants[22] = skyClouds->viewOrigin[2];
|
||||||
|
constants[23] = skyClouds->zMin;
|
||||||
|
constants[28] = skyClouds->skyColor[0];
|
||||||
|
constants[29] = skyClouds->skyColor[1];
|
||||||
|
constants[30] = skyClouds->skyColor[2];
|
||||||
|
constants[31] = skyClouds->opacity;
|
||||||
|
constants[32] = skyClouds->viewForward[0];
|
||||||
|
constants[33] = skyClouds->viewForward[1];
|
||||||
|
constants[34] = skyClouds->viewForward[2];
|
||||||
|
constants[35] = skyClouds->zMax;
|
||||||
|
constants[36] = skyClouds->viewRight[0];
|
||||||
|
constants[37] = skyClouds->viewRight[1];
|
||||||
|
constants[38] = skyClouds->viewRight[2];
|
||||||
|
constants[39] = skyClouds->tanHalfFovX;
|
||||||
|
constants[40] = skyClouds->viewUp[0];
|
||||||
|
constants[41] = skyClouds->viewUp[1];
|
||||||
|
constants[42] = skyClouds->viewUp[2];
|
||||||
|
constants[43] = skyClouds->tanHalfFovY;
|
||||||
|
constants[44] = skyClouds->noiseScale;
|
||||||
|
constants[45] = skyClouds->coverage;
|
||||||
|
constants[46] = skyClouds->density;
|
||||||
|
constants[47] = skyClouds->seedOffset;
|
||||||
|
}
|
||||||
cl->SetGraphicsRoot32BitConstants(QD3D12_PostRootConstants, QD3D12_PostConstantDwords, constants, 0);
|
cl->SetGraphicsRoot32BitConstants(QD3D12_PostRootConstants, QD3D12_PostConstantDwords, constants, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void QD3D12_BindPostFogResources(ID3D12GraphicsCommandList* cl, QD3D12Window& w, bool applySceneFog)
|
static void QD3D12_BindPostFogResources(ID3D12GraphicsCommandList* cl, QD3D12Window& w, bool applySceneFog)
|
||||||
{
|
{
|
||||||
if (!cl || !applySceneFog || !g_gl.sceneFogValidThisFrame)
|
if (!cl)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (w.sceneColorBuffers[w.frameIndex] && w.sceneColorSrvIndex[w.frameIndex] != UINT_MAX)
|
||||||
|
{
|
||||||
|
QD3D12_TransitionResource(cl, w.sceneColorBuffers[w.frameIndex].Get(), w.sceneColorState[w.frameIndex], D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE);
|
||||||
|
cl->SetGraphicsRootDescriptorTable(11, w.sceneColorSrvGpu[w.frameIndex]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!applySceneFog || !g_gl.sceneFogValidThisFrame)
|
||||||
return;
|
return;
|
||||||
if (!w.positionBuffers[w.frameIndex] || !w.depthBuffer)
|
if (!w.positionBuffers[w.frameIndex] || !w.depthBuffer)
|
||||||
return;
|
return;
|
||||||
@@ -8895,6 +9089,11 @@ static bool QD3D12_ToneMapFullscreenPass(
|
|||||||
cl->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
|
cl->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
|
||||||
cl->SetGraphicsRootDescriptorTable(0, hdrInputSrv);
|
cl->SetGraphicsRootDescriptorTable(0, hdrInputSrv);
|
||||||
cl->SetGraphicsRootDescriptorTable(7, w.toneMapSceneMaxSrvGpu[frame]);
|
cl->SetGraphicsRootDescriptorTable(7, w.toneMapSceneMaxSrvGpu[frame]);
|
||||||
|
if (w.sceneColorBuffers[frame] && w.sceneColorSrvIndex[frame] != UINT_MAX)
|
||||||
|
{
|
||||||
|
QD3D12_TransitionResource(cl, w.sceneColorBuffers[frame].Get(), w.sceneColorState[frame], D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE);
|
||||||
|
cl->SetGraphicsRootDescriptorTable(11, w.sceneColorSrvGpu[frame]);
|
||||||
|
}
|
||||||
QD3D12_BindPostFogResources(cl, w, applySceneFog);
|
QD3D12_BindPostFogResources(cl, w, applySceneFog);
|
||||||
cl->DrawInstanced(3, 1, 0, 0);
|
cl->DrawInstanced(3, 1, 0, 0);
|
||||||
return true;
|
return true;
|
||||||
@@ -9019,6 +9218,52 @@ void APIENTRY glDrawScreenSpaceDecalsQD3D12(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void APIENTRY glDrawSkyCloudsQD3D12(const glSkyClouds_t* clouds)
|
||||||
|
{
|
||||||
|
if (!clouds || clouds->opacity <= 0.0f || clouds->density <= 0.0f)
|
||||||
|
return;
|
||||||
|
|
||||||
|
QD3D12Window* window = g_currentWindow;
|
||||||
|
if (!window || !g_gl.device || !g_gl.cmdList || !g_gl.postSkyCloudsPSO)
|
||||||
|
return;
|
||||||
|
if (!window->sceneColorBuffers[window->frameIndex])
|
||||||
|
return;
|
||||||
|
|
||||||
|
QD3D12_EnsureFrameOpen();
|
||||||
|
QD3D12_FlushQueuedBatches();
|
||||||
|
|
||||||
|
const UINT frame = window->frameIndex;
|
||||||
|
ID3D12GraphicsCommandList* cl = g_gl.cmdList.Get();
|
||||||
|
QD3D12_TransitionResource(cl, window->sceneColorBuffers[frame].Get(), window->sceneColorState[frame], D3D12_RESOURCE_STATE_RENDER_TARGET);
|
||||||
|
|
||||||
|
D3D12_VIEWPORT viewport{};
|
||||||
|
viewport.TopLeftX = 0.0f;
|
||||||
|
viewport.TopLeftY = 0.0f;
|
||||||
|
viewport.Width = (float)window->renderWidth;
|
||||||
|
viewport.Height = (float)window->renderHeight;
|
||||||
|
viewport.MinDepth = 0.0f;
|
||||||
|
viewport.MaxDepth = 1.0f;
|
||||||
|
|
||||||
|
D3D12_RECT scissor{};
|
||||||
|
scissor.left = 0;
|
||||||
|
scissor.top = 0;
|
||||||
|
scissor.right = (LONG)window->renderWidth;
|
||||||
|
scissor.bottom = (LONG)window->renderHeight;
|
||||||
|
|
||||||
|
ID3D12DescriptorHeap* heaps[] = { g_gl.srvHeap.Get() };
|
||||||
|
cl->SetDescriptorHeaps(_countof(heaps), heaps);
|
||||||
|
cl->SetGraphicsRootSignature(g_gl.postRootSig.Get());
|
||||||
|
QD3D12_SetPostConstants(cl, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f, false, 0.0f, 0.0f, false, 16.0f, 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, clouds);
|
||||||
|
cl->SetPipelineState(g_gl.postSkyCloudsPSO.Get());
|
||||||
|
cl->SetGraphicsRootDescriptorTable(0, g_gl.whiteTexture.srvGpu);
|
||||||
|
D3D12_CPU_DESCRIPTOR_HANDLE sceneColorRtv = QD3D12_RtvAt(*window, QD3D12_RTV_SCENE_RENDER, frame);
|
||||||
|
cl->OMSetRenderTargets(1, &sceneColorRtv, FALSE, nullptr);
|
||||||
|
cl->RSSetViewports(1, &viewport);
|
||||||
|
cl->RSSetScissorRects(1, &scissor);
|
||||||
|
cl->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
|
||||||
|
cl->DrawInstanced(3, 1, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
static void QD3D12_DrawScreenSpaceParticleBatch(const QD3D12ScreenSpaceParticleBatch& batch, ID3D12Resource* tlas, bool emissiveOnly, bool nativeOutput)
|
static void QD3D12_DrawScreenSpaceParticleBatch(const QD3D12ScreenSpaceParticleBatch& batch, ID3D12Resource* tlas, bool emissiveOnly, bool nativeOutput)
|
||||||
{
|
{
|
||||||
const glScreenSpaceParticleVertex_t* verts = batch.vertices.empty() ? nullptr : batch.vertices.data();
|
const glScreenSpaceParticleVertex_t* verts = batch.vertices.empty() ? nullptr : batch.vertices.data();
|
||||||
@@ -9538,7 +9783,6 @@ static void QD3D12_RunUpscalerOrBlit(QD3D12Window& w)
|
|||||||
sl::Resource depth = { sl::ResourceType::eTex2d, w.depthBuffer.Get(), nullptr, nullptr, uint32_t(w.depthState) };
|
sl::Resource depth = { sl::ResourceType::eTex2d, w.depthBuffer.Get(), nullptr, nullptr, uint32_t(w.depthState) };
|
||||||
sl::Resource mvec = { sl::ResourceType::eTex2d, w.velocityBuffers[w.frameIndex].Get(), nullptr, nullptr, uint32_t(w.velocityBufferState[w.frameIndex]) };
|
sl::Resource mvec = { sl::ResourceType::eTex2d, w.velocityBuffers[w.frameIndex].Get(), nullptr, nullptr, uint32_t(w.velocityBufferState[w.frameIndex]) };
|
||||||
sl::Resource diffuseAlbedo = { sl::ResourceType::eTex2d, w.sceneColorBuffers[w.frameIndex].Get(), nullptr, nullptr, uint32_t(w.sceneColorState[w.frameIndex]) };
|
sl::Resource diffuseAlbedo = { sl::ResourceType::eTex2d, w.sceneColorBuffers[w.frameIndex].Get(), nullptr, nullptr, uint32_t(w.sceneColorState[w.frameIndex]) };
|
||||||
sl::Resource specularMvec = { sl::ResourceType::eTex2d, w.velocityBuffers[w.frameIndex].Get(), nullptr, nullptr, uint32_t(w.velocityBufferState[w.frameIndex]) };
|
|
||||||
sl::Resource specularAlbedo = { sl::ResourceType::eTex2d, w.specularBuffers[w.frameIndex].Get(), nullptr, nullptr, uint32_t(w.specularBufferState[w.frameIndex]) };
|
sl::Resource specularAlbedo = { sl::ResourceType::eTex2d, w.specularBuffers[w.frameIndex].Get(), nullptr, nullptr, uint32_t(w.specularBufferState[w.frameIndex]) };
|
||||||
sl::Resource normalRoughness = { sl::ResourceType::eTex2d, w.normalBuffers[w.frameIndex].Get(), nullptr, nullptr, uint32_t(w.normalBufferState[w.frameIndex]) };
|
sl::Resource normalRoughness = { sl::ResourceType::eTex2d, w.normalBuffers[w.frameIndex].Get(), nullptr, nullptr, uint32_t(w.normalBufferState[w.frameIndex]) };
|
||||||
|
|
||||||
@@ -9549,7 +9793,6 @@ static void QD3D12_RunUpscalerOrBlit(QD3D12Window& w)
|
|||||||
sl::ResourceTag{ &depth, sl::kBufferTypeDepth, sl::ResourceLifecycle::eValidUntilPresent, &renderExtent },
|
sl::ResourceTag{ &depth, sl::kBufferTypeDepth, sl::ResourceLifecycle::eValidUntilPresent, &renderExtent },
|
||||||
sl::ResourceTag{ &mvec, sl::kBufferTypeMotionVectors, sl::ResourceLifecycle::eOnlyValidNow, &renderExtent },
|
sl::ResourceTag{ &mvec, sl::kBufferTypeMotionVectors, sl::ResourceLifecycle::eOnlyValidNow, &renderExtent },
|
||||||
sl::ResourceTag{ &diffuseAlbedo, sl::kBufferTypeAlbedo, sl::ResourceLifecycle::eOnlyValidNow, &renderExtent },
|
sl::ResourceTag{ &diffuseAlbedo, sl::kBufferTypeAlbedo, sl::ResourceLifecycle::eOnlyValidNow, &renderExtent },
|
||||||
sl::ResourceTag{ &specularMvec, sl::kBufferTypeSpecularMotionVectors, sl::ResourceLifecycle::eOnlyValidNow, &renderExtent },
|
|
||||||
sl::ResourceTag{ &specularAlbedo, sl::kBufferTypeSpecularAlbedo, sl::ResourceLifecycle::eOnlyValidNow, &renderExtent },
|
sl::ResourceTag{ &specularAlbedo, sl::kBufferTypeSpecularAlbedo, sl::ResourceLifecycle::eOnlyValidNow, &renderExtent },
|
||||||
sl::ResourceTag{ &normalRoughness, sl::kBufferTypeNormalRoughness, sl::ResourceLifecycle::eOnlyValidNow, &renderExtent }
|
sl::ResourceTag{ &normalRoughness, sl::kBufferTypeNormalRoughness, sl::ResourceLifecycle::eOnlyValidNow, &renderExtent }
|
||||||
};
|
};
|
||||||
@@ -10784,6 +11027,7 @@ static void QD3D12_CompileShaders()
|
|||||||
g_gl.postPsScreenDecalBlob = CompileShaderSourceVariant(kQD3D12PostHLSL, "PSScreenDecals", "ps_6_0");
|
g_gl.postPsScreenDecalBlob = CompileShaderSourceVariant(kQD3D12PostHLSL, "PSScreenDecals", "ps_6_0");
|
||||||
g_gl.postVsScreenParticleBlob = CompileShaderSourceVariant(kQD3D12PostHLSL, "VSParticle", "vs_6_0");
|
g_gl.postVsScreenParticleBlob = CompileShaderSourceVariant(kQD3D12PostHLSL, "VSParticle", "vs_6_0");
|
||||||
g_gl.postPsScreenParticleBlob = CompileShaderSourceVariant(kQD3D12PostHLSL, "PSScreenParticles", "ps_6_5", L"QD3D12_SCREEN_PARTICLE_RAYQUERY=1");
|
g_gl.postPsScreenParticleBlob = CompileShaderSourceVariant(kQD3D12PostHLSL, "PSScreenParticles", "ps_6_5", L"QD3D12_SCREEN_PARTICLE_RAYQUERY=1");
|
||||||
|
g_gl.postPsSkyCloudsBlob = CompileShaderSourceVariant(kQD3D12PostHLSL, "PSSkyClouds", "ps_6_0");
|
||||||
}
|
}
|
||||||
|
|
||||||
static const D3D12_INPUT_ELEMENT_DESC kGLVertexInputLayout[] =
|
static const D3D12_INPUT_ELEMENT_DESC kGLVertexInputLayout[] =
|
||||||
@@ -11015,6 +11259,16 @@ static void QD3D12_CreatePSOs()
|
|||||||
d.BlendState.RenderTarget[0].DestBlendAlpha = D3D12_BLEND_ONE;
|
d.BlendState.RenderTarget[0].DestBlendAlpha = D3D12_BLEND_ONE;
|
||||||
QD3D12_CHECK(g_gl.device->CreateGraphicsPipelineState(&d, IID_PPV_ARGS(&g_gl.postScreenDecalStainPSO)));
|
QD3D12_CHECK(g_gl.device->CreateGraphicsPipelineState(&d, IID_PPV_ARGS(&g_gl.postScreenDecalStainPSO)));
|
||||||
|
|
||||||
|
d.PS = { g_gl.postPsSkyCloudsBlob->GetBufferPointer(), g_gl.postPsSkyCloudsBlob->GetBufferSize() };
|
||||||
|
d.BlendState.RenderTarget[0].BlendEnable = TRUE;
|
||||||
|
d.BlendState.RenderTarget[0].SrcBlend = D3D12_BLEND_SRC_ALPHA;
|
||||||
|
d.BlendState.RenderTarget[0].DestBlend = D3D12_BLEND_INV_SRC_ALPHA;
|
||||||
|
d.BlendState.RenderTarget[0].BlendOp = D3D12_BLEND_OP_ADD;
|
||||||
|
d.BlendState.RenderTarget[0].SrcBlendAlpha = D3D12_BLEND_ONE;
|
||||||
|
d.BlendState.RenderTarget[0].DestBlendAlpha = D3D12_BLEND_INV_SRC_ALPHA;
|
||||||
|
d.BlendState.RenderTarget[0].BlendOpAlpha = D3D12_BLEND_OP_ADD;
|
||||||
|
QD3D12_CHECK(g_gl.device->CreateGraphicsPipelineState(&d, IID_PPV_ARGS(&g_gl.postSkyCloudsPSO)));
|
||||||
|
|
||||||
D3D12_GRAPHICS_PIPELINE_STATE_DESC particleDesc = d;
|
D3D12_GRAPHICS_PIPELINE_STATE_DESC particleDesc = d;
|
||||||
particleDesc.VS = { g_gl.postVsScreenParticleBlob->GetBufferPointer(), g_gl.postVsScreenParticleBlob->GetBufferSize() };
|
particleDesc.VS = { g_gl.postVsScreenParticleBlob->GetBufferPointer(), g_gl.postVsScreenParticleBlob->GetBufferSize() };
|
||||||
particleDesc.PS = { g_gl.postPsScreenParticleBlob->GetBufferPointer(), g_gl.postPsScreenParticleBlob->GetBufferSize() };
|
particleDesc.PS = { g_gl.postPsScreenParticleBlob->GetBufferPointer(), g_gl.postPsScreenParticleBlob->GetBufferSize() };
|
||||||
@@ -17881,6 +18135,7 @@ PROC WINAPI qd3d12_wglGetProcAddress(LPCSTR name) {
|
|||||||
{ "glDrawScreenSpaceDecalsQD3D12",(PROC)glDrawScreenSpaceDecalsQD3D12 },
|
{ "glDrawScreenSpaceDecalsQD3D12",(PROC)glDrawScreenSpaceDecalsQD3D12 },
|
||||||
{ "glSetScreenSpaceParticleLightsQD3D12",(PROC)glSetScreenSpaceParticleLightsQD3D12 },
|
{ "glSetScreenSpaceParticleLightsQD3D12",(PROC)glSetScreenSpaceParticleLightsQD3D12 },
|
||||||
{ "glDrawScreenSpaceParticlesQD3D12",(PROC)glDrawScreenSpaceParticlesQD3D12 },
|
{ "glDrawScreenSpaceParticlesQD3D12",(PROC)glDrawScreenSpaceParticlesQD3D12 },
|
||||||
|
{ "glDrawSkyCloudsQD3D12", (PROC)glDrawSkyCloudsQD3D12 },
|
||||||
{ "QD3D12_SetUpscalerBackend", (PROC)QD3D12_SetUpscalerBackend },
|
{ "QD3D12_SetUpscalerBackend", (PROC)QD3D12_SetUpscalerBackend },
|
||||||
{ "QD3D12_SetUpscalerQuality", (PROC)QD3D12_SetUpscalerQuality },
|
{ "QD3D12_SetUpscalerQuality", (PROC)QD3D12_SetUpscalerQuality },
|
||||||
{ "QD3D12_SetUpscalerSharpness", (PROC)QD3D12_SetUpscalerSharpness },
|
{ "QD3D12_SetUpscalerSharpness", (PROC)QD3D12_SetUpscalerSharpness },
|
||||||
|
|||||||
@@ -1794,6 +1794,24 @@ typedef struct glScreenSpaceParticleVertex_s
|
|||||||
float pad0;
|
float pad0;
|
||||||
} glScreenSpaceParticleVertex_t;
|
} glScreenSpaceParticleVertex_t;
|
||||||
|
|
||||||
|
typedef struct glSkyClouds_s
|
||||||
|
{
|
||||||
|
float skyColor[3];
|
||||||
|
float opacity;
|
||||||
|
float viewOrigin[3];
|
||||||
|
float zMin;
|
||||||
|
float viewForward[3];
|
||||||
|
float zMax;
|
||||||
|
float viewRight[3];
|
||||||
|
float tanHalfFovX;
|
||||||
|
float viewUp[3];
|
||||||
|
float tanHalfFovY;
|
||||||
|
float noiseScale;
|
||||||
|
float coverage;
|
||||||
|
float density;
|
||||||
|
float seedOffset;
|
||||||
|
} glSkyClouds_t;
|
||||||
|
|
||||||
int glRaytracingInit(void);
|
int glRaytracingInit(void);
|
||||||
void glRaytracingShutdown(void);
|
void glRaytracingShutdown(void);
|
||||||
void glRaytracingClear(void);
|
void glRaytracingClear(void);
|
||||||
@@ -1893,6 +1911,7 @@ void glSetScreenSpaceDecalsQD3D12(const glScreenSpaceDecal
|
|||||||
void glDrawScreenSpaceDecalsQD3D12(void);
|
void glDrawScreenSpaceDecalsQD3D12(void);
|
||||||
void glSetScreenSpaceParticleLightsQD3D12(const glRaytracingLight_t* lights, uint32_t lightCount);
|
void glSetScreenSpaceParticleLightsQD3D12(const glRaytracingLight_t* lights, uint32_t lightCount);
|
||||||
void glDrawScreenSpaceParticlesQD3D12(const glScreenSpaceParticleVertex_t* verts, uint32_t vertexCount, uint32_t textureId, uint32_t blendMode, float softDepth, float emissiveScale);
|
void glDrawScreenSpaceParticlesQD3D12(const glScreenSpaceParticleVertex_t* verts, uint32_t vertexCount, uint32_t textureId, uint32_t blendMode, float softDepth, float emissiveScale);
|
||||||
|
void glDrawSkyCloudsQD3D12(const glSkyClouds_t* clouds);
|
||||||
|
|
||||||
ID3D12Device* QD3D12_GetDevice(void);
|
ID3D12Device* QD3D12_GetDevice(void);
|
||||||
ID3D12CommandQueue* QD3D12_GetQueue(void);
|
ID3D12CommandQueue* QD3D12_GetQueue(void);
|
||||||
@@ -2313,6 +2332,8 @@ void glUpdateTopLevelAceelStructure(
|
|||||||
void glRaytracingLightingSetExternalDenoiser(int enable);
|
void glRaytracingLightingSetExternalDenoiser(int enable);
|
||||||
void glRaytracingLightingUseExternalDenoiser(int enable);
|
void glRaytracingLightingUseExternalDenoiser(int enable);
|
||||||
void glRaytracingLightingSetPathTracingOptions(uint32_t samplesPerPixel, uint32_t maxBounces, int enableDenoiser, float denoiseStrength);
|
void glRaytracingLightingSetPathTracingOptions(uint32_t samplesPerPixel, uint32_t maxBounces, int enableDenoiser, float denoiseStrength);
|
||||||
|
void glRaytracingLightingSetGIAmount(float amount);
|
||||||
|
void glRaytracingLightingSetWorldGrime(float amount);
|
||||||
void glRaytracingLightingSetSecondaryLightBudget(int budget, float compensation);
|
void glRaytracingLightingSetSecondaryLightBudget(int budget, float compensation);
|
||||||
void QD3D12_SetPathTracingQuality(uint32_t samplesPerPixel, uint32_t maxBounces);
|
void QD3D12_SetPathTracingQuality(uint32_t samplesPerPixel, uint32_t maxBounces);
|
||||||
void QD3D12_SetPathTracingFallbackSamples(uint32_t samplesPerPixel);
|
void QD3D12_SetPathTracingFallbackSamples(uint32_t samplesPerPixel);
|
||||||
|
|||||||
@@ -189,6 +189,8 @@ idCVar r_showInteractionFrustums( "r_showInteractionFrustums", "0", CVAR_RENDERE
|
|||||||
idCVar r_showInteractionScissors( "r_showInteractionScissors", "0", CVAR_RENDERER | CVAR_INTEGER, "1 = show screen rectangle which contains the interaction frustum, 2 = also draw construction lines", 0, 2, idCmdSystem::ArgCompletion_Integer<0,2> );
|
idCVar r_showInteractionScissors( "r_showInteractionScissors", "0", CVAR_RENDERER | CVAR_INTEGER, "1 = show screen rectangle which contains the interaction frustum, 2 = also draw construction lines", 0, 2, idCmdSystem::ArgCompletion_Integer<0,2> );
|
||||||
idCVar r_showLightCount( "r_showLightCount", "0", CVAR_RENDERER | CVAR_INTEGER, "1 = colors surfaces based on light count, 2 = also count everything through walls, 3 = also print overdraw", 0, 3, idCmdSystem::ArgCompletion_Integer<0,3> );
|
idCVar r_showLightCount( "r_showLightCount", "0", CVAR_RENDERER | CVAR_INTEGER, "1 = colors surfaces based on light count, 2 = also count everything through walls, 3 = also print overdraw", 0, 3, idCmdSystem::ArgCompletion_Integer<0,3> );
|
||||||
idCVar r_showPathTraceProfile( "r_showPathTraceProfile", "0", CVAR_RENDERER | CVAR_INTEGER, "report path tracer GPU and estimated ray workload, 1 = once per second, 2 = every frame", 0, 2, idCmdSystem::ArgCompletion_Integer<0,2> );
|
idCVar r_showPathTraceProfile( "r_showPathTraceProfile", "0", CVAR_RENDERER | CVAR_INTEGER, "report path tracer GPU and estimated ray workload, 1 = once per second, 2 = every frame", 0, 2, idCmdSystem::ArgCompletion_Integer<0,2> );
|
||||||
|
idCVar r_pathTraceGIAmount( "r_pathTraceGIAmount", "0.6", CVAR_RENDERER | CVAR_FLOAT, "scale path traced indirect GI, 0 = off, 1 = normal, values above 1 boost GI" );
|
||||||
|
idCVar r_pathTraceWorldGrime( "r_pathTraceWorldGrime", "1.5", CVAR_RENDERER | CVAR_FLOAT, "add stable cavity dirt to non-skeletal path traced surfaces, 0 = off" );
|
||||||
idCVar r_pathTraceSecondaryLightBudget( "r_pathTraceSecondaryLightBudget", "0", CVAR_RENDERER | CVAR_INTEGER, "secondary GI light budget, 0 = automatic, -1 = full light list" );
|
idCVar r_pathTraceSecondaryLightBudget( "r_pathTraceSecondaryLightBudget", "0", CVAR_RENDERER | CVAR_INTEGER, "secondary GI light budget, 0 = automatic, -1 = full light list" );
|
||||||
idCVar r_pathTraceSecondaryLightCompensation( "r_pathTraceSecondaryLightCompensation", "0.62", CVAR_RENDERER | CVAR_FLOAT, "energy compensation for capped secondary GI lights, 0 = none, 1 = full scale" );
|
idCVar r_pathTraceSecondaryLightCompensation( "r_pathTraceSecondaryLightCompensation", "0.62", CVAR_RENDERER | CVAR_FLOAT, "energy compensation for capped secondary GI lights, 0 = none, 1 = full scale" );
|
||||||
idCVar r_pathTracePortalWorldCulling( "r_pathTracePortalWorldCulling", "0", CVAR_RENDERER | CVAR_BOOL, "use portal flood to hide/show static world ray tracing instances" );
|
idCVar r_pathTracePortalWorldCulling( "r_pathTracePortalWorldCulling", "0", CVAR_RENDERER | CVAR_BOOL, "use portal flood to hide/show static world ray tracing instances" );
|
||||||
@@ -532,6 +534,8 @@ void R_InitOpenGL( void ) {
|
|||||||
|
|
||||||
glRaytracingLightingSetExternalDenoiser(0);
|
glRaytracingLightingSetExternalDenoiser(0);
|
||||||
glRaytracingLightingSetPathTracingOptions(1, 2, 1, 1.0f);
|
glRaytracingLightingSetPathTracingOptions(1, 2, 1, 1.0f);
|
||||||
|
glRaytracingLightingSetGIAmount(r_pathTraceGIAmount.GetFloat());
|
||||||
|
glRaytracingLightingSetWorldGrime(r_pathTraceWorldGrime.GetFloat());
|
||||||
|
|
||||||
// Create the DXR worlds.
|
// Create the DXR worlds.
|
||||||
for (int i = 0; i < DXR_WORLD_NUM; i++)
|
for (int i = 0; i < DXR_WORLD_NUM; i++)
|
||||||
|
|||||||
@@ -400,6 +400,8 @@ void RB_DXDrawInteractions(void)
|
|||||||
{
|
{
|
||||||
backEnd.viewDef->renderWorld->SubmitWorldDecalsToScreenSpace();
|
backEnd.viewDef->renderWorld->SubmitWorldDecalsToScreenSpace();
|
||||||
glSetScreenSpaceParticleLightsQD3D12(screenParticleLights.Ptr(), screenParticleLights.Num());
|
glSetScreenSpaceParticleLightsQD3D12(screenParticleLights.Ptr(), screenParticleLights.Num());
|
||||||
|
glRaytracingLightingSetGIAmount(r_pathTraceGIAmount.GetFloat());
|
||||||
|
glRaytracingLightingSetWorldGrime(r_pathTraceWorldGrime.GetFloat());
|
||||||
glRaytracingLightingSetSecondaryLightBudget(
|
glRaytracingLightingSetSecondaryLightBudget(
|
||||||
r_pathTraceSecondaryLightBudget.GetInteger(),
|
r_pathTraceSecondaryLightBudget.GetInteger(),
|
||||||
r_pathTraceSecondaryLightCompensation.GetFloat());
|
r_pathTraceSecondaryLightCompensation.GetFloat());
|
||||||
|
|||||||
@@ -960,6 +960,8 @@ extern idCVar r_showEntityScissors; // show entity scissor rectangles
|
|||||||
extern idCVar r_showInteractionFrustums;// show a frustum for each interaction
|
extern idCVar r_showInteractionFrustums;// show a frustum for each interaction
|
||||||
extern idCVar r_showInteractionScissors;// show screen rectangle which contains the interaction frustum
|
extern idCVar r_showInteractionScissors;// show screen rectangle which contains the interaction frustum
|
||||||
extern idCVar r_showPathTraceProfile; // report path tracer GPU and estimated ray workload
|
extern idCVar r_showPathTraceProfile; // report path tracer GPU and estimated ray workload
|
||||||
|
extern idCVar r_pathTraceGIAmount; // scale path traced indirect GI
|
||||||
|
extern idCVar r_pathTraceWorldGrime; // stable cavity dirt for non-skeletal path traced surfaces
|
||||||
extern idCVar r_pathTraceSecondaryLightBudget; // secondary GI light budget
|
extern idCVar r_pathTraceSecondaryLightBudget; // secondary GI light budget
|
||||||
extern idCVar r_pathTraceSecondaryLightCompensation; // secondary GI energy compensation
|
extern idCVar r_pathTraceSecondaryLightCompensation; // secondary GI energy compensation
|
||||||
extern idCVar r_pathTracePortalWorldCulling; // portal cull static ray tracing world instances
|
extern idCVar r_pathTracePortalWorldCulling; // portal cull static ray tracing world instances
|
||||||
|
|||||||
@@ -11,6 +11,16 @@ static idCVar r_skyDomeRadius("r_skyDomeRadius", "8192", CVAR_RENDERER | CVAR_FL
|
|||||||
static idCVar r_skyDomeRings("r_skyDomeRings", "24", CVAR_RENDERER | CVAR_INTEGER, "skydome vertical subdivisions");
|
static idCVar r_skyDomeRings("r_skyDomeRings", "24", CVAR_RENDERER | CVAR_INTEGER, "skydome vertical subdivisions");
|
||||||
static idCVar r_skyDomeSegments("r_skyDomeSegments", "48", CVAR_RENDERER | CVAR_INTEGER, "skydome horizontal subdivisions");
|
static idCVar r_skyDomeSegments("r_skyDomeSegments", "48", CVAR_RENDERER | CVAR_INTEGER, "skydome horizontal subdivisions");
|
||||||
|
|
||||||
|
static idCVar r_skyClouds("r_skyClouds", "1", CVAR_RENDERER | CVAR_BOOL, "render automatic raymarched sky clouds");
|
||||||
|
static idCVar r_skyCloudZMin("r_skyCloudZMin", "2600", CVAR_RENDERER | CVAR_FLOAT, "sky cloud slab minimum world z");
|
||||||
|
static idCVar r_skyCloudZMax("r_skyCloudZMax", "7600", CVAR_RENDERER | CVAR_FLOAT, "sky cloud slab maximum world z");
|
||||||
|
static idCVar r_skyCloudScale("r_skyCloudScale", "0.00021", CVAR_RENDERER | CVAR_FLOAT, "sky cloud world noise scale");
|
||||||
|
static idCVar r_skyCloudCoverage("r_skyCloudCoverage", "0.30", CVAR_RENDERER | CVAR_FLOAT, "sky cloud coverage threshold, lower is denser");
|
||||||
|
static idCVar r_skyCloudDensity("r_skyCloudDensity", "0.5", CVAR_RENDERER | CVAR_FLOAT, "sky cloud density accumulation");
|
||||||
|
static idCVar r_skyCloudOpacity("r_skyCloudOpacity", "0.78", CVAR_RENDERER | CVAR_FLOAT, "sky cloud final opacity");
|
||||||
|
static idCVar r_skyCloudSeedOffset("r_skyCloudSeedOffset", "12000", CVAR_RENDERER | CVAR_FLOAT, "sky cloud world noise seed offset");
|
||||||
|
static idCVar r_skyCloudColor("r_skyCloudColor", "0.85 0.62 0.48", CVAR_RENDERER, "sky cloud color override as 'r g b' in 0..1 or 0..255; auto samples the skydome");
|
||||||
|
|
||||||
static void R_UploadSkyDomeMeshToVertexCache(srfTriangles_t* tri) {
|
static void R_UploadSkyDomeMeshToVertexCache(srfTriangles_t* tri) {
|
||||||
if (!tri) {
|
if (!tri) {
|
||||||
return;
|
return;
|
||||||
@@ -131,6 +141,97 @@ static srfTriangles_t* R_BuildSkyDomeMesh(int rings, int segs, float radius) {
|
|||||||
return tri;
|
return tri;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static idImage* R_GetSkyDomeImage() {
|
||||||
|
if (!g_skyDomeMat || g_skyDomeMat->GetNumStages() <= 0) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
const shaderStage_t* stage = g_skyDomeMat->GetStage(0);
|
||||||
|
|
||||||
|
if (!stage || !stage->texture.image) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return stage->texture.image;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void R_GetSkyAverageColor(float color[3]) {
|
||||||
|
color[0] = 0.16f;
|
||||||
|
color[1] = 0.28f;
|
||||||
|
color[2] = 0.48f;
|
||||||
|
|
||||||
|
idImage* skyImage = R_GetSkyDomeImage();
|
||||||
|
|
||||||
|
if (!skyImage) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
skyImage->Bind();
|
||||||
|
|
||||||
|
const float* average = skyImage->GetAverageColor();
|
||||||
|
|
||||||
|
if (!average) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
color[0] = idMath::ClampFloat(0.03f, 1.0f, average[0]);
|
||||||
|
color[1] = idMath::ClampFloat(0.03f, 1.0f, average[1]);
|
||||||
|
color[2] = idMath::ClampFloat(0.03f, 1.0f, average[2]);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void R_GetSkyCloudColor(float color[3]) {
|
||||||
|
R_GetSkyAverageColor(color);
|
||||||
|
|
||||||
|
float overrideColor[3];
|
||||||
|
if (sscanf(r_skyCloudColor.GetString(), "%f %f %f", &overrideColor[0], &overrideColor[1], &overrideColor[2]) != 3) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const bool byteColor = overrideColor[0] > 1.0f || overrideColor[1] > 1.0f || overrideColor[2] > 1.0f;
|
||||||
|
const float scale = byteColor ? (1.0f / 255.0f) : 1.0f;
|
||||||
|
color[0] = idMath::ClampFloat(0.0f, 1.0f, overrideColor[0] * scale);
|
||||||
|
color[1] = idMath::ClampFloat(0.0f, 1.0f, overrideColor[1] * scale);
|
||||||
|
color[2] = idMath::ClampFloat(0.0f, 1.0f, overrideColor[2] * scale);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void RB_DrawSkyCloudOverlay(const viewDef_t* viewDef) {
|
||||||
|
if (!viewDef || !r_skyClouds.GetBool()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
glSkyClouds_t clouds;
|
||||||
|
memset(&clouds, 0, sizeof(clouds));
|
||||||
|
|
||||||
|
R_GetSkyCloudColor(clouds.skyColor);
|
||||||
|
clouds.opacity = idMath::ClampFloat(0.0f, 1.0f, r_skyCloudOpacity.GetFloat());
|
||||||
|
|
||||||
|
const idVec3& viewOrg = viewDef->renderView.vieworg;
|
||||||
|
clouds.viewOrigin[0] = viewOrg.x;
|
||||||
|
clouds.viewOrigin[1] = viewOrg.y;
|
||||||
|
clouds.viewOrigin[2] = viewOrg.z;
|
||||||
|
clouds.zMin = r_skyCloudZMin.GetFloat();
|
||||||
|
clouds.zMax = Max(r_skyCloudZMax.GetFloat(), clouds.zMin + 64.0f);
|
||||||
|
|
||||||
|
const idMat3& axis = viewDef->renderView.viewaxis;
|
||||||
|
clouds.viewForward[0] = axis[0].x;
|
||||||
|
clouds.viewForward[1] = axis[0].y;
|
||||||
|
clouds.viewForward[2] = axis[0].z;
|
||||||
|
clouds.viewRight[0] = -axis[1].x;
|
||||||
|
clouds.viewRight[1] = -axis[1].y;
|
||||||
|
clouds.viewRight[2] = -axis[1].z;
|
||||||
|
clouds.viewUp[0] = axis[2].x;
|
||||||
|
clouds.viewUp[1] = axis[2].y;
|
||||||
|
clouds.viewUp[2] = axis[2].z;
|
||||||
|
clouds.tanHalfFovX = idMath::Tan(DEG2RAD(viewDef->renderView.fov_x * 0.5f));
|
||||||
|
clouds.tanHalfFovY = idMath::Tan(DEG2RAD(viewDef->renderView.fov_y * 0.5f));
|
||||||
|
clouds.noiseScale = Max(r_skyCloudScale.GetFloat(), 0.00001f);
|
||||||
|
clouds.coverage = idMath::ClampFloat(0.0f, 1.0f, r_skyCloudCoverage.GetFloat());
|
||||||
|
clouds.density = Max(r_skyCloudDensity.GetFloat(), 0.0f);
|
||||||
|
clouds.seedOffset = r_skyCloudSeedOffset.GetFloat();
|
||||||
|
|
||||||
|
glDrawSkyCloudsQD3D12(&clouds);
|
||||||
|
}
|
||||||
|
|
||||||
void R_InitSkyDome() {
|
void R_InitSkyDome() {
|
||||||
if (g_skyDomeTri) {
|
if (g_skyDomeTri) {
|
||||||
return;
|
return;
|
||||||
@@ -198,10 +299,10 @@ void RB_DrawSkyDome(const viewDef_t* viewDef) {
|
|||||||
|
|
||||||
GL_SelectTexture(0);
|
GL_SelectTexture(0);
|
||||||
|
|
||||||
const shaderStage_t* stage = g_skyDomeMat->GetStage(0);
|
idImage* skyImage = R_GetSkyDomeImage();
|
||||||
|
|
||||||
if (stage && stage->texture.image) {
|
if (skyImage) {
|
||||||
stage->texture.image->Bind();
|
skyImage->Bind();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
globalImages->whiteImage->Bind();
|
globalImages->whiteImage->Bind();
|
||||||
@@ -228,12 +329,14 @@ void RB_DrawSkyDome(const viewDef_t* viewDef) {
|
|||||||
|
|
||||||
glGeometryFlagf(GEOMETRY_FLAG_UNLIT);
|
glGeometryFlagf(GEOMETRY_FLAG_UNLIT);
|
||||||
RB_DrawElementsWithCounters(g_skyDomeTri);
|
RB_DrawElementsWithCounters(g_skyDomeTri);
|
||||||
|
RB_DrawSkyCloudOverlay(viewDef);
|
||||||
glGeometryFlagf(GEOMETRY_FLAG_NONE);
|
glGeometryFlagf(GEOMETRY_FLAG_NONE);
|
||||||
|
|
||||||
glPopMatrix();
|
glPopMatrix();
|
||||||
|
|
||||||
|
GL_State(GLS_DEFAULT);
|
||||||
glDepthMask(GL_TRUE);
|
glDepthMask(GL_TRUE);
|
||||||
glEnable(GL_CULL_FACE);
|
glEnable(GL_CULL_FACE);
|
||||||
|
|
||||||
glClear(GL_DEPTH_BUFFER_BIT);
|
glClear(GL_DEPTH_BUFFER_BIT);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -593,6 +593,8 @@ BEGIN
|
|||||||
POPUP "&Misc"
|
POPUP "&Misc"
|
||||||
BEGIN
|
BEGIN
|
||||||
MENUITEM "&Benchmark", ID_MISC_BENCHMARK
|
MENUITEM "&Benchmark", ID_MISC_BENCHMARK
|
||||||
|
MENUITEM "Automatic City Builder", ID_TOOLS_AUTOMATICCITYBUILDER
|
||||||
|
MENUITEM SEPARATOR
|
||||||
POPUP "&Colors"
|
POPUP "&Colors"
|
||||||
BEGIN
|
BEGIN
|
||||||
POPUP "Themes"
|
POPUP "Themes"
|
||||||
|
|||||||
@@ -872,6 +872,7 @@ If you have questions concerning this license or the applicable additional terms
|
|||||||
#define ID_SELECTION_VIEW_WIREFRAMEOFF 30403
|
#define ID_SELECTION_VIEW_WIREFRAMEOFF 30403
|
||||||
#define ID_SELECTION_VIEW_VISIBLEON 30404
|
#define ID_SELECTION_VIEW_VISIBLEON 30404
|
||||||
#define ID_SELECTION_VIEW_VISIBLEOFF 30405
|
#define ID_SELECTION_VIEW_VISIBLEOFF 30405
|
||||||
|
#define ID_TOOLS_AUTOMATICCITYBUILDER 30406
|
||||||
#define ID_ENTITY_START 40000
|
#define ID_ENTITY_START 40000
|
||||||
#define ID_ENTITY_END 45000
|
#define ID_ENTITY_END 45000
|
||||||
|
|
||||||
@@ -881,7 +882,7 @@ If you have questions concerning this license or the applicable additional terms
|
|||||||
#ifndef APSTUDIO_READONLY_SYMBOLS
|
#ifndef APSTUDIO_READONLY_SYMBOLS
|
||||||
#define _APS_3D_CONTROLS 1
|
#define _APS_3D_CONTROLS 1
|
||||||
#define _APS_NEXT_RESOURCE_VALUE 10083
|
#define _APS_NEXT_RESOURCE_VALUE 10083
|
||||||
#define _APS_NEXT_COMMAND_VALUE 30406
|
#define _APS_NEXT_COMMAND_VALUE 30407
|
||||||
#define _APS_NEXT_CONTROL_VALUE 10555
|
#define _APS_NEXT_CONTROL_VALUE 10555
|
||||||
#define _APS_NEXT_SYMED_VALUE 10083
|
#define _APS_NEXT_SYMED_VALUE 10083
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -848,7 +848,7 @@ static void WriteOutputEntity( int entityNum ) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ( entityNum == 0 ) {
|
if ( entityNum == 0 ) {
|
||||||
WritePathTraceAreas( e );
|
// WritePathTraceAreas( e );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,568 @@
|
|||||||
|
/*
|
||||||
|
===========================================================================
|
||||||
|
|
||||||
|
IceTech GPL Source Code
|
||||||
|
Copyright (C) 2026 Justin Marshall
|
||||||
|
|
||||||
|
This file is part of the IceTech GPL Source Code.
|
||||||
|
|
||||||
|
===========================================================================
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "precompiled.h"
|
||||||
|
#pragma hdrstop
|
||||||
|
|
||||||
|
#include "qe3.h"
|
||||||
|
#include "CityBuilder.h"
|
||||||
|
|
||||||
|
extern int mapModified;
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
struct cityStats_t {
|
||||||
|
int brushes;
|
||||||
|
int entities;
|
||||||
|
int buildings;
|
||||||
|
int streets;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct cityBounds_t {
|
||||||
|
idVec3 mins;
|
||||||
|
idVec3 maxs;
|
||||||
|
};
|
||||||
|
|
||||||
|
static const float CITY_DEFAULT_HALF_SIZE = 4096.0f;
|
||||||
|
static const float CITY_MIN_SIZE = 3072.0f;
|
||||||
|
static const float CITY_MAX_SIZE = 65536.0f;
|
||||||
|
static const float CITY_ROAD_PITCH = 1152.0f;
|
||||||
|
static const float CITY_ROAD_WIDTH = 256.0f;
|
||||||
|
static const float CITY_SIDEWALK_WIDTH = 80.0f;
|
||||||
|
static const float CITY_CURB_WIDTH = 12.0f;
|
||||||
|
static const float CITY_CEILING_HEIGHT = 1536.0f;
|
||||||
|
static const float CITY_TEXTURE_SIZE = 1024.0f;
|
||||||
|
static const float CITY_ROAD_TEXTURE_LENGTH = 512.0f;
|
||||||
|
static const float CITY_SIDEWALK_TEXTURE_LENGTH = 256.0f;
|
||||||
|
static const float CITY_BUILDING_TEXTURE_WIDTH = 256.0f;
|
||||||
|
static const float CITY_BUILDING_TEXTURE_HEIGHT = 384.0f;
|
||||||
|
static const float CITY_BUILDING_EDGE_SETBACK = 96.0f;
|
||||||
|
static const float CITY_BUILDING_LOT_SIZE = 640.0f;
|
||||||
|
static const float CITY_BUILDING_ALLEY = 56.0f;
|
||||||
|
static const float CITY_POINT_LIGHT_RADIUS = 300000.0f;
|
||||||
|
|
||||||
|
static const char* CITY_MAT_MARS_DIRT = "textures/mars_citybuilder/mars_dirt";
|
||||||
|
static const char* CITY_MAT_MARS_ROAD = "textures/mars_citybuilder/mars_road_dusty_center";
|
||||||
|
static const char* CITY_MAT_MARS_ROAD_EAST_WEST = "textures/mars_citybuilder/mars_road_dusty_center_east_west";
|
||||||
|
static const char* CITY_MAT_MARS_ROAD_INTERSECTION = "textures/mars_citybuilder/mars_road_dusty_intersection";
|
||||||
|
static const char* CITY_MAT_MARS_SIDEWALK = "textures/mars_citybuilder/mars_sidewalk_dusty";
|
||||||
|
static const char* CITY_MAT_MARS_BUILDING_01 = "textures/mars_citybuilder/mars_building_dark_01";
|
||||||
|
static const char* CITY_MAT_MARS_BUILDING_02 = "textures/mars_citybuilder/mars_building_dark_02";
|
||||||
|
static const idVec3 CITY_POINT_LIGHT_ORIGIN(-3200.0f, 3336.0f, 0.0f);
|
||||||
|
static const idVec3 CITY_POINT_LIGHT_COLOR(242.0f / 255.0f, 160.0f / 255.0f, 130.0f / 255.0f);
|
||||||
|
|
||||||
|
static float City_ClampFloat(float v, float minValue, float maxValue) {
|
||||||
|
if (v < minValue) {
|
||||||
|
return minValue;
|
||||||
|
}
|
||||||
|
if (v > maxValue) {
|
||||||
|
return maxValue;
|
||||||
|
}
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int City_ClampInt(int v, int minValue, int maxValue) {
|
||||||
|
if (v < minValue) {
|
||||||
|
return minValue;
|
||||||
|
}
|
||||||
|
if (v > maxValue) {
|
||||||
|
return maxValue;
|
||||||
|
}
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
static unsigned int City_Hash(int x, int y, int salt) {
|
||||||
|
unsigned int h = (unsigned int)(x * 73856093) ^ (unsigned int)(y * 19349663) ^ (unsigned int)(salt * 83492791);
|
||||||
|
h ^= h >> 13;
|
||||||
|
h *= 1274126177u;
|
||||||
|
h ^= h >> 16;
|
||||||
|
return h;
|
||||||
|
}
|
||||||
|
|
||||||
|
static float City_Random01(int x, int y, int salt) {
|
||||||
|
return (City_Hash(x, y, salt) & 0xffff) / 65535.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
static float City_TexScale(float worldUnits) {
|
||||||
|
return worldUnits / CITY_TEXTURE_SIZE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static float City_TexShift(float worldCoord, float scale) {
|
||||||
|
if (scale == 0.0f) {
|
||||||
|
return 0.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
float shift = fmod(-worldCoord / scale, CITY_TEXTURE_SIZE);
|
||||||
|
if (shift < 0.0f) {
|
||||||
|
shift += CITY_TEXTURE_SIZE;
|
||||||
|
}
|
||||||
|
return shift;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void City_SetTexdef(texdef_t& td, const char* material, float scale0 = 0.5f, float scale1 = 0.5f, float rotate = 0.0f, float shift0 = 0.0f, float shift1 = 0.0f) {
|
||||||
|
td.SetName(material);
|
||||||
|
td.shift[0] = shift0;
|
||||||
|
td.shift[1] = shift1;
|
||||||
|
td.rotate = rotate;
|
||||||
|
td.scale[0] = scale0;
|
||||||
|
td.scale[1] = scale1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static idEditorBrush* City_AddWorldBrushUV(const idVec3& mins, const idVec3& maxs, const char* material, float scale0, float scale1, float rotate, float shift0, float shift1, cityStats_t& stats) {
|
||||||
|
if (mins.x >= maxs.x || mins.y >= maxs.y || mins.z >= maxs.z || world_entity == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
texdef_t td;
|
||||||
|
City_SetTexdef(td, material, scale0, scale1, rotate, shift0, shift1);
|
||||||
|
|
||||||
|
idEditorBrush* b = Brush_Create(mins, maxs, &td);
|
||||||
|
if (b == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
b->Brush_AddToList(&active_brushes);
|
||||||
|
world_entity->Entity_LinkBrush(b);
|
||||||
|
b->Brush_Build();
|
||||||
|
Undo_EndBrush(b);
|
||||||
|
stats.brushes++;
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
|
||||||
|
static idEditorBrush* City_AddWorldBrush(const idVec3& mins, const idVec3& maxs, const char* material, cityStats_t& stats) {
|
||||||
|
return City_AddWorldBrushUV(mins, maxs, material, 0.5f, 0.5f, 0.0f, 0.0f, 0.0f, stats);
|
||||||
|
}
|
||||||
|
|
||||||
|
static idEditorBrush* City_AddVerticalRoadBrush(float x, float y0, float y1, const cityBounds_t& bounds, cityStats_t& stats) {
|
||||||
|
const float roadHalf = CITY_ROAD_WIDTH * 0.5f;
|
||||||
|
const float scale0 = City_TexScale(CITY_ROAD_WIDTH);
|
||||||
|
const float scale1 = City_TexScale(CITY_ROAD_TEXTURE_LENGTH);
|
||||||
|
const idVec3 mins(x - roadHalf, y0, bounds.mins.z);
|
||||||
|
const idVec3 maxs(x + roadHalf, y1, bounds.mins.z + 8.0f);
|
||||||
|
return City_AddWorldBrushUV(mins, maxs, CITY_MAT_MARS_ROAD_EAST_WEST, scale0, scale1, 0.0f, City_TexShift(mins.x, scale0), City_TexShift(mins.y, scale1), stats);
|
||||||
|
}
|
||||||
|
|
||||||
|
static idEditorBrush* City_AddHorizontalRoadBrush(float x0, float x1, float y, const cityBounds_t& bounds, cityStats_t& stats) {
|
||||||
|
const float roadHalf = CITY_ROAD_WIDTH * 0.5f;
|
||||||
|
const float scale0 = City_TexScale(CITY_ROAD_TEXTURE_LENGTH);
|
||||||
|
const float scale1 = City_TexScale(CITY_ROAD_WIDTH);
|
||||||
|
const idVec3 mins(x0, y - roadHalf, bounds.mins.z);
|
||||||
|
const idVec3 maxs(x1, y + roadHalf, bounds.mins.z + 8.0f);
|
||||||
|
return City_AddWorldBrushUV(mins, maxs, CITY_MAT_MARS_ROAD, scale0, scale1, 0.0f, City_TexShift(mins.x, scale0), City_TexShift(mins.y, scale1), stats);
|
||||||
|
}
|
||||||
|
|
||||||
|
static idEditorBrush* City_AddIntersectionRoadBrush(float x, float y, const cityBounds_t& bounds, cityStats_t& stats) {
|
||||||
|
const float roadHalf = CITY_ROAD_WIDTH * 0.5f;
|
||||||
|
const float scale = City_TexScale(CITY_ROAD_WIDTH);
|
||||||
|
const idVec3 mins(x - roadHalf, y - roadHalf, bounds.mins.z);
|
||||||
|
const idVec3 maxs(x + roadHalf, y + roadHalf, bounds.mins.z + 8.0f);
|
||||||
|
return City_AddWorldBrushUV(mins, maxs, CITY_MAT_MARS_ROAD_INTERSECTION, scale, scale, 0.0f, City_TexShift(mins.x, scale), City_TexShift(mins.y, scale), stats);
|
||||||
|
}
|
||||||
|
|
||||||
|
static idEditorBrush* City_AddVerticalSidewalkBrush(float x0, float x1, float y0, float y1, const cityBounds_t& bounds, cityStats_t& stats) {
|
||||||
|
const float scale0 = City_TexScale(CITY_SIDEWALK_WIDTH);
|
||||||
|
const float scale1 = City_TexScale(CITY_SIDEWALK_TEXTURE_LENGTH);
|
||||||
|
const idVec3 mins(x0, y0, bounds.mins.z);
|
||||||
|
const idVec3 maxs(x1, y1, bounds.mins.z + 8.0f);
|
||||||
|
return City_AddWorldBrushUV(mins, maxs, CITY_MAT_MARS_SIDEWALK, scale0, scale1, 0.0f, City_TexShift(mins.x, scale0), City_TexShift(mins.y, scale1), stats);
|
||||||
|
}
|
||||||
|
|
||||||
|
static idEditorBrush* City_AddHorizontalSidewalkBrush(float x0, float x1, float y0, float y1, const cityBounds_t& bounds, cityStats_t& stats) {
|
||||||
|
const float scale0 = City_TexScale(CITY_SIDEWALK_TEXTURE_LENGTH);
|
||||||
|
const float scale1 = City_TexScale(CITY_SIDEWALK_WIDTH);
|
||||||
|
const idVec3 mins(x0, y0, bounds.mins.z);
|
||||||
|
const idVec3 maxs(x1, y1, bounds.mins.z + 8.0f);
|
||||||
|
return City_AddWorldBrushUV(mins, maxs, CITY_MAT_MARS_SIDEWALK, scale0, scale1, 0.0f, City_TexShift(mins.x, scale0), City_TexShift(mins.y, scale1), stats);
|
||||||
|
}
|
||||||
|
|
||||||
|
static idEditorBrush* City_AddBuildingBrush(const idVec3& mins, const idVec3& maxs, const char* material, cityStats_t& stats) {
|
||||||
|
const float scale0 = City_TexScale(CITY_BUILDING_TEXTURE_WIDTH);
|
||||||
|
const float scale1 = City_TexScale(CITY_BUILDING_TEXTURE_HEIGHT);
|
||||||
|
return City_AddWorldBrushUV(mins, maxs, material, scale0, scale1, 0.0f, 0.0f, City_TexShift(mins.z, scale1), stats);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void City_SetVecKey(idEditorEntity* ent, const char* key, const idVec3& value) {
|
||||||
|
ent->SetKeyValue(key, va("%i %i %i", (int)value.x, (int)value.y, (int)value.z));
|
||||||
|
}
|
||||||
|
|
||||||
|
static idEditorEntity* City_AddFixedEntity(const char* classname, const idVec3& origin, cityStats_t& stats) {
|
||||||
|
idEditorEntity* ent = idEditorEntity::Entity_New();
|
||||||
|
if (ent == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
ent->brushes.onext = ent->brushes.oprev = &ent->brushes;
|
||||||
|
ent->origin = origin;
|
||||||
|
ent->SetKeyValue("classname", classname);
|
||||||
|
City_SetVecKey(ent, "origin", origin);
|
||||||
|
ent->Entity_Name(false);
|
||||||
|
ent->Entity_PostParse(&active_brushes);
|
||||||
|
ent->Entity_AddToList(&entities);
|
||||||
|
g_qeglobals.d_num_entities++;
|
||||||
|
|
||||||
|
Undo_EndEntity(ent);
|
||||||
|
for (idEditorBrush* b = ent->brushes.onext; b != &ent->brushes; b = b->onext) {
|
||||||
|
b->Brush_Build();
|
||||||
|
Undo_EndBrush(b);
|
||||||
|
stats.brushes++;
|
||||||
|
}
|
||||||
|
|
||||||
|
stats.entities++;
|
||||||
|
return ent;
|
||||||
|
}
|
||||||
|
|
||||||
|
static cityBounds_t City_GetTargetBounds() {
|
||||||
|
cityBounds_t bounds;
|
||||||
|
bounds.mins.Set(-CITY_DEFAULT_HALF_SIZE, -CITY_DEFAULT_HALF_SIZE, 0.0f);
|
||||||
|
bounds.maxs.Set(CITY_DEFAULT_HALF_SIZE, CITY_DEFAULT_HALF_SIZE, CITY_CEILING_HEIGHT);
|
||||||
|
|
||||||
|
if (selected_brushes.next != NULL && selected_brushes.next != &selected_brushes) {
|
||||||
|
idVec3 mins(999999.0f, 999999.0f, 999999.0f);
|
||||||
|
idVec3 maxs(-999999.0f, -999999.0f, -999999.0f);
|
||||||
|
for (idEditorBrush* b = selected_brushes.next; b != &selected_brushes; b = b->next) {
|
||||||
|
for (int i = 0; i < 3; i++) {
|
||||||
|
if (b->mins[i] < mins[i]) {
|
||||||
|
mins[i] = b->mins[i];
|
||||||
|
}
|
||||||
|
if (b->maxs[i] > maxs[i]) {
|
||||||
|
maxs[i] = b->maxs[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((maxs.x - mins.x) >= 128.0f && (maxs.y - mins.y) >= 128.0f) {
|
||||||
|
bounds.mins.x = mins.x;
|
||||||
|
bounds.mins.y = mins.y;
|
||||||
|
bounds.mins.z = mins.z;
|
||||||
|
bounds.maxs.x = maxs.x;
|
||||||
|
bounds.maxs.y = maxs.y;
|
||||||
|
bounds.maxs.z = mins.z + CITY_CEILING_HEIGHT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const float centerX = (bounds.mins.x + bounds.maxs.x) * 0.5f;
|
||||||
|
const float centerY = (bounds.mins.y + bounds.maxs.y) * 0.5f;
|
||||||
|
float width = City_ClampFloat(bounds.maxs.x - bounds.mins.x, CITY_MIN_SIZE, CITY_MAX_SIZE);
|
||||||
|
float depth = City_ClampFloat(bounds.maxs.y - bounds.mins.y, CITY_MIN_SIZE, CITY_MAX_SIZE);
|
||||||
|
width = floor(width / 64.0f) * 64.0f;
|
||||||
|
depth = floor(depth / 64.0f) * 64.0f;
|
||||||
|
|
||||||
|
bounds.mins.x = centerX - width * 0.5f;
|
||||||
|
bounds.maxs.x = centerX + width * 0.5f;
|
||||||
|
bounds.mins.y = centerY - depth * 0.5f;
|
||||||
|
bounds.maxs.y = centerY + depth * 0.5f;
|
||||||
|
bounds.maxs.z = bounds.mins.z + CITY_CEILING_HEIGHT;
|
||||||
|
return bounds;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void City_AddVerticalStreetEdges(float x, float y0, float y1, const cityBounds_t& bounds, cityStats_t& stats) {
|
||||||
|
if (y1 <= y0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const float z0 = bounds.mins.z;
|
||||||
|
const float roadHalf = CITY_ROAD_WIDTH * 0.5f;
|
||||||
|
const float sideHalf = roadHalf + CITY_SIDEWALK_WIDTH;
|
||||||
|
|
||||||
|
City_AddVerticalSidewalkBrush(x - sideHalf, x - roadHalf, y0, y1, bounds, stats);
|
||||||
|
City_AddVerticalSidewalkBrush(x + roadHalf, x + sideHalf, y0, y1, bounds, stats);
|
||||||
|
City_AddWorldBrush(
|
||||||
|
idVec3(x - roadHalf - CITY_CURB_WIDTH, y0, z0 + 8.0f),
|
||||||
|
idVec3(x - roadHalf, y1, z0 + 14.0f),
|
||||||
|
"textures/base_wall/steel",
|
||||||
|
stats);
|
||||||
|
City_AddWorldBrush(
|
||||||
|
idVec3(x + roadHalf, y0, z0 + 8.0f),
|
||||||
|
idVec3(x + roadHalf + CITY_CURB_WIDTH, y1, z0 + 14.0f),
|
||||||
|
"textures/base_wall/steel",
|
||||||
|
stats);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void City_AddHorizontalStreetEdges(float y, float x0, float x1, const cityBounds_t& bounds, cityStats_t& stats) {
|
||||||
|
if (x1 <= x0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const float z0 = bounds.mins.z;
|
||||||
|
const float roadHalf = CITY_ROAD_WIDTH * 0.5f;
|
||||||
|
const float sideHalf = roadHalf + CITY_SIDEWALK_WIDTH;
|
||||||
|
|
||||||
|
City_AddHorizontalSidewalkBrush(x0, x1, y - sideHalf, y - roadHalf, bounds, stats);
|
||||||
|
City_AddHorizontalSidewalkBrush(x0, x1, y + roadHalf, y + sideHalf, bounds, stats);
|
||||||
|
City_AddWorldBrush(
|
||||||
|
idVec3(x0, y - roadHalf - CITY_CURB_WIDTH, z0 + 8.0f),
|
||||||
|
idVec3(x1, y - roadHalf, z0 + 14.0f),
|
||||||
|
"textures/base_wall/steel",
|
||||||
|
stats);
|
||||||
|
City_AddWorldBrush(
|
||||||
|
idVec3(x0, y + roadHalf, z0 + 8.0f),
|
||||||
|
idVec3(x1, y + roadHalf + CITY_CURB_WIDTH, z0 + 14.0f),
|
||||||
|
"textures/base_wall/steel",
|
||||||
|
stats);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void City_AddVerticalStreetEdges(float x, const cityBounds_t& bounds, const idList<float>& blockers, cityStats_t& stats) {
|
||||||
|
const float clearHalf = CITY_ROAD_WIDTH * 0.5f + CITY_SIDEWALK_WIDTH;
|
||||||
|
float y0 = bounds.mins.y;
|
||||||
|
|
||||||
|
for (int i = 0; i < blockers.Num(); i++) {
|
||||||
|
const float y1 = blockers[i] - clearHalf;
|
||||||
|
City_AddVerticalStreetEdges(x, y0, y1, bounds, stats);
|
||||||
|
y0 = blockers[i] + clearHalf;
|
||||||
|
}
|
||||||
|
|
||||||
|
City_AddVerticalStreetEdges(x, y0, bounds.maxs.y, bounds, stats);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void City_AddHorizontalStreetEdges(float y, const cityBounds_t& bounds, const idList<float>& blockers, cityStats_t& stats) {
|
||||||
|
const float clearHalf = CITY_ROAD_WIDTH * 0.5f + CITY_SIDEWALK_WIDTH;
|
||||||
|
float x0 = bounds.mins.x;
|
||||||
|
|
||||||
|
for (int i = 0; i < blockers.Num(); i++) {
|
||||||
|
const float x1 = blockers[i] - clearHalf;
|
||||||
|
City_AddHorizontalStreetEdges(y, x0, x1, bounds, stats);
|
||||||
|
x0 = blockers[i] + clearHalf;
|
||||||
|
}
|
||||||
|
|
||||||
|
City_AddHorizontalStreetEdges(y, x0, bounds.maxs.x, bounds, stats);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void City_AddStreetSign(float x, float y, int avenue, int street, const cityBounds_t& bounds, cityStats_t& stats) {
|
||||||
|
const float z0 = bounds.mins.z;
|
||||||
|
const float poleX = x + CITY_ROAD_WIDTH * 0.5f + 44.0f;
|
||||||
|
const float poleY = y - CITY_ROAD_WIDTH * 0.5f - 44.0f;
|
||||||
|
|
||||||
|
City_AddWorldBrush(idVec3(poleX - 4.0f, poleY - 4.0f, z0 + 8.0f), idVec3(poleX + 4.0f, poleY + 4.0f, z0 + 128.0f), "textures/base_wall/steel", stats);
|
||||||
|
City_AddWorldBrush(idVec3(poleX - 56.0f, poleY - 5.0f, z0 + 112.0f), idVec3(poleX + 56.0f, poleY + 5.0f, z0 + 136.0f), "textures/base_wall/greenpanel1", stats);
|
||||||
|
City_AddWorldBrush(idVec3(poleX - 5.0f, poleY - 56.0f, z0 + 140.0f), idVec3(poleX + 5.0f, poleY + 56.0f, z0 + 164.0f), "textures/base_wall/greenpanel1", stats);
|
||||||
|
common->Printf("Automatic City Builder: street node A%i / S%i at %.0f %.0f\n", avenue + 1, street + 1, x, y);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void City_AddRoads(const cityBounds_t& bounds, idList<float>& roadX, idList<float>& roadY, cityStats_t& stats) {
|
||||||
|
const float roadHalf = CITY_ROAD_WIDTH * 0.5f;
|
||||||
|
const int xRoads = City_ClampInt((int)((bounds.maxs.x - bounds.mins.x) / CITY_ROAD_PITCH), 2, 64);
|
||||||
|
const int yRoads = City_ClampInt((int)((bounds.maxs.y - bounds.mins.y) / CITY_ROAD_PITCH), 2, 64);
|
||||||
|
const float xStep = (bounds.maxs.x - bounds.mins.x) / (float)xRoads;
|
||||||
|
const float yStep = (bounds.maxs.y - bounds.mins.y) / (float)yRoads;
|
||||||
|
|
||||||
|
for (int i = 1; i < xRoads; i++) {
|
||||||
|
roadX.Append(bounds.mins.x + xStep * i);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 1; i < yRoads; i++) {
|
||||||
|
roadY.Append(bounds.mins.y + yStep * i);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < roadX.Num(); i++) {
|
||||||
|
const float x = roadX[i];
|
||||||
|
for (int segment = 0; segment <= roadY.Num(); segment++) {
|
||||||
|
const float y0 = (segment == 0) ? bounds.mins.y : roadY[segment - 1] + roadHalf;
|
||||||
|
const float y1 = (segment == roadY.Num()) ? bounds.maxs.y : roadY[segment] - roadHalf;
|
||||||
|
City_AddVerticalRoadBrush(x, y0, y1, bounds, stats);
|
||||||
|
}
|
||||||
|
City_AddVerticalStreetEdges(x, bounds, roadY, stats);
|
||||||
|
stats.streets++;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < roadY.Num(); i++) {
|
||||||
|
const float y = roadY[i];
|
||||||
|
for (int segment = 0; segment <= roadX.Num(); segment++) {
|
||||||
|
const float x0 = (segment == 0) ? bounds.mins.x : roadX[segment - 1] + roadHalf;
|
||||||
|
const float x1 = (segment == roadX.Num()) ? bounds.maxs.x : roadX[segment] - roadHalf;
|
||||||
|
City_AddHorizontalRoadBrush(x0, x1, y, bounds, stats);
|
||||||
|
}
|
||||||
|
City_AddHorizontalStreetEdges(y, bounds, roadX, stats);
|
||||||
|
stats.streets++;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int x = 0; x < roadX.Num(); x++) {
|
||||||
|
for (int y = 0; y < roadY.Num(); y++) {
|
||||||
|
City_AddIntersectionRoadBrush(roadX[x], roadY[y], bounds, stats);
|
||||||
|
if (((x + y) & 1) == 0) {
|
||||||
|
City_AddStreetSign(roadX[x], roadY[y], x, y, bounds, stats);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void City_AddDirtLot(const cityBounds_t& bounds, float minX, float minY, float maxX, float maxY, cityStats_t& stats) {
|
||||||
|
if (maxX - minX <= 1.0f || maxY - minY <= 1.0f) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
City_AddWorldBrush(
|
||||||
|
idVec3(minX, minY, bounds.mins.z),
|
||||||
|
idVec3(maxX, maxY, bounds.mins.z + 8.0f),
|
||||||
|
CITY_MAT_MARS_DIRT,
|
||||||
|
stats);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void City_AddDirtLots(const cityBounds_t& bounds, const idList<float>& roadX, const idList<float>& roadY, cityStats_t& stats) {
|
||||||
|
const float clearHalf = CITY_ROAD_WIDTH * 0.5f + CITY_SIDEWALK_WIDTH;
|
||||||
|
float y0 = bounds.mins.y;
|
||||||
|
|
||||||
|
for (int y = 0; y <= roadY.Num(); y++) {
|
||||||
|
const float y1 = (y == roadY.Num()) ? bounds.maxs.y : roadY[y] - clearHalf;
|
||||||
|
float x0 = bounds.mins.x;
|
||||||
|
|
||||||
|
for (int x = 0; x <= roadX.Num(); x++) {
|
||||||
|
const float x1 = (x == roadX.Num()) ? bounds.maxs.x : roadX[x] - clearHalf;
|
||||||
|
City_AddDirtLot(bounds, x0, y0, x1, y1, stats);
|
||||||
|
|
||||||
|
if (x < roadX.Num()) {
|
||||||
|
x0 = roadX[x] + clearHalf;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (y < roadY.Num()) {
|
||||||
|
y0 = roadY[y] + clearHalf;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char* City_BuildingMaterial(int x, int y) {
|
||||||
|
static const char* materials[] = {
|
||||||
|
CITY_MAT_MARS_BUILDING_01,
|
||||||
|
CITY_MAT_MARS_BUILDING_02
|
||||||
|
};
|
||||||
|
return materials[City_Hash(x, y, 17) % (sizeof(materials) / sizeof(materials[0]))];
|
||||||
|
}
|
||||||
|
|
||||||
|
static void City_AddBuilding(float minX, float minY, float maxX, float maxY, float baseZ, int gx, int gy, cityStats_t& stats) {
|
||||||
|
const int floors = 2 + (City_Hash(gx, gy, 31) % 8);
|
||||||
|
const float z0 = baseZ + 8.0f;
|
||||||
|
const float z1 = z0 + 96.0f * floors + City_Random01(gx, gy, 23) * 64.0f;
|
||||||
|
idVec3 mins(minX, minY, z0);
|
||||||
|
idVec3 maxs(maxX, maxY, z1);
|
||||||
|
|
||||||
|
City_AddBuildingBrush(mins, maxs, City_BuildingMaterial(gx, gy), stats);
|
||||||
|
City_AddWorldBrush(idVec3(minX - 8.0f, minY - 8.0f, z1), idVec3(maxX + 8.0f, maxY + 8.0f, z1 + 16.0f), CITY_MAT_MARS_DIRT, stats);
|
||||||
|
stats.buildings++;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void City_AddBlockBuildings(const cityBounds_t& bounds, float minX, float minY, float maxX, float maxY, int blockX, int blockY, cityStats_t& stats) {
|
||||||
|
minX += CITY_BUILDING_EDGE_SETBACK;
|
||||||
|
minY += CITY_BUILDING_EDGE_SETBACK;
|
||||||
|
maxX -= CITY_BUILDING_EDGE_SETBACK;
|
||||||
|
maxY -= CITY_BUILDING_EDGE_SETBACK;
|
||||||
|
if (maxX - minX < 128.0f || maxY - minY < 128.0f) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const int lotsX = City_ClampInt((int)((maxX - minX) / CITY_BUILDING_LOT_SIZE), 1, 2);
|
||||||
|
const int lotsY = City_ClampInt((int)((maxY - minY) / CITY_BUILDING_LOT_SIZE), 1, 2);
|
||||||
|
const float stepX = (maxX - minX) / (float)lotsX;
|
||||||
|
const float stepY = (maxY - minY) / (float)lotsY;
|
||||||
|
|
||||||
|
for (int y = 0; y < lotsY; y++) {
|
||||||
|
for (int x = 0; x < lotsX; x++) {
|
||||||
|
if ((City_Hash(blockX * 17 + x, blockY * 19 + y, 7) % 100) < 22) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
float cellMinX = minX + x * stepX + CITY_BUILDING_ALLEY;
|
||||||
|
float cellMinY = minY + y * stepY + CITY_BUILDING_ALLEY;
|
||||||
|
float cellMaxX = minX + (x + 1) * stepX - CITY_BUILDING_ALLEY;
|
||||||
|
float cellMaxY = minY + (y + 1) * stepY - CITY_BUILDING_ALLEY;
|
||||||
|
if (cellMaxX - cellMinX < 96.0f || cellMaxY - cellMinY < 96.0f) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const float shrinkX = City_Random01(blockX * 31 + x, blockY * 37 + y, 11) * 24.0f;
|
||||||
|
const float shrinkY = City_Random01(blockX * 31 + x, blockY * 37 + y, 13) * 24.0f;
|
||||||
|
City_AddBuilding(
|
||||||
|
cellMinX + shrinkX,
|
||||||
|
cellMinY + shrinkY,
|
||||||
|
cellMaxX - shrinkX,
|
||||||
|
cellMaxY - shrinkY,
|
||||||
|
bounds.mins.z,
|
||||||
|
blockX * 10 + x,
|
||||||
|
blockY * 10 + y,
|
||||||
|
stats);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void City_AddBuildings(const cityBounds_t& bounds, const idList<float>& roadX, const idList<float>& roadY, cityStats_t& stats) {
|
||||||
|
const float clearHalf = CITY_ROAD_WIDTH * 0.5f + CITY_SIDEWALK_WIDTH;
|
||||||
|
float y0 = bounds.mins.y;
|
||||||
|
|
||||||
|
for (int y = 0; y <= roadY.Num(); y++) {
|
||||||
|
const float y1 = (y == roadY.Num()) ? bounds.maxs.y : roadY[y] - clearHalf;
|
||||||
|
float x0 = bounds.mins.x;
|
||||||
|
|
||||||
|
for (int x = 0; x <= roadX.Num(); x++) {
|
||||||
|
const float x1 = (x == roadX.Num()) ? bounds.maxs.x : roadX[x] - clearHalf;
|
||||||
|
City_AddBlockBuildings(bounds, x0, y0, x1, y1, x, y, stats);
|
||||||
|
|
||||||
|
if (x < roadX.Num()) {
|
||||||
|
x0 = roadX[x] + clearHalf;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (y < roadY.Num()) {
|
||||||
|
y0 = roadY[y] + clearHalf;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void City_AddPlayerStart(const cityBounds_t& bounds, cityStats_t& stats) {
|
||||||
|
City_AddFixedEntity("info_player_start", idVec3(bounds.mins.x + 192.0f, bounds.mins.y + 192.0f, bounds.mins.z + 48.0f), stats);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void City_AddPointLight(cityStats_t& stats) {
|
||||||
|
idEditorEntity* ent = City_AddFixedEntity("light", CITY_POINT_LIGHT_ORIGIN, stats);
|
||||||
|
if (ent == NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ent->SetKeyValue("_color", va("%.3f %.3f %.3f", CITY_POINT_LIGHT_COLOR.x, CITY_POINT_LIGHT_COLOR.y, CITY_POINT_LIGHT_COLOR.z));
|
||||||
|
ent->SetKeyValue("light_radius", va("%i %i %i", (int)CITY_POINT_LIGHT_RADIUS, (int)CITY_POINT_LIGHT_RADIUS, (int)CITY_POINT_LIGHT_RADIUS));
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
void Radiant_GenerateAutomaticCity() {
|
||||||
|
if (world_entity == NULL) {
|
||||||
|
Sys_Status("Automatic City Builder needs an open map\n");
|
||||||
|
Sys_Beep();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Sys_BeginWait();
|
||||||
|
Undo_Start("automatic city");
|
||||||
|
|
||||||
|
cityStats_t stats;
|
||||||
|
stats.brushes = 0;
|
||||||
|
stats.entities = 0;
|
||||||
|
stats.buildings = 0;
|
||||||
|
stats.streets = 0;
|
||||||
|
|
||||||
|
idList<float> roadX;
|
||||||
|
idList<float> roadY;
|
||||||
|
const cityBounds_t bounds = City_GetTargetBounds();
|
||||||
|
|
||||||
|
Select_Deselect();
|
||||||
|
City_AddRoads(bounds, roadX, roadY, stats);
|
||||||
|
City_AddDirtLots(bounds, roadX, roadY, stats);
|
||||||
|
City_AddBuildings(bounds, roadX, roadY, stats);
|
||||||
|
City_AddPlayerStart(bounds, stats);
|
||||||
|
City_AddPointLight(stats);
|
||||||
|
|
||||||
|
Map_BuildBrushData();
|
||||||
|
Sys_UpdateWindows(W_ALL);
|
||||||
|
mapModified = 1;
|
||||||
|
|
||||||
|
Undo_End();
|
||||||
|
Sys_EndWait();
|
||||||
|
common->Printf("Automatic City Builder: %i streets, %i buildings, %i brushes, %i entities\n", stats.streets, stats.buildings, stats.brushes, stats.entities);
|
||||||
|
Sys_Status(va("Automatic City Builder: %i streets, %i buildings generated", stats.streets, stats.buildings), 0);
|
||||||
|
}
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
/*
|
||||||
|
===========================================================================
|
||||||
|
|
||||||
|
IceTech GPL Source Code
|
||||||
|
Copyright (C) 2026 Justin Marshall
|
||||||
|
|
||||||
|
This file is part of the IceTech GPL Source Code.
|
||||||
|
|
||||||
|
===========================================================================
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __RADIANT_CITYBUILDER_H__
|
||||||
|
#define __RADIANT_CITYBUILDER_H__
|
||||||
|
|
||||||
|
void Radiant_GenerateAutomaticCity();
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -57,6 +57,7 @@ If you have questions concerning this license or the applicable additional terms
|
|||||||
#include "EntKeyFindReplace.h"
|
#include "EntKeyFindReplace.h"
|
||||||
#include "InspectorDialog.h"
|
#include "InspectorDialog.h"
|
||||||
#include "autocaulk.h"
|
#include "autocaulk.h"
|
||||||
|
#include "CityBuilder.h"
|
||||||
#include <commctrl.h>
|
#include <commctrl.h>
|
||||||
|
|
||||||
#include "../../sys/win32/rc/common_resource.h"
|
#include "../../sys/win32/rc/common_resource.h"
|
||||||
@@ -883,6 +884,7 @@ BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd)
|
|||||||
ON_COMMAND(ID_SELECT_COMPLETE_ENTITY, OnSelectCompleteEntity)
|
ON_COMMAND(ID_SELECT_COMPLETE_ENTITY, OnSelectCompleteEntity)
|
||||||
ON_COMMAND(ID_PRECISION_CURSOR_CYCLE, OnPrecisionCursorCycle)
|
ON_COMMAND(ID_PRECISION_CURSOR_CYCLE, OnPrecisionCursorCycle)
|
||||||
ON_COMMAND(ID_MATERIALS_GENERATEMATERIALSLIST, OnGenerateMaterialsList)
|
ON_COMMAND(ID_MATERIALS_GENERATEMATERIALSLIST, OnGenerateMaterialsList)
|
||||||
|
ON_COMMAND(ID_TOOLS_AUTOMATICCITYBUILDER, OnToolsAutomaticCityBuilder)
|
||||||
ON_COMMAND(ID_SELECTION_VIEW_WIREFRAMEON, OnSelectionWireFrameOn)
|
ON_COMMAND(ID_SELECTION_VIEW_WIREFRAMEON, OnSelectionWireFrameOn)
|
||||||
ON_COMMAND(ID_SELECTION_VIEW_WIREFRAMEOFF, OnSelectionWireFrameOff)
|
ON_COMMAND(ID_SELECTION_VIEW_WIREFRAMEOFF, OnSelectionWireFrameOff)
|
||||||
ON_COMMAND(ID_SELECTION_VIEW_VISIBLEON, OnSelectionVisibleOn)
|
ON_COMMAND(ID_SELECTION_VIEW_VISIBLEON, OnSelectionVisibleOn)
|
||||||
@@ -7980,6 +7982,10 @@ void CMainFrame::OnGenerateMaterialsList()
|
|||||||
Sys_EndWait();
|
Sys_EndWait();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CMainFrame::OnToolsAutomaticCityBuilder() {
|
||||||
|
Radiant_GenerateAutomaticCity();
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
=======================================================================================================================
|
=======================================================================================================================
|
||||||
=======================================================================================================================
|
=======================================================================================================================
|
||||||
|
|||||||
@@ -657,6 +657,7 @@ public:
|
|||||||
afx_msg void OnNurbEditor();
|
afx_msg void OnNurbEditor();
|
||||||
afx_msg void OnSelectCompleteEntity();
|
afx_msg void OnSelectCompleteEntity();
|
||||||
afx_msg void OnGenerateMaterialsList();
|
afx_msg void OnGenerateMaterialsList();
|
||||||
|
afx_msg void OnToolsAutomaticCityBuilder();
|
||||||
afx_msg void OnMru(unsigned int nID);
|
afx_msg void OnMru(unsigned int nID);
|
||||||
afx_msg void OnViewNearest(unsigned int nID);
|
afx_msg void OnViewNearest(unsigned int nID);
|
||||||
afx_msg void OnTextureWad(unsigned int nID);
|
afx_msg void OnTextureWad(unsigned int nID);
|
||||||
|
|||||||