FreeType generates multiple textures - c++

I'm trying to use FreeType under DirectX 11, in order to draw some text on my screen. For the moment i'm able to convert a FT_Bitmap* to a ID3D11Texture2D*, then I create a ID3D11ShaderResourceView*.
I then use a shader to draw this shader resource view. The problem is that this code only draws the last letter of the text 4 times, and I don't really see why.
First, here is how I render a UI Element :
Graph.cpp :
void Graph::DrawSprite(Object* p_object)
{
/*...*/
// Problem here
Text* text = nullptr;
text = p_object->GetComponent<Text>();
if (text)
_graphicAPI->Draw(text->GetBuffer());
/*...*/
}
GraphicAPI :
void GraphicAPI::Draw(const TextBuffer& p_text)
{
_shaders._orthoWindow->Render(_deviceContext);
_shaders._sprite->Render(_deviceContext, _shaders._orthoWindow->GetIndexCount(),
_managers._font->GetTextureView(p_text._font), p_text._matrix, _camera2D);
}
SpriteShader.cpp :
bool SpriteShader::Render(ID3D11DeviceContext* p_deviceContext, unsigned int p_indexCount, ID3D11ShaderResourceView* p_texView,
const Math::Mat4& p_matrix, const CameraBuffer& p_camera)
{
bool result = SetShaderParameters(p_deviceContext, p_texView, p_matrix, p_camera._view, p_camera._projection);
if (!result)
return false;
RenderShader(p_deviceContext, p_indexCount);
return true;
}
bool SpriteShader::SetShaderParameters(ID3D11DeviceContext* p_deviceContext, ID3D11ShaderResourceView* p_texView,
const Math::Mat4& p_worldMatrix, const Math::Mat4& p_viewMatrix, const Math::Mat4& p_projectionMatrix)
{
HRESULT result;
D3D11_MAPPED_SUBRESOURCE mappedResource;
unsigned int bufferNumber;
MatrixBufferType* dataMatrixPtr;
result = p_deviceContext->Map(_matrixBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
if (FAILED(result))
return false;
dataMatrixPtr = (MatrixBufferType*)mappedResource.pData;
dataMatrixPtr->world = p_worldMatrix;
dataMatrixPtr->view = p_viewMatrix;
dataMatrixPtr->projection = p_projectionMatrix;
p_deviceContext->Unmap(_matrixBuffer, 0);
bufferNumber = 0;
p_deviceContext->VSSetConstantBuffers(bufferNumber, 1, &_matrixBuffer);
p_deviceContext->PSSetShaderResources(0, 1, &p_texView);
return true;
}
void SpriteShader::RenderShader(ID3D11DeviceContext* p_deviceContext, unsigned int p_indexCount)
{
p_deviceContext->IASetInputLayout(_layout);
p_deviceContext->VSSetShader(_vertexShader, NULL, 0);
p_deviceContext->PSSetShader(_pixelShader, NULL, 0);
p_deviceContext->PSSetSamplers(0, 1, &_sampleState);
p_deviceContext->DrawIndexed(p_indexCount, 0, 0);
}
Here is how I load a TTF font and convert it to a ID3D11ShaderResourceView*.
FontManager.cpp :
bool FontManager::LoadFont(ID3D11Device* p_device, const std::string p_extension, const char* p_fileName)
{
if (p_extension == ".ttf")
{
Font* font = new Font();
if (!font)
return false;
if (!font->LoadTTF(p_device, _library, p_fileName))
{
delete font;
return false;
}
// sets text (tmp)
font->RenderFont(p_device, "ASDASD", Math::Vec2(100, 100));
_fonts.push_back(font);
return true;
}
return false;
}
For the Font class, I based myself on this tutorial. CreateShaderResourceView() is my_draw_bitmap().
Font.cpp :
bool Font::LoadTTF(ID3D11Device* p_device, FT_Library p_library, const char* p_fileName)
{
_fileName = p_fileName;
if (FT_New_Face(p_library, p_fileName, 0, &_face))
return false;
if (FT_Set_Pixel_Sizes(_face, 0, DEFAULT_FONT_SIZE))
return false;
return true;
}
void Font::RenderFont(ID3D11Device* p_device, const char* p_text, Math::Vec2 p_position)
{
FT_GlyphSlot slot = _face->glyph;
FT_Vector pen;
pen.x = p_position._x;
pen.y = p_position._y;
FT_Matrix matrix;
float angle = (/*90*/0.0 / 360) * 3.14159 * 2;
matrix.xx = (FT_Fixed)(cos(angle) * 0x10000L);
matrix.xy = (FT_Fixed)(-sin(angle) * 0x10000L);
matrix.yx = (FT_Fixed)(sin(angle) * 0x10000L);
matrix.yy = (FT_Fixed)(cos(angle) * 0x10000L);
for (unsigned int i = 0; i < strlen(p_text); ++i)
{
FT_Set_Transform(_face, &matrix, &pen);
if (FT_Load_Char(_face, p_text[i], FT_LOAD_RENDER))
continue;
if (!CreateShaderResourceView(p_device, &slot->bitmap))
return;
// Increment pen position
pen.x += slot->advance.x >> 6;
}
}
bool Font::CreateShaderResourceView(ID3D11Device* p_device, FT_Bitmap* p_bitmap)
{
D3D11_TEXTURE2D_DESC textureDesc;
ZeroMemory(&textureDesc, sizeof(textureDesc));
textureDesc.Width = p_bitmap->width;
textureDesc.Height = p_bitmap->rows;
textureDesc.MipLevels = 1;
textureDesc.ArraySize = 1;
textureDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
textureDesc.SampleDesc.Count = 1;
textureDesc.SampleDesc.Quality = 0;
textureDesc.Usage = D3D11_USAGE_DEFAULT;
textureDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
textureDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
textureDesc.MiscFlags = 0;
ID3D11Texture2D* texture2D;
ZeroMemory(&texture2D, sizeof(texture2D));
D3D11_SUBRESOURCE_DATA resourceData;
resourceData.pSysMem = p_bitmap->buffer;
resourceData.SysMemPitch = p_bitmap->pitch;
resourceData.SysMemSlicePitch = 0;
HRESULT res = p_device->CreateTexture2D(&textureDesc, &resourceData, &texture2D);
if (FAILED(res))
return false;
D3D11_SHADER_RESOURCE_VIEW_DESC shaderResourceViewDesc;
shaderResourceViewDesc.Format = textureDesc.Format;
shaderResourceViewDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
shaderResourceViewDesc.Texture2D.MostDetailedMip = 0;
shaderResourceViewDesc.Texture2D.MipLevels = 1;
HRESULT result = p_device->CreateShaderResourceView(texture2D, &shaderResourceViewDesc, &_shaderResourceView);
if (FAILED(result))
return false;
return true;
}
And the shaders :
Sprite.ps (I use this shader to draw UI elements):
Texture2D spriteTexture;
SamplerState SampleType;
struct PixelInputType
{
float4 position : SV_POSITION;
float2 tex : TEXCOORD0;
};
float4 SpritePixelShader(PixelInputType input) : SV_TARGET
{
float4 textureColor;
textureColor = spriteTexture.Sample(SampleType, input.tex);
return textureColor;
}
Sprite.vs :
cbuffer MatrixBuffer
{
matrix worldMatrix;
matrix viewMatrix;
matrix projectionMatrix;
};
struct VertexInputType
{
float4 position : POSITION;
float2 tex : TEXCOORD0;
};
struct PixelInputType
{
float4 position : SV_POSITION;
float2 tex : TEXCOORD0;
};
PixelInputType SpriteVertexShader(VertexInputType input)
{
PixelInputType output;
input.position.w = 1.0f;
output.position = mul(input.position, worldMatrix);
output.position = mul(output.position, viewMatrix);
output.position = mul(output.position, projectionMatrix);
output.tex = input.tex;
return output;
}
Here is what I get :
This guy (here) had the same issue, but the solution doesn't work for me. Does anyone know how to solve this ? I've been stuck on this for a week now...

It seems that inside of for (unsigned int i = 0; i < strlen(p_text); ++i) you try to render font letter-by-letter and recreate shader resource view on each iteration. So at the end you are left with shader resource view containing last letter texture view.

Related

How can I change the texture position in DirectX 12

I need to change the position of the texture in the window, I have it drawn in the upper left corner, and I want to place it in the center. In directx 11 we can do this
m_deviceResources->GetD2DDeviceContext()->SetTransform(...), but I haven't found any similar code for directx 12. I don't understand how i can change the texture position, maybe I need to change something in ConstantBuffer or change the code for the shader.
Texture Code
void CreateTexture(int width, int height, const void* pData)
{
D3D12_RESOURCE_DESC resourceDesc = {};
resourceDesc.MipLevels = 1;
resourceDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
resourceDesc.Width = width;
resourceDesc.Height = height;
resourceDesc.Flags = D3D12_RESOURCE_FLAG_NONE;
resourceDesc.DepthOrArraySize = 1;
resourceDesc.SampleDesc.Count = 1;
resourceDesc.SampleDesc.Quality = 0;
resourceDesc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D;
D3D12MA::ALLOCATION_DESC allocationDesc = {};
allocationDesc.HeapType = D3D12_HEAP_TYPE_DEFAULT;
D3D12MA::Allocation* alloc = nullptr;
allocator->CreateResource(
&allocationDesc,
&resourceDesc,
D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE,
nullptr,
&alloc,
IID_PPV_ARGS(&OffscreenTexture));
UpdateTextureResource(width, height, pData);
// Describe and create a SRV for the texture.
D3D12_SHADER_RESOURCE_VIEW_DESC srvDesc = {};
srvDesc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING;
srvDesc.Format = resourceDesc.Format;
srvDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D;
srvDesc.Texture2D.MipLevels = 1;
Device->CreateShaderResourceView(OffscreenTexture, &srvDesc, OffscreenSrvHeap->GetCPUDescriptorHandleForHeapStart());
alloc->Release();
}
void UpdateTextureResource(int width, int height, const void* pData)
{
if (pData == nullptr)
return;
if (upload_texture)
upload_texture->Release();
auto Barrier = CD3DX12_RESOURCE_BARRIER::Transition(OffscreenTexture, D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE, D3D12_RESOURCE_STATE_COPY_DEST);
CommandList->ResourceBarrier(1, &Barrier);
const UINT64 uploadBufferSize = GetRequiredIntermediateSize(OffscreenTexture, 0, 1);
D3D12_RESOURCE_DESC desc = CD3DX12_RESOURCE_DESC::Buffer(uploadBufferSize);
D3D12MA::ALLOCATION_DESC allocationDesc = {};
allocationDesc.HeapType = D3D12_HEAP_TYPE_UPLOAD;
allocator->CreateResource(
&allocationDesc,
&desc,
D3D12_RESOURCE_STATE_GENERIC_READ,
NULL,
&upload_texture,
__uuidof(ID3D12Resource),
nullptr);
if (upload_texture == nullptr)
return;
D3D12_SUBRESOURCE_DATA textureData = {};
textureData.pData = pData;
textureData.RowPitch = width * 4; // TextureWidth * TextureSize
textureData.SlicePitch = textureData.RowPitch * height;
UpdateSubresources(CommandList, OffscreenTexture, upload_texture->GetResource(), 0, 0, 1, &textureData);
auto barrier = CD3DX12_RESOURCE_BARRIER::Transition(OffscreenTexture, D3D12_RESOURCE_STATE_COPY_DEST, D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE);
CommandList->ResourceBarrier(1, &barrier);
}
Shader Code
struct PSInput
{
float4 position : SV_POSITION;
float2 uv : TEXCOORD;
};
Texture2D g_texture : register(t0);
SamplerState g_sampler : register(s0);
PSInput VSMain(float4 position : POSITION, float4 uv : TEXCOORD)
{
PSInput result;
result.position = position;
result.uv = uv;
return result;
}
float4 PSMain(PSInput input) : SV_TARGET
{
return g_texture.Sample(g_sampler, input.uv);
}

The image does not load (DirectX11)

How do I solve this? I think there is a problem with the part that binds to the pipeline. It was confirmed that the bitmap was loaded.I handed over the buffer containing pixel information to pSysmem, checked DXGI_FORMAT, and wrote the shader correctly (probably). I also checked the register number.
LoadBitmap
Gdiplus::Bitmap bitmap(path.c_str());
if (bitmap.GetLastStatus() != Gdiplus::Status::Ok)
{
MessageBox(nullptr, "Load Image Failed", "Failed", MB_OK);
}
_width = bitmap.GetWidth();
_height = bitmap.GetHeight();
_buffer = std::make_unique<Color[]>(_width * _height);
for (UINT y = 0; y < _height; ++y)
{
for (UINT x = 0; x < _width; ++x)
{
Gdiplus::Color c;
bitmap.GetPixel(x, y, &c);
_buffer[y * _width + x] = c.GetValue();
}
}
CreateTexture
D3D11_TEXTURE2D_DESC tex2DDesc = {};
tex2DDesc.Width = _width;
tex2DDesc.Height = _height;
tex2DDesc.MipLevels = 1;
tex2DDesc.ArraySize = 1;
tex2DDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
tex2DDesc.SampleDesc.Count = 1;
tex2DDesc.SampleDesc.Quality = 0;
tex2DDesc.Usage = D3D11_USAGE_DEFAULT;
tex2DDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
tex2DDesc.CPUAccessFlags = 0;
tex2DDesc.MiscFlags = 0;
D3D11_SUBRESOURCE_DATA sd = {};
sd.pSysMem = _buffer.get();
sd.SysMemPitch = _width * sizeof(Texture::Color);
DEVICE->CreateTexture2D(&tex2DDesc, &sd, _tex2D.GetAddressOf());
D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
srvDesc.Format = tex2DDesc.Format;
srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
srvDesc.Texture2D.MostDetailedMip = 0;
srvDesc.Texture2D.MipLevels = 1;
DEVICE->CreateShaderResourceView(_tex2D.Get(), &srvDesc, _srv.GetAddressOf());
CONTEXT->PSSetShaderResources(0u, 1u, _srv.GetAddressOf());
CreateSamplerState
D3D11_SAMPLER_DESC samplerDesc = {};
samplerDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR;
samplerDesc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP;
samplerDesc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP;
samplerDesc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP;
DEVICE->CreateSamplerState(&samplerDesc, _samplerState.GetAddressOf());
CONTEXT->PSSetSamplers(0u, 1u, _samplerState.GetAddressOf());
inputLayout
D3D11_INPUT_ELEMENT_DESC desc[] =
{
{ "Position",0,DXGI_FORMAT_R32G32B32_FLOAT,0,0,D3D11_INPUT_PER_VERTEX_DATA,0 },
{ "TexCoord", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0}
};
DEVICE->CreateInputLayout(desc, std::size(desc), _vsBlob->GetBufferPointer(), _vsBlob->GetBufferSize(), _inputLayout.GetAddressOf());
VertexShader
cbuffer CBuf
{
matrix transform;
};
struct VSOut
{
float4 pos : SV_Position;
float2 uv : TEXCOORD;
};
VSOut main(float3 pos : POSITION, float2 uv : TEXCOORD)
{
VSOut vso;
vso.pos = mul(float4(pos, 1.f), transform);
vso.uv = uv;
return vso;
}
PixelShader
Texture2D texture_0 : register(t0);
SamplerState sample_0 : register(s0);
float4 main(float2 uv : TEXCOORD) : SV_Target
{
float4 color = texture_0.Sample(sample_0, uv);
return color;
}

C++ DirectX11 Texture On Terrain Not Rendering Properly

I am developing a game engine using the Rastertek tutorials.
My problem is that the terrain texture isn't loading properly.
Pixel Shader:
Texture2D shaderTexture;
SamplerState SampleType;
cbuffer LightBuffer
{
float4 ambientColor;
float4 diffuseColor;
float3 lightDirection;
float padding;
};
//////////////
// TYPEDEFS //
//////////////
struct PixelInputType
{
float4 position : SV_POSITION;
float2 tex : TEXCOORD0;
float3 normal : NORMAL;
};
////////////////////////////////////////////////////////////////////////////////
// Pixel Shader
////////////////////////////////////////////////////////////////////////////////
float4 TerrainPixelShader(PixelInputType input) : SV_TARGET
{
float4 textureColor;
float3 lightDir;
float lightIntensity;
float4 color;
// Sample the pixel color from the texture using the sampler at this texture coordinate location.
textureColor = shaderTexture.Sample(SampleType, input.tex);
// Set the default output color to the ambient light value for all pixels.
color = ambientColor;
// Invert the light direction for calculations.
lightDir = -lightDirection;
// Calculate the amount of light on this pixel.
lightIntensity = saturate(dot(input.normal, lightDir));
if(lightIntensity > 0.0f)
{
// Determine the final diffuse color based on the diffuse color and the amount of light intensity.
color += (diffuseColor * lightIntensity);
}
// Saturate the final light color.
color = saturate(color);
// Multiply the texture pixel and the final light color to get the result.
color = color * textureColor;
Vertex Shader:
cbuffer MatrixBuffer
{
matrix worldMatrix;
matrix viewMatrix;
matrix projectionMatrix;
};
//////////////
// TYPEDEFS //
//////////////
struct VertexInputType
{
float4 position : POSITION;
float2 tex : TEXCOORD0;
float3 normal : NORMAL;
};
struct PixelInputType
{
float4 position : SV_POSITION;
float2 tex : TEXCOORD0;
float3 normal : NORMAL;
};
////////////////////////////////////////////////////////////////////////////////
// Vertex Shader
////////////////////////////////////////////////////////////////////////////////
PixelInputType TerrainVertexShader(VertexInputType input)
{
PixelInputType output;
// Change the position vector to be 4 units for proper matrix calculations.
input.position.w = 1.0f;
// Calculate the position of the vertex against the world, view, and projection matrices.
output.position = mul(input.position, worldMatrix);
output.position = mul(output.position, viewMatrix);
output.position = mul(output.position, projectionMatrix);
// Store the texture coordinates for the pixel shader.
output.tex = input.tex;
// Calculate the normal vector against the world matrix only.
output.normal = mul(input.normal, (float3x3)worldMatrix);
// Normalize the normal vector.
output.normal = normalize(output.normal);
return output;
}
Terrain Shader Class:
bool TerrainShaderClass::SetShaderParameters(ID3D11DeviceContext* deviceContext, D3DXMATRIX world, D3DXMATRIX view,
D3DXMATRIX projection, D3DXVECTOR4 ambientColor, D3DXVECTOR4 diffuseColor, D3DXVECTOR3 lightDirection,
ID3D11ShaderResourceView* texture)
{
HRESULT result;
D3D11_MAPPED_SUBRESOURCE mappedResource;
unsigned int bufferNumber;
MatrixBufferType* matrixData;
LightBufferType* lightData;
D3DXMatrixTranspose(&world, &world);
D3DXMatrixTranspose(&view, &view);
D3DXMatrixTranspose(&projection, &projection);
result = deviceContext->Map(m_matrixBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
if (FAILED(result))
{
return false;
}
matrixData = (MatrixBufferType*)mappedResource.pData;
matrixData->world = world;
matrixData->view = view;
matrixData->projection = projection;
deviceContext->Unmap(m_matrixBuffer, 0);
bufferNumber = 0;
deviceContext->VSSetConstantBuffers(bufferNumber, 1, &m_matrixBuffer);
deviceContext->Map(m_lightBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
lightData = (LightBufferType*)mappedResource.pData;
lightData->ambientColor = ambientColor;
lightData->diffuseColor = diffuseColor;
lightData->lightDirection = lightDirection;
lightData->padding = 0.0f;
deviceContext->Unmap(m_lightBuffer, 0);
bufferNumber = 0;
deviceContext->PSSetConstantBuffers(bufferNumber, 1, &m_lightBuffer);
deviceContext->PSSetShaderResources(0, 1, &texture);
return true;
}
void TerrainShaderClass::OutputShaderErrorMessage(ID3D10Blob* errorMessage, HWND hwnd, LPCSTR shaderFileName)
{
char* compileErrors = (char*)(errorMessage->GetBufferPointer());
unsigned long bufferSize = errorMessage->GetBufferSize();
ofstream fout;
fout.open("shader-error.txt");
for (unsigned long i = 0; i < bufferSize; i++)
{
fout << compileErrors[i];
}
fout.close();
errorMessage->Release();
errorMessage = nullptr;
MessageBox(hwnd, "Error compiling shader. Check shader-error.txt for message.", shaderFileName, MB_OK);
}
void TerrainShaderClass::RenderShader(ID3D11DeviceContext* deviceContext, int indexCount)
{
deviceContext->IASetInputLayout(m_layout);
deviceContext->VSSetShader(m_vertexShader, NULL, 0);
deviceContext->PSSetShader(m_pixelShader, NULL, 0);
deviceContext->PSSetSamplers(0, 1, &m_samplerState);
deviceContext->DrawIndexed(indexCount, 0, 0);
}
bool TerrainShaderClass::InitializeShader(ID3D11Device* device, HWND hwnd, LPCSTR vsFileName, LPCSTR psFileName)
{
HRESULT result;
ID3D10Blob* errorMessage = nullptr;
ID3D10Blob* vertexShaderBuffer = nullptr;
ID3D10Blob* pixelShaderBuffer = nullptr;
D3D11_INPUT_ELEMENT_DESC polygonLayout[3];
unsigned int numElements;
D3D11_SAMPLER_DESC samplerDesc;
D3D11_BUFFER_DESC matrixBufferDesc;
D3D11_BUFFER_DESC lightBufferDesc;
result = D3DX11CompileFromFile(vsFileName, NULL, NULL, "TerrainVertexShader", "vs_5_0", D3D10_SHADER_ENABLE_STRICTNESS,
0, NULL, &vertexShaderBuffer, &errorMessage, NULL);
if (FAILED(result))
{
if (errorMessage)
{
OutputShaderErrorMessage(errorMessage, hwnd, vsFileName);
}
else
{
MessageBox(hwnd, "Missing Shader File", vsFileName, MB_OK);
}
return false;
}
result = D3DX11CompileFromFile(psFileName, NULL, NULL, "TerrainPixelShader", "ps_5_0", D3D10_SHADER_ENABLE_STRICTNESS,
0, NULL, &pixelShaderBuffer, &errorMessage, NULL);
if (FAILED(result))
{
if (errorMessage)
{
OutputShaderErrorMessage(errorMessage, hwnd, psFileName);
}
else
{
MessageBox(hwnd, "Missing Shader File", psFileName, MB_OK);
}
return false;
}
result = device->CreateVertexShader(vertexShaderBuffer->GetBufferPointer(), vertexShaderBuffer->GetBufferSize(), NULL, &m_vertexShader);
if (FAILED(result))
{
return false;
}
result = device->CreatePixelShader(pixelShaderBuffer->GetBufferPointer(), pixelShaderBuffer->GetBufferSize(), NULL, &m_pixelShader);
if (FAILED(result))
{
return false;
}
polygonLayout[0].SemanticName = "POSITION";
polygonLayout[0].SemanticIndex = 0;
polygonLayout[0].Format = DXGI_FORMAT_R32G32B32_FLOAT;
polygonLayout[0].InputSlot = 0;
polygonLayout[0].AlignedByteOffset = 0;
polygonLayout[0].InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA;
polygonLayout[0].InstanceDataStepRate = 0;
polygonLayout[1].SemanticName = "TEXCOORD";
polygonLayout[1].SemanticIndex = 0;
polygonLayout[1].Format = DXGI_FORMAT_R32G32_FLOAT;
polygonLayout[1].InputSlot = 0;
polygonLayout[1].AlignedByteOffset = D3D11_APPEND_ALIGNED_ELEMENT;
polygonLayout[1].InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA;
polygonLayout[1].InstanceDataStepRate = 0;
polygonLayout[2].SemanticName = "NORMAL";
polygonLayout[2].SemanticIndex = 0;
polygonLayout[2].Format = DXGI_FORMAT_R32G32B32_FLOAT;
polygonLayout[2].InputSlot = 0;
polygonLayout[2].AlignedByteOffset = D3D11_APPEND_ALIGNED_ELEMENT;
polygonLayout[2].InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA;
polygonLayout[2].InstanceDataStepRate = 0;
numElements = sizeof(polygonLayout) / sizeof(polygonLayout[0]);
result = device->CreateInputLayout(polygonLayout, numElements, vertexShaderBuffer->GetBufferPointer(), vertexShaderBuffer->GetBufferSize(), &m_layout);
if (FAILED(result))
{
return false;
}
vertexShaderBuffer->Release();
vertexShaderBuffer = nullptr;
pixelShaderBuffer->Release();
pixelShaderBuffer = nullptr;
samplerDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR;
samplerDesc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP;
samplerDesc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP;
samplerDesc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP;
samplerDesc.MipLODBias = 0.0f;
samplerDesc.MaxAnisotropy = 1;
samplerDesc.ComparisonFunc = D3D11_COMPARISON_ALWAYS;
samplerDesc.BorderColor[0] = 0;
samplerDesc.BorderColor[1] = 0;
samplerDesc.BorderColor[2] = 0;
samplerDesc.BorderColor[3] = 0;
samplerDesc.MinLOD = 0;
samplerDesc.MaxLOD = D3D11_FLOAT32_MAX;
result = device->CreateSamplerState(&samplerDesc, &m_samplerState);
if (FAILED(result))
{
return false;
}
matrixBufferDesc.Usage = D3D11_USAGE_DYNAMIC;
matrixBufferDesc.ByteWidth = sizeof(MatrixBufferType);
matrixBufferDesc.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
matrixBufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
matrixBufferDesc.MiscFlags = 0;
matrixBufferDesc.StructureByteStride = 0;
result = device->CreateBuffer(&matrixBufferDesc, NULL, &m_matrixBuffer);
if (FAILED(result))
{
return false;
}
//ByteWidth must be a multiple of 16 if using D3D11_BIND_CONSTANT_BUFFER or CreateBuffer will fail.
lightBufferDesc.Usage = D3D11_USAGE_DYNAMIC;
lightBufferDesc.ByteWidth = sizeof(LightBufferType);
lightBufferDesc.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
lightBufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
lightBufferDesc.MiscFlags = 0;
lightBufferDesc.StructureByteStride = 0;
device->CreateBuffer(&lightBufferDesc, NULL, &m_lightBuffer);
if (FAILED(result))
{
return false;
}
return true;
}
The texture is supposed to look like displayed on the link, but instead looks like really weird (can't seem to be able to take a screen shot, will add if possible).
I tried looking into other questions here, but none solved the issue.
I am still fairly new to DX11, so any help is much appreciated.
Edit: Here is a screenshot (left side: supposed, right side: my game)
Im looking at your screenshot, and your not only is your texture not rendering correctly, but your normals aren't either otherwise you would have a diffuse at least shading it properly. I would summise, that although your stride is correct, what you are pulling out of the buffer for UV and Normal is not aligned properly. My first thoughts.

Texture shows as black

I am trying to make a texture to cover a triangle instead of color, but it looks like there is something wrong with the Texture Initialization...
Texture loading is fine, I tried it with Opengl and It worked perfectly however it isn't working in Directx 11.
void DX11Texture2D::Create(Texture_Data Data, Texture_Desc Desc)
{
D3D11_TEXTURE2D_DESC texDesc;
ZeroMemory(&texDesc, sizeof(texDesc));
texDesc.Width = Data.width;
texDesc.Height = Data.height;
texDesc.MipLevels = 0;
texDesc.ArraySize = 1;
texDesc.Format = GetDXTextureFormat(Desc.Format);
texDesc.SampleDesc.Count = 1;
texDesc.SampleDesc.Quality = 0;
texDesc.Usage = D3D11_USAGE_DEFAULT;
texDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
texDesc.CPUAccessFlags = 0;
texDesc.MiscFlags = 0;
D3D11_SUBRESOURCE_DATA subData;
subData.pSysMem = Data.databuf;
subData.SysMemPitch = Data.width * 4;
subData.SysMemSlicePitch = Data.width * Data.height * 4;
Core::Internals::DX11Renderer::GetDevice()->CreateTexture2D(&texDesc, &subData, &textureID);
//TODO: Add a way to disable and enable mip map
Core::Internals::DX11Renderer::GetDevice()->CreateShaderResourceView(textureID, 0, &resourceView);
D3D11_SAMPLER_DESC samplerDesc;
ZeroMemory(&samplerDesc, sizeof(D3D11_SAMPLER_DESC));
samplerDesc.AddressU = GetDXTextureWrap(Desc.Wrap);
samplerDesc.AddressV = GetDXTextureWrap(Desc.Wrap);
samplerDesc.AddressW = GetDXTextureWrap(Desc.Wrap);
samplerDesc.Filter = GetDXTextureFilter(Desc.Filter);
samplerDesc.ComparisonFunc = D3D11_COMPARISON_ALWAYS;
samplerDesc.MinLOD = 0;
samplerDesc.MaxLOD = D3D11_FLOAT32_MAX;
Core::Internals::DX11Renderer::GetDevice()->CreateSamplerState(&samplerDesc, &samplerState);
}
void DX11Texture2D::Bind(unsigned int index)
{
Core::Internals::DX11Renderer::GetContext()->PSSetShaderResources(index, 1, &resourceView);
Core::Internals::DX11Renderer::GetContext()->PSSetSamplers(index, 1, &samplerState);
}
DXGI_FORMAT DX11Texture2D::GetDXTextureFormat(API::TextureFormat format)
{
switch (format)
{
case API::TextureFormat::R8: return DXGI_FORMAT_R8_UNORM;
case API::TextureFormat::R8G8: return DXGI_FORMAT_R8G8_UNORM;
case API::TextureFormat::R8G8B8: return DXGI_FORMAT_R8G8B8A8_UNORM;
case API::TextureFormat::R8G8B8A8: return DXGI_FORMAT_R8G8B8A8_UNORM;
default: return DXGI_FORMAT_R8G8B8A8_UNORM;
}
}
D3D11_TEXTURE_ADDRESS_MODE DX11Texture2D::GetDXTextureWrap(API::TextureWrap textureWrap)
{
switch (textureWrap)
{
case API::TextureWrap::Repeat: return D3D11_TEXTURE_ADDRESS_WRAP;
case API::TextureWrap::MirroredReapeat: return D3D11_TEXTURE_ADDRESS_MIRROR;
case API::TextureWrap::ClampToEdge: return D3D11_TEXTURE_ADDRESS_CLAMP;
case API::TextureWrap::ClampToBorder: return D3D11_TEXTURE_ADDRESS_BORDER;
default: return D3D11_TEXTURE_ADDRESS_WRAP;
}
}
D3D11_FILTER DX11Texture2D::GetDXTextureFilter(API::TextureFilter textureFilter)
{
//TODO: Add more texture filter types to control both min and mag
switch (textureFilter)
{
case API::TextureFilter::Nearest: return D3D11_FILTER_MIN_MAG_MIP_POINT;
case API::TextureFilter::Linear: return D3D11_FILTER_MIN_MAG_MIP_LINEAR;
default: return D3D11_FILTER_MIN_MAG_MIP_POINT;
}
}
Also my shaders
Triangle.vs:
struct VertexInputType
{
float3 position : POSITION;
float3 color : COLOR;
float2 tex : TEXCOORD;
};
struct PixelInputType
{
float4 position : SV_POSITION;
float2 tex : TEXCOORD;
};
PixelInputType main(VertexInputType input)
{
PixelInputType output;
// Calculate the position of the vertex against the world, view, and projection matrices.
output.position = float4(input.position, 1);
// Store the input texture for the pixel shader to use.
output.tex = input.tex;
return output;
}
Triangle.ps
struct PixelInputType
{
float4 position : SV_POSITION;
float2 tex : TEXCOORD;
};
Texture2D shaderTexture : register(t0);;
SamplerState SampleType : register(s0);;
float4 main(PixelInputType input) : SV_TARGET
{
return shaderTexture.Sample(SampleType, input.tex);
}
Cheers,
Zlixine.
It seems you are creating a texture with a full mip map chain, but looking at initial data it looks like you provide only one slice (if your sampler tries to access another slice, since no data was provided, it will be black)
In that case you should enforce single mip by using :
texDesc.MipLevels = 1;
The line:
subData.SysMemSlicePitch = Data.width * Data.height * 4;
is not needed, as this parameter is ignored in case of 2d texture (you can leave it to 0 or any value).
Also, you should check result codes when creating resources eg:
HRESULT hr = Core::Internals::DX11Renderer::GetDevice()->CreateTexture2D(&texDesc, &subData, &textureID);
if FAILED(hr)
{
//Handle issue if texture creation did fail
}
And make sure to use D3D11CreateDevice with D3D11_CREATE_DEVICE_DEBUG,
so when debugging, you will have meaningful error messages in your visual studio output window (if creation fails, you will have an explanation instead of getting only INVALIDARG hresult, which is not really useful)

Need Help Understanding Invalid Argument Error When Creating Vertex Shader

I'm just starting out in DirectX 11, and I've run into a problem. I'm loading an extremely simple shader in an HSDL file:
struct VOut{
float4 position : SV_POSITION;
float4 color : COLOR;
};
VOut VS_Main( float4 pos : POSITION, float4 color : COLOR )
{
VOut output;
output.position = pos;
output.color = color;
return output;
}
float4 PS_Main( float4 pos : SV_POSITION, float4 color : COLOR ) : SV_TARGET
{
return color;
}
Using the following code (that DOES NOT trigger the if(FAILED(result) statement):
bool PathfindingDemoBase::CompileD3DShader(char* filePath, char* entry, char* shaderModel, ID3DBlob** buffer){
DWORD shaderFlags = D3DCOMPILE_ENABLE_STRICTNESS;
#if defined(DEBUG) || defined(_DEBUG)
shaderFlags |= D3DCOMPILE_DEBUG;
#endif
ID3DBlob* errorBuffer = 0;
HRESULT result;
result = D3DX11CompileFromFile(filePath, 0, 0, entry, shaderModel,
0, 0, 0, buffer, &errorBuffer, 0);
if(FAILED(result)){
if(errorBuffer != 0){
OutputDebugStringA((char*)errorBuffer->GetBufferPointer());
errorBuffer->Release();
}
return false;
}
if(errorBuffer != 0){
errorBuffer->Release();
}
return true;
}
But what does happen is in the LoadContent function, the commented line (//<---) triggers an "E_INVALIDARG" result (in d3dResult), but the vsBuffer-> calls aren't returning null :/
bool AStarDemo::LoadContent(){
ID3D10Blob* vsBuffer = 0;
bool compileResult = CompileD3DShader("ReturnColor.hlsl", "VS_Main", "vs_5_0", &vsBuffer);
if(compileResult == false){
MessageBox(0, "Error loading vertex shader!", "Compile Error", MB_OK);
return false;
}
HRESULT d3dResult;
d3dResult = d3dDevice->CreateVertexShader(vsBuffer->GetBufferPointer(),
vsBuffer->GetBufferSize(), 0, &returnColorVS);
//actually set the vertex shader
d3dContext->VSSetShader(returnColorVS, 0, 0);
if(FAILED(d3dResult)){
if(vsBuffer){
vsBuffer->Release();
}
return false;
}
D3D11_INPUT_ELEMENT_DESC solidColorLayout[] ={
{ "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 }
};
unsigned int totalLayoutElements = ARRAYSIZE(solidColorLayout);
d3dResult = d3dDevice->CreateInputLayout(solidColorLayout, totalLayoutElements,
vsBuffer->GetBufferPointer(), vsBuffer->GetBufferSize(), &inputLayout);
vsBuffer->Release();
if(FAILED(d3dResult)){
return false;
}
ID3D10Blob* psBuffer = 0;
compileResult = CompileD3DShader("ReturnColor.hlsl", "PS_Main", "ps_5_0", &psBuffer);
//actually set the pixel shader
d3dContext->PSSetShader(returnColorPS, 0, 0);
if(compileResult == false){
MessageBox(0, "Error loading pixel shader!", "Compile Error", MB_OK);
return false;
}
d3dResult = d3dDevice->CreatePixelShader(psBuffer->GetBufferPointer(),
psBuffer->GetBufferSize(), 0, &returnColorPS);
psBuffer->Release();
if(FAILED(d3dResult)){
return false;
}
Vertex vertices[4 * TOTAL_NUMBER_GRID_SQUARES];
gridSquares = new GridSquare[TOTAL_NUMBER_GRID_SQUARES];
//for each grid square
for(int i = 0; i < TOTAL_NUMBER_GRID_SQUARES; i++){
XMFLOAT4 color = ((i%2) == 0) ? GREEN : RED;
//create a grid square object
GridSquare gs;
gs.TopLeft = Vertex( XMFLOAT3(0.5f * i, 0.5f * i, Z_LEVEL),
color);
gs.TopRight = Vertex( XMFLOAT3( 0.5f * i, -0.5f * i, Z_LEVEL),
color);
gs.BottomRight = Vertex( XMFLOAT3(-0.5f * i, -0.5f * i, Z_LEVEL),
color);
gs.BottomLeft = Vertex( XMFLOAT3(-0.5f * i, 0.5f * i, Z_LEVEL),
color);
gs.type = ((i%2) == 0) ? prey : hunter;
gridSquares[i] = gs;
vertices[4*i] = gs.TopLeft;
vertices[(4*i)+1] = gs.TopRight;
vertices[(4*i)+2] = gs.BottomRight;
vertices[(4*i)+3] = gs.BottomLeft;
}
D3D11_BUFFER_DESC vertexDesc;
ZeroMemory(&vertexDesc, sizeof(vertexDesc));
vertexDesc.Usage = D3D11_USAGE_DYNAMIC;
vertexDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
vertexDesc.ByteWidth = 4 * TOTAL_NUMBER_GRID_SQUARES * sizeof(Vertex);
vertexDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
D3D11_SUBRESOURCE_DATA resourceData;
ZeroMemory(&resourceData, sizeof(resourceData));
resourceData.pSysMem = vertices;
d3dResult = d3dDevice->CreateBuffer(&vertexDesc, &resourceData, &vertexBuffer);
if(FAILED(d3dResult)){
return false;
}
return true;
}
Any advice would be greatly appreciated! :)
Found the answer after digging around a bit- apparently there are some problems with using "ps_5_0" and "vs_5_0", even though my machine runs DirectX 11