Directx11: remove alpha blending for specific sprite - c++

Background:
- I've been spending the last 6 weeks trying to learn Directx 11 programming.
I'm currently rendering dds images on-screen following this book
http://www.amazon.co.uk/Beginning-Directx-11-Game-Programming/dp/1435458958/ref=sr_1_1?ie=UTF8&qid=1346510304&sr=8-1
I am trying to draw 2D sprites upon a 2D background which in itself also is a 2D sprite. Problem is that these two lines
d3dDevice_->CreateBlendState( &blendDesc, &alphaBlendState_ );
d3dContext_->OMSetBlendState( alphaBlendState_, blendFactor, 0xFFFFFFFF );
to enable the alpha transparency in the dds images. I like to have the option to blend sprites but right now every sprites is blended with my blue background thus resulting in blu logos, icons etc.
How do I make the Alpha Blending ignore a specific image in directx 11?
Since the background sprite is the first to be drawn I can't activate the Blending later in the code when rendering the other sprites without every sprite turning blue.
thanks in advance :)
EDIT:
I've been working on this issue for the past 3 weeks and still no solution. Everytime the blend state is enabled in the DeviceContext is seems to apply to every texture drawn on the screen no matter the order of rendering.
Here is the source code of the header file:
class GameSpriteDemo : public Dx11DemoBase
{
public:
GameSpriteDemo( );
virtual ~GameSpriteDemo( );
bool LoadContent( );
void UnloadContent( );
void Update( float dt );
void Render( );
void DisableBlending();
ID3D11ShaderResourceView* getColorMap(int);
int UniqSpriteAmount();
// text rendering system
private:
bool DrawString( char* message, float startX, float startY );
private:
ID3D11VertexShader* solidColorVS_;
ID3D11VertexShader* solidColorVS_2;
ID3DX11Effect* effect_;
vector<ID3D11VertexShader*> solidColorVShaders;
ID3D11PixelShader* solidColorPS_;
ID3D11PixelShader* solidColorPS_2;
ID3D11InputLayout* inputLayout_;
ID3D11InputLayout* inputLayout2;
ID3D11Buffer* vertexBuffer_;
vector<ID3D11Buffer*> vertexBuffers;
ID3D11ShaderResourceView* colorMap_;
vector<ID3D11ShaderResourceView*> colorMaps;
ID3D11SamplerState* colorMapSampler_;
vector<ID3D11SamplerState*> colorSamplers;
ID3D11BlendState* alphaBlendState_;
ID3D11BlendState* alphaBlendStateOff;
vector<LPCTSTR> elements2D;
vector<GameSprite> sprites_;
ID3D11Buffer* mvpCB_;
XMMATRIX vpMatrix_;
};
#endif
Here is the source code of the cpp file: (the Base Class DxD11DemoClass is not needed since it only sets up SwapChain and D3DContext)
bool GameSpriteDemo::LoadContent( )
{
// add sprite textures to the engine, giving them index 0, 1, 2... etc.
elements2D.push_back("placeholder3.dds");
elements2D.push_back("cav.dds");
elements2D.push_back("Stats.dds");
// create sprites
XMFLOAT2 sprite1Pos( 0.0f, 500.0f);
GameSprite sprite1(getDevice(), "placeholder3.dds", 0, sprite1Pos, 0.0f);
XMFLOAT2 sprite1Scale( 0.5f, 0.5f );
XMFLOAT2 mini(0.8f, 0.6f);
sprite1.SetScale(mini);
sprites_.push_back(sprite1);
XMFLOAT2 sprite2Pos( 200.0f, 100.0f );
GameSprite sprite2(getDevice(), "Stats.dds", 2, sprite2Pos, 2.0f);
// sprites_.push_back(sprite2);
XMFLOAT2 sprite3Pos( 290.0f, 300.0f );
GameSprite sprite3(getDevice(), "cav.dds", 1, sprite3Pos, 2.0f);
sprite3.SetScale(sprite1Scale);
sprites_.push_back(sprite3);
// create vertex buffers, colorMaps and colorSamplers
for (int i = 0; i <= elements2D.size(); i++) {
solidColorVShaders.push_back(solidColorVS_);
colorMaps.push_back(colorMap_);
colorSamplers.push_back(colorMapSampler_);
vertexBuffers.push_back(vertexBuffer_);
}
// continue
ID3DBlob* vsBuffer = 0;
bool compileResult = CompileD3DShader( "TextureMap.fx", "VS_Main", "vs_4_0", &vsBuffer );
if( compileResult == false )
{
DXTRACE_MSG( "Error compiling the vertex shader!" );
return false;
}
HRESULT d3dResult;
d3dResult = d3dDevice_->CreateVertexShader( vsBuffer->GetBufferPointer( ),
vsBuffer->GetBufferSize( ), 0, &solidColorVShaders[0] );
if( FAILED( d3dResult ) )
{
DXTRACE_MSG( "Error creating the vertex shader!" );
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 },
{ "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 12, 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 ) )
{
DXTRACE_MSG( "Error creating the input layout!" );
return false;
}
ID3DBlob* psBuffer = 0;
compileResult = CompileD3DShader( "TextureMap.fx", "PS_Main", "ps_4_0", &psBuffer );
if( compileResult == false )
{
DXTRACE_MSG( "Error compiling pixel shader!" );
return false;
}
d3dResult = d3dDevice_->CreatePixelShader( psBuffer->GetBufferPointer( ),
psBuffer->GetBufferSize( ), 0, &solidColorPS_ );
psBuffer->Release( );
if( FAILED( d3dResult ) )
{
DXTRACE_MSG( "Error creating pixel shader!" );
return false;
}
// create ColorMap, ColorSampler and VertexBuffer for each unique sprite
D3D11_SAMPLER_DESC colorMapDesc;
D3D11_BUFFER_DESC vertexDesc;
D3D11_SUBRESOURCE_DATA resourceData;
for (int j = 0; j < elements2D.size(); j++) {
d3dResult = D3DX11CreateShaderResourceViewFromFile( d3dDevice_,
elements2D[j], 0, 0, &colorMaps[j], 0 );
if( FAILED( d3dResult ) )
{
DXTRACE_MSG( "Failed to load the texture image!" );
return false;
}
ZeroMemory( &colorMapDesc, sizeof( colorMapDesc ) );
colorMapDesc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP;
colorMapDesc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP;
colorMapDesc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP;
colorMapDesc.ComparisonFunc = D3D11_COMPARISON_NEVER;
colorMapDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR;
colorMapDesc.MaxLOD = D3D11_FLOAT32_MAX;
d3dResult = d3dDevice_->CreateSamplerState( &colorMapDesc, &colorSamplers[j] );
if( FAILED( d3dResult ) )
{
DXTRACE_MSG( "Failed to create color map sampler state!" );
return false;
}
float Width = sprites_[j].getWidth();
float Height = sprites_[j].getHeight();
VertexPos vertices[] =
{
{ XMFLOAT3( Width, Height, 1.0f ), XMFLOAT2( 1.0f, 0.0f ) },
{ XMFLOAT3( Width, -Height, 1.0f ), XMFLOAT2( 1.0f, 1.0f ) },
{ XMFLOAT3( -Width, -Height, 1.0f ), XMFLOAT2( 0.0f, 1.0f ) },
{ XMFLOAT3( -Width, -Height, 1.0f ), XMFLOAT2( 0.0f, 1.0f ) },
{ XMFLOAT3( -Width, Height, 1.0f ), XMFLOAT2( 0.0f, 0.0f ) },
{ XMFLOAT3( Width, Height, 1.0f ), XMFLOAT2( 1.0f, 0.0f ) },
};
ZeroMemory( &vertexDesc, sizeof( vertexDesc ) );
vertexDesc.Usage = D3D11_USAGE_DEFAULT;
vertexDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
vertexDesc.ByteWidth = sizeof( VertexPos ) * 6;
ZeroMemory( &resourceData, sizeof( resourceData ) );
resourceData.pSysMem = vertices;
d3dResult = d3dDevice_->CreateBuffer( &vertexDesc, &resourceData, &vertexBuffers[j] );
if( FAILED( d3dResult ) )
{
DXTRACE_MSG( "Failed to create vertex buffer!" );
return false;
}
}
// end of foor loop
// create text fonts
d3dResult = D3DX11CreateShaderResourceViewFromFile( d3dDevice_,
"font.dds", 0, 0, &colorMap_, 0 );
if( FAILED( d3dResult ) )
{
DXTRACE_MSG( "Failed to load the texture image!" );
return false;
}
D3D11_SAMPLER_DESC colorMapDesc2;
ZeroMemory( &colorMapDesc2, sizeof( colorMapDesc2 ) );
colorMapDesc2.AddressU = D3D11_TEXTURE_ADDRESS_WRAP;
colorMapDesc2.AddressV = D3D11_TEXTURE_ADDRESS_WRAP;
colorMapDesc2.AddressW = D3D11_TEXTURE_ADDRESS_WRAP;
colorMapDesc2.ComparisonFunc = D3D11_COMPARISON_NEVER;
colorMapDesc2.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR;
colorMapDesc2.MaxLOD = D3D11_FLOAT32_MAX;
d3dResult = d3dDevice_->CreateSamplerState( &colorMapDesc2, &colorMapSampler_ );
if( FAILED( d3dResult ) )
{
DXTRACE_MSG( "Failed to create color map sampler state!" );
return false;
}
D3D11_BUFFER_DESC vertexDesc2;
ZeroMemory( &vertexDesc2, sizeof( vertexDesc2 ) );
vertexDesc2.Usage = D3D11_USAGE_DYNAMIC;
vertexDesc2.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
vertexDesc2.BindFlags = D3D11_BIND_VERTEX_BUFFER;
const int sizeOfSprite = sizeof( VertexPos ) * 6;
const int maxLetters = 24;
vertexDesc2.ByteWidth = sizeOfSprite * maxLetters;
d3dResult = d3dDevice_->CreateBuffer( &vertexDesc2, 0, &vertexBuffer_ );
if( FAILED( d3dResult ) )
{
DXTRACE_MSG( "Failed to create vertex buffer!" );
return false;
}
// end of font creation
D3D11_BUFFER_DESC constDesc;
ZeroMemory( &constDesc, sizeof( constDesc ) );
constDesc.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
constDesc.ByteWidth = sizeof( XMMATRIX );
constDesc.Usage = D3D11_USAGE_DEFAULT;
d3dResult = d3dDevice_->CreateBuffer( &constDesc, 0, &mvpCB_ );
if( FAILED( d3dResult ) )
{
return false;
}
XMMATRIX view = XMMatrixIdentity( );
XMMATRIX projection = XMMatrixOrthographicOffCenterLH( 0.0f, 1366.0f, 0.0f, 768.0f, 0.1f, 100.0f );
vpMatrix_ = XMMatrixMultiply( view, projection );
D3D11_BLEND_DESC blendDesc;
ZeroMemory( &blendDesc, sizeof( blendDesc ) );
blendDesc.RenderTarget[0].BlendEnable = TRUE;
blendDesc.RenderTarget[0].BlendOp = D3D11_BLEND_OP_ADD;
blendDesc.RenderTarget[0].SrcBlend = D3D11_BLEND_SRC_ALPHA;
blendDesc.RenderTarget[0].DestBlend = D3D11_BLEND_ONE;
blendDesc.RenderTarget[0].BlendOpAlpha = D3D11_BLEND_OP_ADD;
blendDesc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_ZERO;
blendDesc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_ZERO;
blendDesc.RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL;
float blendFactor[4] = { 0.0f, 0.0f, 0.0f, 0.0f };
d3dDevice_->CreateBlendState( &blendDesc, &alphaBlendState_ );
// create the disabled blend state
blendDesc.RenderTarget[0].BlendEnable = FALSE;
d3dDevice_->CreateBlendState( &blendDesc, &alphaBlendStateOff );
d3dContext_->OMSetBlendState( alphaBlendState_, blendFactor, 0xFFFFFFFF );
// holy shit here we go again
ID3DBlob* vsBuffer2 = 0;
compileResult = CompileD3DShader( "TextMap.fx", "VS_Main", "vs_4_0", &vsBuffer2 );
if( compileResult == false )
{
DXTRACE_MSG( "Error compiling the vertex shader!" );
return false;
}
d3dResult = d3dDevice_->CreateVertexShader( vsBuffer2->GetBufferPointer( ),
vsBuffer2->GetBufferSize( ), 0, &solidColorVS_2 );
ID3DBlob* psBuffer2 = 0;
compileResult = CompileD3DShader( "TextureMap.fx", "PS_Main", "ps_4_0", &psBuffer2 );
if( compileResult == false )
{
DXTRACE_MSG( "Error compiling pixel shader!" );
return false;
}
d3dResult = d3dDevice_->CreatePixelShader( psBuffer2->GetBufferPointer( ),
psBuffer2->GetBufferSize( ), 0, &solidColorPS_2 );
psBuffer2->Release( );
return true;
}
void GameSpriteDemo::UnloadContent( )
{
if( colorMapSampler_ ) colorMapSampler_->Release( );
if( colorMap_ ) colorMap_->Release( );
if( solidColorVShaders[0] ) solidColorVShaders[0]->Release( );
if( solidColorPS_ ) solidColorPS_->Release( );
if( inputLayout_ ) inputLayout_->Release( );
if( vertexBuffer_ ) vertexBuffer_->Release( );
if( mvpCB_ ) mvpCB_->Release( );
if( alphaBlendState_ ) alphaBlendState_->Release( );
if( alphaBlendStateOff ) alphaBlendStateOff->Release( );
colorMapSampler_ = 0;
colorMap_ = 0;
solidColorVShaders[0] = 0;
solidColorPS_ = 0;
inputLayout_ = 0;
vertexBuffer_ = 0;
mvpCB_ = 0;
alphaBlendState_ = 0;
alphaBlendStateOff = 0;
}
void GameSpriteDemo::Update( float dt )
{
// Nothing to update
}
bool GameSpriteDemo::DrawString( char* message, float startX, float startY )
{
// Size in bytes for a single sprite.
const int sizeOfSprite = sizeof( VertexPos ) * 6;
// Demo's dynamic buffer setup for max of 24 letters.
const int maxLetters = 24;
int length = strlen( message );
// Clamp for strings too long.
if( length > maxLetters )
length = maxLetters;
// Char's width on screen.
float charWidth = 32.0f / (1366.0f*1.0f);
// Char's height on screen.
float charHeight = 32.0f / (768.0f*1.0f);
// Char's texel width.
float texelWidth = 32.0f / 896.0f;
// verts per-triangle (3) * total triangles (2) = 6.
const int verticesPerLetter = 6;
D3D11_MAPPED_SUBRESOURCE mapResource;
HRESULT d3dResult = d3dContext_->Map( vertexBuffer_, 0, D3D11_MAP_WRITE_DISCARD, 0, &mapResource );
if( FAILED( d3dResult ) )
{
DXTRACE_MSG( "Failed to map resource!" );
return false;
}
// Point to our vertex buffer's internal data.
VertexPos *spritePtr = ( VertexPos* )mapResource.pData;
const int indexA = static_cast<char>( 'A' );
const int indexZ = static_cast<char>( 'Z' );
const int index_a = static_cast<char>( 'a' );
for( int i = 0; i < length; ++i )
{
float thisStartX = startX + ( charWidth * static_cast<float>( i ) );
float thisEndX = thisStartX + charWidth;
float thisEndY = startY + charHeight;
spritePtr[0].pos = XMFLOAT3( thisEndX, thisEndY, 1.0f );
spritePtr[1].pos = XMFLOAT3( thisEndX, startY, 1.0f );
spritePtr[2].pos = XMFLOAT3( thisStartX, startY, 1.0f );
spritePtr[3].pos = XMFLOAT3( thisStartX, startY, 1.0f );
spritePtr[4].pos = XMFLOAT3( thisStartX, thisEndY, 1.0f );
spritePtr[5].pos = XMFLOAT3( thisEndX, thisEndY, 1.0f );
int texLookup = 0;
int letter = static_cast<char>( message[i] );
if (letter == index_a) {
texLookup = (indexZ - indexA) + 2;
}
else if( letter < indexA || letter > indexZ )
{
// Grab one index past Z, which is a blank space in the texture.
texLookup = ( indexZ - indexA ) + 1;
}
else
{
// A = 0, B = 1, Z = 25, etc.
texLookup = ( letter - indexA );
}
float tuStart = 0.0f + ( texelWidth * static_cast<float>( texLookup ) );
float tuEnd = tuStart + texelWidth;
spritePtr[0].tex0 = XMFLOAT2( tuEnd, 0.0f );
spritePtr[1].tex0 = XMFLOAT2( tuEnd, 1.0f );
spritePtr[2].tex0 = XMFLOAT2( tuStart, 1.0f );
spritePtr[3].tex0 = XMFLOAT2( tuStart, 1.0f );
spritePtr[4].tex0 = XMFLOAT2( tuStart, 0.0f );
spritePtr[5].tex0 = XMFLOAT2( tuEnd, 0.0f );
spritePtr += 6;
}
d3dContext_->Unmap( vertexBuffer_, 0 );
d3dContext_->Draw( 6 * length, 0 );
return true;
}
void GameSpriteDemo::Render( )
{
if( d3dContext_ == 0 )
return;
float clearColor[4] = { 0.0f, 0.0f, 0.0f, 1.0f };
d3dContext_->ClearRenderTargetView( backBufferTarget_, clearColor );
unsigned int stride = sizeof( VertexPos );
unsigned int offset = 0;
d3dContext_->IASetInputLayout( inputLayout_ );
d3dContext_->IASetPrimitiveTopology( D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST );
d3dContext_->VSSetShader( solidColorVShaders[0], 0, 0 );
d3dContext_->PSSetShader( solidColorPS_, 0, 0 );
XMMATRIX world;
XMMATRIX mvp;
int index;
for (int k = 0; k < sprites_.size(); k++) {
index = sprites_[k].getIndex();
d3dContext_->IASetVertexBuffers( 0, 1, &vertexBuffers[index], &stride, &offset );
d3dContext_->PSSetShaderResources( 0, 1, &colorMaps[index] );
d3dContext_->PSSetSamplers( 0, 1, &colorSamplers[index] );
world = sprites_[k].GetWorldMatrix();
mvp = XMMatrixMultiply( world, vpMatrix_ );
mvp = XMMatrixTranspose( mvp );
d3dContext_->UpdateSubresource( mvpCB_, 0, 0, &mvp, 0, 0 );
d3dContext_->VSSetConstantBuffers( 0, 1, &mvpCB_ );
d3dContext_->Draw( 6, 0 );
}
// render text
DisableBlending();
d3dContext_->IASetVertexBuffers( 0, 1, &vertexBuffer_, &stride, &offset );
d3dContext_->PSSetShaderResources( 0, 1, &colorMap_ );
d3dContext_->PSSetSamplers( 0, 1, &colorMapSampler_ );
d3dContext_->VSSetShader( solidColorVS_2, 0, 0 );
d3dContext_->PSSetShader( solidColorPS_2, 0, 0 );
DrawString( "PROTOTYPE TEXT", -0.2f, 0.0f );
swapChain_->Present( 0, 0 );
}
ID3D11ShaderResourceView* GameSpriteDemo::getColorMap(int index) {
return colorMaps[index];
}
// this functions disables the alpha blending
void GameSpriteDemo::DisableBlending() {
float blendFactor[4] = { 0.0f, 0.0f, 0.0f, 0.0f };
d3dContext_->OMSetBlendState( alphaBlendStateOff, blendFactor, 0xFFFFFFFF );
}
Screen of the results when drawing with blending enabled
http://i49.tinypic.com/33kao9v.jpg
and here is the HLSL code for the two FX files I'm using (the first for the sprites, the second for the text)
TextureMap.fx
cbuffer cbChangesPerFrame : register( b0 )
{
matrix mvp_;
};
Texture2D colorMap_ : register( t0 );
SamplerState colorSampler_ : register( s0 );
struct VS_Input
{
float4 pos : POSITION;
float2 tex0 : TEXCOORD0;
};
struct PS_Input
{
float4 pos : SV_POSITION;
float2 tex0 : TEXCOORD0;
};
PS_Input VS_Main( VS_Input vertex )
{
PS_Input vsOut = ( PS_Input )0;
vsOut.pos = mul( vertex.pos, mvp_ );
vsOut.tex0 = vertex.tex0;
return vsOut;
}
float4 PS_Main( PS_Input frag ) : SV_TARGET
{
return colorMap_.Sample( colorSampler_, frag.tex0 );
}
TextMap.fx
Texture2D colorMap_ : register( t0 );
SamplerState colorSampler_ : register( s0 );
struct VS_Input
{
float4 pos : POSITION;
float2 tex0 : TEXCOORD0;
};
struct PS_Input
{
float4 pos : SV_POSITION;
float2 tex0 : TEXCOORD0;
};
PS_Input VS_Main( VS_Input vertex )
{
PS_Input vsOut = ( PS_Input )0;
vsOut.pos = vertex.pos;
vsOut.tex0 = vertex.tex0;
return vsOut;
}
float4 PS_Main( PS_Input frag ) : SV_TARGET
{
return colorMap_.Sample( colorSampler_, frag.tex0 );
}
I have wondered maybe to use pixel shaders to perform alpha blending for specific 2D images but my first attempts has not worked at all.
Hope someone can find a solution somehow :)
and thanks again for the help.

Related

Creating structure for geometry data

I want to draw multiple polygons in one buffer, here is my conception of how I think it should work, but it does not.
This is what I have:
GLuint VertexArrayID;
GLuint vao;
GLuint program;
typedef struct object{
GLuint vao;
GLuint numVertices;
} object;
object objects[MAX_VERTEX_COUNT];
Here I create VBO:
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
glBindBuffer(GL_ARRAY_BUFFER, VertexArrayID);
glBufferData(GL_ARRAY_BUFFER, 2 * vertex_count * sizeof(float), data, GL_STATIC_DRAW);
glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(data), data);
glUseProgram(program);
GLuint vPosition = glGetAttribLocation(program, "vPosition");
glEnableVertexAttribArray(vPosition);
glVertexAttribPointer(vPosition, 2, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(0));
glVertexPointer(2, GL_FLOAT, 0, NULL);
glEnableClientState(GL_VERTEX_ARRAY);
//glDrawArrays(GL_TRIANGLE_FAN, 0, vertex_count);
And I made loop like that, but I think, when I put vao in objects[i].vao, every time when I came through that loop, it does the same without this loop, but I am not sure.
for (int i = 0; i < 5; i++)
{
objects[i].vao = vao;
glBindVertexArray(objects[i].vao);
objects[i].numVertices = vertex_count;
glDrawArrays(GL_TRIANGLE_FAN, 0, objects[i].numVertices);
}
glDisableClientState(GL_VERTEX_ARRAY);
Maybe you have some ideas?
Here I have an Image2D class object that is used to render basic 2D Images that works with my GUI hierarchy. My Shader Engine is quite large for I have a system to manage Shaders using template types. It also uses a Batch Process and all of my Assets that are loaded into memory are saved into a Storage class that handles the clean up of their memory footprint. It is too large of a project to show everything necessary to be able to compile a working program, but here is an example of a generated renderable object from within my ShaderEngine.
Image2d.h
class Image2d : public VisualMko {
private:
TextureInfo m_textureInfo;
// --- Only For Version 1.0 ---
// VBO //
unsigned m_vboTexture; //
unsigned m_vboPosition; //
unsigned m_vboIndices; //
// //
// VAO //
unsigned m_vao; //
// ------------------------- //
// version 2.0 variables below
glm::vec2 m_offsetPosition;
public:
Image2d( float fWidth, float fHeight, TextureInfo::FilterQuality filterQuality, bool generateMipMap, const std::string& strTextureFilename, const std::string& strId );
Image2d( const glm::uvec2& origin, const glm::uvec2& size, const std::string& strTextureFilename, const std::string& strId = std::string() );
virtual ~Image2d();
void setOffsetPosition( const glm::vec2& offset );
virtual void clearTextureInfos() override;
void render() override;
TextureInfo getTextureInfo() const;
void setTextureInfo( const TextureInfo& textureInfo );
private:
Image2d( const Image2d& c ); // Not Implemented
Image2d& operator=( const Image2d& c );
}; // Image2d
} // namespace vmk
#endif // IMAGE2D_H
Image2d.cpp
#include "stdafx.h"
#include "Image2d.h"
#include "AssetStorage.h"
#include "ShaderManager.h" // Only Needed For Version 1.0
#include "TextureFileReader.h"
namespace vmk {
// ----------------------------------------------------------------------------
// Image2d()
// Creates A Rectangular 2D Imgae Of The Size Specified And Stores It In A
// Vertex Array Object For Rendering. The Surface Verts Are Defined Like:
// width
// <------->
// v0 --- v2 ^
// : / : | height
// : / : |
// v1 --- v3 v
//
Image2d::Image2d( float fWidth, float fHeight, TextureInfo::FilterQuality filterQuality, bool generateMipMap, const std::string& strTextureFilename, const std::string& strId ) :
VisualMko( glm::uvec2(), strId ),
m_vboTexture( 0 ),
m_vboPosition( 0 ),
m_vboIndices( 0 ),
m_vao( 0 ) {
if ( fWidth <= 0 || fHeight <= 0 ) {
std::ostringstream strStream;
strStream << __FUNCTION__ << " Invalid image size (" << fWidth << "," << fHeight << ") must be more then 0 in each dimension.";
throw ExceptionHandler( strStream );
}
// Save TextureID
TextureFileReader textureFileReader( strTextureFilename );
m_textureInfo = textureFileReader.getOrCreateTextureInfo( filterQuality, generateMipMap, false );
// Define Texture Coordinates
std::vector<float> vTextureCoordinates;
vTextureCoordinates.push_back( 0.0f );
vTextureCoordinates.push_back( 1.0f );
vTextureCoordinates.push_back( 0.0f );
vTextureCoordinates.push_back( 0.0f );
vTextureCoordinates.push_back( 1.0f );
vTextureCoordinates.push_back( 1.0f );
vTextureCoordinates.push_back( 1.0f );
vTextureCoordinates.push_back( 0.0f );
// Define Vertex Positions (x,y,z)
std::vector<float> vVertexPositions;
vVertexPositions.push_back( 0.0f );
vVertexPositions.push_back( fHeight );
vVertexPositions.push_back( 0.0f );
vVertexPositions.push_back( 0.0f );
vVertexPositions.push_back( 0.0f );
vVertexPositions.push_back( 0.0f );
vVertexPositions.push_back( fWidth );
vVertexPositions.push_back( fHeight );
vVertexPositions.push_back( 0.0f );
vVertexPositions.push_back( fWidth );
vVertexPositions.push_back( 0.0f );
vVertexPositions.push_back( 0.0f );
// Define 2 Triangle Faces
std::vector<unsigned char> vIndices;
vIndices.push_back( 0 );
vIndices.push_back( 1 );
vIndices.push_back( 2 );
vIndices.push_back( 3 );
// Create Vertex Array Object
glGenVertexArrays( 1, &m_vao );
glBindVertexArray( m_vao ); // Start Array
m_pShaderManager->setAttribute( A_COLOR, COLOR_WHITE );
// Create Position Buffer And Store On Video Card
glGenBuffers( 1, &m_vboPosition );
glBindBuffer( GL_ARRAY_BUFFER, m_vboPosition );
glBufferData( GL_ARRAY_BUFFER, vVertexPositions.size() * sizeof( vVertexPositions[0] ), &vVertexPositions[0], GL_STATIC_DRAW );
m_pShaderManager->enableAttribute( A_POSITION );
// Create Texture Coordinate Buffer
glGenBuffers( 1, &m_vboTexture );
glBindBuffer( GL_ARRAY_BUFFER, m_vboTexture );
glBufferData( GL_ARRAY_BUFFER, vTextureCoordinates.size() * sizeof( vTextureCoordinates[0] ), &vTextureCoordinates[0], GL_STATIC_DRAW );
m_pShaderManager->enableAttribute( A_TEXTURE_COORD0 );
// Create Index Buffer
glGenBuffers( 1, &m_vboIndices );
glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, m_vboIndices );
glBufferData( GL_ELEMENT_ARRAY_BUFFER, vIndices.size() * sizeof( vIndices[0] ), &vIndices[0], GL_STATIC_DRAW );
glBindVertexArray( 0 ); // Stop Array
// Disable Attribute Pointers
m_pShaderManager->disableAttribute( A_POSITION );
m_pShaderManager->disableAttribute( A_TEXTURE_COORD0 );
// THIS MUST BE AFTER: Vertex Array Buffer Is Unbound!
glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, 0 ); // Stop Buffer Index
glBindBuffer( GL_ARRAY_BUFFER, 0 ); // Stop Buffer
} // Image2d - v1.0
// ----------------------------------------------------------------------------
// Image2d()
Image2d::Image2d( const glm::uvec2& origin, const glm::uvec2& size, const std::string& strTextureFilename, const std::string& strId ) :
VisualMko( size, strId ),
m_vboTexture( 0 ),
m_vboPosition( 0 ),
m_vboIndices( 0 ),
m_vao( 0 ) {
m_version = 2;
TextureFileReader textureFileReader( strTextureFilename );
m_textureInfo = textureFileReader.getOrCreateTextureInfo( TextureInfo::FILTER_NONE, false, false );
m_config.uTextureId = m_textureInfo.uTextureId;
if ( 0 == m_textureInfo.size.x || 0 == m_textureInfo.size.y ) {
std::ostringstream strStream;
strStream << __FUNCTION__ << " size of " << strTextureFilename << " is invalid " << m_textureInfo.size;
throw ExceptionHandler( strStream );
}
// Verify Image Fits Inside Texture
if ( m_textureInfo.size.x < size.x + origin.x || m_textureInfo.size.y < size.y + origin.y ) {
std::ostringstream strStream;
strStream << __FUNCTION__ << " " << strTextureFilename << " size is " << m_textureInfo.size
<< " which is too small for an image that is " << size
<< " pixels in size, with an origin point set at " << origin ;
throw ExceptionHandler( strStream );
}
glm::vec2 textureCoordScaleFactor( 1.0f / static_cast<float>( m_textureInfo.size.x ),
1.0f / static_cast<float>( m_textureInfo.size.y ) );
glm::vec2 texCoordBottomLeft = glm::vec2( textureCoordScaleFactor.x * origin.x,
textureCoordScaleFactor.y * ( m_textureInfo.size.y - origin.y - size.y ) );
glm::vec2 texCoordTopRight = glm::vec2( textureCoordScaleFactor.x * ( origin.x + size.x ),
textureCoordScaleFactor.y * (m_textureInfo.size.y - origin.y ) );
// Set Colors And Texture Coordinates (Position Will Be Updated In Render Function
m_vVertices.push_back( GuiVertex( glm::vec2(), COLOR_WHITE, glm::vec2( texCoordBottomLeft.x, texCoordTopRight.y ) ) );
m_vVertices.push_back( GuiVertex( glm::vec2(), COLOR_WHITE, glm::vec2( texCoordBottomLeft.x, texCoordBottomLeft.y ) ) );
m_vVertices.push_back( GuiVertex( glm::vec2(), COLOR_WHITE, glm::vec2( texCoordTopRight.x, texCoordTopRight.y ) ) );
m_vVertices.push_back( GuiVertex( glm::vec2(), COLOR_WHITE, glm::vec2( texCoordTopRight.x, texCoordBottomLeft.y ) ) );
} // Image2d() - v2.0
// ----------------------------------------------------------------------------
// ~Image2d()
Image2d::~Image2d() {
if ( 1 == m_version ) {
// Destroy Objects
if ( m_vboTexture != 0 ) {
glBindBuffer( GL_ARRAY_BUFFER, 0 );
glDeleteBuffers( 1, &m_vboTexture );
m_vboTexture = 0;
}
if ( m_vboPosition != 0 ) {
glBindBuffer( GL_ARRAY_BUFFER, 0 );
glDeleteBuffers( 1, &m_vboPosition );
m_vboPosition = 0;
}
if ( m_vboIndices != 0 ) {
glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, 0 );
glDeleteBuffers( 1, &m_vboIndices );
m_vboIndices = 0;
}
if ( m_vao != 0 ) {
glBindVertexArray( 0 );
glDeleteVertexArrays( 1, &m_vao );
m_vao = 0;
}
}
} // Image2d
// ----------------------------------------------------------------------------
// setOffsetPosition()
void Image2d::setOffsetPosition( const glm::vec2& offset ) {
if ( offset.x != m_offsetPosition.x || offset.y != m_offsetPosition.y ) {
m_offsetPosition = offset;
m_transformMatrix.updateTranslation = true;
}
} // setOffsetPosition
// ----------------------------------------------------------------------------
// clearTextureInfos()
void Image2d::clearTextureInfos() {
if ( m_pAssetStorage->removeTextureInfo( m_textureInfo.uTextureId ) ) {
m_textureInfo = TextureInfo();
}
} // clearTextureInfos
// ----------------------------------------------------------------------------
// render()
void Image2d::render() {
if ( 1 == m_version ) {
m_pShaderManager->setTexture( 0, U_TEXTURE0_SAMPLER_2D, m_textureInfo.uTextureId );
glBindVertexArray( m_vao );
glDrawElements( GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_BYTE, nullptr );
glBindVertexArray( 0 );
} else {
// Version 2.0
// Update Vertices
if ( m_transformMatrix.updateTranslation || m_transformMatrix.updateScale || m_transformMatrix.updateRotation ) {
m_transformMatrix.updateTranslation = m_transformMatrix.updateScale = m_transformMatrix.updateRotation = false;
// Order Of Operations Matter Here!
glm::mat4 matrix; // identity
if ( m_transformMatrix.hasTranslation ) {
matrix[3][0] = m_transformMatrix.translation.x;
matrix[3][1] = m_transformMatrix.translation.y;
}
if ( m_transformMatrix.hasRotation ) {
matrix = glm::rotate( matrix, m_transformMatrix.fRotationAngleDegrees, glm::vec3( 0.0f, 0.0f, -1.0f ) );
}
if ( m_transformMatrix.hasScale ) {
matrix = matrix * glm::mat4( m_transformMatrix.scale.x, 0.0f, 0.0f, 0.0f,
0.0f, m_transformMatrix.scale.y, 0.0f, 0.0f,
0.0f, 0.0f, 1.0f, 0.0f,
0.0f, 0.0f, 0.0f, 1.0f );
}
// Center Offset
if ( m_offsetPosition.x != 0 || m_offsetPosition.y != 0 ) {
matrix = glm::translate( matrix, glm::vec3( -m_offsetPosition.x, -m_offsetPosition.y, 0.0f ) );
}
// Apply Transformation To All 4 Vertices
m_vVertices[0].position = glm::vec2( matrix * glm::vec4( 0, 0, 0, 1.0f ) );
m_vVertices[1].position = glm::vec2( matrix * glm::vec4( 0, m_size.y, 0, 1.0f ) );
m_vVertices[2].position = glm::vec2( matrix * glm::vec4( m_size.x, 0, 0, 1.0f ) );
m_vVertices[3].position = glm::vec2( matrix * glm::vec4( m_size.x, m_size.y, 0, 1.0f ) );
}
renderBatch();
}
} // render
// ----------------------------------------------------------------------------
// getTextureInfos()
TextureInfo Image2d::getTextureInfo() const {
return m_textureInfo;
} // getTextureInfo
// ----------------------------------------------------------------------------
// setTextureInfo()
void Image2d::setTextureInfo( const TextureInfo& textureInfo ) {
m_textureInfo = textureInfo;
} // setTextureInfo
} // namespace vmk
Now this class has two constructors which will get called depending on which version of the Image2d is being used. If I remember correctly version 1 does not use the BatchManager or Batch Process while version 2 does. If you look at the 1st Constructor. glBindVertexArray( 0 ); and glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, 0 ); glBindBuffer( GL_ARRAY_BUFFER, 0 ); methods are called to stop the arrays and buffers. In render call in the first section of the if statement again we call glBindVertexArray( 0 ); to stop the array.
If you look at the destructor version 2 does not get cleaned up due to the fact that it is being used through the BatchManager and everything that is used through the BatchManager is automatically cleaned up and handled by my AssetStorage class. However, since version 1 of this class does not use the BatchManager it has to clean itself up and you can see the calls to glBindBuffer( BUFFER_ENUMERATED_TYPE, 0 ); followed by a glDeleteBuffers(...); call then setting the VBOs and VAO to 0.
If you would like to know more about this and how to successfully build a 3D Graphics ShaderEngine using modern OpenGL visit http://www.marekknows.com for this is where I have learned how to successfully use OpenGL. These works are not of my own design, but everything in this Engine was manually typed and debugged by following Marek's video tutorials.

DirectX 11.2 triangle shape is distorted by normal vectors

I am new to DirectX. I now have a to some extent silly question.
I am using Windows 8.1 DirectX 11.2 and I am using right-hand coordinate system.
I tried to apply the texture to an equilateral triangle in x-y plane and centred at (0,0,0).
But the output shape is distorted(It doesn't look like equilateral triangle at all!!). And In theory if looking from x-axis, I can see nothing because the equilateral triangle locates in the x-y plane. But it turns out that I can see the triangle. In addition, if I change the value of normal vectors, the output shape changes too! I do not understand why and please help!
Here is the view matrix configuration:
static const XMVECTORF32 eye = { 0.0f, 0.0f, 1.5f, 0.0f };
static const XMVECTORF32 at = { 0.0f, 0.0f, 0.0f, 0.0f };
static const XMVECTORF32 up = { 0.0f, 1.0f, 0.0f, 0.0f };
Here is the vertexshader:
cbuffer ModelViewProjectionConstantBuffer : register(b0)
{
matrix model;
matrix view;
matrix projection;
};
struct VertexShaderInput
{
float3 pos : POSITION;
float3 norm : NORMAL;
float2 tex : TEXCOORD0;
};
struct PixelShaderInput
{
float4 pos : SV_POSITION;
float3 norm : NORMAL;
float2 tex : TEXCOORD0;
};
PixelShaderInput main(VertexShaderInput input)
{
PixelShaderInput vertexShaderOutput;
float4 pos = float4(input.pos, 1.0f);
pos = mul(pos, model);
pos = mul(pos, view);
pos = mul(pos, projection);
vertexShaderOutput.pos = pos;
vertexShaderOutput.tex = input.tex;
vertexShaderOutput.norm = mul(float4(normalize(input.norm), 0.0f), model).xyz;
return vertexShaderOutput;
}
Here is the pixelshader:
Texture2D Texture : register(t0);
SamplerState Sampler : register(s0);
struct PixelShaderInput
{
float4 pos : SV_POSITION;
float3 norm : NORMAL;
float2 tex : TEXCOORD0;
};
float4 main(PixelShaderInput input) : SV_TARGET
{
float3 lightDirection = normalize(float3(0, 0, -1));
return Texture.Sample(Sampler, input.tex); //* (0.8f * saturate(dot(normalize(input.norm), -lightDirection)) + 0.2f);
}
Here is the coordinates:
VertexPositionTexture vertexPositionTexture[] =
{
{ XMFLOAT3(-1.5, -0.5*sqrtf(3), 0.0f), XMFLOAT3(0.0f, 0.0f, 0.4f), XMFLOAT2(0.0, 1.0) },
{ XMFLOAT3(0.0f, sqrtf(3), 0.0f), XMFLOAT3(0.0f, 0.0f, 0.4f), XMFLOAT2(0.5, 0.0) },
{ XMFLOAT3(1.5, -0.5*sqrtf(3), 0.0f), XMFLOAT3(0.0f, 0.0f, 0.4f), XMFLOAT2(1.0, 1.0) },
}
The index array would simply be {0,1,2} in clockwise order.
So if I change the normal vector value in vertexPositionTexture XMFLOAT3(0.0, 0.0, 0.4) to XMFLOAT3(0.0, 0.0, -1), the shape will definitely change. I don't know why?
Here is how I create the DeviceDependentResources:
void TextureSceneRenderer::CreateDeviceDependentResources()
{
// Load shaders asynchronously.
auto loadVSTask = DX::ReadDataAsync(L"TextureVertexShader.cso");
auto loadPSTask = DX::ReadDataAsync(L"TexturePixelShader.cso");
BasicLoader^ loader = ref new BasicLoader(m_deviceResources->GetD3DDevice());
loader->LoadTexture(
L"cat.dds",
&m_texture,
&m_textureSRV
);
// create the sampler
D3D11_SAMPLER_DESC samplerDesc;
ZeroMemory(&samplerDesc, sizeof(D3D11_SAMPLER_DESC));
samplerDesc.Filter = D3D11_FILTER_ANISOTROPIC;
samplerDesc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP;
samplerDesc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP;
samplerDesc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP;
samplerDesc.MipLODBias = 0.0f;
// use 4x on feature level 9.2 and above, otherwise use only 2x
samplerDesc.MaxAnisotropy = 8;
samplerDesc.ComparisonFunc = D3D11_COMPARISON_NEVER;
samplerDesc.BorderColor[0] = 0.0f;
samplerDesc.BorderColor[1] = 0.0f;
samplerDesc.BorderColor[2] = 0.0f;
samplerDesc.BorderColor[3] = 0.0f;
// allow use of all mip levels
samplerDesc.MinLOD = 0;
samplerDesc.MaxLOD = D3D11_FLOAT32_MAX;
DX::ThrowIfFailed(
m_deviceResources->GetD3DDevice()->CreateSamplerState(
&samplerDesc,
&m_sampler)
);
// After the vertex shader file is loaded, create the shader and input layout.
auto createVSTask = loadVSTask.then([this](const std::vector<byte>& fileData) {
DX::ThrowIfFailed(
m_deviceResources->GetD3DDevice()->CreateVertexShader(
&fileData[0],
fileData.size(),
nullptr,
&m_vertexShader
)
);
static const D3D11_INPUT_ELEMENT_DESC vertexDesc[] =
{
{ "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 },
{ "NORMAL", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 },
{ "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 24, D3D11_INPUT_PER_VERTEX_DATA, 0 },
};
DX::ThrowIfFailed(
m_deviceResources->GetD3DDevice()->CreateInputLayout(
vertexDesc,
ARRAYSIZE(vertexDesc),
&fileData[0],
fileData.size(),
&m_inputLayout
)
);
});
// After the pixel shader file is loaded, create the shader and constant buffer.
auto createPSTask = loadPSTask.then([this](const std::vector<byte>& fileData) {
DX::ThrowIfFailed(
m_deviceResources->GetD3DDevice()->CreatePixelShader(
&fileData[0],
fileData.size(),
nullptr,
&m_pixelShader
)
);
CD3D11_BUFFER_DESC constantBufferDesc(sizeof(ModelViewProjectionConstantBuffer), D3D11_BIND_CONSTANT_BUFFER);
DX::ThrowIfFailed(
m_deviceResources->GetD3DDevice()->CreateBuffer(
&constantBufferDesc,
nullptr,
&m_constantBuffer
)
);
});
// Once both shaders are loaded, create the mesh.
auto createCubeTask = (createPSTask && createVSTask).then([this]() {
D3D11_SUBRESOURCE_DATA vertexBufferData = { 0 };
vertexBufferData.pSysMem = this->model->getVertexPositionTexture();
vertexBufferData.SysMemPitch = 0;
vertexBufferData.SysMemSlicePitch = 0;
CD3D11_BUFFER_DESC vertexBufferDesc(sizeof(this->model- >getVertexPositionTexture()[0])*this->model->n_texture_vertex, D3D11_BIND_VERTEX_BUFFER);
DX::ThrowIfFailed(
m_deviceResources->GetD3DDevice()->CreateBuffer(
&vertexBufferDesc,
&vertexBufferData,
&m_vertexBuffer
)
);
m_indexCount = this->model->n_mesh;//ARRAYSIZE(cubeIndices);
D3D11_SUBRESOURCE_DATA indexBufferData = { 0 };
indexBufferData.pSysMem = this->model->getMeshTextureIndex();
indexBufferData.SysMemPitch = 0;
indexBufferData.SysMemSlicePitch = 0;
CD3D11_BUFFER_DESC indexBufferDesc(sizeof(this->model->getMeshTextureIndex()[0])*m_indexCount, D3D11_BIND_INDEX_BUFFER);
DX::ThrowIfFailed(
m_deviceResources->GetD3DDevice()->CreateBuffer(
&indexBufferDesc,
&indexBufferData,
&m_indexBuffer
)
);
});
// Once the cube is loaded, the object is ready to be rendered.
createCubeTask.then([this]() {
m_loadingComplete = true;
});
}
Here is the render function:
void TextureSceneRenderer::Render()
{
// Loading is asynchronous. Only draw geometry after it's loaded.
if (!m_loadingComplete)
{
return;
}
auto context = m_deviceResources->GetD3DDeviceContext();
// Set render targets to the screen.
ID3D11RenderTargetView *const targets[1] = { m_deviceResources->GetBackBufferRenderTargetView() };
context->OMSetRenderTargets(1, targets, m_deviceResources->GetDepthStencilView());
// Prepare the constant buffer to send it to the graphics device.
context->UpdateSubresource(
m_constantBuffer.Get(),
0,
NULL,
&m_constantBufferData,
0,
0
);
// Each vertex is one instance of the VertexPositionColor struct.
UINT stride = sizeof(VertexPositionColor);
UINT offset = 0;
context->IASetVertexBuffers(
0,
1,
m_vertexBuffer.GetAddressOf(),
&stride,
&offset
);
context->IASetIndexBuffer(
m_indexBuffer.Get(),
DXGI_FORMAT_R16_UINT, // Each index is one 16-bit unsigned integer (short).
0
);
context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
context->IASetInputLayout(m_inputLayout.Get());
// Attach our vertex shader.
context->VSSetShader(
m_vertexShader.Get(),
nullptr,
0
);
// Send the constant buffer to the graphics device.
context->VSSetConstantBuffers(
0,
1,
m_constantBuffer.GetAddressOf()
);
// Attach our pixel shader.
context->PSSetShader(
m_pixelShader.Get(),
nullptr,
0
);
context->PSSetShaderResources(
0,
1,
m_textureSRV.GetAddressOf()
);
context->PSSetSamplers(
0, // starting at the first sampler slot
1, // set one sampler binding
m_sampler.GetAddressOf()
);
// Draw the objects.
context->DrawIndexed(
m_indexCount,
0,
0
);
}

Creating SpaceBattle: bottlenecks (~100 polygons, 200 FPS), optimization

I just started with DirectX learning and decided to write a simple classic game: SpaceBattle. But now I have some performance problems mainly related to Render (I guess not to Update). As a result: I have 150-200 FPS with maximum 80-100 polygons. If I comment Render method, FPS grows up to 2500-3000. So here is my Render method:
void DX11Game::Render()
{
if( d3dContext_ == 0 )
return;
stride = sizeof( VertexPT );
offset = 0;
d3dContext_->IASetInputLayout(inputLayout);
d3dContext_->IASetVertexBuffers(0, 1, &vertexBuffer, &stride, &offset);
d3dContext_->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
d3dContext_->VSSetShader(VS, 0, 0);
d3dContext_->PSSetShader(PS, 0, 0);
d3dContext_->PSSetSamplers(0, 1, &samplerState);
d3dContext_->VSSetConstantBuffers(0, 1, &cbMatricesBuffer);
d3dContext_->PSSetConstantBuffers(1, 1, &cbParametersBuffer);
switch (DX11Game::gameState)
{
case GAME_STATE::GAME_STATE_PLAY:
d3dContext_->ClearRenderTargetView(backBufferTarget_, backColor);
DrawAsteroids();
DrawShip();
DrawUserBullets();
DrawEnemies();
DrawGUI();
break;
case GAME_STATE::GAME_STATE_GAMEOVER:
d3dContext_->ClearRenderTargetView(backBufferTarget_, backColor);
DrawAsteroids();
DrawShip();
DrawUserBullets();
DrawGameOver();
break;
case GAME_STATE::GAME_STATE_SCORES:
break;
}
swapChain_->Present(0, 0);
}
And here is one of the methods that draws game objects. Others Draws is similar to this:
void DX11Game::DrawAsteroids()
{
std::vector<std::shared_ptr<Asteroid>>* asteroids = gameLogic->GetAsteroids();
std::vector<std::shared_ptr<Asteroid>>::iterator it = asteroids->begin();
while (it != asteroids->end())
{
float SIZE = *((*it)->GetSize());
float* temp = (*it)->GetTexCoord();
XMFLOAT4 texBounds = XMFLOAT4( temp[0], temp[1], temp[2], temp[3] );
vertices[0].pos = XMFLOAT3( SIZE, SIZE, 1.0f );
vertices[0].tex0 = XMFLOAT2( texBounds.x + texBounds.z, texBounds.y );
vertices[1].pos = XMFLOAT3( SIZE, -SIZE, 1.0f );
vertices[1].tex0 = XMFLOAT2( texBounds.x + texBounds.z, texBounds.y + texBounds.w );
vertices[2].pos = XMFLOAT3( -SIZE, -SIZE, 1.0f );
vertices[2].tex0 =XMFLOAT2( texBounds.x,texBounds.y + texBounds.w );
vertices[3].pos = XMFLOAT3( -SIZE, -SIZE, 1.0f );
vertices[3].tex0 =XMFLOAT2( texBounds.x, texBounds.y + texBounds.w );
vertices[4].pos = XMFLOAT3( -SIZE, SIZE, 1.0f );
vertices[4].tex0 = XMFLOAT2( texBounds.x, texBounds.y );
vertices[5].pos = XMFLOAT3( SIZE, SIZE, 1.0f );
vertices[5].tex0 =XMFLOAT2( texBounds.x +texBounds.z, texBounds.y );
XMMATRIX world = XMMatrixTranslation(
( *it )->GetPosition()[0],
( *it )->GetPosition()[1],
0.0f );
world = XMMatrixTranspose(world);
d3dContext_->PSSetShaderResources(0, 1, &texGameSprites);
d3dContext_->UpdateSubresource(vertexBuffer, 0, 0, vertices, 0, 0);
CB_Matrices matrices;
matrices.World = world;
matrices.Projection = proj;
d3dContext_->UpdateSubresource(cbMatricesBuffer, 0, 0, &matrices, 0, 0);
CB_Parameters params;
params.isTextured = true;
params.color[0] = 1.0f; params.color[1] = 1.0f;
params.color[2] = 0.0f; params.color[3] = 1.0f;
d3dContext_->UpdateSubresource(cbParametersBuffer, 0, 0, &params, 0, 0);
d3dContext_->Draw(6, 0);
it++;
}
}
So what I have to do to optimize my game?
Thanks!

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

Conditional operator in HLSL's pass

According to
http://msdn.microsoft.com/en-us/library/windows/desktop/bb509610(v=vs.85).aspx
HLSL supports conditional operator (since version 2.0? I am using 4_0)
I need to set blending state before each Draw call. In FX file I'm doing this:
BlendState BlendNone
{
AlphaToCoverageEnable = FALSE;
BlendEnable[0] = FALSE;
};
BlendState BlendSrcAlphaOne
{
BlendEnable[0] = TRUE;
SrcBlend = SRC_ALPHA;
DestBlend = INV_SRC_ALPHA;
BlendOp = ADD;
RenderTargetWriteMask[0] = 0x0F;
};
BlendState BlendSrcAlphaOneMinusSrcAlpha
{
BlendEnable[0] = TRUE;
SrcBlend = SRC_ALPHA;
DestBlend = ONE;
BlendOp = ADD;
RenderTargetWriteMask[0] = 0x0F;
};
int g_Blend;
technique10 Render
{
pass P0
{
SetVertexShader( CompileShader( vs_4_0, VS() ) );
SetGeometryShader( CompileShader( gs_4_0, GS() ) );
SetPixelShader( CompileShader( ps_4_0, PS() ) );
SetRasterizerState(rsCullNone);
SetDepthStencilState( EnableDepth, 0 );
if (g_Blend == 0)
{
SetBlendState( BlendNone, float4( 0.0f, 0.0f, 0.0f, 0.0f ), 0xFFFFFFFF );
}
else if (g_Blend == 1)
{
SetBlendState( BlendSrcAlphaOne, float4( 0.0f, 0.0f, 0.0f, 0.0f ), 0xFFFFFFFF );
}
else if (g_Blend == 2)
{
SetBlendState( BlendSrcAlphaOneMinusSrcAlpha, float4( 0.0f, 0.0f, 0.0f, 0.0f ), 0xFFFFFFFF );
}
}
}
This does not compile with error:
error X3000: syntax error: unexpected token 'if'
If I move the whole block into a separate function like:
void setBlend()
{
if (g_Blend == 0)
{
SetBlendState( BlendNone, float4( 0.0f, 0.0f, 0.0f, 0.0f ), 0xFFFFFFFF );
}
else if (g_Blend == 1)
{
SetBlendState( BlendSrcAlphaOne, float4( 0.0f, 0.0f, 0.0f, 0.0f ), 0xFFFFFFFF );
}
else if (g_Blend == 2)
{
SetBlendState( BlendSrcAlphaOneMinusSrcAlpha, float4( 0.0f, 0.0f, 0.0f, 0.0f ), 0xFFFFFFFF );
}
}
technique10 Render
{
pass P0
{
SetVertexShader( CompileShader( vs_4_0, VS() ) );
SetGeometryShader( CompileShader( gs_4_0, GS() ) );
SetPixelShader( CompileShader( ps_4_0, PS() ) );
SetRasterizerState(rsCullNone);
SetDepthStencilState( EnableDepth, 0 );
setBlend();
}
}
it doesn't compile with error:
error X3000: this FX API is not available in this part your program (SetBlendState)
So, is if supported in HLSL?
Ok, after lots of attempts and reading
http://msdn.microsoft.com/en-us/library/windows/desktop/bb205052(v=vs.85).aspx#Blend
This compiles:
BlendState blendStates[3]
{
{
AlphaToCoverageEnable = FALSE;
BlendEnable[0] = FALSE;
},
{
BlendEnable[0] = TRUE;
SrcBlend = SRC_ALPHA;
DestBlend = INV_SRC_ALPHA;
BlendOp = ADD;
RenderTargetWriteMask[0] = 0x0F;
},
{
BlendEnable[0] = TRUE;
SrcBlend = SRC_ALPHA;
DestBlend = ONE;
BlendOp = ADD;
RenderTargetWriteMask[0] = 0x0F;
}
};
int g_Blend;
technique10 Render
{
pass P0
{
SetVertexShader( CompileShader( vs_4_0, VS() ) );
SetGeometryShader( CompileShader( gs_4_0, GS() ) );
SetPixelShader( CompileShader( ps_4_0, PS() ) );
SetRasterizerState(rsCullNone);
SetDepthStencilState( EnableDepth, 0 );
SetBlendState( blendStates[g_Blend], float4( 0.0f, 0.0f, 0.0f, 0.0f ), 0xFFFFFFFF );
}
}
SetBlendState is not strictly a function call and conditional operators are not allowed inside the pass {}. However it's allowed to pass array of state objects with index instead of just state objects.