Reputation: 11
Study of the UV mapping problem without taking into account texture coordinates Introduction:
While working on a 3D graphics project, a problem was discovered related to the mapping of UV mapping to a model without taking into account texture coordinates. This problem manifests itself during rendering, which makes it difficult to correctly display textures on the model.
Research methods:
The correct loading and display of UV mapping in Blender 3D was checked.
The check showed that UV mapping loads stably and is correctly displayed in the UV editor.
Problem description:
The following problem is observed when rendering the model: UV mapping is mapped to the model without taking into account texture coordinates.
Here is the DirectX9 initialization code and the state renderer:
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;
}
Here is the render of the mesh itself:
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);
}
}
And here are the shaders:
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;
}
And the pixel shader:
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;
}
Debugging:
As a result of debugging, it was found that texture coordinates are passed to shaders, but the problem with mapping textures to the model remains.
Upvotes: 0
Views: 42