mirror of
https://github.com/ZDoom/ZDRay.git
synced 2025-04-07 15:31:58 +00:00
Add surface and sunlight to the new CPU ray tracer
This commit is contained in:
parent
75798fae9b
commit
c7b220c2ba
5 changed files with 113 additions and 21 deletions
|
@ -19,7 +19,6 @@
|
|||
#include "glsl_miss.h"
|
||||
#include "glsl_closesthit.h"
|
||||
|
||||
extern int Multisample;
|
||||
extern int LightBounce;
|
||||
extern float GridSize;
|
||||
|
||||
|
@ -281,7 +280,29 @@ void GPURaytracer::Raytrace(LevelMesh* level)
|
|||
|
||||
void GPURaytracer::RaytraceProbeSample(LightProbeSample* probe)
|
||||
{
|
||||
Vec3 color(0.0f, 0.0f, 0.0f);
|
||||
Vec3 incoming(0.0f, 0.0f, 0.0f);
|
||||
|
||||
if (LightBounce > 0)
|
||||
{
|
||||
Vec3 directions[6] =
|
||||
{
|
||||
{ 1.0f, 0.0f, 0.0f },
|
||||
{ -1.0f, 0.0f, 0.0f },
|
||||
{ 0.0f, 1.0f, 0.0f },
|
||||
{ 0.0f, -1.0f, 0.0f },
|
||||
{ 0.0f, 0.0f, 1.0f, },
|
||||
{ 0.0f, 0.0f, -1.0f, }
|
||||
};
|
||||
for (int i = 0; i < SAMPLE_COUNT; i++)
|
||||
{
|
||||
const Vec3& normal = directions[i % 6];
|
||||
Vec2 Xi = Hammersley(i, SAMPLE_COUNT);
|
||||
Vec3 H = ImportanceSampleGGX(Xi, normal, 1.0f);
|
||||
Vec3 L = Vec3::Normalize(H * (2.0f * Vec3::Dot(normal, H)) - normal);
|
||||
incoming += TracePath(probe->Position, L, i);
|
||||
}
|
||||
incoming = incoming / (float)SAMPLE_COUNT / (float)LightBounce;
|
||||
}
|
||||
|
||||
for (ThingLight& light : mesh->map->ThingLights)
|
||||
{
|
||||
|
@ -298,10 +319,15 @@ void GPURaytracer::RaytraceProbeSample(LightProbeSample* probe)
|
|||
float dist = dir.Unit();
|
||||
dir.Normalize();
|
||||
|
||||
color += light.rgb * (light.SpotAttenuation(dir) * light.DistAttenuation(dist) * light.intensity);
|
||||
incoming += light.rgb * (light.SpotAttenuation(dir) * light.DistAttenuation(dist) * light.intensity);
|
||||
}
|
||||
|
||||
probe->Color = color;
|
||||
const Vec3& sundir = mesh->map->GetSunDirection();
|
||||
LevelTraceHit trace = mesh->Trace(probe->Position, probe->Position + sundir * 32768.0f);
|
||||
if (trace.fraction != 1.0f && trace.hitSurface->bSky)
|
||||
incoming += mesh->map->GetSunColor();
|
||||
|
||||
probe->Color = incoming;
|
||||
}
|
||||
|
||||
void GPURaytracer::RaytraceSurfaceSample(Surface* surface, int x, int y)
|
||||
|
@ -330,6 +356,15 @@ void GPURaytracer::RaytraceSurfaceSample(Surface* surface, int x, int y)
|
|||
|
||||
incoming = incoming + GetSurfaceEmittance(surface, 0.0f) + GetLightEmittance(surface, pos);
|
||||
|
||||
const Vec3& sundir = mesh->map->GetSunDirection();
|
||||
float attenuation = normal.Dot(sundir);
|
||||
if (attenuation > 0.0f)
|
||||
{
|
||||
LevelTraceHit trace = mesh->Trace(pos, pos + sundir * 32768.0f);
|
||||
if (trace.fraction != 1.0f && trace.hitSurface->bSky)
|
||||
incoming += mesh->map->GetSunColor() * attenuation;
|
||||
}
|
||||
|
||||
size_t sampleWidth = surface->lightmapDims[0];
|
||||
surface->samples[x + y * sampleWidth] = incoming;
|
||||
}
|
||||
|
@ -369,20 +404,30 @@ Vec3 GPURaytracer::TracePath(const Vec3& pos, const Vec3& dir, int sampleIndex,
|
|||
if (depth >= LightBounce)
|
||||
return Vec3(0.0f);
|
||||
|
||||
LevelTraceHit hit = mesh->Trace(pos, pos + dir * 1000.0f);
|
||||
LevelTraceHit hit = mesh->Trace(pos + dir * 0.1f, pos + dir * 2000.0f);
|
||||
if (hit.fraction == 1.0f)
|
||||
return Vec3(0.0f);
|
||||
|
||||
Vec3 normal = hit.hitSurface->plane.Normal();
|
||||
Vec3 hitpos = hit.start * (1.0f - hit.fraction) + hit.end * hit.fraction + normal * 0.1f;
|
||||
Vec3 hitpos = hit.start * (1.0f - hit.fraction) + hit.end * hit.fraction;
|
||||
|
||||
Vec3 emittance = GetSurfaceEmittance(hit.hitSurface, pos.Distance(hitpos)) + GetLightEmittance(hit.hitSurface, hitpos) * 0.5f;
|
||||
|
||||
const Vec3& sundir = mesh->map->GetSunDirection();
|
||||
float attenuation = normal.Dot(sundir);
|
||||
if (attenuation > 0.0f)
|
||||
{
|
||||
Vec3 start = hitpos + normal * 0.1f;
|
||||
LevelTraceHit trace = mesh->Trace(start, start + sundir * 32768.0f);
|
||||
if (trace.fraction != 1.0f && trace.hitSurface->bSky)
|
||||
emittance += mesh->map->GetSunColor() * (attenuation * 0.5f);
|
||||
}
|
||||
|
||||
Vec2 Xi = Hammersley(sampleIndex, SAMPLE_COUNT);
|
||||
Vec3 H = ImportanceSampleGGX(Xi, normal, 1.0f);
|
||||
Vec3 L = Vec3::Normalize(H * (2.0f * Vec3::Dot(normal, H)) - normal);
|
||||
|
||||
float NdotL = std::max(Vec3::Dot(normal, L), 0.0f);
|
||||
float NdotL = Vec3::Dot(normal, L);
|
||||
if (NdotL <= 0.0f)
|
||||
return emittance;
|
||||
|
||||
|
@ -456,9 +501,10 @@ Vec3 GPURaytracer::GetSurfaceEmittance(Surface* surface, float distance)
|
|||
}
|
||||
}
|
||||
|
||||
if (def)
|
||||
if (def && distance < def->distance + def->distance)
|
||||
{
|
||||
float attenuation = std::max(1.0f - (distance / def->distance), 0.0f);
|
||||
float radius = def->distance + def->distance;
|
||||
float attenuation = std::max(1.0f - (distance / radius), 0.0f);
|
||||
return def->rgb * (attenuation * def->intensity);
|
||||
}
|
||||
else
|
||||
|
|
|
@ -47,7 +47,7 @@ private:
|
|||
static Vec2 Hammersley(uint32_t i, uint32_t N);
|
||||
static Vec3 ImportanceSampleGGX(Vec2 Xi, Vec3 N, float roughness);
|
||||
|
||||
int SAMPLE_COUNT = 1024;// 128;// 1024;
|
||||
int SAMPLE_COUNT = 1024;
|
||||
|
||||
LevelMesh* mesh = nullptr;
|
||||
|
||||
|
|
|
@ -13,7 +13,6 @@
|
|||
#include <algorithm>
|
||||
#include <zlib.h>
|
||||
|
||||
extern int Multisample;
|
||||
extern int LightBounce;
|
||||
extern float GridSize;
|
||||
|
||||
|
@ -71,7 +70,29 @@ void Raytracer::Raytrace(LevelMesh* level)
|
|||
|
||||
void Raytracer::RaytraceProbeSample(LightProbeSample* probe)
|
||||
{
|
||||
Vec3 color(0.0f, 0.0f, 0.0f);
|
||||
Vec3 incoming(0.0f, 0.0f, 0.0f);
|
||||
|
||||
if (LightBounce > 0)
|
||||
{
|
||||
Vec3 directions[6] =
|
||||
{
|
||||
{ 1.0f, 0.0f, 0.0f },
|
||||
{ -1.0f, 0.0f, 0.0f },
|
||||
{ 0.0f, 1.0f, 0.0f },
|
||||
{ 0.0f, -1.0f, 0.0f },
|
||||
{ 0.0f, 0.0f, 1.0f, },
|
||||
{ 0.0f, 0.0f, -1.0f, }
|
||||
};
|
||||
for (int i = 0; i < SAMPLE_COUNT; i++)
|
||||
{
|
||||
const Vec3& normal = directions[i % 6];
|
||||
Vec2 Xi = Hammersley(i, SAMPLE_COUNT);
|
||||
Vec3 H = ImportanceSampleGGX(Xi, normal, 1.0f);
|
||||
Vec3 L = Vec3::Normalize(H * (2.0f * Vec3::Dot(normal, H)) - normal);
|
||||
incoming += TracePath(probe->Position, L, i);
|
||||
}
|
||||
incoming = incoming / (float)SAMPLE_COUNT / (float)LightBounce;
|
||||
}
|
||||
|
||||
for (ThingLight& light : mesh->map->ThingLights)
|
||||
{
|
||||
|
@ -88,10 +109,15 @@ void Raytracer::RaytraceProbeSample(LightProbeSample* probe)
|
|||
float dist = dir.Unit();
|
||||
dir.Normalize();
|
||||
|
||||
color += light.rgb * (light.SpotAttenuation(dir) * light.DistAttenuation(dist) * light.intensity);
|
||||
incoming += light.rgb * (light.SpotAttenuation(dir) * light.DistAttenuation(dist) * light.intensity);
|
||||
}
|
||||
|
||||
probe->Color = color;
|
||||
const Vec3& sundir = mesh->map->GetSunDirection();
|
||||
LevelTraceHit trace = mesh->Trace(probe->Position, probe->Position + sundir * 32768.0f);
|
||||
if (trace.fraction != 1.0f && trace.hitSurface->bSky)
|
||||
incoming += mesh->map->GetSunColor();
|
||||
|
||||
probe->Color = incoming;
|
||||
}
|
||||
|
||||
void Raytracer::RaytraceSurfaceSample(Surface* surface, int x, int y)
|
||||
|
@ -120,6 +146,15 @@ void Raytracer::RaytraceSurfaceSample(Surface* surface, int x, int y)
|
|||
|
||||
incoming = incoming + GetSurfaceEmittance(surface, 0.0f) + GetLightEmittance(surface, pos);
|
||||
|
||||
const Vec3& sundir = mesh->map->GetSunDirection();
|
||||
float attenuation = normal.Dot(sundir);
|
||||
if (attenuation > 0.0f)
|
||||
{
|
||||
LevelTraceHit trace = mesh->Trace(pos, pos + sundir * 32768.0f);
|
||||
if (trace.fraction != 1.0f && trace.hitSurface->bSky)
|
||||
incoming += mesh->map->GetSunColor() * attenuation;
|
||||
}
|
||||
|
||||
size_t sampleWidth = surface->lightmapDims[0];
|
||||
surface->samples[x + y * sampleWidth] = incoming;
|
||||
}
|
||||
|
@ -159,20 +194,30 @@ Vec3 Raytracer::TracePath(const Vec3& pos, const Vec3& dir, int sampleIndex, int
|
|||
if (depth >= LightBounce)
|
||||
return Vec3(0.0f);
|
||||
|
||||
LevelTraceHit hit = mesh->Trace(pos, pos + dir * 1000.0f);
|
||||
LevelTraceHit hit = mesh->Trace(pos + dir * 0.1f, pos + dir * 2000.0f);
|
||||
if (hit.fraction == 1.0f)
|
||||
return Vec3(0.0f);
|
||||
|
||||
Vec3 normal = hit.hitSurface->plane.Normal();
|
||||
Vec3 hitpos = hit.start * (1.0f - hit.fraction) + hit.end * hit.fraction + normal * 0.1f;
|
||||
Vec3 hitpos = hit.start * (1.0f - hit.fraction) + hit.end * hit.fraction;
|
||||
|
||||
Vec3 emittance = GetSurfaceEmittance(hit.hitSurface, pos.Distance(hitpos)) + GetLightEmittance(hit.hitSurface, hitpos) * 0.5f;
|
||||
|
||||
const Vec3& sundir = mesh->map->GetSunDirection();
|
||||
float attenuation = normal.Dot(sundir);
|
||||
if (attenuation > 0.0f)
|
||||
{
|
||||
Vec3 start = hitpos + normal * 0.1f;
|
||||
LevelTraceHit trace = mesh->Trace(start, start + sundir * 32768.0f);
|
||||
if (trace.fraction != 1.0f && trace.hitSurface->bSky)
|
||||
emittance += mesh->map->GetSunColor() * (attenuation * 0.5f);
|
||||
}
|
||||
|
||||
Vec2 Xi = Hammersley(sampleIndex, SAMPLE_COUNT);
|
||||
Vec3 H = ImportanceSampleGGX(Xi, normal, 1.0f);
|
||||
Vec3 L = Vec3::Normalize(H * (2.0f * Vec3::Dot(normal, H)) - normal);
|
||||
|
||||
float NdotL = std::max(Vec3::Dot(normal, L), 0.0f);
|
||||
float NdotL = Vec3::Dot(normal, L);
|
||||
if (NdotL <= 0.0f)
|
||||
return emittance;
|
||||
|
||||
|
@ -246,9 +291,10 @@ Vec3 Raytracer::GetSurfaceEmittance(Surface* surface, float distance)
|
|||
}
|
||||
}
|
||||
|
||||
if (def)
|
||||
if (def && distance < def->distance + def->distance)
|
||||
{
|
||||
float attenuation = std::max(1.0f - (distance / def->distance), 0.0f);
|
||||
float radius = def->distance + def->distance;
|
||||
float attenuation = std::max(1.0f - (distance / radius), 0.0f);
|
||||
return def->rgb * (attenuation * def->intensity);
|
||||
}
|
||||
else
|
||||
|
|
|
@ -23,7 +23,7 @@ private:
|
|||
static Vec2 Hammersley(uint32_t i, uint32_t N);
|
||||
static Vec3 ImportanceSampleGGX(Vec2 Xi, Vec3 N, float roughness);
|
||||
|
||||
int SAMPLE_COUNT = 1024;// 128;// 1024;
|
||||
int SAMPLE_COUNT = 1024;
|
||||
|
||||
LevelMesh* mesh = nullptr;
|
||||
};
|
||||
|
|
|
@ -506,7 +506,7 @@ static void ShowUsage()
|
|||
" -P, --no-polyobjs Do not check for polyobject subsector splits\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\n"
|
||||
" slow compile time) must be in powers of two (default %d)\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"
|
||||
" -M, --multisample=NNN Number of samples to use per texel (default %d)\n"
|
||||
|
|
Loading…
Reference in a new issue