OpenGL GLSL Uniform and In Values ​​демонстрирует нечетное поведение на разных аппаратных средствах при использовании унифицированных значений в качестве индексов In / Uniform Array и Hardcoding - PullRequest
0 голосов
/ 30 октября 2019

Я пытаюсь понять, почему мой фрагментный шейдер 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, упомянутых выше,Вот ожидаемое поведение:enter image description hereВот неправильное поведение (вы можете видеть, что он отображает правильные символы, начиная со второй строки, но с небольшим количеством мусора):enter image description hereВсе отображается правильно, когда программа запускается на ПК с графической картой, независимо от того, жестко ли я закодировал индекс массива, закодировал переменную для использования в качестве индекса массива (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 в этом примере. Дальнейшее объяснение:

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...