Полигон перестает рисовать если добавить вызов отрисовки текста

Версия Minecraft
1.12.2
API
Forge
7,099
324
1,510
Хочу сделать следующую вещь:
рендерить какой-нить контент во фреймбуфер и потом юзать этот фреймбуфер в качестве текстуры для другого полигона.

Есть такой фрагмент кода, который производит рендер во фреймбуфер
Scala:
def drawPageContainerContent(): Unit = {
    mc.fontRenderer.drawString("Testlol", 100, 100, 0xff00ff)

    val buffer = Tessellator.getInstance.getBuffer
    buffer.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_COLOR)
    buffer.pos(0, 0, 0).color(255, 0, 255, 255).endVertex()
    buffer.pos(0, 50, 0).color(255, 0, 255, 255).endVertex()
    buffer.pos(50, 50, 0).color(255, 0, 255, 255).endVertex()
    buffer.pos(50, 0, 0).color(255, 0, 255, 255).endVertex()
    Tessellator.getInstance.draw()
}
Результат:
1) текст рисуется глифами галактического алфавита(зачарования), хотя я не включал эту опцию
2) фиолетового полигона не видно
Если убрать строчку рендера текста, то полигон становится виден.
Эта штука рендерит во фреймбуфер, а потом использует его как текстуру, чтобы нарисовать квад размером с фреймбуфер.
Если рендерить сразу на экран, то эффект 2) сохраняется, а эффект 1) - нет.
Как это работает? Почему оно так работает? Как это исправить?

Полный код:
Scala:
package ru.mousecray.endmagic.client.render.book

import net.minecraft.client.Minecraft
import net.minecraft.client.renderer.vertex.DefaultVertexFormats
import net.minecraft.client.renderer.{GlStateManager, Tessellator}
import net.minecraft.client.shader.Framebuffer
import net.minecraft.util.ResourceLocation
import org.lwjgl.opengl.GL11
import ru.mousecray.endmagic.EM
import ru.mousecray.endmagic.api.embook.PageContainer

object PageRenderer {

  lazy val mc = Minecraft.getMinecraft

  def drawPageTo(pageContainer: PageContainer, framebuffer: Framebuffer): Unit = {
    GlStateManager.enableTexture2D()
    GlStateManager.disableLighting()
    GlStateManager.enableAlpha()
    GlStateManager.enableBlend()
    GlStateManager.disableDepth()

    framebuffer.bindFramebuffer(true)

    saveMatrices()

    identityMatrices()

    setupProjectionArea()

    drawPageContainerBackRect()
    drawPageContainerContent()

    restoreMatrices()

    mc.getFramebuffer.bindFramebuffer(true)

  }

  def drawPageContainerContent(): Unit = {
    mc.fontRenderer.drawString("Testlol", 100, 100, 0xff00ff)

    val buffer = Tessellator.getInstance.getBuffer
    buffer.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_COLOR)
    buffer.pos(0, 0, 0).color(255, 0, 255, 255).endVertex()
    buffer.pos(0, 50, 0).color(255, 0, 255, 255).endVertex()
    buffer.pos(50, 50, 0).color(255, 0, 255, 255).endVertex()
    buffer.pos(50, 0, 0).color(255, 0, 255, 255).endVertex()
    Tessellator.getInstance.draw()
  }

  val w = 260
  val h = 208

  val tw = 128
  val th = 64

  val uw = 20
  val vh = 16

  val u0 = 48d
  val v0 = 20d
  val u1 = u0 + uw
  val v1 = v0 + vh

  def drawPageContainerBackRect(): Unit = {
    Minecraft.getMinecraft.getTextureManager.bindTexture(new ResourceLocation(EM.ID, "textures/models/book/em_book.png"))
    val buffer = Tessellator.getInstance.getBuffer
    buffer.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_TEX_COLOR)
    buffer.pos(0, 0, 0).tex(u0 / tw, v0 / th).color(255, 255, 255, 255).endVertex()
    buffer.pos(0, h, 0).tex(u0 / tw, v1 / th).color(255, 255, 255, 255).endVertex()
    buffer.pos(w, h, 0).tex(u1 / tw, v1 / th).color(255, 255, 255, 255).endVertex()
    buffer.pos(w, 0, 0).tex(u1 / tw, v0 / th).color(255, 255, 255, 255).endVertex()
    Tessellator.getInstance.draw()
  }

  private def setupProjectionArea(): Unit = {
    GL11.glOrtho(0, w, h, 0, -10, 10)
  }

  private def identityMatrices(): Unit = {
    GL11.glMatrixMode(GL11.GL_MODELVIEW)
    GL11.glLoadIdentity()
    GL11.glMatrixMode(GL11.GL_PROJECTION)
    GL11.glLoadIdentity()
  }

  private def saveMatrices(): Unit = {
    GL11.glMatrixMode(GL11.GL_MODELVIEW)
    GL11.glPushMatrix()
    GL11.glMatrixMode(GL11.GL_PROJECTION)
    GL11.glPushMatrix()
  }

  private def restoreMatrices(): Unit = {
    GL11.glMatrixMode(GL11.GL_PROJECTION)
    GL11.glPopMatrix()
    GL11.glMatrixMode(GL11.GL_MODELVIEW)
    GL11.glPopMatrix()
  }


}

Scala:
package ru.mousecray.endmagic.client.render.book

import net.minecraft.client.shader.Framebuffer
import ru.mousecray.endmagic.api.embook.PageContainer
import ru.mousecray.endmagic.client.render.book.Refs._
import ru.mousecray.endmagic.client.render.book.PageRenderer._

import scala.collection.mutable
import scala.collection.mutable.ArrayBuffer

object PageTextureHolder {

  def getTexture(pageContainer: PageContainer): Framebuffer = {
    textures.getOrElseUpdate(pageContainer, {
      if (freeTextures.isEmpty)
        throw new IllegalStateException("Attempt to use more that 4 framebuffers")
      val fb = freeTextures.remove(freeTextures.size - 1)
      drawPageTo(pageContainer, fb)
      fb
    })
  }

  def freeTexture(pageContainer: PageContainer): Unit = {
    textures.get(pageContainer).foreach {
      fb =>
        textures -= pageContainer
        freeTextures += fb
    }
  }

  private val textures = new mutable.HashMap[PageContainer, Framebuffer]

  private lazy val freeTextures = {
    val r = new ArrayBuffer[Framebuffer]
    for (i <- 1 to 4)
      r += new Framebuffer(pageContainerWidth, pageHeight, false)
    r
  }
}

Java:
package ru.mousecray.endmagic.client.render.book;

import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.BufferBuilder;
import net.minecraft.client.renderer.Tessellator;
import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
import net.minecraft.client.shader.Framebuffer;
import net.minecraft.util.ResourceLocation;
import net.minecraftforge.client.event.RenderGameOverlayEvent;
import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
import org.lwjgl.opengl.GL11;
import ru.mousecray.endmagic.EM;
import ru.mousecray.endmagic.api.embook.BookApi;

import static org.lwjgl.opengl.GL11.GL_TEXTURE_2D;

@Mod.EventBusSubscriber(modid = EM.ID)
public class TestOverlay {

    @SubscribeEvent
    public static void onRenderTest(RenderGameOverlayEvent.Pre event) {
        PageTextureHolder.freeTexture(BookApi.mainChapter());
        Framebuffer texture = PageTextureHolder.getTexture(BookApi.mainChapter());
        drawPageContainerRect(texture);

        //PageRenderer.drawPageContainerBackRect();
        //PageRenderer.drawPageContainerContent();
        //drawPageContainerRectOriginal();
    }

    static int x = 10;
    static int y = 10;
    static int w = 260;
    static int h = 208;

    private static void drawPageContainerRect(Framebuffer framebuffer) {
        int current = GL11.glGetInteger(GL11.GL_TEXTURE_BINDING_2D);

        framebuffer.bindFramebufferTexture();
        {

            BufferBuilder buffer = Tessellator.getInstance().getBuffer();
            buffer.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_TEX_COLOR);
            buffer.pos(x, y, 0).tex(0, 1).color(255, 255, 255, 255).endVertex();
            buffer.pos(x, y + h, 0).tex(0, 0).color(255, 255, 255, 255).endVertex();
            buffer.pos(x + w, y + h, 0).tex(1, 0).color(255, 255, 255, 255).endVertex();
            buffer.pos(x + w, y, 0).tex(1, 1).color(255, 255, 255, 255).endVertex();
            Tessellator.getInstance().draw();
        }
        framebuffer.unbindFramebufferTexture();

        {
            //framebuffer.framebufferClear();
            //mc.getFramebuffer().bindFramebuffer(true);
            GL11.glBindTexture(GL_TEXTURE_2D, current);
        }
    }

    private static void drawPageContainerRectOriginal() {
        int current = GL11.glGetInteger(GL11.GL_TEXTURE_BINDING_2D);

        //framebuffer.bindFramebufferTexture();
        Minecraft.getMinecraft().getTextureManager().bindTexture(new ResourceLocation(EM.ID, "textures/models/book/page.png"));
        {

            BufferBuilder buffer = Tessellator.getInstance().getBuffer();
            buffer.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_TEX_COLOR);
            buffer.pos(x + w + 10, y, 0).tex(0, 0).color(255, 255, 255, 255).endVertex();
            buffer.pos(x + w + 10, y + h, 0).tex(0, 1).color(255, 255, 255, 255).endVertex();
            buffer.pos(x + w + w + 10, y + h, 0).tex(1, 1).color(255, 255, 255, 255).endVertex();
            buffer.pos(x + w + w + 10, y, 0).tex(1, 0).color(255, 255, 255, 255).endVertex();
            Tessellator.getInstance().draw();
        }
        //framebuffer.unbindFramebufferTexture();

        {
            //framebuffer.framebufferClear();
            //mc.getFramebuffer().bindFramebuffer(true);
            GL11.glBindTexture(GL_TEXTURE_2D, current);
        }
    }
}
 
Решение
Проблема странного текста решена выключением юникода
mc.fontRenderer.setUnicodeFlag(false)
Пока что не догнал, когда он включается
Проблема пропадания квада при наличии текста решается выключением Texture2D перед рендером квада, потому что рендер текста включает эту опцию
GlStateManager.disableTexture2D()
7,099
324
1,510
Проблема странного текста решена выключением юникода
mc.fontRenderer.setUnicodeFlag(false)
Пока что не догнал, когда он включается
Проблема пропадания квада при наличии текста решается выключением Texture2D перед рендером квада, потому что рендер текста включает эту опцию
GlStateManager.disableTexture2D()
 
7,099
324
1,510
Новая трабла: при попытке рисовать русский текст рисуются кракозябры такие же, как при попытке рендера английского текста с включенным юникодом
Java:
mc.fontRenderer.setUnicodeFlag(false)
mc.fontRenderer.drawString("Абв Testlol", 100, 100, 0xff00ff)
1624605988203.png
Если включить юникод:
Java:
mc.fontRenderer.setUnicodeFlag(true)
mc.fontRenderer.drawString("Абв Testlol", 100, 100, 0xff00ff)
1624606050902.png
 
7,099
324
1,510
Это какой-то дикий-придикий бред:
Если размеры фбо поставить на размеры экрана, то рендер текста налаживается
Как это работает?
 
7,099
324
1,510
Причина была в том, что разрешение фбо было в два раза меньше, чем требуется чтобы вписать в пиксели текст такого размера
 
Сверху