光栅渲染器(三)光栅化2D三角形
2017-10-29 08:59
337 查看
这篇主要讲扫描转换方法光栅化2d三角形
之前我们已经完成了线段的绘制,而三角形其实3条线段的首尾相连,所以我们只要给出三个不在同一直线的顶点就能绘制三角形
如下
这样一来就完成了相对高效且完全通用的画线算法
接下来在重绘函数里测试代码
奇怪这个三角形怎么只有线段,好吧,我们需要填充三角形
我们需要用一个个线段填充三角形的内部
这是一个平底三角形,我们可以通过从最上方顶点开始从上而下绘制线段
我们可以发现任何一个三角形都是由2个平底三角形组成,只要让他的顶点根据y坐标排序,挑选出y坐标大小排序在中间的点,做平行x轴的直线,就可以将任何一个非平底或平顶三角形分割成2个平底或平顶三角形。
算法实现如下
我写的顶点排序算法有些复杂,我又心急接下来光栅渲染器的实现,就先不在这里纠结了,如果大家有更好的算法,希望告知
最终完成了,一个简陋,实现算法糟糕的2d三角形
之前我们已经完成了线段的绘制,而三角形其实3条线段的首尾相连,所以我们只要给出三个不在同一直线的顶点就能绘制三角形
一、完善画线算法
Bresenham算法是种相对高效的算法,但目前我项目中的这一算法在顶点x坐标或y坐标相同时还无法完成绘制。所以这一情况下,我选择DDA算法取代。如下
void DrawLine(point_t v1, point_t v2, color_t c) { if (v1.x == v2.x || v1.y == v2.y) { DrawLineDDA2d(v1, v2, c); } else { DrawLineBre(v1, v2, c); } }
这样一来就完成了相对高效且完全通用的画线算法
二、用画线算法绘制三角形
算法很简单,就是绘制三条首尾相连的三角形void DrawTriangle(point_t v1, point_t v2, point_t v3,color_t c) { if (v1.x == v2.x&&v1.x == v3.x) return; if (v1.y == v2.y&&v1.y == v3.y) return; DrawLine(v1, v2,c); DrawLine(v2, v3,c); DrawLine(v3, v1,c); }
接下来在重绘函数里测试代码
// 重绘函数 void myDisplay(void) { glClear(GL_COLOR_BUFFER_BIT); // 清屏幕 glBegin(GL_POINTS); point_t v1{ 10,15 }; point_t v2{ 400,405 }; point_t v3{ 100,405 }; color_t c{ 1.0,1.0,0,1.0 };//黄色 DrawTriangle(v1, v2, v3, c); glEnd(); glFlush(); // 将所有输出到显示屏上 }
奇怪这个三角形怎么只有线段,好吧,我们需要填充三角形
三、扫描转换算法
int Sgn(float d)//符号判断 { if (d<0) return -1; else if (d == 0) return 0; else return 1; } // 计算插值:t 为 [0, 1] 之间的数值 float interp(float x1, float x2, float t) { return x1 + (x2 - x1) * t; }
我们需要用一个个线段填充三角形的内部
这是一个平底三角形,我们可以通过从最上方顶点开始从上而下绘制线段
//扫描转换填充三角形 void DrawTriangle_ScanConversion(point_t v1, point_t v2, point_t v3, color_t c) { float dy =abs(v2.y-v1.y); int x = v1.x; int y = v1.y; int x2 = v2.x; int y2 = v2.y; int x3 = v3.x; int y3 = v3.y; int s = Sgn(y - y3); point_t newV1=v1; point_t newV2=v1; for (int i = 1; i<dy; i++) { float f = i / dy; newV1.x = interp(x, x2, f)+0.5; newV1.y -= s; newV2.x = interp(x, x3, f)+0.5; newV2.y -= s; DrawLine(newV1, newV2, c); } }
四、填充三角形
之前的算法只适合平底三角形,接下来我们把之前算法拓展到任何一种三角形我们可以发现任何一个三角形都是由2个平底三角形组成,只要让他的顶点根据y坐标排序,挑选出y坐标大小排序在中间的点,做平行x轴的直线,就可以将任何一个非平底或平顶三角形分割成2个平底或平顶三角形。
算法实现如下
void DrawTriangle(point_t v1, point_t v2, point_t v3,color_t c) { if (v1.x == v2.x&&v1.x == v3.x) return; if (v1.y == v2.y&&v1.y == v3.y) return; //DrawLine(v1, v2,c); //DrawLine(v2, v3,c); //DrawLine(v3, v1,c); vector<float> PointY{ v1.y,v2.y,v3.y }; sort(PointY.begin(), PointY.end()); float midY = PointY[1]; float minY = PointY[0]; float maxY = PointY[2]; point_t MaxYPoint; point_t MidYPoint; point_t MinYPoint; if (midY != minY && midY != maxY) { if (midY == v1.y) { MidYPoint = v1; if (maxY == v2.y) { MaxYPoint = v2; MinYPoint = v3; } if (maxY == v3.y) { MaxYPoint = v3; MinYPoint = v2; } } else if (midY == v2.y) { MidYPoint = v2; if (maxY == v1.y) { MaxYPoint = v1; MinYPoint = v3; } if (maxY == v3.y) { MaxYPoint = v3; MinYPoint = v1; } } else if (midY == v3.y) { MidYPoint = v3; if (maxY == v1.y) { MaxYPoint = v1; MinYPoint = v2; } if (maxY == v2.y) { MaxYPoint = v2; MinYPoint = v1; } } point_t newV; float t = (midY - maxY) / (minY - maxY); newV.x = interp(MaxYPoint.x, MinYPoint.x, t); newV.y = midY; DrawTriangle_ScanConversion(MaxYPoint, MidYPoint, newV, c); DrawTriangle_ScanConversion(MinYPoint, MidYPoint, newV, c); } else { if(v1.y==v2.y) DrawTriangle_ScanConversion(v3, v1,v2, c); if (v1.y == v3.y) DrawTriangle_ScanConversion(v2, v1, v3, c); if (v3.y == v2.y) DrawTriangle_ScanConversion(v1, v3, v2, c); } }
我写的顶点排序算法有些复杂,我又心急接下来光栅渲染器的实现,就先不在这里纠结了,如果大家有更好的算法,希望告知
最终完成了,一个简陋,实现算法糟糕的2d三角形
相关文章推荐
- 2D三角形光栅化算法
- iOS开发UI-利用Quartz2D 实现基本绘图(画三角形、矩形、圆、圆弧)
- 三角形光栅化算法
- Flash3D学习计划(三)——学习VB,IB相关,理解三角形顶点顺序;在屏幕上显示2D矩形,并实现缩放,平移,旋转
- 3D软引擎之三角形光栅化
- ios-day14-01(使用Quartz 2D绘制基本图形——线、三角形、矩形、圆、圆弧、扇形、文字、图片等)
- iOS Quartz 2D 绘制图形(线段\三角形\矩形\圆\圆弧等)
- Quartz2d (画线 矩形 圆 三角形 弧线 扇形 进度圈等)
- 基于tilemap,生成2D平面的三角形组成的navigation mesh
- iOS开发UI-利用Quartz2D 实现基本绘图(画三角形、矩形、圆、圆弧)
- 从零开始写光栅化渲染器3:三角形光栅化
- 判断一个点是否在 2D 三角形内(转)
- DirectX 3D_基础之模型表示 顶点格式 三角形 索引 虚拟摄像机 投影窗口 绘制流水线 局部坐标系 观察坐标系 世界坐标系 背面消隐 光照 裁剪 投影 视口变换 光栅化
- Quartz2d从易到难全解析---绘制封闭三角形,四边形
- 2D中判断点是否在某一三角形内算法
- [软件渲染器入门]四,填充光栅化的三角形并使用深度缓冲
- 70-Quartz2D的具体使用(画线,三角形,矩形,圆弧,扇形,重绘(下载提示条),画饼图,定时器(雪花下落),模仿系统的控件,矩形变换)
- 2D空间中判断一点是否在三角形内
- 利用Quartz2D-contex绘制三角形
- 【CG】三角形的光栅化