[英]Can't read a FORMAT_R8 uniform sampler2D texture correctly from within a shader in Godot
我需要將整數數組作為統一傳遞給着色器。 由於尚不支持統一的 arrays,因此我使用FORMAT_R8
紋理/isampler2D 來實現此目的。
如果我從紋理中正確讀取字節,它們應該在 [0..7] 范圍內,然后通過規范化該值,我應該得到不同的紅色陰影,但這沒有發生。
在屏幕截圖中,您可以看到當值被讀取為 0 時,它正確地顯示為黑色,但當它不是 0 時,它是全紅色的,沒有陰影。 我嘗試比較讀取的值,它總是大於我可以嘗試的任何值,直到 32 位簽名 integer 的最大值,所以不知道我從紋理中讀回的值是什么。
有任何想法嗎?
完整的項目在這里: https://github.com/Drean64/clash-of-the-colors/tree/simple
GDScript:
extends ViewportContainer
func _ready():
var attr_ink = PoolByteArray([])
attr_ink.resize(32*24)
for i in range(0, 32*24):
attr_ink[i] = i % 8 # fill array with [0..7]
var image = Image.new()
image.create_from_data(32, 24, false, Image.FORMAT_R8, attr_ink)
var ink = ImageTexture.new()
ink.create_from_image(image, 0)
(self.material as ShaderMaterial).set_shader_param("ink", ink)
着色器:
shader_type canvas_item;
uniform isampler2D ink;
void fragment() {
COLOR = vec4(0., 0., 0., 1.); // Black
ivec2 cell = ivec2(UV / TEXTURE_PIXEL_SIZE) / 8; // 8x8 pixel cell coordinate
int ink_color = texelFetch(ink, cell, 0).r; // Should be [0..7]
COLOR.r = float(ink_color) / 7.; // Should normalize the red value to [0..1]
// Line above is a kind of debug to get a hint at what the ink_color value is
}
這對我有用:
sampler2D
而不是isampler2D
(這似乎是罪魁禍首)。32.0
(即256.0 / 8.0
)進行歸一化。那是:
COLOR.r = texelFetch(ink, cell, 0).r * 32.0;
更新:顯然使用isampler2D
時存在這些值,但編碼錯誤。
我首先確認紋理生成正確。 問題是在為着色器綁定紋理時。
我查看了 Godot 的源代碼,但沒有針對isampler2D
的紋理進行投標。 這讓我認為它的處理方式與sampler2D
相同(或者我不太擅長看,在任何一種情況下,我都應該嘗試找出與着色器代碼混淆的事情)。
首先要嘗試的是弄清楚值在哪里有多大。 他們來了大約1000000000
。 所以,我們似乎得到了 32 位的值。 在嘗試了每一個之后,這非常接近一個解決方案:
int x = texelFetch(ink, cell, 0).r;
COLOR.r = mod(float(x / (256 * 256)), 256.0) / 256.0;
這幾乎行得通。 由於我不清楚的原因,它應該有第二個紅色陰影,它是黑色的。 這讓我覺得也許這些值被編碼為浮點數。
根據這個想法,我決定將這些值除以2097152
(2²¹ = 256 * 256 * 32)。 這將擺脫大部分小數部分。
float binary integer
5.877471754111438e-39 -> 0 00000000 01000000000000000000000 -> 2097152
1 -> 0 01111111 00000000000000000000000 -> 1065353216
2 -> 0 10000000 00000000000000000000000 -> 1073741824
3 -> 0 10000000 10000000000000000000000 -> 1077936128
4 -> 0 10000001 00000000000000000000000 -> 1082130432
5 -> 0 10000001 01000000000000000000000 -> 1084227584
6 -> 0 10000001 10000000000000000000000 -> 1086324736
7 -> 0 10000001 11000000000000000000000 -> 1088421888
X XX
我使用https://baseconvert.com/ieee-754-floating-point得到了浮點值的這些二進制表示
我的想法是采用我在上面標記為 X 的部分。 除以2097152
后,它們將移至三個最低有效位。 這給我們留下了這段代碼:
int x = texelFetch(ink, cell, 0).r;
COLOR.r = mod(float(x / 2097152), 8.0) / 8.0;
那樣有用嗎? 再次,幾乎。 這與之前的結果相同。 除了根據上表對結果進行(部分)解釋外,因為我在上面標記為 X 的位上的值 2 為 0。 事實上,0 和 1 的值也需要修補。
現在,我只能修補這些值,不知何故,我們會有工作代碼,對吧? 我只需要弄清楚這些值最終是什么。
如果我嘗試將 2 的值1073741824
除以2097152
我得到512
。 哪個......沒有用(我會責怪baseconvert.com)。 但作為搜索實際值的良好起點。
我以以下代碼結束,它將給出預期的結果isampler2D
:
int x = texelFetch(ink, cell, 0).r;
int y = x / 2097152;
COLOR.r = mod(float(y), 8.0) / 8.0;
if (y == 476)
{
COLOR.r = 1.0 / 8.0;
}
if (y == 480)
{
COLOR.r = 2.0 / 8.0;
}
if (y == 482)
{
COLOR.r = 3.0 / 8.0;
}
所以在那里,我的解釋是它將值作為浮點數傳遞,但將它們作為整數讀取。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.