processTexturemapping之setuptextureMapping
2021-03-04 13:09 kk20161206 阅读(133) 评论(0) 编辑 收藏 举报1. setuptextureMapping函数里会calculateTexelCorners,这个函数会光栅化每个三角形里的每个corner,
// Rasterize each triangle offset by the corner offsets for (int32 CornerIndex = 0; CornerIndex < NumTexelCorners; CornerIndex++) { FTriangleRasterizer<FTexelCornerRasterPolicy> TexelCornerRasterizer(FTexelCornerRasterPolicy( Scene, TexelToCornersMap, CornerIndex, bDebugThisMapping )); TexelCornerRasterizer.DrawTriangle( V0, V1, V2, V0.TextureCoordinates[UVIndex] * FVector2D(TexelToCornersMap.GetSizeX(), TexelToCornersMap.GetSizeY()) + CornerOffsets[CornerIndex], V1.TextureCoordinates[UVIndex] * FVector2D(TexelToCornersMap.GetSizeX(), TexelToCornersMap.GetSizeY()) + CornerOffsets[CornerIndex], V2.TextureCoordinates[UVIndex] * FVector2D(TexelToCornersMap.GetSizeX(), TexelToCornersMap.GetSizeY()) + CornerOffsets[CornerIndex], false ); }
注意这里光栅化的时候会设置texeltocorner为valid,而且得到位置、切线等信息:
void FTexelCornerRasterPolicy::ProcessPixel(int32 X, int32 Y, const InterpolantType& Vertex, bool BackFacing) { FTexelToCorners& TexelToCorners = TexelToCornersMap(X, Y); #if ALLOW_LIGHTMAP_SAMPLE_DEBUGGING if (bDebugThisMapping && X == Scene.DebugInput.LocalX && Y == Scene.DebugInput.LocalY) { int32 TempBreak = 0; } #endif TexelToCorners.Corners[CornerIndex].WorldPosition = Vertex.WorldPosition; TexelToCorners.WorldTangentX = Vertex.WorldTangentX; TexelToCorners.WorldTangentY = Vertex.WorldTangentY; TexelToCorners.WorldTangentZ = Vertex.WorldTangentZ; TexelToCorners.bValid[CornerIndex] = true; }
2. 设置是否用保守的纹素光栅化,同时贴图映射为双线性滤波,
为true,则 会遍历每个三角形,x,y双重循环1到7,计算sampleOffset及sample权重然后会通过staticLightingRasterpolicy计算图素对应的顶点sample,
FTriangleRasterizer<FStaticLightingRasterPolicy> TexelMappingRasterizer(FStaticLightingRasterPolicy( Scene, TexelToVertexMap, SampleWeight, TriangleNormal, bDebugThisMapping, GeneralSettings.bUseMaxWeight )); TexelMappingRasterizer.DrawTriangle( V0, V1, V2, UV0 + FVector2D(SampleXOffset, SampleYOffset), UV1 + FVector2D(SampleXOffset, SampleYOffset), UV2 + FVector2D(SampleXOffset, SampleYOffset), false );
光栅化得到texelTOVertex数据
void FStaticLightingRasterPolicy::ProcessPixel(int32 X,int32 Y,const InterpolantType& Interpolant,bool BackFacing) { FTexelToVertex& TexelToVertex = TexelToVertexMap(X,Y); bool bDebugThisTexel = false; #if ALLOW_LIGHTMAP_SAMPLE_DEBUGGING if (bDebugThisMapping && X == Scene.DebugInput.LocalX && Y == Scene.DebugInput.LocalY) { bDebugThisTexel = true; } #endif if (bUseMaxWeight) { if (SampleWeight > TexelToVertex.MaxSampleWeight) { // Use the sample with the largest weight. // This has the disadvantage compared averaging based on weight that it won't be well centered for texels on a UV seam, // But it has the advantage that the final position is guaranteed to be valid (ie actually on a triangle), // Even for split texels which are mapped to triangles in different parts of the mesh. TexelToVertex.MaxSampleWeight = SampleWeight; TexelToVertex.WorldPosition = Interpolant.Vertex.WorldPosition; TexelToVertex.ElementIndex = Interpolant.ElementIndex; for( int32 CurCoordIndex = 0; CurCoordIndex < MAX_TEXCOORDS; ++CurCoordIndex ) { TexelToVertex.TextureCoordinates[ CurCoordIndex ] = Interpolant.Vertex.TextureCoordinates[ CurCoordIndex ]; } } // Weighted average of normal, improves the case where the position chosen by the max weight has a different normal than the rest of the texel // Eg, small extrusions from an otherwise flat surface, and the texel center lies on the perpendicular extrusion //@todo - only average normals within the texel radius to improve the split texel case? TexelToVertex.WorldTangentX += Interpolant.Vertex.WorldTangentX * SampleWeight; TexelToVertex.WorldTangentY += Interpolant.Vertex.WorldTangentY * SampleWeight; TexelToVertex.WorldTangentZ += Interpolant.Vertex.WorldTangentZ * SampleWeight; checkSlow(!TriangleNormal.ContainsNaN()); TexelToVertex.TriangleNormal += TriangleNormal * SampleWeight; TexelToVertex.TotalSampleWeight += SampleWeight; } else if (!bUseMaxWeight) { // Update the sample weight, and compute the scales used to update the sample's averages. const float NewTotalSampleWeight = TexelToVertex.TotalSampleWeight + SampleWeight; const float OldSampleWeight = TexelToVertex.TotalSampleWeight / NewTotalSampleWeight; const float NewSampleWeight = SampleWeight / NewTotalSampleWeight; TexelToVertex.TotalSampleWeight = NewTotalSampleWeight; // Add this sample to the mapping. TexelToVertex.WorldPosition = TexelToVertex.WorldPosition * OldSampleWeight + Interpolant.Vertex.WorldPosition * NewSampleWeight; TexelToVertex.WorldTangentX = FVector4(TexelToVertex.WorldTangentX) * OldSampleWeight + Interpolant.Vertex.WorldTangentX * NewSampleWeight; TexelToVertex.WorldTangentY = FVector4(TexelToVertex.WorldTangentY) * OldSampleWeight + Interpolant.Vertex.WorldTangentY * NewSampleWeight; TexelToVertex.WorldTangentZ = FVector4(TexelToVertex.WorldTangentZ) * OldSampleWeight + Interpolant.Vertex.WorldTangentZ * NewSampleWeight; TexelToVertex.TriangleNormal = TriangleNormal; TexelToVertex.ElementIndex = Interpolant.ElementIndex; for( int32 CurCoordIndex = 0; CurCoordIndex < MAX_TEXCOORDS; ++CurCoordIndex ) { TexelToVertex.TextureCoordinates[ CurCoordIndex ] = TexelToVertex.TextureCoordinates[ CurCoordIndex ] * OldSampleWeight + Interpolant.Vertex.TextureCoordinates[ CurCoordIndex ] * NewSampleWeight; } } }
如果为false,则只是在纹素中心光栅化,不用考虑权重混合。如果中心不在三角形内则纹素不会被映射。
3. 最后这个函数AdjustRepresentativeSurfelForTexelsTextureMapping会设置lightmapData为是否映射,
if (LightMapData != nullptr) { // Mark the texel as mapped to some geometry in the scene FGatheredLightMapSample& CurrentLightSample = (*LightMapData)(X, Y); CurrentLightSample.bIsMapped = true; }
会重新计算调整texelToVertex的坐标、tangent等信息并且检测会不会重叠,重叠的话,会进行偏移。