2014-09-27 78 views
3

我編寫了一個管理射燈影子映射的3D應用程序。要做到這一點,我使用經典的陰影貼圖技術(我在第一個渲染過程中填充深度紋理,在第二個渲染過程中,我比較從光線到第一個遮擋物的距離以及從光線到頂點位置的距離,以瞭解我的片段是否在陰影中)。使用立方體貼圖(OpenGL/GLSL)的點光源可能會產生柔和的陰影嗎?

這裏的一個屏幕截圖(點光/ 2D深度紋理陰影映射):

enter image description here

在這個例子中我使用使用函數「textureProjOffset」 PCF陰影映射技術。下面是我的片段着色器的一段代碼:

取樣使用:

sampler2DShadow Shadow2DSampler[MAX_LIGHTS_COUNT]; 

對於HARD陰影:

shadowFactor = textureProj(Shadow2DSampler[idx], ShadowCoords[idx]); 

對於PCF軟陰影:

我也有管理基本立方體貼圖陰影映射以管理當前應用於點光源的全向陰影映射。爲了在第一個渲染過程中做到這一點,我使用幾何着色器來分派由6個陰影邊界提供的投影和視圖矩陣(全部都在一次傳遞中!)這種技術的不同之處在於,使用6種渲染狀態來填充6個單獨的紋理)。

下面是截圖(點光源/立方深度紋理陰影映射):

enter image description here

正如你所看到的,它只能硬陰影映射。要恢復編碼到立方體貼圖中的深度值,我必須使用此函數的'紋理'(TextureProj不存在'samplerCube'和'samplerCubeShadow')。接下來,我必須計算光照位置和世界空間頂點位置之間的距離,然後將其轉換爲剪輯空間,因爲紋理中包含的深度值已經在剪輯空間中。

下面是片段着色器的一段代碼來查看進程:

取樣使用:

samplerCubeShadow ShadowCubeSampler[MAX_LIGHTS_COUNT]; 

對於HARD陰影:

float ConvertDistToClipSpace(vec3 lightDir_ws) 
{ 
    vec3 AbsVec = abs(lightDir_ws); 
    float LocalZcomp = max(AbsVec.x, max(AbsVec.y, AbsVec.z)); 

    float NormZComp = (NearFar.y + NearFar.x)/(NearFar.y - NearFar.x) 
     - (2.0f * NearFar.y * NearFar.x)/(LocalZcomp * NearFar.y - NearFar.x); 

    return ((NormZComp + 1) * 0.5f); 
} 

float GetBiased_Cube_Hard_ShadowFactor(vec3 vertexPosition_ws, int idx) 
{ 
    vec3 lightToVertexDir_ws = vertexPosition_ws - LightPos_ws.xyz; 
    float LightToVertexClipDist = ConvertDistToClipSpace(lightToVertexDir_ws); 

    float LightToOccluderClipDist = texture(
     ShadowCubeSampler[idx], vec4(lightToVertexDir_ws, LightToVertexClipDist)); 

    if (LightToOccluderClipDist < LightToVertexClipDist) 
     return (0.0f); 
    return (1.0f); 
} 

而且知道,那PCF SOFT使用立方體貼圖的陰影?我做了一些研究,顯然它不存在任何函數來恢復紋理偏移,就像使用簡單的2D紋理一樣,並在片段着色器中使用關鍵字「sampler2DShadow」。我錯了嗎 ? (但願如此!)。

我認爲有一個解決辦法(當然,如果不存在與立方體貼圖任何溶液的話):

顯然,以恢復紋理偏移我將不得不使用6個獨立的紋理(這樣的「陣列sampler2DShadow '大小爲6,而不是'samplerCubeShadow')。因此,我將擁有同樣統一的matrix4x4陣列,代表我在第一種情況下在光照空間中表示世界的表示方式,就像我在第一種情況下對於光斑映射所做的那樣。然後我將使用6種紋理的方法'textureProjOffset'。

那麼,您怎麼看?是否有可能使用cubemap來做PCF軟陰影?如果不是這樣,我的解決方案是否正確?使用'samplerCube'或'samplerCubeShadow'可以使用像'textureProjOffset'這樣的函數嗎?還是有其他選擇嗎?

非常感謝您的幫助!

回答

2

我知道爲立方體貼圖實現PCF柔和陰影的唯一方法是用小偏移量多次查詢紋理。例如在這個GPU Gems article (12.4)中描述了這種方法。

+0

非常感謝您的回答。再見。 – user1364743 2014-09-28 16:33:22

+3

在現代的AMD和NV驅動程序上,如果您使用'samplerCubeShadow'和'GL_LINEAR'作爲過濾器,它將自動執行2x2 PCF。一個2×2的窗口雖然很小,但你應該將硬件PCF與幾個偏移量結合起來,以增加有效的窗口大小。那篇文章沒有利用硬件的能力來做2x2 PCF,因爲它的年齡,但這通常是你應該如何處理這個問題。如果利用這一點,您可以使用4個查找來實現4x4 PCF,而不是16個。 – 2014-09-29 17:41:49