Освещение блоков с кастомным IBakedModel

Версия Minecraft
1.12.2
1,057
50
234
Сделал рендер 2 слоя на блоках через IBakedModel, все прекрасно, все работает, но, освещение на блоках ломается. Где фиксить?

Java:
public class BakedModelFullbright extends BakedModelDelegate {
  
    private static final VertexFormat format = new VertexFormat(DefaultVertexFormats.BLOCK).addElement(DefaultVertexFormats.TEX_2S);
  
  
    private static String texture, layer;
    private static int bright;
    private static double alpha;
    TextureAtlasSprite sprite;

    public BakedModelFullbright(IBakedModel base, String texture, int bright, double color) {
        super(base);
       // this.texture = texture;
        this.bright = bright;
        this.alpha = color;
      
        sprite = Minecraft.getMinecraft().getTextureMapBlocks().getAtlasSprite(texture.toString());
      
    }

    private void putVertex(UnpackedBakedQuad.Builder builder, IBlockState state, Vec3d normal, double x, double y, double z, TextureAtlasSprite sprite, float u, float v, boolean hasBrightness, int brightness, Vec3d color)
    {
      
        for (int e = 0; e < format.getElementCount(); e++)
        {
            switch (format.getElement(e).getUsage())
            {
                case POSITION:
                    builder.put(e, (float) x, (float) y, (float) z);
                    break;
                case COLOR:
                    builder.put(e, (float)color.x, (float)color.y, (float)color.z, 1.0F);
                    break;
                case UV:
                    if (format.getElement(e).getIndex() == 1)
                    {
                        if (hasBrightness)
                        {
                            float blockLight = ((float) ((brightness >> 4) & 15) * 32) / 65535;
                            float skyLight = ((float) ((brightness >> 20) & 15) * 32) / 65535;
                            builder.put(e, blockLight, skyLight);
                        }
                        else
                        {
                            builder.put(e);
                        }
                    }
                    else
                    {
                        u = sprite.getInterpolatedU(u);
                        v = sprite.getInterpolatedV(v);
                        builder.put(e, u, v);
                    }
                    break;
                case NORMAL:
                    if (hasBrightness)
                    {
                        builder.put(e, 0.0F, 1.0F, 0.0F);
                    }
                    else
                    {
                        builder.put(e,(float) normal.x, (float) normal.y, (float) normal.z);
                    }
                    break;
                default:
                    builder.put(e);
                    break;
            }
        }
    }
  
    @Override
    public List<BakedQuad> getQuads(@Nullable IBlockState state, @Nullable EnumFacing side, long rand) {
      
      
        if (state == null) {
            return base.getQuads(state, side, rand);
        }

        List<BakedQuad> quads = new ArrayList<>();
      
      
        quads.add(createQuad(state, new Vec3d(1.0D, 0.0D, 0.0D), new Vec3d(1.0D, 0.0D, 1.0D), new Vec3d(0.0D, 0.0D, 1.0D), new Vec3d(0.0D, 0.0D, 0.0D), this.base.getParticleTexture(), false, 0, new Vec3d(1.0D, 1.0D, 1.0D), 0));
        quads.add(createQuad(state, new Vec3d(0.0D, 1.0D, 0.0D), new Vec3d(0.0D, 1.0D, 1.0D), new Vec3d(1.0D, 1.0D, 1.0D), new Vec3d(1.0D, 1.0D, 0.0D), this.base.getParticleTexture(), false, 0, new Vec3d(1.0D, 1.0D, 1.0D), 0));
        quads.add(createQuad(state, new Vec3d(1.0D, 0.0D, 1.0D), new Vec3d(1.0D, 1.0D, 1.0D), new Vec3d(0.0D, 1.0D, 1.0D), new Vec3d(0.0D, 0.0D, 1.0D), this.base.getParticleTexture(), false, 0, new Vec3d(1.0D, 1.0D, 1.0D), 0));
        quads.add(createQuad(state, new Vec3d(0.0D, 0.0D, 0.0D), new Vec3d(0.0D, 1.0D, 0.0D), new Vec3d(1.0D, 1.0D, 0.0D), new Vec3d(1.0D, 0.0D, 0.0D), this.base.getParticleTexture(), false, 0, new Vec3d(1.0D, 1.0D, 1.0D), 0));
        quads.add(createQuad(state, new Vec3d(0.0D, 0.0D, 1.0D), new Vec3d(0.0D, 1.0D, 1.0D), new Vec3d(0.0D, 1.0D, 0.0D), new Vec3d(0.0D, 0.0D, 0.0D), this.base.getParticleTexture(), false, 0, new Vec3d(1.0D, 1.0D, 1.0D), 0));
        quads.add(createQuad(state, new Vec3d(1.0D, 0.0D, 0.0D), new Vec3d(1.0D, 1.0D, 0.0D), new Vec3d(1.0D, 1.0D, 1.0D), new Vec3d(1.0D, 0.0D, 1.0D), this.base.getParticleTexture(), false, 0, new Vec3d(1.0D, 1.0D, 1.0D), 0));
      
        quads.add(createQuad(state, new Vec3d(1.0D, 0.0D, 0.0D), new Vec3d(1.0D, 0.0D, 1.0D), new Vec3d(0.0D, 0.0D, 1.0D), new Vec3d(0.0D, 0.0D, 0.0D), sprite, true, this.bright, new Vec3d(this.alpha, this.alpha, this.alpha), 0));
        quads.add(createQuad(state, new Vec3d(0.0D, 1.0D, 0.0D), new Vec3d(0.0D, 1.0D, 1.0D), new Vec3d(1.0D, 1.0D, 1.0D), new Vec3d(1.0D, 1.0D, 0.0D), sprite, true, this.bright, new Vec3d(this.alpha, this.alpha, this.alpha), 0));
        quads.add(createQuad(state, new Vec3d(1.0D, 0.0D, 1.0D), new Vec3d(1.0D, 1.0D, 1.0D), new Vec3d(0.0D, 1.0D, 1.0D), new Vec3d(0.0D, 0.0D, 1.0D), sprite, true, this.bright, new Vec3d(this.alpha, this.alpha, this.alpha), 0));
        quads.add(createQuad(state, new Vec3d(0.0D, 0.0D, 0.0D), new Vec3d(0.0D, 1.0D, 0.0D), new Vec3d(1.0D, 1.0D, 0.0D), new Vec3d(1.0D, 0.0D, 0.0D), sprite, true, this.bright, new Vec3d(this.alpha, this.alpha, this.alpha), 0));
        quads.add(createQuad(state, new Vec3d(0.0D, 0.0D, 1.0D), new Vec3d(0.0D, 1.0D, 1.0D), new Vec3d(0.0D, 1.0D, 0.0D), new Vec3d(0.0D, 0.0D, 0.0D), sprite, true, this.bright, new Vec3d(this.alpha, this.alpha, this.alpha), 0));
        quads.add(createQuad(state, new Vec3d(1.0D, 0.0D, 0.0D), new Vec3d(1.0D, 1.0D, 0.0D), new Vec3d(1.0D, 1.0D, 1.0D), new Vec3d(1.0D, 0.0D, 1.0D), sprite, true, this.bright, new Vec3d(this.alpha, this.alpha, this.alpha), 0));
      
        return quads;
    }

    private BakedQuad createQuad(IBlockState state, Vec3d v1, Vec3d v2, Vec3d v3, Vec3d v4, TextureAtlasSprite sprite, boolean hasBrightness, int brightness, Vec3d color, int tint)
    {
        Vec3d normal = v3.subtract(v2).crossProduct(v1.subtract(v2)).normalize();
      
        UnpackedBakedQuad.Builder builder = new UnpackedBakedQuad.Builder(format);

        builder.setTexture(sprite);
        builder.setQuadTint(tint);
        putVertex(builder, state, normal, v1.x, v1.y, v1.z, sprite, 16, 16, hasBrightness, brightness, color);
        putVertex(builder, state, normal, v2.x, v2.y, v2.z, sprite, 16, 0, hasBrightness, brightness, color);
        putVertex(builder, state, normal, v3.x, v3.y, v3.z, sprite, 0, 0, hasBrightness, brightness, color);
        putVertex(builder, state, normal, v4.x, v4.y, v4.z, sprite, 0, 16, hasBrightness, brightness, color);
        //builder.setApplyDiffuseLighting(false);
        return builder.build();
    }
    

    @Override
    public boolean isAmbientOcclusion() {
        return true;
    }
}

2018-08-22_14.11.31.png
 
Даже, если я ставлю
Java:
float blockLight = ((float) ((240 >> 4) & 15) * 32) / 65535;
                            float skyLight = ((float) ((240 >> 20) & 15) * 32) / 65535;
                            builder.put(e, blockLight, skyLight);
то освещение остается кривым =\
2018-08-23_10.38.03.png

2018-08-23_10.38.05.png
Просто светимость слоя стала лучше.
После очередного копания в коде, я выяснил, что ломается освещение при добавлении квадов
Java:
quads.add(createQuad(state, new Vec3d(1.0D, 0.0D, 0.0D), new Vec3d(1.0D, 0.0D, 1.0D), new Vec3d(0.0D, 0.0D, 1.0D), new Vec3d(0.0D, 0.0D, 0.0D), this.base.getParticleTexture(), false, (int) state.getAmbientOcclusionLightValue(), new Vec3d(1.0D, 1.0D, 1.0D), 0));
        quads.add(createQuad(state, new Vec3d(0.0D, 1.0D, 0.0D), new Vec3d(0.0D, 1.0D, 1.0D), new Vec3d(1.0D, 1.0D, 1.0D), new Vec3d(1.0D, 1.0D, 0.0D), this.base.getParticleTexture(), false, (int) state.getAmbientOcclusionLightValue(), new Vec3d(1.0D, 1.0D, 1.0D), 0));
        quads.add(createQuad(state, new Vec3d(1.0D, 0.0D, 1.0D), new Vec3d(1.0D, 1.0D, 1.0D), new Vec3d(0.0D, 1.0D, 1.0D), new Vec3d(0.0D, 0.0D, 1.0D), this.base.getParticleTexture(), false, (int) state.getAmbientOcclusionLightValue(), new Vec3d(1.0D, 1.0D, 1.0D), 0));
        quads.add(createQuad(state, new Vec3d(0.0D, 0.0D, 0.0D), new Vec3d(0.0D, 1.0D, 0.0D), new Vec3d(1.0D, 1.0D, 0.0D), new Vec3d(1.0D, 0.0D, 0.0D), this.base.getParticleTexture(), false, (int) state.getAmbientOcclusionLightValue(), new Vec3d(1.0D, 1.0D, 1.0D), 0));
        quads.add(createQuad(state, new Vec3d(0.0D, 0.0D, 1.0D), new Vec3d(0.0D, 1.0D, 1.0D), new Vec3d(0.0D, 1.0D, 0.0D), new Vec3d(0.0D, 0.0D, 0.0D), this.base.getParticleTexture(), false, (int) state.getAmbientOcclusionLightValue(), new Vec3d(1.0D, 1.0D, 1.0D), 0));
        quads.add(createQuad(state, new Vec3d(1.0D, 0.0D, 0.0D), new Vec3d(1.0D, 1.0D, 0.0D), new Vec3d(1.0D, 1.0D, 1.0D), new Vec3d(1.0D, 0.0D, 1.0D), this.base.getParticleTexture(), false, (int) state.getAmbientOcclusionLightValue(), new Vec3d(1.0D, 1.0D, 1.0D), 0));
      
        quads.add(createQuad(state, new Vec3d(1.0D, 0.0D, 0.0D), new Vec3d(1.0D, 0.0D, 1.0D), new Vec3d(0.0D, 0.0D, 1.0D), new Vec3d(0.0D, 0.0D, 0.0D), sprite, true, this.bright, new Vec3d(this.alpha, this.alpha, this.alpha), 0));
        quads.add(createQuad(state, new Vec3d(0.0D, 1.0D, 0.0D), new Vec3d(0.0D, 1.0D, 1.0D), new Vec3d(1.0D, 1.0D, 1.0D), new Vec3d(1.0D, 1.0D, 0.0D), sprite, true, this.bright, new Vec3d(this.alpha, this.alpha, this.alpha), 0));
        quads.add(createQuad(state, new Vec3d(1.0D, 0.0D, 1.0D), new Vec3d(1.0D, 1.0D, 1.0D), new Vec3d(0.0D, 1.0D, 1.0D), new Vec3d(0.0D, 0.0D, 1.0D), sprite, true, this.bright, new Vec3d(this.alpha, this.alpha, this.alpha), 0));
        quads.add(createQuad(state, new Vec3d(0.0D, 0.0D, 0.0D), new Vec3d(0.0D, 1.0D, 0.0D), new Vec3d(1.0D, 1.0D, 0.0D), new Vec3d(1.0D, 0.0D, 0.0D), sprite, true, this.bright, new Vec3d(this.alpha, this.alpha, this.alpha), 0));
        quads.add(createQuad(state, new Vec3d(0.0D, 0.0D, 1.0D), new Vec3d(0.0D, 1.0D, 1.0D), new Vec3d(0.0D, 1.0D, 0.0D), new Vec3d(0.0D, 0.0D, 0.0D), sprite, true, this.bright, new Vec3d(this.alpha, this.alpha, this.alpha), 0));
        quads.add(createQuad(state, new Vec3d(1.0D, 0.0D, 0.0D), new Vec3d(1.0D, 1.0D, 0.0D), new Vec3d(1.0D, 1.0D, 1.0D), new Vec3d(1.0D, 0.0D, 1.0D), sprite, true, this.bright, new Vec3d(this.alpha, this.alpha, this.alpha), 0));
если их убрать, и возвращать base.getQuads(state, side, rand); - проблем с освещением нет, но и 2 слоя на блоках соответственно нет...
2018-08-23_10.41.54.png
 
При таком большом кол-ве вершин сложно понять, че представляют из себя эти квады и правильно ли они сделаны
 
Если я правильно понимаю, ломается у тебя не освещение, а вычисление AO (ambient occlusion) для блока, это дополнительное затенение (для "мягкого освещения").

По идее самым адекватным решением будет вернуть ванильную реализацию base.getQuads для каждого слоя (насколько я понимаю, тебе это должно подойти), и ручками внутри подменить (хуками, например) текстуру\иконку\ювшки, что тебе там нужно. Ну и квады от каждого слоя потом можно соединить в один список.
 
Назад
Сверху