Я пытаюсь понять, почему мой фрагментный шейдер GLSL демонстрирует различное поведение на разных машинах. В моем случае у меня есть компьютер с видеокартой (GeForce 1080) и два ноутбука с интегрированной графикой Intel (Intel HD Graphics 5500). На моем компьютере я получаю ожидаемое поведение, но на моих ноутбуках ожидаемое поведение происходит только тогда, когда я жестко кодирую унифицированный индекс индекса / в массиве. В приведенном ниже примере единственным отличием является использование int toUse = 0 в качестве поиска индекса массива по сравнению с жестким кодированием [0] для каждого массива. Если это имеет какое-либо значение, то плоские значения кодируются в одну и ту же текстуру (tilemap0 в приведенном ниже примере) и декодируются в вершинный шейдер перед передачей во фрагментный шейдер.
if(fragShaderToUse[TileAtlasToUse] == 0)
{
//toUse should be equal to fragShadertoUse[TileAtlasToUse]
int toUse = 0;
int tx = int(gl_FragCoord.x)
- vpOffsetXY[toUse].x
+ offsetXY[toUse].x;
int ty = int(gl_FragCoord.y)
+ vpOffsetXY[toUse].y
- offsetXY[toUse].y
+ offsetTileSize[toUse];
ivec2 screen_coordinates = ivec2(tx,ty);
ivec2 sc = screen_coordinates / offsetTileSize[toUse];
//obtain current pixel of encoded data to decipher
currentPixel = texelFetch(tilemap0,sc,0);
//decipher data
int curTil = int(currentPixel.b*255.0); //bgra decoded to int32 or char
//b = 0-255 tile atlas lookup
//determine tile atlas lookup pixel to use
int yCoord = screen_coordinates.y % offsetTileSize[toUse];
int xCoord = screen_coordinates.x % offsetTileSize[toUse];
yCoord = (int(yCoord / offsetZoomFactor[toUse]) - TILE_SIZE_Y[toUse]) * -1;
xCoord = int(xCoord / offsetZoomFactor[toUse]);
//convert to ivec2 and shift by current tile atlas offset
ivec2 tileCoordinate;
tileCoordinate.x = 2040 + xCoord;
tileCoordinate.y = ((curTil+1) * 8) - 1 - yCoord;
//lookup pixel in tile atlas
vec4 tileColor = texelFetch(tileAtlas,tileCoordinate,0);
}
out_Color = tileColor;
Если я жестко закодировалвсе вышеперечисленные индексы массива и не используют переменную int toUse в качестве индекса массива. Я получаю ожидаемое поведение:
if(fragShaderToUse[TileAtlasToUse] == 0)
{
//0 should be equal to fragShadertoUse[TileAtlasToUse]
int toUse = 0;
int tx = int(gl_FragCoord.x)
- vpOffsetXY[0].x
+ offsetXY[0].x;
int ty = int(gl_FragCoord.y)
+ vpOffsetXY[0].y
- offsetXY[0].y
+ offsetTileSize[0];
ivec2 screen_coordinates = ivec2(tx,ty);
ivec2 sc = screen_coordinates / offsetTileSize[0];
//obtain current pixel of encoded data to decipher
currentPixel = texelFetch(tilemap0,sc,0);
//decipher data
int curTil = int(currentPixel.b*255.0); //bgra decoded to int32 or char
//b = 0-255 tile atlas lookup
//determine tile atlas lookup pixel to use
int yCoord = screen_coordinates.y % offsetTileSize[0];
int xCoord = screen_coordinates.x % offsetTileSize[0];
yCoord = (int(yCoord / offsetZoomFactor[0]) - TILE_SIZE_Y[0]) * -1;
xCoord = int(xCoord / offsetZoomFactor[0]);
//convert to ivec2 and shift by current tile atlas offset
ivec2 tileCoordinate;
tileCoordinate.x = 2040 + xCoord;
tileCoordinate.y = ((curTil+1) * 8) - 1 - yCoord;
//lookup pixel in tile atlas
vec4 tileColor = texelFetch(tileAtlas,tileCoordinate,0);
}
out_Color = tileColor;
TILE_SIZE_Y 2 - это один из унифицированных массивов int, упомянутых выше,Вот ожидаемое поведение:Вот неправильное поведение (вы можете видеть, что он отображает правильные символы, начиная со второй строки, но с небольшим количеством мусора):Все отображается правильно, когда программа запускается на ПК с графической картой, независимо от того, жестко ли я закодировал индекс массива, закодировал переменную для использования в качестве индекса массива (int toUse) или использовал fragShadertoUse [TileAtlasToUse] в качестве индекса массива.
Более подробно: у меня 4 квартиры в массивах:2 ivec2
flat in ivec2 offsetXY[2]
flat in ivec2 vpOffsetXY[2]
1 int
flat in int offsetTileSize[2]
1 float
flat in float offsetZoomFactor[2]
Они обновляются каждый раз от вершинного шейдера
У меня есть различные однородные массивы int, которые обновляются во время инициализации и не изменяются во время работы программы.
Один из универсальных массивов int определяет, какиеиз двух логических путей шейдера для использования
uniform int fragShaderToUse[2]
В моей программе у меня есть 2 прямоугольника, состоящих из двух треугольников каждый, которые определяют, какой из массивов fragShaderToUse выбрать:
int TextureToUse = int(gl_PrimitiveID);
int TileAtlasToUse = TextureToUse / 2;
Итак, 0 или 1 в этом примере
Затем определяются два логических пути моего фрагментного шейдера:
if(fragShaderToUse[TileAtlasToUse] == 0)
{
//logic path 0
}
else if(fragShaderToUse[TileAtlasToUse] == 1)
{
//logic path 1
}
Внутри каждого логического пути, если я жестко закодирую индекс массива, я получуправильное поведение на обеих машинах, однако, если я использую fragShaderToUse [TileAtlasToUse] в качестве индекса массива, я получаю странное, искаженное поведение на ноутбуках, но корректное поведение на ПК с видеокартой. Я не понимаю, как это возможно, поскольку мы уже определили, что fragShaderToUse [TileAtlasToUse] равен либо 0, либо 1. Чтобы еще больше усложнить ситуацию, то же поведение проявляется, если я жестко закодирую переменную (например, set int IndexToUse = 1;в логическом пути 1, а затем используйте offsetTileSize [IndexToUse] в качестве одного примера) и используйте его в качестве индекса массива вместо жесткого кодирования поиска в массиве для каждого значения (offsetTileSize [1]). Я использую #version 430 в этом примере. Дальнейшее объяснение: