mirror of
https://github.com/ZDoom/ZDRay.git
synced 2024-11-14 16:40:43 +00:00
- add indirect light pass
This commit is contained in:
parent
ef3257e062
commit
63715b855d
7 changed files with 216 additions and 69 deletions
|
@ -309,8 +309,11 @@ struct LevelTraceHit
|
||||||
{
|
{
|
||||||
kexVec3 start;
|
kexVec3 start;
|
||||||
kexVec3 end;
|
kexVec3 end;
|
||||||
surface_t *hitSurface;
|
|
||||||
float fraction;
|
float fraction;
|
||||||
|
|
||||||
|
surface_t *hitSurface;
|
||||||
|
int indices[3];
|
||||||
|
float b, c;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct FLevel
|
struct FLevel
|
||||||
|
@ -357,6 +360,7 @@ struct FLevel
|
||||||
// Dlight helpers
|
// Dlight helpers
|
||||||
|
|
||||||
TArray<kexVec3> MeshVertices;
|
TArray<kexVec3> MeshVertices;
|
||||||
|
TArray<int> MeshUVIndex;
|
||||||
TArray<unsigned int> MeshElements;
|
TArray<unsigned int> MeshElements;
|
||||||
TArray<int> MeshSurfaces;
|
TArray<int> MeshSurfaces;
|
||||||
std::unique_ptr<TriangleMeshShape> CollisionMesh;
|
std::unique_ptr<TriangleMeshShape> CollisionMesh;
|
||||||
|
|
|
@ -358,6 +358,24 @@ LevelTraceHit FLevel::Trace(const kexVec3 &startVec, const kexVec3 &endVec)
|
||||||
trace.start = startVec;
|
trace.start = startVec;
|
||||||
trace.end = endVec;
|
trace.end = endVec;
|
||||||
trace.fraction = hit.fraction;
|
trace.fraction = hit.fraction;
|
||||||
trace.hitSurface = (trace.fraction < 1.0f) ? surfaces[hit.surface].get() : nullptr;
|
if (trace.fraction < 1.0f)
|
||||||
|
{
|
||||||
|
int elementIdx = hit.triangle * 3;
|
||||||
|
trace.hitSurface = surfaces[MeshSurfaces[hit.triangle]].get();
|
||||||
|
trace.indices[0] = MeshUVIndex[MeshElements[elementIdx]];
|
||||||
|
trace.indices[1] = MeshUVIndex[MeshElements[elementIdx + 1]];
|
||||||
|
trace.indices[2] = MeshUVIndex[MeshElements[elementIdx + 2]];
|
||||||
|
trace.b = hit.b;
|
||||||
|
trace.c = hit.c;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
trace.hitSurface = nullptr;
|
||||||
|
trace.indices[0] = 0;
|
||||||
|
trace.indices[1] = 0;
|
||||||
|
trace.indices[2] = 0;
|
||||||
|
trace.b = 0.0f;
|
||||||
|
trace.c = 0.0f;
|
||||||
|
}
|
||||||
return trace;
|
return trace;
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,8 +27,8 @@
|
||||||
#include <immintrin.h>
|
#include <immintrin.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
TriangleMeshShape::TriangleMeshShape(const kexVec3 *vertices, int num_vertices, const unsigned int *elements, int num_elements, const int *surfaces)
|
TriangleMeshShape::TriangleMeshShape(const kexVec3 *vertices, int num_vertices, const unsigned int *elements, int num_elements)
|
||||||
: vertices(vertices), num_vertices(num_vertices), elements(elements), num_elements(num_elements), surfaces(surfaces)
|
: vertices(vertices), num_vertices(num_vertices), elements(elements), num_elements(num_elements)
|
||||||
{
|
{
|
||||||
int num_triangles = num_elements / 3;
|
int num_triangles = num_elements / 3;
|
||||||
if (num_triangles <= 0)
|
if (num_triangles <= 0)
|
||||||
|
@ -94,8 +94,6 @@ TraceHit TriangleMeshShape::find_first_hit(TriangleMeshShape *shape, const kexVe
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hit.surface != -1)
|
|
||||||
hit.surface = shape->surfaces[hit.surface / 3];
|
|
||||||
return hit;
|
return hit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -193,7 +191,8 @@ bool TriangleMeshShape::find_any_hit(TriangleMeshShape *shape, const RayBBox &ra
|
||||||
{
|
{
|
||||||
if (shape->is_leaf(a))
|
if (shape->is_leaf(a))
|
||||||
{
|
{
|
||||||
return intersect_triangle_ray(shape, ray, a) < 1.0f;
|
float baryB, baryC;
|
||||||
|
return intersect_triangle_ray(shape, ray, a, baryB, baryC) < 1.0f;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -212,11 +211,14 @@ void TriangleMeshShape::find_first_hit(TriangleMeshShape *shape, const RayBBox &
|
||||||
{
|
{
|
||||||
if (shape->is_leaf(a))
|
if (shape->is_leaf(a))
|
||||||
{
|
{
|
||||||
float t = intersect_triangle_ray(shape, ray, a);
|
float baryB, baryC;
|
||||||
|
float t = intersect_triangle_ray(shape, ray, a, baryB, baryC);
|
||||||
if (t < hit->fraction)
|
if (t < hit->fraction)
|
||||||
{
|
{
|
||||||
hit->fraction = t;
|
hit->fraction = t;
|
||||||
hit->surface = shape->nodes[a].element_index;
|
hit->triangle = shape->nodes[a].element_index / 3;
|
||||||
|
hit->b = baryB;
|
||||||
|
hit->c = baryC;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -232,7 +234,7 @@ bool TriangleMeshShape::overlap_bv_ray(TriangleMeshShape *shape, const RayBBox &
|
||||||
return IntersectionTest::ray_aabb(ray, shape->nodes[a].aabb) == IntersectionTest::overlap;
|
return IntersectionTest::ray_aabb(ray, shape->nodes[a].aabb) == IntersectionTest::overlap;
|
||||||
}
|
}
|
||||||
|
|
||||||
float TriangleMeshShape::intersect_triangle_ray(TriangleMeshShape *shape, const RayBBox &ray, int a)
|
float TriangleMeshShape::intersect_triangle_ray(TriangleMeshShape *shape, const RayBBox &ray, int a, float &barycentricB, float &barycentricC)
|
||||||
{
|
{
|
||||||
const int start_element = shape->nodes[a].element_index;
|
const int start_element = shape->nodes[a].element_index;
|
||||||
|
|
||||||
|
@ -243,49 +245,6 @@ float TriangleMeshShape::intersect_triangle_ray(TriangleMeshShape *shape, const
|
||||||
shape->vertices[shape->elements[start_element + 2]]
|
shape->vertices[shape->elements[start_element + 2]]
|
||||||
};
|
};
|
||||||
|
|
||||||
#if 1
|
|
||||||
|
|
||||||
kexVec3 e1 = p[1] - p[0];
|
|
||||||
kexVec3 e2 = p[2] - p[0];
|
|
||||||
|
|
||||||
kexVec3 triangleNormal = kexVec3::Cross(e1, e2);
|
|
||||||
float dist = kexVec3::Dot(p[0], triangleNormal);
|
|
||||||
float distA = kexVec3::Dot(ray.start, triangleNormal) - dist;
|
|
||||||
float distB = kexVec3::Dot(ray.end, triangleNormal) - dist;
|
|
||||||
|
|
||||||
if (distA * distB >= 0.0f)
|
|
||||||
return 1.0f;
|
|
||||||
|
|
||||||
// Backface check
|
|
||||||
//if (distA < 0.0f)
|
|
||||||
// return 1.0f;
|
|
||||||
|
|
||||||
float projLength = distA - distB;
|
|
||||||
float distance = (distA) / (projLength);
|
|
||||||
if (distance > 1.0f)
|
|
||||||
return 1.0f;
|
|
||||||
|
|
||||||
float edgeTolerance = triangleNormal.LengthSq() * -0.0001f;
|
|
||||||
kexVec3 point = ray.start * (1.0f - distance) + ray.end * distance;
|
|
||||||
|
|
||||||
kexVec3 v0p = p[0] - point;
|
|
||||||
kexVec3 v1p = p[1] - point;
|
|
||||||
kexVec3 cp0 = kexVec3::Cross(v0p, v1p);
|
|
||||||
if (kexVec3::Dot(cp0, triangleNormal) < edgeTolerance)
|
|
||||||
return 1.0f;
|
|
||||||
|
|
||||||
kexVec3 v2p = p[2] - point;
|
|
||||||
kexVec3 cp1 = kexVec3::Cross(v1p, v2p);
|
|
||||||
if (kexVec3::Dot(cp1, triangleNormal) < edgeTolerance)
|
|
||||||
return 1.0f;
|
|
||||||
|
|
||||||
kexVec3 cp2 = kexVec3::Cross(v2p, v0p);
|
|
||||||
if (kexVec3::Dot(cp2, triangleNormal) < edgeTolerance)
|
|
||||||
return 1.0f;
|
|
||||||
|
|
||||||
return distance;
|
|
||||||
|
|
||||||
#else
|
|
||||||
// Moeller–Trumbore ray-triangle intersection algorithm:
|
// Moeller–Trumbore ray-triangle intersection algorithm:
|
||||||
|
|
||||||
kexVec3 D = ray.end - ray.start;
|
kexVec3 D = ray.end - ray.start;
|
||||||
|
@ -329,12 +288,14 @@ float TriangleMeshShape::intersect_triangle_ray(TriangleMeshShape *shape, const
|
||||||
return 1.0f;
|
return 1.0f;
|
||||||
|
|
||||||
float t = kexVec3::Dot(e2, Q) * inv_det;
|
float t = kexVec3::Dot(e2, Q) * inv_det;
|
||||||
if (t > FLT_EPSILON)
|
if (t <= FLT_EPSILON)
|
||||||
return t;
|
return 1.0f;
|
||||||
|
|
||||||
// No hit, no win
|
// Return hit location on triangle in barycentric coordinates
|
||||||
return 1.0f;
|
barycentricB = u;
|
||||||
#endif
|
barycentricC = v;
|
||||||
|
|
||||||
|
return t;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TriangleMeshShape::sweep_overlap_bv_sphere(TriangleMeshShape *shape1, SphereShape *shape2, int a, const kexVec3 &target)
|
bool TriangleMeshShape::sweep_overlap_bv_sphere(TriangleMeshShape *shape1, SphereShape *shape2, int a, const kexVec3 &target)
|
||||||
|
|
|
@ -39,7 +39,9 @@ public:
|
||||||
struct TraceHit
|
struct TraceHit
|
||||||
{
|
{
|
||||||
float fraction = 1.0f;
|
float fraction = 1.0f;
|
||||||
int surface = -1;
|
int triangle = -1;
|
||||||
|
float b = 0.0f;
|
||||||
|
float c = 0.0f;
|
||||||
};
|
};
|
||||||
|
|
||||||
class CollisionBBox : public kexBBox
|
class CollisionBBox : public kexBBox
|
||||||
|
@ -80,7 +82,7 @@ public:
|
||||||
class TriangleMeshShape
|
class TriangleMeshShape
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
TriangleMeshShape(const kexVec3 *vertices, int num_vertices, const unsigned int *elements, int num_elements, const int *surfaces);
|
TriangleMeshShape(const kexVec3 *vertices, int num_vertices, const unsigned int *elements, int num_elements);
|
||||||
|
|
||||||
int get_min_depth() const;
|
int get_min_depth() const;
|
||||||
int get_max_depth() const;
|
int get_max_depth() const;
|
||||||
|
@ -113,7 +115,6 @@ public:
|
||||||
const int num_vertices = 0;
|
const int num_vertices = 0;
|
||||||
const unsigned int *elements = nullptr;
|
const unsigned int *elements = nullptr;
|
||||||
int num_elements = 0;
|
int num_elements = 0;
|
||||||
const int *surfaces = nullptr;
|
|
||||||
|
|
||||||
std::vector<Node> nodes;
|
std::vector<Node> nodes;
|
||||||
int root = -1;
|
int root = -1;
|
||||||
|
@ -128,7 +129,7 @@ private:
|
||||||
static void find_first_hit(TriangleMeshShape *shape1, const RayBBox &ray, int a, TraceHit *hit);
|
static void find_first_hit(TriangleMeshShape *shape1, const RayBBox &ray, int a, TraceHit *hit);
|
||||||
|
|
||||||
inline static bool overlap_bv_ray(TriangleMeshShape *shape, const RayBBox &ray, int a);
|
inline static bool overlap_bv_ray(TriangleMeshShape *shape, const RayBBox &ray, int a);
|
||||||
inline static float intersect_triangle_ray(TriangleMeshShape *shape, const RayBBox &ray, int a);
|
inline static float intersect_triangle_ray(TriangleMeshShape *shape, const RayBBox &ray, int a, float &barycentricB, float &barycentricC);
|
||||||
|
|
||||||
inline static bool sweep_overlap_bv_sphere(TriangleMeshShape *shape1, SphereShape *shape2, int a, const kexVec3 &target);
|
inline static bool sweep_overlap_bv_sphere(TriangleMeshShape *shape1, SphereShape *shape2, int a, const kexVec3 &target);
|
||||||
inline static float sweep_intersect_triangle_sphere(TriangleMeshShape *shape1, SphereShape *shape2, int a, const kexVec3 &target);
|
inline static float sweep_intersect_triangle_sphere(TriangleMeshShape *shape1, SphereShape *shape2, int a, const kexVec3 &target);
|
||||||
|
|
|
@ -464,19 +464,18 @@ void kexLightmapBuilder::TraceSurface(surface_t *surface)
|
||||||
bShouldLookupTexture = true;
|
bShouldLookupTexture = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
kexMath::Clamp(c, 0, 1);
|
|
||||||
colorSamples[i * LIGHTMAP_MAX_SIZE + j] = c;
|
colorSamples[i * LIGHTMAP_MAX_SIZE + j] = c;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// SVE redraws the scene for lightmaps, so for optimizations,
|
// SVE redraws the scene for lightmaps, so for optimizations,
|
||||||
// tell the engine to ignore this surface if completely black
|
// tell the engine to ignore this surface if completely black
|
||||||
if (bShouldLookupTexture == false)
|
/*if (bShouldLookupTexture == false)
|
||||||
{
|
{
|
||||||
surface->lightmapNum = -1;
|
surface->lightmapNum = -1;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else
|
else*/
|
||||||
{
|
{
|
||||||
int x = 0, y = 0;
|
int x = 0, y = 0;
|
||||||
int width = surface->lightmapDims[0];
|
int width = surface->lightmapDims[0];
|
||||||
|
@ -534,6 +533,126 @@ void kexLightmapBuilder::TraceSurface(surface_t *surface)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static float RadicalInverse_VdC(uint32_t bits)
|
||||||
|
{
|
||||||
|
bits = (bits << 16u) | (bits >> 16u);
|
||||||
|
bits = ((bits & 0x55555555u) << 1u) | ((bits & 0xAAAAAAAAu) >> 1u);
|
||||||
|
bits = ((bits & 0x33333333u) << 2u) | ((bits & 0xCCCCCCCCu) >> 2u);
|
||||||
|
bits = ((bits & 0x0F0F0F0Fu) << 4u) | ((bits & 0xF0F0F0F0u) >> 4u);
|
||||||
|
bits = ((bits & 0x00FF00FFu) << 8u) | ((bits & 0xFF00FF00u) >> 8u);
|
||||||
|
return float(bits) * 2.3283064365386963e-10f; // / 0x100000000
|
||||||
|
}
|
||||||
|
|
||||||
|
static kexVec2 Hammersley(uint32_t i, uint32_t N)
|
||||||
|
{
|
||||||
|
return kexVec2(float(i) / float(N), RadicalInverse_VdC(i));
|
||||||
|
}
|
||||||
|
|
||||||
|
static kexVec3 ImportanceSampleGGX(kexVec2 Xi, kexVec3 N, float roughness)
|
||||||
|
{
|
||||||
|
float a = roughness * roughness;
|
||||||
|
|
||||||
|
float phi = 2.0f * M_PI * Xi.x;
|
||||||
|
float cosTheta = sqrt((1.0f - Xi.y) / (1.0f + (a*a - 1.0f) * Xi.y));
|
||||||
|
float sinTheta = sqrt(1.0f - cosTheta * cosTheta);
|
||||||
|
|
||||||
|
// from spherical coordinates to cartesian coordinates
|
||||||
|
kexVec3 H(std::cos(phi) * sinTheta, std::sin(phi) * sinTheta, cosTheta);
|
||||||
|
|
||||||
|
// from tangent-space vector to world-space sample vector
|
||||||
|
kexVec3 up = std::abs(N.z) < 0.999f ? kexVec3(0.0f, 0.0f, 1.0f) : kexVec3(1.0f, 0.0f, 0.0f);
|
||||||
|
kexVec3 tangent = kexVec3::Normalize(kexVec3::Cross(up, N));
|
||||||
|
kexVec3 bitangent = kexVec3::Cross(N, tangent);
|
||||||
|
|
||||||
|
kexVec3 sampleVec = tangent * H.x + bitangent * H.y + N * H.z;
|
||||||
|
return kexVec3::Normalize(sampleVec);
|
||||||
|
}
|
||||||
|
|
||||||
|
void kexLightmapBuilder::TraceIndirectLight(surface_t *surface)
|
||||||
|
{
|
||||||
|
if (surface->lightmapNum == -1)
|
||||||
|
return;
|
||||||
|
|
||||||
|
int sampleWidth = surface->lightmapDims[0];
|
||||||
|
int sampleHeight = surface->lightmapDims[1];
|
||||||
|
|
||||||
|
kexVec3 normal = surface->plane.Normal();
|
||||||
|
|
||||||
|
uint16_t *currentTexture = &indirectoutput[surface->lightmapNum * textureWidth * textureHeight * 3];
|
||||||
|
|
||||||
|
for (int i = 0; i < sampleHeight; i++)
|
||||||
|
{
|
||||||
|
for (int j = 0; j < sampleWidth; j++)
|
||||||
|
{
|
||||||
|
kexVec3 pos = surface->lightmapOrigin + normal +
|
||||||
|
(surface->lightmapSteps[0] * (float)j) +
|
||||||
|
(surface->lightmapSteps[1] * (float)i);
|
||||||
|
|
||||||
|
const int SAMPLE_COUNT = 128;// 1024;
|
||||||
|
|
||||||
|
float totalWeight = 0.0f;
|
||||||
|
kexVec3 c(0.0f, 0.0f, 0.0f);
|
||||||
|
|
||||||
|
for (int i = 0; i < SAMPLE_COUNT; i++)
|
||||||
|
{
|
||||||
|
kexVec2 Xi = Hammersley(i, SAMPLE_COUNT);
|
||||||
|
kexVec3 H = ImportanceSampleGGX(Xi, normal, 1.0f);
|
||||||
|
kexVec3 L = kexVec3::Normalize(H * (2.0f * kexVec3::Dot(normal, H)) - normal);
|
||||||
|
|
||||||
|
float NdotL = std::max(kexVec3::Dot(normal, L), 0.0f);
|
||||||
|
if (NdotL > 0.0f)
|
||||||
|
{
|
||||||
|
tracedTexels++;
|
||||||
|
LevelTraceHit hit = map->Trace(pos, pos + L * 1000.0f);
|
||||||
|
if (hit.fraction < 1.0f)
|
||||||
|
{
|
||||||
|
kexVec3 surfaceLight;
|
||||||
|
if (hit.hitSurface->bSky)
|
||||||
|
{
|
||||||
|
surfaceLight = { 0.5f, 0.5f, 0.5f };
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
float u =
|
||||||
|
hit.hitSurface->lightmapCoords[hit.indices[0] * 2] * (1.0f - hit.b - hit.c) +
|
||||||
|
hit.hitSurface->lightmapCoords[hit.indices[1] * 2] * hit.b +
|
||||||
|
hit.hitSurface->lightmapCoords[hit.indices[2] * 2] * hit.c;
|
||||||
|
|
||||||
|
float v =
|
||||||
|
hit.hitSurface->lightmapCoords[hit.indices[0] * 2 + 1] * (1.0f - hit.b - hit.c) +
|
||||||
|
hit.hitSurface->lightmapCoords[hit.indices[1] * 2 + 1] * hit.b +
|
||||||
|
hit.hitSurface->lightmapCoords[hit.indices[2] * 2 + 1] * hit.c;
|
||||||
|
|
||||||
|
int hitTexelX = clamp((int)(u * textureWidth + 0.5f), 0, textureWidth - 1);
|
||||||
|
int hitTexelY = clamp((int)(v * textureHeight + 0.5f), 0, textureHeight - 1);
|
||||||
|
|
||||||
|
uint16_t *hitTexture = textures[hit.hitSurface->lightmapNum].data();
|
||||||
|
uint16_t *hitPixel = hitTexture + (hitTexelX + hitTexelY * textureWidth) * 3;
|
||||||
|
|
||||||
|
float attenuation = (1.0f - hit.fraction);
|
||||||
|
surfaceLight.x = halfToFloat(hitPixel[0]) * attenuation;
|
||||||
|
surfaceLight.y = halfToFloat(hitPixel[1]) * attenuation;
|
||||||
|
surfaceLight.z = halfToFloat(hitPixel[2]) * attenuation;
|
||||||
|
}
|
||||||
|
c += surfaceLight * NdotL;
|
||||||
|
}
|
||||||
|
totalWeight += NdotL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
c = c / totalWeight;
|
||||||
|
|
||||||
|
// convert RGB to bytes
|
||||||
|
int tx = j + surface->lightmapOffs[0];
|
||||||
|
int ty = i + surface->lightmapOffs[1];
|
||||||
|
uint16_t *pixel = currentTexture + (tx + ty * textureWidth) * 3;
|
||||||
|
pixel[0] = floatToHalf(c.x);
|
||||||
|
pixel[1] = floatToHalf(c.y);
|
||||||
|
pixel[2] = floatToHalf(c.z);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void kexLightmapBuilder::LightSurface(const int surfid)
|
void kexLightmapBuilder::LightSurface(const int surfid)
|
||||||
{
|
{
|
||||||
BuildSurfaceParams(surfaces[surfid].get());
|
BuildSurfaceParams(surfaces[surfid].get());
|
||||||
|
@ -552,6 +671,21 @@ void kexLightmapBuilder::LightSurface(const int surfid)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void kexLightmapBuilder::LightIndirect(const int surfid)
|
||||||
|
{
|
||||||
|
TraceIndirectLight(surfaces[surfid].get());
|
||||||
|
|
||||||
|
int numsurfs = surfaces.size();
|
||||||
|
int lastproc = processed * 100 / numsurfs;
|
||||||
|
processed++;
|
||||||
|
int curproc = processed * 100 / numsurfs;
|
||||||
|
if (lastproc != curproc || processed == 1)
|
||||||
|
{
|
||||||
|
float remaining = (float)processed / (float)numsurfs;
|
||||||
|
printf("%i%c surfaces done\r", (int)(remaining * 100.0f), '%');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void kexLightmapBuilder::CreateLightmaps(FLevel &doomMap)
|
void kexLightmapBuilder::CreateLightmaps(FLevel &doomMap)
|
||||||
{
|
{
|
||||||
map = &doomMap;
|
map = &doomMap;
|
||||||
|
@ -577,6 +711,29 @@ void kexLightmapBuilder::CreateLightmaps(FLevel &doomMap)
|
||||||
});
|
});
|
||||||
|
|
||||||
printf("Texels traced: %i \n\n", tracedTexels);
|
printf("Texels traced: %i \n\n", tracedTexels);
|
||||||
|
|
||||||
|
printf("------------- Tracing indirect -------------\n");
|
||||||
|
|
||||||
|
indirectoutput.resize(textures.size() * textureWidth * textureHeight * 3);
|
||||||
|
|
||||||
|
tracedTexels = 0;
|
||||||
|
processed = 0;
|
||||||
|
kexWorker::RunJob(surfaces.size(), [=](int id) {
|
||||||
|
LightIndirect(id);
|
||||||
|
});
|
||||||
|
|
||||||
|
for (size_t i = 0; i < textures.size(); i++)
|
||||||
|
{
|
||||||
|
uint16_t *tex = textures[i].data();
|
||||||
|
uint16_t *indirect = &indirectoutput[i * textureWidth * textureHeight * 3];
|
||||||
|
int count = textureWidth * textureHeight * 3;
|
||||||
|
for (int j = 0; j < count; j++)
|
||||||
|
{
|
||||||
|
tex[j] = floatToHalf(halfToFloat(tex[j]) + halfToFloat(indirect[j]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("Texels traced: %i \n\n", tracedTexels);
|
||||||
}
|
}
|
||||||
|
|
||||||
void kexLightmapBuilder::SetupLightCellGrid()
|
void kexLightmapBuilder::SetupLightCellGrid()
|
||||||
|
@ -585,8 +742,8 @@ void kexLightmapBuilder::SetupLightCellGrid()
|
||||||
float blockWorldSize = LIGHTCELL_BLOCK_SIZE * LIGHTCELL_SIZE;
|
float blockWorldSize = LIGHTCELL_BLOCK_SIZE * LIGHTCELL_SIZE;
|
||||||
grid.x = static_cast<int>(std::floor(worldBBox.min.x / blockWorldSize));
|
grid.x = static_cast<int>(std::floor(worldBBox.min.x / blockWorldSize));
|
||||||
grid.y = static_cast<int>(std::floor(worldBBox.min.y / blockWorldSize));
|
grid.y = static_cast<int>(std::floor(worldBBox.min.y / blockWorldSize));
|
||||||
grid.width = static_cast<int>(std::ceil(worldBBox.max.x / blockWorldSize + 1.0f) - 1.0f) - grid.x;
|
grid.width = static_cast<int>(std::ceil(worldBBox.max.x / blockWorldSize)) - grid.x;
|
||||||
grid.height = static_cast<int>(std::ceil(worldBBox.max.y / blockWorldSize + 1.0f) - 1.0f) - grid.y;
|
grid.height = static_cast<int>(std::ceil(worldBBox.max.y / blockWorldSize)) - grid.y;
|
||||||
grid.blocks.resize(grid.width * grid.height);
|
grid.blocks.resize(grid.width * grid.height);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -641,7 +798,7 @@ void kexLightmapBuilder::LightBlock(int id)
|
||||||
{
|
{
|
||||||
// Allocate space for the cells
|
// Allocate space for the cells
|
||||||
block.z = static_cast<int>(std::floor(minFloor / LIGHTCELL_SIZE));
|
block.z = static_cast<int>(std::floor(minFloor / LIGHTCELL_SIZE));
|
||||||
block.layers = static_cast<int>(std::ceil(maxCeiling / LIGHTCELL_SIZE + 1.0f) - 1.0f) - block.z;
|
block.layers = static_cast<int>(std::ceil(maxCeiling / LIGHTCELL_SIZE)) - block.z;
|
||||||
block.cells.Resize(LIGHTCELL_BLOCK_SIZE * LIGHTCELL_BLOCK_SIZE * block.layers);
|
block.cells.Resize(LIGHTCELL_BLOCK_SIZE * LIGHTCELL_BLOCK_SIZE * block.layers);
|
||||||
|
|
||||||
// Ray trace the cells
|
// Ray trace the cells
|
||||||
|
|
|
@ -79,12 +79,15 @@ private:
|
||||||
|
|
||||||
void BuildSurfaceParams(surface_t *surface);
|
void BuildSurfaceParams(surface_t *surface);
|
||||||
void TraceSurface(surface_t *surface);
|
void TraceSurface(surface_t *surface);
|
||||||
|
void TraceIndirectLight(surface_t *surface);
|
||||||
void SetupLightCellGrid();
|
void SetupLightCellGrid();
|
||||||
void LightBlock(int blockid);
|
void LightBlock(int blockid);
|
||||||
void LightSurface(const int surfid);
|
void LightSurface(const int surfid);
|
||||||
|
void LightIndirect(const int surfid);
|
||||||
|
|
||||||
FLevel *map;
|
FLevel *map;
|
||||||
std::vector<std::vector<uint16_t>> textures;
|
std::vector<std::vector<uint16_t>> textures;
|
||||||
|
std::vector<uint16_t> indirectoutput;
|
||||||
std::vector<std::vector<int>> allocBlocks;
|
std::vector<std::vector<int>> allocBlocks;
|
||||||
int numTextures = 0;
|
int numTextures = 0;
|
||||||
int extraSamples = 2;
|
int extraSamples = 2;
|
||||||
|
|
|
@ -397,7 +397,10 @@ void CreateSurfaces(FLevel &doomMap)
|
||||||
unsigned int pos = doomMap.MeshVertices.Size();
|
unsigned int pos = doomMap.MeshVertices.Size();
|
||||||
|
|
||||||
for (int j = 0; j < numVerts; j++)
|
for (int j = 0; j < numVerts; j++)
|
||||||
|
{
|
||||||
doomMap.MeshVertices.Push(s->verts[j]);
|
doomMap.MeshVertices.Push(s->verts[j]);
|
||||||
|
doomMap.MeshUVIndex.Push(j);
|
||||||
|
}
|
||||||
|
|
||||||
if (s->type == ST_FLOOR || s->type == ST_CEILING)
|
if (s->type == ST_FLOOR || s->type == ST_CEILING)
|
||||||
{
|
{
|
||||||
|
@ -431,5 +434,5 @@ void CreateSurfaces(FLevel &doomMap)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
doomMap.CollisionMesh = std::make_unique<TriangleMeshShape>(&doomMap.MeshVertices[0], doomMap.MeshVertices.Size(), &doomMap.MeshElements[0], doomMap.MeshElements.Size(), &doomMap.MeshSurfaces[0]);
|
doomMap.CollisionMesh = std::make_unique<TriangleMeshShape>(&doomMap.MeshVertices[0], doomMap.MeshVertices.Size(), &doomMap.MeshElements[0], doomMap.MeshElements.Size());
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue