⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 shader_lighting.cpp

📁 游戏编程精华02-含有几十个游戏编程例子
💻 CPP
📖 第 1 页 / 共 2 页
字号:
	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 + -