📄 shader_brdf.cpp
字号:
m_pD3DDev->SetTextureStageState(0, D3DTSS_MAGFILTER, D3DTEXF_LINEAR );
m_pD3DDev->SetTextureStageState(0, D3DTSS_MIPFILTER, D3DTEXF_LINEAR);
m_pD3DDev->SetRenderState( D3DRS_ALPHABLENDENABLE, FALSE);
m_pD3DDev->SetRenderState( D3DRS_SRCBLEND, D3DBLEND_SRCALPHA );
m_pD3DDev->SetRenderState( D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
//load textures
hr = D3DXCreateTextureFromFile(m_pD3DDev, GetFilePath("woman.dds").c_str(), &m_pWomanTexture);
if (FAILED(hr))
return hr;
// create a normalization cubemap
hr = CreateNormalizationCubeMap(m_pD3DDev, 256, 9, &m_pNormalizingTexture);
if (FAILED(hr))
return hr;
hr = CreateMinnaertMap(m_pD3DDev, 256, 256, 0, &m_pMinnaertTexture, m_MinnaertPower);
if (FAILED(hr))
return hr;
//load textures
hr = D3DXCreateTextureFromFile(m_pD3DDev, GetFilePath("velvetBump.dds").c_str(), &m_pVelvetBumpMapTexture);
if (FAILED(hr))
return hr;
Create2DBitmap(0, 0, 100, 100);
CreateTestQuad();
m_pD3DDev->SetTexture(1, m_pWomanTexture);
m_pD3DDev->SetTextureStageState(0, D3DTSS_TEXCOORDINDEX, 0);
m_pD3DDev->SetTextureStageState(0, D3DTSS_ADDRESSU, D3DTADDRESS_CLAMP);
m_pD3DDev->SetTextureStageState(0, D3DTSS_ADDRESSV, D3DTADDRESS_CLAMP);
m_pD3DDev->SetTextureStageState(0, D3DTSS_MINFILTER, D3DTEXF_POINT);
m_pD3DDev->SetTextureStageState(0, D3DTSS_MAGFILTER, D3DTEXF_POINT);
m_pD3DDev->SetTextureStageState(0, D3DTSS_MIPFILTER, D3DTEXF_NONE);
m_pD3DDev->SetTextureStageState(1, D3DTSS_TEXCOORDINDEX, 1);
m_pD3DDev->SetTextureStageState(1, D3DTSS_ADDRESSU, D3DTADDRESS_CLAMP);
m_pD3DDev->SetTextureStageState(1, D3DTSS_ADDRESSV, D3DTADDRESS_CLAMP);
m_pD3DDev->SetTextureStageState(1, D3DTSS_MINFILTER, D3DTEXF_POINT);
m_pD3DDev->SetTextureStageState(1, D3DTSS_MAGFILTER, D3DTEXF_POINT);
m_pD3DDev->SetTextureStageState(1, D3DTSS_MIPFILTER, D3DTEXF_NONE);
m_pD3DDev->SetTextureStageState(2, D3DTSS_TEXCOORDINDEX, 2);
m_pD3DDev->SetTextureStageState(2, D3DTSS_ADDRESSU, D3DTADDRESS_CLAMP);
m_pD3DDev->SetTextureStageState(2, D3DTSS_ADDRESSV, D3DTADDRESS_CLAMP);
m_pD3DDev->SetTextureStageState(2, D3DTSS_MINFILTER, D3DTEXF_POINT);
m_pD3DDev->SetTextureStageState(2, D3DTSS_MAGFILTER, D3DTEXF_POINT);
m_pD3DDev->SetTextureStageState(2, D3DTSS_MIPFILTER, D3DTEXF_NONE);
if(m_bUseTrilinear)
m_pD3DDev->SetTextureStageState(0, D3DTSS_MIPFILTER, D3DTEXF_LINEAR);
// setup our object pitched about 90 degrees, because of 3ds max exporter
// doesn't
#ifdef TESTQUAD
D3DXMatrixRotationYawPitchRoll(&m_MatObject[WOMAN_OBJECT], D3DXToRadian(0.0f), D3DXToRadian(0.0f), D3DXToRadian(0.0f));
#else
D3DXMatrixIdentity(&m_MatObject[WOMAN_OBJECT]);
#endif
D3DXMatrixIdentity(&m_MatObject[LIGHT_OBJECT]);
SetLightPosition();
// make enough room for camera to rotate around radius of object,
// with a gap of approximately 1/4 of the size of the light object.
SetupFixedCamera(m_ObjectRadius[WOMAN_OBJECT]+(m_ObjectRadius[LIGHT_OBJECT]*1.5f));
return S_OK;
}
void CShaderBRDF::SetupFixedCamera(float radius)
{
m_vEyePt = D3DXVECTOR3( 0.0f, 0.0f, -2.0f*radius);
m_vLookatPt = D3DXVECTOR3( 0.0f, 0.0f, 0.0f);
m_vUp = D3DXVECTOR3( 0.0f, 1.0f, 0.0f);
D3DXMatrixLookAtLH(&m_MatView, &m_vEyePt, &m_vLookatPt, &m_vUp);
FLOAT fAspect = m_D3DViewPort.Width / (FLOAT)m_D3DViewPort.Height;
D3DXMatrixPerspectiveFovLH( &m_MatProj, D3DX_PI/4, fAspect, 100.0f,
radius*4);
}
void CShaderBRDF::UpdateObject(DWORD index)
{
D3DXMATRIX matRotationInverse;
D3DXMATRIX matRotation;
D3DXMATRIX matTemp;
D3DXMatrixTranslation( &m_MatWorld, -m_ObjectCenter[index].x,
-m_ObjectCenter[index].y,
-m_ObjectCenter[index].z );
switch (index)
{
case WOMAN_OBJECT:
if (m_Rotating == WOMAN_OBJECT)
{
if (m_bAutoRotate)
{
// rotate about y axis
m_curPitch += D3DXToRadian(1.0f);
m_curYaw += D3DXToRadian(5.0f);
D3DXMatrixRotationAxis(&m_MatObject[WOMAN_OBJECT], &m_VRotation, m_curYaw);
}
else
{
D3DXMatrixMultiply( &m_MatObject[WOMAN_OBJECT], &m_mUI->GetRotationMatrix(), &m_mUI->GetTranslationMatrix() );
}
}
D3DXMatrixMultiply( &m_MatWorld, &m_MatWorld, &m_MatObject[WOMAN_OBJECT] );
break;
case LIGHT_OBJECT:
if (m_Rotating == LIGHT_OBJECT)
{
if (m_bAutoRotate)
{
m_curPitch += D3DXToRadian(1.0f);
m_curYaw += D3DXToRadian(5.0f);
D3DXMatrixRotationAxis(&matTemp, &m_VRotation, m_curYaw);
}
else
{
matTemp = m_mUI->GetRotationMatrix();
}
m_LightDir.x = 0.0f;
m_LightDir.y = 0.0f;
m_LightDir.z = 1.0f;
D3DXVec3Normalize(&m_LightDir, &m_LightDir);
D3DXVec3TransformNormal(&m_LightDir, &m_LightDir, &matTemp);
SetLightPosition();
}
D3DXMatrixMultiply( &m_MatWorld, &m_MatWorld, &m_MatObject[LIGHT_OBJECT]);
break;
}
}
void CShaderBRDF::SetLightPosition()
{
D3DXMATRIX matTemp;
D3DXVECTOR3 lightPos(0, 0, -m_ObjectRadius[WOMAN_OBJECT]+(m_ObjectRadius[LIGHT_OBJECT]*.25f));
D3DXVECTOR3 vLightObjectDir(0.0f, 0.0f, 1.0f);
m_mUI->GetTranslationMatrix(&matTemp);
D3DXVec3TransformCoord(&lightPos, &lightPos, &matTemp);
// Create the rotation axis
D3DXVECTOR3 vOrthoNormal;
D3DXVec3Cross(&vOrthoNormal, &m_LightDir, &vLightObjectDir);
D3DXVec3Normalize(&vOrthoNormal, &vOrthoNormal);
// Calculate the angle between the two vectors.
float fAngle = acos(D3DXVec3Dot(&m_LightDir, &vLightObjectDir));
// Rotate the object about our rotation axis to map one vector onto another
D3DXMatrixRotationAxis(&m_MatObject[LIGHT_OBJECT], &vOrthoNormal, -fAngle);
D3DXMatrixTranslation( &matTemp, lightPos.x, lightPos.y, lightPos.z);
D3DXMatrixMultiply(&m_MatObject[LIGHT_OBJECT], &matTemp, &m_MatObject[LIGHT_OBJECT]);
}
HRESULT CShaderBRDF::SetVertexShaderMatrices(DWORD index)
{
// set up vertex shading constants to contain proper
// transformation matrices etc.
D3DXMATRIX matWorldView;
D3DXMATRIX matWorldViewProj;
D3DXMATRIX matWorldI;
UpdateObject(index);
D3DXMatrixInverse(&matWorldI, NULL, &m_MatWorld);
D3DXMatrixMultiply(&matWorldView, &m_MatWorld, &m_MatView);
D3DXMatrixMultiply(&matWorldViewProj, &matWorldView, &m_MatProj);
// Write Projection to clip space
D3DXMatrixTranspose(&matWorldViewProj, &matWorldViewProj);
m_pD3DDev->SetVertexShaderConstant(CV_WORLDVIEWPROJ_0, &matWorldViewProj(0, 0), 4);
// made this a vector 4 so, we wouldn't have to set the w part in the shader
D3DXVECTOR4 vecLight;
// Transform from world space to model space and point it away from the vertex towards the light
// Light is pointing into the world
D3DXVec3TransformNormal((D3DXVECTOR3*)&vecLight, &m_LightDir, &matWorldI);
D3DXVec3Normalize((D3DXVECTOR3*)&vecLight, (D3DXVECTOR3*)&vecLight);
// Shader math requires that the vector is to the light
vecLight = -vecLight;
vecLight.w = 1.0f;
m_pD3DDev->SetVertexShaderConstant(CVP_LIGHT_DIRECTION, &vecLight, 1);
// bias and scale, because pixel shader will clamp these values
vecLight += D3DXVECTOR4( 1.0f, 1.0f, 1.0f, 0.0f );
vecLight *= .5f;
vecLight.w = 1.0f;
m_pD3DDev->SetPixelShaderConstant(CVP_LIGHT_DIRECTION, &vecLight, 1);
// made this a vector 4 so, we wouldn't have to set the w part in the shader
D3DXVECTOR4 eyePos;
// put eye into object space.
D3DXVec3TransformCoord((D3DXVECTOR3*)&eyePos, &m_vEyePt, &matWorldI);
eyePos.w = 1.0f;
m_pD3DDev->SetVertexShaderConstant(CV_EYE_POSITION, &eyePos, 1);
D3DXVECTOR4 vecOne(1.0f, 1.0f, 1.0f, 1.0f);
m_pD3DDev->SetVertexShaderConstant(CV_ONE, &vecOne, 1);
return S_OK;
}
// ------------------------------------------------------------------------------
// CShaderBRDF::Free
//
// Description: Called when we switch away from this demo. Free up all the
// memory that is in use.
// ------------------------------------------------------------------------------
HRESULT CShaderBRDF::Free()
{
DWORD i;
for (i=0; i<NUM_OBJECTS; i++)
{
SAFE_RELEASE(m_pVertexBuffer[i]);
SAFE_RELEASE(m_pIndexBuffer[i]);
SAFE_DELETE_ARRAY(m_pAttributes[i]);
SAFE_DELETE_ARRAY(m_pMaterials[i]);
if (m_pD3DDev)
{
if (m_dwCurrentVShader[i] != 0)
{
m_pD3DDev->DeleteVertexShader(m_dwCurrentVShader[i]);
m_dwCurrentVShader[i] = 0;
}
if (m_dwCurrentPShader[i] != 0)
{
m_pD3DDev->DeletePixelShader(m_dwCurrentPShader[i]);
m_dwCurrentPShader[i] = 0;
}
}
}
SAFE_RELEASE(m_pD3DDev);
SAFE_RELEASE(m_pWomanTexture);
SAFE_RELEASE(m_pMinnaertTexture);
SAFE_RELEASE(m_pNormalizingTexture);
SAFE_RELEASE(m_pVelvetBumpMapTexture);
SAFE_RELEASE(m_pTestQuadVB);
SAFE_RELEASE(m_pTexture2DVB);
SAFE_DELETE(m_mUI);
return S_OK;
}
HRESULT CShaderBRDF::LoadXFile(const char* fileName, const DWORD dwFVF, DWORD index)
{
ID3DXMesh *tempMesh, *tempMeshFVF, *tempMeshOpt;
LPBYTE pSrc;
HRESULT hr = D3DXLoadMeshFromX(const_cast<char*>(fileName), D3DXMESH_SYSTEMMEM, m_pD3DDev, NULL,
(ID3DXBuffer**)&m_pMaterials[index], &m_dwNumSections[index], &tempMesh);
//convert to our format
hr = tempMesh->CloneMeshFVF(D3DXMESH_DYNAMIC, dwFVF, m_pD3DDev, &tempMeshFVF);
tempMeshFVF->Optimize(D3DXMESHOPT_ATTRSORT, NULL, NULL, NULL, NULL, &tempMeshOpt);
DWORD attribSize = m_dwNumSections[index];
hr = tempMeshOpt->GetAttributeTable(NULL, &attribSize);
m_pAttributes[index] = new D3DXATTRIBUTERANGE[attribSize];
hr = tempMeshOpt->GetAttributeTable(m_pAttributes[index], &attribSize);
tempMeshOpt->GetVertexBuffer(&m_pVertexBuffer[index]);
tempMeshOpt->GetIndexBuffer(&m_pIndexBuffer[index]);
m_pVertexBuffer[index]->Lock( 0, 0, (BYTE**)&pSrc, 0 );
// grab bound sphere, so we may initially scale our view.
D3DXComputeBoundingSphere(pSrc, tempMeshOpt->GetNumVertices(), dwFVF, &m_ObjectCenter[index], &m_ObjectRadius[index]);
m_pVertexBuffer[index]->Unlock();
SAFE_RELEASE(tempMesh);
SAFE_RELEASE(tempMeshFVF);
SAFE_RELEASE(tempMeshOpt);
return S_OK;
}
// ------------------------------------------------------------------------------
// CShaderBRDF::Start
//
// Description: Called to reset
// ------------------------------------------------------------------------------
HRESULT CShaderBRDF::Start()
{
return S_OK;
}
// this really should be a general drawing function inside the effects browser
// code.
HRESULT CShaderBRDF::Draw2DBitmap()
{
DWORD dwVertexShader;
DWORD dwPixelShader;
UINT VBStride;
LPDIRECT3DVERTEXBUFFER8 pVB;
LPDIRECT3DBASETEXTURE8 pTexture;
DWORD i;
typedef struct tagRenderStates
{
D3DRENDERSTATETYPE Type;
DWORD Value;
} tRenderStates;
typedef struct tagTextureStageStates
{
D3DTEXTURESTAGESTATETYPE Type;
DWORD Value;
} tTextureStates;
tRenderStates SavedRender[] =
{
{ D3DRS_ZENABLE, 0 },
{ D3DRS_ALPHATESTENABLE, 0 },
{ D3DRS_ALPHAREF, 0 },
{ D3DRS_ALPHAFUNC, 0 },
{ D3DRS_ALPHABLENDENABLE, 0 },
{ D3DRS_SRCBLEND, 0 },
{ D3DRS_DESTBLEND, 0 },
{ D3DRS_FOGENABLE, 0 },
{ D3DRS_CULLMODE, 0 },
{ D3DRS_FILLMODE, 0 },
{ D3DRS_WRAP0, 0}
};
tTextureStates SavedTextureStage0[] =
{
{ D3DTSS_COLOROP, 0 },
{ D3DTSS_COLORARG1, 0 },
{ D3DTSS_ALPHAOP, 0 },
{ D3DTSS_ALPHAARG1, 0 },
{ D3DTSS_TEXCOORDINDEX, 0 },
{ D3DTSS_MINFILTER, 0 },
{ D3DTSS_MAGFILTER, 0 },
};
tTextureStates SavedTextureStage1[] =
{
{ D3DTSS_COLOROP, 0 },
{ D3DTSS_ALPHAOP, 0 },
{ D3DTSS_TEXCOORDINDEX, 0 }
};
// Save state
m_pD3DDev->GetVertexShader(&dwVertexShader);
m_pD3DDev->GetPixelShader(&dwPixelShader);
m_pD3DDev->GetStreamSource(0, &pVB, &VBStride);
m_pD3DDev->GetTexture(0, &pTexture);
for (i = 0; i < sizeof(SavedRender) / sizeof(tRenderStates); i++)
{
m_pD3DDev->GetRenderState(SavedRender[i].Type, &SavedRender[i].Value);
}
for (i = 0; i < sizeof(SavedTextureStage0) / sizeof(tTextureStates); i++)
{
m_pD3DDev->GetTextureStageState(0, SavedTextureStage0[i].Type, &SavedTextureStage0[i].Value);
}
for (i = 0; i < sizeof(SavedTextureStage1) / sizeof(tTextureStates); i++)
{
m_pD3DDev->GetTextureStageState(1, SavedTextureStage1[i].Type, &SavedTextureStage1[i].Value);
}
// draw logo
m_pD3DDev->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
m_pD3DDev->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
m_pD3DDev->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);
m_pD3DDev->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);
m_pD3DDev->SetTextureStageState(0, D3DTSS_TEXCOORDINDEX, 0);
m_pD3DDev->SetTextureStageState(0, D3DTSS_MINFILTER, D3DTEXF_LINEAR );
m_pD3DDev->SetTextureStageState(0, D3DTSS_MAGFILTER, D3DTEXF_LINEAR );
m_pD3DDev->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE);
m_pD3DDev->SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_DISABLE);
m_pD3DDev->SetTextureStageState(1, D3DTSS_TEXCOORDINDEX, 1);
m_pD3DDev->SetStreamSource(0, m_pTexture2DVB, sizeof(TLVertex));
m_pD3DDev->SetVertexShader(D3DFVF_TLVERTEX);
m_pD3DDev->SetPixelShader(0);
// Enable alpha testing to remove the outer pixels
m_pD3DDev->SetRenderState(D3DRS_ZENABLE, FALSE);
m_pD3DDev->SetRenderState(D3DRS_ALPHATESTENABLE, TRUE);
m_pD3DDev->SetRenderState(D3DRS_ALPHAREF, 0x80 );
m_pD3DDev->SetRenderState(D3DRS_ALPHAFUNC, D3DCMP_GREATER);
m_pD3DDev->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
m_pD3DDev->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
m_pD3DDev->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
m_pD3DDev->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
m_pD3DDev->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID);
m_pD3DDev->SetRenderState(D3DRS_FOGENABLE, FALSE);
m_pD3DDev->SetRenderState( D3DRS_WRAP0, 0);
m_pD3DDev->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2 );
// Restore state
m_pD3DDev->SetVertexShader(dwVertexShader);
m_pD3DDev->SetStreamSource(0, pVB, VBStride);
m_pD3DDev->SetTexture(0, pTexture);
m_pD3DDev->SetPixelShader(dwPixelShader);
SAFE_RELEASE(pTexture);
SAFE_RELEASE(pVB);
for (i = 0; i < sizeof(SavedRender) / sizeof(tRenderStates); i++)
{
m_pD3DDev->SetRenderState(SavedRender[i].Type, SavedRender[i].Value);
}
for (i = 0; i < sizeof(SavedTextureStage0) / sizeof(tTextureStates); i++)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -