Skip to content
Snippets Groups Projects
Commit 85443e8d authored by Nicolas Pope's avatar Nicolas Pope
Browse files

Barycentric approach

parent a4425d76
No related branches found
No related tags found
1 merge request!151Implements #216 triangle renderer
......@@ -11,6 +11,85 @@ using ftl::render::SplatParams;
__device__ inline float length2(int dx, int dy) { return dx*dx + dy*dy; }
__device__ inline float cross(const float2 &a, const float2 &b) {
return a.x*b.y - a.y*b.x;
}
__device__ inline bool within(float x) {
return 0.0f <= x <= 1.0f;
}
__device__ inline bool operator==(const float2 &a, const float2 &b) {
return a.x == b.x && a.y == b.y;
}
__device__ inline bool insideTriangle(const float2 &a, const float2 &b, const float2 &c, const float2 &p)
{
float det = (b.y - c.y)*(a.x - c.x) + (c.x - b.x)*(a.y - c.y);
float factor_alpha = (b.y - c.y)*(p.x - c.x) + (c.x - b.x)*(p.y - c.y);
float factor_beta = (c.y - a.y)*(p.x - c.x) + (a.x - c.x)*(p.y - c.y);
float alpha = factor_alpha / det;
float beta = factor_beta / det;
float gamma = 1.0 - alpha - beta;
return p == a || p == b || p == c || (within(alpha) && within(beta) && within(gamma));
}
__device__ inline void swap(short2 &a, short2 &b) {
short2 t = a;
a = b;
b = t;
}
__device__ void drawLine(TextureObject<int> &depth_out, int y, int x1, int x2, float d) {
for (int x=x1; x<=x2; ++x) {
if (x < 0) continue;
if (x >= depth_out.width()) return;
atomicMin(&depth_out(x,y), int(d*1000.0f));
}
}
/**
* Calculate the signed area of a given triangle.
*/
__device__ static inline
float calculateSignedArea(const short2 &a, const short2 &b, const short2 &c) {
return 0.5f * (float(c.x - a.x) * float(b.y - a.y) - float(b.x - a.x) * float(c.y - a.y));
}
// CHECKITOUT
/**
* Helper function for calculating barycentric coordinates.
*/
__device__ static inline
float calculateBarycentricCoordinateValue(const short2 &a, const short2 &b, const short2 &c, const short2 (&tri)[3]) {
return calculateSignedArea(a,b,c) / calculateSignedArea(tri[0], tri[1], tri[2]);
}
// CHECKITOUT
/**
* Calculate barycentric coordinates.
* TODO: Update to handle triangles coming in and not the array
*/
__device__ static
float3 calculateBarycentricCoordinate(const short2 (&tri)[3], const short2 &point) {
float beta = calculateBarycentricCoordinateValue(tri[0], point, tri[2], tri);
float gamma = calculateBarycentricCoordinateValue(tri[0], tri[1], point, tri);
float alpha = 1.0 - beta - gamma;
return make_float3(alpha, beta, gamma);
}
// CHECKITOUT
/**
* Check if a barycentric coordinate is within the boundaries of a triangle.
*/
__host__ __device__ static
bool isBarycentricCoordInBounds(const float3 &barycentricCoord) {
return barycentricCoord.x >= 0.0 && barycentricCoord.x <= 1.0 &&
barycentricCoord.y >= 0.0 && barycentricCoord.y <= 1.0 &&
barycentricCoord.z >= 0.0 && barycentricCoord.z <= 1.0;
}
/*
* Convert source screen position to output screen coordinates.
*/
......@@ -30,15 +109,63 @@ __device__ inline float length2(int dx, int dy) { return dx*dx + dy*dy; }
d[2] = depth_in.tex2D(x+A,y+(1-B));
// Is this triangle valid
if (fabs(d[0] - d[1]) > 0.04f || fabs(d[0] - d[2]) > 0.04f) return;
if (fabs(d[0] - d[1]) > 0.04f || fabs(d[0] - d[2]) > 0.04f || fabs(d[1] - d[2]) > 0.04f) return;
if (d[0] < params.camera.minDepth || d[0] > params.camera.maxDepth) return;
short2 s[3];
s[0] = screen.tex2D(x+A,y+B);
s[1] = screen.tex2D(x+(1-A),y+B);
s[2] = screen.tex2D(x+A,y+(1-B));
short2 v[3];
v[0] = screen.tex2D(x+A,y+B);
v[1] = screen.tex2D(x+(1-A),y+B);
v[2] = screen.tex2D(x+A,y+(1-B));
const int minX = min(v[0].x, min(v[1].x, v[2].x));
const int minY = min(v[0].y, min(v[1].y, v[2].y));
const int maxX = max(v[0].x, max(v[1].x, v[2].x));
const int maxY = max(v[0].y, max(v[1].y, v[2].y));
//if ((maxX - minX) * (maxY - minY) > 200) return;
int incx = ((maxX - minX) / 20) + 1;
int incy = ((maxY - minY) / 20) + 1;
float2 vs0 = make_float2(v[0].x, v[0].y);
float2 vs1 = make_float2(v[1].x, v[1].y);
float2 vs2 = make_float2(v[2].x, v[2].y);
for (int sy=minY; sy <= maxY; sy+=incy) {
for (int sx=minX; sx <= maxX; sx+=incx) {
if (sx >= params.camera.width || sx < 0 || sy >= params.camera.height || sy < 0) continue;
//float2 q = make_float2(sx, sy);
//float s = det(q - vs0, vs1) / det(vs0, vs1); //cross(q, vs2) / cross(vs1, vs2);
//float t = det(vs0, q - vs1) / det(vs0, vs1); //cross(vs1, q) / cross(vs1, vs2);
float3 baryCentricCoordinate = calculateBarycentricCoordinate(v, make_short2(sx, sy));
if (isBarycentricCoordInBounds(baryCentricCoordinate)) {
//if (s >= 0 && t >= 0 && ss+t <= 1) {
//if (insideTriangle(vs0,vs1,vs2, make_float2(sx,sy))) {
/*float dist1 = length2(sx - s[0].x, sy - s[0].y);
float dist2 = length2(sx - s[1].x, sy - s[1].y);
float dist3 = length2(sx - s[2].x, sy - s[2].y);
float maxlen = max(dist1, max(dist2, dist3));
if (maxlen > 0.0f) {
dist1 = 1.0f - dist1 / maxlen;
dist2 = 1.0f - dist2 / maxlen;
dist3 = 1.0f - dist3 / maxlen;
}
float new_depth = (maxlen == 0.0f) ? d[0] : (d[0]*dist1 + d[1]*dist2 + d[2]*dist3) / (dist1+dist2+dist3);
//if (new_depth < params.camera.minDepth || new_depth > params.camera.maxDepth) continue;*/
float new_depth = d[0];
atomicMin(&depth_out(sx,sy), int(new_depth*1000.0f));
}
}
}
// OLD
const int dx = (A) ? -1 : 1;
/*const int dx = (A) ? -1 : 1;
const int dy = (B) ? -1 : 1;
s[1].x = (A) ? s[0].x - s[1].x : s[1].x - s[0].x;
......@@ -65,7 +192,7 @@ __device__ inline float length2(int dx, int dy) { return dx*dx + dy*dy; }
atomicMin(&depth_out(dx*sx+s[0].x,dy*sy+s[0].y), int(new_depth*1000.0f));
}
}
}*/
}
void ftl::cuda::triangle_render1(TextureObject<float> &depth_in, TextureObject<int> &depth_out, TextureObject<short2> &screen, const SplatParams &params, cudaStream_t stream) {
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment