Browse Source

集成Gutter 边缘缓冲

ManualUV
hesuicong 12 hours ago
parent
commit
1b9cf3ea46
  1. 60
      libs/MVS/SceneTexture.cpp

60
libs/MVS/SceneTexture.cpp

@ -14332,6 +14332,8 @@ bool MeshTexture::RasterizeVirtualFaces( @@ -14332,6 +14332,8 @@ bool MeshTexture::RasterizeVirtualFaces(
// ✅ 拷贝到 atlas(OpenMP critical 区)
#pragma omp critical
{
const int gutter = 4; // 4像素边缘缓冲
for (int y = 0; y < patchH; ++y) {
for (int x = 0; x < patchW; ++x) {
cv::Vec3b color = patch.at<cv::Vec3b>(y, x);
@ -14344,6 +14346,56 @@ bool MeshTexture::RasterizeVirtualFaces( @@ -14344,6 +14346,56 @@ bool MeshTexture::RasterizeVirtualFaces(
atlasY < 0 || atlasY >= textureSize)
continue;
// ✅ 计算当前像素的 UV 坐标
float u = (float)atlasX / (float)textureSize;
float v = (float)atlasY / (float)textureSize;
// ✅ 获取三角形的三个 UV 点
const TexCoord& uv0 = scene.mesh.faceTexcoords[vf.faces[0] * 3 + 0];
const TexCoord& uv1 = scene.mesh.faceTexcoords[vf.faces[0] * 3 + 1];
const TexCoord& uv2 = scene.mesh.faceTexcoords[vf.faces[0] * 3 + 2];
// ✅ 计算点到三角形三条边的有符号距离(UV空间)
// 使用重心坐标或点到线段的距离公式
auto pointToLineDistance = [](float px, float py,
float x1, float y1,
float x2, float y2) -> float {
float dx = x2 - x1;
float dy = y2 - y1;
if (dx == 0.0f && dy == 0.0f) return std::sqrt((px-x1)*(px-x1) + (py-y1)*(py-y1));
float t = ((px - x1) * dx + (py - y1) * dy) / (dx*dx + dy*dy);
t = std::max(0.0f, std::min(1.0f, t));
float closestX = x1 + t * dx;
float closestY = y1 + t * dy;
return std::sqrt((px - closestX)*(px - closestX) +
(py - closestY)*(py - closestY));
};
// 计算到三条边的距离
float d0 = pointToLineDistance(u, v, uv0.x, uv0.y, uv1.x, uv1.y);
float d1 = pointToLineDistance(u, v, uv1.x, uv1.y, uv2.x, uv2.y);
float d2 = pointToLineDistance(u, v, uv2.x, uv2.y, uv0.x, uv0.y);
// 取最小距离作为到三角形边界的距离
float distToEdge = std::min({d0, d1, d2});
// 转换为像素距离
float pixelDist = distToEdge * textureSize;
// ✅ Gutter 衰减逻辑(只衰减评分,不修改颜色!)
float gutterWeight = 1.0f;
if (pixelDist < gutter) {
// 使用平滑衰减函数(二次曲线)
gutterWeight = (pixelDist * pixelDist) / (gutter * gutter);
// 极边缘处给极低权重,但不跳过
if (pixelDist < 0.5f) {
gutterWeight = 0.01f; // 极低权重,几乎不会被选中
}
}
size_t idx = atlasY * textureSize + atlasX;
TexelScore& ts = m_texelScores[idx];
@ -14352,11 +14404,13 @@ bool MeshTexture::RasterizeVirtualFaces( @@ -14352,11 +14404,13 @@ bool MeshTexture::RasterizeVirtualFaces(
? -1.0f
: virtualFaceViewWeights[i][0];
// ✅ 只接受更高评分的写入
if (currentScore > ts.score) {
// ✅ 只衰减评分,不修改颜色!
float finalScore = currentScore * gutterWeight;
if (finalScore > ts.score) {
atlas(atlasY, atlasX) =
Pixel8U{color[2], color[1], color[0]};
ts.score = currentScore;
ts.score = finalScore;
ts.viewID = viewID;
}
}

Loading…
Cancel
Save