1)So, the first step is translation from view space into clip space(homogeneous space). All code is here https://pastebin.com/fA1vWdrk. I appreciate any help. Thanks in advance.

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); |

2) Then in clip space I use something like Cohen–Sutherland algorithm.

First of all, I check if all 3 triangle's points outside canonical view volume, I will discard entire triangle.

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; } |

If there are vertices beyond near clipping plane(=1.0f), the next step will be clipping.If there are not vertices beyond near clipping plane then do perspective divide(Divide by W), then viewport transformation and rasterization. Maybe I am doing solving line equation wrong?

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); } |

Where am I wrong? All code is here https://pastebin.com/fA1vWdrk.