Мерцание текстуры

Agravaine написал(а):
Бле, может ты сначала попробуешь, а потом будешь глупые вопросы задавать?
Правила нарушать не надо?делаешь не впервые.IHLMod.proxy.getFBOID().Я такой маг,догадался ,что это,да?
 
Foghrye4 написал(а):
Стандартный номер буфера в майнкрафте - 1, но ты можешь проверить это с помощью функции:
Код:
                boolean isframebuffer = EXTFramebufferObject.glIsFramebufferEXT(i);
                if(isframebuffer)
                {
                    defaultMinecraftFBOId=i;
                }
Повылазило?
 
krok написал(а):
Код:
RenderGameOverlayEvent

Ты уверен?Это вроде текст на экране
Да, это он и есть. Просто если ты будешь отрисовывать твою новую текстуру во время отрисовки модели, ты замучаешься размещать её на экране так, чтобы на неё не влияли настройки поля зрения игрока, а потом возможно придётся заново настраивать стандартный вид камеры.

[font=Verdana, Helvetica, Arial, sans-serif]IHLMod.proxy.getFBOID()[/font]
[font=Verdana, Helvetica, Arial, sans-serif]На самом деле это хороший вопрос. Это номер твоего собственного личного буфера, в котором ты можешь рисовать что угодно, не влияя на картинку, которую видит игрок. Вот так я генерирую этот номер и, заодно [/font][font=Verdana, Helvetica, Arial, sans-serif]Renderbuffer (это разные вещи)[/font][font=Verdana, Helvetica, Arial, sans-serif]:[/font]
Код:
    fboId = EXTFramebufferObject.glGenFramebuffersEXT();
renderBufferId = EXTFramebufferObject.glGenRenderbuffersEXT();
Генерируется он всего один раз на все время работы манкрафта, так же, как и текстура. Я это делаю в момент загрузки моего клиентского прокси.
 
Нифига, на форуме прибыло любителей OpenGL :3
Лень читать весь твой пост, вкратце, ты динамически (единожды) создаёшь текстуру с помощью фреймбуфера, в которой рисуешь скин игрока и одежду поверх первого, и используешь её потом в качестве текстуры для модели?
Не надо ли потом удалять фреймбуфер? (Ну, понятно, что не обязательно, но ПАМЯТЬ же, хотя там смехотворно мало её используется, наверное) И не снесёт ли это привязанную к нему текстуру (доки по этому поводу не читал)?
 
Oldestkon написал(а):
динамически (единожды) создаёшь текстуру с помощью фреймбуфера, в которой рисуешь скин игрока и одежду поверх первого, и используешь её потом в качестве текстуры для модели?
Да, ты все правильно понял.

Oldestkon написал(а):
Не надо ли потом удалять фреймбуфер? (Ну, понятно, что не обязательно, но ПАМЯТЬ же, хотя там смехотворно мало её используется, наверное) И не снесёт ли это привязанную к нему текстуру (доки по этому поводу не читал)?
Теоретически надо удалять каждую созданную тобой текстуру, RenderBuffer и FrameBuffer по закрытию Minecraft. В LWJGL предусмотрены соответствующие функции.
Код:
        EXTFramebufferObject.glDeleteFramebuffersEXT(fboId);
        EXTFramebufferObject.glDeleteRenderbuffersEXT(renderBufferId);
        GL11.glDeleteTextures(textureIDBuffer);
Вот только в Minecraft Forge отсутствуют события, к которым можно привязать данное действие (событие выгрузки клиента). Да и в самом Minecraft'е я не нашел упоминания этих функций.
 
Большого смысла удалять текстуры на выходе нет, это только увеличит время закрытия игры. При уничтожении контекста openGL автоматически вычищаются все объекты, что были им созданы. А удалять текстуры при выходе - это, ну... как если бы приложениям при закрытии надо было самим за собой оперативку освобождать. Очистка видеопамяти при закрытии приложения - работа драйвера, как очистка оперативки - работа ОС.

Если мне нужно было бы действительно наложить текстуру одежды на скин, то я скорее всего не заморачивался бы с использованием своего фреймбуффера (это openGL 3+!), а сделал бы это силами процессора, все равно тут никаких сложных вычислений нет. Если текстура большая и/или её уже нет в оперативке, то можно отрендерить в стандартный фреймбуффер между кадрами, такое будет работать даже на openGL 1.1.
 
GloomyFolken написал(а):
Если мне нужно было бы действительно наложить текстуру одежды на скин, то я скорее всего не заморачивался бы с использованием своего фреймбуффера (это openGL 3+!), а сделал бы это силами процессора, все равно тут никаких сложных вычислений нет. Если текстура большая и/или её уже нет в оперативке, то можно отрендерить в стандартный фреймбуффер между кадрами, такое будет работать даже на openGL 1.1.
Интересно. Покажешь как?
 
Решение в лоб: можно перехватить подгрузку нужного ресурса и заменить код загрузки текстуры в видеопамять. Это, небось, трансформеры. Не имел пока особого опыта с правкой ванильного кода.
 
Что именно? Как соединить текстуры в стандартном фреймбуффере? Да намного проще, чем в своём. Пишу из головы, так что работоспособность не обещаю. Использовать нужно во время тика логики, чтобы не нарисовать лишнего в реальный кадр. Кроме того, оно не будет работать, если размер текстуры больше размеров окна (почему-то не подумал об этом, когда писал предыдущее сообщение).
Код:
//Нужно сначала задать modelview и projection матрицы для отрисовки поверх экрана. Метод для этого уже есть - EntityRenderer#setupOverlayRendering, но у него одна проблема: в glOrtho передается разрешение в зависимости от настройки "gui scale", а стоит туда передавать реальный размер окна (mc.displayWidth, mc.displayHeight).
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0.0D, mc.displayWidth, mc.displayHeight, 0.0D, 1000.0D, 3000.0D);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(0.0F, 0.0F, -2000.0F);

//Дальше нужно просто отрендерить обе текстуры. Для этого опять-таки есть метод, и опять-таки он не вполне идеально подходит. Делаем то же самое, что в Gui#drawTexturedModalRect, но f и f1 заменяем на 1F/textureWidth и 1F/textureHeight. Метод drawTextureRect в конце.
glDisable(GL_DEPTH_TEST);
mc.renderEngine.bindTexture(skinTexture);
drawTexturedRect(0, 0, 0, 0, 1, 1, textureWidth, textureHeight);
mc.renderEngine.bindTexture(armorTexture);
drawTexturedRect(0, 0, 0, 0, 1, 1, textureWidth, textureHeight);

// Осталось только сохранить это из фреймбуффера в текстуру
mc.renderEngine.bindTexture(blankTexture); // стоит сделать сначала DynamicTexture размером 1х1 пиксель, а то проблем не оберешься, если биндить текстуру по ResourceLocation.
glBindTexture(GL_TEXTURE_2D, BLANK.getGlTextureId());
glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 0, 0, textureWidth, textureHeight, 0);


//создание своей DynamicTexture
public DynamicTexture createDynamicTexture() {
    DynamicTexture blank = new DynamicTexture(1, 1);
    blank.updateDynamicTexture();
    return blank;
}

// просто скопипастил свой старый код, лень было писать то же самое без лишних параметров
public void drawTexturedRect(int x, int y, float minU, float minV, float maxU, float maxV, int width, int height){
    int i = width;
    int j = height;
    Tessellator t = Tessellator.instance;
    t.startDrawingQuads();
    t.addVertexWithUV((x + 0) * scale, (y + j) * scale, 0, minU, maxV);
    t.addVertexWithUV((x + i) * scale, (y + j) * scale, 0, maxU, maxV);
    t.addVertexWithUV((x + i) * scale, (y + 0) * scale, 0, maxU, minV);
    t.addVertexWithUV((x + 0) * scale, (y + 0) * scale, 0, minU, minV);
    t.draw();
}
 
Oldestkon написал(а):
можно перехватить подгрузку нужного ресурса и заменить код загрузки текстуры в видеопамять
А хотя я хрень написал, лол. Тогда же все скины заменятся на скины с одеждой ._.
 
Oldestkon написал(а):
Решение в лоб: можно перехватить подгрузку нужного ресурса и заменить код загрузки текстуры в видеопамять. Это, небось, трансформеры. Не имел пока особого опыта с правкой ванильного кода.
Да не надо ничего перехватывать, можно просто использовать DynamicTexture. Читаешь текстуры с диска в два BufferedImage (как в SimpleTexture, это в три строки делается), из этих данных собираешь одну текстуру, которую кладешь прямо в массив пикселей DynamicTexture (dynamicTexture.getTextureData()), вызываешь updateDynamicTexture(), вуаля. Самое простое решение, на всё про всё уйдет строк пятнадцать.
 
На каком? Как соединить текстуры на процессоре? ИМХО я достаточно подробно написал, подробнее только код будет .-.
 
Да я уже написал в предыдущем посте, что хрень сказал. Лел.
---
Foghrye4 написал(а):
из этих данных собираешь одну текстуру
Вот на этом месте по-подробнее, пожалуйста.
Он же приводил код. Сбрасываешь все трансформации, врубаешь орторежим с системой координат, где длина и ширина равны реальным размерам окна, рисуешь две текстуры, дальше это дело функцией
Код:
glCopyTexImage2D //копирует данные из текущего фреймбуфера (его колор-текстуры) в твою забинденную текстуру
Кидаешь в нужную тебе текстуру. Как её создавать он тоже показал.
 
Oldestkon написал(а):
Он же приводил код. Сбрасываешь все трансформации, врубаешь орторежим с системой координат, где длина и ширина равны реальным размерам окна, рисуешь две текстуры, дальше
Что за "тик логики"?
 
Foghrye4 написал(а):
Что за "тик логики"?
Рисовать надо до отрисовки чего либо кубачом, но после инициализации лвжгл-дисплея.
>Чтобы не испортить кадр.
А вообще это делается единожды (ведь так?), так что, имхо, пофиг где рисовать.
 
Как смешать две текстуры в одну на процессоре?
Код:
DynamicTexture dynamicTexture = new DynamicTexture(textureWidth, textureHeight);
int[] pixels = dynamicTexture.getTextureData();
// ну уж их-то достать не проблема
BufferedImage skinTexture = ...;
BufferedImage armorTexture = ...;
for (int x = 0; x < textureWidth; x++) {
    for (int y = 0; y < textureHeight; y++) {
        int skinColor = skinTexture.getRGB(x, y);
        int armorColor = armorTexture.getRGB(x, y);
        int armorAlpha = (armorColor>>24)&0xFF; // вытаскиваем альфу из RGBA
        pixels[y*textureWidth + x] = armorAlpha > 0 ? armorColor : skinColor; // если пиксель на текстуре брнони непрозрачный, то используем его, иначе пиксель с текстуры скина
    }
}
 
Назад
Сверху