在UV坐标中查找像素

我正在建立3D模型的光照贴图。 我的光照贴图algorithm需要确定光照贴图纹理中的哪些像素(stream明)落在网格面(三角形)的边界内…此过程发生在每个网格面上…

我使用重心坐标技术来完成这个任务。 它适用于大部分…这里是代码:

bool PixelIsWithinBounds( const D3DXVECTOR2 &t0, const D3DXVECTOR2 &t1, const D3DXVECTOR2 &t2, const D3DXVECTOR2 &pUV ) { // compute vectors D3DXVECTOR2 v0 = t1 - t0, v1 = t2 - t0, v2 = pUV - t0; // do bounds test for each position float f00 = D3DXVec2Dot( &v0, &v0 ); float f01 = D3DXVec2Dot( &v0, &v1 ); float f11 = D3DXVec2Dot( &v1, &v1 ); float f02 = D3DXVec2Dot( &v0, &v2 ); float f12 = D3DXVec2Dot( &v1, &v2 ); // Compute barycentric coordinates float invDenom = 1 / ( f00 * f11 - f01 * f01 ); float fU = ( f11 * f02 - f01 * f12 ) * invDenom; float fV = ( f00 * f12 - f01 * f02 ) * invDenom; // Check if point is in triangle if( ( fU >= 0 ) && ( fV >= 0 ) && ( fU + fV <= 1 ) ) return true; return false; } 

此function将input3个UV坐标(网格面)和一个像素UV坐标。 这种方法的问题是,如果像素仅被部分覆盖,则函数返回false(因为像素中心不在三角形内)。 我可以对三角形上的每个点进行重叠testing…我想知道是否有更有效的方法…因为这个过程每一代光照贴图都会发生很多次…

…有任何想法吗?

这里是一个屏幕截图,显示光照贴图生成后的网格面的端点…该面的拐角与像素面重叠,但不与像素中心重叠…algorithm将此像素保留为黑色(不亮)…

光照贴图生成后的网格面的屏幕截图

编辑:着色器代码来扩大像素

 //--------------------------------------------------------------// // Dilation Pass //--------------------------------------------------------------// PS_INPUT_Quad DilationPass_Vertex_Shader( VS_INPUT_Quad Input ) { PS_INPUT_Quad Output = ( PS_INPUT_Quad )0; Output.Position = mul( Input.Position, mOrtho ); Output.UV = Input.UV; return Output; } float4 DilationPass_Pixel_Shader( PS_INPUT_Quad Input ) : COLOR0 { float4 vC = tex2D( g_SamplerLightMap, Input.UV ); if( vC.w != 0 ) return vC; int nValidPixels = 0; float4 vFinalColor = 0; for( int i = 0; i < 8; ++i ) { float4 vNeighborColor = tex2D( g_SamplerLightMap, Input.UV + TexelKernel[ i ] ); if( vNeighborColor.w == 0 ) continue; //vFinalColor = ( length( vFinalColor ) > length( vNeighborColor ) ) ? vFinalColor : vNeighborColor; vFinalColor += vNeighborColor; nValidPixels++; } return vFinalColor / max( nValidPixels, 1 ); } 

首先,find落在三角形中的像素的过程称为光栅化。 您可能需要查看一些关于快速软件光栅化的文章,或者更好地将光照贴图构建过程(或者至less光栅化部分)移到GPU上,因为它会快得多。

光照贴图中存在两个可能的解决scheme。 一种解决scheme是基于图像的。 在正常栅格化三角形之后,使用像素着色器应用膨胀滤镜 ,以便用相邻的绘制像素填充未提取像素的值。 (你可以使用alpha通道来轻松地跟踪哪些像素被绘制。)运行一下这个过程,它会在光照贴图的每个补丁周围生长一个像素厚的边框。

另一个可能的解决scheme是保守的光栅化(谷歌它)。 这意味着光栅化接触基元的所有像素,而不是那些中心位于基元中的像素。 IIRC在软件光栅化器中对方程进行相当简单的修改; GPU硬件光栅化程序不直接支持它,但可以通过将每个三角形展开一个像素来进行模拟(如本文所示)。 这将会产生副作用,即先前水密的相邻三角形现在将重叠,这可能导致它自己的问题。 我可能坚持使用图像空间方法。