Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
4164daa
cache ray-hits in sparse gbuffer
Try Jul 18, 2026
714ebfb
deferred lighting for surfels
Try Jul 18, 2026
bcebe86
deferred lighting for surfels
Try Jul 18, 2026
04611a0
Merge branch 'gi-2-cached' of https://github.com/Try/OpenGothic into …
Try Jul 18, 2026
48226c5
test: render-pass based splttig of surfels
Try Jul 19, 2026
e5c92bb
optimization in progress
Try Jul 19, 2026
3c6e78d
Update surf_apply.comp
Try Jul 19, 2026
ba65ba9
experiment with surfel coverage
Try Jul 19, 2026
df7b012
enable shadowmap for lighting
Try Jul 19, 2026
acac68b
optimize surfel storage
Try Jul 21, 2026
1dc7d9c
change default surfel coverage
Try Jul 21, 2026
4323366
optimization in progress
Try Jul 21, 2026
2b1c476
optimize apply pass
Try Jul 21, 2026
0979831
fixup surfel apply/gc
Try Jul 21, 2026
babd551
update sky sampling
Try Jul 22, 2026
d4d270c
do not evaluate lighting in surfel gbuffer pass
Try Jul 22, 2026
2822a62
Merge branch 'gi-2-cached' of https://github.com/Try/OpenGothic into …
Try Jul 22, 2026
550e545
sky fixup
Try Jul 22, 2026
ddd2c75
display allocated amount in frame
Try Jul 22, 2026
dca3255
surfel culling in progress
Try Jul 22, 2026
4eb1e0a
fix viewvec in sky shader
Try Jul 22, 2026
c9b59ae
micro optimization
Try Jul 22, 2026
76fcbf7
surfels: handle water hits
Try Jul 23, 2026
8911fce
fixup
Try Jul 23, 2026
cd43214
fixup water rays
Try Jul 23, 2026
0718aef
fixup hit mean calculation
Try Jul 23, 2026
a45bd44
update hit mean calculation
Try Jul 25, 2026
37e7d66
revert rErrScale: 0.75 -> 0.5
Try Jul 25, 2026
3f96ee4
rework surfel GC
Try Jul 25, 2026
cc5c976
experimenting with binning pass
Try Jul 26, 2026
c24fc44
optimize weight calculation
Try Jul 26, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
256 changes: 155 additions & 101 deletions game/graphics/renderer.cpp

Large diffs are not rendered by default.

13 changes: 11 additions & 2 deletions game/graphics/renderer.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@ class Renderer final {
Tempest::StorageImage& usesImage2d(Tempest::StorageImage& ret, Tempest::TextureFormat frm, Tempest::Size sz, bool mips = false);
Tempest::StorageImage& usesImage3d(Tempest::StorageImage& ret, Tempest::TextureFormat frm, uint32_t w, uint32_t h, uint32_t d, bool mips = false);
Tempest::ZBuffer& usesZBuffer(Tempest::ZBuffer& ret, Tempest::TextureFormat frm, uint32_t w, uint32_t h);
Tempest::Attachment& usesAttachment(Tempest::Attachment&ret, Tempest::TextureFormat frm, Tempest::Size sz);
Tempest::Attachment& usesAttachment(Tempest::Attachment&ret, Tempest::TextureFormat frm, uint32_t w, uint32_t h);
Tempest::StorageBuffer& usesSsbo(Tempest::StorageBuffer& ret, size_t size);
Tempest::StorageBuffer& usesSsboInit(Tempest::StorageBuffer& ret, size_t size);
Tempest::StorageBuffer& usesScratch(Tempest::StorageBuffer& ret, size_t size);
Expand All @@ -66,6 +68,7 @@ class Renderer final {
void prepareEpipolar (Tempest::Encoder<Tempest::CommandBuffer>& cmd, WorldView& wview);

void prepareSurfels (Tempest::Encoder<Tempest::CommandBuffer>& cmd, WorldView& wview);
void surfelsApply (Tempest::Encoder<Tempest::CommandBuffer>& cmd, WorldView& wview, int32_t tileSize, bool postPass);
void surfelsBinning (Tempest::Encoder<Tempest::CommandBuffer>& cmd, WorldView& wview, int32_t tileSize, bool postPass);
void surfelsTrace (Tempest::Encoder<Tempest::CommandBuffer>& cmd, WorldView& wview, Tempest::StorageBuffer& surfels, bool postPass);

Expand Down Expand Up @@ -169,6 +172,8 @@ class Renderer final {
Tempest::TextureFormat lutRGBFormat = Tempest::TextureFormat::R11G11B10UF;
Tempest::TextureFormat lutRGBAFormat = Tempest::TextureFormat::RGBA16F;

Tempest::Sampler sampler = Tempest::Sampler::bilinear();

bool lutIsInitialized = false;
Tempest::Attachment transLut, multiScatLut, viewLut, viewCldLut;
Tempest::StorageImage cloudsLut, fogLut3D, fogLut3DMs;
Expand Down Expand Up @@ -210,14 +215,18 @@ class Renderer final {
} gi;

struct {
const uint32_t maxSurfels = 16*1024;
const Tempest::IVec2 gbufTile = {8, 8};
const uint32_t gbufTilesX = 256;
const uint32_t gbufTilesY = 256;
const uint32_t maxSurfels = gbufTilesX*gbufTilesY;
Tempest::StorageBuffer surfels;

Tempest::StorageImage irrImage;
Tempest::StorageImage surfCnts, surfBins;
Tempest::StorageBuffer surfBinsCtrl, surfList;

Tempest::StorageImage dbgImage;
Tempest::StorageBuffer gbuffFree;
Tempest::StorageImage gbuffDiff, gbuffNorm, gbuffHitT;
} surf;

struct {
Expand Down
3 changes: 3 additions & 0 deletions game/graphics/shaders.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -261,8 +261,11 @@ void Shaders::compileShaders() {

surfAlloc = computeShader("surf_alloc.comp.sprv");
surfApply = computeShader("surf_apply.comp.sprv");
surfFList = computeShader("surf_freelist.comp.sprv");

surfPathtrace = computeShader("surf_pathtrace.comp.sprv");
surfRaycast = computeShader("surf_raycast.comp.sprv");
surLighting = computeShader("surf_lighting.comp.sprv");
}

if(Shaders::isVsmSupported()) {
Expand Down
4 changes: 2 additions & 2 deletions game/graphics/shaders.h
Original file line number Diff line number Diff line change
Expand Up @@ -90,10 +90,10 @@ class Shaders {
Tempest::RenderPipeline surfDbg;
Tempest::ComputePipeline surfBinClear, surfBinPass, surfBinAlloc, surfBinSort;

Tempest::ComputePipeline surfAlloc, surfApply;
Tempest::ComputePipeline surfAlloc, surfApply, surfFList;
Tempest::ComputePipeline surfUpdate, surfCulling, surfDecimate, surfCompact;

Tempest::ComputePipeline surfPathtrace;
Tempest::ComputePipeline surfPathtrace, surfRaycast, surLighting;

// Epipolar
Tempest::ComputePipeline fogEpipolarVsm;
Expand Down
3 changes: 3 additions & 0 deletions shader/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -319,13 +319,16 @@ add_shader(surf_compact.comp lighting/surfels/surf_compact.comp)

add_shader(surf_alloc.comp lighting/surfels/surf_alloc.comp)
add_shader(surf_apply.comp lighting/surfels/surf_apply.comp)
add_shader(surf_freelist.comp lighting/surfels/surf_freelist.comp)

add_shader(surf_bin_clear.comp lighting/surfels/surf_bin_clear.comp)
add_shader(surf_bin_alloc.comp lighting/surfels/surf_bin_alloc.comp)
add_shader(surf_bin_pass.comp lighting/surfels/surf_bin_pass.comp)
add_shader(surf_bin_sort.comp lighting/surfels/surf_bin_sort.comp)

add_shader(surf_pathtrace.comp lighting/surfels/surf_pathtrace.comp)
add_shader(surf_raycast.comp lighting/surfels/surf_raycast.comp)
add_shader(surf_lighting.comp lighting/surfels/surf_lighting.comp)

# Pathtracing
add_shader(pathtrace.frag lighting/pt/pathtrace.frag -DRAY_QUERY -DRAY_QUERY_AT)
Expand Down
6 changes: 6 additions & 0 deletions shader/common.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,12 @@ float fresnel(const vec3 incident, const vec3 normal, const float ior) {
return kr;
}

vec3 waterTransmittance(float raylen) {
const float depth = raylen / 5000.0; // 50 meters
const vec3 transmittance = exp(-depth * vec3(4,2,1) * 1.25);
return transmittance;
}

float safeacos(const float x) {
return acos(clamp(x, -1.0, 1.0));
}
Expand Down
6 changes: 5 additions & 1 deletion shader/lighting/ambient_light.frag
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ layout(binding = 2) uniform usampler2D gbufNormal;
#if defined(SURFEL_GI)
layout(binding = 3) uniform sampler2D surfGi;
layout(binding = 4) uniform sampler2D ssao;
layout(binding = 5, std430) readonly buffer SB0 { uint count; } surf;
layout(binding = 5, std430) readonly buffer SB0 { uint count, one1, one2, added; } surf;
#elif defined(SSAO)
layout(binding = 3) uniform texture2D irradiance;
layout(binding = 4) uniform sampler2D ssao;
Expand Down Expand Up @@ -97,6 +97,10 @@ void main() {
outColor = vec4(1);
return;
}
if(drawInt(fragCoord.xy-ivec2(100,120), int(surf.added))>0) {
outColor = vec4(1);
return;
}
#endif

outColor = vec4(color, 1);
Expand Down
6 changes: 3 additions & 3 deletions shader/lighting/light.frag
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,9 @@ layout(push_constant, std140) uniform Pbo {
layout(binding = 0, std140) uniform UboScene {
SceneDesc scene;
};
layout(binding = 1) uniform sampler2D gbufDiffuse;
layout(binding = 2) uniform usampler2D gbufNormal;
layout(binding = 3) uniform sampler2D depth;
layout(binding = 1) uniform texture2D gbufDiffuse;
layout(binding = 2) uniform utexture2D gbufNormal;
layout(binding = 3) uniform texture2D depth;

#if defined(VIRTUAL_SHADOW)
layout(binding = 5, std430) readonly buffer Omni { uint pageTblOmni[]; };
Expand Down
5 changes: 1 addition & 4 deletions shader/lighting/pt/pathtrace.frag
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
#version 460

#define LIGHTING 1
#define RAY_QUERY
#define RAY_QUERY_AT

Expand Down Expand Up @@ -201,9 +200,7 @@ vec4 pathtrace(vec3 rayOrigin, vec3 rayDirection) {
}

if(underWater) {
const float depth = hit.rayT / 5000.0; // 50 meters
const vec3 transmittance = exp(-depth * vec3(4,2,1) * 1.25);
thruput *= transmittance;
thruput *= waterTransmittance(hit.rayT);
}

if(hit.water) {
Expand Down
19 changes: 13 additions & 6 deletions shader/lighting/pt/pathtrace_common.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

#include "random.glsl"

const float TMax = 1e30f;
const float TMax = 500*100;

struct HitResolve {
vec4 diff;
Expand Down Expand Up @@ -40,27 +40,30 @@ float rayQueryProceedShadow(const vec3 rayOrigin, const vec3 rayDirection, inout

rayQueryEXT rayQuery;
rayQueryInitializeEXT(rayQuery, topLevelAS, flags, CM_ShadowCaster,
rayOrigin, tMin, rayDirection, 500*100);
rayOrigin, tMin, rayDirection, TMax);
rayQueryProceedAlphaTest(rayQuery);
// rayQueryProceedAlphaTest(rayQuery, rngState);
if(rayQueryGetIntersectionTypeEXT(rayQuery, true) == gl_RayQueryCommittedIntersectionNoneEXT)
return 1;
return 0;
}

HitResolve rayQueryProceedPrimary(const vec3 rayOrigin, const vec3 rayDirection, float mipOverride, inout Random rngState) {
HitResolve rayQueryProceedPrimary(const vec3 rayOrigin, const vec3 rayDirection, float mipOverride, uint mask, inout Random rngState) {
// CullBack due to vegetation
uint flags = gl_RayFlagsSkipAABBEXT | gl_RayFlagsCullBackFacingTrianglesEXT;
float tMin = 2;

rayQueryEXT rayQuery;
rayQueryInitializeEXT(rayQuery, topLevelAS, flags, 0xFF,
rayOrigin, tMin, rayDirection, 500*100);
rayQueryInitializeEXT(rayQuery, topLevelAS, flags, mask,
rayOrigin, tMin, rayDirection, TMax);
rayQueryProceedAlphaTest(rayQuery);
// rayQueryProceedAlphaTest(rayQuery, rngState);
if(rayQueryGetIntersectionTypeEXT(rayQuery, true) == gl_RayQueryCommittedIntersectionNoneEXT) {
HitResolve ret;
ret.rayT = TMax;
ret.rayT = TMax;
ret.diff = vec4(0);
ret.norm = vec3(0);
ret.water = false;
return ret;
}

Expand Down Expand Up @@ -98,4 +101,8 @@ HitResolve rayQueryProceedPrimary(const vec3 rayOrigin, const vec3 rayDirection,
return ret;
}

HitResolve rayQueryProceedPrimary(const vec3 rayOrigin, const vec3 rayDirection, float mipOverride, inout Random rngState) {
return rayQueryProceedPrimary(rayOrigin, rayDirection, mipOverride, 0xFF, rngState);
}

#endif
43 changes: 17 additions & 26 deletions shader/lighting/surfels/surf_alloc.comp
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,12 @@ layout(local_size_x = 16, local_size_y = 16) in;

const uint NumThreads = gl_WorkGroupSize.x*gl_WorkGroupSize.y*gl_WorkGroupSize.z;

const float NormalBias = 0.0030;
const uint Salt = 0x9D;
const float MaxAttempts = 1;
const int MaxQueue = 256;

layout(std140, push_constant) uniform Push {
vec3 originLwc;
uint tileSize;
};
layout(binding = 0, std140) uniform UboScene {
SceneDesc scene;
Expand All @@ -24,34 +22,22 @@ layout(binding = 1) uniform texture2D irradiance;
layout(binding = 2) uniform utexture2D gbufNormal;
layout(binding = 3) uniform texture2D depth;
layout(binding = 4, std430) buffer SB0 { SurfHeader header; Surfel surfels[]; } surf;
//
layout(binding = 6, r32ui) uniform uimage2D surfCnts;
layout(binding = 7, r32ui) uniform uimage2D surfBins;
layout(binding = 8, std430) readonly buffer SB2 { uint surfelList[]; };
//
layout(binding = 11, rgba8) uniform image2D dbgImage;
layout(binding = 5, std430) buffer SB1 { uint count; uint ids[]; } freelist;

shared Candidate pointQueue[MaxQueue];
shared int pointQueueSize;

shared uint fragVote;

vec3 worldPos(float z, vec3 normal, ivec2 fragCoord, ivec2 screenSize) {
vec3 worldPos(float z, ivec2 fragCoord) {
const mat4 inv = scene.viewProjectLwcInv;
const vec2 uv = vec2(fragCoord+0.5)*scene.screenResInv;
const vec4 pos = inv*vec4(uv * 2.0 - 1.0, z, 1);
return (pos.xyz + normal*NormalBias)/pos.w + originLwc;
return pos.xyz/pos.w + originLwc;
}

float pixelToWorld(float pixelRadius, float z) {
z = linearDepth(z, scene.clipInfo);

float clipRadiusX = (2.0 * pixelRadius) * scene.screenResInv.x;
float clipRadiusY = (2.0 * pixelRadius) * scene.screenResInv.y;

float worldRadiusX = (clipRadiusX * z) / scene.project[0][0];
float worldRadiusY = (clipRadiusY * z) / scene.project[1][1];
return min(worldRadiusX, worldRadiusY);
return pixelToWorld(scene, pixelRadius, z);
}

float calculteWeight(const Candidate s, const vec3 wpos, const vec3 norm) {
Expand Down Expand Up @@ -85,6 +71,13 @@ void fragCoverageVote(float wSum) {
atomicMin(fragVote, b);
}

uint allocPayload() {
uint i = atomicAdd(freelist.count, 1);
if(i<freelist.ids.length())
return freelist.ids[i];
return 0;
}

void storeSurfels() {
const uint laneID = gl_LocalInvocationIndex;

Expand All @@ -109,9 +102,9 @@ void storeSurfels() {
sx.norm = encodeNormal(p.norm.xyz);
sx.fragCoord = fragCoord;
sx.radius = p.pos.w;
sx.radiusMean = p.pos.w * 2;
sx.radiusMean = p.pos.w * rEffScale;
sx.irradiance = debugColors[(gl_WorkGroupID.x*32+gl_WorkGroupID.y)%debugColors.length()] / scene.exposure;
sx.radiusPix = DefaultCoverage;
sx.payload = allocPayload();
surf.surfels[ptr] = sx;
}
}
Expand All @@ -126,7 +119,7 @@ void allocSurfel(ivec2 fragCoord, const ivec2 screenSize, const uint vote) {

const vec3 norm = normalFetch(gbufNormal, fragCoord);
const float z = texelFetch(depth, fragCoord, 0).x;
const vec3 wpos = worldPos(z, norm, fragCoord, screenSize);
const vec3 wpos = worldPos(z, fragCoord);

if(laneID==0 && pointQueueSize<pointQueue.length()) {
const float sz = max(pixelToWorld(DefaultCoverage, z), 0);
Expand All @@ -145,7 +138,7 @@ void mainSubtile(const ivec2 at, const ivec2 fragCoord, const ivec2 screenSize)
const bool sky = (z >= SKY_DEPTH);

const vec3 norm = normalFetch(gbufNormal, fragCoord);
const vec3 wpos = worldPos(z, norm, fragCoord, screenSize);
const vec3 wpos = worldPos(z, fragCoord);

float coverage = (sky ? 1.0 : estimateCoverage(fragCoord, wpos, norm, 0));

Expand All @@ -169,8 +162,6 @@ void mainSubtile(const ivec2 at, const ivec2 fragCoord, const ivec2 screenSize)

coverage += amendCoverage(fragCoord, wpos, norm);
}

imageStore(dbgImage, fragCoord, vec4(coverage));
}

ivec2 remap(ivec2 subtile, ivec2 tileCnt) {
Expand All @@ -196,10 +187,10 @@ void main() {
barrier();

const ivec2 screenSize = ivec2(textureSize(depth,0));
const ivec2 tileCount = ivec2(tileSize)/ivec2(gl_WorkGroupSize.xy);
const ivec2 tileCount = ivec2(LargeTile)/ivec2(gl_WorkGroupSize.xy);
for(int y=0; y<tileCount.y; ++y)
for(int x=0; x<tileCount.x; ++x) {
ivec2 at = ivec2(gl_WorkGroupID.xy) * int(tileSize);
ivec2 at = ivec2(gl_WorkGroupID.xy) * int(LargeTile);
at += remap(ivec2(x,y), tileCount)*ivec2(gl_WorkGroupSize.xy);
mainSubtile(at, at + ivec2(gl_LocalInvocationID.xy), screenSize);
}
Expand Down
Loading
Loading