mirror of
https://github.com/ZDoom/ZDRay.git
synced 2024-11-21 19:50:54 +00:00
Add the shaders
This commit is contained in:
parent
0b09fa9793
commit
f8b8005d4a
17 changed files with 1056 additions and 2 deletions
|
@ -63,6 +63,21 @@ set(ZDRAY_SOURCES
|
|||
src/lightmapper/gpuraytracer.h
|
||||
src/lightmapper/stacktrace.cpp
|
||||
src/lightmapper/stacktrace.h
|
||||
src/lightmapper/glsl/binding_lightmapper.glsl.h
|
||||
src/lightmapper/glsl/binding_raytrace.glsl.h
|
||||
src/lightmapper/glsl/binding_textures.glsl.h
|
||||
src/lightmapper/glsl/frag_blur.glsl.h
|
||||
src/lightmapper/glsl/frag_copy.glsl.h
|
||||
src/lightmapper/glsl/frag_raytrace.glsl.h
|
||||
src/lightmapper/glsl/frag_resolve.glsl.h
|
||||
src/lightmapper/glsl/polyfill_rayquery.glsl.h
|
||||
src/lightmapper/glsl/trace_ambient_occlusion.glsl.h
|
||||
src/lightmapper/glsl/trace_levelmesh.glsl.h
|
||||
src/lightmapper/glsl/trace_light.glsl.h
|
||||
src/lightmapper/glsl/trace_sunlight.glsl.h
|
||||
src/lightmapper/glsl/vert_copy.glsl.h
|
||||
src/lightmapper/glsl/vert_raytrace.glsl.h
|
||||
src/lightmapper/glsl/vert_screenquad.glsl.h
|
||||
src/models/model.cpp
|
||||
src/models/model.h
|
||||
src/models/model_md2.h
|
||||
|
@ -97,6 +112,7 @@ source_group("src\\Platform" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/sr
|
|||
source_group("src\\Platform\\Windows" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/src/platform/windows/.+")
|
||||
source_group("src\\Wad" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/src/wad/.+")
|
||||
source_group("src\\Lightmapper" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/src/lightmapper/.+")
|
||||
source_group("src\\Lightmapper\\glsl" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/src/lightmapper/glsl/.+")
|
||||
source_group("src\\Models" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/src/models/.+")
|
||||
|
||||
source_group("thirdparty" REGULAR_EXPRESSION "${CMAKE_CURRENT_SOURCE_DIR}/thirdparty/.+")
|
||||
|
|
91
src/lightmapper/glsl/binding_lightmapper.glsl.h
Normal file
91
src/lightmapper/glsl/binding_lightmapper.glsl.h
Normal file
|
@ -0,0 +1,91 @@
|
|||
static const char* binding_lightmapper_glsl = R"glsl(
|
||||
|
||||
layout(set = 0, binding = 0) uniform Uniforms
|
||||
{
|
||||
vec3 SunDir;
|
||||
float Padding1;
|
||||
vec3 SunColor;
|
||||
float SunIntensity;
|
||||
};
|
||||
|
||||
struct SurfaceInfo
|
||||
{
|
||||
vec3 Normal;
|
||||
float Sky;
|
||||
float SamplingDistance;
|
||||
uint PortalIndex;
|
||||
int TextureIndex;
|
||||
float Alpha;
|
||||
};
|
||||
|
||||
struct PortalInfo
|
||||
{
|
||||
mat4 Transformation;
|
||||
};
|
||||
|
||||
struct LightInfo
|
||||
{
|
||||
vec3 Origin;
|
||||
float Padding0;
|
||||
vec3 RelativeOrigin;
|
||||
float Padding1;
|
||||
float Radius;
|
||||
float Intensity;
|
||||
float InnerAngleCos;
|
||||
float OuterAngleCos;
|
||||
vec3 SpotDir;
|
||||
float Padding2;
|
||||
vec3 Color;
|
||||
float Padding3;
|
||||
};
|
||||
|
||||
layout(set = 0, binding = 1) buffer SurfaceIndexBuffer { uint surfaceIndices[]; };
|
||||
layout(set = 0, binding = 2) buffer SurfaceBuffer { SurfaceInfo surfaces[]; };
|
||||
layout(set = 0, binding = 3) buffer LightBuffer { LightInfo lights[]; };
|
||||
layout(set = 0, binding = 4) buffer PortalBuffer { PortalInfo portals[]; };
|
||||
|
||||
#if defined(USE_DRAWINDIRECT)
|
||||
|
||||
struct LightmapRaytracePC
|
||||
{
|
||||
uint LightStart;
|
||||
uint LightEnd;
|
||||
int SurfaceIndex;
|
||||
int PushPadding1;
|
||||
vec3 WorldToLocal;
|
||||
float TextureSize;
|
||||
vec3 ProjLocalToU;
|
||||
float PushPadding2;
|
||||
vec3 ProjLocalToV;
|
||||
float PushPadding3;
|
||||
float TileX;
|
||||
float TileY;
|
||||
float TileWidth;
|
||||
float TileHeight;
|
||||
};
|
||||
|
||||
layout(std430, set = 0, binding = 5) buffer ConstantsBuffer { LightmapRaytracePC constants[]; };
|
||||
|
||||
#else
|
||||
|
||||
layout(push_constant) uniform LightmapRaytracePC
|
||||
{
|
||||
uint LightStart;
|
||||
uint LightEnd;
|
||||
int SurfaceIndex;
|
||||
int PushPadding1;
|
||||
vec3 WorldToLocal;
|
||||
float TextureSize;
|
||||
vec3 ProjLocalToU;
|
||||
float PushPadding2;
|
||||
vec3 ProjLocalToV;
|
||||
float PushPadding3;
|
||||
float TileX;
|
||||
float TileY;
|
||||
float TileWidth;
|
||||
float TileHeight;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
)glsl";
|
42
src/lightmapper/glsl/binding_raytrace.glsl.h
Normal file
42
src/lightmapper/glsl/binding_raytrace.glsl.h
Normal file
|
@ -0,0 +1,42 @@
|
|||
static const char* binding_raytrace_glsl = R"glsl(
|
||||
|
||||
#if defined(USE_RAYQUERY)
|
||||
|
||||
layout(set = 1, binding = 0) uniform accelerationStructureEXT acc;
|
||||
|
||||
#else
|
||||
|
||||
struct CollisionNode
|
||||
{
|
||||
vec3 center;
|
||||
float padding1;
|
||||
vec3 extents;
|
||||
float padding2;
|
||||
int left;
|
||||
int right;
|
||||
int element_index;
|
||||
int padding3;
|
||||
};
|
||||
|
||||
layout(std430, set = 1, binding = 0) buffer NodeBuffer
|
||||
{
|
||||
int nodesRoot;
|
||||
int nodebufferPadding1;
|
||||
int nodebufferPadding2;
|
||||
int nodebufferPadding3;
|
||||
CollisionNode nodes[];
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
struct SurfaceVertex
|
||||
{
|
||||
vec4 pos;
|
||||
vec2 uv;
|
||||
float Padding1, Padding2;
|
||||
};
|
||||
|
||||
layout(std430, set = 1, binding = 1) buffer VertexBuffer { SurfaceVertex vertices[]; };
|
||||
layout(std430, set = 1, binding = 2) buffer ElementBuffer { int elements[]; };
|
||||
|
||||
)glsl";
|
5
src/lightmapper/glsl/binding_textures.glsl.h
Normal file
5
src/lightmapper/glsl/binding_textures.glsl.h
Normal file
|
@ -0,0 +1,5 @@
|
|||
static const char* binding_textures_glsl = R"glsl(
|
||||
|
||||
layout(set = 2, binding = 0) uniform sampler2D textures[];
|
||||
|
||||
)glsl";
|
35
src/lightmapper/glsl/frag_blur.glsl.h
Normal file
35
src/lightmapper/glsl/frag_blur.glsl.h
Normal file
|
@ -0,0 +1,35 @@
|
|||
static const char* frag_blur_glsl = R"glsl(
|
||||
|
||||
layout(set = 0, binding = 0) uniform sampler2D tex;
|
||||
|
||||
layout(location = 0) in vec2 TexCoord;
|
||||
layout(location = 0) out vec4 fragcolor;
|
||||
|
||||
vec4 centerFragColor;
|
||||
|
||||
vec4 clampedSample(vec4 f)
|
||||
{
|
||||
return f != vec4(0, 0, 0, 0) ? f : centerFragColor;
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
ivec2 size = textureSize(tex, 0);
|
||||
vec2 texCoord = gl_FragCoord.xy / vec2(size);
|
||||
|
||||
centerFragColor = textureOffset(tex, texCoord, ivec2(0, 0));
|
||||
|
||||
#if defined(BLUR_HORIZONTAL)
|
||||
fragcolor =
|
||||
centerFragColor * 0.5 +
|
||||
clampedSample(textureOffset(tex, texCoord, ivec2( 1, 0))) * 0.25 +
|
||||
clampedSample(textureOffset(tex, texCoord, ivec2(-1, 0))) * 0.25;
|
||||
#else
|
||||
fragcolor =
|
||||
centerFragColor * 0.5 +
|
||||
clampedSample(textureOffset(tex, texCoord, ivec2(0, 1))) * 0.25 +
|
||||
clampedSample(textureOffset(tex, texCoord, ivec2(0,-1))) * 0.25;
|
||||
#endif
|
||||
}
|
||||
|
||||
)glsl";
|
13
src/lightmapper/glsl/frag_copy.glsl.h
Normal file
13
src/lightmapper/glsl/frag_copy.glsl.h
Normal file
|
@ -0,0 +1,13 @@
|
|||
static const char* frag_copy_glsl = R"glsl(
|
||||
|
||||
layout(set = 0, binding = 0) uniform sampler2D Tex;
|
||||
|
||||
layout(location = 0) in vec2 TexCoord;
|
||||
layout(location = 0) out vec4 FragColor;
|
||||
|
||||
void main()
|
||||
{
|
||||
FragColor = texture(Tex, TexCoord);
|
||||
}
|
||||
|
||||
)glsl";
|
50
src/lightmapper/glsl/frag_raytrace.glsl.h
Normal file
50
src/lightmapper/glsl/frag_raytrace.glsl.h
Normal file
|
@ -0,0 +1,50 @@
|
|||
static const char* frag_raytrace_glsl = R"glsl(
|
||||
|
||||
#include <shaders/lightmap/binding_lightmapper.glsl>
|
||||
#include <shaders/lightmap/binding_raytrace.glsl>
|
||||
#include <shaders/lightmap/binding_textures.glsl>
|
||||
#include <shaders/lightmap/polyfill_rayquery.glsl>
|
||||
#include <shaders/lightmap/trace_levelmesh.glsl>
|
||||
#include <shaders/lightmap/trace_sunlight.glsl>
|
||||
#include <shaders/lightmap/trace_light.glsl>
|
||||
#include <shaders/lightmap/trace_ambient_occlusion.glsl>
|
||||
|
||||
#if defined(USE_DRAWINDIRECT)
|
||||
|
||||
layout(location = 1) in flat int InstanceIndex;
|
||||
|
||||
#endif
|
||||
|
||||
layout(location = 0) centroid in vec3 worldpos;
|
||||
layout(location = 0) out vec4 fragcolor;
|
||||
|
||||
void main()
|
||||
{
|
||||
#if defined(USE_DRAWINDIRECT)
|
||||
uint LightStart = constants[InstanceIndex].LightStart;
|
||||
uint LightEnd = constants[InstanceIndex].LightEnd;
|
||||
int SurfaceIndex = constants[InstanceIndex].SurfaceIndex;
|
||||
#endif
|
||||
|
||||
vec3 normal = surfaces[SurfaceIndex].Normal;
|
||||
vec3 origin = worldpos + normal * 0.1;
|
||||
|
||||
#if defined(USE_SUNLIGHT)
|
||||
vec3 incoming = TraceSunLight(origin, normal, SurfaceIndex);
|
||||
#else
|
||||
vec3 incoming = vec3(0.0);
|
||||
#endif
|
||||
|
||||
for (uint j = LightStart; j < LightEnd; j++)
|
||||
{
|
||||
incoming += TraceLight(origin, normal, lights[j], SurfaceIndex);
|
||||
}
|
||||
|
||||
#if defined(USE_AO)
|
||||
incoming.rgb *= TraceAmbientOcclusion(origin, normal);
|
||||
#endif
|
||||
|
||||
fragcolor = vec4(incoming, 1.0);
|
||||
}
|
||||
|
||||
)glsl";
|
49
src/lightmapper/glsl/frag_resolve.glsl.h
Normal file
49
src/lightmapper/glsl/frag_resolve.glsl.h
Normal file
|
@ -0,0 +1,49 @@
|
|||
static const char* frag_resolve_glsl = R"glsl(
|
||||
|
||||
layout(set = 0, binding = 0) uniform sampler2DMS tex;
|
||||
|
||||
layout(location = 0) in vec2 TexCoord;
|
||||
layout(location = 0) out vec4 fragcolor;
|
||||
|
||||
vec4 samplePixel(ivec2 pos, int count)
|
||||
{
|
||||
vec4 c = vec4(0.0);
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
c += texelFetch(tex, pos, i);
|
||||
}
|
||||
if (c.a > 0.0)
|
||||
c /= c.a;
|
||||
return c;
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
int count = textureSamples(tex);
|
||||
ivec2 size = textureSize(tex);
|
||||
ivec2 pos = ivec2(gl_FragCoord.xy);
|
||||
|
||||
vec4 c = samplePixel(pos, count);
|
||||
if (c.a == 0.0)
|
||||
{
|
||||
for (int y = -1; y <= 1; y++)
|
||||
{
|
||||
for (int x = -1; x <= 1; x++)
|
||||
{
|
||||
if (x != 0 || y != 0)
|
||||
{
|
||||
ivec2 pos2;
|
||||
pos2.x = clamp(pos.x + x, 0, size.x - 1);
|
||||
pos2.y = clamp(pos.y + y, 0, size.y - 1);
|
||||
c += samplePixel(pos2, count);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (c.a > 0.0)
|
||||
c /= c.a;
|
||||
}
|
||||
|
||||
fragcolor = c;
|
||||
}
|
||||
|
||||
)glsl";
|
269
src/lightmapper/glsl/polyfill_rayquery.glsl.h
Normal file
269
src/lightmapper/glsl/polyfill_rayquery.glsl.h
Normal file
|
@ -0,0 +1,269 @@
|
|||
static const char* polyfill_rayquery_glsl = R"glsl(
|
||||
|
||||
#if defined(USE_RAYQUERY)
|
||||
|
||||
int TraceFirstHitTriangleNoPortal(vec3 origin, float tmin, vec3 dir, float tmax, out float t, out vec3 primitiveWeights)
|
||||
{
|
||||
rayQueryEXT rayQuery;
|
||||
rayQueryInitializeEXT(rayQuery, acc, gl_RayFlagsCullBackFacingTrianglesEXT, 0xFF, origin, tmin, dir, tmax);
|
||||
|
||||
while(rayQueryProceedEXT(rayQuery))
|
||||
{
|
||||
if (rayQueryGetIntersectionTypeEXT(rayQuery, false) == gl_RayQueryCommittedIntersectionTriangleEXT)
|
||||
{
|
||||
rayQueryConfirmIntersectionEXT(rayQuery);
|
||||
}
|
||||
}
|
||||
|
||||
if (rayQueryGetIntersectionTypeEXT(rayQuery, true) == gl_RayQueryCommittedIntersectionTriangleEXT)
|
||||
{
|
||||
t = rayQueryGetIntersectionTEXT(rayQuery, true);
|
||||
|
||||
primitiveWeights.xy = rayQueryGetIntersectionBarycentricsEXT(rayQuery, true);
|
||||
primitiveWeights.z = 1.0 - primitiveWeights.x - primitiveWeights.y;
|
||||
|
||||
return rayQueryGetIntersectionPrimitiveIndexEXT(rayQuery, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
t = tmax;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
bool TraceAnyHit(vec3 origin, float tmin, vec3 dir, float tmax)
|
||||
{
|
||||
rayQueryEXT rayQuery;
|
||||
rayQueryInitializeEXT(rayQuery, acc, gl_RayFlagsTerminateOnFirstHitEXT | gl_RayFlagsCullBackFacingTrianglesEXT, 0xFF, origin, tmin, dir, tmax);
|
||||
while(rayQueryProceedEXT(rayQuery)) { }
|
||||
return rayQueryGetIntersectionTypeEXT(rayQuery, true) != gl_RayQueryCommittedIntersectionNoneEXT;
|
||||
}
|
||||
*/
|
||||
|
||||
#else
|
||||
|
||||
struct RayBBox
|
||||
{
|
||||
vec3 start, end;
|
||||
vec3 c, w, v;
|
||||
};
|
||||
|
||||
RayBBox create_ray(vec3 ray_start, vec3 ray_end)
|
||||
{
|
||||
RayBBox ray;
|
||||
ray.start = ray_start;
|
||||
ray.end = ray_end;
|
||||
ray.c = (ray_start + ray_end) * 0.5;
|
||||
ray.w = ray_end - ray.c;
|
||||
ray.v = abs(ray.w);
|
||||
return ray;
|
||||
}
|
||||
|
||||
bool overlap_bv_ray(RayBBox ray, int a)
|
||||
{
|
||||
vec3 v = ray.v;
|
||||
vec3 w = ray.w;
|
||||
vec3 h = nodes[a].extents;
|
||||
vec3 c = ray.c - nodes[a].center;
|
||||
|
||||
if (abs(c.x) > v.x + h.x ||
|
||||
abs(c.y) > v.y + h.y ||
|
||||
abs(c.z) > v.z + h.z)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (abs(c.y * w.z - c.z * w.y) > h.y * v.z + h.z * v.y ||
|
||||
abs(c.x * w.z - c.z * w.x) > h.x * v.z + h.z * v.x ||
|
||||
abs(c.x * w.y - c.y * w.x) > h.x * v.y + h.y * v.x)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#define FLT_EPSILON 1.192092896e-07F // smallest such that 1.0+FLT_EPSILON != 1.0
|
||||
|
||||
float intersect_triangle_ray(RayBBox ray, int a, out float barycentricB, out float barycentricC)
|
||||
{
|
||||
int start_element = nodes[a].element_index;
|
||||
|
||||
vec3 p[3];
|
||||
p[0] = vertices[elements[start_element]].pos.xyz;
|
||||
p[1] = vertices[elements[start_element + 1]].pos.xyz;
|
||||
p[2] = vertices[elements[start_element + 2]].pos.xyz;
|
||||
|
||||
// Moeller-Trumbore ray-triangle intersection algorithm:
|
||||
|
||||
vec3 D = ray.end - ray.start;
|
||||
|
||||
// Find vectors for two edges sharing p[0]
|
||||
vec3 e1 = p[1] - p[0];
|
||||
vec3 e2 = p[2] - p[0];
|
||||
|
||||
// Begin calculating determinant - also used to calculate u parameter
|
||||
vec3 P = cross(D, e2);
|
||||
float det = dot(e1, P);
|
||||
|
||||
// Backface check
|
||||
if (det < 0.0f)
|
||||
return 1.0f;
|
||||
|
||||
// If determinant is near zero, ray lies in plane of triangle
|
||||
if (det > -FLT_EPSILON && det < FLT_EPSILON)
|
||||
return 1.0f;
|
||||
|
||||
float inv_det = 1.0f / det;
|
||||
|
||||
// Calculate distance from p[0] to ray origin
|
||||
vec3 T = ray.start - p[0];
|
||||
|
||||
// Calculate u parameter and test bound
|
||||
float u = dot(T, P) * inv_det;
|
||||
|
||||
// Check if the intersection lies outside of the triangle
|
||||
if (u < 0.f || u > 1.f)
|
||||
return 1.0f;
|
||||
|
||||
// Prepare to test v parameter
|
||||
vec3 Q = cross(T, e1);
|
||||
|
||||
// Calculate V parameter and test bound
|
||||
float v = dot(D, Q) * inv_det;
|
||||
|
||||
// The intersection lies outside of the triangle
|
||||
if (v < 0.f || u + v > 1.f)
|
||||
return 1.0f;
|
||||
|
||||
float t = dot(e2, Q) * inv_det;
|
||||
if (t <= FLT_EPSILON)
|
||||
return 1.0f;
|
||||
|
||||
// Return hit location on triangle in barycentric coordinates
|
||||
barycentricB = u;
|
||||
barycentricC = v;
|
||||
return t;
|
||||
}
|
||||
|
||||
bool is_leaf(int node_index)
|
||||
{
|
||||
return nodes[node_index].element_index != -1;
|
||||
}
|
||||
|
||||
/*
|
||||
bool TraceAnyHit(vec3 origin, float tmin, vec3 dir, float tmax)
|
||||
{
|
||||
if (tmax <= 0.0f)
|
||||
return false;
|
||||
|
||||
RayBBox ray = create_ray(origin, origin + dir * tmax);
|
||||
tmin /= tmax;
|
||||
|
||||
int stack[64];
|
||||
int stackIndex = 0;
|
||||
stack[stackIndex++] = nodesRoot;
|
||||
do
|
||||
{
|
||||
int a = stack[--stackIndex];
|
||||
if (overlap_bv_ray(ray, a))
|
||||
{
|
||||
if (is_leaf(a))
|
||||
{
|
||||
float baryB, baryC;
|
||||
float t = intersect_triangle_ray(ray, a, baryB, baryC);
|
||||
if (t >= tmin && t < 1.0)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
stack[stackIndex++] = nodes[a].right;
|
||||
stack[stackIndex++] = nodes[a].left;
|
||||
}
|
||||
}
|
||||
} while (stackIndex > 0);
|
||||
return false;
|
||||
}
|
||||
*/
|
||||
|
||||
struct TraceHit
|
||||
{
|
||||
float fraction;
|
||||
int triangle;
|
||||
float b;
|
||||
float c;
|
||||
};
|
||||
|
||||
TraceHit find_first_hit(RayBBox ray)
|
||||
{
|
||||
TraceHit hit;
|
||||
hit.fraction = 1.0;
|
||||
hit.triangle = -1;
|
||||
hit.b = 0.0;
|
||||
hit.c = 0.0;
|
||||
|
||||
int stack[64];
|
||||
int stackIndex = 0;
|
||||
stack[stackIndex++] = nodesRoot;
|
||||
do
|
||||
{
|
||||
int a = stack[--stackIndex];
|
||||
if (overlap_bv_ray(ray, a))
|
||||
{
|
||||
if (is_leaf(a))
|
||||
{
|
||||
float baryB, baryC;
|
||||
float t = intersect_triangle_ray(ray, a, baryB, baryC);
|
||||
if (t < hit.fraction)
|
||||
{
|
||||
hit.fraction = t;
|
||||
hit.triangle = nodes[a].element_index / 3;
|
||||
hit.b = baryB;
|
||||
hit.c = baryC;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
stack[stackIndex++] = nodes[a].right;
|
||||
stack[stackIndex++] = nodes[a].left;
|
||||
}
|
||||
}
|
||||
} while (stackIndex > 0);
|
||||
return hit;
|
||||
}
|
||||
|
||||
int TraceFirstHitTriangleNoPortal(vec3 origin, float tmin, vec3 dir, float tmax, out float tparam, out vec3 primitiveWeights)
|
||||
{
|
||||
// Perform segmented tracing to keep the ray AABB box smaller
|
||||
vec3 ray_start = origin;
|
||||
vec3 ray_end = origin + dir * tmax;
|
||||
vec3 ray_dir = dir;
|
||||
float tracedist = tmax;
|
||||
float segmentlen = max(200.0, tracedist / 20.0);
|
||||
for (float t = 0.0; t < tracedist; t += segmentlen)
|
||||
{
|
||||
float segstart = t;
|
||||
float segend = min(t + segmentlen, tracedist);
|
||||
|
||||
RayBBox ray = create_ray(ray_start + ray_dir * segstart, ray_start + ray_dir * segend);
|
||||
TraceHit hit = find_first_hit(ray);
|
||||
if (hit.fraction < 1.0)
|
||||
{
|
||||
tparam = hit.fraction = segstart * (1.0 - hit.fraction) + segend * hit.fraction;
|
||||
primitiveWeights.x = hit.b;
|
||||
primitiveWeights.y = hit.c;
|
||||
primitiveWeights.z = 1.0 - hit.b - hit.c;
|
||||
return hit.triangle;
|
||||
}
|
||||
}
|
||||
|
||||
tparam = tracedist;
|
||||
return -1;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
)glsl";
|
57
src/lightmapper/glsl/trace_ambient_occlusion.glsl.h
Normal file
57
src/lightmapper/glsl/trace_ambient_occlusion.glsl.h
Normal file
|
@ -0,0 +1,57 @@
|
|||
static const char* trace_ambient_occlusion_glsl = R"glsl(
|
||||
|
||||
vec2 Hammersley(uint i, uint N);
|
||||
float RadicalInverse_VdC(uint bits);
|
||||
|
||||
float TraceAmbientOcclusion(vec3 origin, vec3 normal)
|
||||
{
|
||||
const float minDistance = 0.05;
|
||||
const float aoDistance = 100;
|
||||
const int SampleCount = 128;
|
||||
|
||||
vec3 N = normal;
|
||||
vec3 up = abs(N.x) < abs(N.y) ? vec3(1.0, 0.0, 0.0) : vec3(0.0, 1.0, 0.0);
|
||||
vec3 tangent = normalize(cross(up, N));
|
||||
vec3 bitangent = cross(N, tangent);
|
||||
|
||||
float ambience = 0.0f;
|
||||
for (uint i = 0; i < SampleCount; i++)
|
||||
{
|
||||
vec2 Xi = Hammersley(i, SampleCount);
|
||||
vec3 H = normalize(vec3(Xi.x * 2.0f - 1.0f, Xi.y * 2.0f - 1.0f, 1.5 - length(Xi)));
|
||||
vec3 L = H.x * tangent + H.y * bitangent + H.z * N;
|
||||
|
||||
float hitDistance;
|
||||
int primitiveID = TraceFirstHitTriangleT(origin, minDistance, L, aoDistance, hitDistance);
|
||||
if (primitiveID != -1)
|
||||
{
|
||||
SurfaceInfo surface = surfaces[surfaceIndices[primitiveID]];
|
||||
if (surface.Sky == 0.0)
|
||||
{
|
||||
ambience += clamp(hitDistance / aoDistance, 0.0, 1.0);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ambience += 1.0;
|
||||
}
|
||||
}
|
||||
return ambience / float(SampleCount);
|
||||
}
|
||||
|
||||
vec2 Hammersley(uint i, uint N)
|
||||
{
|
||||
return vec2(float(i) / float(N), RadicalInverse_VdC(i));
|
||||
}
|
||||
|
||||
float RadicalInverse_VdC(uint 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
|
||||
}
|
||||
|
||||
)glsl";
|
139
src/lightmapper/glsl/trace_levelmesh.glsl.h
Normal file
139
src/lightmapper/glsl/trace_levelmesh.glsl.h
Normal file
|
@ -0,0 +1,139 @@
|
|||
static const char* trace_levelmesh_glsl = R"glsl(
|
||||
|
||||
vec4 rayColor;
|
||||
|
||||
vec4 alphaBlend(vec4 a, vec4 b);
|
||||
vec4 BeerLambertSimple(vec4 medium, vec4 ray_color);
|
||||
vec4 blend(vec4 a, vec4 b);
|
||||
|
||||
int TraceFirstHitTriangleT(vec3 origin, float tmin, vec3 dir, float tmax, out float t)
|
||||
{
|
||||
int primitiveID = -1;
|
||||
vec3 primitiveWeights;
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
primitiveID = TraceFirstHitTriangleNoPortal(origin, tmin, dir, tmax, t, primitiveWeights);
|
||||
|
||||
if(primitiveID < 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
SurfaceInfo surface = surfaces[surfaceIndices[primitiveID]];
|
||||
|
||||
if(surface.PortalIndex == 0)
|
||||
{
|
||||
int index = primitiveID * 3;
|
||||
vec2 uv = vertices[elements[index + 1]].uv * primitiveWeights.x + vertices[elements[index + 2]].uv * primitiveWeights.y + vertices[elements[index + 0]].uv * primitiveWeights.z;
|
||||
|
||||
if (surface.TextureIndex < 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
vec4 color = texture(textures[surface.TextureIndex], uv);
|
||||
color.w *= surface.Alpha;
|
||||
|
||||
if (color.w > 0.999 || all(lessThan(rayColor.rgb, vec3(0.001))))
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
rayColor = blend(color, rayColor);
|
||||
}
|
||||
|
||||
// Portal was hit: Apply transformation onto the ray
|
||||
mat4 transformationMatrix = portals[surface.PortalIndex].Transformation;
|
||||
|
||||
origin = (transformationMatrix * vec4(origin + dir * t, 1.0)).xyz;
|
||||
dir = (transformationMatrix * vec4(dir, 0.0)).xyz;
|
||||
tmax -= t;
|
||||
}
|
||||
return primitiveID;
|
||||
}
|
||||
|
||||
int TraceFirstHitTriangle(vec3 origin, float tmin, vec3 dir, float tmax)
|
||||
{
|
||||
float t;
|
||||
return TraceFirstHitTriangleT(origin, tmin, dir, tmax, t);
|
||||
}
|
||||
|
||||
bool TraceAnyHit(vec3 origin, float tmin, vec3 dir, float tmax)
|
||||
{
|
||||
return TraceFirstHitTriangle(origin, tmin, dir, tmax) >= 0;
|
||||
}
|
||||
|
||||
bool TracePoint(vec3 origin, vec3 target, float tmin, vec3 dir, float tmax)
|
||||
{
|
||||
int primitiveID;
|
||||
float t;
|
||||
vec3 primitiveWeights;
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
t = tmax;
|
||||
primitiveID = TraceFirstHitTriangleNoPortal(origin, tmin, dir, tmax, t, primitiveWeights);
|
||||
|
||||
origin += dir * t;
|
||||
tmax -= t;
|
||||
|
||||
if(primitiveID < 0)
|
||||
{
|
||||
// We didn't hit anything
|
||||
break;
|
||||
}
|
||||
|
||||
SurfaceInfo surface = surfaces[surfaceIndices[primitiveID]];
|
||||
|
||||
if (surface.PortalIndex == 0)
|
||||
{
|
||||
int index = primitiveID * 3;
|
||||
vec2 uv = vertices[elements[index + 1]].uv * primitiveWeights.x + vertices[elements[index + 2]].uv * primitiveWeights.y + vertices[elements[index + 0]].uv * primitiveWeights.z;
|
||||
|
||||
if (surface.TextureIndex < 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
vec4 color = texture(textures[surface.TextureIndex], uv);
|
||||
color.w *= surface.Alpha;
|
||||
|
||||
if (color.w > 0.999 || all(lessThan(rayColor.rgb, vec3(0.001))))
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
rayColor = blend(color, rayColor);
|
||||
}
|
||||
|
||||
if(dot(surface.Normal, dir) >= 0.0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
mat4 transformationMatrix = portals[surface.PortalIndex].Transformation;
|
||||
origin = (transformationMatrix * vec4(origin, 1.0)).xyz;
|
||||
dir = (transformationMatrix * vec4(dir, 0.0)).xyz;
|
||||
}
|
||||
|
||||
return distance(origin, target) <= 1.0;
|
||||
}
|
||||
|
||||
vec4 alphaBlend(vec4 a, vec4 b)
|
||||
{
|
||||
float na = a.w + b.w * (1.0 - a.w);
|
||||
return vec4((a.xyz * a.w + b.xyz * b.w * (1.0 - a.w)) / na, max(0.001, na));
|
||||
}
|
||||
|
||||
vec4 BeerLambertSimple(vec4 medium, vec4 ray_color) // based on Beer-Lambert law
|
||||
{
|
||||
float z = medium.w;
|
||||
ray_color.rgb *= exp(-medium.rgb * vec3(z));
|
||||
return ray_color;
|
||||
}
|
||||
|
||||
vec4 blend(vec4 a, vec4 b)
|
||||
{
|
||||
return BeerLambertSimple(vec4(1.0 - a.rgb, a.w), b);
|
||||
}
|
||||
|
||||
)glsl";
|
79
src/lightmapper/glsl/trace_light.glsl.h
Normal file
79
src/lightmapper/glsl/trace_light.glsl.h
Normal file
|
@ -0,0 +1,79 @@
|
|||
static const char* trace_light_glsl = R"glsl(
|
||||
|
||||
vec2 getVogelDiskSample(int sampleIndex, int sampleCount, float phi);
|
||||
|
||||
vec3 TraceLight(vec3 origin, vec3 normal, LightInfo light, int surfaceIndex)
|
||||
{
|
||||
const float minDistance = 0.01;
|
||||
vec3 incoming = vec3(0.0);
|
||||
float dist = distance(light.RelativeOrigin, origin);
|
||||
if (dist > minDistance && dist < light.Radius)
|
||||
{
|
||||
vec3 dir = normalize(light.RelativeOrigin - origin);
|
||||
|
||||
float distAttenuation = max(1.0 - (dist / light.Radius), 0.0);
|
||||
float angleAttenuation = 1.0f;
|
||||
if (surfaceIndex >= 0)
|
||||
{
|
||||
angleAttenuation = max(dot(normal, dir), 0.0);
|
||||
}
|
||||
float spotAttenuation = 1.0;
|
||||
if (light.OuterAngleCos > -1.0)
|
||||
{
|
||||
float cosDir = dot(dir, light.SpotDir);
|
||||
spotAttenuation = smoothstep(light.OuterAngleCos, light.InnerAngleCos, cosDir);
|
||||
spotAttenuation = max(spotAttenuation, 0.0);
|
||||
}
|
||||
|
||||
float attenuation = distAttenuation * angleAttenuation * spotAttenuation;
|
||||
if (attenuation > 0.0)
|
||||
{
|
||||
#if defined(USE_SOFTSHADOWS)
|
||||
|
||||
vec3 v = (abs(dir.x) > abs(dir.y)) ? vec3(0.0, 1.0, 0.0) : vec3(1.0, 0.0, 0.0);
|
||||
vec3 xdir = normalize(cross(dir, v));
|
||||
vec3 ydir = cross(dir, xdir);
|
||||
|
||||
float lightsize = 10;
|
||||
int step_count = 10;
|
||||
for (int i = 0; i < step_count; i++)
|
||||
{
|
||||
vec2 gridoffset = getVogelDiskSample(i, step_count, gl_FragCoord.x + gl_FragCoord.y * 13.37) * lightsize;
|
||||
vec3 pos = light.Origin + xdir * gridoffset.x + ydir * gridoffset.y;
|
||||
|
||||
rayColor = vec4(light.Color.rgb, 1.0);
|
||||
if (TracePoint(origin, pos, minDistance, normalize(pos - origin), distance(origin, pos)))
|
||||
{
|
||||
incoming.rgb += (rayColor.rgb * rayColor.w) * (attenuation * light.Intensity) / float(step_count);
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
rayColor = vec4(light.Color.rgb, 1.0);
|
||||
if(TracePoint(origin, light.Origin, minDistance, dir, dist))
|
||||
{
|
||||
incoming.rgb += (rayColor.rgb * rayColor.w) * (attenuation * light.Intensity);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
return incoming;
|
||||
}
|
||||
|
||||
vec2 getVogelDiskSample(int sampleIndex, int sampleCount, float phi)
|
||||
{
|
||||
const float goldenAngle = radians(180.0) * (3.0 - sqrt(5.0));
|
||||
float sampleIndexF = float(sampleIndex);
|
||||
float sampleCountF = float(sampleCount);
|
||||
|
||||
float r = sqrt((sampleIndexF + 0.5) / sampleCountF); // Assuming index and count are positive
|
||||
float theta = sampleIndexF * goldenAngle + phi;
|
||||
|
||||
float sine = sin(theta);
|
||||
float cosine = cos(theta);
|
||||
|
||||
return vec2(cosine, sine) * r;
|
||||
}
|
||||
|
||||
)glsl";
|
60
src/lightmapper/glsl/trace_sunlight.glsl.h
Normal file
60
src/lightmapper/glsl/trace_sunlight.glsl.h
Normal file
|
@ -0,0 +1,60 @@
|
|||
static const char* trace_sunlight_glsl = R"glsl(
|
||||
|
||||
vec2 getVogelDiskSample(int sampleIndex, int sampleCount, float phi);
|
||||
|
||||
vec3 TraceSunLight(vec3 origin, vec3 normal, int surfaceIndex)
|
||||
{
|
||||
float angleAttenuation = 1.0f;
|
||||
if (surfaceIndex >= 0)
|
||||
{
|
||||
angleAttenuation = max(dot(normal, SunDir), 0.0);
|
||||
if (angleAttenuation == 0.0)
|
||||
return vec3(0.0);
|
||||
}
|
||||
|
||||
const float minDistance = 0.01;
|
||||
vec3 incoming = vec3(0.0);
|
||||
const float dist = 32768.0;
|
||||
|
||||
#if defined(USE_SOFTSHADOWS)
|
||||
|
||||
vec3 target = origin + SunDir * dist;
|
||||
vec3 dir = SunDir;
|
||||
vec3 v = (abs(dir.x) > abs(dir.y)) ? vec3(0.0, 1.0, 0.0) : vec3(1.0, 0.0, 0.0);
|
||||
vec3 xdir = normalize(cross(dir, v));
|
||||
vec3 ydir = cross(dir, xdir);
|
||||
|
||||
float lightsize = 100;
|
||||
int step_count = 10;
|
||||
for (int i = 0; i < step_count; i++)
|
||||
{
|
||||
vec2 gridoffset = getVogelDiskSample(i, step_count, gl_FragCoord.x + gl_FragCoord.y * 13.37) * lightsize;
|
||||
vec3 pos = target + xdir * gridoffset.x + ydir * gridoffset.y;
|
||||
|
||||
rayColor = vec4(SunColor.rgb * SunIntensity, 1.0);
|
||||
|
||||
int primitiveID = TraceFirstHitTriangle(origin, minDistance, normalize(pos - origin), dist);
|
||||
if (primitiveID != -1)
|
||||
{
|
||||
SurfaceInfo surface = surfaces[surfaceIndices[primitiveID]];
|
||||
incoming.rgb += rayColor.rgb * rayColor.w * surface.Sky / float(step_count);
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
rayColor = vec4(SunColor.rgb * SunIntensity, 1.0);
|
||||
|
||||
int primitiveID = TraceFirstHitTriangle(origin, minDistance, SunDir, dist);
|
||||
if (primitiveID != -1)
|
||||
{
|
||||
SurfaceInfo surface = surfaces[surfaceIndices[primitiveID]];
|
||||
incoming.rgb = rayColor.rgb * rayColor.w * surface.Sky;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
return incoming * angleAttenuation;
|
||||
}
|
||||
|
||||
)glsl";
|
44
src/lightmapper/glsl/vert_copy.glsl.h
Normal file
44
src/lightmapper/glsl/vert_copy.glsl.h
Normal file
|
@ -0,0 +1,44 @@
|
|||
static const char* vert_copy_glsl = R"glsl(
|
||||
|
||||
layout(push_constant) uniform PushConstants
|
||||
{
|
||||
int SrcTexSize;
|
||||
int DestTexSize;
|
||||
int Padding1;
|
||||
int Padding2;
|
||||
};
|
||||
|
||||
struct TileCopy
|
||||
{
|
||||
ivec2 SrcPos;
|
||||
ivec2 DestPos;
|
||||
ivec2 TileSize;
|
||||
int Padding1, Padding2;
|
||||
};
|
||||
|
||||
layout(std430, set = 0, binding = 1) buffer CopyBuffer
|
||||
{
|
||||
TileCopy tiles[];
|
||||
};
|
||||
|
||||
layout(location = 0) out vec2 TexCoord;
|
||||
|
||||
vec2 positions[4] = vec2[](
|
||||
vec2(0.0, 0.0),
|
||||
vec2(1.0, 0.0),
|
||||
vec2(0.0, 1.0),
|
||||
vec2(1.0, 1.0)
|
||||
);
|
||||
|
||||
void main()
|
||||
{
|
||||
TileCopy tile = tiles[gl_InstanceIndex];
|
||||
vec2 uv = positions[gl_VertexIndex];
|
||||
vec2 src = (vec2(tile.SrcPos) + uv * vec2(tile.TileSize)) / float(SrcTexSize);
|
||||
vec2 dest = (vec2(tile.DestPos) + uv * vec2(tile.TileSize)) / float(DestTexSize);
|
||||
|
||||
gl_Position = vec4(dest * 2.0 - 1.0, 0.0, 1.0);
|
||||
TexCoord = src;
|
||||
}
|
||||
|
||||
)glsl";
|
44
src/lightmapper/glsl/vert_raytrace.glsl.h
Normal file
44
src/lightmapper/glsl/vert_raytrace.glsl.h
Normal file
|
@ -0,0 +1,44 @@
|
|||
static const char* vert_raytrace_glsl = R"glsl(
|
||||
|
||||
#include <shaders/lightmap/binding_lightmapper.glsl>
|
||||
|
||||
layout(location = 0) in vec3 aPosition;
|
||||
layout(location = 0) out vec3 worldpos;
|
||||
|
||||
#if defined(USE_DRAWINDIRECT)
|
||||
layout(location = 1) out flat int InstanceIndex;
|
||||
#endif
|
||||
|
||||
void main()
|
||||
{
|
||||
#if defined(USE_DRAWINDIRECT)
|
||||
vec3 WorldToLocal = constants[gl_InstanceIndex].WorldToLocal;
|
||||
float TextureSize = constants[gl_InstanceIndex].TextureSize;
|
||||
vec3 ProjLocalToU = constants[gl_InstanceIndex].ProjLocalToU;
|
||||
vec3 ProjLocalToV = constants[gl_InstanceIndex].ProjLocalToV;
|
||||
float TileX = constants[gl_InstanceIndex].TileX;
|
||||
float TileY = constants[gl_InstanceIndex].TileY;
|
||||
float TileWidth = constants[gl_InstanceIndex].TileWidth;
|
||||
float TileHeight = constants[gl_InstanceIndex].TileHeight;
|
||||
InstanceIndex = gl_InstanceIndex;
|
||||
#endif
|
||||
|
||||
worldpos = aPosition;
|
||||
|
||||
// Project to position relative to tile
|
||||
vec3 localPos = aPosition - WorldToLocal;
|
||||
float x = dot(localPos, ProjLocalToU);
|
||||
float y = dot(localPos, ProjLocalToV);
|
||||
|
||||
// Find the position in the output texture
|
||||
gl_Position = vec4(vec2(TileX + x, TileY + y) / TextureSize * 2.0 - 1.0, 0.0, 1.0);
|
||||
|
||||
// Clip all surfaces to the edge of the tile (effectly we are applying a viewport/scissor to the tile)
|
||||
// Note: the tile has a 1px border around it that we also draw into
|
||||
gl_ClipDistance[0] = x + 1.0;
|
||||
gl_ClipDistance[1] = y + 1.0;
|
||||
gl_ClipDistance[2] = TileWidth + 1.0 - x;
|
||||
gl_ClipDistance[3] = TileHeight + 1.0 - y;
|
||||
}
|
||||
|
||||
)glsl";
|
23
src/lightmapper/glsl/vert_screenquad.glsl.h
Normal file
23
src/lightmapper/glsl/vert_screenquad.glsl.h
Normal file
|
@ -0,0 +1,23 @@
|
|||
static const char* vert_screenquad_glsl = R"glsl(
|
||||
|
||||
layout(location = 0) out vec2 TexCoord;
|
||||
|
||||
vec2 positions[3] = vec2[](
|
||||
vec2(-1.0, -1.0),
|
||||
vec2( 3.0, -1.0),
|
||||
vec2(-1.0, 3.0)
|
||||
);
|
||||
|
||||
vec2 uvs[3] = vec2[](
|
||||
vec2(0.0, 0.0),
|
||||
vec2(2.0, 0.0),
|
||||
vec2(0.0, 2.0)
|
||||
);
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_Position = vec4(positions[gl_VertexIndex], 0.0, 1.0);
|
||||
TexCoord = uvs[gl_VertexIndex];
|
||||
}
|
||||
|
||||
)glsl";
|
|
@ -5,6 +5,23 @@
|
|||
#include "zvulkan/vulkanbuilders.h"
|
||||
#include "Framework/halffloat.h"
|
||||
#include "framework/zstring.h"
|
||||
#include <map>
|
||||
|
||||
#include "glsl/binding_lightmapper.glsl.h"
|
||||
#include "glsl/binding_raytrace.glsl.h"
|
||||
#include "glsl/binding_textures.glsl.h"
|
||||
#include "glsl/frag_blur.glsl.h"
|
||||
#include "glsl/frag_copy.glsl.h"
|
||||
#include "glsl/frag_raytrace.glsl.h"
|
||||
#include "glsl/frag_resolve.glsl.h"
|
||||
#include "glsl/polyfill_rayquery.glsl.h"
|
||||
#include "glsl/trace_ambient_occlusion.glsl.h"
|
||||
#include "glsl/trace_levelmesh.glsl.h"
|
||||
#include "glsl/trace_light.glsl.h"
|
||||
#include "glsl/trace_sunlight.glsl.h"
|
||||
#include "glsl/vert_copy.glsl.h"
|
||||
#include "glsl/vert_raytrace.glsl.h"
|
||||
#include "glsl/vert_screenquad.glsl.h"
|
||||
|
||||
#define USE_DRAWINDIRECT
|
||||
|
||||
|
@ -626,9 +643,30 @@ int VkLightmap::GetRaytracePipelineIndex()
|
|||
|
||||
FString VkLightmap::LoadPrivateShaderLump(const char* lumpname)
|
||||
{
|
||||
// To do: load the shader
|
||||
static std::map<FString, FString> sources =
|
||||
{
|
||||
{ "shaders/lightmap/binding_lightmapper.glsl", binding_lightmapper_glsl },
|
||||
{ "shaders/lightmap/binding_raytrace.glsl", binding_raytrace_glsl },
|
||||
{ "shaders/lightmap/binding_textures.glsl", binding_textures_glsl },
|
||||
{ "shaders/lightmap/frag_blur.glsl", frag_blur_glsl },
|
||||
{ "shaders/lightmap/frag_copy.glsl", frag_copy_glsl },
|
||||
{ "shaders/lightmap/frag_raytrace.glsl", frag_raytrace_glsl },
|
||||
{ "shaders/lightmap/frag_resolve.glsl", frag_resolve_glsl },
|
||||
{ "shaders/lightmap/polyfill_rayquery.glsl", polyfill_rayquery_glsl },
|
||||
{ "shaders/lightmap/trace_ambient_occlusion.glsl", trace_ambient_occlusion_glsl },
|
||||
{ "shaders/lightmap/trace_levelmesh.glsl", trace_levelmesh_glsl },
|
||||
{ "shaders/lightmap/trace_light.glsl", trace_light_glsl },
|
||||
{ "shaders/lightmap/trace_sunlight.glsl", trace_sunlight_glsl },
|
||||
{ "shaders/lightmap/vert_copy.glsl", vert_copy_glsl },
|
||||
{ "shaders/lightmap/vert_raytrace.glsl", vert_raytrace_glsl },
|
||||
{ "shaders/lightmap/vert_screenquad.glsl", vert_screenquad_glsl }
|
||||
};
|
||||
|
||||
return FString();
|
||||
auto it = sources.find(lumpname);
|
||||
if (it != sources.end())
|
||||
return it->second;
|
||||
else
|
||||
return FString();
|
||||
}
|
||||
|
||||
ShaderIncludeResult VkLightmap::OnInclude(FString headerName, FString includerName, size_t depth, bool system)
|
||||
|
|
Loading…
Reference in a new issue