mirror of
https://github.com/ZDoom/ZDRay.git
synced 2024-11-24 21:01:15 +00:00
Add ambient occlusion
This commit is contained in:
parent
b67f265c75
commit
bc0f419fff
2 changed files with 84 additions and 3 deletions
|
@ -61,6 +61,9 @@ layout(push_constant) uniform PushConstants
|
|||
layout(location = 0) in vec3 worldpos;
|
||||
layout(location = 0) out vec4 fragcolor;
|
||||
|
||||
vec2 Hammersley(uint i, uint N);
|
||||
float RadicalInverse_VdC(uint bits);
|
||||
|
||||
void main()
|
||||
{
|
||||
const float minDistance = 0.01;
|
||||
|
@ -137,7 +140,72 @@ void main()
|
|||
}
|
||||
}
|
||||
|
||||
// Ambient occlusion
|
||||
if (SurfaceIndex >= 0)
|
||||
{
|
||||
const float minDistance = 0.05;
|
||||
const float aoDistance = 100;
|
||||
const int SampleCount = 2048;
|
||||
|
||||
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;
|
||||
|
||||
rayQueryEXT rayQuery;
|
||||
rayQueryInitializeEXT(rayQuery, acc, gl_RayFlagsTerminateOnFirstHitEXT, 0xFF, origin, minDistance, L, aoDistance);
|
||||
|
||||
while(rayQueryProceedEXT(rayQuery))
|
||||
{
|
||||
if (rayQueryGetIntersectionTypeEXT(rayQuery, false) == gl_RayQueryCommittedIntersectionTriangleEXT)
|
||||
{
|
||||
rayQueryConfirmIntersectionEXT(rayQuery);
|
||||
}
|
||||
}
|
||||
|
||||
if (rayQueryGetIntersectionTypeEXT(rayQuery, true) == gl_RayQueryCommittedIntersectionTriangleEXT)
|
||||
{
|
||||
int primitiveID = rayQueryGetIntersectionPrimitiveIndexEXT(rayQuery, true);
|
||||
SurfaceInfo surface = surfaces[surfaceIndices[primitiveID]];
|
||||
if (surface.Sky == 0.0)
|
||||
{
|
||||
float hitDistance = rayQueryGetIntersectionTEXT(rayQuery, true);
|
||||
ambience += clamp(hitDistance / aoDistance, 0.0, 1.0);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ambience += 1.0;
|
||||
}
|
||||
}
|
||||
ambience /= float(SampleCount);
|
||||
|
||||
incoming.rgb = incoming.rgb * ambience;
|
||||
}
|
||||
|
||||
fragcolor = vec4(incoming, 1.0);
|
||||
}
|
||||
|
||||
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";
|
||||
|
|
|
@ -65,8 +65,15 @@ void GPURaytracer2::Raytrace(LevelMesh* level)
|
|||
Surface* surface = mesh->surfaces[i].get();
|
||||
int sampleWidth = surface->lightmapDims[0];
|
||||
int sampleHeight = surface->lightmapDims[1];
|
||||
surfaceImages.push_back(CreateImage(sampleWidth, sampleHeight));
|
||||
}
|
||||
|
||||
LightmapImage img = CreateImage(sampleWidth, sampleHeight);
|
||||
for (size_t i = 0; i < mesh->surfaces.size(); i++)
|
||||
{
|
||||
Surface* surface = mesh->surfaces[i].get();
|
||||
int sampleWidth = surface->lightmapDims[0];
|
||||
int sampleHeight = surface->lightmapDims[1];
|
||||
LightmapImage& img = surfaceImages[i];
|
||||
|
||||
RenderPassBegin()
|
||||
.RenderPass(renderPass.get())
|
||||
|
@ -96,6 +103,14 @@ void GPURaytracer2::Raytrace(LevelMesh* level)
|
|||
cmdbuffer->draw(4, 1, 0, 0);
|
||||
|
||||
cmdbuffer->endRenderPass();
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < mesh->surfaces.size(); i++)
|
||||
{
|
||||
Surface* surface = mesh->surfaces[i].get();
|
||||
int sampleWidth = surface->lightmapDims[0];
|
||||
int sampleHeight = surface->lightmapDims[1];
|
||||
LightmapImage& img = surfaceImages[i];
|
||||
|
||||
PipelineBarrier()
|
||||
.AddImage(img.Image.get(), VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT)
|
||||
|
@ -108,8 +123,6 @@ void GPURaytracer2::Raytrace(LevelMesh* level)
|
|||
region.imageExtent.height = sampleHeight;
|
||||
region.imageExtent.depth = 1;
|
||||
cmdbuffer->copyImageToBuffer(img.Image->image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, img.Transfer->buffer, 1, ®ion);
|
||||
|
||||
surfaceImages.push_back(std::move(img));
|
||||
}
|
||||
|
||||
FinishCommands();
|
||||
|
|
Loading…
Reference in a new issue