I have been trying to add a particle system to my Directx11 graphics demo, and so i have been using the 'Introduction to 3d Game Programming with directx 11' book.
Because of this am attempting to use a HLSL StreamOut technique to update the particle system and a separate technique to render the particles.
Below is the HLSL code for the particle system, i have tried adjusting the acceleration and velocity in the off chance the speed was sending the particles off the screen, however this had no effect.
cbuffer cbPerFrame
{
float3 gEyePosW;
float3 gEmitPosW;
float3 gEmitDirW;
float gGameTime;
float gTimeStep;
float4x4 gViewProj;
};
cbuffer cbFixed
{
// Net constant acceleration used to accerlate the particles.
float3 gAccelW = {0.0f, 0.2f, 0.0f};
// Texture coordinates for billbording are always the same - we use a qquad in this effect :)
float2 gTexC[4] =
{
float2(0.0f, 1.0f),
float2(0.0f, 0.0f),
float2(1.0f, 1.0f),
float2(1.0f, 0.0f)
};
};
// Nonnumeric values cannot be added to a cbuffer.
Texture2DArray gTextureMapArray;
// Random texture used to generate random numbers in shaders.
Texture1D gRandomTexture;
SamplerState samLinear
{
Filter = MIN_MAG_MIP_LINEAR;
AddressU = WRAP;
AddressV = WRAP;
};
DepthStencilState DisableDepth
{
DepthEnable = FALSE;
DepthWriteMask = ZERO;
};
DepthStencilState NoDepthWrites
{
DepthEnable = TRUE;
DepthWriteMask = ZERO;
};
BlendState AdditiveBlending
{
AlphaToCoverageEnable = FALSE;
BlendEnable[0] = TRUE;
SrcBlend = SRC_ALPHA;
DestBlend = ONE;
BlendOp = ADD;
SrcBlendAlpha = ZERO;
DestBlendAlpha = ZERO;
BlendOpAlpha = ADD;
RenderTargetWriteMask[0] = 0x0F;
};
///////////////////////////////////////////////////////////////
// Helper functions
//
///////////////////////////////////////////////////////////////
float3 RandUnitVec3(float offset)
{
// Use game time plus offset to sample random texture.
float u = (gGameTime + offset);
// coordinates in [-1,1]
float3 v = gRandomTexture.SampleLevel(samLinear, u, 0).xyz;
// project onto unit sphere (Normalize)
return normalize(v);
}
///////////////////////////////////////////////////////////////
// Stream Out Technique
//
///////////////////////////////////////////////////////////////
#define PT_EMITTER 0
#define PT_FLARE 1
struct Particle
{
float3 InitPosW : POSITION;
float3 InitVelW : VELOCITY;
float2 SizeW : SIZE;
float Age : AGE;
uint Type : Type;
};
Particle StreamOutVS(Particle vin)
{
return vin;
}
// The stream-out GS is just responsible for emitting
// new particles and destroying old particles. The logic
// programed here will generally vary from particle system
// to particle system, as the destroy/spawn rules will be
// different.
[maxvertexcount(2)]
void StreamOutGS(point Particle gin[1],
inout PointStream<Particle> ptStream)
{
gin[0].Age += gTimeStep;
// if particle is emitter particle
if (gin[0].Type == PT_EMITTER)
{
// If it's time to emit new particle
if (gin[0].Age > 0.005f)
{
float3 vRandom = RandUnitVec3(0.0f);
vRandom.x *= 0.5f;
vRandom.z *= 0.5f;
Particle p;
p.InitPosW = gEmitPosW.xyz;
p.InitVelW = 0.5f*vRandom;
p.SizeW = float2(3.0f, 3.0f);
p.Age = 0.0f;
p.Type = PT_FLARE;
ptStream.Append(p);
// reset the time to emit
gin[0].Age = 0.0f;
}
// always keep emitters
ptStream.Append(gin[0]);
}
else
{
// Set conditions to keep a particle - in this case age limit
if (gin[0].Age <= 1.0f)
{
ptStream.Append(gin[0]);
}
}
}
GeometryShader gsStreamOut = ConstructGSWithSO(
CompileShader( gs_5_0, StreamOutGS() ),
"POSITION.xyz; VELOCITY.xyz; SIZE.xyz; AGE.x; TYPE.x" );
technique11 StreamOutTech
{
pass P0
{
SetVertexShader( CompileShader( vs_5_0, StreamOutVS() ) );
SetGeometryShader( gsStreamOut );
// disable pixel shader for stream-out only
SetPixelShader(NULL);
// we must also disable the depth buffer for stream-out only
SetDepthStencilState( DisableDepth, 0 );
}
}
///////////////////////////////////////////////////////////////
// Draw Technique
//
///////////////////////////////////////////////////////////////
struct VertexIn
{
float3 Pos : POSITION;
float2 SizeW : SIZE;
};
struct VertexOut
{
float3 PosW : POSITION;
float2 SizeW : SIZE;
float4 Colour : COLOR;
uint Type : TYPE;
};
VertexOut DrawVS(Particle vin)
{
VertexOut vout;
float t = vin.Age;
// constant Acceleration equation
vout.PosW = 0.5f*t*t*gAccelW + t*vin.InitVelW + vin.InitPosW;
// fade colour with time
float opacity = 1.0f - smoothstep(0.0f, 1.0f, t/1.0f);
vout.Colour = float4(1.0f, 1.0f, 1.0f, opacity);
vout.SizeW = vin.SizeW;
vout.Type = vin.Type;
return vout;
}
struct GeoOut
{
float4 PosH : SV_POSITION;
float4 Colour : COLOR;
float2 Tex : TEXCOORD;
};
// Expand each 'Point' into a quad (4 verticies)
[maxvertexcount(4)]
void DrawGS(point VertexOut gin[1],
inout TriangleStream<GeoOut> triStream)
{
// Do not draw Emiter particles in this system
if (gin[0].Type != PT_EMITTER)
{
//
// Compute world matrix so that billboard faces the camera.
//
float3 look = normalize(gEyePosW.xyz - gin[0].PosW);
float3 right = normalize(cross(float3(0,1,0), look));
float3 up = cross(look, right);
//
// Compute triangle strip vertices (quad) in world space.
//
float halfWidth = 0.5f*gin[0].SizeW.x;
float halfHeight = 0.5f*gin[0].SizeW.y;
float4 v[4];
v[0] = float4(gin[0].PosW + halfWidth*right - halfHeight*up, 1.0f);
v[1] = float4(gin[0].PosW + halfWidth*right + halfHeight*up, 1.0f);
v[2] = float4(gin[0].PosW - halfWidth*right - halfHeight*up, 1.0f);
v[3] = float4(gin[0].PosW - halfWidth*right + halfHeight*up, 1.0f);
//
// Transform quad vertices to world space and output
// them as a triangle strip.
//
GeoOut gout;
[unroll]
for(int i = 0; i < 4; ++i)
{
gout.PosH = mul(v[i], gViewProj);
gout.Tex = gTexC[i];
gout.Colour = gin[0].Colour;
triStream.Append(gout);
}
}
}
float DrawPS(GeoOut pin) : SV_TARGET
{
return gTextureMapArray.Sample(samLinear, float3(pin.Tex, 0)) * pin.Colour;
}
technique11 DrawTech
{
pass P0
{
SetVertexShader( CompileShader( vs_5_0, DrawVS() ) );
SetGeometryShader( CompileShader( gs_5_0, DrawGS() ) );
SetPixelShader( CompileShader( ps_5_0, DrawPS() ) );
SetBlendState(AdditiveBlending, float4(0.0f, 0.0f, 0.0f, 0.0f), 0xffffffff);
SetDepthStencilState( NoDepthWrites, 0 );
}
}
Below is the code for building the VB.
void ParticleSystem::BuildVB(ID3D11Device* device)
{
/////////////////////////////////////////////////////////
// Create the buffer to start the particle system.
/////////////////////////////////////////////////////////
D3D11_BUFFER_DESC vbd;
vbd.Usage = D3D11_USAGE_DEFAULT;
vbd.ByteWidth = sizeof(Vertex::Particle) * 1;
vbd.BindFlags = D3D11_BIND_VERTEX_BUFFER;
vbd.CPUAccessFlags = 0;
vbd.MiscFlags = 0;
vbd.StructureByteStride = 0;
// The initial particle emitter has type 0 and age 0. The rest
// of the particle attributes do not apply to an emitter.
Vertex::Particle p;
ZeroMemory(&p, sizeof(Vertex::Particle));
p.Age = 0.0f;
p.Type = 0;
D3D11_SUBRESOURCE_DATA vinitData;
vinitData.pSysMem = &p;
HR(device->CreateBuffer(&vbd, &vinitData, &mInitVB));
//////////////////////////////////////////////////////////////
// Create the buffers which swap back and forth for stream-out and drawing.
//////////////////////////////////////////////////////////////
vbd.ByteWidth = sizeof(Vertex::Particle) * mMaxParticles;
vbd.BindFlags = D3D11_BIND_VERTEX_BUFFER | D3D11_BIND_STREAM_OUTPUT;
HR(device->CreateBuffer(&vbd, 0, &mDrawVB));
HR(device->CreateBuffer(&vbd, 0, &mStreamOutVB));
}
And now the Draw cpp code.
void ParticleSystem::Draw(ID3D11DeviceContext* dc, const XMMATRIX& viewProj)
{
//
// Set constants.
//
mFX->SetViewProj(viewProj);
mFX->SetGameTime(mGameTime);
mFX->SetTimeStep(mTimeStep);
mFX->SetEyePosW(mEyePosW);
mFX->SetEmitPosW(mEmitPosW);
mFX->SetEmitDirW(mEmitDirW);
mFX->SetTexArray(mTextureArraySRV);
mFX->SetRandomTex(mRandomTextureSRV);
//
// Set IA stage.
//
dc->IASetInputLayout(InputLayouts::Particle);
dc->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_POINTLIST);
UINT stride = sizeof(Vertex::Particle);
UINT offset = 0;
// On the first pass, use the initialization VB. Otherwise, use
// the VB that contains the current particle list.
if( mFirstRun )
dc->IASetVertexBuffers(0, 1, &mInitVB, &stride, &offset);
else
dc->IASetVertexBuffers(0, 1, &mDrawVB, &stride, &offset);
//
// Draw the current particle list using stream-out only to update them.
// The updated vertices are streamed-out to the target VB.
//
dc->SOSetTargets(1, &mStreamOutVB, &offset);
D3DX11_TECHNIQUE_DESC techDesc;
mFX->StreamOutTech->GetDesc( &techDesc );
for(UINT p = 0; p < techDesc.Passes; ++p)
{
mFX->StreamOutTech->GetPassByIndex( p )->Apply(0, dc);
if(mFirstRun)
{
dc->Draw(1, 0);
mFirstRun = false;
}
else
{
dc->DrawAuto();
}
}
// done streaming-out--unbind the vertex buffer
ID3D11Buffer* bufferArray[1] = {0};
dc->SOSetTargets(1, bufferArray, &offset);
// ping-pong the vertex buffers
std::swap(mDrawVB, mStreamOutVB);
//
// Draw the updated particle system we just streamed-out.
//
dc->IASetVertexBuffers(0, 1, &mDrawVB, &stride, &offset);
mFX->DrawTech->GetDesc( &techDesc );
for(UINT p = 0; p < techDesc.Passes; ++p)
{
mFX->DrawTech->GetPassByIndex( p )->Apply(0, dc);
dc->DrawAuto();
}
}
I had thought that perhaps either a blend state or Depth state in use by some of the other objects in my scene may be causing the issue, (perhaps i have misunderstood something I have set earlier). I tried removing all other render code leaving just the draw code above, but with no results.
To my mind, I can only think of a few possible causes for the issue i am having, but so far i am unable to find a solution.
The scale of the system is wrong for my scene. eg. the particles are drawing but are moving off the screen to fast to be seen.
As mentioned above i have tried removing the acceleration and velocity of the particles in the HLSL code, in order to see stationary particles. This had no effect.
Blend state/Depth stencil state is incorrect. Eg. As mentioned above.
The Emitter particle is, for some reason, not being produced/placed correctly. causing no 'drawable' particles to be produced in turn.
As most of this code is in the .fx file, I am unable to step through to check the emitter particles. I think this is the more likely issue, but i have been wrong before.
Any help on this would be greatly appreciated, I am well and truly stuck on this.
Below I have added additional snippets of code which may be of use.
E.G. Input layout.
const D3D11_INPUT_ELEMENT_DESC InputLayoutDesc::Particle[5] =
{
{"POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0},
{"VELOCITY", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0},
{"SIZE", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 24, D3D11_INPUT_PER_VERTEX_DATA, 0},
{"AGE", 0, DXGI_FORMAT_R32_FLOAT, 0, 32, D3D11_INPUT_PER_VERTEX_DATA, 0},
{"TYPE", 0, DXGI_FORMAT_R32_UINT, 0, 36, D3D11_INPUT_PER_VERTEX_DATA, 0},
};
And particle system INIT
mFire.Init(md3dDevice, AppEffects::FireFX, mFlareTextureSRV, mRandomTextureSRV, 500);
mFire.SetEmitPos(XMFLOAT3(1.0f, 0.5f, 0.0f));
void ParticleSystem::Init(ID3D11Device* device, ParticleEffect* fx,
ID3D11ShaderResourceView* textureArraySRV,
ID3D11ShaderResourceView* randomTextureSRV,
UINT maxParticles)
{
mMaxParticles = maxParticles;
mFX = fx;
mTextureArraySRV = textureArraySRV;
mRandomTextureSRV = randomTextureSRV;
BuildVB(device);
}
If i have missed any section of the code you would need to see, let me know.
Thanks in advance.
Sorry about this stupid question all. Turns out it was a stupid mistake in the pixel shader. I had set the pixel shader as a float instead of float4.
Related
I am currently working on an project but my problem is that my Vertex shader gets the wrong data, so my position values aren't any longer the same as i set them at the beginning.
So this is where I define the position/anchor of my Sprite
struct SpriteVertex
{
DirectX::XMFLOAT3 position;
float radius;
int textureIndex;
};
//Sprite renderer
vector<SpriteVertex> sprite_vertices;
SpriteVertex current;
current.position.x = 0;
current.position.y = 0;
current.position.z = 0;
current.radius = 100;
current.textureIndex = 0;
sprite_vertices.push_back(current);
g_SpriteRenderer->renderSprites(pd3dImmediateContext, sprite_vertices, g_camera);
So in my SpriteRenderer Class I have the create method where I set up the Input layout and create an empty vertex buffer.
HRESULT SpriteRenderer::create(ID3D11Device* pDevice)
{
cout << "Spriterender Create has been called" << endl;
HRESULT hr;
D3D11_BUFFER_DESC bd;
ZeroMemory(&bd, sizeof(bd));
bd.Usage = D3D11_USAGE_DEFAULT;
bd.ByteWidth = 1024 * sizeof(SpriteVertex);
bd.BindFlags = D3D11_BIND_SHADER_RESOURCE;
bd.CPUAccessFlags = 0;
bd.MiscFlags = 0;
V(pDevice->CreateBuffer(&bd , nullptr, &m_pVertexBuffer));
const D3D11_INPUT_ELEMENT_DESC layout[] ={
{ "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_VERTEX_DATA, 0 },
{ "RADIUS", 0, DXGI_FORMAT_R32_FLOAT, 0, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_VERTEX_DATA, 0 },
{ "TEXTUREINDEX",0,DXGI_FORMAT_R32_SINT,0,D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_VERTEX_DATA, 0 }
};
UINT numEements = sizeof(layout) / sizeof(layout[0]);
D3DX11_PASS_DESC pd;
V_RETURN(m_pEffect->GetTechniqueByName("Render")->GetPassByName("SpritePass")->GetDesc(&pd));
V_RETURN(pDevice->CreateInputLayout(layout, numEements, pd.pIAInputSignature, pd.IAInputSignatureSize, &m_pInputLayout));
return S_OK;
}
And I have the render method which fills the buffer and is supposed to render it with the shader I coded:
void SpriteRenderer::renderSprites(ID3D11DeviceContext* context, const std::vector<SpriteVertex>& sprites, const CFirstPersonCamera& camera)
{
//cout << "SpriterenderrenderSprites has been called" << endl;
D3D11_BOX box;
box.left = 0; box.right = sprites.size()*sizeof(SpriteVertex);
box.top = 0; box.bottom = 1;
box.front = 0; box.back = 1;
context->UpdateSubresource(m_pVertexBuffer,0,&box,&sprites[0],0,0);
const UINT size = sizeof(SpriteVertex);
context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_POINTLIST);
context->IASetInputLayout(m_pInputLayout);
context->IASetVertexBuffers(0, 0, &m_pVertexBuffer, &size, nullptr);
//setting shader resouirces
DirectX::XMMATRIX worldviewProj =camera.GetViewMatrix()*camera.GetProjMatrix();
m_pEffect->GetVariableByName("g_ViewProjection")->AsMatrix()->SetMatrix(( float* ) &worldviewProj);
m_pEffect->GetVariableByName("g_cameraRight")->AsVector()->SetFloatVector((float*) &camera.GetWorldRight());
m_pEffect->GetVariableByName("g_cameraUP")->AsVector()->SetFloatVector((float*)&camera.GetWorldUp());
m_pEffect->GetTechniqueByName("Render")->GetPassByName("SpritePass")->Apply( 0,context);
context->Draw(size,0);
}
So my big problem is that when I debug the Shaders that my inital Position radius and so on aren't even close to what I want:
Debug VS
I'm trying to fix this now for ever any help would be really appreciated.
EDIT: HLSL Code might help ;=)
//--------------------------------------------------------------------------------------
// Shader resources
//--------------------------------------------------------------------------------------
//--------------------------------------------------------------------------------------
// Constant buffers
//--------------------------------------------------------------------------------------
cbuffer cbCOnstant
{
matrix g_ViewProjection;
float4 g_cameraRight;
float4 g_cameraUP;
};
//--------------------------------------------------------------------------------------
// Structs
//--------------------------------------------------------------------------------------
struct SpriteVertex
{
float3 POSITION : POSITION;
float RADIUS: RADIUS;
int TEXIN : TEXTUREINDEX;
};
struct PSVertex
{
float4 POSITION : SV_Position;
int TEXIN : TEXTUREINDEX;
};
//--------------------------------------------------------------------------------------
// Rasterizer states
//--------------------------------------------------------------------------------------
RasterizerState rsCullNone
{
CullMode = None;
};
//--------------------------------------------------------------------------------------
// DepthStates
//--------------------------------------------------------------------------------------
DepthStencilState EnableDepth
{
DepthEnable = TRUE;
DepthWriteMask = ALL;
DepthFunc = LESS_EQUAL;
};
BlendState NoBlending
{
AlphaToCoverageEnable = FALSE;
BlendEnable[0] = FALSE;
};
//--------------------------------------------------------------------------------------
// Shaders
//--------------------------------------------------------------------------------------
SpriteVertex DummyVS(SpriteVertex Input)
{
return Input;
}
[maxvertexcount(4)]
void SpriteGS(point SpriteVertex vertex[1], inout TriangleStream<PSVertex> stream){
PSVertex input;
input.TEXIN = vertex[0].TEXIN;
//bottom left
input.POSITION = mul(float4(vertex[0].POSITION,1) - vertex[0].RADIUS * g_cameraRight - vertex[0].RADIUS * g_cameraUP, g_ViewProjection);
stream.Append(input);
//top left
input.POSITION = mul(float4(vertex[0].POSITION,1) - vertex[0].RADIUS * g_cameraRight + vertex[0].RADIUS * g_cameraUP, g_ViewProjection);
stream.Append(input);
//top right
input.POSITION = mul(float4(vertex[0].POSITION,1) + vertex[0].RADIUS * g_cameraRight + vertex[0].RADIUS * g_cameraUP, g_ViewProjection);
stream.Append(input);
//bot right
input.POSITION = mul(float4(vertex[0].POSITION,1) + vertex[0].RADIUS * g_cameraRight - vertex[0].RADIUS * g_cameraUP, g_ViewProjection);
stream.Append(input);
}
float4 DummyPS(PSVertex input) : SV_Target0
{
return float4(1, 1, 0, 1);
}
//--------------------------------------------------------------------------------------
// Techniques
//--------------------------------------------------------------------------------------
technique11 Render
{
pass SpritePass
{
SetVertexShader(CompileShader(vs_5_0, DummyVS()));
SetGeometryShader(CompileShader(gs_5_0, SpriteGS()));
SetPixelShader(CompileShader(ps_5_0, DummyPS()));
SetRasterizerState(rsCullNone);
SetDepthStencilState(EnableDepth,0);
SetBlendState(NoBlending, float4(0.0f, 0.0f, 0.0f, 0.0f), 0xFFFFFFFF);
}
}
Your binding of the vertex buffer below is wrong :
context->IASetVertexBuffers(0, 0, &m_pVertexBuffer, &size, nullptr);
The seconde arguments of ID3D11DeviceContext::IASetVertexBuffers is the number of buffer to bind, it has to be one here, and offsets has to be valid :
UINT offset = 0;
context->IASetVertexBuffers(0, 1, &m_pVertexBuffer, &size, &offset);
As a general advice, you should turn on the debug device at creation with the flag D3D11_CREATE_DEVICE_DEBUG and look for any message in the output. On windows 10, you may have to install it first following Microsoft instructions installing the debug device
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
);
}
I am following an example book called: Introduction to 3D Game Programming with DirectX 11
It is all written in VS2010. I would like to try using VS2013... It is an example project for Windows Desktop Program
I have a program with the following in it (including some other files as part of common use):
color.fx
//***************************************************************************************
// color.fx by Frank Luna (C) 2011 All Rights Reserved.
//
// Transforms and colors geometry.
//***************************************************************************************
cbuffer cbPerObject
{
float4x4 gWorldViewProj;
};
struct VertexIn
{
float3 PosL : POSITION;
float4 Color : COLOR;
};
struct VertexOut
{
float4 PosH : SV_POSITION;
float4 Color : COLOR;
};
VertexOut VS(VertexIn vin)
{
VertexOut vout;
// Transform to homogeneous clip space.
vout.PosH = mul(float4(vin.PosL, 1.0f), gWorldViewProj);
// Just pass vertex color into the pixel shader.
vout.Color = vin.Color;
return vout;
}
float4 PS(VertexOut pin) : SV_Target
{
return pin.Color;
}
technique11 ColorTech
{
pass P0
{
SetVertexShader( CompileShader( vs_5_0, VS() ) );
SetGeometryShader( NULL );
SetPixelShader( CompileShader( ps_5_0, PS() ) );
}
}
BoxDemo.cpp
//***************************************************************************************
// BoxDemo.cpp by Frank Luna (C) 2011 All Rights Reserved.
//
// Demonstrates rendering a colored box.
//
// Controls:
// Hold the left mouse button down and move the mouse to rotate.
// Hold the right mouse button down to zoom in and out.
//
//***************************************************************************************
#include "d3dApp.h"
#include "d3dx11Effect.h"
#include "MathHelper.h"
struct Vertex
{
XMFLOAT3 Pos;
XMFLOAT4 Color;
};
class BoxApp : public D3DApp
{
public:
BoxApp(HINSTANCE hInstance);
~BoxApp();
bool Init();
void OnResize();
void UpdateScene(float dt);
void DrawScene();
void OnMouseDown(WPARAM btnState, int x, int y);
void OnMouseUp(WPARAM btnState, int x, int y);
void OnMouseMove(WPARAM btnState, int x, int y);
private:
void BuildGeometryBuffers();
void BuildFX();
void BuildVertexLayout();
private:
ID3D11Buffer* mBoxVB;
ID3D11Buffer* mBoxIB;
ID3DX11Effect* mFX;
ID3DX11EffectTechnique* mTech;
ID3DX11EffectMatrixVariable* mfxWorldViewProj;
ID3D11InputLayout* mInputLayout;
XMFLOAT4X4 mWorld;
XMFLOAT4X4 mView;
XMFLOAT4X4 mProj;
float mTheta;
float mPhi;
float mRadius;
POINT mLastMousePos;
};
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE prevInstance,
PSTR cmdLine, int showCmd)
{
// Enable run-time memory check for debug builds.
#if defined(DEBUG) | defined(_DEBUG)
_CrtSetDbgFlag( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF );
#endif
BoxApp theApp(hInstance);
if( !theApp.Init() )
return 0;
return theApp.Run();
}
BoxApp::BoxApp(HINSTANCE hInstance)
: D3DApp(hInstance), mBoxVB(0), mBoxIB(0), mFX(0), mTech(0),
mfxWorldViewProj(0), mInputLayout(0),
mTheta(1.5f*MathHelper::Pi), mPhi(0.25f*MathHelper::Pi), mRadius(5.0f)
{
mMainWndCaption = L"Box Demo";
mLastMousePos.x = 0;
mLastMousePos.y = 0;
XMMATRIX I = XMMatrixIdentity();
XMStoreFloat4x4(&mWorld, I);
XMStoreFloat4x4(&mView, I);
XMStoreFloat4x4(&mProj, I);
}
BoxApp::~BoxApp()
{
ReleaseCOM(mBoxVB);
ReleaseCOM(mBoxIB);
ReleaseCOM(mFX);
ReleaseCOM(mInputLayout);
}
bool BoxApp::Init()
{
if(!D3DApp::Init())
return false;
BuildGeometryBuffers();
BuildFX();
BuildVertexLayout();
return true;
}
void BoxApp::OnResize()
{
D3DApp::OnResize();
// The window resized, so update the aspect ratio and recompute the projection matrix.
XMMATRIX P = XMMatrixPerspectiveFovLH(0.25f*MathHelper::Pi, AspectRatio(), 1.0f, 1000.0f);
XMStoreFloat4x4(&mProj, P);
}
void BoxApp::UpdateScene(float dt)
{
// Convert Spherical to Cartesian coordinates.
float x = mRadius*sinf(mPhi)*cosf(mTheta);
float z = mRadius*sinf(mPhi)*sinf(mTheta);
float y = mRadius*cosf(mPhi);
// Build the view matrix.
XMVECTOR pos = XMVectorSet(x, y, z, 1.0f);
XMVECTOR target = XMVectorZero();
XMVECTOR up = XMVectorSet(0.0f, 1.0f, 0.0f, 0.0f);
XMMATRIX V = XMMatrixLookAtLH(pos, target, up);
XMStoreFloat4x4(&mView, V);
}
void BoxApp::DrawScene()
{
md3dImmediateContext->ClearRenderTargetView(mRenderTargetView, reinterpret_cast<const float*>(&Colors::LightSteelBlue));
md3dImmediateContext->ClearDepthStencilView(mDepthStencilView, D3D11_CLEAR_DEPTH|D3D11_CLEAR_STENCIL, 1.0f, 0);
md3dImmediateContext->IASetInputLayout(mInputLayout);
md3dImmediateContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
UINT stride = sizeof(Vertex);
UINT offset = 0;
md3dImmediateContext->IASetVertexBuffers(0, 1, &mBoxVB, &stride, &offset);
md3dImmediateContext->IASetIndexBuffer(mBoxIB, DXGI_FORMAT_R32_UINT, 0);
// Set constants
XMMATRIX world = XMLoadFloat4x4(&mWorld);
XMMATRIX view = XMLoadFloat4x4(&mView);
XMMATRIX proj = XMLoadFloat4x4(&mProj);
XMMATRIX worldViewProj = world*view*proj;
mfxWorldViewProj->SetMatrix(reinterpret_cast<float*>(&worldViewProj));
D3DX11_TECHNIQUE_DESC techDesc;
mTech->GetDesc( &techDesc );
for(UINT p = 0; p < techDesc.Passes; ++p)
{
mTech->GetPassByIndex(p)->Apply(0, md3dImmediateContext);
// 36 indices for the box.
md3dImmediateContext->DrawIndexed(36, 0, 0);
}
HR(mSwapChain->Present(0, 0));
}
void BoxApp::OnMouseDown(WPARAM btnState, int x, int y)
{
mLastMousePos.x = x;
mLastMousePos.y = y;
SetCapture(mhMainWnd);
}
void BoxApp::OnMouseUp(WPARAM btnState, int x, int y)
{
ReleaseCapture();
}
void BoxApp::OnMouseMove(WPARAM btnState, int x, int y)
{
if( (btnState & MK_LBUTTON) != 0 )
{
// Make each pixel correspond to a quarter of a degree.
float dx = XMConvertToRadians(0.25f*static_cast<float>(x - mLastMousePos.x));
float dy = XMConvertToRadians(0.25f*static_cast<float>(y - mLastMousePos.y));
// Update angles based on input to orbit camera around box.
mTheta += dx;
mPhi += dy;
// Restrict the angle mPhi.
mPhi = MathHelper::Clamp(mPhi, 0.1f, MathHelper::Pi-0.1f);
}
else if( (btnState & MK_RBUTTON) != 0 )
{
// Make each pixel correspond to 0.005 unit in the scene.
float dx = 0.005f*static_cast<float>(x - mLastMousePos.x);
float dy = 0.005f*static_cast<float>(y - mLastMousePos.y);
// Update the camera radius based on input.
mRadius += dx - dy;
// Restrict the radius.
mRadius = MathHelper::Clamp(mRadius, 3.0f, 15.0f);
}
mLastMousePos.x = x;
mLastMousePos.y = y;
}
void BoxApp::BuildGeometryBuffers()
{
// Create vertex buffer
Vertex vertices[] =
{
{ XMFLOAT3(-1.0f, -1.0f, -1.0f), (const float*)&Colors::White },
{ XMFLOAT3(-1.0f, +1.0f, -1.0f), (const float*)&Colors::Black },
{ XMFLOAT3(+1.0f, +1.0f, -1.0f), (const float*)&Colors::Red },
{ XMFLOAT3(+1.0f, -1.0f, -1.0f), (const float*)&Colors::Green },
{ XMFLOAT3(-1.0f, -1.0f, +1.0f), (const float*)&Colors::Blue },
{ XMFLOAT3(-1.0f, +1.0f, +1.0f), (const float*)&Colors::Yellow },
{ XMFLOAT3(+1.0f, +1.0f, +1.0f), (const float*)&Colors::Cyan },
{ XMFLOAT3(+1.0f, -1.0f, +1.0f), (const float*)&Colors::Magenta }
};
D3D11_BUFFER_DESC vbd;
vbd.Usage = D3D11_USAGE_IMMUTABLE;
vbd.ByteWidth = sizeof(Vertex) * 8;
vbd.BindFlags = D3D11_BIND_VERTEX_BUFFER;
vbd.CPUAccessFlags = 0;
vbd.MiscFlags = 0;
vbd.StructureByteStride = 0;
D3D11_SUBRESOURCE_DATA vinitData;
vinitData.pSysMem = vertices;
HR(md3dDevice->CreateBuffer(&vbd, &vinitData, &mBoxVB));
// Create the index buffer
UINT indices[] = {
// front face
0, 1, 2,
0, 2, 3,
// back face
4, 6, 5,
4, 7, 6,
// left face
4, 5, 1,
4, 1, 0,
// right face
3, 2, 6,
3, 6, 7,
// top face
1, 5, 6,
1, 6, 2,
// bottom face
4, 0, 3,
4, 3, 7
};
D3D11_BUFFER_DESC ibd;
ibd.Usage = D3D11_USAGE_IMMUTABLE;
ibd.ByteWidth = sizeof(UINT) * 36;
ibd.BindFlags = D3D11_BIND_INDEX_BUFFER;
ibd.CPUAccessFlags = 0;
ibd.MiscFlags = 0;
ibd.StructureByteStride = 0;
D3D11_SUBRESOURCE_DATA iinitData;
iinitData.pSysMem = indices;
HR(md3dDevice->CreateBuffer(&ibd, &iinitData, &mBoxIB));
}
void BoxApp::BuildFX()
{
DWORD shaderFlags = 0;
#if defined( DEBUG ) || defined( _DEBUG )
shaderFlags |= D3D10_SHADER_DEBUG;
shaderFlags |= D3D10_SHADER_SKIP_OPTIMIZATION;
#endif
ID3D10Blob* compiledShader = 0;
ID3D10Blob* compilationMsgs = 0;
HRESULT hr = D3DX11CompileFromFile(L"FX/color.fx", 0, 0, 0, "fx_5_0", shaderFlags,
0, 0, &compiledShader, &compilationMsgs, 0);
// compilationMsgs can store errors or warnings.
if( compilationMsgs != 0 )
{
MessageBoxA(0, (char*)compilationMsgs->GetBufferPointer(), 0, 0);
ReleaseCOM(compilationMsgs);
}
// Even if there are no compilationMsgs, check to make sure there were no other errors.
if(FAILED(hr))
{
DXTrace(__FILE__, (DWORD)__LINE__, hr, L"D3DX11CompileFromFile", true);
}
HR(D3DX11CreateEffectFromMemory(compiledShader->GetBufferPointer(), compiledShader->GetBufferSize(),
0, md3dDevice, &mFX));
// Done with compiled shader.
ReleaseCOM(compiledShader);
mTech = mFX->GetTechniqueByName("ColorTech");
mfxWorldViewProj = mFX->GetVariableByName("gWorldViewProj")->AsMatrix();
}
void BoxApp::BuildVertexLayout()
{
// Create the vertex input layout.
D3D11_INPUT_ELEMENT_DESC vertexDesc[] =
{
{"POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0},
{"COLOR", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0}
};
// Create the input layout
D3DX11_PASS_DESC passDesc;
mTech->GetPassByIndex(0)->GetDesc(&passDesc);
HR(md3dDevice->CreateInputLayout(vertexDesc, 2, passDesc.pIAInputSignature,
passDesc.IAInputSignatureSize, &mInputLayout));
}
When I goto compile it it throws the error:
FXC : error X3501: 'main': entrypoint not found
What is the entry point of my shader file from the examples? and how do I set that in the shader compiler properties? do I also have to set it to shader 5 considering it is mentioning vs_5_0 in the shader file?
I have tried a variation of the following article: http://social.msdn.microsoft.com/Forums/windowsapps/en-US/51859322-fc36-4946-b4cb-b5971fcaa9e5/fxc-error-x3501-main-entrypoint-not-found?forum=wingameswithdirectx but just can't get it to run.
The option below only works on Visual Studio 2012 or later version.
If you compile a .fx file, you can set the shader type to "fx" as below:
Right click your project in VS and select properties
Expand the HLSL compiler option, select "Effect(/fx)" for Shader Type, you can
also specify a entry point function for Entrypoint Name.
since VS2012 microsoft decided to include a HLSL compiler (that's where the error comes from), but you don't need it since you are loading and compiling the .fx file at runtime using the D3DX11CompileFromFile() function. So just exclude the .fx file from the build, right-click on the file in the solution explorer and choose properties->configuration properties->general->excluded from build->yes.
rekotc answer is good, but in Microsoft DirectX examples https://github.com/Microsoft/DirectXTK, "configuration properties->general->Item Type->Does not participate in build" is used instead "configuration properties->general->excluded from build->yes".
That also works.
I equally have been working with that book and using the samples in VS 2013 and ran into the same error, when I came across your question.
In order to compile the samples you need to have the Project's Properties > Config. Properties > General > Platform Toolset to v100 (VS2010), so you won't see the HLSL Compiler options that zdd mentions in their answer because that comes with later versions of VS's toolset (e.g. having your Platform Toolset set to v120 (VS2013)).
Using the v100 toolset you can still set up the build process, as outlined in 6.8.5 Compiling an Effect at Build Time (p. 221), which configures it as a custom build step.
I have a Windows Phone 8 C#/XAML project with DirectX component. I'm trying to rendering some particles. I create a vertex buffer, which I saw it go into the function to create, but when it gets to an update vertex buffer, the buffer is NULL. I have not released the buffers yet. Do you know why this will happen? Does any of the output messages help? Thanks.
Printouts and errors on my Output Window:
'TaskHost.exe' (Win32): Loaded '\Device\HarddiskVolume4\Windows\System32\d3d11_1SDKLayers.dll'. Cannot find or open the PDB file.
D3D11 WARNING: ID3D11Texture2D::SetPrivateData: Existing private data of same name with different size found! [ STATE_SETTING WARNING #55: SETPRIVATEDATA_CHANGINGPARAMS]
Create vertex buffer
D3D11 WARNING: ID3D11DeviceContext::DrawIndexed: The Pixel Shader unit expects a Sampler to be set at Slot 0, but none is bound. This is perfectly valid, as a NULL Sampler maps to default Sampler state. However, the developer may not want to rely on the defaults. [ EXECUTION WARNING #352: DEVICE_DRAW_SAMPLER_NOT_SET]
The thread 0xb64 has exited with code 0 (0x0).
m_vertexBuffer is null
D3D11 WARNING: ID3D11DeviceContext::DrawIndexed: The Pixel Shader unit expects a Sampler to be set at Slot 0, but none is bound. This is perfectly valid, as a NULL Sampler maps to default Sampler state. However, the developer may not want to rely on the defaults. [ EXECUTION WARNING #352: DEVICE_DRAW_SAMPLER_NOT_SET]
m_vertexBuffer is null
In CreateDeviceResources, I call CreateVertexShader, CreateInputLayout, CreatePixelShader, CreateBuffer. Then I get to creating the sampler and vertex buffer, code below:
auto createCubeTask = (createPSTask && createVSTask).then([this] () {
// Create a texture sampler state description.
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;
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;
// Create the texture sampler state.
HRESULT result = m_d3dDevice->CreateSamplerState(&samplerDesc, &m_sampleState);
if(FAILED(result))
{
OutputDebugString(L"Can't CreateSamplerState");
}
//InitParticleSystem();
// Set the maximum number of vertices in the vertex array.
m_vertexCount = m_maxParticles * 6;
// Set the maximum number of indices in the index array.
m_indexCount = m_vertexCount;
// Create the vertex array for the particles that will be rendered.
m_vertices = new VertexType[m_vertexCount];
if(!m_vertices)
{
OutputDebugString(L"Can't create the vertex array for the particles that will be rendered.");
}
else
{
// Initialize vertex array to zeros at first.
int sizeOfVertexType = sizeof(VertexType);
int totalSizeVertex = sizeOfVertexType * m_vertexCount;
memset(m_vertices, 0, totalSizeVertex);
D3D11_SUBRESOURCE_DATA vertexBufferData = {0};
vertexBufferData.pSysMem = m_vertices;
vertexBufferData.SysMemPitch = 0;
vertexBufferData.SysMemSlicePitch = 0;
int sizeOfMVertices = sizeof(m_vertices);
CD3D11_BUFFER_DESC vertexBufferDesc(
totalSizeVertex, // byteWidth
D3D11_BIND_VERTEX_BUFFER, // bindFlags
D3D11_USAGE_DYNAMIC, // D3D11_USAGE usage = D3D11_USAGE_DEFAULT
D3D11_CPU_ACCESS_WRITE, // cpuaccessFlags
0, // miscFlags
0 // structureByteStride
);
OutputDebugString(L"Create vertex buffer\n");
DX::ThrowIfFailed(
m_d3dDevice->CreateBuffer(
&vertexBufferDesc,
&vertexBufferData,
&m_vertexBuffer
)
);
}
unsigned long* indices = new unsigned long[m_indexCount];
if(!indices)
{
OutputDebugString(L"Can't create the index array.");
}
else
{
// Initialize the index array.
for(int i=0; i<m_indexCount; i++)
{
indices[i] = i;
}
// Set up the description of the static index buffer.
// Create the index array.
D3D11_BUFFER_DESC indexBufferDesc;
indexBufferDesc.Usage = D3D11_USAGE_DEFAULT;
indexBufferDesc.ByteWidth = sizeof(unsigned long) * m_indexCount;
indexBufferDesc.BindFlags = D3D11_BIND_INDEX_BUFFER;
indexBufferDesc.CPUAccessFlags = 0;
indexBufferDesc.MiscFlags = 0;
indexBufferDesc.StructureByteStride = 0;
// Give the subresource structure a pointer to the index data.
D3D11_SUBRESOURCE_DATA indexData;
indexData.pSysMem = indices;
indexData.SysMemPitch = 0;
indexData.SysMemSlicePitch = 0;
// Create the index buffer.
DX::ThrowIfFailed(
m_d3dDevice->CreateBuffer(
&indexBufferDesc,
&indexData,
&m_indexBuffer
)
);
// Release the index array since it is no longer needed.
delete [] indices;
indices = 0;
}
});
createCubeTask.then([this] () {
m_loadingComplete = true;
});
}
My vertex is position, tex, and color:
struct VertexType
{
DirectX::XMFLOAT3 position;
DirectX::XMFLOAT2 texture;
DirectX::XMFLOAT4 color;
};
Microsoft::WRL::ComPtr<ID3D11SamplerState> m_sampleState;
VertexType* m_vertices;
Microsoft::WRL::ComPtr<ID3D11Buffer> m_vertexBuffer;
const D3D11_INPUT_ELEMENT_DESC vertexDesc[] =
{
{ "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 },
{ "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_VERTEX_DATA, 0 },
{ "COLOR", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_VERTEX_DATA, 0 },
};
VertexShader.HLSL:
cbuffer ModelViewProjectionConstantBuffer : register(b0)
{
matrix model;
matrix view;
matrix projection;
};
struct VertexInputType
{
float4 position : POSITION;
float2 tex : TEXCOORD0;
float4 color : COLOR;
};
struct PixelInputType
{
float4 position : SV_POSITION;
float2 tex : TEXCOORD0;
float4 color : COLOR;
};
PixelInputType main(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, model);
output.position = mul(output.position, view);
output.position = mul(output.position, projection);
// Store the texture coordinates for the pixel shader.
output.tex = input.tex;
// Store the particle color for the pixel shader.
output.color = input.color;
return output;
}
After the call to: m_d3dDevice->CreateBuffer(&vertexBufferDesc, &vertexBufferData, &m_vertexBuffer) the m_vertexBuffer is not null.
But when I get to my Update() function, m_vertexBuffer is NULL!
D3D11_MAPPED_SUBRESOURCE mappedResource;
if (m_vertexBuffer == nullptr)
{
OutputDebugString(L"m_vertexBuffer is null\n");
}
else
{
// Lock the vertex buffer.
DX::ThrowIfFailed(m_d3dContext->Map(m_vertexBuffer.Get(), 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource));
// Get a pointer to the data in the vertex buffer.
VertexType * verticesPtr = (VertexType*)mappedResource.pData;
//// Copy the data into the vertex buffer.
int sizeOfVertices = sizeof(VertexType) * m_vertexCount;
memcpy(verticesPtr, (void*)m_vertices, sizeOfVertices);
//// Unlock the vertex buffer.
m_d3dContext->Unmap(m_vertexBuffer.Get(), 0);
}
About the sampler, you need to assign it to your pixelshader.
m_d3dContext.Get()->PSSetSamplers(0,1,&m_sampleState);
I was making the incorrect call on m_vertexBuffer when I go Render it.
This fixes the error with the m_vertexBuffer being null.
Previous:
m_d3dContext.Get()->IASetVertexBuffers(0, 1, &m_vertexBuffer, &stride, &offset);
Fix:
m_d3dContext.Get()->IASetVertexBuffers(0, 1, m_vertexBuffer.GetAddressOf(), &stride, &offset);
It doesn't fix the error with the sampler states though:
DrawIndexed: The Pixel Shader unit expects a Sampler to be set at Slot
0
I am attempting to do some processing in the pixel shader on a texture. The data for the texture is coming from a memory chunk of 8 bit data. The problem I am facing is how to read the data in the shader.
Code to create the texture and ressource view:
In OnD3D11CreateDevice:
D3D11_TEXTURE2D_DESC tDesc;
tDesc.Height = 480;
tDesc.Width = 640;
tDesc.Usage = D3D11_USAGE_DYNAMIC;
tDesc.MipLevels = 1;
tDesc.ArraySize = 1;
tDesc.SampleDesc.Count = 1;
tDesc.SampleDesc.Quality = 0;
tDesc.Format = DXGI_FORMAT_R8_UINT;
tDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
tDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
tDesc.MiscFlags = 0;
V_RETURN(pd3dDevice->CreateTexture2D(&tDesc, NULL, &g_pCurrentImage));
D3D11_SHADER_RESOURCE_VIEW_DESC rvDesc;
g_pCurrentImage->GetDesc(&tDesc);
rvDesc.Format = DXGI_FORMAT_R8_UINT;
rvDesc.Texture2D.MipLevels = tDesc.MipLevels;
rvDesc.Texture2D.MostDetailedMip = tDesc.MipLevels - 1;
rvDesc.ViewDimension = D3D_SRV_DIMENSION_TEXTURE2D;
V_RETURN(pd3dDevice->CreateShaderResourceView(g_pCurrentImage, &rvDesc, &g_pImageRV)); </code>
in OnD3D11FrameRender:
HRESULT okay;
if( !g_updateDone ) {
D3D11_MAPPED_SUBRESOURCE resource;
resource.pData = mImage.GetData();
resource.RowPitch = 640;
resource.DepthPitch = 1;
okay = pd3dImmediateContext->Map(g_pCurrentImage, 0, D3D11_MAP_WRITE_DISCARD, 0, &resource);
g_updateDone = true;
}
pd3dImmediateContext->PSSetShaderResources(0, 1, &g_pImageRV);
This returns no errors so far, everything seems to work.
The HLSL Shader:
//-----
// Textures and Samplers
//-----
Texture2D <int> g_txDiffuse : register( t0 );
SamplerState g_samLinear : register( s0 );
//-----
// shader input/output structure
//-----
struct VS_INPUT
{
float4 Position : POSITION; // vertex position
float2 TextureUV : TEXCOORD0;// vertex texture coords
};
struct VS_OUTPUT
{
float4 Position : SV_POSITION; // vertex position
float2 TextureUV : TEXCOORD0; // vertex texture coords
};
//-----
// Vertex shader
//-----
VS_OUTPUT RenderSceneVS( VS_INPUT input )
{
VS_OUTPUT Output;
Output.Position = input.Position;
Output.TextureUV = input.TextureUV;
return Output;
}
//-----
// Pixel Shader
//-----
float4 RenderScenePS( VS_OUTPUT In ) : SV_TARGET
{
int3 loc;
loc.x = 0;
loc.y = 0;
loc.z = 1;
int r = g_txDiffuse.Load(loc);
//float fTest = (float) r;
return float4( In.TextureUV.x, In.TextureUV.y, In.TextureUV.x + In.TextureUV.y, 1);
}
The thing is, I can't even debug it in PIX to see what r results in, because even with Shader optimization disabled, the line int r = ... is never reached
I tested
float fTest = (float) r;
return float4( In.TextureUV.x, In.TextureUV.y, In.TextureUV.x + In.TextureUV.y, fTest);
but this would result in "cannot map expression to pixel shader instruction set", even though it's a float.
So how do I read and use 8bit integers from a texture, and if possible, with no sampling at all.
Thanks for any feedback.
Oh my this is a really old question, I thought it said 2012!
But anyway as it's still open:
Due to the nature of GPU's being optimised for floating point arithmetic, you probably wont get a great deal of performance advantage by using a Texture2D<int> over a Texture2D<float>.
You could attempt to use a Texture2D<float> and then try:
return float4( In.TextureUV.x, In.TextureUV.y, In.TextureUV.x + In.TextureUV.y, g_txDiffuse.Load(loc));
loc.z = 1;
Should be 0 here, because texture mip levels is 1 in your case, and mipmaps start at 0 in HLSL for Load intrinsic.