Neler yeni
XenForo Bannerlar
Modern AdBlock Uyarısı

Foruma hoş geldin, Ziyaretçi

Forum içeriğine ve tüm hizmetlerimize erişim sağlamak için foruma kayıt olmalı ya da giriş yapmalısınız. Foruma üye olmak tamamen ücretsizdir.

Kod Client'te Daha İyi Doku (Tekstür) Kalitesi

Fatih Bulut

Süper Üye
Katılım
6 Kas 2021
Mesajlar
4,304
Tepkime puanı
5,675
Puanları
113
Yaş
32
Konum
Türkiye
Dc
fatihbulut
Bu rehber Metin2 client'inde dokuların (tekstürlerin) yüklenme şeklini CPU / GPU veya RAM tüketiminde gözle görülür bir fark olmadan maksimum kalitede olacak biçimde nasıl değiştireceğinizi gösterir.

Pratikte texture bias low memory ve format downgrade ile ilgili eski kısıtlamalar kaldırılır böylece dokular mümkün olan en iyi kalitede yüklenir.

1782228555058.png


GrpImageTexture.cpp dosyasında bu kodu ara:

Kod:
    bool CGraphicImageTexture::Lock(int* pRetPitch, void** ppRetPixels, int level)

Bu Kod ile değiştir:

Kod:
    #include "StdAfx.h"
    #include "../eterBase/MappedFile.h"
    #include "../eterPack/EterPackManager.h"
    #include "GrpImageTexture.h"

    bool CGraphicImageTexture::Lock(int* pRetPitch, void** ppRetPixels, int level)
    {
        D3DLOCKED_RECT lockedRect;
        if (FAILED(m_lpd3dTexture->LockRect(level, &lockedRect, nullptr, 0)))
            return false;

        *pRetPitch = lockedRect.Pitch;
        *ppRetPixels = static_cast<void*>(lockedRect.pBits);
        return true;
    }

    void CGraphicImageTexture::Unlock(int level)
    {
        if (m_lpd3dTexture) [[likely]]
            m_lpd3dTexture->UnlockRect(level);
    }

    void CGraphicImageTexture::Initialize()
    {
        CGraphicTexture::Initialize();
        m_stFileName = "";
        m_d3dFmt = D3DFMT_UNKNOWN;
        m_dwFilter = 0;
    }

    void CGraphicImageTexture::Destroy()
    {
        CGraphicTexture::Destroy();
        Initialize();
    }

    bool CGraphicImageTexture::CreateDeviceObjects()
    {
        assert(ms_lpd3dDevice != nullptr);
        assert(m_lpd3dTexture == nullptr);

        if (m_stFileName.empty())
        {
            if (FAILED(ms_lpd3dDevice->CreateTexture(m_width, m_height, 1, 0, m_d3dFmt, D3DPOOL_MANAGED, &m_lpd3dTexture)))
                return false;
        }
        else
        {
            CMappedFile mappedFile;
            LPCVOID c_pvMap;

            if (!CEterPackManager::Instance().Get(mappedFile, m_stFileName.c_str(), &c_pvMap))
                return false;

            if (!CreateFromMemoryFile(mappedFile.Size(), c_pvMap, m_d3dFmt, m_dwFilter))
            {
                TraceError("CGraphicImageTexture::CreateDeviceObjects: texture not found(%s)", m_stFileName.c_str());
                return false;
            }
            return true;
        }

        m_bEmpty = false;
        return true;
    }

    bool CGraphicImageTexture::Create(UINT width, UINT height, D3DFORMAT d3dFmt, DWORD dwFilter)
    {
        assert(ms_lpd3dDevice != nullptr);
        Destroy();

        m_width = width;
        m_height = height;
        m_d3dFmt = d3dFmt;
        m_dwFilter = dwFilter;

        return CreateDeviceObjects();
    }

    void CGraphicImageTexture::CreateFromTexturePointer(const CGraphicTexture* c_pSrcTexture)
    {
        if (m_lpd3dTexture)
            m_lpd3dTexture->Release();

        m_width = c_pSrcTexture->GetWidth();
        m_height = c_pSrcTexture->GetHeight();
        m_lpd3dTexture = c_pSrcTexture->GetD3DTexture();

        if (m_lpd3dTexture)
            m_lpd3dTexture->AddRef();

        m_bEmpty = false;
    }

    bool CGraphicImageTexture::CreateDDSTexture(CDXTCImage& image, const BYTE* /*c_pbBuf*/)
    {
        int mipmapCount = image.m_dwMipMapCount == 0 ? 1 : image.m_dwMipMapCount;

        D3DFORMAT format;
        if (image.m_CompFormat == PF_DXT5)
            format = D3DFMT_DXT5;
        else if (image.m_CompFormat == PF_DXT3)
            format = D3DFMT_DXT3;
        else
            format = D3DFMT_DXT1;

        LPDIRECT3DTEXTURE8 lpd3dTexture;
        if (FAILED(D3DXCreateTexture(ms_lpd3dDevice, image.m_nWidth, image.m_nHeight, mipmapCount, 0, format, D3DPOOL_MANAGED, &lpd3dTexture)))
        {
            TraceError("CreateDDSTexture: Cannot create texture");
            return false;
        }

        for (DWORD i = 0; i < static_cast<DWORD>(mipmapCount); ++i)
        {
            D3DLOCKED_RECT lockedRect;
            if (SUCCEEDED(lpd3dTexture->LockRect(i, &lockedRect, nullptr, 0)))
            {
                image.Copy(i, reinterpret_cast<BYTE*>(lockedRect.pBits), lockedRect.Pitch);
                lpd3dTexture->UnlockRect(i);
            }
        }

        m_lpd3dTexture = lpd3dTexture;
        m_width = image.m_nWidth;
        m_height = image.m_nHeight;
        m_bEmpty = false;

        return true;
    }

    bool CGraphicImageTexture::CreateFromMemoryFile(UINT bufSize, const void* c_pvBuf, D3DFORMAT d3dFmt, DWORD dwFilter)
    {
        assert(ms_lpd3dDevice != nullptr);
        assert(m_lpd3dTexture == nullptr);

        static CDXTCImage image;

        if (image.LoadHeaderFromMemory(static_cast<const BYTE*>(c_pvBuf)))
        {
            return CreateDDSTexture(image, static_cast<const BYTE*>(c_pvBuf));
        }
        else
        {
            D3DXIMAGE_INFO imageInfo;
            if (FAILED(D3DXCreateTextureFromFileInMemoryEx(
                ms_lpd3dDevice,
                c_pvBuf,
                bufSize,
                D3DX_DEFAULT,
                D3DX_DEFAULT,
                D3DX_DEFAULT,
                0,
                d3dFmt,
                D3DPOOL_MANAGED,
                D3DX_FILTER_TRIANGLE | D3DX_FILTER_DITHER,
                D3DX_FILTER_TRIANGLE | D3DX_FILTER_DITHER,
                0,
                &imageInfo,
                nullptr,
                &m_lpd3dTexture)))
            {
                TraceError("CreateFromMemoryFile: Cannot create texture from memory");
                return false;
            }

            m_width = imageInfo.Width;
            m_height = imageInfo.Height;
        }

        m_bEmpty = false;
        return true;
    }

    void CGraphicImageTexture::SetFileName(const char* c_szFileName)
    {
        m_stFileName = c_szFileName;
    }

    bool CGraphicImageTexture::CreateFromDiskFile(const char* c_szFileName, D3DFORMAT d3dFmt, DWORD dwFilter)
    {
        Destroy();
        SetFileName(c_szFileName);
        m_d3dFmt = d3dFmt;
        m_dwFilter = dwFilter;
        return CreateDeviceObjects();
    }

    CGraphicImageTexture::CGraphicImageTexture()
    {
        Initialize();
    }

    CGraphicImageTexture::~CGraphicImageTexture()
    {
        Destroy();
    }
Kısa açıklama:
low texture memory (düşük doku belleği) ile ilgili kısıtlamalar kaldırılır
doku, orijinal boyutunda korunur
mevcut tüm mipmap'ler yüklenir
yükleme sırasında daha iyi bir filtreleme kullanılır
kaliteyi düşüren eski format dönüşümleri kaldırılır

Tam olarak neyi değiştiriyor:
D3DX_DEFAULT → görüntünün orijinal boyutunu korur
D3DX_FILTER_TRIANGLE | D3DX_FILTER_DITHER → daha iyi bir yeniden örnekleme (resample) kullanır
artık A8R8G8B8 -> A4R4G4B4 gibi otomatik kalite düşürme (downgrade) yapılmaz
DDS dosyaları doğrudan kendi gerçek formatlarıyla oluşturulur

Yukarıdaki Kod DirectX 8 optimizasyonu için aşağıya DirectX 9 optimizasyonunu da bırakıyorum.

Kod:
#include "StdAfx.h"
#include "../eterBase/MappedFile.h"
#include "../eterPack/EterPackManager.h"
#include "GrpImageTexture.h"

bool CGraphicImageTexture::Lock(int* pRetPitch, void** ppRetPixels, int level)
{
    D3DLOCKED_RECT lockedRect;
    if (FAILED(m_lpd3dTexture->LockRect(level, &lockedRect, NULL, 0)))
        return false;

    *pRetPitch = lockedRect.Pitch;
    *ppRetPixels = (void*)lockedRect.pBits;
    return true;
}

void CGraphicImageTexture::Unlock(int level)
{
    if (m_lpd3dTexture)
        m_lpd3dTexture->UnlockRect(level);
}

void CGraphicImageTexture::Initialize()
{
    CGraphicTexture::Initialize();

    m_stFileName = "";

    m_d3dFmt = D3DFMT_UNKNOWN;
    m_dwFilter = 0;
}

void CGraphicImageTexture::Destroy()
{
    CGraphicTexture::Destroy();

    Initialize();
}

bool CGraphicImageTexture::CreateDeviceObjects()
{
    assert(ms_lpd3dDevice != NULL);
    assert(m_lpd3dTexture == NULL);

    if (m_stFileName.empty())
    {
        if (FAILED(ms_lpd3dDevice->CreateTexture(m_width, m_height, 1, 0, m_d3dFmt, D3DPOOL_MANAGED, &m_lpd3dTexture, NULL)))
            return false;
    }
    else
    {
        CMappedFile    mappedFile;
        LPCVOID        c_pvMap;

        if (!CEterPackManager::Instance().Get(mappedFile, m_stFileName.c_str(), &c_pvMap))
            return false;

        if (!CreateFromMemoryFile(mappedFile.Size(), c_pvMap, m_d3dFmt, m_dwFilter))
        {
            TraceError("CGraphicImageTexture::CreateDeviceObjects: CreateFromMemoryFile: texture not found(%s)", m_stFileName.c_str());
            return false;
        }
        return true;
    }

    m_bEmpty = false;
    return true;
}

bool CGraphicImageTexture::Create(UINT width, UINT height, D3DFORMAT d3dFmt, DWORD dwFilter)
{
    assert(ms_lpd3dDevice != NULL);
    Destroy();

    m_width = width;
    m_height = height;
    m_d3dFmt = d3dFmt;
    m_dwFilter = dwFilter;

    return CreateDeviceObjects();
}

void CGraphicImageTexture::CreateFromTexturePointer(const CGraphicTexture * c_pSrcTexture)
{
    if (m_lpd3dTexture)
        m_lpd3dTexture->Release();

    m_width = c_pSrcTexture->GetWidth();
    m_height = c_pSrcTexture->GetHeight();
    m_lpd3dTexture = c_pSrcTexture->GetD3DTexture();

    if (m_lpd3dTexture)
        m_lpd3dTexture->AddRef();

    m_bEmpty = false;
}

bool CGraphicImageTexture::CreateDDSTexture(CDXTCImage & image, const BYTE * /*c_pbBuf*/)
{
    int mipmapCount = image.m_dwMipMapCount == 0 ? 1 : image.m_dwMipMapCount;

    D3DFORMAT format;
    LPDIRECT3DTEXTURE9 lpd3dTexture;

    if(image.m_CompFormat == PF_DXT5)
        format = D3DFMT_DXT5;
    else if(image.m_CompFormat == PF_DXT3)
        format = D3DFMT_DXT3;
    else
        format = D3DFMT_DXT1;

    // S-a eliminat coborarea calitatii texturilor (uTexBias) pentru performanta maxima vizuala

    if (FAILED(D3DXCreateTexture(    ms_lpd3dDevice, image.m_nWidth, image.m_nHeight,
                                    mipmapCount, 0, format, D3DPOOL_MANAGED, &lpd3dTexture)))
    {
        TraceError("CreateDDSTexture: Cannot create texture");
        return false;
    }

    for (DWORD i = 0; i < (DWORD)mipmapCount; ++i)
    {
        D3DLOCKED_RECT lockedRect;

        if (FAILED(lpd3dTexture->LockRect(i, &lockedRect, NULL, 0)))
        {
            TraceError("CreateDDSTexture: Cannot lock texture");
        }
        else
        {
            image.Copy(i, (BYTE*)lockedRect.pBits, lockedRect.Pitch);
            lpd3dTexture->UnlockRect(i);
        }
    }

    m_lpd3dTexture = lpd3dTexture;
    m_width = image.m_nWidth;
    m_height = image.m_nHeight;
    m_bEmpty = false;

    return true;
}

bool CGraphicImageTexture::CreateFromMemoryFile(UINT bufSize, const void * c_pvBuf, D3DFORMAT d3dFmt, DWORD dwFilter)
{
    assert(ms_lpd3dDevice != NULL);
    assert(m_lpd3dTexture == NULL);

    static CDXTCImage image;

    if (image.LoadHeaderFromMemory((const BYTE *) c_pvBuf))
    {
        return (CreateDDSTexture(image, (const BYTE *) c_pvBuf));
    }
    else
    {
        D3DXIMAGE_INFO imageInfo;
        if (FAILED(D3DXCreateTextureFromFileInMemoryEx(
                    ms_lpd3dDevice,
                    c_pvBuf,
                    bufSize,
                    D3DX_DEFAULT,
                    D3DX_DEFAULT,
                    D3DX_DEFAULT,
                    0,
                    d3dFmt,
                    D3DPOOL_MANAGED,
                    D3DX_FILTER_TRIANGLE | D3DX_FILTER_DITHER, // Optimizare Calitate: Filtrare avansata
                    D3DX_FILTER_TRIANGLE | D3DX_FILTER_DITHER,
                    0xffff00ff,
                    &imageInfo,
                    NULL,
                    &m_lpd3dTexture)))
        {
            TraceError("CreateFromMemoryFile: Cannot create texture");
            return false;
        }

        m_width = imageInfo.Width;
        m_height = imageInfo.Height;
        
        // S-a eliminat coborarea calitatii texturilor la 16 bit si reducerea dimensiunii
    }

    m_bEmpty = false;
    return true;
}

bool CGraphicImageTexture::CreateTextureFromByteVector(const std::vector<BYTE>& byteVector, D3DFORMAT format, DWORD filter)
{
    assert(ms_lpd3dDevice != NULL);
    assert(m_lpd3dTexture == NULL);

    D3DXIMAGE_INFO imageInfo;
    HRESULT hr = D3DXCreateTextureFromFileInMemoryEx(
        ms_lpd3dDevice,                         // Direct3D device
        byteVector.data(),               // Pointer to image data
        static_cast<UINT>(byteVector.size()), // Size of the image data
        D3DX_DEFAULT,                    // Texture width (default: image width)
        D3DX_DEFAULT,                    // Texture height (default: image height)
        D3DX_DEFAULT,                    // Mip levels (default: full chain)
        0,                               // Usage flags
        format,                          // Desired texture format
        D3DPOOL_MANAGED,                 // Memory pool (managed for efficiency)
        D3DX_FILTER_TRIANGLE | D3DX_FILTER_DITHER, // Fortare calitate
        D3DX_FILTER_TRIANGLE | D3DX_FILTER_DITHER,
        0,                               // Color key (transparent color)
        &imageInfo,                      // Image info output
        NULL,                            // Palette (optional)
        &m_lpd3dTexture                      // Output texture
    );

    if (FAILED(hr)) {
        return false;
    }

    m_width = imageInfo.Width;
    m_height = imageInfo.Height;

    m_bEmpty = false;
    return true;
}

void CGraphicImageTexture::SetFileName(const char * c_szFileName)
{
    m_stFileName=c_szFileName;
}

bool CGraphicImageTexture::CreateFromDiskFile(const char * c_szFileName, D3DFORMAT d3dFmt, DWORD dwFilter)
{
    Destroy();

    SetFileName(c_szFileName);

    m_d3dFmt = d3dFmt;
    m_dwFilter = dwFilter;
    return CreateDeviceObjects();
}

CGraphicImageTexture::CGraphicImageTexture()
{
    Initialize();
}

CGraphicImageTexture::~CGraphicImageTexture()
{
    Destroy();
}
 

Forumdan daha fazla yararlanmak için giriş yapın yada üye olun!

Forumdan daha fazla yararlanmak için giriş yapın veya kayıt olun!

Kayıt ol

Forumda bir hesap oluşturmak tamamen ücretsizdir.

Şimdi kayıt ol
Giriş yap

Eğer bir hesabınız var ise lütfen giriş yapın

Giriş yap

Tema düzenleyici

Tema özelletirmeleri

Grafik arka planlar

Granit arka planlar