vault backup: 2024-01-02 15:12:18
This commit is contained in:
parent
8b1651fd54
commit
26dc4eba7f
@ -78,6 +78,14 @@
|
|||||||
"lastUpdated": 1704117184719
|
"lastUpdated": 1704117184719
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"c++17带来的代码变化": {
|
||||||
|
"c++17带来的代码变化": {
|
||||||
|
"internalLink": {
|
||||||
|
"count": 1,
|
||||||
|
"lastUpdated": 1704171666800
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -13,13 +13,15 @@ rating: ⭐
|
|||||||
- [x] gaussian
|
- [x] gaussian
|
||||||
- render - sibr_gaussian
|
- render - sibr_gaussian
|
||||||
- apps - SIBR_gaussianViewer_app
|
- apps - SIBR_gaussianViewer_app
|
||||||
- [ ] diff-gaussian-rasterization(CUDA)
|
- [x] diff-gaussian-rasterization(CUDA)
|
||||||
# render - sibr_gaussian
|
# render - sibr_gaussian
|
||||||
- picojson:JSON库
|
- picojson:JSON库
|
||||||
- rapidxml:XML库
|
- rapidxml:XML库
|
||||||
- **nanoflann**:是一个c++11标准库,用于构建具有不同拓扑(R2,R3(点云),SO(2)和SO(3)(2D和3D旋转组))的KD树。
|
- **nanoflann**:是一个c++11标准库,用于构建具有不同拓扑(R2,R3(点云),SO(2)和SO(3)(2D和3D旋转组))的KD树。
|
||||||
|
|
||||||
## GaussianSurfaceRenderer
|
## GaussianSurfaceRenderer
|
||||||
|
>主要用于渲染椭圆体,估计是用于Debug用的。
|
||||||
|
|
||||||
### GaussianData
|
### GaussianData
|
||||||
- GaussianData():通过构造函数形参接受CPU端读取的高斯数据,再通过调用glCreateBuffers()、glNamedBufferStorage()创建GL缓存对象并且初始化,并使用GLuint进行记录(index)。
|
- GaussianData():通过构造函数形参接受CPU端读取的高斯数据,再通过调用glCreateBuffers()、glNamedBufferStorage()创建GL缓存对象并且初始化,并使用GLuint进行记录(index)。
|
||||||
- render:给Shader绑定GL缓存,并且绘制数组实例。
|
- render:给Shader绑定GL缓存,并且绘制数组实例。
|
||||||
@ -58,7 +60,7 @@ rating: ⭐
|
|||||||
- 初始化3D高斯渲染器对象_gaussianRenderer。
|
- 初始化3D高斯渲染器对象_gaussianRenderer。
|
||||||
- 创建GL缓存对象imageBuffer。
|
- 创建GL缓存对象imageBuffer。
|
||||||
- CUDA插值操作。
|
- CUDA插值操作。
|
||||||
- 绑定3个geomBufferFunc、binningBufferFunc、imgBufferFunc仿函数。
|
- 绑定3个geomBufferFunc、binningBufferFunc、imgBufferFunc仿函数,用来调整CUDA渲染时的缓存大小(创建或者回收内存空间)
|
||||||
- onRenderIBR():View的渲染函数。
|
- onRenderIBR():View的渲染函数。
|
||||||
- Ellipsoids(椭圆体渲染):使用_gaussianRenderer->process() 进行渲染。(OpenGL)
|
- Ellipsoids(椭圆体渲染):使用_gaussianRenderer->process() 进行渲染。(OpenGL)
|
||||||
- Initial Points:`_pointbasedrenderer->process()`渲染点。
|
- Initial Points:`_pointbasedrenderer->process()`渲染点。
|
||||||
@ -86,5 +88,223 @@ CUDA文件位于`SIBR_viewers\extlibs\CudaRasterizer\CudaRasterizer\cuda_rasteri
|
|||||||
6. 计算Alpha。
|
6. 计算Alpha。
|
||||||
7. 渲染`out_color = vec4(align * colorVert, a);` 也就是colorTexture
|
7. 渲染`out_color = vec4(align * colorVert, a);` 也就是colorTexture
|
||||||
8. 渲染`out_id = boxID;`也就是idTexture
|
8. 渲染`out_id = boxID;`也就是idTexture
|
||||||
|
|
||||||
|
# CudaRasterizer
|
||||||
|
**本人没学过CUDA,以下仅仅是对代码的猜测。**
|
||||||
|
额外需要了解Tile渲染方式(具体可以看**Tiled-Based Deferred Rendering(TBDR)**) https://zhuanlan.zhihu.com/p/547943994
|
||||||
|
|
||||||
|
- 屏幕分成`16 * 16`的tile,每个tile进行单独计算。之后对每个像素进行计算。
|
||||||
|
- 取得对应tile中Start与End的位置,对已经排序完的高斯点进行计算,求微分。
|
||||||
|
- 计算当前像素的透明度T
|
||||||
|
- 2D协方差 => power => alpha。
|
||||||
|
- 每次循环都进行`float test_T = T * (1 - alpha)`,当test_T极小时(不透明)则停止循环。
|
||||||
|
- T = test_T。
|
||||||
|
- 计算当前像素的颜色,也就是计算各个方向接受的辐射照度。
|
||||||
|
- `for (int ch = 0; ch < CHANNELS; ch++)`
|
||||||
|
`C[ch] += features[collected_id[j] * CHANNELS + ch] * alpha * T;`
|
||||||
|
- 计算最终贡献值
|
||||||
|
- 如果当前像素在范围中则输出
|
||||||
|
- `final_T[pix_id]`最终透明度。
|
||||||
|
- `n_contrib[pix_id]`最终贡献值。
|
||||||
|
- `out_color[ch * H * W + pix_id]`最终颜色。`C[ch] + T * bg_color[ch]`
|
||||||
|
|
||||||
|
对屏幕分Tile
|
||||||
|
![[ScreenSpaceTile.jpg]]
|
||||||
|
|
||||||
|
以此减少需要遍历的点云数量。
|
||||||
|
![[TileRange.jpg|500]]
|
||||||
|
|
||||||
|
每个点云相当于空间中当前位置空间的辐射强度分布。
|
||||||
|
![[GS_radiation.jpg]]
|
||||||
|
|
||||||
|
一个像素的渲染会计算这个像素范围内所有的点云的辐射强度、透明度,最后求微分。下图两条横线内相当于一个像素的范围。
|
||||||
|
![[一个像素需要计算范围内所有电源的辐射强度.png|500]]
|
||||||
|
|
||||||
|
## rasterizer_impl.cu
|
||||||
|
- getHigherMsb()
|
||||||
|
- checkFrustum():判断点云是否在视锥内,返回一个bool数组。
|
||||||
|
- duplicateWithKeys()
|
||||||
|
- identifyTileRanges():确定每个Tile的工作起点与终点。
|
||||||
|
- markVisible():标记高斯点云是否处于可视状态。
|
||||||
|
- GeometryState::fromChunk():计算数据块的指针偏移,并且返回创建的GeometryState结构体对象。
|
||||||
|
- ImageState::fromChunk():计算数据块的指针偏移,并且返回创建的ImageState结构体对象。
|
||||||
|
- BinningState::fromChunk():计算数据块的指针偏移,并且返回创建的BinningState结构体对象。
|
||||||
|
- forward():前向渲染可微分光栅化的高斯。具体见下文。
|
||||||
|
- backward():生成优化所需的梯度数据,并传递到forward()。**该项目中目前未被调用**
|
||||||
|
|
||||||
|
相关数据结构体定义在rasterizer_impl.h中:
|
||||||
|
```c++
|
||||||
|
struct GeometryState
|
||||||
|
{
|
||||||
|
size_t scan_size;
|
||||||
|
float* depths;
|
||||||
|
char* scanning_space;
|
||||||
|
bool* clamped;
|
||||||
|
int* internal_radii;
|
||||||
|
float2* means2D;
|
||||||
|
float* cov3D;
|
||||||
|
float4* conic_opacity;
|
||||||
|
float* rgb;
|
||||||
|
uint32_t* point_offsets;
|
||||||
|
uint32_t* tiles_touched;
|
||||||
|
|
||||||
|
static GeometryState fromChunk(char*& chunk, size_t P);
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ImageState
|
||||||
|
{
|
||||||
|
uint2* ranges;
|
||||||
|
uint32_t* n_contrib;
|
||||||
|
float* accum_alpha;
|
||||||
|
|
||||||
|
static ImageState fromChunk(char*& chunk, size_t N);
|
||||||
|
};
|
||||||
|
|
||||||
|
struct BinningState
|
||||||
|
{
|
||||||
|
size_t sorting_size;
|
||||||
|
uint64_t* point_list_keys_unsorted;
|
||||||
|
uint64_t* point_list_keys;
|
||||||
|
uint32_t* point_list_unsorted;
|
||||||
|
uint32_t* point_list;
|
||||||
|
char* list_sorting_space;
|
||||||
|
|
||||||
|
static BinningState fromChunk(char*& chunk, size_t P);
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
### forward()
|
||||||
|
1. 创建相关变量:GeometryState、ImageState、minn、maxx。
|
||||||
|
2. FORWARD::preprocess()
|
||||||
|
3. 计算所有tile的高斯点云总量。
|
||||||
|
4. 根据需要需要渲染的高斯点云总量来调整CUDA buffer大小。
|
||||||
|
5. 创建BinningState。
|
||||||
|
6. duplicateWithKeys()
|
||||||
|
7. getHigherMsb()
|
||||||
|
8. 对高斯点运行排序。
|
||||||
|
9. cudaMemset(imgState.ranges, 0, tile_grid.x * tile_grid.y * sizeof(uint2));
|
||||||
|
10. 调用identifyTileRanges(),确定每个Tile的工作起点与终点。
|
||||||
|
11. 取得点云颜色数组。
|
||||||
|
12. FORWARD::render()
|
||||||
|
|
||||||
|
## forward.cu
|
||||||
|
### preprocess()
|
||||||
|
在光栅化之前,对每个高斯进行初始化处理。
|
||||||
|
- 只处理在视锥中并且在盒子中的高斯。
|
||||||
|
- 使用投影矩阵对点云的点进行变换,并进行归一化,赋予给新变量p_proj。
|
||||||
|
- 计算协方差矩阵cov3D。
|
||||||
|
- 计算2D屏幕空间的协方差矩阵cov
|
||||||
|
- Invert covariance
|
||||||
|
- Compute extent in screen space (by finding eigenvalues of 2D covariance matrix). Use extent to compute a bounding rectangle of screen-space tiles that this Gaussian overlaps with. Quit if rectangle covers 0 tiles.
|
||||||
|
- 如果没有颜色数据则从球谐函数中计算辐射照度。
|
||||||
|
- 存储当前数据。
|
||||||
|
- `depths[idx]`
|
||||||
|
- `radii[idx]`
|
||||||
|
- `points_xy_image[idx]`
|
||||||
|
- `conic_opacity[idx]`
|
||||||
|
- `tiles_touched[idx]`
|
||||||
|
|
||||||
|
```c++
|
||||||
|
// Invert covariance (EWA algorithm)
|
||||||
|
float det = (cov.x * cov.z - cov.y * cov.y);
|
||||||
|
if (det == 0.0f)
|
||||||
|
return;
|
||||||
|
float det_inv = 1.f / det;
|
||||||
|
float3 conic = { cov.z * det_inv, -cov.y * det_inv, cov.x * det_inv };
|
||||||
|
|
||||||
|
// Compute extent in screen space (by finding eigenvalues of
|
||||||
|
// 2D covariance matrix). Use extent to compute a bounding rectangle
|
||||||
|
// of screen-space tiles that this Gaussian overlaps with. Quit if
|
||||||
|
// rectangle covers 0 tiles.
|
||||||
|
float mid = 0.5f * (cov.x + cov.z);
|
||||||
|
float lambda1 = mid + sqrt(max(0.1f, mid * mid - det));
|
||||||
|
float lambda2 = mid - sqrt(max(0.1f, mid * mid - det));
|
||||||
|
float my_radius = ceil(3.f * sqrt(max(lambda1, lambda2)));
|
||||||
|
float2 point_image = { ndc2Pix(p_proj.x, W), ndc2Pix(p_proj.y, H) };
|
||||||
|
uint2 rect_min, rect_max;
|
||||||
|
|
||||||
|
if (rects == nullptr) // More conservative
|
||||||
|
{
|
||||||
|
getRect(point_image, my_radius, rect_min, rect_max, grid);
|
||||||
|
}
|
||||||
|
else // Slightly more aggressive, might need a math cleanup
|
||||||
|
{
|
||||||
|
const int2 my_rect = { (int)ceil(3.f * sqrt(cov.x)), (int)ceil(3.f * sqrt(cov.z)) };
|
||||||
|
rects[idx] = my_rect;
|
||||||
|
getRect(point_image, my_rect, rect_min, rect_max, grid);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((rect_max.x - rect_min.x) * (rect_max.y - rect_min.y) == 0)
|
||||||
|
return;
|
||||||
|
```
|
||||||
|
|
||||||
|
### render()
|
||||||
|
对所有Tile进行并行计算。针对CUDA核心数量创建对应的Block以及对应数据。`int collected_id[BLOCK_SIZE]、float2 collected_xy[BLOCK_SIZE]、float4 collected_conic_opacity[BLOCK_SIZE]`。
|
||||||
|
|
||||||
|
递归所有的Block,计算透明度、Color以及贡献值(用于计算平均值)。
|
||||||
|
|
||||||
|
```c++
|
||||||
|
// Iterate over batches until all done or range is complete
|
||||||
|
for (int i = 0; i < rounds; i++, toDo -= BLOCK_SIZE)
|
||||||
|
{
|
||||||
|
// End if entire block votes that it is done rasterizing
|
||||||
|
int num_done = __syncthreads_count(done);
|
||||||
|
if (num_done == BLOCK_SIZE)
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Collectively fetch per-Gaussian data from global to shared
|
||||||
|
int progress = i * BLOCK_SIZE + block.thread_rank();
|
||||||
|
if (range.x + progress < range.y)
|
||||||
|
{ int coll_id = point_list[range.x + progress];
|
||||||
|
collected_id[block.thread_rank()] = coll_id;
|
||||||
|
collected_xy[block.thread_rank()] = points_xy_image[coll_id];
|
||||||
|
collected_conic_opacity[block.thread_rank()] = conic_opacity[coll_id];
|
||||||
|
} block.sync();
|
||||||
|
|
||||||
|
// Iterate over current batch
|
||||||
|
for (int j = 0; !done && j < min(BLOCK_SIZE, toDo); j++)
|
||||||
|
{ // Keep track of current position in range
|
||||||
|
contributor++;
|
||||||
|
|
||||||
|
// Resample using conic matrix (cf. "Surface
|
||||||
|
// Splatting" by Zwicker et al., 2001)
|
||||||
|
float2 xy = collected_xy[j];
|
||||||
|
float2 d = { xy.x - pixf.x, xy.y - pixf.y };
|
||||||
|
float4 con_o = collected_conic_opacity[j];
|
||||||
|
float power = -0.5f * (con_o.x * d.x * d.x + con_o.z * d.y * d.y) - con_o.y * d.x * d.y;
|
||||||
|
if (power > 0.0f)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// Eq. (2) from 3D Gaussian splatting paper.
|
||||||
|
// Obtain alpha by multiplying with Gaussian opacity // and its exponential falloff from mean. // Avoid numerical instabilities (see paper appendix).float alpha = min(0.99f, con_o.w * exp(power));
|
||||||
|
if (alpha < 1.0f / 255.0f)
|
||||||
|
continue;
|
||||||
|
float test_T = T * (1 - alpha);
|
||||||
|
if (test_T < 0.0001f)
|
||||||
|
{ done = true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// Eq. (3) from 3D Gaussian splatting paper.
|
||||||
|
for (int ch = 0; ch < CHANNELS; ch++)
|
||||||
|
C[ch] += features[collected_id[j] * CHANNELS + ch] * alpha * T;
|
||||||
|
|
||||||
|
T = test_T;
|
||||||
|
|
||||||
|
// Keep track of last range entry to update this
|
||||||
|
// pixel. last_contributor = contributor;
|
||||||
|
}}
|
||||||
|
```
|
||||||
|
|
||||||
|
```c++
|
||||||
|
// All threads that treat valid pixel write out their final
|
||||||
|
// rendering data to the frame and auxiliary buffers.
|
||||||
|
if (inside)
|
||||||
|
{
|
||||||
|
final_T[pix_id] = T;
|
||||||
|
n_contrib[pix_id] = last_contributor;
|
||||||
|
for (int ch = 0; ch < CHANNELS; ch++)
|
||||||
|
out_color[ch * H * W + pix_id] = C[ch] + T * bg_color[ch];
|
||||||
|
}
|
||||||
|
```
|
||||||
# apps - SIBR_gaussianViewer_app
|
# apps - SIBR_gaussianViewer_app
|
||||||
调用`gaussianviewer/renderer/GaussianView.hpp`封装的App。
|
调用`gaussianviewer/renderer/GaussianView.hpp`封装的App。
|
BIN
08-Assets/Images/AIGC/GS_radiation.jpg
Normal file
BIN
08-Assets/Images/AIGC/GS_radiation.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 54 KiB |
BIN
08-Assets/Images/AIGC/ScreenSpaceTile.jpg
Normal file
BIN
08-Assets/Images/AIGC/ScreenSpaceTile.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 32 KiB |
BIN
08-Assets/Images/AIGC/TileRange.jpg
Normal file
BIN
08-Assets/Images/AIGC/TileRange.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 41 KiB |
BIN
08-Assets/Images/AIGC/一个像素需要计算范围内所有电源的辐射强度.png
Normal file
BIN
08-Assets/Images/AIGC/一个像素需要计算范围内所有电源的辐射强度.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 55 KiB |
Loading…
x
Reference in New Issue
Block a user