m0_58862449 2021-06-23 16:24 采纳率: 0%
浏览 71
已结题

软光栅渲染器,同边三角形光栅化中间会有空隙

如图,三角形边框会有虚线,明明顶点是相同的,是扫描线的哪里写的有问题吗

void DeviceContext::scanLineFill(const VertexOut& left, const VertexOut& right, int yIndex)
{

	double dx = right.fragPos.x - left.fragPos.x;

	for (double x = left.fragPos.x; x <= right.fragPos.x; x += 1.0)
	{
		
		int xIndex = x;
		if (xIndex >= 0 && xIndex < m_device->getClientWidth())
		{
			//插值系数
			double lerpFactor = 0;
			if (dx != 0)
			{
				lerpFactor = (x - left.fragPos.x) / dx;
			}

			//深度测试
			//1/z’与x’和y'是线性关系的
			double oneOverZ = Lerp(left.oneOverZ, right.oneOverZ, lerpFactor);
			if (oneOverZ >= m_device->getZ(xIndex, yIndex))
			{
				m_device->setZ(xIndex, yIndex, oneOverZ);
				//透视矫正
				double w = 1.0 / oneOverZ;
				VertexOut out = Lerp(left, right, lerpFactor);
				out.fragPos = out.fragPos * w;
				out.fragPos.y = yIndex;
				out.tex.x *= w;
				out.tex.y *= w;
				out.normal.x *= w;
				out.normal.y *= w;
				out.normal.z *= w;
				out.color.x *= w;
				out.color.y *= w;
				out.color.z *= w;
				//画像素点颜色
				//m_device->DrawPixel(xIndex, yIndex, m_shader->pixelShader(out));
				m_device->DrawPixel(xIndex, yIndex, Vec4(0.0,1.0,0.0));
			}
		}
		
	}
}

void DeviceContext::drawTriangleTop(const VertexOut& v1, const VertexOut& v2, const VertexOut& v3)
{
	double slope1 = (v3.fragPos.x - v1.fragPos.x) / (v3.fragPos.y - v1.fragPos.y);
	double slope2 = (v3.fragPos.x - v2.fragPos.x) / (v3.fragPos.y - v2.fragPos.y);

	double curx1 = v1.fragPos.x;
	double curx2 = v2.fragPos.x;
	
	double dy = 0;//每次y增加一个像素
	for (double y = v1.fragPos.y; y <= v3.fragPos.y; y += 1)
	{
		int yIndex = y;
		if (y >= 0 && y < m_device->getClientHeight())
		{
			double t = dy / (v3.fragPos.y - v1.fragPos.y);

			//插值生成左右顶点
			VertexOut new1 = Lerp(v1, v3, t);
			VertexOut new2 = Lerp(v2, v3, t);
			
			new1.fragPos.x = floor(curx1);
			new2.fragPos.x = ceil(curx2);
			
			//扫描线填充
			if (new1.fragPos.x <= new2.fragPos.x)
			{
				scanLineFill(new1, new2, yIndex);
			}
			else
			{
				scanLineFill(new2, new1, yIndex);
			}
		}
		dy += 1.0;
		curx1 += slope1;
		curx2 += slope2;
	}
}

//画平底三角形 v1为上顶点
void DeviceContext::drawTriangleBottom(const VertexOut& v1, const VertexOut& v2, const VertexOut& v3)
{	
	double slope1 = (v2.fragPos.x - v1.fragPos.x) / (v2.fragPos.y - v1.fragPos.y);
	double slope2 = (v3.fragPos.x - v1.fragPos.x) / (v3.fragPos.y - v1.fragPos.y);
	
	double curx1 = v2.fragPos.x;
	double curx2 = v3.fragPos.x;

	double dy = 0;//每次y增加一个像素
	for (double y = v2.fragPos.y; y > v1.fragPos.y; y -= 1)
	{
		int yIndex = y;
		if (y >= 0 && y < m_device->getClientHeight())
		{
			double t = dy / (v2.fragPos.y - v1.fragPos.y);

			//插值左右顶点
			VertexOut new1 = Lerp(v2, v1, t);
			VertexOut new2 = Lerp(v3, v1, t);
			
			new1.fragPos.x = floor(curx1);
			new2.fragPos.x = ceil(curx2);
			
			//扫描线填充
			if (new1.fragPos.x <= new2.fragPos.x)
			{
				scanLineFill(new1, new2, yIndex);
			}
			else
			{
				scanLineFill(new2, new1, yIndex);
			}
			
		}
		dy += 1.0;
		curx1 -= slope1;
		curx2 -= slope2;
	}
	
	
}

void DeviceContext::triangleRasterization(const VertexOut& v1, const VertexOut& v2, const VertexOut& v3)
{
	std::vector<VertexOut> vertices{ v1,v2,v3 };
	std::sort(vertices.begin(), vertices.end(), [](VertexOut v1, VertexOut v2) { return v1.fragPos.y < v2.fragPos.y; });
	VertexOut top = vertices[0];
	VertexOut middle = vertices[1];
	VertexOut bottom = vertices[2];

	if (middle.fragPos.y == bottom.fragPos.y)
	{
		drawTriangleBottom(top, middle, bottom);
	}
	else if (top.fragPos.y == middle.fragPos.y)
	{
		drawTriangleTop(top, middle, bottom);
	}
	else
	{
		//插值求中间点
		double middleX = top.fragPos.x + (middle.fragPos.y - top.fragPos.y) / (bottom.fragPos.y - top.fragPos.y)*(bottom.fragPos.x - top.fragPos.x);
		double dy = middle.fragPos.y - top.fragPos.y;
		double t = dy / (bottom.fragPos.y - top.fragPos.y);

		VertexOut newMiddle = Lerp(top, bottom, t);
		newMiddle.fragPos.x = middleX;
		newMiddle.fragPos.y = middle.fragPos.y;
		
		//平顶
		drawTriangleTop(middle, newMiddle, bottom);
		//平底
		drawTriangleBottom(top, middle, newMiddle);
	}
}
  • 写回答

3条回答 默认 最新

  • 王大师王文峰 企业官方账号 2021-06-23 16:38
    关注

    望采纳,这个是底面,换个角度就行了

    评论

报告相同问题?

悬赏问题

  • ¥15 seatunnel-web使用SQL组件时候后台报错,无法找到表格
  • ¥15 fpga自动售货机数码管(相关搜索:数字时钟)
  • ¥15 用前端向数据库插入数据,通过debug发现数据能走到后端,但是放行之后就会提示错误
  • ¥30 3天&7天&&15天&销量如何统计同一行
  • ¥30 帮我写一段可以读取LD2450数据并计算距离的Arduino代码
  • ¥15 飞机曲面部件如机翼,壁板等具体的孔位模型
  • ¥15 vs2019中数据导出问题
  • ¥20 云服务Linux系统TCP-MSS值修改?
  • ¥20 关于#单片机#的问题:项目:使用模拟iic与ov2640通讯环境:F407问题:读取的ID号总是0xff,自己调了调发现在读从机数据时,SDA线上并未有信号变化(语言-c语言)
  • ¥20 怎么在stm32门禁成品上增加查询记录功能