Гайд Создание своего чита. Глава 2 - Рендер

  • Автор темы Автор темы mewiz
  • Дата начала Дата начала
Начинающий
Начинающий
Статус
Онлайн
Регистрация
29 Июл 2025
Сообщения
153
Реакции
2

Перед прочтением основного контента ниже, пожалуйста, обратите внимание на обновление внутри секции Майна на нашем форуме. У нас появились:

  • бесплатные читы для Майнкрафт — любое использование на свой страх и риск;
  • маркетплейс Майнкрафт — абсолютно любая коммерция, связанная с игрой, за исключением продажи читов (аккаунты, предоставления услуг, поиск кодеров читов и так далее);
  • приватные читы для Minecraft — в этом разделе только платные хаки для игры, покупайте группу "Продавец" и выставляйте на продажу свой софт;
  • обсуждения и гайды — всё тот же раздел с вопросами, но теперь модернизированный: поиск нужных хаков, пати с игроками-читерами и другая полезная информация.

Спасибо!

Продолжаем создавать свой клиент, в этом топике расскажу всё что даровано мною великим сенсеем микромягким о рендере :goplol:
В кубомире существует несколько способов рендера, а именно:

1. Иммедиатный рендер (OpenGL)
До жути старый метод отрисовки, на данный момент его никто не юзает (лично я ещё не встречал таких)
По сути бесполезный, не имеет буферизации и очень медленный и нихуя не масштабируется

2. Tessellator + BufferBuilder
Стандартный рендер кубиков, работает в паре с MatrixStack
Позволяет рендерить как и в 2д, так и в 3д
Из минусов подмечу очень сука сложную реализацию, код одной ватермарки можно расстянуть на дохулион строк

3. DrawableHelper
По сути покусанный, обрезанный рендер состоящий из тесселятора, используется только в гуи, не имеет гибкости

4. Framebuffer
Рисуется в отдельном фбо, потом выводиться на экран, в основном используется для пост-эффектов
(Есть ещё пару типов рендера, но их я не упомянул)

И так, как же начать писать свой рендер?
Для начала советую почитать о OpenGL и GLSL, в рендере штука нужная
К примеру, OpenGL даст вам информации о координатных систем, работа с матрицей и трансформацией
GLSL научит высислениям в шейдере и работой с юниформами и аттрибутами

Утилки писать мы не будем к сожалению, но я вам расскажу что и как работает, на основе популярной рендер системы - MRE (!noad! ссылка на гитхаб -
Пожалуйста, авторизуйтесь для просмотра ссылки.
)
Начнем мы с шейдер программы
Код:
Expand Collapse Copy
// К Примеру возьмём обычный рект
public record BuiltRectangle(
        SizeState size,          // Хранит размеры прямоугольника (height и weight)
        QuadRadiusState radius,  // Радиусы скруглений для углов
        QuadColorState color,    // Цвета для каждой из вершин
        float smoothness         // Параметр сглаживания
    ) implements IRenderer {

    // Ключ для шейдерной программы
    // Путь к шейдеру и сообственно указывает откуда подгружать
    private static final ShaderProgramKey RECTANGLE_SHADER_KEY = new ShaderProgramKey(
        ResourceProvider.getShaderIdentifier("rectangle"),
        VertexFormats.POSITION_COLOR,
        Defines.EMPTY
    );

    @Override
    public void render(Matrix4f matrix, float x, float y, float z) {
        // Тута мы включаем альфа блендинг для прозрачности
        RenderSystem.enableBlend();
        RenderSystem.defaultBlendFunc(); // Устанавливаем стандартный режим смешивания цветов
        RenderSystem.disableCull(); // Отключаем отсечение невидимых граней (чтобы рисовалось всё)

        // Получаем ширину и высоту из объекта SizeState
        float width = this.size.width(), height = this.size.height();

        // Устанавливаем текущий шейдер и получаем к нему доступ
        ShaderProgram shader = RenderSystem.setShader(RECTANGLE_SHADER_KEY);

        // Передаём в шейдер юниформ переменные
        shader.getUniform("Size").set(width, height); // Размер прямоугольника
        shader.getUniform("Radius").set(              // Радиусы скруглений для 4 углов
            this.radius.radius1(),
            this.radius.radius2(),
            this.radius.radius3(),
            this.radius.radius4()
        );
        shader.getUniform("Smoothness").set(this.smoothness); // Сглаживание краёв

        // Создаeм буфер для отрисовки вершин (QUADS = 4 вершины)
        BufferBuilder builder = Tessellator.getInstance().begin(DrawMode.QUADS, VertexFormats.POSITION_COLOR);

        // Добавляем 4 вершины прямоугольника с указанием цвета для каждой
        builder.vertex(matrix, x, y, z).color(this.color.color1());               // Левая нижняя вершина
        builder.vertex(matrix, x, y + height, z).color(this.color.color2());      // Левая верхняя вершина
        builder.vertex(matrix, x + width, y + height, z).color(this.color.color3());// Правая верхняя вершина
        builder.vertex(matrix, x + width, y, z).color(this.color.color4());       // Правая нижняя вершина

        // Отправляем буфер на GPU с использованием текущей шейдерной программы
        BufferRenderer.drawWithGlobalProgram(builder.end());

        // Возвращаем стандартные настройки рендера
        RenderSystem.enableCull(); // Включаем обратно отсечение невидимых граней
        RenderSystem.disableBlend(); // Выключаем прозрачность
    }
}
Ну, шейдер программу мы разобрали и поняли как работать с шейдерами, а рендерить то как???
Приступим к самому рендеру
Код:
Expand Collapse Copy
public final class RectangleBuilder extends AbstractBuilder<BuiltRectangle> {

    // Хранит настройки для прямоугольника, которые будем настраивать
    private SizeState size;            // Размер
    private QuadRadiusState radius;    // Радиус скругления
    private QuadColorState color;      // Цвета углов
    private float smoothness;          // Сглаживание углов

    // Метод для установки размера прямоугольника
    public RectangleBuilder size(SizeState size) {
        this.size = size;          // Запоминаем размер
        return this;              // Бекаем текущий объект для цепочки
    }

    // Метод для установки радиусов скругления углов
    public RectangleBuilder radius(QuadRadiusState radius) {
        this.radius = radius;      // Запоминаем радиус
        return this;              // Бекаем текущий объект для цепочки
    }

    // Метод для установки цветов вершин
    public RectangleBuilder color(QuadColorState color) {
        this.color = color;        // Запоминаем цвета углов
        return this;              // И сновааааа бекаем текущий обьект для цепочки
    }

    // Метод для установки сглаживания краёв
    public RectangleBuilder smoothness(float smoothness) {
        this.smoothness = smoothness;  // Запоминаем параметр сглаживания
        return this;                  // Ну бля думаю вы поняли
    }

    // Собирает объект (рект) из заданных настроек
    @Override
    protected BuiltRectangle _build() {
        return new BuiltRectangle(
            this.size,
            this.radius,
            this.color,
            this.smoothness
        );
    }

    // Сбрасывает всё по умолчанию, что бы можно было заново отрендерить обьект
    @Override
    protected void reset() {
        this.size = SizeState.NONE;               // Нет размера
        this.radius = QuadRadiusState.NO_ROUND;   // Без скругления
        this.color = QuadColorState.TRANSPARENT;  // Фулл прозрачный
        this.smoothness = 1.0f;                    // Сглаживание чйоткае ле
    }
}
Готово, теперь можно рендерить! (в скобачках нед)))
Забыли мы про шейдеры, давайте и про них расскажу
Как и писал выше, существуют 2 типа шейдеров (Фрагментные - vsh, fsh и glsl)
Фрагментный шейдер это программа на GLSL, которая дрочит цвет и прозрачность каждого пикселя на экране, а GLSL это язык, на котором пишут такие шейдеры для управления эффектами в рендере
Код:
Expand Collapse Copy
#version 150

in vec2 texCoord;          // Интерполированные юниформы из вершинного шейдера
out vec4 fragColor;        // Цвет пикселя на выходе

uniform sampler2D textureSampler;  // Текстура для семплирования цвета

void main() {
    // Берем цвет из текстуры по UV
    vec4 texColor = texture(textureSampler, texCoord);

    // Выводим цвет без изменений, просто цвет короче
    fragColor = texColor;
}

Вот самый примитивный шейдер на GLSL, ниже показан пример с фрагметным

Код:
Expand Collapse Copy
#version 150

in vec2 texCoord;      // Юниформы из вершинного шейдера
out vec4 fragColor;    // Цвет пикселя

void main() {
    // Создаем градиент, к примеру от красного к синему
    fragColor = vec4(texCoord.x, 0.0, 1.0 - texCoord.x, 1.0);
}

На этом закрою данный топик, вроде базовую информацию для незнающих я донес, желаю удаче!
:pepepopcorn:

Опционально:
Советую прочитать что то типо документации по GLSL и OpenGL
Пожалуйста, авторизуйтесь для просмотра ссылки.
Пожалуйста, авторизуйтесь для просмотра ссылки.
 
 
ну у тебя больше информации, у меня скорее гайд для чайников
 
1. Иммедиатный рендер (OpenGL)
До жути старый метод отрисовки, на данный момент его никто не юзает (лично я ещё не встречал таких)
По сути бесполезный, не имеет буферизации и очень медленный и нихуя не масштабируется
На форуме по кд публикуют какую-то фигню вроде HitCircle которые используют immediate mode rendering, некоторые и вовсе "рекомендуют" его использовать
Бесполезным я бы его не назвал, но единственные его реальные применения должны ограничиваться дебагом (имхо)

Дальше - нудятина, для общего развития скорее
Буферизация там как раз таки есть (я ес честно сомневаюсь что вообще как либо можно передавать вершины по отдельности если это только не 2 вертекс-стрима, и то это что-то странное), и из-за этой буферизации и происходит затуп потому-что мы всё это передаем по отдельности в драйвер, который это всё собирает. В случае с VBO - собираем всё 1 раз, передаём хендл буффера для рендеринга, по необходимости обновляем данные если буффер позволяет таковое. В случае с Tessellator(VAO с короткоживущим VBO) мы уже имеем собранный буффер данных, и не перегружаем драйвер передачей каждого отдельного аттрибута вершины. Поэтому: Immediate mode < Tessellator < VBO (потому-что VBO мы собираем 1 раз и храним, пока Tessellator собирает буфферы с 0 каждый кадр, а Immediate mode делает тоже самое, только размазывая каждый аттрибут по драйверу :roflanEbalo:)

Жалко ваще что до сих пор не видел ни разу ни в модах, ни в читах использования UBO (ну или хотя-бы кеширования юниформов), вещи то далеко не бесполезные...
 
в 1.21.7+ использование UBO в шейдерах обязательно
 
Это разве чит/мод? :kappa:
В играх то ясное дело, а вот в остальных случаях моддинга еще не видел ни разу в майнкрафте включая саму игру (в винтажке(кубач с ТФК) был случай но я не уверен, там то ли предложение было внедрить UBO в саму игру, то ли мод был прям уже делающий это)

в 1.21.7+ использование UBO в шейдерах обязательно
О, эт прикольно если они внутренним API отказались от сырой передачи юниформов и сдвинулись в сторону UBO, не знал
 
Да, и вообще, игра, походу, готовится к переходу на мультипоточность, разграничивая логику и рендеринг, тк была введена карусель буферов и драв контекст (через что рендерится ванильный худ), теперь сначала коллектит объекты, а затем разом рисует
 
Да, и вообще, игра, походу, готовится к переходу на мультипоточность, разграничивая логику и рендеринг, тк была введена карусель буферов и драв контекст (через что рендерится ванильный худ), теперь сначала коллектит объекты, а затем разом рисует
Походит на простой батчинг на самом деле, хотя что-то подобное есть в bgfx который на бедроке графон держит, просто что ОГЛ в таком случае ну немного имхо странно уже было бы держать
 
знал что ты напишешь это. я просто к слову, что игра построена на майне
Да много чего там поменяли уже, я думаю СК уже плюс минус лет как 10, на базе кубача довольно много прикольных штук с разными масштабами внедрения делали (вспомнить тот-же ресталкер о котором вряд-ли кто-то тут знает, который был написан на 1.3.2, выглядел всрато, но вполне себе был живым)0 )
Ну и из-за количества изменений я-б не рассматривал, полюбому(имхо) там кубачевского кода еще достаточно, но наверняка мы об этом вряд-ли узнаем. Пред-стимовые дампы довольно древние да и ковыряться в них ради того что-б знать скок у них кубача осталось ну такое как по мне
 
Назад
Сверху Снизу