Hi, this is my first post here. I've been learning C++ On and off for the last 3 years, And have recently picked up a book to learn about 3D Game Engine Programing. I've started my own Game Engine everything Rendering related works except Shaders and i can't figure out why. I have spent the last week looking through tutorials ect. I'm using Visual Studio 2005 with Direct X 9 SDK. The strange thing about my problem is Visual Studio throws no compile errors and my Engine doesn't throw any errors either. I've been debugging and every Shader function return S_OK, in fact the only thing is i cant see the shaders when it renders i.e No lighting ect. it just looks like a Large Black Cube rotating. Ill include the code im using.
Ok This is all of my Engine code for shaders.
void RVD3D::PrepareShaderStuff(void) {
D3DCAPS9 d3dCaps;
if (FAILED(m_pDevice->GetDeviceCaps(&d3dCaps))) {
Log("error: GetDeviceCaps() in PrepareShaderStuff failed");
m_bCanDoShaders = false;
return;
}
if (d3dCaps.VertexShaderVersion < D3DVS_VERSION(1,1) ) {
Log("warning: Vertex Shader Version < 1.1 => no support");
m_bCanDoShaders = false;
return;
}
if (d3dCaps.PixelShaderVersion < D3DPS_VERSION(1,1) ) {
Log("warning: Pixel Shader Version < 1.1 => no support");
m_bCanDoShaders = false;
return;
}
// vertex declarations needed for shaders
D3DVERTEXELEMENT9 declPVertex[] =
{
{ 0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
D3DDECL_END()
};
D3DVERTEXELEMENT9 declVertex[] =
{
{ 0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
{ 0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
{ 0, 24, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
D3DDECL_END()
};
D3DVERTEXELEMENT9 declLVertex[] =
{
{ 0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
{ 0, 12, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
{ 0, 16, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
D3DDECL_END()
};
D3DVERTEXELEMENT9 declCVertex[] =
{
{ 0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
{ 0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
{ 0, 24, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
{ 0, 32, D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 1},
D3DDECL_END()
};
D3DVERTEXELEMENT9 decl3TVertex[] =
{
{ 0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
{ 0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
{ 0, 24, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
{ 0, 32, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 1},
{ 0, 40, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 2},
D3DDECL_END()
};
D3DVERTEXELEMENT9 declTVertex[] =
{
{ 0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
{ 0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
{ 0, 24, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
{ 0, 32, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TANGENT, 0},
D3DDECL_END()
};
// create the declarations
m_pDevice->CreateVertexDeclaration(declVertex, &m_pDeclVertex);
m_pDevice->CreateVertexDeclaration(declPVertex, &m_pDeclPVertex);
m_pDevice->CreateVertexDeclaration(declLVertex, &m_pDeclLVertex);
m_pDevice->CreateVertexDeclaration(declCVertex, &m_pDeclCVertex);
m_pDevice->CreateVertexDeclaration(decl3TVertex, &m_pDecl3TVertex);
m_pDevice->CreateVertexDeclaration(declTVertex, &m_pDeclTVertex);
m_pDevice->SetFVF(NULL);
m_bCanDoShaders = true;
Log("use of shaders activated (VS 1.1, PS 1.1)");
} // PrepareShaderStuff
void RVD3D::UseShaders(bool b) {
if (!m_bCanDoShaders) return;
if (m_bUseShaders == b) return;
// clear all vertex caches
m_pVertexMan->ForcedFlushAll();
m_pVertexMan->InvalidateStates();
m_bUseShaders = b;
// deactivate use of shaders
if (!m_bUseShaders) {
m_pDevice->SetVertexShader(NULL);
m_pDevice->SetPixelShader(NULL);
m_pDevice->SetVertexDeclaration(NULL);
}
else {
m_pDevice->SetFVF(0);
}
} // UseShaders
HRESULT RVD3D::ActivateVShader(UINT nID, RVVERTEXID VertexID) {
if (!m_bCanDoShaders) return RV_NOSHADERSUPPORT;
if (nID >= m_nNumVShaders) return RV_INVALIDID;
// clear all vertex caches
m_pVertexMan->ForcedFlushAll();
// m_pVertexMan->InvalidateStates();
// get size and format of vertex
switch (VertexID) {
case VID_PS: {
if (FAILED(m_pDevice->SetVertexDeclaration(m_pDeclPVertex)))
return RV_FAIL;
} break;
case VID_UU: {
if (FAILED(m_pDevice->SetVertexDeclaration(m_pDeclVertex)))
return RV_FAIL;
} break;
case VID_UL: {
if (FAILED(m_pDevice->SetVertexDeclaration(m_pDeclLVertex)))
return RV_FAIL;
} break;
case VID_CA: {
if (FAILED(m_pDevice->SetVertexDeclaration(m_pDeclCVertex)))
return RV_FAIL;
} break;
case VID_3T: {
if (FAILED(m_pDevice->SetVertexDeclaration(m_pDecl3TVertex)))
return RV_FAIL;
} break;
case VID_TV: {
if (FAILED(m_pDevice->SetVertexDeclaration(m_pDeclTVertex)))
return RV_FAIL;
} break;
default: return RV_INVALIDID;
} // switch
if (FAILED(m_pDevice->SetVertexShader(m_pVShader[nID])))
return RV_FAIL;
m_nActiveVShader = nID;
m_bUseShaders = true;
return RV_OK;
} // ActivateVShader
HRESULT RVD3D::ActivatePShader(UINT nID) {
if (!m_bCanDoShaders) return RV_NOSHADERSUPPORT;
if (nID >= m_nNumPShaders) return RV_INVALIDID;
// clear out buffers prior to state changes
m_pVertexMan->ForcedFlushAll();
// m_pVertexMan->InvalidateStates();
if (FAILED(m_pDevice->SetPixelShader(m_pPShader[nID])))
return RV_FAIL;
m_nActivePShader = nID;
m_bUseShaders = true;
return RV_OK;
} // ActivatePShader
HRESULT RVD3D::SetShaderConstant(RVSHADERTYPE sht,
RVDATATYPE dat,
UINT nReg, UINT nNum,
const void *pData) {
if (!m_bCanDoShaders) return RV_NOSHADERSUPPORT;
if (sht == SHT_VERTEX) {
if (nReg < 20) return RV_INVALIDPARAM;
switch (dat) {
case DAT_BOOL:
m_pDevice->SetVertexShaderConstantB(
nReg, (BOOL*)pData, nNum);
break;
case DAT_INT:
m_pDevice->SetVertexShaderConstantI(
nReg, (int*)pData, nNum);
break;
case DAT_FLOAT:
m_pDevice->SetVertexShaderConstantF(
nReg, (float*)pData, nNum);
break;
default: return RV_FAIL;
} // switch
}
else {
switch (dat) {
case DAT_BOOL:
m_pDevice->SetPixelShaderConstantB(
nReg, (BOOL*)pData, nNum);
break;
case DAT_INT:
m_pDevice->SetPixelShaderConstantI(
nReg, (int*)pData, nNum);
break;
case DAT_FLOAT:
m_pDevice->SetPixelShaderConstantF(
nReg, (float*)pData, nNum);
break;
default: return RV_FAIL;
} // switch
}
return RV_OK;
} // SetShaderConstant
HRESULT RVD3D::CreateVShader(const void *pData, UINT nSize,
bool bLoadFromFile,
bool bIsCompiled, UINT *pID) {
LPD3DXBUFFER pCode=NULL;
LPD3DXBUFFER pDebug=NULL;
HRESULT hrC=RV_OK, hrA=RV_OK;
DWORD *pVS=NULL;
HANDLE hFile, hMap;
// do we have space for one more?
if (m_nNumVShaders >= (MAX_SHADER-1)) {
Log("error: max number of shaders reached in RVD3D::CreateVShader");
return RV_OUTOFMEMORY;
}
// (1): ALREADY ASSEMBLED
if (bIsCompiled) {
// already compiled (from file)
if (bLoadFromFile) {
#ifndef ANSI
string *tstr = new string((char*)pData);
LPCWSTR temp = STRTOWSTR((LPCSTR)tstr->data());
delete tstr;
#else
LPCSTR temp = (LPCSTR)pData;
#endif
hFile = CreateFile(temp, GENERIC_READ,
0, 0, OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL, 0);
if (hFile == INVALID_HANDLE_VALUE) {
Log("error: CreateFile() in RVD3D::CreateVShader failed");
return RV_FILENOTFOUND;
}
hMap = CreateFileMapping(hFile,0,PAGE_READONLY, 0,0,0);
pVS = (DWORD*)MapViewOfFile(hMap,FILE_MAP_READ,0,0,0);
}
// already compiled (from datapointer)
else { pVS = (DWORD*)pData; }
} // if
// (2): STILL NEEDS ASSEMBLING
else {
// not yet compiled (from file)
#ifndef ANSI
string *tstr = new string((char*)pData);
LPCWSTR temp = STRTOWSTR((LPCSTR)tstr->data());
#else
string *tstr = new string((char*)pData);
LPCSTR temp = tstr->data();
#endif
if (bLoadFromFile) {
hrA = D3DXAssembleShaderFromFile(temp,
NULL, NULL, 0,
&pCode, &pDebug);
}
// not yet compiled (from datapointer)
else {
hrA = D3DXAssembleShader(tstr->data(),
nSize-1,
NULL, NULL, 0,
&pCode, &pDebug);
}
delete tstr;
// track errors if any
if (SUCCEEDED(hrA)) {
pVS = (DWORD*)pCode->GetBufferPointer();
}
else {
Log("error: Assemble[Vertex]Shader[FromFile]() failed");
if (hrA==D3DERR_INVALIDCALL)
Log("INVALID_CALL");
else if (hrA==D3DXERR_INVALIDDATA)
Log("D3DXERR_INVALIDDATA");
else if (hrA==E_OUTOFMEMORY)
Log("E_OUTOFMEMORY");
if (pDebug->GetBufferPointer())
Log("Shader debugger says: %s", (char*)pDebug->GetBufferPointer());
else
Log("no debug infos stored");
return RV_FAIL;
}
} // else
// create the shader object
if (FAILED(hrC=m_pDevice->CreateVertexShader(pVS,
&m_pVShader[m_nNumVShaders]))) {
Log("error: CreateVertexShader() failed");
if (hrC==D3DERR_INVALIDCALL)
Log("INVALID_CALL");
else if (hrC==D3DERR_OUTOFVIDEOMEMORY)
Log("D3DERR_OUTOFVIDEOMEMORY");
else if (hrC==E_OUTOFMEMORY)
Log("E_OUTOFMEMORY");
return RV_FAIL;
}
// store index to this shader
if (pID) (*pID) = m_nNumVShaders;
// free resources
if (bIsCompiled && bLoadFromFile) {
UnmapViewOfFile(pVS);
CloseHandle(hMap);
CloseHandle(hFile);
}
m_nNumVShaders++;
return RV_OK;
} // CreateVShader
HRESULT RVD3D::CreatePShader(const void *pData, UINT nSize,
bool bLoadFromFile,
bool bIsCompiled, UINT *pID) {
LPD3DXBUFFER pCode=NULL;
LPD3DXBUFFER pDebug=NULL;
HRESULT hrC=RV_OK, hrA=RV_OK;
DWORD *pPS=NULL;
HANDLE hFile, hMap;
// do we have space for one more?
if (m_nNumPShaders >= (MAX_SHADER-1))
return RV_OUTOFMEMORY;
// (1): ALREADY ASSEMBLED
if (bIsCompiled) {
#ifndef ANSI
string *tstr = new string((char*)pData);
LPCWSTR temp = STRTOWSTR((LPCSTR)tstr->data());
delete tstr;
#else
LPCSTR temp = (LPCSTR)pData;
#endif
// already compiled (from file)
if (bLoadFromFile) {
hFile = CreateFile(temp, GENERIC_READ,
0, 0, OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL, 0);
if (hFile == INVALID_HANDLE_VALUE) {
Log("error: CreateFile() in RVD3D::CreatePShader failed");
return RV_FILENOTFOUND;
}
hMap = CreateFileMapping(hFile,0,PAGE_READONLY, 0,0,0);
pPS = (DWORD*)MapViewOfFile(hMap,FILE_MAP_READ,0,0,0);
}
// already compiled (from datapointer)
else { pPS = (DWORD*)pData; }
} // if
// (2): STILL NEEDS ASSEMBLING
else {
// not yet compiled (from file)
#ifndef ANSI
string *tstr = new string((char*)pData);
LPCWSTR temp = STRTOWSTR((LPCSTR)tstr->data());
#else
string *tstr = new string((char*)pData);
LPCSTR temp = tstr->data();
#endif
if (bLoadFromFile) {
hrA = D3DXAssembleShaderFromFile(temp,
NULL, NULL, 0,
&pCode, &pDebug);
}
// not yet compiled (from datapointer)
else {
hrA = D3DXAssembleShader(tstr->data(),
nSize-1,
NULL, NULL, 0,
&pCode, &pDebug);
}
delete tstr;
// track errors if any
if (SUCCEEDED(hrA)) {
pPS = (DWORD*)pCode->GetBufferPointer();
}
else {
Log("error: Assemble[Pixel]Shader[FromFile]() failed");
if (hrA==D3DERR_INVALIDCALL)
Log("INVALID_CALL");
else if (hrA==D3DXERR_INVALIDDATA)
Log("D3DXERR_INVALIDDATA");
else if (hrA==E_OUTOFMEMORY)
Log("E_OUTOFMEMORY");
if (pDebug->GetBufferPointer())
Log("Shader debugger says: %s", (char*)pDebug->GetBufferPointer());
else
Log("no debug infos stored");
return RV_FAIL;
}
} // else
// create the shader object
if (FAILED(hrC=m_pDevice->CreatePixelShader(pPS,
&m_pPShader[m_nNumPShaders]))) {
Log("error: CreatePixelShader() failed");
if (hrC==D3DERR_INVALIDCALL)
Log("INVALID_CALL");
else if (hrC==D3DERR_OUTOFVIDEOMEMORY)
Log("D3DERR_OUTOFVIDEOMEMORY");
else if (hrC==E_OUTOFMEMORY)
Log("E_OUTOFMEMORY");
return RV_FAIL;
}
// store index to this shader
if (pID) (*pID) = m_nNumPShaders;
// free resources
if (bIsCompiled && bLoadFromFile) {
UnmapViewOfFile(pPS);
CloseHandle(hMap);
CloseHandle(hFile);
}
m_nNumPShaders++;
return RV_OK;
} // CreatePShader
And here is my Example Programs Shader Code
HRESULT ProgramTick(void) {
HRESULT hr = RV_FAIL;
RVMatrix mat;
mat.Identity();
// clear buffers and start scene
g_pDevice->BeginRendering(true,true,true);
Render(-1); // ambient
g_pDevice->UseShaders(false);
g_pDevice->DrawText(g_nFontID, 10, 10, 255, 255, 0,
"Per-Vertex Directional Light Demo");
// flip backbuffer to front
g_pDevice->EndRendering();
return hr;
} // Tick
HRESULT Render(int n) {
static float fR = -0.4f;
RVMatrix mat, matInv;
RVVector vcLightDir(0.0f, 0.0f, 1.0f);
// spin the room around
if (fR < -6.283185f)
fR += 6.283185f;
fR -= 0.02f;
mat.RotaY(fR);
mat._42 -= 0.5f;
mat._41 -= 0.5f;
g_pDevice->SetAmbientLight(0.2f, 0.2f, 0.2f);
g_pDevice->SetWorldTransform(&mat);
// transform light direction to object space
matInv.InverseOf(mat);
vcLightDir = matInv * vcLightDir;
// set light direction to shader constant c20
g_pDevice->SetShaderConstant(SHT_VERTEX, DAT_FLOAT,
20, 1, &vcLightDir);
g_pDevice->ActivateVShader(g_Base[0], VID_TV);
g_pDevice->ActivatePShader(g_Base[1]);
return g_pDevice->GetVertexManager()->Render(g_sRoom);
} // Render
HRESULT BuildAndSetShader(void) {
if (!g_pDevice->CanDoShaders()) return S_OK;
//Vertex Shader
const char vBase[] = "vs.1.1 \n" "dcl_position v0 \n" "dcl_normal v3 \n" "dcl_texcoord v6 \n" "dcl_tangent v8 \n" "m4x4 oPos, v0, c0 \n" "mov oD0, c4 \n" "mov oT0, v6 \n" "mov oT1, v6 \n" "dp3 oD1, v3, -c20 \n";
//Pixel Shader
const char pBase[] = "ps.1.1 \n" "tex t0 \n" "tex t1 \n" "add r0, v0, v1 \n" "mul r0, r0, t0 \n" "add r1, v0, v1 \n" "mul r1, r1, t1 \n" "mul r0, r0, r1 \n";
UINT tpval1 = (UINT)strlen(vBase);
UINT tpval2 = (UINT)strlen(pBase);
g_pDevice->CreateVShader(&vBase, tpval1, false, false, &g_Base[0]);
g_pDevice->CreatePShader(&pBase, tpval2, false, false, &g_Base[1]);
return RV_OK;
} // BuildAndSetShader
I hope that is enough information for you guys to help me. I've been try to figure this thing out for about a week.
Thanks in advance
GuTeR