將3d紋理映射到視錐(或其一部分)上


5

我正在OpenGL渲染器中實現體積霧。首先,我使用計算著色器,原子操作和陰影貼圖可見性檢查將顏色注入3D紋理。我用來計算細胞指數和在世界空間中的位置的信息是統一的:相機pos,細胞大小和紋理尺寸。接下來,當準備好填充數據的捲時,我需要將其與視錐面對齊以通過紋理進行射線成像,並在後期處理(延遲階段)中應用效果,而我對此非常困惑。我認為有兩種選擇(紅色是紋理體積):3d texture aligned with frustum

因此,在應用效果時,我從攝影機pos到片段pos(來自G緩衝區紋理)進行光線投射。我不知道它是否正確,但是我想我需要將碎片pos轉換為NDC,將其縮放到[0,1],然後從體積上使用此樣本。

嘗試了一些魔術,例如:

vec4 texcoords = vpMatrix * vec4(fragPos, 1.0); //to clip space
texcoords.xyz /= texcoords.w; //to NDC
texcoords.xyz = texcoords.xyz *0.5 +0.5; //[-1,1] to [0,1]

最終:

vec3 texcoords;
texcoords.x = texcoord0.x; //texcoord0 - texcoords of screen quad
texcoords.y = texcoord0.y;
texcoords.z = depth; //depth from vector: worldpos-camerapos

但這只是猜測。另外,我不知道在這種情況下(專業遊戲引擎)使用圖片中的哪個選項,以及如何僅將其應用於截頭圓錐體的一定長度,因為它相當大。對於這個的任何提示,我們將不勝感激。

要檢查它現在是否可以按以下方式實施:將相機對準體積中心,因此旋轉它並不是很重要。因此,我可能也需要修改注入階段,以獲取正確計算的靜態單元格索引,例如:

vec3 index = vec3(gl_GlobalInvocationID); //cell number of texture;
vec3 pos = camerapos+index*cellSize;
2

In techniques I've seen that use a frustum-aligned voxel grid (so-called "froxels"), it looks like option 2 in your diagram. The voxels are cuboids in post-projective screen space, so when transformed back to world space they look like mini-frusta, automatically expanding as they get farther from the camera.

Marching along eye rays is then very easy: you just step along the grid's Z axis. Summing optical density or in-scattered light along an eye ray is just a matter of iterating over the Z dimension of the texture. (Or you could try to apply methods like parallel prefix sum as well, but it may not be worthwhile, depending on the texture size.)

If you're rendering some geometry and you want to know which voxel it's in, you don't have to do any matrix transformations. Just use gl_FragCoord​, which represents the screen-space position (including depth) of the current fragment. It comes in window units (i.e. pixels) so you'll have to remap it to [0,1] for texture sampling, or to voxel units if you're doing an image store.

Otherwise, for mapping world-space positions into the voxel grid, use the usual sequence of transformations. It looks to me like you got it right in your code snippet, assuming fragPos is in world space. For getting from the voxel grid back to world space, you'll need to invert that sequence of transformations.