I am a newbie in DirectX11, so sorry for a dull question.
I have a pixel shader:
struct PixelShaderInput
{
float4 pos : SV_POSITION;
float2 texCoord : TEXCOORD0;
};
Texture2D s_texture : register(t0);
SamplerState s_sampleParams
{
Filter = MIN_MAG_MIP_LINEAR;
AddressU = CLAMP;
AddressV = CLAMP;
};
float4 main(PixelShaderInput input) : SV_TARGET
{
float4 t = s_texture.Sample(s_sampleParams, input.texCoord);
return t;
}
Now I want to add a color to my shader:
struct PixelShaderInput
{
float4 pos : SV_POSITION;
float2 texCoord : TEXCOORD0;
};
Texture2D s_texture : register(t0);
float4 s_color;
SamplerState s_sampleParams
{
Filter = MIN_MAG_MIP_LINEAR;
AddressU = CLAMP;
AddressV = CLAMP;
};
float4 main(PixelShaderInput input) : SV_TARGET
{
float4 t = s_texture.Sample(s_sampleParams, input.texCoord);
return t * s_color;
}
How do I set s_color from C++ code? Do I have to use m_d3dContext->PSSetConstantBuffers? In this case I should change
`float4 s_color;`
to
cbuffer ColorOnlyConstantBuffer : register(b0)
{
float4 m_color;
};
, right?
Or I can keep simple definition float4 s_color; and set it from C++ somehow else?
As far as I remember, you specify input items for vertex shader by using specific structure:
D3D11_INPUT_ELEMENT_DESC inputLayoutDesc[2] =
{
{ "Position",
0,
DXGI_FORMAT_R32G32B32_FLOAT,
0,
D3D11_APPEND_ALIGNED_ELEMENT,
D3D11_INPUT_PER_VERTEX_DATA,
0
},
{ "Color",
0,
DXGI_FORMAT_R32G32B32_FLOAT,
0,
D3D11_APPEND_ALIGNED_ELEMENT,
D3D11_INPUT_PER_VERTEX_DATA,
0
}
};
This structure is being used to create ID3D11InputLayout:
const UINT inputLayoutDescCount = 2;
hr = device->CreateInputLayout(
inputLayoutDesc,
inputLayoutDescCount,
compiledVsShader->GetBufferPointer(),
compiledVsShader->GetBufferSize(),
&inputLayout);
You can then use semantics to specify, which element represents which entry:
struct VS_INPUT
{
float4 Pos : POSITION;
float4 Col : COLOR;
};
Edit: in response to comments.
Sorry, didn't get that. You'll need a constant buffer. Relevant (sample) parts of code follows. Just modify them to your needs:
struct PixelConstantBuffer
{
XMFLOAT4 lightPos;
XMFLOAT4 observerPos;
};
// ***
D3D11_BUFFER_DESC pixelConstantBufferDesc;
pixelConstantBufferDesc.ByteWidth = sizeof(PixelConstantBuffer);
pixelConstantBufferDesc.Usage = D3D11_USAGE_DEFAULT;
pixelConstantBufferDesc.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
pixelConstantBufferDesc.CPUAccessFlags = 0;
pixelConstantBufferDesc.MiscFlags = 0;
pixelConstantBufferDesc.StructureByteStride = 0;
hr = device->CreateBuffer(&pixelConstantBufferDesc, nullptr, &pixelConstantBuffer);
// ***
context->PSSetConstantBuffers(1, 1, &pixelConstantBuffer);
context->PSSetShader(pixelShader, nullptr, 0);
// ***
PixelConstantBuffer pcBuffer;
pcBuffer.lightPos = XMFLOAT4(lightPos.m128_f32[0], lightPos.m128_f32[1], lightPos.m128_f32[2], lightPos.m128_f32[3]);
pcBuffer.observerPos = XMFLOAT4(camPos.m128_f32[0], camPos.m128_f32[1], camPos.m128_f32[2], camPos.m128_f32[3]);
context->UpdateSubresource(pixelConstantBuffer, 0, nullptr, &pcBuffer, 0, 0);
// *** (hlsl)
cbuffer PixelConstantBuffer : register(b1)
{
float4 LightPos;
float4 ObserverPos;
}
Related
I'm new to directx and I need to set up opacity in my shaders. I don't use textures or anything and I just need to add opacity to whole objects based on one variable in shader.
I've tried to simply put this variable in shader's output color alpha channel, but it didn't work and I guess that the solution of this problem is not in shaders. This is my shader so far.
cbuffer ConstantBuffer : register(b0)
{
matrix World;
matrix View;
matrix Projection;
float4 vLigthDir[2];
float4 vLigthColor[2];
float4 vOutputColor;
float intensity;
float3 colors;
}
struct VS_INPUT
{
float4 pos : POSITION;
float3 norm : NORMAL;
};
struct PS_INPUT
{
float4 pos : SV_POSITION;
float3 norm : TEXCOORD0;
};
PS_INPUT VS(VS_INPUT input)
{
PS_INPUT output = (PS_INPUT) 0;
output.pos = mul(input.pos, World);
output.pos = mul(output.pos, View);
output.pos = mul(output.pos, Projection);
output.norm = mul(input.norm, World);
return output;
}
float4 PS(PS_INPUT input) : SV_Target
{
float4 finalColor = 0;
finalColor.r = colors.r;
finalColor.g = colors.g;
finalColor.b = colors.b;
finalColor.a = intensity;
return finalColor;
}
float4 PSSolid(PS_INPUT input) : SV_Target
{
return vOutputColor;
}
//Create BlendState
D3D11_BLEND_DESC blendDesc;
blendDesc.AlphaToCoverageEnable = false;
blendDesc.IndependentBlendEnable = false;
blendDesc.RenderTarget[0].BlendEnable = true;
blendDesc.RenderTarget[0].SrcBlend = D3D11_BLEND_SRC_ALPHA;
blendDesc.RenderTarget[0].DestBlend = D3D11_BLEND_INV_SRC_ALPHA;
blendDesc.RenderTarget[0].BlendOp = D3D11_BLEND_OP_ADD;
blendDesc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_ONE;
blendDesc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_ZERO;
blendDesc.RenderTarget[0].BlendOpAlpha = D3D11_BLEND_OP_ADD;
blendDesc.RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL;
hr = g_pd3dDevice->CreateBlendState(&blendDesc, &pBlendState);
//Using BlendState
float blendFactor[4] = { 1.0f, 1.0f, 1.0f, 1.0f };
UINT sampleMask = 0xffffffff;
g_pImmediateContext->OMGetBlendState(&pBlendState, blendFactor, &sampleMask);
///////////Rendering geometry part///////////
g_pImmediateContext->OMGetBlendState(NULL, NULL, NULL);
I expect some objects to have opacity, but instead nothing happenening at all, there are just solid color.
basically I am trying to render a scene to a texture as in this ogl tutorial here but in DirectX 11, and I faced some issues:
Absolutely nothing is rendered when I launch the program IDK why.
The only thing the texture displays 'correctly' is the clear color.
I have examined the executable in RenderDoc, and in the captured frame the back buffer draws the quad and the texture on it displays the scene correctly!
Source code peak:
D3D11_TEXTURE2D_DESC texDesc;
ZeroMemory(&texDesc, sizeof(D3D11_TEXTURE2D_DESC));
texDesc.Width = Data.Width;
texDesc.Height = Data.Height;
texDesc.Format = R32G32B32A32_FLOAT;
texDesc.Usage = D3D11_USAGE_DEFAULT;
texDesc.SampleDesc.Count = 1;
texDesc.SampleDesc.Quality = 0;
texDesc.CPUAccessFlags = 0;
texDesc.ArraySize = 1;
texDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET;
texDesc.MiscFlags = 0;
texDesc.MipLevels = 1;
if (Data.Img_Data_Buf == NULL)
{
if (FAILED(DX11Context::GetDevice()->CreateTexture2D(&texDesc, NULL, &result->tex2D)))
{
Log.Error("[DirectX] Texture2D Creation Failed for Null-ed Texture2D!\n");
return;
}
D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
srvDesc.Format = texDesc.Format;
srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
srvDesc.Texture2D.MostDetailedMip = 0;
srvDesc.Texture2D.MipLevels = 1;
DX11Context::GetDevice()->CreateShaderResourceView(result->tex2D, &srvDesc, &result->resourceView);
return;
}
//depth stencil texture
D3D11_TEXTURE2D_DESC texDesc;
{
texDesc.Width = size.x;
texDesc.Height = size.y;
texDesc.MipLevels = 1;
texDesc.ArraySize = 1;
texDesc.Format = DXGI_FORMAT_D24_UNORM_S8_UINT;
texDesc.SampleDesc.Count = 1;
texDesc.SampleDesc.Quality = 0;
texDesc.Usage = D3D11_USAGE_DEFAULT;
texDesc.BindFlags = D3D11_BIND_DEPTH_STENCIL;
texDesc.CPUAccessFlags = 0;
texDesc.MiscFlags = 0;
}
if (FAILED(API::DirectX::DX11Context::GetDevice()->CreateTexture2D(&texDesc, nullptr, &depthstenciltex)))
{
Log.Error("[DX11RenderTarget] Failed to create DepthStencilTexture for render-target!\n");
//Return or the next call will fail too
return;
}
if (FAILED(API::DirectX::DX11Context::GetDevice()->CreateDepthStencilView(depthstenciltex, nullptr, &depthstencilview)))
{
Log.Error("[DX11RenderTarget] Failed to create DepthStencilView for render-target!\n");
}
//render target
D3D11_RENDER_TARGET_VIEW_DESC renderTargetViewDesc;
ZeroMemory(&renderTargetViewDesc, sizeof(D3D11_RENDER_TARGET_VIEW_DESC));
renderTargetViewDesc.Format = texDesc.Format;
renderTargetViewDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
renderTargetViewDesc.Texture2D.MipSlice = 0;
ID3D11RenderTargetView* rtv;
if (FAILED(API::DirectX::DX11Context::GetDevice()->CreateRenderTargetView(texture->tex2D, &renderTargetViewDesc, &rtv)))
{
Log.Error("[DX11RenderTarget] Failed to create render-target-view (RTV)!\n");
return;
}
//binding
Context->OMSetRenderTargets(1, &rtv, rt->depthstenciltex);
Shaders:
std::string VertexShader = R"(struct VertexInputType
{
float4 position : POSITION;
float2 tex : TEXCOORD;
};
struct PixelInputType
{
float4 position : SV_POSITION;
float2 tex : TEXCOORD;
};
cbuffer NE_Camera : register(b0)
{
matrix Model;
matrix View;
matrix Projection;
};
PixelInputType main(VertexInputType input)
{
PixelInputType output;
// Calculate the position of the vertex against the world, view, and projection matrices.
output.position = mul(Model, input.position);
output.position = mul(View, output.position);
output.position = mul(Projection, output.position);
// Store the input texture for the pixel shader to use.
output.tex = input.tex;
return output;
})";
std::string PixelShader = R"(
struct PixelInputType
{
float4 position : SV_POSITION;
float2 tex : TEXCOORD;
};
Texture2D NE_Tex_Diffuse : register(t0);
SamplerState NE_Tex_Diffuse_Sampler : register(s0);
float4 main(PixelInputType input) : SV_TARGET
{
return NE_Tex_Diffuse.Sample(NE_Tex_Diffuse_Sampler, input.tex);
}
)";
std::string ScreenVertexShader = R"(struct VertexInputType
{
float2 position : POSITION;
float2 tex : TEXCOORD;
};
struct PixelInputType
{
float4 position : SV_POSITION;
float2 tex : TEXCOORD;
};
PixelInputType main(VertexInputType input)
{
PixelInputType output;
// CalcSulate the position of the vertex against the world, view, and projection matrices.
output.position = float4(input.position.x,input.position.y,0.0f,1.0f);
// Store the input texture for the pixel shader to use.
output.tex = input.tex;
return output;
})";
std::string ScreenPixelShader = R"(
struct PixelInputType
{
float4 position : SV_POSITION;
float2 tex : TEXCOORD;
};
Texture2D ScreenTexture : register(t0);
SamplerState ScreenTexture_Sampler : register(s0);
float4 main(PixelInputType input) : SV_TARGET
{
return float4(ScreenTexture.Sample(ScreenTexture_Sampler, input.tex).rgb, 1.0f);
}
)";
Full Source Code
Also I captured a frame with visual studio graphics debugger, and noticed that the render to texture draw call has the PS shader with "stage didn't run, no output".
Note: I know that the scene should be flipped in DirectX.
I have found the bug causing this problem, I wasn't clearing the depth stencil view at rendering, I wonder why is clearing the DSV essential for RenderTarget output.
I have an application based on the Windows8-DirectX template from the Visual Studio and i'm trying to draw a texture with an alpha channel with the following D3D11_BLEND_DESC:
D3D11_BLEND_DESC blendDesc{};
blendDesc.RenderTarget[0].BlendEnable = TRUE;
blendDesc.RenderTarget[0].SrcBlend = D3D11_BLEND_SRC_ALPHA;
blendDesc.RenderTarget[0].DestBlend = D3D11_BLEND_INV_SRC_ALPHA;
blendDesc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_INV_DEST_ALPHA;
blendDesc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_ONE;
blendDesc.RenderTarget[0].BlendOp = D3D11_BLEND_OP_ADD;
blendDesc.RenderTarget[0].BlendOpAlpha = D3D11_BLEND_OP_ADD;
blendDesc.RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL;
ThrowIfFailed(device->CreateBlendState(&blendDesc, &_blendState));
And i'm binding this blend state this way:
float blendFactor[4] = { 0.0f, 0.0f, 1.0f, 1.0f };
UINT sampleMask = 0xffffffff;
context->OMSetBlendState(_blendState.Get(), blendFactor, sampleMask);
Here is my Vertex Shader:
cbuffer ModelViewProjectionConstantBuffer : register(b0)
{
matrix model;
matrix view;
matrix projection;
};
struct VertexShaderInput
{
float3 pos : POSITION;
float2 texcoord : TEXCOORD;
};
struct PixelShaderInput
{
float4 pos : SV_POSITION;
float2 texcoord : TEXCOORD;
};
PixelShaderInput main(VertexShaderInput input)
{
PixelShaderInput output;
float4 pos = float4(input.pos, 1.0f);
pos = mul(pos, model);
pos = mul(pos, view);
pos = mul(pos, projection);
output.pos = pos;
output.texcoord = input.texcoord;
return output;
}
Pixel Shader:
Texture2D tex0;
SamplerState s0;
struct PixelShaderInput
{
float4 pos : SV_POSITION;
float2 texcoord : TEXCOORD;
};
float4 main(PixelShaderInput input) : SV_TARGET
{
float4 color = tex0.Sample(s0, input.texcoord);
return color;
}
And that is my texture:
D3D11_TEXTURE2D_DESC textureDesc{};
textureDesc.Width = width;
textureDesc.Height = height;
textureDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
textureDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
textureDesc.MipLevels = textureDesc.ArraySize = 1;
textureDesc.SampleDesc.Count = 1;
ThrowIfFailed(device->CreateTexture2D(&textureDesc, NULL, &_texture));
ThrowIfFailed(device->CreateShaderResourceView(_texture.Get(), NULL, &_textureView));
But the problem is that the blending is not working properly. An texture is only blending with the background, but not with another texture, eg. if i call the ClearRenderTargetView method with blue color as third parameter then the partially transparent texture will be bluish but will not be blended with an overlapping texture.
My Problem is, that when I render to a rendertarget, which has a texture binded to it, the rendered information cannot be seen, because the alpha is 0.
If I turn the alpha value within the shader to 1 when displaying the rendertarget, then I can see it clear.
If I save the texture to a file, everywhere where there is nothing rendered, it is the clearcolor. Everywhere, where something is rendered, there's alpha = 0.
My blendstate:
D3D10_BLEND_DESC BlendState;
ZeroMemory(&BlendState, sizeof(D3D10_BLEND_DESC));
BlendState.AlphaToCoverageEnable = FALSE;
for (int32 i=0;i<this->m_TextureCount;i++)
BlendState.BlendEnable[i] = TRUE;
BlendState.SrcBlend = D3D10_BLEND_SRC_ALPHA;
BlendState.DestBlend = D3D10_BLEND_INV_SRC_ALPHA;
BlendState.BlendOp = D3D10_BLEND_OP_ADD;
BlendState.SrcBlendAlpha = D3D10_BLEND_ZERO;
BlendState.DestBlendAlpha = D3D10_BLEND_ZERO;
BlendState.BlendOpAlpha = D3D10_BLEND_OP_ADD;
for (int32 i = 0; i<this->m_TextureCount; i++)
BlendState.RenderTargetWriteMask[i] = D3D10_COLOR_WRITE_ENABLE_ALL;
this->m_pDevice->CreateBlendState(&BlendState, &this->m_pBlendState);
Before rendering:
this->m_pDevice->OMSetBlendState(this->m_pBlendState, 0, 0xffffffff);
Shadercode to draw the bricks:
float4x4 View;
float4x4 Projection;
Texture2D Diffuse;
SamplerState TextureSampler
{
Filter = MIN_MAG_MIP_Linear;
AddressU = WRAP;
AddressV = WRAP;
};
struct VertexShaderInput
{
float3 Position : POSITION0;
float2 UV : TEXCOORD0;
float3 Color : COLOR0;
float3 Normal : NORMAL0;
row_major float4x4 Offset : MATRIX;
};
struct VertexShaderOutput
{
float4 PositionOut : SV_POSITION;
float4 Position : POSITION0;
float2 UV : TEXCOORD0;
float3 Color : COLOR0;
float3 Normal : NORMAL0;
};
struct PixelShaderOutput
{
float4 colorMap: SV_TARGET0;
float4 normalMap: SV_TARGET1;
float4 positionMap: SV_TARGET2;
};
VertexShaderOutput VS_MAIN(VertexShaderInput input)
{
VertexShaderOutput Output = (VertexShaderOutput)0;
float4 pos = float4(input.Position.xyz, 1);
float4x4 Model = input.Offset;
float4x4 MVP = mul(mul(Model,View),Projection);
Output.Position = mul(pos,MVP);
Output.PositionOut = mul(pos,MVP);
Output.UV = input.UV;
Output.Color = input.Color;
Output.Normal = normalize(mul(input.Normal,(float3x3)Model));
return Output;
}
PixelShaderOutput PS_MAIN(VertexShaderOutput input)
{
PixelShaderOutput output;
output.colorMap = float4(1,0,0,1); // This is the texture above
output.normalMap = float4(input.Normal,1);
output.positionMap = float4(input.Position.xyz,1);
return output;
}
technique10 Main
{
pass p0
{
SetVertexShader(CompileShader(vs_4_0, VS_MAIN()));
SetGeometryShader(NULL);
SetPixelShader(CompileShader(ps_4_0, PS_MAIN()));
}
};
changed Rendertarget's Blendstate to
D3D10_BLEND_DESC BlendState;
ZeroMemory(&BlendState, sizeof(D3D10_BLEND_DESC));
BlendState.AlphaToCoverageEnable = true;
for (int32 i=0;i<this->m_TextureCount;i++)
BlendState.BlendEnable[i] = TRUE;
BlendState.SrcBlend = D3D10_BLEND_SRC_ALPHA;
BlendState.DestBlend = D3D10_BLEND_INV_SRC_ALPHA;
BlendState.BlendOp = D3D10_BLEND_OP_ADD;
BlendState.SrcBlendAlpha = D3D10_BLEND_SRC_ALPHA;
BlendState.DestBlendAlpha = D3D10_BLEND_INV_SRC_ALPHA;
BlendState.BlendOpAlpha = D3D10_BLEND_OP_ADD;
for (int32 i = 0; i<this->m_TextureCount; i++)
BlendState.RenderTargetWriteMask[i] = D3D10_COLOR_WRITE_ENABLE_ALL;
this->m_pDevice->CreateBlendState(&BlendState, &this->m_pBlendState);
And it works now.
I am trying to add things to my working code, but it is returning an error [Invalid Arg] when calling CreateInputLayout().
It works before I add the texture stuff, but fails when I add it.
The shader file compiled with no errors.
I think the way I made the layout is bad. Is this correct?
C++ Vertex structure:
struct VertexData{
XMFLOAT3 Pos;
XMFLOAT4 Color;
XMFLOAT2 TexCoord;
};
C++ Layout:
D3D11_INPUT_ELEMENT_DESC inputLayout[]={
{ "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 },
{ "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 28, D3D11_INPUT_PER_VERTEX_DATA, 0 },
}; uint lSize=sizeof(inputLayout)/sizeof(inputLayout[0]);
Shader code:
// Stuff from DX Tutorial 7
Texture2D txDiffuse : register( t0 );
SamplerState samLinear : register( s0 );
cbuffer ViewData : register(b0){
matrix World;
matrix View;
matrix Projection;
}
struct VS_INPUT{
float4 pos : SV_POSITION;
float4 color : COLOR0;
float2 tex : TEXCOORD0;
};
struct PS_INPUT{
float4 pos : SV_POSITION;
float4 color : COLOR0;
float2 tex : TEXCOORD0;
};
PS_INPUT VS(VS_INPUT input){
PS_INPUT output=(PS_INPUT)0;
output.pos=mul(input.pos, World);
output.pos=mul(output.pos, View);
output.pos=mul(output.pos, Projection);
output.color = input.color;
output.tex = input.tex;
return output;
}
float4 PS(PS_INPUT input) : SV_Target {
return input.color;
}
Edit:
After a bunch of twiddling with the shader code, I found that if I change the semantics of the...
1st position to: float4 pos : POSITION;
2nd position to: float4 pos : SV_POSITION;
...the input layout successfully creates.
I tried both without the SV_ [system value] prefix, but that also failed. I dont know why I cant have them be the same.
The Semantics seem a bit magical. Not sure if I should answer my own Q with this, or wait for someone smarter to answer better.
Your structs do not match:
struct VertexData
{
XMFLOAT3 Pos; // float3 here
XMFLOAT4 Color;
XMFLOAT2 TexCoord;
};
struct VS_INPUT{
float4 pos : SV_POSITION; // float4 here
float4 color : COLOR0;
float2 tex : TEXCOORD0;
};
For position in 3D space I prefer to use float3. So, as your input layout:
"POSITION", 0, R32G32B32_FLOAT
About semantics magic:
Names in HLSL must match input layout names. For example:
Layout:
{ "POSITION", 0, .. }
Vertex Shader:
float4 pos : POSITION0;
The only exception is that pixel shader must always have float4 pos : SV_POSITION semantics for the input position of pixel (It is a one of the System Value semantics).
And as a bonus, some commonly used stuff I'd like to recommend:
int size = ARRYSIZE(inputayoutDesc);
use D3D11_APPEND_ALIGNED_ELEMENT instead of 12, 28, numbers as alignment offset.
Input semantics shouldn't be SV_POSITION if they are in your input vertices, they should be POSITION I think.
Also you declare this -
struct VS_INPUT{
float4 pos : SV_POSITION;
Shouldn't this be float3 pos : POSITION;
Your input layout only has 3 floats for that item. Not sure if it's the problem but it doesn't look quite right.