GAMES101-现代计算机图形学学习笔记(作业02)
GAMES101-現代計算機圖形學學習筆記(作業02)
Assignment 02
- GAMES101-現代計算機圖形學學習筆記(作業02)
- 作業
- 作業描述
- 需要補充的函數
- 思路
- 結果
原課程視頻鏈接以及官網
b站視頻鏈接: link.
課程官網鏈接: link.
作業
作業描述
在上次作業中,雖然我們在屏幕上畫出一個線框三角形,但這看起來并不是 那么的有趣。所以這一次我們繼續推進一步——在屏幕上畫出一個實心三角形, 換言之,柵格化一個三角形。上一次作業中,在視口變化之后,我們調用了函數 rasterize_wireframe(const Triangle& t)。但這一次,你需要自己填寫并調用函數 rasterize_triangle(const Triangle& t)。
提高篇:用 super-sampling 處理 Anti-aliasing : 你可能會注意到,當我們放大圖像時,圖像邊緣會有鋸齒感。我們可以用 super-sampling 來解決這個問題,即對每個像素進行 2 * 2 采樣,并比較前后的結果 (這里 并不需要考慮像素與像素間的樣本復用)。需要注意的點有,對于像素內的每一個樣本都需要維護它自己的深度值,即每一個像素都需要維護一個 sample list。最后,如果你實現正確的話,你得到的三角形不應該有不正常的黑邊。
需要補充的函數
rasterize_triangle(): 執行三角形柵格化算法
static bool insideTriangle(): 測試點是否在三角形內。你可以修改此函 數的定義,這意味著,你可以按照自己的方式更新返回類型或函數參數。
思路
①三角形柵格算法
作業要求已經給出了*rasterize_triangle()*函數的工作流程:
老師這里要求實現的是Barycentric Algorithm(三角形柵格化),下面幾個點可能需要注意一下:
①尋找三角形的bounding box:根據三角形的三個坐標,找出最大x,最小x,最大y,最小y坐標即可,注意最小x,y坐標需要取比原數小,最大x,y坐標需要取比原數大
②點是否在三角形內:只需要連接點和三角形個點,形成一系列向量,然后判斷它們的叉乘結果的z值是否統一即可
③MSAA 4X 深度:把一個點看成一個格子,判斷里面4個小點是否落在三角形內,然后找到其中插值的最小z值,和幀緩沖中的z值進行比較替換即可。
③MSAA 4X 顏色:
判斷有4個小點中有幾個小點落入三角形,然后按比例對顏色進行采樣即可。
光柵化函數:
//Screen space rasterization void rst::rasterizer::rasterize_triangle(const Triangle& t) {auto v = t.toVector4();// bounding boxfloat min_x = std::min(v[0][0], std::min(v[1][0], v[2][0]));float max_x = std::max(v[0][0], std::max(v[1][0], v[2][0]));float min_y = std::min(v[0][1], std::min(v[1][1], v[2][1]));float max_y = std::max(v[0][1], std::max(v[1][1], v[2][1]));min_x = (int)std::floor(min_x);max_x = (int)std::ceil(max_x);min_y = (int)std::floor(min_y);max_y = (int)std::ceil(max_y);bool MSAA = false;//MSAA 4Xif (MSAA) {// 格子里的細分四個小點坐標std::vector<Eigen::Vector2f> pos{{0.25,0.25},{0.75,0.25},{0.25,0.75},{0.75,0.75},};for (int x = min_x; x <= max_x; x++) {for (int y = min_y; y <= max_y; y++) {// 記錄最小深度float minDepth = FLT_MAX;// 四個小點中落入三角形中的點的個數int count = 0;// 對四個小點坐標進行判斷 for (int i = 0; i < 4; i++) {// 小點是否在三角形內if (insideTriangle((float)x + pos[i][0], (float)y + pos[i][1], t.v)) {// 如果在,對深度z進行插值auto tup = computeBarycentric2D((float)x + pos[i][0], (float)y + pos[i][1], t.v);float alpha;float beta;float gamma;std::tie(alpha, beta, gamma) = tup;float w_reciprocal = 1.0 / (alpha / v[0].w() + beta / v[1].w() + gamma / v[2].w());float z_interpolated = alpha * v[0].z() / v[0].w() + beta * v[1].z() / v[1].w() + gamma * v[2].z() / v[2].w();z_interpolated *= w_reciprocal;minDepth = std::min(minDepth, z_interpolated);count++;}}if (count != 0) {if (depth_buf[get_index(x, y)] > minDepth) {Vector3f color = t.getColor() * count / 4.0;Vector3f point(3);point << (float)x, (float)y, minDepth;// 替換深度depth_buf[get_index(x, y)] = minDepth;// 修改顏色set_pixel(point, color);}}}}}else {for (int x = min_x; x <= max_x; x++) {for (int y = min_y; y <= max_y; y++) {if (insideTriangle((float)x + 0.5, (float)y + 0.5, t.v)) {auto tup = computeBarycentric2D((float)x + 0.5, (float)y + 0.5, t.v);float alpha;float beta;float gamma;std::tie(alpha, beta, gamma) = tup;float w_reciprocal = 1.0 / (alpha / v[0].w() + beta / v[1].w() + gamma / v[2].w());float z_interpolated = alpha * v[0].z() / v[0].w() + beta * v[1].z() / v[1].w() + gamma * v[2].z() / v[2].w();z_interpolated *= w_reciprocal;if (depth_buf[get_index(x, y)] > z_interpolated) {Vector3f color = t.getColor();Vector3f point(3);point << (float)x, (float)y, z_interpolated;depth_buf[get_index(x, y)] = z_interpolated;set_pixel(point, color);}}}}} }判斷點是否位于三角形內函數
static bool insideTriangle(double x, double y, const Vector3f* _v) { // TODO : Implement this function to check if the point (x, y) is inside the triangle represented by _v[0], _v[1], _v[2]Eigen::Vector2f p;p << x, y;Eigen::Vector2f AB = _v[1].head(2) - _v[0].head(2);Eigen::Vector2f BC = _v[2].head(2) - _v[1].head(2);Eigen::Vector2f CA = _v[0].head(2) - _v[2].head(2);Eigen::Vector2f AP = p - _v[0].head(2);Eigen::Vector2f BP = p - _v[1].head(2);Eigen::Vector2f CP = p - _v[2].head(2);// 判斷每個z坐標是否統一return AB[0] * AP[1] - AB[1] * AP[0] > 0 && BC[0] * BP[1] - BC[1] * BP[0] > 0&& CA[0] * CP[1] - CA[1] * CP[0] > 0; }結果
以下是結果:
以下依次是沒有做MSAA 4X的結果和做了MSAA 4X的結果:
這個光柵化算法其實是比較慢的,一個是自己實現的問題,第二個是從bounding box來看,會掃描很多多余的像素。這里貼幾個鏈接,里面提到了其他的光柵化算法,以后有機會可以改成其他光柵化的算法來實現:
鏈接: http://www.sunshine2k.de/coding/java/TriangleRasterization/TriangleRasterization.html#algo1.
https://www.thecrazyprogrammer.com/2017/01/bresenhams-line-drawing-algorithm-c-c.html.
https://blog.csdn.net/cppyin/article/details/6232453.
總結
以上是生活随笔為你收集整理的GAMES101-现代计算机图形学学习笔记(作业02)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 北京“曼联梦剧场”项目开业,迎接中国球迷
- 下一篇: 测试计划包括哪些内容?目的和意义是什么?