как вернуть маску выборочных пикселей - PullRequest
0 голосов
/ 01 ноября 2018

Я использую программу, которая доступна на GitHub ( здесь ), для преобразования равностороннего изображения (360-градусные изображения) в перспективный вид (область просмотра) с использованием OpenGL. Для этого используется метод трассировки лучей, чтобы найти пересечение точек фрагмента на единичной сфере, и позже эта информация будет использоваться для выборки требуемых пикселей из равноугольных изображений и проецирования их на перспективный вид. Все работает нормально, но теперь по результату проецирования мне нужна программа, которая возвращает мне также маску изображения (типа байта без знака и того же размера равностороннего изображения), который представляет пиксели, которые взяты из равносторонних изображений.

Как я могу изменить фрагментный шейдер, чтобы он возвращал мне эту беззнаковую байтовую маску (0 представляет не сэмплы и 255 представляет сэмплированные пиксели) в то время, когда он рендерит представление в буфере кадров?

Чтобы быть более точным, мой текущий фрагментный шейдер выглядит следующим образом:

const float pi = 3.141592653589793;
varying vec3 planePoints;
uniform sampler2D tex;
void main()
{
        vec2 equirectangularTexturePos;
        vec3 spherepos = normalize(planePoints);
        equirectangularTexturePos.x = (atan(spherepos.y, -spherepos.x)+pi)/(2.0*pi);
        equirectangularTexturePos.y = acos(spherepos.z)/(pi);
        gl_FragColor = texture2D(tex, equirectangularTexturePos);
}

и я хочу добавить что-то похожее на мой фрагментный шейдер:

texture2D(mask, equirectangularTexturePos) = 255;

1 Ответ

0 голосов
/ 02 ноября 2018

Я просто пишу это, чтобы прояснить возможное решение, на которое я пытался намекнуть в приведенном выше комментарии, используя Image Load Store. Во-первых, вам нужно создать новую текстуру того же размера, что и ваша равноугольная текстура (вы можете использовать GL_R8 в качестве внутреннего формата). Вы можете сделать это с помощью glTexImage2D или glTexStorage2D.

Затем вам нужно объявить точку привязки изображения в вашем шейдере и привязать первый уровень изображения маски к этой точке привязки изображения. Затем в шейдере, когда вы производите выборку из исходной цветовой текстуры, вы также собираетесь использовать функцию imageStore() для записи в текстуру маски в этом месте текселя. Внимание: расположение текселей указано в фактических текселях, а не в части размера текстуры!

Для первого приближения мы просто используем усеченную целочисленную координату вашей исходной позиции выборки (для вашего вызова texture2D). На самом деле, поскольку вы используете GL_LINEAR в качестве функции фильтрации, вы должны вычислить ближайшие 4 текселя и записать их. См. Страницу PDF 150 https://www.khronos.org/registry/OpenGL/specs/gl/glspec13.pdf, чтобы узнать, какой алгоритм использует GL для определения четырех текселей для ЛИНЕЙНОЙ фильтрации.

Итак, части вашего шейдера будут выглядеть так:

#extension GL_ARB_shader_image_load_store : enable

layout(binding = 0, r8) writeonly uniform image2D maskImage;
...
ivec2 texel = ivec2(equirectangularTexturePos * textureSize(tex, 0));
imageStore(maskImage, texel, vec4(1.0, 0.0, 0.0, 0.0));

Чтобы привязать изображение к точке привязки изображения, вы должны использовать это в вашей хост-программе:

glBindImageTexture(0, maskTex, 0, false, 0, GL_WRITE_ONLY, GL_R8);

Также не забудьте очистить текстуру перед запуском шейдера. После того, как шейдер запустил и заполнил доступ к текселям уровня 0 вашей текстуры маски, вам нужно добавить соответствующий барьер синхронизации, чтобы дальнейшие вызовы GL из этой текстуры видели обновленные значения текстуры. Вы делаете это через:

glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);

Теперь вы можете использовать эту текстуру любым способом и получать ее, например, с помощью другого шейдера.

...