1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | triangle *Triangle = &gTriangles[TriangleIndex];
v3 V0 = Triangle->Vertex[0];
v3 V1 = Triangle->Vertex[1];
v3 V2 = Triangle->Vertex[2];
// NOTE(shvayko): Transform to clip space
f32 FOV = 90.0f; // NOTE(shvayko):
f32 n = 1.0f; // NOTE: Near plane
f32 f = 15.0f; // NOTE: Far plane
f32 AspectRatio = (f32)WINDOW_WIDTH / (f32)WINDOW_HEIGHT;
v4 ClipV0,ClipV1,ClipV2;
TransformIntoClipSpace(FOV,n,f,AspectRatio,V0,V1,V2,
&ClipV0, &ClipV1, &ClipV2);
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 | // NOTE(shvayko): Count how much vertices have Z > NearPlane
u32 VerticesInsideZRange = 0;
v4 TestVertices[3] = {ClipV0,ClipV1,ClipV2};
for(u32 VertexIndex = 0;
VertexIndex < 3;
VertexIndex++)
{
v4 CurrentTestVertex = TestVertices[VertexIndex];
if(CurrentTestVertex.x > CurrentTestVertex.w)
{
ClipCode[VertexIndex] |= CLIPCODE_X_GREATER;
}
else if(CurrentTestVertex.x < -CurrentTestVertex.w)
{
ClipCode[VertexIndex] |= CLIPCODE_X_LOWER;
}
else
{
ClipCode[VertexIndex] |= CLIPCODE_X_INSIDE;
}
if(CurrentTestVertex.y > CurrentTestVertex.w)
{
ClipCode[VertexIndex] |= CLIPCODE_Y_GREATER;
}
else if(CurrentTestVertex.y < -CurrentTestVertex.w)
{
ClipCode[VertexIndex] |= CLIPCODE_Y_LOWER;
}
else
{
ClipCode[VertexIndex] |= CLIPCODE_Y_INSIDE;
}
if(CurrentTestVertex.z > CurrentTestVertex.w)
{
ClipCode[VertexIndex] |= CLIPCODE_Z_GREATER;
}
else if(CurrentTestVertex.z < -CurrentTestVertex.w)
{
ClipCode[VertexIndex] |= CLIPCODE_Z_LOWER;
}
else
{
ClipCode[VertexIndex] |= CLIPCODE_Z_INSIDE;
VerticesInsideZRange++;
}
}
// NOTE(shvayko):Check if all 3 points outside canonical volume
if(IsTrivialReject(ClipCode,Clipping_CheckX) ||
IsTrivialReject(ClipCode,Clipping_CheckY) ||
IsTrivialReject(ClipCode,Clipping_CheckZ))
{
// NOTE(shvayko): Go to the next polygon
continue;
}
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 | // NOTE(shvayko):Check if any vertex lying beyond near plane
if(IsBitSet(ClipCode[0],7) ||
IsBitSet(ClipCode[1],7) ||
IsBitSet(ClipCode[2],7))
{
if(VerticesInsideZRange == 1)
{
// NOTE(shvayko): The simplest case where only one interior vertex.
// Just interpolate each exterior vertex with interior vertex and that
// will produce new vertices which will represent one new triangle.
// NOTE(shvayko): TmpV0 - Interior vertex; TmpV1 - Exterior vertex;
// TmpV2 - Exterior vertex
v3 TmpV0,TmpV1,TmpV2;
if(IsBitSet(ClipCode[0],8))
{
TmpV0 = V0;
TmpV1 = V1;
TmpV2 = V2;
}
else if(IsBitSet(ClipCode[1],8))
{
TmpV0 = V1;
TmpV1 = V0;
TmpV2 = V2;
}
else
{
TmpV0 = V2;
TmpV1 = V0;
TmpV2 = V1;
}
// NOTE(shvayko): Solve for t when z component is equal to near z
// Pi(x,y,z) = P0(x,y,z) + (P1(x,y,z) - P0(x,y,z))*t
// NOTE(shvayko): 1.0f is near plane Z
// NOTE(shvayko): TmpV0 and TmpV2
f32 t = 1.0f-TmpV1.z / (TmpV0.z - TmpV1.z);
f32 x = TmpV1.x + (TmpV0.x - TmpV1.x)*t;
f32 y = TmpV1.y + (TmpV0.y - TmpV1.y)*t;
f32 z = TmpV1.z + (TmpV0.z - TmpV1.z)*t;
TmpV1 = v3f(x,y,1.1f);
// NOTE(shvayko): TmpV0 and TmpV2
f32 t1 = 1.0f-TmpV2.z / (TmpV0.z - TmpV2.z);
x = TmpV2.x + (TmpV0.x - TmpV2.x)*t1;
y = TmpV2.y + (TmpV0.y - TmpV2.y)*t1;
z = TmpV2.z + (TmpV0.z - TmpV2.z)*t1;
TmpV2 = v3f(x,y,1.1f);
// NOTE(shvayko): New triangle
v3 NT0 = TmpV0;
v3 NT1 = TmpV1;
v3 NT2 = TmpV2;
AddTriangle(NT0,NT1,NT2,Triangle->Color);
}
else if(VerticesInsideZRange == 2)
{
// NOTE(shvayko): The case where two interior vertex.
// That case will produce 2 triangles
// NOTE(shvayko): TmpV0 - Interior vertex; TmpV1 - Interior vertex;
// TmpV2 - Exterior vertex
v3 TmpV0,TmpV1,TmpV2;
if(ClipCode[0] & CLIPCODE_Z_INSIDE)
{
TmpV0 = V0;
if(ClipCode[1] & CLIPCODE_Z_INSIDE)
{
TmpV1 = V1;
TmpV2 = V2;
}
else
{
TmpV1 = V2;
TmpV2 = V1;
}
}
else if(ClipCode[1] & CLIPCODE_Z_INSIDE)
{
TmpV0 = V1;
TmpV1 = V2;
TmpV2 = V0;
}
// NOTE(shvayko): Solve for t when z component is equal to near z
// NOTE(shvayko): first created new vertex
// NOTE(shvayko): 1.0f is near plane Z
f32 t = 1.0f-TmpV2.z / (TmpV0.z - TmpV2.z);
f32 X0i = TmpV2.x + (TmpV0.x - TmpV2.x)*t;
f32 Y0i = TmpV2.y + (TmpV0.y - TmpV2.y)*t;
f32 Z0i = TmpV2.z + (TmpV0.z - TmpV2.z)*t;
// NOTE(shvayko): second created new vertex
f32 t1 = 1.0f-TmpV2.z / (TmpV1.z - TmpV2.z);
f32 X1i = TmpV2.x + (TmpV1.x - TmpV2.x)*t1;
f32 Y1i = TmpV2.y + (TmpV1.y - TmpV2.y)*t1;
f32 Z1i = TmpV2.z + (TmpV1.z - TmpV2.z)*t1;
// NOTE(shvayko): Split into 2 triangles
AddTriangle(TmpV0,v3f(X0i,Y0i,1.1f),TmpV1,Triangle->Color);
AddTriangle(TmpV0,TmpV1,v3f(X1i,Y1i,1.1f),Triangle->Color);
}
else
{
assert(!"lol");
}
}
else
{
// NOTE(shvayko): All vertices is in Z range. Process without any clipping
// NOTE(shvayko): Pespective divide. (Transforming from Clip Space into NDC space)
v3 NdcV0,NdcV1,NdcV2;
TransformHomogeneousToNDC(ClipV0,ClipV1,ClipV2,&NdcV0,&NdcV1,&NdcV2);
// NOTE(shvayko):Viewport tranformation(Transforming from NDC space(-1.0f - 1.0f))
// to screen space(0 - Width, 0 - Height)
v3 WinPV0,WinPV1,WinPV2;
Viewport(NdcV0,NdcV1,NdcV2,&WinPV0,&WinPV1,&WinPV2,ClipV0.z,ClipV1.z,ClipV2.z);
// NOTE(shvayko): Rasterization Stage
DrawTriangle(Backbuffer,WinPV0,WinPV1,WinPV2, Triangle->Color);
}
|
1 2 3 4 | f32 t = 1.0f-TmpV1.z / (TmpV0.z - TmpV1.z); // Should be f32 t = (1.0f-TmpV1.z) / (TmpV0.z - TmpV1.z); |
1 2 | f32 t = ( -w - TmpV1.z ) / ( TmpV0.z - TmpV1.z ); // But what is w ? |
1 2 3 4 5 | v3 inside = v3( TmpV0.x / TmpV0.w, TmpV0.y / TmpV0.w, TmpV0.z / TmpV0.w ); v3 outside = v3( TmpV1.x / TmpV1.w, TmpV1.y / TmpV1.w, TmpV1.z / TmpV1.w ); // In ndc space, -1.0 is the near plane f32 t = ( -1.0f - outside.z ) / ( inside.z - outside.z ); v3 new_point_in_ndc = outside + ( inside - outside ) * t; |
ExTray2020
Thanks for your answer. I appreciate that.
A very dumb mistake with parentheses. Fixed it. it's working better now. Thank you.
I think you are right about that I cannot use vertices like that. Your way seems resonable but I need to give the AddTriangle function vertices in world's coordinates not in NDC. So I don't know how to approach that. May be you know how to translate ndc coordinates into world space? Also, I think I may change architecture of my rendering loop without adding new triangles in the end list. I just will render and transform my new constructed triangles right in place. By the way, can you suggest way to handle that?