m0_58862449
m0_58862449
2021-06-23 16:24
浏览 59
已结题

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

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

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条回答 默认 最新

  • Feng_wwf
    NDSC专家-王文峯 2021-06-23 16:38

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

    点赞 评论
  • sdhexu
    sdhexu 2021-06-23 16:40

    重合的顶点,法线是否一致?UV纹理是否一致?

    点赞 评论
  • sdhexu
    sdhexu 2021-06-23 17:29

    一个立方体,UV展开之后大概就是这样。具体要看你模型是怎么展开UV的。图中,红色的边就是所谓的“接缝”。如果你渲染模式不对,或者UV不对,就会让模型看上去有接缝。。这是基本原理。具体原因得看你的具体情况啊。

    点赞 评论

相关推荐