Загрузка буфера глубины во фрагментный шейдер

Версия Minecraft
1.16.5
API
Forge
4,045
63
645
Всем доброго дня!
Запрашиваю тяжёлую артиллерию, а именно ребят, шарящих в OGL.
@Dahaka-у, @CumingSoon-а и @Oldestkon-а отмечу сразу, потому что надеюсь на них и уповаю )

Основной вопрос в названии.
Собираюсь создавать постэффект (знающие люди догадаются какой именно), буду рисовать на экран полигон с собственным шейдером, куда хотелось бы в виде uniform sampler2D (или чего-то ещё) загрузить буфер глубины из ванильного FBO, а так же второй буфер из собственного FBO, с которыми и буду работать.

В идеале хочу получить что-то типа этого (простейший пример, для наглядности):
Код:
#version 120

uniform sampler2D depth1;
uniform sampler2D depth2;

void main() {
    vec2 texcoord = vec2(gl_FragCoord.xy);
    gl_FragColor = texture2D(depth1, texcoord.xy) + texture2D(depth2, texcoord.xy) ;
}

Проблема в том, что я не знаю, как именно загрузить глубину в шейдер.
Вторая проблема в том, что глубину, скорее всего, придётся грузить в формате GL20.GL_DEPTH_COMPONENT24, а как именно достать из него цвет внутри шейдера я тоже не в курсе... Прошу подсказать.

На данный момент имею следующее (прошу поправить меня, если это не верно):
Копирование глубины в текстуру:
Java:
// Как я понял, текстура биндится в текущий FBO и из него же достаётся информация о глубине
GL11.glBindTexture(GL11.GL_TEXTURE_2D, texture);
GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER, GL12.GL_LINEAR);
GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MAG_FILTER, GL12.GL_LINEAR);
GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_S, GL12.GL_CLAMP_TO_EDGE);
GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_T, GL12.GL_CLAMP_TO_EDGE);
GL11.glTexImage2D(GL11.GL_TEXTURE_2D, 0, GL20.GL_DEPTH_COMPONENT24, mc.getMainWindow().getFramebufferWidth(), mc.getMainWindow().getFramebufferHeight(), 0, GL12.GL_DEPTH_COMPONENT, GL12.GL_UNSIGNED_INT, 0);

Загрузка текстуры в качестве униформы в шейдер и отрисовка квада:
Java:
ShaderProgram.useShader(ShaderProgram.program);

GL20.glActiveTexture(GL20.GL_TEXTURE0);
GL20.glBindTexture(GL20.GL_TEXTURE_2D, texture);
GL20.glUniform1i(GL20.glGetUniformLocation(ShaderProgram.program, "depth"), 0);

drawQuad();

ShaderProgram.releaseShader();

На выходе имею белый экран.
Победой будет хотя бы обычная визуализация чёрно-белой картинки глубины.

Прощу наставить на путь истинный )
Не бейте, если написал полную ахинею.
И заранее спасибо, если поможете )
 
Решение
На данный момент имею следующее (прошу поправить меня, если это не верно):
Делаешь какую-то фигню. И комментарий в коде говорит о том, что ты вообще не понимаешь, что делаешь.
В майновском фбо есть атачмент глубины. Надо понять что там: текстура или рендербуфер. Если текстура, то можешь просто её брать и использовать в шейдере. Если рендербуфер, то сложнее. Либо заменить на текстуру, либо в рантайме каждый кадр блитить глубину из рендербуфера в текстуру.

Текстура глубины (в твоем случае и в случае с майном тоже) имеет формат GL_DEPTH_COMPONENT24. Это значит, что у нее один компонент размером 24 байта. Значит, чтобы достать цвет пикселя, достаточно сделать texture2D(depth, texcoord.xy).r. Но это еще не все. Даже если ты...
2,505
81
397
На данный момент имею следующее (прошу поправить меня, если это не верно):
Делаешь какую-то фигню. И комментарий в коде говорит о том, что ты вообще не понимаешь, что делаешь.
В майновском фбо есть атачмент глубины. Надо понять что там: текстура или рендербуфер. Если текстура, то можешь просто её брать и использовать в шейдере. Если рендербуфер, то сложнее. Либо заменить на текстуру, либо в рантайме каждый кадр блитить глубину из рендербуфера в текстуру.

Текстура глубины (в твоем случае и в случае с майном тоже) имеет формат GL_DEPTH_COMPONENT24. Это значит, что у нее один компонент размером 24 байта. Значит, чтобы достать цвет пикселя, достаточно сделать texture2D(depth, texcoord.xy).r. Но это еще не все. Даже если ты все сделаешь правильно, то на выходе получишь, скорее всего, белую картинку. Серые пиксели будут видны, только если в упор смотреть на блоки. Чтобы получить более приятную картинку, значение глубины нужно линеаризовать.

Большинство эффектов, кстати, требуют линейную глубину. Поэтому часто делают отдельный пасс, которым сохраняют именно линейную глубину в отдельной текстуре. Особенно, когда эффектов, требующих линейную глубину, много или сложность какого-то такого эффекта больше О(n).
 
4,045
63
645
Ну, на данный момент в 1.16.5 ванильный буфер глубины создаётся так:
Java:
this.depthBuffer = TextureUtil.generateTextureId();

// А под капотом у него
return GL11.glGenTextures();

То есть, это всё таки текстура.
И получается я могу просто грузить её в униформу методом описанном в вопросе? Надеюсь, он верный )

Про линеаризацию почитаю, спасибо...
Как я понял, там нужно знать ближнее и дальнее значения диапазона? Или я тупо их сам их задаю?
 
Последнее редактирование:
4,045
63
645
Так! Что-то получается, но что-то я явно делаю не так...
Цвета реально меняются... Но такое ощущение, что я беру информацию о глубине только из одного пикселя, так как темнеет или светлеет весь экран целиком (вращаю камерой, перемещаюсь).

Шейдер, на данный момент, такой:
Код:
#version 120

uniform sampler2D DiffuseSampler;

const float far = 100;

float linearizeDepth(float depth) {
    return (exp(depth*log(far+1)) - 1)/far;
}

void main() {
    vec2 texcoord = vec2(gl_TexCoord[0]); // или vec2(gl_FragCoord.xy); ноль реакции
    float f = linearizeDepth(texture2D(DiffuseSampler, texcoord.xy).r);
    gl_FragColor = vec4(f,f,f,1);
}

Может быть беда в вертексном?
Код:
#version 120

void main(){
    gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
}

Где ошибка?
 
7,099
324
1,509
texture2D работает с абсолютными координатами или с относительными? Ты передаешь ей относительные
 
2,505
81
397
А как ты рендеришь квад? Попробуй повыводить не глубину, а любую другую текстуру, которую ты точно знаешь. Потести без linearizeDepth. Твоя функция выглядит не очень.

Как я понял, там нужно знать ближнее и дальнее значения диапазона?
Да

Или я тупо их сам их задаю?
Нет. Надо где-то в майне найти эти значения и передать юниформой. Либо еще есть оптимизированный способ через матрицу проекции.

C-like:
float linearDepth(float depth) {
    return u_projMat[3][2] / (u_projMat[2][2] + (depth * 2.0 - 1.0));
}

float linearDepthOld(float depth) {
    depth = depth * 2.0 - 1.0;
    return (2.0 * u_near * u_far) / (u_far + u_near - depth * (u_far - u_near));
}
 
4,045
63
645
Так же, выяснил одну интересную штуку: если активирую вторую текстуру GL20.glActiveTexture(GL20.GL_TEXTURE2);, то во всём мире отключаются тени...
В майне где-то есть отдельная маска теней?
Реально ли как-то получить её текстуру или текстуру мира без теней, но при этом сохранив оригинальную картинку нетронутой?
 
2,505
81
397
@Dahaka, а как ты борешься вот с таким эффектом полосатости?
Я не знаю, что ты делаешь и как ты это получил, поэтому не могу подсказать. И я не ловил такого.

Так же, выяснил одну интересную штуку: если активирую вторую текстуру GL20.glActiveTexture(GL20.GL_TEXTURE2);, то во всём мире отключаются тени...
Не знаю, как в новом майне, но раньше лайтмапа лежала в GL_TEXTURE1.
Реально ли как-то получить её текстуру или текстуру мира без теней, но при этом сохранив оригинальную картинку нетронутой?
Раньше майн лайтмапу применял сразу же при рендере чанков.
 
4,045
63
645
Видимо, теперь она лежит в GL_TEXTURE2.
А эффект я ловлю просто наложением глубины на майновскую картинку через альфу и белый цвет.
Скриншот сделан в пещере... Там темно. Соответственно, наложенная поверх этого глубина даёт вот такие вот полоски.
...
Слушай, а как лайтмапа зовётся в шейдере?
 
Последнее редактирование:

CumingSoon

Местный стендапер
1,634
12
269
Не могу помочь тебе по теме, так как нет желания разбираться в твоем коде.
Я когда-то пробовал писать объемный туман (но у меня не вышло почему-то), может ты что-то отсюда зацепишь для себя, а может даже напишешь ПР с рабочим кодом! (я буду очень рад этому раскладу, кстати)
 
Сверху