2011-06-24 123 views
4

我正在傳遞到頂點着色器(glsl)2紋理:從屏幕和更小的法線貼圖。 法線圖縮放爲屏幕大小。因此,如果第一個紋理是1152×864像素,法線貼圖是256×256,則它將從其大小縮放到較大。在着色器中平鋪紋理

我該如何平鋪?例如。使其尺寸爲256×256,並通過所有紋理進行拼貼。


UPD

例如,我的主要(大)紋理映射這樣的:

[0.17, 0.61, 0.33, 0.83] 

相反的:

[0, 0, 1, 1] 

這樣我正常紋理也被映射爲第一個座標。所以我看到它的一個小的映射矩形。我如何將它映射到着色器的全尺寸?

+0

不知道關於OpenGL,但在DirectX中,這是一個採樣器的用例。 OGL會有類似的東西。 –

回答

6

它會從它的大小縮放到更大。

不,它肯定不會。這是關於紋理的常見誤解。紋理只不過是花哨的查找表。紋理相對於彼此不是「縮放」的;這僅僅是你使用什麼紋理座標的問題。

在所有可能的情況下,您正在做的是使用與法線貼圖相同的紋理座標作爲屏幕紋理。由於我們可能在討論標準化的紋理座標,所以這意味着您將同一個[0,1]範圍映射到它們兩個。

爲了達到你所說的效果,你需要爲你的普通紋理計算紋理座標,以滿足你所需要的紋理座標。所以如果你有一個相對於屏幕紋理的紋理座標,你必須把它轉換到你想要的紋理中。

有幾種方法可以做到這一點。手動方式是計算CPU上紋理大小相互之間的比率,然後將其傳遞給着色器。使用您給出的數字,大小比率將爲:

(1152.0/256.0, 864.0/256.0) = (4.5, 3.375). 

確保這是在浮點數學中完成的。一旦這樣做,簡單地沿一個均勻的由該比率在着色器採樣之前通過這和繁殖紋理座標:

uniform vec2 textureRatio; 

void main() { 
//Get the texture coordinate. 
vec4 screenTexColor = texture(screenTex, texCoord); 
vec2 normTexCoord = textureRatio * texCoord; 
vec4 normalValue = texture(normalTex, normTexCoord); 
//Do something with these. 
} 

在GLSL所述的自動方法是直接在着色器做到這一點。這要求GLSL 1.30或更高。基本上,您使用的語言的可用功能來計算的比例:

void main() { 
//Get the texture coordinate. 
vec2 textureRatio = textureSize(screenTex)/textureSize(normalTex); 
vec4 screenTexColor = texture(screenTex, texCoord); 
vec2 normTexCoord = textureRatio * texCoord; 
vec4 normalValue = texture(normalTex, normTexCoord); 
//Do something with these. 
} 

在這兩種情況下,我假設你GL_TEXTURE_WRAP_S/T設置適當的紋理或採樣參數GL_REPEAT。

請注意,計算CPU上的比例並將其作爲統一傳遞將可能比在着色器中計算它快。尤其對於片段着色器來說,這將會非常重要。

+0

好的答案,但是對於1.30的特性,對每個片段計算常量比可能不是一個好主意,或者更糟糕的是鼓勵新手重新計算每個片段的常量值。我認爲你需要一個非常優化的GLSL編譯器來優化它。 –

+0

@Christian Rau:同意。但他確實說他正在「傳遞給頂點着色器(glsl)2紋理」。現在是的,這對他看起來實際上並沒有什麼意義,但這就是他所說的。所以如果他從頂點着色器訪問它們,可能並不是那麼糟糕。但是我會添加關於性能影響的說明。 –

+0

bolas很好的答案,謝謝!說實話,我不像你想象的那麼新鮮。我的英語是純粹的,我不能告訴你我真的在想什麼:) – Ockonal