Move sample distance, bounces and light probe grid size settings to the zdrayinfo actor as they affect map visuals

This commit is contained in:
Magnus Norddahl 2021-11-11 05:51:00 +01:00
parent cd3563759c
commit 031dc4a4db
8 changed files with 62 additions and 61 deletions

View file

@ -1,13 +1,29 @@
# ZDRay baking utility for GZDoom # ZDRay baking utility for GZDoom
ZDRay is a node and lightmap generator. It is based on zdbsp for the node generation and dlight for the lightmap generation. ZDRay is a node and lightmap generator for GZDoom. ZDRay is intended as a drop-in replacement for zdbsp, with the additional feature
that it can also bake lights. Once ZDRay has processed the level WAD it is ready to be used by GZDoom.
Special thanks to Randi Heit, Samuel Villarreal, Christoph Oelckers and anyone else involved in creating or maintaining those tools. ZDRay is based on zdbsp for the node generation and originally used dlight for the lightmap generation. Special thanks to Randi Heit,
Samuel Villarreal, Christoph Oelckers and anyone else involved in creating or maintaining those tools.
The ray tracing code has been completely rewritten since. It now supports bounces and can do the ray tracing on the GPU.
## ZDRay UDMF properties ## ZDRay UDMF properties
<pre> <pre>
thing // ZDRayInfo (zdray properties for the map)
{
type = 9890;
suncolor = &lt;int&gt; (color)
sundirx = &lt;float&gt; (X direction for the sun)
sundiry = &lt;float&gt; (Y direction for the sun)
sundirz = &lt;float&gt; (Z direction for the sun)
sampledistance = &lt;int&gt; (default: 8, map units each lightmap texel covers, must be in powers of two)
bounces = &lt;int&gt; (default: 1, how many times light bounces off walls)
gridsize = &lt;float&gt; (default: 32, grid density for the automatic light probes)
}
thing // StaticLight (point or spot light to be baked into the lightmap) thing // StaticLight (point or spot light to be baked into the lightmap)
{ {
lightcolor = &lt;int&gt; (color) lightcolor = &lt;int&gt; (color)
@ -22,23 +38,14 @@ thing // LightProbe (light sampling point for actors)
type = 9875; type = 9875;
} }
thing // Sunlight (sunlight properties for the map) linedef // Line emissive surface
{
type = 9890;
suncolor = &lt;int&gt; (color)
sundirx = &lt;float&gt; (X direction for the sun)
sundiry = &lt;float&gt; (Y direction for the sun)
sundirz = &lt;float&gt; (Z direction for the sun)
}
linedef // Line surface emitting
{ {
lightcolor = &lt;int&gt; (color, default: white) lightcolor = &lt;int&gt; (color, default: white)
lightintensity = &lt;float&gt; (default: 1) lightintensity = &lt;float&gt; (default: 1)
lightdistance = &lt;float&gt; (default: 0, no light) lightdistance = &lt;float&gt; (default: 0, no light)
} }
sector // Sector planes emitting light sector // Sector plane emissive surface
{ {
lightcolorfloor = &lt;int&gt; (color, default: white) lightcolorfloor = &lt;int&gt; (color, default: white)
lightintensityfloor = &lt;float&gt; (default: 1) lightintensityfloor = &lt;float&gt; (default: 1)

View file

@ -387,8 +387,11 @@ struct FLevel
TArray<SurfaceLightDef> SurfaceLights; TArray<SurfaceLightDef> SurfaceLights;
TArray<int> ThingLightProbes; TArray<int> ThingLightProbes;
Vec3 defaultSunColor = Vec3(1, 1, 1); Vec3 defaultSunColor;
Vec3 defaultSunDirection = Vec3(0.45f, 0.3f, 0.9f); Vec3 defaultSunDirection;
int Samples;
int LightBounce;
float GridSize;
void FindMapBounds (); void FindMapBounds ();
void RemoveExtraLines (); void RemoveExtraLines ();

View file

@ -30,7 +30,6 @@
#endif #endif
extern int LMDims; extern int LMDims;
extern int Samples;
extern bool CPURaytrace; extern bool CPURaytrace;
extern void ShowView (FLevel *level); extern void ShowView (FLevel *level);
@ -693,7 +692,7 @@ void FProcessor::BuildNodes()
void FProcessor::BuildLightmaps() void FProcessor::BuildLightmaps()
{ {
Level.SetupLights(); Level.SetupLights();
LightmapMesh = std::make_unique<LevelMesh>(Level, Samples, LMDims); LightmapMesh = std::make_unique<LevelMesh>(Level, Level.Samples, LMDims);
if (CPURaytrace) if (CPURaytrace)
{ {

View file

@ -84,6 +84,13 @@ void FLevel::SetupLights()
} }
} }
// GG to whoever memset'ed FLevel
defaultSunColor = Vec3(1, 1, 1);
defaultSunDirection = Vec3(0.45f, 0.3f, 0.9f);
Samples = 8;
LightBounce = 1;
GridSize = 32.0f;
for (int i = 0; i < (int)Things.Size(); ++i) for (int i = 0; i < (int)Things.Size(); ++i)
{ {
IntThing* thing = &Things[i]; IntThing* thing = &Things[i];
@ -91,7 +98,7 @@ void FLevel::SetupLights()
{ {
ThingLightProbes.Push(i); ThingLightProbes.Push(i);
} }
else if (thing->type == 9890) // Sunlight else if (thing->type == 9890) // ZDRayInfo
{ {
uint32_t lightcolor = 0xffffff; uint32_t lightcolor = 0xffffff;
Vec3 sundir(0.0f, 0.0f, 0.0f); Vec3 sundir(0.0f, 0.0f, 0.0f);
@ -116,6 +123,25 @@ void FLevel::SetupLights()
{ {
sundir.z = atof(key.value); sundir.z = atof(key.value);
} }
else if (!stricmp(key.key, "sampledistance"))
{
Samples = atoi(key.value);
if (Samples <= 0) Samples = 1;
if (Samples > 128) Samples = 128;
Samples = Math::RoundPowerOfTwo(Samples);
}
else if (!stricmp(key.key, "bounces"))
{
LightBounce = atoi(key.value);
if (LightBounce < 0) LightBounce = 0;
if (LightBounce > 8) LightBounce = 8;
}
else if (!stricmp(key.key, "gridsize"))
{
GridSize = atof(key.value);
if (GridSize < 0.f) GridSize = 0.f;
if (GridSize > 1024.f) GridSize = 1024.f;
}
} }
if (Vec3::Dot(sundir, sundir) > 0.01f) if (Vec3::Dot(sundir, sundir) > 0.01f)

View file

@ -12,7 +12,6 @@
#include <algorithm> #include <algorithm>
#include <zlib.h> #include <zlib.h>
extern int LightBounce;
extern bool VKDebug; extern bool VKDebug;
CPURaytracer::CPURaytracer() CPURaytracer::CPURaytracer()
@ -59,7 +58,7 @@ void CPURaytracer::Raytrace(LevelMesh* level)
CreateHemisphereVectors(); CreateHemisphereVectors();
CreateLights(); CreateLights();
printf("Ray tracing with %d bounce(s)\n", LightBounce); printf("Ray tracing with %d bounce(s)\n", mesh->map->LightBounce);
Worker::RunJob((int)tasks.size(), [=](int id) { RaytraceTask(tasks[id]); }); Worker::RunJob((int)tasks.size(), [=](int id) { RaytraceTask(tasks[id]); });
@ -107,7 +106,7 @@ void CPURaytracer::RaytraceTask(const CPUTraceTask& task)
state.HemisphereVec = HemisphereVectors[state.SampleIndex]; state.HemisphereVec = HemisphereVectors[state.SampleIndex];
RunBounceTrace(state); RunBounceTrace(state);
for (int bounce = 0; bounce < LightBounce && !state.EndTrace; bounce++) for (int bounce = 0; bounce < mesh->map->LightBounce && !state.EndTrace; bounce++)
{ {
state.SampleCount = coverageSampleCount; state.SampleCount = coverageSampleCount;
RunLightTrace(state); RunLightTrace(state);

View file

@ -21,7 +21,6 @@
#include "glsl_rmiss_light.h" #include "glsl_rmiss_light.h"
#include "glsl_rmiss_sun.h" #include "glsl_rmiss_sun.h"
extern int LightBounce;
extern bool VKDebug; extern bool VKDebug;
GPURaytracer::GPURaytracer() GPURaytracer::GPURaytracer()
@ -86,7 +85,7 @@ void GPURaytracer::Raytrace(LevelMesh* level)
HemisphereVectors.push_back(H); HemisphereVectors.push_back(H);
} }
printf("Ray tracing with %d bounce(s)\n", LightBounce); printf("Ray tracing with %d bounce(s)\n", mesh->map->LightBounce);
size_t maxTasks = (size_t)rayTraceImageSize * rayTraceImageSize; size_t maxTasks = (size_t)rayTraceImageSize * rayTraceImageSize;
for (size_t startTask = 0; startTask < tasks.size(); startTask += maxTasks) for (size_t startTask = 0; startTask < tasks.size(); startTask += maxTasks)
@ -119,7 +118,7 @@ void GPURaytracer::Raytrace(LevelMesh* level)
uniforms.HemisphereVec = HemisphereVectors[uniforms.SampleIndex]; uniforms.HemisphereVec = HemisphereVectors[uniforms.SampleIndex];
RunTrace(uniforms, rgenBounceRegion); RunTrace(uniforms, rgenBounceRegion);
for (int bounce = 0; bounce < LightBounce; bounce++) for (int bounce = 0; bounce < mesh->map->LightBounce; bounce++)
{ {
uniforms.SampleCount = coverageSampleCount; uniforms.SampleCount = coverageSampleCount;
RunTrace(uniforms, rgenLightRegion); RunTrace(uniforms, rgenLightRegion);

View file

@ -34,8 +34,6 @@
#include "pngwriter.h" #include "pngwriter.h"
#include <map> #include <map>
extern float GridSize;
#ifdef _MSC_VER #ifdef _MSC_VER
#pragma warning(disable: 4267) // warning C4267: 'argument': conversion from 'size_t' to 'int', possible loss of data #pragma warning(disable: 4267) // warning C4267: 'argument': conversion from 'size_t' to 'int', possible loss of data
#pragma warning(disable: 4244) // warning C4244: '=': conversion from '__int64' to 'int', possible loss of data #pragma warning(disable: 4244) // warning C4244: '=': conversion from '__int64' to 'int', possible loss of data
@ -392,12 +390,12 @@ void LevelMesh::CreateLightProbes(FLevel& map)
float maxX = std::floor(map.MaxX / 65536.0f) + 1.0f; float maxX = std::floor(map.MaxX / 65536.0f) + 1.0f;
float maxY = std::floor(map.MaxY / 65536.0f) + 1.0f; float maxY = std::floor(map.MaxY / 65536.0f) + 1.0f;
float halfGridSize = GridSize * 0.5f; float halfGridSize = map.GridSize * 0.5f;
float doubleGridSize = GridSize * 2.0f; float doubleGridSize = map.GridSize * 2.0f;
for (float y = minY; y < maxY; y += GridSize) for (float y = minY; y < maxY; y += map.GridSize)
{ {
for (float x = minX; x < maxX; x += GridSize) for (float x = minX; x < maxX; x += map.GridSize)
{ {
MapSubsectorEx* ssec = map.PointInSubSector((int)x, (int)y); MapSubsectorEx* ssec = map.PointInSubSector((int)x, (int)y);
IntSector* sec = ssec ? map.GetSectorFromSubSector(ssec) : nullptr; IntSector* sec = ssec ? map.GetSectorFromSubSector(ssec) : nullptr;

View file

@ -115,11 +115,8 @@ bool HaveSSE1, HaveSSE2;
int SSELevel; int SSELevel;
int NumThreads = 0; int NumThreads = 0;
int LMDims = 1024; int LMDims = 1024;
int Samples = 8;
bool CPURaytrace = false; bool CPURaytrace = false;
bool VKDebug = false; bool VKDebug = false;
int LightBounce = 1;
float GridSize = 32.0f;
// PRIVATE DATA DEFINITIONS ------------------------------------------------ // PRIVATE DATA DEFINITIONS ------------------------------------------------
@ -155,16 +152,13 @@ static option long_opts[] =
{"no-sse2", no_argument, 0, 1003}, {"no-sse2", no_argument, 0, 1003},
{"comments", no_argument, 0, 'c'}, {"comments", no_argument, 0, 'c'},
{"threads", required_argument, 0, 'j'}, {"threads", required_argument, 0, 'j'},
{"samples", required_argument, 0, 'Q'},
{"size", required_argument, 0, 'S'}, {"size", required_argument, 0, 'S'},
{"cpu-raytrace", no_argument, 0, 'C'}, {"cpu-raytrace", no_argument, 0, 'C'},
{"bounce", required_argument, 0, 'B'},
{"gridsize", required_argument, 0, 'i'},
{"vkdebug", no_argument, 0, 'D'}, {"vkdebug", no_argument, 0, 'D'},
{0,0,0,0} {0,0,0,0}
}; };
static const char short_opts[] = "wVgGvbNrReEm:o:f:p:s:d:PqtzZXx5cj:Q:S:CD"; static const char short_opts[] = "wVgGvbNrReEm:o:f:p:s:d:PqtzZXx5cj:S:CD";
// CODE -------------------------------------------------------------------- // CODE --------------------------------------------------------------------
@ -439,12 +433,6 @@ static void ParseArgs(int argc, char **argv)
case 'j': case 'j':
NumThreads = atoi(optarg); NumThreads = atoi(optarg);
break; break;
case 'Q':
Samples = atoi(optarg);
if (Samples <= 0) Samples = 1;
if (Samples > 128) Samples = 128;
Samples = Math::RoundPowerOfTwo(Samples);
break;
case 'S': case 'S':
LMDims = atoi(optarg); LMDims = atoi(optarg);
if (LMDims <= 0) LMDims = 1; if (LMDims <= 0) LMDims = 1;
@ -457,15 +445,6 @@ static void ParseArgs(int argc, char **argv)
case 'D': case 'D':
VKDebug = true; VKDebug = true;
break; break;
case 'B':
LightBounce = atoi(optarg);
if (LightBounce < 0) LightBounce = 0;
if (LightBounce > 8) LightBounce = 8;
break;
case 'i':
GridSize = std::stof(optarg);
if (GridSize < 0.f) GridSize = 0.f;
break;
case 1000: case 1000:
ShowUsage(); ShowUsage();
exit(0); exit(0);
@ -508,15 +487,9 @@ static void ShowUsage()
" -d, --diagonal-cost=NNN Cost for avoiding diagonal splitters (default %d)\n" " -d, --diagonal-cost=NNN Cost for avoiding diagonal splitters (default %d)\n"
" -P, --no-polyobjs Do not check for polyobject subsector splits\n" " -P, --no-polyobjs Do not check for polyobject subsector splits\n"
" -j, --threads=NNN Number of threads used for raytracing (default %d)\n" " -j, --threads=NNN Number of threads used for raytracing (default %d)\n"
" -Q, --samples=NNN Set texel sampling size (lowest = higher quaility but\n"
" slow compile time) must be in powers of two (default %d)\n"
" -S, --size=NNN lightmap texture dimensions for width and height\n" " -S, --size=NNN lightmap texture dimensions for width and height\n"
" must be in powers of two (1, 2, 4, 8, 16, etc)\n" " must be in powers of two (1, 2, 4, 8, 16, etc)\n"
" -C, --cpu-raytrace Use the CPU for ray tracing\n" " -C, --cpu-raytrace Use the CPU for ray tracing\n"
" -B, --bounce=NNN Number of indirect light bounces (default %d, max 8)\n"
" -i, --gridsize=NNN Automatic light probe grid size, floating point\n"
" Lower values increase granularity at the expense of performance\n"
" Recommended: 32.0, 64.0, 128.0, etc (default %.1f)\n"
" -D, --vkdebug Print messages from the vulkan validation layer\n" " -D, --vkdebug Print messages from the vulkan validation layer\n"
" -w, --warn Show warning messages\n" " -w, --warn Show warning messages\n"
#if HAVE_TIMING #if HAVE_TIMING
@ -531,9 +504,6 @@ static void ShowUsage()
, SplitCost , SplitCost
, AAPreference , AAPreference
, (int)std::thread::hardware_concurrency() , (int)std::thread::hardware_concurrency()
, Samples
, LightBounce
, GridSize
); );
} }