Рендер после работы с FrameBuffer

Версия Minecraft
1.12.2
95
1
2
Рендерю в кастомном framebuffer'е обьекты и рисую их затем в майнкрафтовсую текстуру. В общем все как по туториалу вот тут: ссылка
Рендерю все точно так же в RenderWorldLastEvent.

Проблема: Когда пытаюсь нарисовать в мире что-то другое... например обычный квадрат без всяких применений шейдеров, его отображение на экране ломается и виден квадрат только под определенным углом камеры и то не полностью. Я в GL не особо опытен и поэтому даже не знаю где рыть...
1581175317368.png

Плюс вопрос, как достать матрицу проекции, которую передают в шейдеры? Я не совсем понимаю как она в майнкрафте создается
 
Последнее редактирование:
Решение
Плохо понимаешь.

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

Я бы на твоем месте сделал бы с нуля и поэтапно. Во-первых, после каждого этапа проверял бы, что ничего не сломалось (все, что после этапа должно рендерится точно так же, как без него). Во-вторых, научился бы отлаживать фреймбуферы, чтобы быть полностью уверенным, что в них то, что нужно. Это тебе в любом случае пригодится, если начал заниматься постпроцессингом. И после этого можно будет легко локализовать ошибку.
95
1
2
@Ivasik , это видимо не то. Мне нужно как то через uniform передать Matrix4f (увидел это в оптифайне, но не нашел, как эта матрица создается)... либо я что то намутил. Не могу задебажить шейдер(
 
Последнее редактирование:

Icosider

Kotliner
Администратор
3,600
99
663
@Ivasik , это видимо не то. Мне нужно как то через uniform передать Matrix4f (увидел это в оптифайне, но не нашел, как эта матрица создается)... либо я что то намутил. Не могу задебажить шейдер(
Это то, просто содержится помимо матрицы проекции ещё и вью матрица
 
95
1
2
@Ivasik
vec4 tpos = vec4( 0, 2, 0 ,1) * gl_ProjectionMatrix;
tpos = vec4(tpos.xyz/tpos.w, 1.0);
vec2 pos1 = tpos.xy/tpos.z;
vec2 lightPositionOnScreen = (pos1+1)/2;

В общем вот что я вытащил из шейдера на оптифайне. Мне нужно расчитать позицию солнца на экране. в tpos я задаю тестовые значения (вектор позиции) и умножаю на матрицу. И вот я умножаю на gl_ProjectionMatrix, что я полагаю не совсем верно, и в итоге ничего не работает.

Есть класс ActiveCacheInfo или как-то так, там есть матрицы.
Спасибо, нашел. Рефлектом вытащил поле PROJECTION и там вот это : "pos=0 lim=16 cap=16"... это оно?
 
2,505
81
397
Если рендерить в ванильный фбо, проблемы нет?
Показывай код. Как и что рендеришь, и всю работу с фбо.
И ещё несколько скринов хотелось бы.

По одной лишь матрице проекции позицию солнца не узнать. Оптифайн задаёт юниформу sunAngle (точное название не помню) для этого.
 
Последнее редактирование:
95
1
2
@Dahaka
Скину код моей попытки воссоздать godRays. Меньше кода и после него такая же проблема...
(Я знаю, это скорее всего не стоит в RenderWorldLast совать, но в других почему-то не работало...)
Java:
@SubscribeEvent
    public void godRays(RenderWorldLastEvent event) {
        int current = GL11.glGetInteger(GL11.GL_TEXTURE_BINDING_2D); // в 1.12 нужно сохранять текстур атлас
        if (framebuffer == null)
            framebuffer = new Framebuffer(mc.displayWidth, mc.displayHeight, true);
        if (mc.displayWidth != framebuffer.framebufferWidth
                || mc.displayHeight != framebuffer.framebufferHeight)
            framebuffer.createBindFramebuffer(mc.displayWidth, mc.displayHeight);
        if (framebufferSub == null)
            framebufferSub = new Framebuffer(mc.displayWidth, mc.displayHeight, false);
        if (mc.displayWidth != framebufferSub.framebufferWidth
                || mc.displayHeight != framebufferSub.framebufferHeight)
            framebufferSub.createBindFramebuffer(mc.displayWidth, mc.displayHeight);
        framebuffer.bindFramebuffer(false);
        
        GL30.glBindFramebuffer(GL30.GL_READ_FRAMEBUFFER, mc.getFramebuffer().framebufferObject);
        GL30.glBlitFramebuffer(0, 0,
                mc.displayWidth, mc.displayHeight,
                0, 0,
                mc.displayWidth, mc.displayHeight,
                GL11.GL_DEPTH_BUFFER_BIT,
                GL11.GL_NEAREST);
        
        //Sun position
        GL11.glPushMatrix();
            //GL11.glBindTexture(GL11.GL_TEXTURE_2D, 0);
            //GlStateManager.tryBlendFuncSeparate(GlStateManager.SourceFactor.SRC_ALPHA, GlStateManager.DestFactor.ONE, GlStateManager.SourceFactor.ONE, GlStateManager.DestFactor.ZERO);
            WorldClient world = Minecraft.getMinecraft().world;
            float f17 = 1.0f - world.getRainStrength(event.getPartialTicks());
            float br = world.getSunBrightness(event.getPartialTicks()) + 0.1f;
            GL11.glColor4f(1f * br, 1f * br, 1f* br, f17); //brightness
            //GL11.glColor3f(0,0,0); //color
            GL11.glRotatef(-90f, 0, 1, 0);
            GL11.glRotatef(world.getCelestialAngle(event.getPartialTicks())*360, 1, 0, 0);
            GL11.glTranslatef(0, 0, 0.01f);
            drawSun();
        GL11.glPopMatrix();
        
        framebufferSub.bindFramebuffer(false);
        
        ShaderRegister.FILTER.start();
        ShaderRegister.FILTER.uniform();

        GL11.glPushMatrix();
            GL11.glBindTexture(GL11.GL_TEXTURE_2D, mc.getFramebuffer().framebufferTexture);
            GL11.glMatrixMode(GL11.GL_PROJECTION);
            GL11.glLoadIdentity();
            GL11.glMatrixMode(GL11.GL_MODELVIEW);
            GL11.glLoadIdentity();
            drawQuad();
        GL11.glPopMatrix();
        ShaderRegister.FILTER.stop();
        
        GL11.glPushMatrix();
        GL11.glBindTexture(GL11.GL_TEXTURE_2D,  framebuffer.framebufferTexture);
        GL11.glMatrixMode(GL11.GL_PROJECTION);
        GL11.glLoadIdentity();
        GL11.glMatrixMode(GL11.GL_MODELVIEW);
        GL11.glLoadIdentity();
        drawQuad();
        GL11.glPopMatrix();
        
        GL13.glActiveTexture(GL13.GL_TEXTURE3);
        GL11.glBindTexture(GL11.GL_TEXTURE_2D, mc.getFramebuffer().framebufferTexture);
        GL13.glActiveTexture(GL13.GL_TEXTURE0);
        
        mc.getFramebuffer().bindFramebuffer(false);
        
        ShaderRegister.RBLUR.start();
        ShaderRegister.RBLUR.textureUnits(world.getCelestialAngle(event.getPartialTicks()));
        GL11.glPushMatrix();
        GL11.glBindTexture(GL11.GL_TEXTURE_2D, framebufferSub.framebufferTexture);
        GL11.glMatrixMode(GL11.GL_PROJECTION);
        GL11.glLoadIdentity();
        GL11.glMatrixMode(GL11.GL_MODELVIEW);
        GL11.glLoadIdentity();
        drawQuad();
        GL11.glPopMatrix();
        ShaderRegister.RBLUR.stop();
        
        framebuffer.framebufferClear();
        framebufferSub.framebufferClear();
        mc.getFramebuffer().bindFramebuffer(false);
        GL11.glBindTexture(GL11.GL_TEXTURE_2D, current);
        
        //После чего рисую допустим квадрат 1х1
        Tessellator tessellator = Tessellator.getInstance();
        BufferBuilder buffer = tessellator.getBuffer();
        buffer.begin(7, DefaultVertexFormats.POSITION_TEX);
        buffer.pos(-1, -1, 0).tex(0, 0).endVertex();
        buffer.pos(1, -1, 0).tex(1, 0).endVertex();
        buffer.pos(1, 1, 0).tex(1, 1).endVertex();
        buffer.pos(-1, 1, 0).tex(0, 1).endVertex();
        
    }

После чего где бы не рендерил что либо в RenderWorldLastEvent (В других ивентах еще не пробовал), рендерится только от первого лица и то в притык. Отдаляю от игрока квадрат и он не виден вообще ни под каким углом.
1581258280709.png1581258296425.png1581258312242.png1581258326939.png

Вот рендер от первого лица под разными углами. От 3-го же вообще не рендерит
 
2,505
81
397
Ты матрицу проекции испортил потому что. Сделал её единичной, а обратно не вернул. Push-pop всегда делаешь только для modelview.

Еще я не очень понимаю, зачем ты там делаешь всякие drawSun в мировом пространстве. God rays же screen space техника.
 
95
1
2
@Dahaka, я не очень разбираюсь в OpenGL и поэтому не понимаю, как мне это чинить... с
GL11.glMatrixMode(GL11.GL_PROJECTION); работать?

Да, я знаю, что делается это на экране, но у меня в RenderHudEvent как-то не особо работало, и я для начала делал все в мире
 
2,505
81
397
1. Да.
2. Ивент майнкравта тут не причем. Но раз уж заговорил, то в идеале весь постпроцессинг должен быть между RenderWorldLastEvent и рендером hud и gui. Для того, чтобы все моды успели отрендерить мир, но на hud ничего не влияло. А ещё лучше сделать себе postprocessing pass между непрозрачным рендером мира и полупрозрачным. Подозреваю, это потребуется для god rays.
 
95
1
2
@Dahaka , приеняю пуш и поп к двум матрицам, но теперь вообще не рендерит
Java:
        GL11.glMatrixMode(GL11.GL_PROJECTION);
        GL11.glPushMatrix();     
        GL11.glMatrixMode(GL11.GL_MODELVIEW);
        GL11.glPushMatrix();
        
        GL11.glMatrixMode(GL11.GL_PROJECTION);
        GL11.glLoadIdentity();
        GL11.glMatrixMode(GL11.GL_MODELVIEW);
        GL11.glLoadIdentity();
        drawQuad();
        GL11.glMatrixMode(GL11.GL_PROJECTION);
        GL11.glPopMatrix();
        GL11.glMatrixMode(GL11.GL_MODELVIEW);
        GL11.glPopMatrix();
 
95
1
2
@Dahaka, Заметил, что когда не рисую самый последний квадрат на весь экран, к которому применяется шейдер, то все отображается нормально. Немного пошевелив мозгами, я примерно представил в чем может быть проблема, и переместил код рендера квадрата в мире (который не правильно отображается) в самое начала ивента, когда еще ничего не происходило, ну и квадрат успешно отрендерился, а поверх него и шейдер. Но это не решение проблемы, так как все равно рендеры с других методов worldLastEvent отображаются не верно. Значит и с другими модами будет конфликт.
Насколько я понимаю, проблема в том, что я беру текстуру майнкрафта, применяю к ней свои фильтры, а потом рисую уже свою отфильтрованую текстуру в майновский фреймбаффер, а все что происходит после этого, просто не записывается видимо в эту текстуру...
 
2,505
81
397
Плохо понимаешь.

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

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