Смешивание TextureAtlasSprite'ов

Смешивание TextureAtlasSprite'ов 2018-08-02

Нет прав для скачивания
Версия(и) Minecraft
1.12+
Всем привет.
В новых версиях нельзя на прямую взаимодействовать с opengl для рендера обычных блоков и предметов. Поэтому приходится изворачиваться, чтобы получить некоторые возможности. В том числе и бленд(наложение) текстур.

Для чего это нужно?
Самый простой пример - руды. Как фон можно использовать стандартную текстуру камня, а накладывать уже вкрапления ресурсов.

Чем полезно?
Проще рисовать отдельные части текстур, чем сначала искать фон, а потом в графическом редакторе накладывать остальные части. При ресурспаке фоны ваших текстур будут соответствовать текстурам из текстурпака.

Как использовать?
Для начала нужно прочитать этот туториал. И вместо обычной текстурки вернуть эту:
Java:
public class MultiTextureAtlasSprite extends TextureAtlasSprite
{
    private ResourceLocation texture1;
    private ResourceLocation texture2;
    private ImmutableList<ResourceLocation> dependencies;

    /**
     * @param texture1 фон
     * @param texture2 накладываемая сверху текстура
     **/
    public MultiTextureAtlasSprite(ResourceLocation texture1, ResourceLocation texture2) {
        super(texture1.toString().concat("_".concat(texture2.toString())));
        this.texture1 = texture1;
        this.texture2 = texture2;
        dependencies = ImmutableList.of(this.texture1, this.texture2);
    }

    @Override
    public boolean hasCustomLoader(IResourceManager manager, ResourceLocation location) {
        return true;
    }

    @Override
    public Collection<ResourceLocation> getDependencies() {
        return dependencies;
    }

    @Override
    public boolean load(IResourceManager manager, ResourceLocation location, Function<ResourceLocation, TextureAtlasSprite> textureGetter) {
        //получаем текстуры по отдельности
        TextureAtlasSprite sprite = textureGetter.apply(texture1);
        TextureAtlasSprite mappingSprite = textureGetter.apply(texture2);
        width = sprite.getIconWidth();
        height = sprite.getIconHeight();
        int[][] pixels = new int[Minecraft.getMinecraft().gameSettings.mipmapLevels + 1][];
        //кол-во пикселей в новой текстуре
        pixels[0] = new int[width * height];

        //получаем пиксели 1 текстуры
        int[][] oldPixels = sprite.getFrameTextureData(0);
        //получаем пиксели 2 текстуры
        int[][] alphaPixels = mappingSprite.getFrameTextureData(0);

        for (int p = 0; p < width * height; p++) {
            //достаем альфу из значения пикселя(каждый цвет обозначается 8 битами)
            int oldPixelAlpha = alphaPixels[0][p] >>> 24;
            //Проверяем, пустой ли пиксель?
            if (oldPixelAlpha > 0)
                //если не пустой, то сетаем пиксель 2 текстурки в новую
                pixels[0][p] = alphaPixels[0][p];
            else
                //если пустой, то сетаем пиксель 1 текстурки в новую
                pixels[0][p] = oldPixels[0][p];
        }
        //очищаем предыдущие пиксели, которые могли остаться при перезагрузке текстур
        this.clearFramesTextureData();
        //добавляем свои
        this.framesTextureData.add(pixels);
        //возвращаем false, чтобы наш TextureAtlasSprite не загружался обычным способом
        return false;
    }
}
Ну и не забываем регистрировать наши текстутк . Я это делаю так
Java:
public class TextureEventHandler {
    private static List<TextureAtlasSprite> textureAtlasSprites = new ArrayList<>();
 
    @SubscribeEvent
    public void event(TextureStitchEvent.Pre event) {
        for (TextureAtlasSprite sprite : textureAtlasSprites)
            event.getMap().setTextureEntry(sprite);
    }

    public static void registerSprite(TextureAtlasSprite textureAtlasSprite){
        textureAtlasSprites.add(textureAtlasSprite);
    }
}
Теперь при создании любой смешанной текстурки помещаем её в список, и готово!
Ну и регистриуем наш обработчик событий.
Java:
public class OreModel implements IModel {
    ResourceLocation texture;
    public static ResourceLocation rockTexture = new ResourceLocation("blocks/stone");
    MultiTextureAtlasSprite spriteOre;
    public OreModel(ResourceLocation texture) {
        this.texture=texture;
        spriteOre = new MultiTextureAtlasSprite(rockTexture, texture);
        TextureEventHandler.registerSprite(spriteOre);
    }

    @Override
    public IModel smoothLighting(boolean value) {
        return new OreModel(texture);
    }

    @Override
    public Collection<ResourceLocation> getTextures() {
        return Collections.singletonList(texture);
    }

    @Override
    public IBakedModel bake(IModelState state, VertexFormat format, Function<ResourceLocation, TextureAtlasSprite> bakedTextureGetter) {

        ModelBaker baker = ModelBaker.INSTANCE;
        baker.begin(state, format);
        baker.setTexture(spriteOre);
        baker.putCube(0,0,0,0.5f, spriteOre.getMaxU(), spriteOre.getMinU(), spriteOre.getMinV(), spriteOre.getMaxV());
        return new OreBakedModel(baker.bake(), bakedTextureGetter.apply(rockTexture));
    }

}
Java:
public class OreBakedModel implements IBakedModel {
    List<BakedQuad> quads;
    TextureAtlasSprite textureAtlasSprite;

    public OreBakedModel(List<BakedQuad> quads, TextureAtlasSprite textureAtlasSprite){
        this.quads = quads;
        this.textureAtlasSprite = textureAtlasSprite;
    }

    @Override
    public List<BakedQuad> getQuads(@Nullable IBlockState state, @Nullable EnumFacing side, long rand) {
        return quads;
    }

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

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

    @Override
    public boolean isBuiltInRenderer() {
        return false;
    }

    @Override
    public TextureAtlasSprite getParticleTexture() {
        return textureAtlasSprite;
    }

    @Override
    public ItemOverrideList getOverrides() {
        return ItemOverrideList.NONE;
    }

    ItemTransformVec3f firstperson_righthand = new ItemTransformVec3f(new Vector3f(0,45,0), new Vector3f(0, 0, 0), new Vector3f(0.40f, 0.40f, 0.40f));
    ItemTransformVec3f firstperson_lefthand = new ItemTransformVec3f(new Vector3f(0,225,0), new Vector3f(0, 0, 0), new Vector3f(0.40f, 0.40f, 0.40f));

    ItemTransformVec3f thirdperson_righthand = new ItemTransformVec3f(new Vector3f(75,45,0), new Vector3f(0, 0.15f, 0), new Vector3f(0.375f, 0.375f, 0.375f));

    private ItemTransformVec3f fixed = new ItemTransformVec3f(new Vector3f(0,0,0), new Vector3f(0, 0, 0), new Vector3f(0.5f, 0.5f, 0.5f));
    private ItemTransformVec3f ground = new ItemTransformVec3f(new Vector3f(0,0,0), new Vector3f(0, 0.15f, 0), new Vector3f(0.25f, 0.25f, 0.25f));
    private ItemTransformVec3f gui = new ItemTransformVec3f(new Vector3f(30,225,0), new Vector3f(0, 0, 0), new Vector3f(0.625f, 0.625f, 0.625f));


    private ItemCameraTransforms itemCameraTransforms = new ItemCameraTransforms(thirdperson_righthand, thirdperson_righthand,
            firstperson_lefthand, firstperson_righthand,
            ItemTransformVec3f.DEFAULT, gui, ground, fixed);

    @Override
    public ItemCameraTransforms getItemCameraTransforms() {

        return itemCameraTransforms;
    }
}
Получаем в итоге
2018-08-02_22.45.04.png


1533239196667.png
  • Like
Реакции: Garik, CMTV и Nikitat0
Автор
Могучий горгон
Скачивания
4
Просмотры
884
Первый выпуск
Обновление
Оценка
5.00 звёзд 3 оценок

Другие ресурсы пользователя Могучий горгон

Последние рецензии

Отлично, но есть вопросы: где я задаю пути для этих двух новых текстур?
Могучий горгон
Могучий горгон
в ResourceLocation который подается в MultiTextureAtlasSprite
Полезно и понятно
Ссылка битая на пред. тутор. А так туториал отличный!
Могучий горгон
Могучий горгон
Спасибо, исправил
Сверху