Here's a simple hull shader code that i made, to try to understand tessellation.
I just can't find anything wrong with this code, but the compile function always return false. Here's my code:
My input and output structures:
[domain("tri")] // indicates a triangle patch (3 verts)
[partitioning("fractional_odd")] // fractional avoids popping
// vertex ordering for the output triangles
[outputtopology("triangle_cw")]
[outputcontrolpoints(3)]
// name of the patch constant hull shader
[patchconstantfunc("ConstantsHS")]
//[maxtessfactor(7.0)]
cbuffer TessellationBuffer
{
float tessellationAmount;
float3 padding;
};
struct VS_CONTROL_POINT_OUTPUT
{
float3 vWorldPos : POSITION;
float2 vTexCoord : TEXCOORD0;
float3 vNormal : NORMAL0;
};
struct HS_CONTROL_POINT_OUTPUT
{
float3 vWorldPos : POSITION;
float2 vTexCoord : TEXCOORD0;
float3 vNormal : NORMAL0;
};
struct HS_CONSTANT_DATA_OUTPUT
{
float Edges[3] : SV_TessFactor;
float Inside : SV_InsideTessFactor;
};
My functions:
HS_CONTROL_POINT_OUTPUT HS(InputPatch<VS_CONTROL_POINT_OUTPUT, 3> inputPatch, uint uCPID : SV_OutputControlPointID, uint patchId : SV_PrimitiveID )
{
HS_CONTROL_POINT_OUTPUT Output;
Output.vWorldPos = inputPatch[uCPID].vWorldPos;
Output.vTexCoord = inputPatch[uCPID].vTexCoord;
Output.vNormal = inputPatch[uCPID].vNormal;
return Output;
};
HS_CONSTANT_DATA_OUTPUT ConstantsHS(InputPatch<VS_CONTROL_POINT_OUTPUT, 3> inputPatch, uint PatchID : SV_PrimitiveID )
{
HS_CONSTANT_DATA_OUTPUT Output;
Output.Edges[0] = tessellationAmount;
Output.Edges[1] = tessellationAmount;
Output.Edges[2] = tessellationAmount;
Output.Inside = tessellationAmount;
return Output;
};
Thanks for any help.
The attributes have to be set on the entry point like below, then your hull shader is valid :
[domain("tri")] // indicates a triangle patch (3 verts)
[partitioning("fractional_odd")] // fractional avoids popping
// vertex ordering for the output triangles
[outputtopology("triangle_cw")]
[outputcontrolpoints(3)]
// name of the patch constant hull shader
[patchconstantfunc("ConstantsHS")]
//[maxtessfactor(7.0)]
HS_CONTROL_POINT_OUTPUT HS(InputPatch<VS_CONTROL_POINT_OUTPUT, 3> inputPatch, uint uCPID : SV_OutputControlPointID, uint patchId : SV_PrimitiveID )
On a side note, The command line tool FXC.exe would have print an error message that would have put you in the right direction : error X3000: syntax error: unexpected token 'cbuffer'
And i am unsure of what function you are referring to, D3DCompile return a HRESULT, not a boolean, and it also output a blob for you with the error messages in case of failure.
Related
I have a common method in hlsli
/// RendererShaderTypes.hlsli
///
static inline float4 OverlayColor(float2 texOverlay, float4 videoColor)
{
float4 texColor = float4(imageMixTexture[4].Sample(imageMixSampler[4], texOverlay));
if (texColor.r == keyColor.r &&
texColor.g == keyColor.g &&
texColor.b == keyColor.b)
{
return videoColor;
}
return lerp(texColor, videoColor, transparency);
}
It's called from more than one hlsl pixel shaders.
#include "RendererShaderTypes.hlsli"
float4 main(PSPosTexOverlay input) : SV_TARGET
{
return OverlayColor(input.texOverlay, backColor);
}
also called to another pixel shader
#include "RendererShaderTypes.hlsli"
float4 main(PSPosVideoTexture input) : SV_TARGET
{
// lookup color of video
float4 mixColor = mul(colorMatrix[0], VideoColor(imageMixSampler[0], imageMixTexture[0], input.texImage));
mixColor.rgb *= mixColor.a;
mixColor.a = 1.0f;
return OverlayColor(input.texOverlay, mixColor);
}
when compiled shows following warning. Any idea why it's showing?
warning X4000: use of potentially uninitialized variable (OverlayColor)
I don't know yet any satisfactory reason but I have solved the issue. Any function that calls a mid-function return statement will show the warning during compilation. I have re-writed one of above like this and the warning went away.
static inline float4 OverlayColor(int texIndex, float2 texOverlay, float4 videoColor)
{
float4 texColor = float4(imageMixTexture[4].Sample(imageMixSampler[4], texOverlay));
float4 overlayColor;
if (texColor.r == keyColor.r &&
texColor.g == keyColor.g &&
texColor.b == keyColor.b)
{
overlayColor = videoColor;
}
else
overlayColor = lerp(texColor, videoColor, transparency);
return overlayColor;
}
I am working on a game engine using DirectX 11 and am having trouble getting shaders to encode properly. I am precompiling shaders to .csh files and creating shaders with the byte codes.
I get this error when I try to create any shader, but for this example I will use my PassThrough vertex shader.
D3D11 ERROR: ID3D11Device::CreateVertexShader: Encoded Vertex Shader size doesn't match specified size. [ STATE_CREATION ERROR #166: CREATEVERTEXSHADER_INVALIDSHADERBYTECODE]
The Shader:
#include "../VertexLayouts.hlsli"
// structs in included file
struct PASS_THROUGH_VS
{
float3 pos : POSITION;
float2 texCoord : TEXCOORD;
};
struct PASS_THROUGH_PS
{
float4 pos : SV_POSITION;
float2 texCoord : TEXCOORD;
};
PASS_THROUGH_PS main( PASS_THROUGH_VS input )
{
PASS_THROUGH_PS output = (PASS_THROUGH_PS)(0);
output.pos = float4(input.pos, 1);
output.texCoord = input.texCoord;
return output;
}
with these settings:
PassThrough_PS properties
In Renderer.h
#include "Vertex Shaders\PassThrough_VS.csh"
In Renderer.cpp
HRESULT hrReturn;
hrReturn = CreateVertexShader(&PassThrough_VS, sizeof(PassThrough_VS), Pass_Through_VS);
if (FAILED(hrReturn)) {}
//return hrReturn;
HRESULT CRenderer::CreateVertexShader(const void* ptrByteCode, SIZE_T szByteCodeLength, eVertexShaderType type)
{
HRESULT hrReturn;
tVertShader newShader = {};
hrReturn = D3Device->CreateVertexShader(&ptrByteCode, szByteCodeLength, nullptr, &(newShader.m_id3dShader)); // WHERE ERROR OCCURS
if (FAILED(hrReturn))
return hrReturn;
newShader.m_ptrByteCode = ptrByteCode;
newShader.m_szByteCodeLength = szByteCodeLength;
D3VertexShaders[type] = newShader;
return hrReturn;
}
The problem is you are passing a pointer-to-a-pointer, so you aren't actually passing the shader blob data to Direct3D.
HRESULT CRenderer::CreateVertexShader(const void* ptrByteCode, SIZE_T szByteCodeLength, eVertexShaderType type)
{
HRESULT hrReturn;
tVertShader newShader = {};
hrReturn = D3Device->CreateVertexShader(&ptrByteCode, szByteCodeLength,
nullptr, &(newShader.m_id3dShader));
...
The correct code is:
HRESULT CRenderer::CreateVertexShader(const void* ptrByteCode, SIZE_T szByteCodeLength, eVertexShaderType type)
{
HRESULT hrReturn;
tVertShader newShader = {};
hrReturn = D3Device->CreateVertexShader(ptrByteCode, szByteCodeLength,
nullptr, &(newShader.m_id3dShader));
...
You should take a look at DirectX Tool Kit and the tutorials in particular.
You didn't include any details about the tVertShader type, but you could well have reference counting problems. Consider using Microsoft::WRL::ComPtr instead of raw pointers for managing the lifetimes of Direct3D COM objects. See this article.
I've been search for a good text methodolgy recently and found one at http://www.braynzarsoft.net/Articles/index.php?p=VA&article=Easy-Font-Rendering-in-DirectX-11 , which is a good site. I can't seem to get it to run! I've resolved most of the errors but, however on debug, I get HLSL errors:
D3D11: ERROR: ID3D11DeviceContext::Draw: The Vertex Shader expects application provided input data (which is to say data other than hardware auto-generated values such as VertexID or InstanceID). Therefore an Input Assembler object is expected, but none is bound. [ EXECUTION ERROR #349: DEVICE_DRAW_INPUTLAYOUT_NOT_SET ]
Creeped? I am! Since this message is spamming like mad, the issue is most likely happening in my DrawText() function or a bad implementation in the initialize function (Below)
The InitializeGeneralResources() function:
void InfiniteText::InitializeGeneralResources(){
float textureWidth=1024.0f;
UINT numLetters=32;
D3DX11CompileFromFile(L"Font.hlsl", NULL, NULL, "FONT_VS", "vs_5_0",0,0,0,&FontvsBuffer,0,0);
D3DX11CompileFromFile(L"Font.hlsl", NULL, NULL, "FONT_PS", "ps_5_0",0,0,0,&FontpsBuffer,&ppErrorMsgs,0);
iD3D.Device->CreateVertexShader(FontvsBuffer->GetBufferPointer(),FontvsBuffer->GetBufferSize(), NULL, &Fontvs);
iD3D.Device->CreatePixelShader(FontpsBuffer->GetBufferPointer(),FontpsBuffer->GetBufferSize(), NULL, &Fontps);
ID3D11InputLayout* InLayout;
D3D11_INPUT_ELEMENT_DESC IEDesc[]={
{"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},
};
UINT NumElements = ARRAYSIZE(IEDesc);
iD3D.Device->CreateInputLayout(IEDesc,NumElements,FontvsBuffer->GetBufferPointer(),FontvsBuffer->GetBufferSize(),&InLayout);
iD3D.DeviceContext->IASetInputLayout(InLayout);
D3D11_SAMPLER_DESC FontSamplerDesc;
FontSamplerDesc.MaxAnisotropy=1;
FontSamplerDesc.AddressU=D3D11_TEXTURE_ADDRESS_WRAP;
FontSamplerDesc.AddressV=D3D11_TEXTURE_ADDRESS_WRAP;
FontSamplerDesc.AddressW=D3D11_TEXTURE_ADDRESS_WRAP;
FontSamplerDesc.Filter=D3D11_FILTER_MIN_MAG_MIP_LINEAR;
FontSamplerDesc.MipLODBias=0.0f;
D3DX11CreateShaderResourceViewFromFile(iD3D.Device, L"Font.dds", NULL, NULL, &FontSRV, NULL);
iD3D.Device->CreateSamplerState(&FontSamplerDesc, &FontSRVSampler);
D3D11_BUFFER_DESC Vbufferdescription;
ZeroMemory(&Vbufferdescription, sizeof(Vbufferdescription));
Vbufferdescription.BindFlags=D3D11_BIND_VERTEX_BUFFER;
Vbufferdescription.Usage=D3D11_USAGE_DYNAMIC;
Vbufferdescription.CPUAccessFlags=D3D11_CPU_ACCESS_WRITE;
Vbufferdescription.ByteWidth=sizeof(VertexText)*6*numLetters;
Vbufferdescription.MiscFlags=0;
iD3D.Device->CreateBuffer(&Vbufferdescription, NULL, &FontVertexBuffer);
}
I have a rather simple HLSL file:
cbuffer ConstantBuffer:register( b0 )
{
float4x4 WVP;
}
struct VOut
{
float4 position : SV_POSITION;
float2 TexCoord : TEXCOORD0;
};
VOut FONT_VS(float4 position : POSITION, float2 TexCoord : TEXCOORD)
{
VOut output;
output.position = mul(position, WVP);
output.TexCoord = TexCoord;
return output;
}
float2 FONT_PS(float4 position : SV_POSITION, float2 TexCoord : TEXCOORD0) : SV_TARGET
{
return TexCoord;
}
(The DrawString() function)
bool InfiniteText::DrawString(char* Text, float xPos, float yPos){
int letterSize = sizeof(VertexText)*6;
int textSize = strlen(Text);
if(textSize > numLetters)
textSize=numLetters;
float cScreenWidth = 32.0f/iD3D.cWidth;
float cScreenHeight= 32.0f/iD3D.cHeight;
float TexelWidth= 32.0f/textureWidth;
D3D11_MAPPED_SUBRESOURCE MappedSub;
iD3D.DeviceContext->Map(FontVertexBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &MappedSub);
VertexText* Sprite = (VertexText*)MappedSub.pData;
const int indexA = static_cast<int>('A');
const int indexZ = static_cast<int>('Z');
for(int i=0; i<textSize;i++){
float thisStartX=xPos+(cScreenWidth*static_cast<char>(i));
float thisEndX=thisStartX + cScreenWidth;
float thisStartY=yPos;
float thisEndY=thisStartY + cScreenHeight;
Sprite[0].Translation=XMFLOAT3(thisEndX,thisEndY,1.0f);
Sprite[1].Translation=XMFLOAT3(thisEndX,yPos,1.0f);
Sprite[2].Translation=XMFLOAT3(thisStartX,yPos,1.0f);
Sprite[3].Translation=XMFLOAT3(thisStartX,yPos,1.0f);
Sprite[4].Translation=XMFLOAT3(thisStartX,thisEndY,1.0f);
Sprite[5].Translation=XMFLOAT3(thisEndX,thisEndY,1.0f);
UINT TexLookup=0;
UINT Letter= static_cast<int>(Text[i]);
if (Letter < indexA || Letter > indexZ){
TexLookup=(indexA - indexZ) +1;
}
else{
TexLookup=(Letter-indexA);
}
float texStart = 0.0f + (TexelWidth*static_cast<float>(TexLookup));
float TexEnd = texStart + TexelWidth;
Sprite[0].TextureCoord = XMFLOAT2(TexEnd,0.0f);
Sprite[1].TextureCoord = XMFLOAT2(TexEnd,1.0f);
Sprite[2].TextureCoord = XMFLOAT2(texStart,1.0f);
Sprite[3].TextureCoord = XMFLOAT2(texStart,1.0f);
Sprite[4].TextureCoord = XMFLOAT2(texStart,0.0f);
Sprite[5].TextureCoord = XMFLOAT2(TexEnd,0.0f);
Sprite= Sprite + 6;
}
iD3D.DeviceContext->Unmap(FontVertexBuffer,0); //MAP END
UINT stride=sizeof(VertexText);
UINT offset=0;
iD3D.DeviceContext->VSSetShader(iText.Fontvs,0,0);
iD3D.DeviceContext->PSSetShader(iText.Fontps,0,0);
//Projection=XMMatrixPerspectiveFovLH(XM_PIDIV2, 1.0, 0.0f, 1000.0f);
Projection=iD3D.mProjection;
iD3D.WorldCB.mWorldVP=XMMatrixTranspose(Projection);
iD3D.DeviceContext->UpdateSubresource(iD3D.MatrixBuffer, 0, NULL, &iD3D.WorldCB, 0, 0);
iD3D.DeviceContext->VSSetConstantBuffers(0,1,&iD3D.MatrixBuffer);
iD3D.DeviceContext->IASetVertexBuffers(0,1, &iText.FontVertexBuffer, &stride, &offset);
iD3D.DeviceContext->PSSetShaderResources(0,1, &iText.FontSRV);
iD3D.DeviceContext->PSSetSamplers(0,1,&iText.FontSRVSampler);
iD3D.DeviceContext->IASetPrimitiveTopology( D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST );
iD3D.DeviceContext->Draw(6*textSize,0);
return true;
}
If you made it this far, thank you. I think that it might be that my .hlsl file might not be configured properly to receive textures, and I might need to know how textures interface properly with the shader to produce the output. Thanks!
The HLSL was not written correctly to include Texture2D x: register( t0 ) or SamplerState x : register( s0 ), taking in necessary resources for the texture. Another problem has surfaced, but this question has been solved.
I' have the following CgFx file:
struct VertIn {
float4 pos : POSITION;
float4 color : COLOR0;
};
struct VertOut {
float4 pos : POSITION;
float4 color : COLOR0;
};
VertOut vert(VertIn IN) {
VertOut OUT;
OUT.pos = IN.pos;
OUT.color = IN.color;
OUT.color.z = 0.0f;
return OUT;
}
struct FragIn {
float4 color: COLOR;
};
struct FragOut {
float4 color : COLOR;
};
FragOut frag(FragIn IN) {
FragOut OUT;
OUT.color = IN.color;
OUT.color.y = 0.0f;
return OUT;
}
struct GeomIn {
float4 position : POSITION;
float4 color : COLOR0;
};
TRIANGLE void geom(AttribArray<GeomIn> IN) {
for(int i=0; i<IN.length; i++) {
emitVertex(IN[i]);
}
}
technique technique0 {
pass p0 {
VertexShader = compile gp4vp vert(); //line 47
FragmentShader = compile gp4fp frag(); //line 48
GeometryShader = compile gp4gp geom(); //line 49
}
}
when using cgc to verify the 3 shaders, they all compile fine.
but when I try to compile the whole effect using:
context=cgCreateContext();
effect=cgCreateEffectFromFile(context, "my_shader.cgfx", NULL);
if(!effect) {
printf(ygl.cgGetLastErrorString(NULL));
printf(cgGetLastListing(context));
}
then I get the following errors:
CG ERROR : The compile returned an error.
my_shader.cgfx(47) : error C8001: Unknown state 'VertexShader'
my_shader.cgfx(48) : error C8001: Unknown state 'FragmentShader'
my_shader.cgfx(49) : error C8001: Unknown state 'GeometryShader'
What do I do wrong?
After creating your context, you need to call
cgGLRegisterStates(handle);
where handle is your CG context handle. This will register things like VertexShader, PixelShader, FillMode, etc. I'm not sure why those aren't registered by default, but there you have it.
well, solved it, but don't know how. I think the compiler didn't expect CgFx because i did load a cg profile earlier, so it tried to use that one. but not sure.
EDIT: IT seems like the only problem left now is that the light comes from the opposite direction if i use the calculation with a normal map. If i only use:
n = normalize(Input.NorView);
it seems to be fine.
I am starting to learn some HLSL Shading with DirectX10 and I have tried to use a normal map to calculate my phong lightning.
First off here is an example of how far I have come:
http://i.stack.imgur.com/IFAo4.jpg
I am not quite sure if this is what im looking to accomplish with this normal map:
http://i.stack.imgur.com/moQvf.jpg
I dont know..shouldn't this look more 3Dish? Maybe I have just an false understanding of the usage of a normal map, but in my mindset a normal map is used to make a model more detailed by adding shadows based on the normal map, so its looks more 3D ish.
And here is my shading code:
Vertex Shader:
T3dVertexPSIn MeshVS(T3dVertexVSIn Input) {
T3dVertexPSIn output = (T3dVertexPSIn) 0;
float4 tempVar;
output.Pos = mul(float4(Input.Pos.xyz, 1).xyzw, g_WorldViewProjection);
output.Tex = Input.Tex;
tempVar = mul(float4(Input.Pos.xyz, 1).xyzw, g_WorldView);
output.PosView = tempVar.xyz;
tempVar = mul(float4(Input.Nor.xyz, 0).xyzw, g_WorldViewNormals);
output.NorView = tempVar.xyz;
output.NorView = normalize(output.NorView);
tempVar = mul(float4(Input.Tan.xyz, 0).xyzw, g_WorldViewNormals);
output.TanView = tempVar.xyz;
output.TanView = normalize(output.TanView);
return output;
}
Pixel Shader:
float4 MeshPS(T3dVertexPSIn Input) : SV_Target0 {
float4 output = (float4)0; //output color
float3 N = normalize(Input.NorView);
float3 T = Input.TanView;
T = normalize(T - N * dot(N,T));
float3 B = cross(T,N);
column_major float3x3 mTBN= {T, B, N};
float4 matDiffuse = g_Diffuse.Sample(samAnisotropic, Input.Tex);
float4 matSpecular = g_Specular.Sample(samAnisotropic, Input.Tex);
float4 matGlow = g_Glow.Sample(samAnisotropic, Input.Tex);
float4 colLight = float4(1,1,1,1);
float4 colLightAmbient = float4(1,1,1,1);
float3 n = mul(g_Normal.Sample(samAnisotropic, Input.Tex).rgb * 2.0 - 1.0, mTBN);
//float3 n = mul(float3x3(T,B,N), nT);
//float3 n = normalize(Input.NorView);
float4 I = g_LightDirView;
float3 r = reflect(-I.xyz, n);
float3 v = normalize(-Input.PosView);
float cd = 0.5f, cs = 0.3f, ca = 0.1f, cg = 0.3f;
output = cd*matDiffuse*saturate(dot(n,I.xyz))*colLight
+cs*matSpecular*pow(saturate(dot(r.xyz,v)),10)*colLight
+ca*matDiffuse*colLightAmbient
+cg*matGlow;
return output;
}
I also have the feeling that the lightning is changing direction when im using the normal map.but I am not sure.
Maybe someone can explain this matter to me a little bit.
Thanks in advance for any help!
A Normal map does not create shadowing. It, simply, allows you to re-evaluate the lighting per texel.
Seems like i was calculating the normal incorrect and some textures also got the wrong normal.