DirectX9 проблема в развертке текстуры на моделе

Исследование проблемы наложения UV-развертки без учета текстурных координат Введение:

В ходе работы над проектом, связанным с трехмерной графикой, была обнаружена проблема, связанная с наложением UV-развертки на модель без учета текстурных координат. Данная проблема проявляется при рендеринге, что затрудняет корректное отображение текстур на модели.

Методы исследования:

Была проведена проверка корректности загрузки и отображения UV-развертки в программе Blender 3D.

В проверке было установлено, что UV-развертка загружается стабильно и корректно отображается в редакторе UV.

Отладка:

В результате отладки было установлено, что текстурные координаты передаются в шейдеры, однако проблема с наложением текстуры на модель сохраняется.

Описание проблемы:

При рендеринге модели наблюдается следующая проблема: UV-развертка накладывается на модель без учета текстурных координат.

Вот код инициализации DirectX9 и рендер состояний:

bool Render::Initialize(HWND hWnd, RectWnd rect) {
    d3d = Direct3DCreate9(D3D_SDK_VERSION);
    if (!d3d)
        return false;

    D3DMULTISAMPLE_TYPE multisampleType = D3DMULTISAMPLE_2_SAMPLES;
    DWORD qualityLevels;
    if (!(SUCCEEDED(d3d->CheckDeviceMultiSampleType(D3DADAPTER_DEFAULT, 
            D3DDEVTYPE_HAL, D3DFMT_A8R8G8B8, TRUE, multisampleType, &qualityLevels))))
        multisampleType = D3DMULTISAMPLE_NONE;

    D3DPRESENT_PARAMETERS d3dpp;
    ZeroMemory(&d3dpp, sizeof(d3dpp));
    d3dpp.hDeviceWindow = hWnd;
    d3dpp.Windowed = TRUE;
    d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
    d3dpp.BackBufferFormat = D3DFMT_X8R8G8B8;
    d3dpp.BackBufferCount = 3;
    d3dpp.BackBufferWidth = rect.Width;
    d3dpp.BackBufferHeight = rect.Height;
    d3dpp.EnableAutoDepthStencil = TRUE;
    d3dpp.AutoDepthStencilFormat = D3DFMT_D24S8;
    d3dpp.MultiSampleType = multisampleType;
    d3dpp.MultiSampleQuality = qualityLevels - 1;
    d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT;

    HRESULT hr = d3d->CreateDevice(
        D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, 
        hWnd, D3DCREATE_HARDWARE_VERTEXPROCESSING,
        &d3dpp, &d3ddev);

    if (FAILED(hr)) {
        IDirect3D9_Release(d3d);
        d3d = NULL;
        return false;
    }

    d3ddev->SetRenderState(D3DRS_LIGHTING, FALSE);
    d3ddev->SetRenderState(D3DRS_AMBIENT, D3DCOLOR_XRGB(50, 50, 50));
    d3ddev->SetRenderState(D3DRS_CULLMODE, D3DCULL_CCW);
    d3ddev->SetRenderState(D3DRS_ZENABLE, TRUE);
    d3ddev->SetRenderState(D3DRS_EMISSIVEMATERIALSOURCE, D3DMCS_MATERIAL);

    d3ddev->SetRenderState(D3DRS_NORMALIZENORMALS, TRUE);
    d3ddev->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
    d3ddev->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
    d3ddev->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE);
    d3ddev->SetTextureStageState(0, D3DTSS_TEXCOORDINDEX, 0);

    D3DXVECTOR3 vEyePt(0.0f, 25.0f, -100.0f);
    D3DXVECTOR3 vLookatPt(0.0f, 0.0f, 80.0f);
    D3DXVECTOR3 vUpVec(0.0f, 1.0f, 0.0f);
    D3DXMatrixLookAtLH(&matView_, &vEyePt, &vLookatPt, &vUpVec);

    meshes_.reserve(10);
    rect_ = rect;

    return true;
}

Тут сам рендер меша:

void Render::Update(void) {
    if (d3ddev) {
        d3ddev->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER | D3DCLEAR_STENCIL, D3DCOLOR_XRGB(0, 0, 0), 1.0f, 0);
        if (SUCCEEDED(d3ddev->BeginScene())) {
            static float angle = 0.0f;
            angle += 0.01f;
            D3DXMatrixRotationY(&matWorld_, angle);

            D3DXMatrixPerspectiveFovLH(&matProj_, D3DX_PI / 4, static_cast<FLOAT>(rect_.Height / rect_.Width), 1.0f, 200.0f);

            d3ddev->SetTransform(D3DTS_WORLD, &matWorld_);
            d3ddev->SetTransform(D3DTS_VIEW, &matView_);
            d3ddev->SetTransform(D3DTS_PROJECTION, &matProj_);

            float lightIntensity = 0.0f;
            D3DXVECTOR4 lightPosition(50.0f, 3.0f, -100.0f, 1.0f);
            D3DXVECTOR4 lightColor(1.0f, 1.0f, 1.0f, 1.0f);

            D3DXMATRIX worldViewProjection = matWorld_ * matView_ * matProj_;
            shader_->vertexShaderConstantTable_->SetMatrix(d3ddev, "WorldViewProjection", &worldViewProjection);
            shader_->vertexShaderConstantTable_->SetVector(d3ddev, "LightPosition", &lightPosition);
            shader_->vertexShaderConstantTable_->SetVector(d3ddev, "LightColor", &lightColor);
            shader_->vertexShaderConstantTable_->SetFloat(d3ddev, "LightIntensity", lightIntensity);
            shader_->vertexShaderConstantTable_->SetMatrix(d3ddev, "World", &matWorld_);

            d3ddev->SetVertexShader(shader_->GetVertexShader());
            d3ddev->SetPixelShader(shader_->GetPixelShader());

            for (const Mesh* mesh : meshes_) {
                if (mesh && mesh->vertexBuffer_ && mesh->indexBuffer_) {
                    if (!mesh->textures_.empty()) {
                        D3DMATERIAL9 material = mesh->materials_[0].material;
                        D3DXVECTOR4 materialColor(material.Diffuse.r, material.Diffuse.g, material.Diffuse.b, material.Diffuse.a);
                        float materialDiffuse = material.Diffuse.a;
                        float materialSpecular = material.Specular.a;
                        float materialShininess = material.Power;

                        shader_->vertexShaderConstantTable_->SetVector(d3ddev, "MaterialColor", &materialColor);
                        shader_->vertexShaderConstantTable_->SetFloat(d3ddev, "MaterialDiffuse", materialDiffuse);
                        shader_->vertexShaderConstantTable_->SetFloat(d3ddev, "MaterialSpecular", materialSpecular);
                        shader_->vertexShaderConstantTable_->SetFloat(d3ddev, "MaterialShininess", materialShininess);

                        d3ddev->SetTexture(0, mesh->textures_[0]);
                    }
                    d3ddev->SetStreamSource(0, mesh->vertexBuffer_, 0, sizeof(Vertex));
                    d3ddev->SetIndices(mesh->indexBuffer_);

                    d3ddev->SetFVF(D3DFVF_XYZ | D3DFVF_NORMAL | D3DFVF_TEX1);
                    d3ddev->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 0, mesh->vertexCount_, 0, mesh->indexCount_ / 3);
                }
            }

            d3ddev->EndScene();
        }

        d3ddev->Present(NULL, NULL, NULL, NULL);
    }
}

А тут шейдеры:

struct VS_INPUT
{
    float4 Position : POSITION;
    float3 Normal : NORMAL;
    float2 TexCoord : TEXCOORD0;
};

struct VS_OUTPUT
{
    float4 Position : POSITION;
    float3 Normal : TEXCOORD1;
    float2 TexCoord : TEXCOORD0;
    float4 Color : COLOR0;
};

float4x4 WorldViewProjection;
float4x4 World;
float4 LightPosition;
float4 LightColor;
float LightIntensity;
float4 MaterialColor;
float MaterialDiffuse;
float MaterialSpecular;
float MaterialShininess;

VS_OUTPUT VS(VS_INPUT input)
{
    VS_OUTPUT output;
    output.Position = mul(input.Position, WorldViewProjection);
    output.TexCoord = input.TexCoord;
    output.Normal = normalize(mul(input.Normal, (float3x3) World));
    
    float3 worldPosition = mul(input.Position, World).xyz;
    float3 lightDir = normalize(LightPosition.xyz - worldPosition);
    float diffuse = max(dot(output.Normal, lightDir), 0.0);
    output.Color = LightColor * diffuse * LightIntensity * MaterialDiffuse;
    
    float3 viewDir = normalize(-worldPosition);
    float3 reflectDir = reflect(-lightDir, output.Normal);
    float specular = pow(max(dot(viewDir, reflectDir), 0.0), MaterialShininess);
    output.Color += LightColor * specular * MaterialSpecular;

    output.Color += MaterialColor * (1.0 - MaterialDiffuse);

    return output;
}

И пиксельный шейдер:

sampler2D TextureSampler;

struct PS_INPUT
{
    float2 TexCoord : TEXCOORD0;
    float4 Color : COLOR0;
};

float4 PS(PS_INPUT input) : COLOR
{
    float4 textureColor = tex2D(TextureSampler, input.TexCoord);
    return textureColor * input.Color;
}

Результат такой...

введите сюда описание изображения


Ответы (0 шт):