📄 shader_lighting.cpp
字号:
m_pD3DDev->SetVertexShaderConstant(CV_ONE, D3DXVECTOR4(1.0f, 1.0f, 1.0f, 1.0f), 1);
// Half vector is used in lighting calculations
D3DXVECTOR4 HalfVector(0.0f, 0.0f, -1.0f, 0.0f);
m_pD3DDev->SetVertexShaderConstant(CV_EYE_VECTOR, &HalfVector.x, 1);
// material power
D3DXVECTOR4 MaterialPower(0.0f, 0.0f, 0.0f, 5.0f);
m_pD3DDev->SetVertexShaderConstant(CV_MATPOWER, &MaterialPower.x, 1);
// Attenuation for lights
D3DXVECTOR4 Attenuation(1.0f, 0.0f, 0.0f, 0.0f);
m_pD3DDev->SetVertexShaderConstant(CV_LIGHT1_ATTENUATION, &Attenuation.x, 1);
m_pD3DDev->SetVertexShaderConstant(CV_LIGHT2_ATTENUATION, &Attenuation.x, 1);
m_pD3DDev->SetVertexShaderConstant(CV_LIGHT3_ATTENUATION, &Attenuation.x, 1);
// Camera stuff
D3DXMATRIX matProj;
D3DXMATRIX matView;
D3DXVECTOR3 vEyePt = D3DXVECTOR3( 0.0f, 0.0f, -3.5f );
D3DXVECTOR3 vLookatPt = D3DXVECTOR3( 0.0f, 0.0f, 0.0f );
D3DXVECTOR3 vUp = D3DXVECTOR3( 0.0f, 1.0f, 0.0f );
// View
D3DXMatrixLookAtLH(&matView, &vEyePt, &vLookatPt, &vUp);
// Projection
D3DXMatrixPerspectiveFovLH(&matProj, D3DXToRadian(60.0f), 1.0f, 0.5f, 20.0f);
m_pNVDevice->SetViewTransform(&matView);
m_pNVDevice->SetProjectionTransform(&matProj);
if (m_pShapeMesh)
m_pShapeMesh->RestoreDeviceObjects(m_pNVDevice);
if (m_pLightMesh)
m_pLightMesh->RestoreDeviceObjects(m_pNVDevice);
return S_OK;
}
HRESULT CShaderLighting::Free()
{
SAFE_DELETE(m_pShapeMesh);
SAFE_DELETE(m_pLightMesh);
SAFE_RELEASE(m_pSphereBuffer);
SAFE_DELETE(m_pNVDevice);
SAFE_DELETE(m_pUI);
if (m_pD3DDev)
{
m_pD3DDev->DeleteVertexShader(m_dwCurrentShader);
SAFE_RELEASE(m_pD3DDev);
}
return S_OK;
}
HRESULT CShaderLighting::Start()
{
m_fAngle = 0.0f;
return S_OK;
}
HRESULT CShaderLighting::SetTransform()
{
D3DXMATRIX matTemp;
D3DXMATRIX matWorldViewProj;
D3DXMATRIX matWorldView;
D3DXMATRIX matWorldViewIT;
D3DXMATRIX matWorld = m_pNVDevice->GetWorldTransform();
D3DXMATRIX matProj = m_pNVDevice->GetProjectionTransform();
D3DXMATRIX matView = m_pNVDevice->GetViewTransform();
D3DXMatrixMultiply(&matTemp, &matWorld, &matView);
D3DXMatrixMultiply(&matWorldViewProj, &matTemp, &matProj);
D3DXMatrixMultiply(&matWorldView, &matWorld, &matView);
// Create a 3x3 invertse of the worldview for the normal transformation (we transpose it as we load it into
// the constant store)
D3DXMatrixInverse(&matWorldViewIT, NULL, &matWorldView);
// Projection to clip space
D3DXMatrixTranspose(&matWorldViewProj, &matWorldViewProj);
m_pD3DDev->SetVertexShaderConstant(CV_WORLDVIEWPROJ_0, &matWorldViewProj(0, 0), 4);
D3DXMatrixTranspose(&matWorldViewProj, &matWorldViewProj);
// Transform to eye space
D3DXMatrixTranspose(&matWorldView, &matWorldView);
m_pD3DDev->SetVertexShaderConstant(CV_WORLDVIEW_0, &matWorldView(0, 0), 4);
D3DXMatrixTranspose(&matWorldView, &matWorldView);
// Transform for normals
m_pD3DDev->SetVertexShaderConstant(CV_WORLDVIEWIT_0, &matWorldViewIT(0, 0), 1);
m_pD3DDev->SetVertexShaderConstant(CV_WORLDVIEWIT_1, &matWorldViewIT(1, 0), 1);
m_pD3DDev->SetVertexShaderConstant(CV_WORLDVIEWIT_2, &matWorldViewIT(2, 0), 1);
return S_OK;
}
HRESULT CShaderLighting::Tick(EBTimer* pTimer)
{
HRESULT hr = S_OK;
DWORD i;
D3DXMATRIX matWorld;
D3DXMATRIX matView = m_pNVDevice->GetViewTransform();
D3DXMATRIX matTemp;
// Clear to grey
hr = m_pD3DDev->Clear(0, NULL, D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB( 0xAA, 0xAA, 0xAA ), 1.0, 0);
m_pD3DDev->SetRenderState(D3DRS_FILLMODE, m_bWireframe ? D3DFILL_WIREFRAME : D3DFILL_SOLID);
// Increase rotation
if (!m_bPause)
{
m_fAngle = pTimer->GetDuration() * 100.0f;
}
matWorld = m_pUI->GetRotationMatrix() * m_pUI->GetTranslationMatrix();
if (m_LightType != LIGHTTYPE_TWOSIDE)
{
const NVBounds* pBounds = m_pShapeMesh->GetBounds();
// Move the loaded object to the middle and scale
D3DXMatrixScaling(&matTemp, 1.0f / pBounds->m_fRadius, 1.0f / pBounds->m_fRadius, 1.0f / pBounds->m_fRadius);
D3DXMatrixMultiply(&matWorld, &matWorld, &matTemp);
D3DXMatrixTranslation(&matTemp, -pBounds->m_vecCenter.x, -pBounds->m_vecCenter.y, -pBounds->m_vecCenter.z);
D3DXMatrixMultiply(&matWorld, &matTemp, &matWorld);
}
// Load transform data.
m_pNVDevice->SetWorldTransform(&matWorld);
SetTransform();
// Update the light positions
vector<D3DXVECTOR3>vLight;
vLight.resize(m_dwNumLights);
float fAngleIncr = 360.0f / m_dwNumLights;
for (i = 0; i < m_dwNumLights; i++)
{
float x, y, z;
float fLightDistance = 0.3f + 1.0f;
D3DXVECTOR3 vecLightAngles;
fLightDistance = 1.0f;
//fLightDistance = 0.5f;
vecLightAngles.x = D3DXToRadian(-m_fAngle + fAngleIncr * i);
vecLightAngles.y = D3DXToRadian(m_fAngle + fAngleIncr * i);
vecLightAngles.z = D3DXToRadian(m_fAngle + 45.0f + fAngleIncr * i);
x = fLightDistance * cos(vecLightAngles.x);
y = fLightDistance * sin(vecLightAngles.y);
z = fLightDistance * sin(vecLightAngles.z);
// For directional, create a light vector that points towards the origin
switch(m_LightType)
{
case LIGHTTYPE_TWOSIDE:
z = 1.1f;
x = -x;
y = -y;
break;
case LIGHTTYPE_POINT:
case LIGHTTYPE_MANYPOINT:
break;
case LIGHTTYPE_DIRECTIONAL:
x = -x;
y = -y;
z = -z;
break;
}
vLight[i] = D3DXVECTOR3(x, y, z);
D3DXVECTOR4 vLightEye;
if (m_LightType == LIGHTTYPE_POINT)
{
vLight[i] += D3DXVECTOR3(matWorld._41, matWorld._42, matWorld._43);
D3DXVec3Transform(&vLightEye, &vLight[i], &matView);
}
else if (m_LightType == LIGHTTYPE_MANYPOINT)
{
D3DXMATRIX matWorldInverse;
vLight[i] += D3DXVECTOR3(matWorld._41, matWorld._42, matWorld._43);
// Transform light back to model space where the lighting will be done
D3DXMatrixInverse(&matWorldInverse, NULL, &matWorld);
D3DXVec3Transform(&vLightEye, &vLight[i], &matWorldInverse);
}
else
{
D3DXVECTOR3 vLightToEye;
// Transform direction vector into eye space
D3DXVec3Normalize(&vLightToEye, &vLight[i]);
D3DXVec3TransformNormal(&vLightToEye, &vLightToEye, &matView);
D3DXVec3Normalize(&vLightToEye, &vLightToEye);
// Shader math requires that the vector is to the light
vLightEye.x = -vLightToEye.x;
vLightEye.y = -vLightToEye.y;
vLightEye.z = -vLightToEye.z;
vLightEye.w = 1.0f;
}
m_pD3DDev->SetVertexShaderConstant(CV_LIGHT1_POSITION + i, &vLightEye.x, 1);
}
// Draw the object
switch(m_LightType)
{
case LIGHTTYPE_TWOSIDE:
m_pD3DDev->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
break;
default:
m_pD3DDev->SetRenderState(D3DRS_CULLMODE, D3DCULL_CCW);
break;
}
if (m_LightType != LIGHTTYPE_TWOSIDE)
{
m_pShapeMesh->Render(m_pNVDevice);
}
else
{
m_pD3DDev->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
// Point at the vertex data
hr = m_pD3DDev->SetStreamSource(0, m_pSphereBuffer, (sizeof(D3DXVECTOR3) * 3));
if (FAILED(hr))
return hr;
D3DXCOLOR LightFront;
D3DXCOLOR LightBack;
D3DXCOLOR matFront(1.0f, 0.0f, 0.0f, 1.0f);
D3DXCOLOR matBack(1.0f, 1.0f, 1.0f, 1.0f);
// Lighting colors - Light 1
D3DXColorModulate(&LightFront, &m_LightColorDiffuse[0], &matFront);
D3DXColorModulate(&LightBack, &m_LightColorDiffuse[0], &matBack);
m_pD3DDev->SetVertexShaderConstant(CV_FRONTCOLOR, &LightFront.r, 1);
m_pD3DDev->SetVertexShaderConstant(CV_BACKCOLOR, &LightBack.r, 1);
m_pD3DDev->SetVertexShader(m_dwCurrentShader);
m_pD3DDev->DrawPrimitive(D3DPT_TRIANGLELIST, 0, m_dwSphereFaces / 2);
}
// Draw the lights
m_pD3DDev->SetRenderState(D3DRS_CULLMODE, D3DCULL_CCW);
hr = m_pD3DDev->SetVertexShader(m_dwFixedColorShader);
if (FAILED(hr))
return hr;
// Don't want textures
m_pD3DDev->SetTexture(0, NULL);
D3DXMATRIX TeapotWorld = matWorld;
// Walk the list of lights, calculate the correct info needed in the vertex shader to apply them,
// and draw them
for (i = 0; i < m_dwNumLights; i++)
{
const NVBounds* pBounds = m_pLightMesh->GetBounds();
D3DXMatrixIdentity(&matWorld);
// Translate to the middle
D3DXMatrixTranslation(&matTemp, -pBounds->m_vecCenter.x, -pBounds->m_vecCenter.y, -pBounds->m_vecCenter.z);
D3DXMatrixMultiply(&matWorld, &matWorld, &matTemp);
float fLightScale = 0.1f;
D3DXMatrixScaling(&matTemp, fLightScale / pBounds->m_fRadius, fLightScale / pBounds->m_fRadius, fLightScale / pBounds->m_fRadius);
D3DXMatrixMultiply(&matWorld, &matWorld, &matTemp);
if ((m_LightType != LIGHTTYPE_POINT) && (m_LightType != LIGHTTYPE_MANYPOINT))
{
// Orientation of the light object (the arrow)
D3DXVECTOR3 vLightObject = D3DXVECTOR3(0.0f, -1.0f, 0.0f);
// Create the rotation axis
D3DXVECTOR3 vOrthoNormal;
D3DXVec3Cross(&vOrthoNormal, &vLight[i], &vLightObject);
D3DXVec3Normalize(&vOrthoNormal, &vOrthoNormal);
D3DXVECTOR3 vLightDirection;
D3DXVec3Normalize(&vLightDirection, &vLight[i]);
// Calculate the angle between the two vectors.
float fAngle = acos(D3DXVec3Dot(&vLightDirection, &vLightObject));
// Rotate the object about our rotation axis to map one vector onto another
D3DXMatrixRotationAxis(&matTemp, &vOrthoNormal, -fAngle);
D3DXMatrixMultiply(&matWorld, &matWorld, &matTemp);
// vLight is a direction vector, pointing at the origin, so we negate it to find the position
D3DXMatrixTranslation(&matTemp, -vLight[i].x, -vLight[i].y, -vLight[i].z);
matTemp._41 += TeapotWorld._41;
matTemp._42 += TeapotWorld._42;
matTemp._43 += TeapotWorld._43;
D3DXMatrixMultiply(&matWorld, &matWorld, &matTemp);
}
else
{
// Put the light at it's location
D3DXMatrixTranslation(&matTemp,vLight[i].x, vLight[i].y, vLight[i].z);
D3DXMatrixMultiply(&matWorld, &matWorld, &matTemp);
}
m_pNVDevice->SetWorldTransform(&matWorld);
SetTransform();
// Set the fixed color for the light
m_dwCurrentLightDraw = i;
m_pLightMesh->Render(m_pNVDevice);
}
m_dwCurrentLightDraw = -1;
return hr;
}
// This setmaterial call is made by the mesh renderer when it needs to change the material for the shape
// it is about to draw. We use the opportunity to calculate the light properties for the lights shining
// on the material
HRESULT NVLightingDevice::SetMaterial(D3DMATERIAL8* pMat)
{
DWORD dwCurrentLight;
D3DXCOLOR LightAmbient;
D3DXCOLOR LightDiffuse;
D3DXCOLOR LightSpecular;
D3DXCOLOR matAmbient(0.0f, 0.6f, 0.6f, 1.0f);
D3DXCOLOR matDiffuse(pMat->Diffuse);
D3DXCOLOR matSpecular(pMat->Specular);
// Lighting colors - Light 1
for (dwCurrentLight = 0; dwCurrentLight < m_pLightingShader->m_dwNumLights; dwCurrentLight++)
{
D3DXColorModulate(&LightAmbient, &m_pLightingShader->m_LightColorAmbient[dwCurrentLight], &matAmbient);
D3DXColorModulate(&LightDiffuse, &m_pLightingShader->m_LightColorDiffuse[dwCurrentLight], &matDiffuse);
D3DXColorModulate(&LightSpecular, &m_pLightingShader->m_LightColorSpecular[dwCurrentLight], &matSpecular);
// We only do ambient/specular for the directional/point light case.
// The many point lights sample doesn't do ambient and specular
if (m_pLightingShader->m_LightType != LIGHTTYPE_MANYPOINT)
{
m_pD3DDev->SetVertexShaderConstant(CV_LIGHT1_AMBIENT + dwCurrentLight, &LightAmbient.r, 1);
m_pD3DDev->SetVertexShaderConstant(CV_LIGHT1_SPECULAR + dwCurrentLight, &LightSpecular.r, 1);
}
m_pD3DDev->SetVertexShaderConstant(CV_LIGHT1_DIFFUSE + dwCurrentLight, &LightDiffuse.r, 1);
// Are we currently drawing the lights themselves?
if (m_pLightingShader->m_dwCurrentLightDraw != -1)
{
// By default the fixed color is loaded with the light color, but when we are rendering the
// 'handle' of the directional arrows, we want to use the default material
if ((GetRenderPart() == 0) &&
((m_pLightingShader->m_LightType == LIGHTTYPE_DIRECTIONAL) || (m_pLightingShader->m_LightType == LIGHTTYPE_TWOSIDE)))
m_pD3DDev->SetVertexShaderConstant(CV_FIXED_COLOR, &pMat->Diffuse.r, 1);
else
m_pD3DDev->SetVertexShaderConstant(CV_FIXED_COLOR, &m_pLightingShader->m_LightColorDiffuse[m_pLightingShader->m_dwCurrentLightDraw].r, 1);
}
}
return S_OK;
}
HRESULT CShaderLighting::ConfirmDevice(D3DCAPS8* pCaps, DWORD dwBehavior, D3DFORMAT Format)
{
return S_OK;
}
void CShaderLighting::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 CShaderLighting::MouseMove(HWND hWnd, int x, int y)
{
m_pUI->OnMouseMove(x, y);
return;
}
void CShaderLighting::Keyboard(DWORD dwKey, UINT nFlags, bool bDown)
{
eEBKeyAction Action = TranslateEffectKey(dwKey, nFlags, bDown);
static const float fTranslateMagnitude = 0.1f;
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_WIREFRAME:
{
m_bWireframe = !m_bWireframe;
m_dwEffectDirtyFlags |= EBEFFECT_DIRTY_PUBLICSTATE;
}
break;
case EB_RESET:
{
m_pUI->Reset();
m_bWireframe = false;
m_dwEffectDirtyFlags |= EBEFFECT_DIRTY_PUBLICSTATE;
}
break;
case EB_PAUSE:
{
m_bPause = !m_bPause;
m_dwEffectDirtyFlags |= EBEFFECT_DIRTY_PUBLICSTATE;
}
break;
default :
break;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -