📄 shader_modelview.cpp
字号:
NVComplexMeshBounds Bounds;
m_pMesh->ComputeBounds(Bounds);
m_pMesh->Translate(-Bounds.m_vecCenter);
m_pMesh->Scale(1.0f / Bounds.m_fRadius);
UpdateMeshMaterials();
// Prepare the mesh for rendering
hr = m_pMesh->PrepareDeviceObjects(m_pD3DDev);
if (FAILED(hr))
{
m_strLastError = "Loaded, but can't render " + m_strFileName;
MessageBox(NULL, m_strLastError.c_str(), "Error", MB_ICONEXCLAMATION);
SAFE_DELETE(m_pMesh);
return E_FAIL;
}
return S_OK;
}
HRESULT CShaderModelView::UpdateMeshMaterials()
{
// Get a list of sections. We assume we only have pass1, because we created the mesh from
// a mesh file
tSectionList& Sections = m_pMesh->GetPass(0)->GetSections();
tSectionList::iterator itrSections = Sections.begin();
// Walk all the model sections in this pass
while (itrSections != Sections.end())
{
// Set the constants and vertex shaders in this section
NVMaterialResource* pMaterial = NVMaterialResource::GetMaterialResource(itrSections->GetMaterialID());
if (pMaterial)
{
NVConstant* pConstant;
// Tell the mesh where to place it's constants
pConstant = pMaterial->FindConstant("diffuse");
if (pConstant)
pConstant->SetLocation(CV_MAT_DIFFUSE);
pConstant = pMaterial->FindConstant("ambient");
if (pConstant)
pConstant->SetLocation(CV_MAT_AMBIENT);
pConstant = pMaterial->FindConstant("specular");
if (pConstant)
{
pMaterial->AddRenderState(D3DRS_SPECULARENABLE, TRUE);
pConstant->SetLocation(CV_MAT_SPECULAR);
}
else
{
pMaterial->AddRenderState(D3DRS_SPECULARENABLE, FALSE);
}
pConstant = pMaterial->FindConstant("power");
if (pConstant)
pConstant->SetLocation(CV_MAT_POWER);
pMaterial->RestoreTexture(0);
if (m_bHasTexture)
{
if (m_bDirectionalBump)
{
// Setup the vertex shader
pMaterial->AddVertexShader(m_dwDirectionalLightBumpShader);
// Setup texture properties
pMaterial->AddTexture(0, NVRESOURCEMANAGER.FindResourceID("DefaultBumpMap"));
pMaterial->AddTextureStageState(0, D3DTSS_TEXCOORDINDEX, 0);
pMaterial->AddTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
pMaterial->AddTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE);
pMaterial->AddTextureStageState(0, D3DTSS_COLOROP, D3DTOP_DOTPRODUCT3);
pMaterial->AddTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_DISABLE);
pMaterial->AddTextureStageState(0, D3DTSS_MAGFILTER, D3DTEXF_LINEAR);
pMaterial->AddTextureStageState(0, D3DTSS_MINFILTER, D3DTEXF_LINEAR);
pMaterial->AddTextureStageState(0, D3DTSS_MIPFILTER, D3DTEXF_LINEAR);
// Stage 1 has the base texture.
// Modulate the bump output from the previous stage by the current texture
// Use 2x to brighten it up a bit.
pMaterial->AddTexture(1, NVRESOURCEMANAGER.FindResourceID("DefaultBaseTexture"));
pMaterial->AddTextureStageState(1, D3DTSS_TEXCOORDINDEX, 1 );
pMaterial->AddTextureStageState(1, D3DTSS_COLORARG1, D3DTA_TEXTURE);
pMaterial->AddTextureStageState(1, D3DTSS_COLORARG2, D3DTA_CURRENT);
pMaterial->AddTextureStageState(1, D3DTSS_COLOROP, D3DTOP_MODULATE2X);
pMaterial->AddTextureStageState(1, D3DTSS_MAGFILTER, D3DTEXF_LINEAR);
pMaterial->AddTextureStageState(1, D3DTSS_MINFILTER, D3DTEXF_LINEAR);
pMaterial->AddTextureStageState(1, D3DTSS_MIPFILTER, D3DTEXF_LINEAR);
}
else
{
pMaterial->AddTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
pMaterial->AddTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE);
pMaterial->AddTextureStageState(0, D3DTSS_MAGFILTER, D3DTEXF_LINEAR);
pMaterial->AddTextureStageState(0, D3DTSS_MINFILTER, D3DTEXF_LINEAR);
pMaterial->AddTextureStageState(0, D3DTSS_MIPFILTER, D3DTEXF_LINEAR);
pMaterial->AddTextureStageState(0, D3DTSS_TEXCOORDINDEX, 0);
pMaterial->AddVertexShader(m_dwDirectionalLightShader);
if (NVTextureResource::GetTexture(pMaterial->GetTextureID(0)) != NULL)
{
pMaterial->AddTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE);
}
else
{
pMaterial->AddTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG2);
}
pMaterial->AddTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE);
}
}
else
{
pMaterial->AddVertexShader(m_dwDirectionalLightShader);
pMaterial->AddTextureStageState(0, D3DTSS_TEXCOORDINDEX, 0);
pMaterial->AddTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
pMaterial->AddTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE);
pMaterial->AddTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG2);
pMaterial->AddTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE);
}
}
itrSections++;
}
return S_OK;
}
HRESULT CShaderModelView::SetVertexShaderMatrices()
{
D3DXMATRIX WorldViewProjection, WorldViewIT, World;
D3DXMatrixMultiply(&World, &m_pUI->GetRotationMatrix(), &m_pUI->GetTranslationMatrix());
D3DXMatrixMultiply(&WorldViewProjection, &World, &m_matView);
D3DXMatrixInverse(&WorldViewIT, NULL, &WorldViewProjection);
D3DXMatrixMultiply(&WorldViewProjection, &WorldViewProjection, &m_matProjection);
D3DXMatrixTranspose(&WorldViewProjection, &WorldViewProjection);
NVStateManager::GetSingleton().SetVertexShaderConstant(CV_WORLDVIEWPROJ_0, &WorldViewProjection, 4);
NVStateManager::GetSingleton().SetVertexShaderConstant(CV_WORLDVIEWIT_0, &WorldViewIT, 4);
// Transform direction vector into eye space
D3DXVECTOR3 vLight = D3DXVECTOR3(0.3f, 0.0f, 1.0f);
D3DXVECTOR3 vLightToEye;
D3DXVec3Normalize(&vLightToEye, &vLight);
D3DXVec3TransformNormal(&vLightToEye, &vLightToEye, &m_matView);
D3DXVec3Normalize(&vLightToEye, &vLightToEye);
// Shader math requires vector towards light
D3DXVECTOR4 vLightEye;
vLightEye.x = -vLightToEye.x;
vLightEye.y = -vLightToEye.y;
vLightEye.z = -vLightToEye.z;
vLightEye.w = 1.0f;
NVStateManager::GetSingleton().SetVertexShaderConstant(CV_LIGHT1_DIRECTION, &vLightEye, 1);
D3DXMatrixTranspose(&World, &World);
NVStateManager::GetSingleton().SetVertexShaderConstant(CV_WORLD_0, &World, 4);
return S_OK;
}
void CShaderModelView::PropertyUpdateCallback(const EBProperty* pProperty, bool bWritten)
{
if (!bWritten)
return;
if (pProperty->IsKindOf(EBTYPE_TRIGGER_PROP))
{
if (pProperty->GetPropertyName().compare("Flip Normals") == 0)
{
if (m_pMesh)
m_pMesh->FlipNormals();
// Prepare the mesh for rendering
m_pMesh->PrepareDeviceObjects(m_pD3DDev);
}
else
{
OPENFILENAME ofn;
ZeroMemory(&ofn, sizeof(OPENFILENAME));
#define PATH_SIZE 2048
char FileName[PATH_SIZE] = "";
ofn.lStructSize = sizeof(OPENFILENAME);
ofn.hwndOwner = NULL;
ofn.hInstance = NULL;
ofn.lpstrFilter = "Model Files (*.x, *.m)\0*.x;*.m\0\0";
ofn.lpstrCustomFilter = NULL;
ofn.nMaxCustFilter = 0;
ofn.nFilterIndex = 0;
ofn.lpstrFile = &FileName[0];
ofn.nMaxFile = PATH_SIZE;
ofn.lpstrFileTitle = NULL;
ofn.nMaxFileTitle = 0;
ofn.lpstrInitialDir = NULL;
ofn.lpstrTitle = NULL;
ofn.Flags = OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST;
ofn.nFileOffset = 0;
ofn.nFileExtension = 0;
ofn.lpstrDefExt = NULL;
int iSuccess = GetOpenFileName(&ofn);
if (iSuccess > 0)
{
LoadMesh(&FileName[0]);
}
else
{
// Might be OK if the user hit cancel
DWORD dwErr = CommDlgExtendedError();
}
}
}
else
{
if (pProperty->GetPropertyName().compare(STR_DIRECTIONALBUMP) == 0)
{
UpdateMeshMaterials();
}
}
}
// ------------------------------------------------------------------------------
// CShaderModelView::Free
//
// Description: Called when we switch away from this demo. Free up all the
// memory that is in use.
// ------------------------------------------------------------------------------
HRESULT CShaderModelView::Free()
{
SAFE_DELETE(m_pMesh);
if (m_pD3DDev)
{
if (m_dwDirectionalLightShader)
m_pD3DDev->DeleteVertexShader(m_dwDirectionalLightShader);
if (m_dwDirectionalLightBumpShader)
m_pD3DDev->DeleteVertexShader(m_dwDirectionalLightBumpShader);
m_dwDirectionalLightShader = 0;
m_dwDirectionalLightBumpShader = 0;
SAFE_RELEASE(m_pD3DDev);
}
delete m_pUI, m_pUI = 0;
SAFE_DELETE(g_pStateManager);
SAFE_DELETE(g_pResourceManager);
return S_OK;
}
// ------------------------------------------------------------------------------
// CShaderModelView::Start
//
// Description: Called to reset
// ------------------------------------------------------------------------------
HRESULT CShaderModelView::Start()
{
return S_OK;
}
// ------------------------------------------------------------------------------
// CShaderModelView::Tick
//
// Description: This function is called every frame. Here is where we write
// and update constants, clear the z- and back-buffer and render our
// primitives
// ------------------------------------------------------------------------------
HRESULT CShaderModelView::Tick(EBTimer* pTimer)
{
HRESULT hr = S_OK;
SetVertexShaderMatrices();
NVSTATEMANAGER.SetRenderState(D3DRS_FILLMODE, (m_bWireframe ? D3DFILL_WIREFRAME : D3DFILL_SOLID));
m_pD3DDev->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0x00BFBFBF, 1.0f, 0L);
if (m_pMesh)
m_pMesh->Render(m_pD3DDev);
return hr;
}
void CShaderModelView::MouseButton(HWND hWnd, eButtonID button, bool bDown, int x, int y)
{
if(button == MOUSE_LEFTBUTTON)
{
if(bDown)
{
m_pUI->OnLButtonDown(x, y);
}
else
{
m_pUI->OnLButtonUp(x, y);
}
}
return;
}
void CShaderModelView::MouseMove(HWND hWnd, int x, int y)
{
m_pUI->OnMouseMove(x, y);
return;
}
void CShaderModelView::Keyboard(DWORD dwKey, UINT nFlags, bool bDown)
{
eEBKeyAction Action = TranslateEffectKey(dwKey, nFlags, bDown);
switch(Action)
{
case EB_HELP:
{
MessageBoxEx( NULL, " Help : F1 - Help \n\n Home - Reset To Defaults \n\n W - Wireframe Toggle \n\n Space\\Pause - Toggle Pause/Resume \n\n Left Button & Mouse - Rotate Object\n\n Shift Left Button & Mouse - Pan Camera \n\n Ctrl Left Button & Mouse - Move Camera In & Out\n\n",
"Help", MB_ICONINFORMATION | MB_TASKMODAL, MAKELANGID( LANG_NEUTRAL, SUBLANG_DEFAULT ) );
}
break;
case EB_RESET:
{
m_pUI->Reset();
}
break;
case EB_PAUSE:
{
m_bPause = !m_bPause;
m_dwEffectDirtyFlags |= EBEFFECT_DIRTY_PUBLICSTATE;
}
break;
case EB_WIREFRAME:
{
m_bWireframe = !m_bWireframe;
m_dwEffectDirtyFlags |= EBEFFECT_DIRTY_PUBLICSTATE;
}
break;
default:
break;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -