Рендер многослойной текстуры блока (рантайм генерация BakedQuad)

Версия Minecraft
1.12.2
API
Forge
Привет, есть цель создать блок с многослойной текстурой, а именно
  • layer 1: текстура самого блока (желтая)
  • layer 2: кусок текстуры соседнего блока (со стороны прилегания)
  • layer 3: Шов (крест)
У самого блока RenderLayer стоит как CUTOUT_MIPPED

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

2023-05-22_01.39.27.png

Код getQuads
getQuads:
public List<BakedQuad> getQuads(@Nullable IBlockState state, @Nullable EnumFacing side, long rand) {
        List<BakedQuad> bakedQuads = new ArrayList<>();
        if (state instanceof IExtendedBlockState && side != null) {
            IExtendedBlockState blockState = (IExtendedBlockState) state;
            ExchangeValue value = blockState.getValue(FramePanelBlock.EXCHANGE);
            List<BakedQuad> baseQuads = this.base.getQuads(state, side, rand);
            bakedQuads.add(baseQuads.get(0)); // добавляем квад с текстурой самого блока
            if (!EnumFacing.UP.equals(side) && !EnumFacing.DOWN.equals(side)) {
                this.getOverlayQuads(bakedQuads, side, (FramePanelType[]) value.getValue(side.getName())); // добавляем квад с текстурой соседнего блока
                if (baseQuads.size() > 1) {
                    bakedQuads.add(baseQuads.get(1)); // добавляем квад с текстурой шва
                }
            }
        }
        return bakedQuads;
    }

    private void getOverlayQuads(List<BakedQuad> bakedQuads, EnumFacing side, FramePanelType[] overlays) {
        for (int i = 0; i < overlays.length; i++) {
            if (overlays[i] != null) {
                BakedQuad quad = this.createBakedQuad(side, overlays[i], i);
                if (quad != null) {
                    bakedQuads.add(quad);
                }
            }
        }
    }

    private BakedQuad createBakedQuad(EnumFacing side, FramePanelType panelType, int overlayType) {
        OverlayElement element = OverlayService.getOverlayElement(panelType, overlayType);
        if (element != null) {
            UnpackedBakedQuad.Builder builder = new UnpackedBakedQuad.Builder(this.format);
            builder.setQuadOrientation(side);
            builder.setTexture(this.getParticleTexture()); // текстура-заглушка самого блока
            Vec3d[] vertex = element.getRawQuad(side);
            for (int i = 0; i < vertex.length; i++) {   // создание квада на основе кадрированной текстуры соседнего блока
                ModelUtil.putVertex(builder, this.format, Optional.empty(), side,
                        (float) vertex[i].x * 0.0625f, (float) vertex[i].y * 0.0625f, (float) vertex[i].z * 0.0625f,
                        element.getTextureU(i), element.getTextureV(i), 1.0f, 1.0f, 1.0f, 1.0f);
            }
            return builder.build();
        }
        return null;
    }

Код putVertex (взято с форума)
putVertex:
public static void putVertex(UnpackedBakedQuad.Builder builder, VertexFormat format, Optional<TRSRTransformation> transform, EnumFacing side, float x, float y, float z, float u, float v, float r, float g, float b, float a) {
        Vector4f vec = new Vector4f();
        for (int e = 0; e < format.getElementCount(); e++) {
            switch (format.getElement(e).getUsage()) {
                case POSITION:
                    if (transform.isPresent()) {
                        vec.x = x;
                        vec.y = y;
                        vec.z = z;
                        vec.w = 1;
                        transform.get().getMatrix().transform(vec);
                        builder.put(e, vec.x, vec.y, vec.z, vec.w);
                    } else {
                        builder.put(e, x, y, z, 1);
                    }
                    break;
                case COLOR:
                    builder.put(e, r, g, b, a);
                    break;
                case UV:
                    if(u != -1 && v != -1) {
                        if (format.getElement(e).getIndex() == 0) {
                            builder.put(e, u, v, 0f, 1f);
                            break;
                        }
                    }
                case NORMAL:
                    builder.put(e, (float) side.getFrontOffsetX(), (float) side.getFrontOffsetY(), (float) side.getFrontOffsetZ(), 0f);
                    break;
                default:
                    builder.put(e);
                    break;
            }
        }
    }
 
Последнее редактирование:
Решение
Осознав одну интересную особенность lwjgl и поиграв с костылями получилось сделать это:

2023-05-26_00.50.01.png2023-05-26_01.14.16.png

Правда оттого появилось много проблем так что буду и дальше думать в этом направлении )
1,038
57
229
ты хотя бы опиши что ты сделал.
Я помню что был метод по отрисовке любого блока также как модель блока в инвентаре.
Но не помню есть ли такое событие к которому можно было бы привязаться.
Яб сделал именно так, через полигоны и сравнивая блоки рядом стоящие рисовал бы что нужно.
 
Проще говоря я понял, что файтинг текстур в lwjgl возникает при отрисовки квадов разного размера на одном и том же месте. К примеру у блока травы есть вторичный квад для оверлея кромки блока с куксом травы, так вот он также же должен иметь размер квада такой же как и оригинальный блок. Поэтому для процедурного наложения части текстуры другого блока мне пришлось резать блок на часть с наложением и часть без нее и на обе этих части накладывать нужные квады с текстурами как на бутерброд )) Имхо лучше так, чем держать в глобальной текстур мапе 100500+ вариаций текстур с каждым вариантом наложения.

И как я писал, проблема была не в том к какому событию привязаться / как сравнивать блоки / тд, а как корректно и без артефактов нарисовать поверх блока новый квад нужного размера с нужной текстурой.
 
Последнее редактирование:
Сверху