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

📄 depthoffield.cpp

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

    // reset offsets to 0
    offset.x = 0.0f;
    m_pD3DDev->SetVertexShaderConstant(CV_UV_OFFSET_TO_USE, &offset, 1);

	hr = m_pD3DDev->DrawPrimitive(D3DPT_TRIANGLEFAN, 0, 2);

    return hr;
}

HRESULT CDepthOfField::CreateTextureRenderTarget()
{
    HRESULT         hr;

    // first simply create the circle of confusion look up map
    // This texture could be 3D (if available) or 2D or 1D.  Trade-off
    // which parameters vary by how much and how often what size texture
    // can be regenerated.
    if (mbUsesVolumes)
    {
        hr = m_pD3DDev->CreateVolumeTexture( kConfusionLookupWidth, kConfusionLookupHeight, kConfusionLookupDepth,
                                             1, 0, D3DFMT_A8R8G8B8, D3DPOOL_MANAGED,
                                             &mpVolCircleOfConfusionLookup );
        if( FAILED(hr) )
	    {
		    m_strLastError = "Could not create volume texture!";
            return E_FAIL;
	    }
    }
    else
    {
        hr = m_pD3DDev->CreateTexture( kConfusionLookupWidth, kConfusionLookupHeight, 
                                         1, 0, D3DFMT_A8R8G8B8, D3DPOOL_MANAGED,
                                         &mpCircleOfConfusionLookup );
        if( FAILED(hr) )
	    {
		    m_strLastError = "Could not create 2D look-up texture!";
            return E_FAIL;
	    }
    }

    // get a pointer to the current back-buffer (so we can restore it later)
	m_pD3DDev->GetRenderTarget(        &mpBackbufferColor );
	m_pD3DDev->GetDepthStencilSurface( &mpBackbufferDepth );
	_ASSERT( mpBackbufferColor != NULL );
	_ASSERT( mpBackbufferDepth != NULL );

    // get the description for the texture we want to filter
	D3DSURFACE_DESC ddsd;

    mpBackbufferColor->GetDesc(&ddsd);

    // set ddsd width/height to next smaller power of 2
    // we loose some precision, but it is hard to tell, yet the smaller 
    // size is much higher performance as we have to filter many fewer pixels...
    int logWidth  = static_cast<int>(logf(static_cast<float>(ddsd.Width)) /logf(2.0f));
    int logHeight = static_cast<int>(logf(static_cast<float>(ddsd.Height))/logf(2.0f));

    ddsd.Width  = pow(2, logWidth );
    ddsd.Height = pow(2, logHeight);

    // make a depth buffer to go with the first texture
    hr = m_pD3DDev->CreateDepthStencilSurface(ddsd.Width, ddsd.Height,       // use color's width/height!!!
                                  D3DFMT_D24X8, D3DMULTISAMPLE_NONE, 
                                  &mpDepthTarget);

    // create new textures just like the current texture
    // these will be used as filter-targets and sources
    for (int i = 0; i < 3; ++i)
    {
        hr = m_pD3DDev->CreateTexture(ddsd.Width, ddsd.Height, 1, 
                                      D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8, 
                                      D3DPOOL_DEFAULT, &mpTextureFiltered[i]);
        hr = mpTextureFiltered[i]->GetSurfaceLevel(0, &mpFilterTarget[i]);

        // set our render target to the new and shiny textures without depth
        hr = m_pD3DDev->SetRenderTarget(mpFilterTarget[i], (i==0) ? mpDepthTarget : NULL);
        if (FAILED(hr))
        {
		    m_strLastError = "Can't SetRenderTarget to new surface!\n";
            _ASSERT(false);
            return E_FAIL;
        }
    }
    for (i = 0; i < 2; ++i)
    {
        hr = m_pD3DDev->CreateTexture(ddsd.Width, ddsd.Height, 1, 
                                      D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8, 
                                      D3DPOOL_DEFAULT, &mpTempTexture[i]);
        hr = mpTempTexture[i]->GetSurfaceLevel(0, &mpTempTarget[i]);

        // set our render target to the new and shiny textures without depth
        hr = m_pD3DDev->SetRenderTarget(mpTempTarget[i], NULL);
        if (FAILED(hr))
        {
		    m_strLastError = "Can't SetRenderTarget to new surface!\n";
            _ASSERT(false);
            return E_FAIL;
        }
    }

    // switch back to conventional back-buffer
    hr = m_pD3DDev->SetRenderTarget(mpBackbufferColor, mpBackbufferDepth);
    if (FAILED(hr))
    {
		m_strLastError = "Can't SetRenderTarget to original back-buffer surfaces!\n";
        _ASSERT(false);
        return E_FAIL;
    }

    return S_OK;
}

void CDepthOfField::CreateAndWriteUVOffsets(int width, int height)
{
    // set-up offset to achieve a nine-sample box-filter centered 
    // over each texel.  
    float const     kPerTexelWidth  = 1.0f/static_cast<float>(width);
    float const     kPerTexelHeight = 1.0f/static_cast<float>(height);
    float const     noOffsetX[4]    = { 0.0f, 0.0f, 0.0f, 0.0f}; 
    float const     noOffsetY[4]    = { 0.0f, 0.0f, 0.0f, 0.0f};
    int             i;

    // nine sample box filter
    float const s = 2.0f/3.0f;
    float const box9OffsetX[4] = { 0.0f, 
                                   0.0f,  
                                   2.0f * s * kPerTexelWidth,   
                                   2.0f * s * kPerTexelWidth };
    float const box9OffsetY[4] = { 0.0f, 
                                   2.0f * s * kPerTexelHeight, 
                                   2.0f * s * kPerTexelHeight, 
                                   0.0f };

    // write all these offsets to constant memory
    for (i = 0; i < 4; ++i)
    {
        D3DXVECTOR4  noOffset(    noOffsetX[i],   noOffsetY[i],   0.0f, 0.0f);
        D3DXVECTOR4  actualOffset(box9OffsetX[i], box9OffsetY[i], 0.0f, 0.0f);

    	m_pD3DDev->SetVertexShaderConstant(CV_UV_T0_NO_OFFSET + 2*i, &noOffset,     1);
    	m_pD3DDev->SetVertexShaderConstant(CV_UV_T0_TYPE1     + 2*i, &actualOffset, 1);
    }
}

HRESULT CDepthOfField::CreateWorldCube()
{
    HRESULT          hr;
    tQuadVertex     *pVertices;
	WORD            *pIndices;
    int              i, j, k;

    // first do the textures
    string cubeFaceTextures[6] = { "skybox_left.dds",
                                   "wood.dds", 
                                   "skybox_front.dds", 
                                   "skybox_back.dds", 
                                   "skybox_top.dds", 
                                   "skybox_right.dds"
                                  };
	for (i = 0; i < 6; i++)
    {
		mpWorldTextures[i] = new NVTexture();
        hr = mpWorldTextures[i]->CreateFromFile(m_pD3DDev, GetFilePath(cubeFaceTextures[i]));
	    if (FAILED(hr))
	    {
		    m_strLastError = cubeFaceTextures[i];
		    _ASSERT(false);
            return hr;
	    }
    }

    // now lets allocate vertices and indices for the cube faces
    hr = m_pD3DDev->CreateVertexBuffer(kNumVertices * sizeof(tQuadVertex), D3DUSAGE_WRITEONLY, 0, D3DPOOL_MANAGED, &mpWorldBoxVertices);
	hr = mpWorldBoxVertices->Lock(0,   kNumVertices * sizeof(tQuadVertex),(BYTE**)&pVertices, 0);
	if (FAILED(hr))
	{
		m_strLastError = "Could not create/lock vertex buffer!";
		return hr;
	}

	hr = m_pD3DDev->CreateIndexBuffer(kNumIndices * sizeof(WORD), D3DUSAGE_WRITEONLY, D3DFMT_INDEX16, D3DPOOL_MANAGED, &mpWorldBoxIndices);
	hr = mpWorldBoxIndices->Lock(0,   kNumIndices * sizeof(WORD),(BYTE**)&pIndices, 0);
	if (FAILED(hr))
	{
		m_strLastError = "Could not create/lock index buffer!";
		return hr;
	}

    // Set up the vertices for the cube engulfing the world.
    // Note: to prevent tiling problems, the u/v coords are knocked slightly inwards.
    float       const kFloorTextureRepeat = 2.0f * mWorldBoxDimensions.x;

    D3DXVECTOR3 vertexCube[8] = { D3DXVECTOR3(-1.0f,-1.0f,-1.0f), 
                                  D3DXVECTOR3(-1.0f,-1.0f, 1.0f),
                                  D3DXVECTOR3(-1.0f, 1.0f,-1.0f),
                                  D3DXVECTOR3(-1.0f, 1.0f, 1.0f),
                                  D3DXVECTOR3( 1.0f,-1.0f,-1.0f),
                                  D3DXVECTOR3( 1.0f,-1.0f, 1.0f),
                                  D3DXVECTOR3( 1.0f, 1.0f,-1.0f),
                                  D3DXVECTOR3( 1.0f, 1.0f, 1.0f)  };
    D3DXVECTOR2 uvCube[4]     = { D3DXVECTOR2( 0.0f, 0.0f), 
                                  D3DXVECTOR2( 0.0f, 1.0f), 
                                  D3DXVECTOR2( 1.0f, 0.0f), 
                                  D3DXVECTOR2( 1.0f, 1.0f) };
    // right:   0 1 2 3
    // top:     0 1 4 5 
    // front:   0 2 4 6
    // back:    1 3 5 7
    // bottom:  2 3 6 7
    // left:    4 5 6 7
 
    D3DXVECTOR3 ul, ur, ll, lr;
    D3DXVECTOR3 upper, lower, position;
    D3DXVECTOR2 ulUV, urUV, llUV, lrUV;
    D3DXVECTOR2 upperUV, lowerUV, uv;
    float       x, y;

    // each face is tesselated (see kNumQuadsPerSide in .h file)
    // to avoid interpolation errors for computing per-pixel distances
    for (i = 0; i < 6; ++i)         // for each face
    {
        if (i == 1) // bottom face is special
        {
            ul   = D3DXVECTOR3(-1.0f, 0.0001f,-1.0f);
            ur   = D3DXVECTOR3(-1.0f, 0.0001f, 1.0f);
            ll   = D3DXVECTOR3( 1.0f, 0.0001f,-1.0f);
            lr   = D3DXVECTOR3( 1.0f, 0.0001f, 1.0f);

            ulUV = D3DXVECTOR2(0.0f,                0.0f);
            urUV = D3DXVECTOR2(0.0f,                kFloorTextureRepeat);
            llUV = D3DXVECTOR2(kFloorTextureRepeat, 0.0f);
            lrUV = D3DXVECTOR2(kFloorTextureRepeat, kFloorTextureRepeat);
        }
        else
        {
            ul = vertexCube[(i<3)? 0 : (int)pow(2, i-3)];
            ur = vertexCube[(i<3)? 1 + i/2 :3+2*((i-3)/2)];
            ll = vertexCube[(i<3)? 2 + 2*((i+1)/2) : 5+((i-2)/2)];
            lr = vertexCube[(i<3)? 3+(3*i+1)/2 : 7]; 

            ulUV = uvCube[0];
            urUV = uvCube[1];
            llUV = uvCube[2];
            lrUV = uvCube[3];
        }


        for (j = 0; j < kNumQuadsPerSide+1; ++j)        // march in y
        {
            y = static_cast<float>(j)/static_cast<float>(kNumQuadsPerSide); 
            for (k = 0; k < kNumQuadsPerSide+1; ++k)    // march in x
            {
                x = static_cast<float>(k)/static_cast<float>(kNumQuadsPerSide); 

                upper    = (1.f-x)*ul    + x*ur;
                lower    = (1.f-x)*ll    + x*lr;
                position = (1.f-y)*upper + y*lower;

                upperUV  = (1.f-x)*ulUV    + x*urUV;
                lowerUV  = (1.f-x)*llUV    + x*lrUV;
                uv       = (1.f-y)*upperUV + y*lowerUV;

                *pVertices++ = tQuadVertex( position, uv );
            }
        }
    }

    // Set up the indices for the cube
    for (i = 0; i < 6; ++i)         // for each cube face
        for (j = 0; j < kNumQuadsPerSide; ++j)     // for each strip 
            for (k = 0; k < (kNumQuadsPerSide + 1); ++k)
            {
                *pIndices++ = k + j    *(kNumQuadsPerSide+1) + i*kNumVerticesPerFace;
                *pIndices++ = k + (j+1)*(kNumQuadsPerSide+1) + i*kNumVerticesPerFace;
            }

	mpWorldBoxVertices->Unlock();
	mpWorldBoxIndices->Unlock();

    return S_OK;
}

HRESULT CDepthOfField::CreateTetrahedron()
{
    HRESULT             hr;
    tTetrahedronVertex *pVertices;
	WORD               *pIndices;

    // get the texture
	mpObjectTexture = new NVTexture();
    hr = mpObjectTexture->CreateFromFile(m_pD3DDev, GetFilePath("ObjectTexture.dds"));
	if (FAILED(hr))
	{
		m_strLastError = "Could not find ObjectTexture.dds";
		_ASSERT(false);
        return hr;
	}

    // now lets allocate vertices and indices for the tetrahedron
    hr = m_pD3DDev->CreateVertexBuffer( 12 * sizeof(tTetrahedronVertex), D3DUSAGE_WRITEONLY, 0, D3DPOOL_MANAGED, &mpTetrahedronVertices);
	hr = mpTetrahedronVertices->Lock(0, 12 * sizeof(tTetrahedronVertex),(BYTE**)&pVertices, 0);
	if (FAILED(hr))
	{
		m_strLastError = "Could not create/lock vertex buffer!";
		return hr;
	}

	hr = m_pD3DDev->CreateIndexBuffer( 12 * sizeof(WORD), D3DUSAGE_WRITEONLY, D3DFMT_INDEX16, D3DPOOL_MANAGED, &mpTetrahedronIndices);
	hr = mpTetrahedronIndices->Lock(0, 12 * sizeof(WORD),(BYTE**)&pIndices, 0);
	if (FAILED(hr))
	{
		m_strLastError = "Could not create/lock index buffer!";
		return hr;
	}

    D3DXVECTOR2 uvCoord[3] =        { D3DXVECTOR2(0.0f, 0.0f), 
                                      D3DXVECTOR2(0.0f, 1.0f),
                                      D3DXVECTOR2(1.0f, 1.0f)  };
    D3DXVECTOR3 vertexPosition[4] = { D3DXVECTOR3(0.0f, 0.0f, 0.0f), 
                                      D3DXVECTOR3(0.0f, 1.0f, 0.0f),
                                      D3DXVECTOR3(0.5f, 0.5f, 0.0f),
                                      D3DXVECTOR3(0.0f, 0.5f,-0.5f)  };
    float   const   oneOverSqrt3 = 1.0f/sqrt(3.0f);
    D3DXVECTOR3 triangleNormal[4] = { D3DXVECTOR3(-1.0f, 0.0f,  0.0f), 
                                      D3DXVECTOR3( 0.0f, 0.0f,  1.0f),
                                      D3DXVECTOR3( oneOverSqrt3, -oneOverSqrt3, -oneOverSqrt3),
                                      D3DXVECTOR3( oneOverSqrt3,  oneOverSqrt3, -oneOverSqrt3)  };

    // first triangle
    *pVertices++ = tTetrahedronVertex(vertexPosition[0], triangleNormal[0], uvCoord[0]);
    *pVertices++ = tTetrahedronVertex(vertexPosition[1], triangleNormal[0], uvCoord[1]);
    *pVertices++ = tTetrahedronVertex(vertexPosition[3], triangleNormal[0], uvCoord[2]);

    // second triangle
    *pVertices++ = tTetrahedronVertex(vertexPosition[0], triangleNormal[1], uvCoord[0]);
    *pVertices++ = tTetrahedronVertex(vertexPosition[2], triangleNormal[1], uvCoord[1]);
    *pVertices++ = tTetrahedronVertex(vertexPosition[1], triangleNormal[1], uvCoord[2]);

    // third  triangle
    *pVertices++ = tTetrahedronVertex(vertexPosition[0], triangleNormal[2], uvCoord[0]);
    *pVertices++ = tTetrahedronVertex(vertexPosition[3], triangleNormal[2], uvCoord[1]);
    *pVertices++ = tTetrahedronVertex(vertexPosition[2], triangleNormal[2], uvCoord[2]);

    // last triangle
    *pVertices++ = tTetrahedronVertex(vertexPosition[1], triangleNormal[3], uvCoord[0]);
    *pVertices++ = tTetrahedronVertex(vertexPosition[2], triangleNormal[3], uvCoord[1]);
    *pVertices++ = tTetrahedronVertex(vertexPosition[3], triangleNormal[3], uvCoord[2]);

    // indices are easy: simple triangle list in order 
    for (int i = 0; i < 12; ++i)         
        *pIndices++ = i;

	mpTetrahedronVertices->Unlock();
	mpTetrahedronIndices->Unlock();

    return S_OK;
}

HRESULT CDepthOfField::GenerateCircleOfConfusionTexture()

⌨️ 快捷键说明

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