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

📄 depthoffield.cpp

📁 游戏编程精华02-含有几十个游戏编程例子
💻 CPP
📖 第 1 页 / 共 4 页
字号:
/******************************************************************************

  Copyright (C) 1999, 2000 NVIDIA Corporation
  This file is provided without support, instruction, or implied warranty of any
  kind.  NVIDIA makes no guarantee of its fitness for a particular purpose and is
  not liable under any circumstances for any damages or loss whatsoever arising
  from the use or inability to use this file or items derived from it.
          
******************************************************************************/

#include <crtdbg.h>

#include "eb_effect.h"
#include "nvtex.h"
#include "nvdevice.h"
#include "..\CommonSrc\NV_Error.h"

#include "DepthOfField.h"
#include "Constants.h"

using namespace nv_objects;
using namespace std;

DECLARE_EFFECT_MAIN()

extern "C"
{

__declspec(dllexport) unsigned int GetNumEffects() { return 1; }

__declspec(dllexport) EBEffect* CreateEffect(unsigned int EffectNum)
{
	return new CDepthOfField();
}

}


float const       CDepthOfField::kCloseClip  = 0.1f;      // in m
float const       CDepthOfField::kFarClip    = 520.0f;    // in m

// min and max focus distance in cm 
// (focusing beyond 200m is equivalent to infinity, even for 600mm lenses.)
// (focusing closer than the texture-resolution does not make sense)
// Even so, this technique does not work well for wide-angle lenses with
// close focusing: the distance to camera texture resolution is just not there 
// to do that (in addition total depth-resolution is only linear 8bits), so this 
// technique as coded here is really mostly for tele-photo zooms with far-focuses, i.e., 
// following rally-cars, race-cars, etc., etc.)
float const       CDepthOfField::kMinFocusDistance  = kMaxFocusDistance/kConfusionLookupHeight;
float const       CDepthOfField::kMaxFocusDistance  = 20000.0;

// only allow "normal" thru tele-photo lenses
float const       CDepthOfField::kMinFocalLength =  3.0f;       // in cm
float const       CDepthOfField::kMaxFocalLength = 60.0f;       // in cm

// 35mm film is actually 3.6 cm wide!
float const       CDepthOfField::kFilmDimension  = 3.6f;             

// this constant describes how much the circle of confusion espands 
// when applying the 9-sample box-filter to the texture 
float const       CDepthOfField::kBlurFactor = 1.5f; 

CDepthOfField::CDepthOfField()
    : m_pNVDevice(NULL)
    , mbWireFrame   (false)
    , meDisplayOption(SHOW_COLORS)
    , mbUsesVolumes(false)
    , mpMouseUI(NULL)
    , mCamLookDirection(0.0f, 0.0f,   1.0f)
    , mFStop        (    1.0f)       
    , mFocalLength  (   20.0f)       // in cm
    , mFocusDistance( 2536.0f)       // in cm
    , mWorldBoxDimensions( 150.0f, 150.0f, 150.0f )  // in m!
	, mpWorldBoxVertices(NULL)
	, mpWorldBoxIndices (NULL)
	, m_dwBlurVertexShader(0)
	, m_dwBlurPixelShader(0)
	, m_dwWorldVertexShader(0)
	, m_dwWorldPixelShader(0)
	, m_dwWorldNoDoFPixelShader(0)
	, m_dwTetraVertexShader(0)
	, m_dwTetraPixelShader(0)
	, m_dwTetraNoDoFPixelShader(0)
	, m_dwDepthOfFieldPixelShader(0)
    , m_dwShowBlurrinessShader(0)
    , mpQuadVertexBuffer(NULL)
	, mpTetrahedronVertices(NULL)
	, mpTetrahedronIndices (NULL)
    , mpBackbufferColor(NULL) 
    , mpBackbufferDepth(NULL)
    , mpDepthTarget(NULL)
    , mpCircleOfConfusionLookup(NULL)
    , mpVolCircleOfConfusionLookup(NULL)
	, mpObjectTexture(NULL)
{
	m_strEffectName         = "Depth of Field";
	m_strEffectLocation     = "Pixel Shaders\\Image Processing";
	m_strEffectPixelShader  = GetFilePath("Tetrahedron.nvp");
	m_strEffectVertexShader = GetFilePath("World.nvv");

	for (DWORD i = 0; i < 6; i++)
		mpWorldTextures[i] = NULL;
}

CDepthOfField::~CDepthOfField()
{
	Free();	
}

HRESULT CDepthOfField::ConfirmDevice(D3DCAPS8* pCaps, DWORD dwBehavior, D3DFORMAT Format)
{
    // check vertex shading support
    if(D3DSHADER_VERSION_MAJOR(pCaps->VertexShaderVersion) < 1)
	{
		m_strLastError = "Device does not support vertex shaders!";
		return E_FAIL;
	}
    if(D3DSHADER_VERSION_MINOR(pCaps->VertexShaderVersion) < 1)
	{
		m_strLastError = "Device does not support 1.1 vertex shaders!";
		return E_FAIL;
	}

    // check simultaneous texture support
    if(pCaps->MaxSimultaneousTextures < 4)
	{
		m_strLastError = "Device does not support 4 simultaneous textures!";
		return E_FAIL;
	}

    // check pixel shader support
    if(D3DSHADER_VERSION_MAJOR(pCaps->PixelShaderVersion) < 1)
	{
		m_strLastError = "Device does not support pixel shaders!";
		return E_FAIL;
	}
	if(D3DSHADER_VERSION_MINOR(pCaps->PixelShaderVersion) < 1)
	{
		m_strLastError = "Device does not support 1.1 pixel shaders!";
		return E_FAIL;
	}
	if(pCaps->MaxTextureBlendStages < 8)
	{
		m_strLastError = "Device does not support 8 register combiners!";
		return E_FAIL;
	}
    mbUsesVolumes = (pCaps->TextureCaps & D3DPTEXTURECAPS_VOLUMEMAP) != 0;

    return S_OK;
}

void CDepthOfField::UpdateProperties()
{
	EBEffect::UpdateProperties();

    // Options
    AddProperty(new EBProperty("Wireframe",       OBJECT_MEMBER(mbWireFrame),      EBTYPE_BOOL_PROP));

	EBEnumProperty* pEnumProp = new EBEnumProperty("Display Options", OBJECT_MEMBER(meDisplayOption), EBTYPE_DWORD_PROP);
	
    pEnumProp->AddEnumerant(new EBEnumValue(pEnumProp, "Show Colors",     (DWORD)SHOW_COLORS,     EBTYPE_DWORD_PROP));
    pEnumProp->AddEnumerant(new EBEnumValue(pEnumProp, "Show Depth",      (DWORD)SHOW_DEPTH,      EBTYPE_DWORD_PROP));
    pEnumProp->AddEnumerant(new EBEnumValue(pEnumProp, "Show Blurriness", (DWORD)SHOW_BLURRINESS, EBTYPE_DWORD_PROP));
	AddProperty(pEnumProp);

	// Vertex shaders
	m_pVertexShaderEnum->AddEnumerant(new EBEnumValue(m_pVertexShaderEnum, "World Rendering",       GetFilePath("World.nvv"),       EBTYPE_STRING_PROP));
	m_pVertexShaderEnum->AddEnumerant(new EBEnumValue(m_pVertexShaderEnum, "Object Rendering",      GetFilePath("Tetrahedron.nvv"), EBTYPE_STRING_PROP));
	m_pVertexShaderEnum->AddEnumerant(new EBEnumValue(m_pVertexShaderEnum, "Screen-Quad Rendering", GetFilePath("Blur.nvv"),        EBTYPE_STRING_PROP));

	// Pixel shaders
	m_pPixelShaderEnum->AddEnumerant(new EBEnumValue(m_pPixelShaderEnum, "Object Rendering",           GetFilePath("Tetrahedron.nvp"),       EBTYPE_STRING_PROP));
	m_pPixelShaderEnum->AddEnumerant(new EBEnumValue(m_pPixelShaderEnum, "Screen-Quad Rendering",      GetFilePath("World.nvp"),             EBTYPE_STRING_PROP));
	m_pPixelShaderEnum->AddEnumerant(new EBEnumValue(m_pPixelShaderEnum, "Texture Blurring",           GetFilePath("Blur.nvp"),              EBTYPE_STRING_PROP));
	m_pPixelShaderEnum->AddEnumerant(new EBEnumValue(m_pPixelShaderEnum, "Depth of Field Combination", GetFilePath("DepthOfFieldBlend.nvp"), EBTYPE_STRING_PROP));
}

HRESULT CDepthOfField::Initialize(IDirect3DDevice8* pDev)
{
	HRESULT hr;
    ZeroMemory(&m_bKey[0], sizeof(bool) * kMaxVKey);

    // get the device
	m_pD3DDev = pDev;
	pDev->AddRef();

	m_pNVDevice = new NVDevice(pDev);

    //initialize mouse UI
	D3DVIEWPORT8    viewport;
	RECT            rect;

	m_pD3DDev->GetViewport(&viewport);
	rect.left   = rect.top = 0;
	rect.bottom = viewport.Height;
	rect.right  = viewport.Width;
	mpMouseUI   = new MouseUI(rect, true);
    mpMouseUI->SetRotationalSensitivityFactor(1.0f);

    CreateTextureRenderTarget();

    hr = InitBlurRendering();
	if (FAILED(hr))
	{
		m_strLastError = "Failed to initialise blur rendering";
		return hr;
	}

	hr = InitWorldRendering();
	if (FAILED(hr))
	{
		m_strLastError = "Failed to initialise world rendering";
		return hr;
	}

	hr = InitTetrahedronRendering();
	if (FAILED(hr))
	{
		m_strLastError = "Failed to initialise tetrahedron rendering";
		return hr;
	}

    UpdateCameraParameters();
    GenerateCircleOfConfusionTexture();

	return S_OK;
}

HRESULT CDepthOfField::InitBlurRendering()
{
	HRESULT hr;

    // create the vertex and pixel shaders for filtering the rendering target 
	vector<DWORD> Declaration;
	Declaration.push_back(D3DVSD_STREAM(0));
	Declaration.push_back(D3DVSD_REG(0, D3DVSDT_FLOAT3));
	Declaration.push_back(D3DVSD_REG(1, D3DVSDT_FLOAT2));
	Declaration.push_back(D3DVSD_END());

	hr = LoadAndCreateShader(GetFilePath("Blur.vso"), &Declaration[0], 0, SHADERTYPE_VERTEX, &m_dwBlurVertexShader);
	if (FAILED(hr))
		return hr;
	
	hr = LoadAndCreateShader(GetFilePath("Blur.pso"), NULL, 0, SHADERTYPE_PIXEL, &m_dwBlurPixelShader);
	if (FAILED(hr))
		return hr;
	hr = LoadAndCreateShader(GetFilePath("DepthOfFieldBlend.pso"), NULL, 0, SHADERTYPE_PIXEL, &m_dwDepthOfFieldPixelShader);
	if (FAILED(hr))
		return hr;
	hr = LoadAndCreateShader(GetFilePath("ShowBlurriness.pso"), NULL, 0, SHADERTYPE_PIXEL, &m_dwShowBlurrinessShader);
	if (FAILED(hr))
		return hr;

	// create vertex buffer 
	hr = m_pD3DDev->CreateVertexBuffer( 4 * sizeof(tQuadVertex), D3DUSAGE_WRITEONLY | D3DUSAGE_DYNAMIC, 0, D3DPOOL_DEFAULT, &mpQuadVertexBuffer);
	if (FAILED(hr))
		return hr;

	tQuadVertex      *pBuff;

	if (mpQuadVertexBuffer)
	{
		hr = mpQuadVertexBuffer->Lock(0, 4 * sizeof(tQuadVertex),(BYTE**)&pBuff, 0);
		if (FAILED(hr))
		{
			m_strLastError = "Couldn't lock buffer!";
			return hr;
		}

        for (int i = 0; i < 4; ++i)
        {
            pBuff->mPosition = D3DXVECTOR3((i==0 || i==1) ? -1.0f : 1.0f,
                                           (i==0 || i==3) ? -1.0f : 1.0f,
                                          0.0f);
		    pBuff->mTexture  = D3DXVECTOR2((i==0 || i==1) ? 0.0f : 1.0f, 
                                           (i==0 || i==3) ? 1.0f : 0.0f);
		    pBuff++; 
        }
        mpQuadVertexBuffer->Unlock();
    }

    D3DSURFACE_DESC ddsd;
    mpTextureFiltered[0]->GetLevelDesc(0, &ddsd);

    CreateAndWriteUVOffsets(ddsd.Width, ddsd.Height);
	
    return S_OK;
}

HRESULT CDepthOfField::InitWorldRendering()
{
	HRESULT hr;

    // create the vertex and pixel shaders for rendering of world objects
	vector<DWORD> Declaration;
	Declaration.push_back(D3DVSD_STREAM(0));
	Declaration.push_back(D3DVSD_REG(0, D3DVSDT_FLOAT3));
	Declaration.push_back(D3DVSD_REG(2, D3DVSDT_FLOAT2));
	Declaration.push_back(D3DVSD_END());

	hr = LoadAndCreateShader(GetFilePath("World.vso"), &Declaration[0], 0, SHADERTYPE_VERTEX, &m_dwWorldVertexShader);
	if (FAILED(hr))
		return hr;
	
	hr = LoadAndCreateShader(GetFilePath("World.pso"), NULL, 0, SHADERTYPE_PIXEL, &m_dwWorldPixelShader);
	if (FAILED(hr))
		return hr;
	hr = LoadAndCreateShader(GetFilePath("WorldNoDoFLookup.pso"), NULL, 0, SHADERTYPE_PIXEL, &m_dwWorldNoDoFPixelShader);
	if (FAILED(hr))
		return hr;

	CreateWorldCube();

    return S_OK;
}

HRESULT CDepthOfField::InitTetrahedronRendering()
{
	HRESULT hr;

    // create the vertex and pixel shaders for rendering of objects within the world
	vector<DWORD> Declaration;
	Declaration.push_back(D3DVSD_STREAM(0));
	Declaration.push_back(D3DVSD_REG(0, D3DVSDT_FLOAT3));
	Declaration.push_back(D3DVSD_REG(1, D3DVSDT_FLOAT3));
	Declaration.push_back(D3DVSD_REG(2, D3DVSDT_FLOAT2));
	Declaration.push_back(D3DVSD_END());

	hr = LoadAndCreateShader(GetFilePath("Tetrahedron.vso"), &Declaration[0], 0, SHADERTYPE_VERTEX, &m_dwTetraVertexShader);
	if (FAILED(hr))
		return hr;
	
	hr = LoadAndCreateShader(GetFilePath("Tetrahedron.pso"), NULL, 0, SHADERTYPE_PIXEL, &m_dwTetraPixelShader);
	if (FAILED(hr))
		return hr;
	hr = LoadAndCreateShader(GetFilePath("TetrahedronNoDoFLookup.pso"), NULL, 0, SHADERTYPE_PIXEL, &m_dwTetraNoDoFPixelShader);
	if (FAILED(hr))
		return hr;

	CreateTetrahedron();

    return S_OK;
}

HRESULT CDepthOfField::SetBlurRenderState()
{
    m_pD3DDev->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID);

	m_pD3DDev->SetTextureStageState(0, D3DTSS_COLOROP,   D3DTOP_SELECTARG1);
	m_pD3DDev->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
	m_pD3DDev->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE);
	m_pD3DDev->SetTextureStageState(0, D3DTSS_ALPHAOP,   D3DTOP_DISABLE);

    for (int i = 0; i < 4; ++i)
    {
	    m_pD3DDev->SetTextureStageState(i, D3DTSS_MAGFILTER, D3DTEXF_LINEAR);
	    m_pD3DDev->SetTextureStageState(i, D3DTSS_MINFILTER, D3DTEXF_LINEAR);
	    m_pD3DDev->SetTextureStageState(i, D3DTSS_MIPFILTER, D3DTEXF_NONE);
	    m_pD3DDev->SetTextureStageState(i, D3DTSS_ADDRESSU,  D3DTADDRESS_CLAMP);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -