OpenGL接口的基本实现3[转]

OpenGL接口的基本实现3[转]

目录

OpenGL接口的基本实现3[转]

普通三角形

添加颜色

普通三角形

//三角形边信息,从y低到高
class   Ege
{
public:
    int     _x1;
    int     _y1;

    int     _x2;
    int     _y2;
    Ege(int x1,int y1,int x2,int y2)
    {
        if (y1 < y2)
        {
            _x1 =   x1;
            _y1 =   y1;

            _x2 =   x2;
            _y2 =   y2;
        }
        else
        {
            _x1 =   x2;
            _y1 =   y2;

            _x2 =   x1;
            _y2 =   y1;
        }
    }
};


//水平线段,从x小到大
class   Span
{
public:
    int     _xStart;
    int     _xEnd;
    int     _y;
public:
    Span(int xStart,int xEnd,int y)
    {
        if (xStart < xEnd)
        {
            _xStart =   xStart;
            _xEnd   =   xEnd;
            _y      =   y;
        }
        else
        {
            _xStart =   _xEnd;
            _xEnd   =   _xStart;
            _y      =   y;
        }
    }
};


//绘制从一个边到另一个边的水平线
void    drawSpan(const Span& span)
{
    for (int x = span._xStart ; x < span._xEnd; ++ x)
    {
        setPixel(x,span._y,_color);
    }
}


//通过两条边信息画出一个三角形  e1长边 e2短边
void    drawEge(const Ege& e1,const Ege& e2)
{
    //获取最长的一条边的y轴跨度
    float   yOffset1    =   e1._y2 - e1._y1;
    if (yOffset1 == 0)
    {
        return;
    }

    //获取另一条边的y轴跨度
    float   yOffset     =   e2._y2 - e2._y1;
    if (yOffset == 0)
    {
        return;
    }
	
	//e2边 x方向上最大跨度
    float   xOffset =   e2._x2 - e2._x1;
	//x水平移动距离
    float   scale   =   0;
	//看做相似三角形,等比例问题
	//增长一个y轴像素,x轴增加多少
    float step =  1.0f/yOffset;

    //e1长边x方向上最大跨度
    float   xOffset1    =   e1._x2 - e1._x1;
	//起点位置
    float   scale1      =   (float)(e2._y1 - e1._y1)/yOffset1;
	//增长一个y轴像素, x水平移动距离
    float   step1       =   1.0f/yOffset1;
	
    //y轴以一格像素递增,以短边为基准
    for (int y = e2._y1 ; y < e2._y2 ; ++ y)
    {
        int     x1  =   e1._x1 + (int)(scale1 * xOffset1);
        int     x2  =   e2._x1 + (int)(scale * xOffset);
        Span    span(x1,x2,y);
        drawSpan(span);

        //y轴每增加一个像素,x轴移动等比例的像素单位
        scale   +=  step;
        scale1  +=  step1;
    }
}


//绘制三角形
void    drawTriangle(int2 p0,int2 p1,int2 p2)
{
   //由三个定点信息生成三条边
    Ege eges[3]  =   
    {
        Ege(p0.x,p0.y,p1.x,p1.y),
        Ege(p1.x,p1.y,p2.x,p2.y),
        Ege(p2.x,p2.y,p0.x,p0.y),
    };
	
    int iMax    =   0;
	
	//寻找y轴跨度最大的边
	//先获取一条边的y轴
    int length  =   eges[0]._y2 - eges[0]._y1;
    
	//遍历,获取y轴跨度最大的边
    for (int i = 1 ;i < 3 ; ++ i)
    {
        int len =   eges[i]._y2 - eges[i]._y1;
        if (len > length)
        {
            length  =   len;
            iMax    =   i;

        }
    }
	
    int iShort1 =   (iMax + 1)%3;
    int iShort2 =   (iMax + 2)%3;

    drawEge(eges[iMax],eges[iShort1]);
    drawEge(eges[iMax],eges[iShort2]);
}
  • 输出:

添加颜色

class   Span
{
public:
	int     _xStart;
	int     _xEnd;
	Rgba    _colorStart;
	Rgba    _colorEnd;
	int     _y;

public:
	Span(int xStart, int xEnd, int y, Rgba colorStart, Rgba colorEnd)
	{
		if (xStart < xEnd)
		{
			_xStart = xStart;
			_xEnd = xEnd;
			_colorStart = colorStart;
			_colorEnd = colorEnd;
			_y = y;
		}
		else
		{
			_xStart = _xEnd;
			_xEnd = _xStart;

			_colorStart = colorEnd;
			_colorEnd = colorStart;
			_y = y;
		}
	}
};

class   Ege
{
public:
	int     _x1;
	int     _y1;
	Rgba    _color1;

	int     _x2;
	int     _y2;
	Rgba    _color2;

	Ege(int x1, int y1, Rgba color1, int x2, int y2, Rgba color2)
	{
		if (y1 < y2)
		{
			_x1 = x1;
			_y1 = y1;
			_color1 = color1;

			_x2 = x2;
			_y2 = y2;
			_color2 = color2;
		}
		else
		{
			_x1 = x2;
			_y1 = y2;
			_color1 = color2;

			_x2 = x1;
			_y2 = y1;
			_color2 = color1;
		}
	}
};



void    drawTriangle(int2 p0, int2 p1, int2 p2, Rgba c0, Rgba c1, Rgba c2)
{
	Ege eges[3] =
	{
		Ege(p0.x,p0.y,c0,   p1.x,p1.y,c1),
		Ege(p1.x,p1.y,c1,   p2.x,p2.y,c2),
		Ege(p2.x,p2.y,c2,   p0.x,p0.y,c0),
	};
	int iMax = 0;
	int length = eges[0]._y2 - eges[0]._y1;

	for (int i = 1; i < 3; ++i)
	{
		int len = eges[i]._y2 - eges[i]._y1;
		if (len > length)
		{
			length  =   len;
            iMax    =   i;
		}
	}
	int iShort1 = (iMax + 1) % 3;
	int iShort2 = (iMax + 2) % 3;

	drawEge(eges[iMax], eges[iShort1]);
	drawEge(eges[iMax], eges[iShort2]);
}



void    drawEge(const Ege& e1, const Ege& e2)
{
	float   yOffset1 = e1._y2 - e1._y1;
	if (yOffset1 == 0)
	{
		return;
	}

	float   yOffset = e2._y2 - e2._y1;
	if (yOffset == 0)
	{
		return;
	}
	float   xOffset = e2._x2 - e2._x1;
	float   scale = 0;
	float   step = 1.0f / yOffset;


	float   xOffset1 = e1._x2 - e1._x1;
	float   scale1 = (float)(e2._y1 - e1._y1) / yOffset1;
	float   step1 = 1.0f / yOffset1;

	for (int y = e2._y1; y < e2._y2; ++y)
	{
		int     x1 = e1._x1 + (int)(scale1 * xOffset1);
		int     x2 = e2._x1 + (int)(scale * xOffset);
		Rgba    color2 = colorLerp(e2._color1, e2._color2, scale);
		Rgba    color1 = colorLerp(e1._color1, e1._color2, scale1);

		Span    span(x1, x2, y, color1, color2);
		drawSpan(span);

		scale += step;
		scale1 += step1;
	}
}


void    drawSpan(const Span& span)
{
	float   length = span._xEnd - span._xStart;
	for (int x = span._xStart; x < span._xEnd; ++x)
	{
		Rgba  color = colorLerp(
			 span._colorStart
			,span._colorEnd
			,(float)(x - span._xStart) / length
		);
		setPixel(x, span._y, color);
	}
}
	
  • 显示:

  •  优化1:
void    drawSpan(const Span& span)
{
    float   length  =   span._xEnd - span._xStart;
    float   scale   =   0;
    float   step    =   1.0f/length;
    for (int x = span._xStart ; x < span._xEnd; ++ x)
    {
        Rgba    color   =   colorLerp(
             span._colorStart
            ,span._colorEnd
            ,scale
            );
        scale   +=  step;

        setPixel(x,span._y,color);
    }
}
  • 优化2:

  •  优化3:
    •  三角形的点在视图窗口左右两侧外的情况:
void    drawSpan(const Span& span)
{
    float   length  =   span._xEnd - span._xStart;
    float   scale   =   0;
    float   step    =   1.0f/length;
    int     startX  =   tmax<int>(span._xStart,0);
    int     endX    =   tmin<int>(span._xEnd,_width);
            scale   +=  (startX - span._xStart)/length;
    for (int x = startX ; x < endX; ++ x)
    {
        Rgba    color   =   colorLerp(
             span._colorStart
            ,span._colorEnd
            ,scale
            );
        scale   +=  step;

        setPixelEx(x,span._y,color);
    }
}
  • 三角形的点在视图窗口上下两侧外的情况:
 void    drawEge(const Ege& e1,const Ege& e2)
 {
     float   yOffset1    =   e1._y2 - e1._y1;
     if (yOffset1 == 0)
     {
         return;
     }

     float   yOffset     =   e2._y2 - e2._y1;
     if (yOffset == 0)
     {
         return;
     }
     float   xOffset =   e2._x2 - e2._x1;
     float   scale   =   0;
     float   step    =   1.0f/yOffset;
     int     startY  =   tmax<int>(e2._y1,0);
     int     endY    =   tmin<int>(e2._y2,_height);
             scale   +=  (startY - e2._y1)/yOffset;


     float   xOffset1    =   e1._x2 - e1._x1;
     float   scale1      =   (float)(e2._y1 - e1._y1)/yOffset1;
     float   step1       =   1.0f/yOffset1;

     int     startY1     =   tmax<int>(e1._y1,0);
     int     endY1       =   tmin<int>(e1._y2,_height);
             scale1      +=  (startY1 - e1._y1)/yOffset1;

     for (int y = startY ; y < endY ; ++ y)
     {
         int     x1      =   e1._x1 + (int)(scale1 * xOffset1);
         int     x2      =   e2._x1 + (int)(scale * xOffset);
         Rgba    color2  =   colorLerp(e2._color1,e2._color2,scale);
         Rgba    color1  =   colorLerp(e1._color1,e1._color2,scale1);

         Span    span(x1,x2,y,color1,color2);
         drawSpan(span);

         scale   +=  step;
         scale1  +=  step1;

     }
 }

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值