@@ -50,24 +50,13 @@ std::vector<Fragment> Rasterizer::Rasterize(const Vertex& v0, const Vertex& v1,
5050 }
5151
5252 // 透视矫正插值
53- // 1. 获取三个顶点的1/w值
54- float w0_inv = v0.GetPosition ().w ;
55- float w1_inv = v1.GetPosition ().w ;
56- float w2_inv = v2. GetPosition (). w ;
53+ auto perspective_result = PerformPerspectiveCorrection (
54+ v0.GetPosition ().w , v1. GetPosition (). w , v2. GetPosition (). w ,
55+ v0. GetPosition (). z , v1.GetPosition ().z , v2. GetPosition (). z ,
56+ barycentric_coord) ;
5757
58- // 2. 插值1/w
59- float w_inv_interpolated = Interpolate (w0_inv, w1_inv, w2_inv, barycentric_coord);
60-
61- // 3. 计算透视矫正的重心坐标
62- Vector3f corrected_bary (
63- barycentric_coord.x * w0_inv / w_inv_interpolated,
64- barycentric_coord.y * w1_inv / w_inv_interpolated,
65- barycentric_coord.z * w2_inv / w_inv_interpolated
66- );
67-
68- // 4. 使用矫正的重心坐标进行插值
69- auto z = Interpolate (v0.GetPosition ().z , v1.GetPosition ().z ,
70- v2.GetPosition ().z , corrected_bary);
58+ const Vector3f& corrected_bary = perspective_result.corrected_barycentric ;
59+ float z = perspective_result.interpolated_z ;
7160
7261
7362 Fragment fragment;
@@ -114,39 +103,34 @@ void Rasterizer::RasterizeTo(const VertexSoA& soa, size_t i0, size_t i1, size_t
114103 float maxy = std::min (float (height_ - 1 ), bboxMax.y );
115104
116105 // 与外部提供的裁剪区域相交(半开区间) -> 闭区间扫描
117- int sx = std::max (x0, int (std::floor (minx)));
118- int sy = std::max (y0, int (std::floor (miny)));
119- int ex = std::min (x1 - 1 , int (std::floor (maxx)));
120- int ey = std::min (y1 - 1 , int (std::floor (maxy)));
106+ int sx = std::max (x0, static_cast < int > (std::floor (minx)));
107+ int sy = std::max (y0, static_cast < int > (std::floor (miny)));
108+ int ex = std::min (x1 - 1 , static_cast < int > (std::floor (maxx)));
109+ int ey = std::min (y1 - 1 , static_cast < int > (std::floor (maxy)));
121110 if (sx > ex || sy > ey) return ;
122111
123- // 透视矫正插值依赖 w
124- float w0_inv = p0.w ;
125- float w1_inv = p1.w ;
126- float w2_inv = p2.w ;
127-
128112 for (int x = sx; x <= ex; ++x) {
129113 for (int y = sy; y <= ey; ++y) {
130114 auto [is_inside, bary] = GetBarycentricCoord (
131115 Vector3f (p0.x , p0.y , p0.z ), Vector3f (p1.x , p1.y , p1.z ), Vector3f (p2.x , p2.y , p2.z ),
132116 Vector3f (static_cast <float >(x), static_cast <float >(y), 0 ));
133117 if (!is_inside) continue ;
134118
135- float w_inv_interp = Interpolate (w0_inv, w1_inv, w2_inv, bary);
136- Vector3f cb (
137- bary.x * w0_inv / w_inv_interp,
138- bary.y * w1_inv / w_inv_interp,
139- bary.z * w2_inv / w_inv_interp);
119+ // 透视矫正插值
120+ auto perspective_result = PerformPerspectiveCorrection (
121+ p0.w , p1.w , p2.w ,
122+ p0.z , p1.z , p2.z ,
123+ bary);
124+
125+ const Vector3f& corrected_bary = perspective_result.corrected_barycentric ;
126+ float z = perspective_result.interpolated_z ;
140127
141- float z = Interpolate (p0.z , p1.z , p2.z , cb);
142-
143- Fragment frag;
128+ Fragment frag; // Note: material 指针由调用方填写
144129 frag.screen_coord = {x, y};
145- frag.normal = Interpolate (soa.normal [i0], soa.normal [i1], soa.normal [i2], cb );
146- frag.uv = Interpolate (soa.uv [i0], soa.uv [i1], soa.uv [i2], cb );
147- frag.color = InterpolateColor (soa.color [i0], soa.color [i1], soa.color [i2], cb );
130+ frag.normal = Interpolate (soa.normal [i0], soa.normal [i1], soa.normal [i2], corrected_bary );
131+ frag.uv = Interpolate (soa.uv [i0], soa.uv [i1], soa.uv [i2], corrected_bary );
132+ frag.color = InterpolateColor (soa.color [i0], soa.color [i1], soa.color [i2], corrected_bary );
148133 frag.depth = z;
149- // material 指针由调用方填写
150134
151135 out.push_back (frag);
152136 }
@@ -182,14 +166,14 @@ std::pair<bool, Vector3f> Rasterizer::GetBarycentricCoord(const Vector3f& p0,
182166
183167template <typename T>
184168T Rasterizer::Interpolate (const T& v0, const T& v1, const T& v2,
185- const Vector3f& barycentric_coord) {
169+ const Vector3f& barycentric_coord) const {
186170 return v0 * barycentric_coord.x + v1 * barycentric_coord.y +
187171 v2 * barycentric_coord.z ;
188172}
189173
190174Color Rasterizer::InterpolateColor (const Color& color0, const Color& color1,
191175 const Color& color2,
192- const Vector3f& barycentric_coord) {
176+ const Vector3f& barycentric_coord) const {
193177 auto color_r = FloatToUint8_t (
194178 static_cast <float >(color0[Color::kColorIndexRed ]) * barycentric_coord.x +
195179 static_cast <float >(color1[Color::kColorIndexRed ]) * barycentric_coord.y +
@@ -208,6 +192,31 @@ Color Rasterizer::InterpolateColor(const Color& color0, const Color& color1,
208192 return Color (color_r, color_g, color_b);
209193}
210194
195+ // 透视矫正helper函数:在透视投影下,1/w 在屏幕空间中是线性的// 因此需要先对 1/w 进行插值,再用结果矫正其他属性
196+ Rasterizer::PerspectiveCorrectionResult Rasterizer::PerformPerspectiveCorrection (
197+ float w0, float w1, float w2,
198+ float z0, float z1, float z2,
199+ const Vector3f& original_barycentric) const {
200+
201+ // 1. 插值 1/w (注意:这里传入的w0,w1,w2是原始的w值,需要先求倒数)
202+ float w0_inv = 1 .0f / w0;
203+ float w1_inv = 1 .0f / w1;
204+ float w2_inv = 1 .0f / w2;
205+ float w_inv_interpolated = Interpolate (w0_inv, w1_inv, w2_inv, original_barycentric);
206+
207+ // 2. 计算透视矫正的重心坐标
208+ Vector3f corrected_barycentric (
209+ original_barycentric.x * w0_inv / w_inv_interpolated,
210+ original_barycentric.y * w1_inv / w_inv_interpolated,
211+ original_barycentric.z * w2_inv / w_inv_interpolated
212+ );
213+
214+ // 3. 使用矫正的重心坐标插值深度值
215+ float interpolated_z = Interpolate (z0, z1, z2, corrected_barycentric);
216+
217+ return {corrected_barycentric, interpolated_z};
218+ }
219+
211220// Calculate the normal vector based on the vertices
212221// 根据顶点计算法向量
213222Vector3f Rasterizer::CalculateNormal (const Vector3f& v0, const Vector3f& v1,
0 commit comments