📄 effect_reflectivebumpdynamic.cpp
字号:
/*********************************************************************NVMH2****
Path: C:\DEV\devrel\NV_SDK_4\DX8\NVEffectsBrowser\Effects\ReflectiveBumpDynamic
File: Effect_ReflectiveBumpDynamic.cpp
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.
Comments:
******************************************************************************/
#include "eb_effect.h"
#include "CA_Water.h"
#include "nvdevice.h"
#include "NV_Error.h"
#include "SimpleObject8.h"
#include "Dot3_util.h"
#include "Effect_ReflectiveBumpDynamic.h"
#include "Constants.h"
#include "PixelConstants.h"
#include <vector>
using namespace nv_objects;
using namespace std;
/////////////////////////////////////////////////
#define INIT_BUMPSCALE 0.12f
/////////////////////////////////////////////////
#ifndef ASSERT_IF_FAILED
#define ASSERT_IF_FAILED( hres ) \
{ \
if( FAILED(hres) ) \
assert( false ); \
}
#endif
/////////////////////////////////////////////////
DECLARE_EFFECT_MAIN()
DECLARE_EFFECT_COUNT(1)
DECLARE_EFFECT_CREATE_BEG()
DECLARE_EFFECT_CREATE(0, NVEffect_DynamicReflection())
DECLARE_EFFECT_CREATE_END()
///////////////////////////////////////////////////////////////////////////
HRESULT NVEffect_DynamicReflection::ConfirmDevice(D3DCAPS8* pCaps, DWORD dwBehavior, D3DFORMAT Format)
{
if (!(pCaps->TextureCaps & D3DPTEXTURECAPS_CUBEMAP))
{
m_strLastError = "Device does not support cubemaps!";
return E_FAIL;
}
if (!(pCaps->TextureCaps & D3DPTEXTURECAPS_PROJECTED))
{
m_strLastError = "Device does not support 3 element texture coordinates!";
return E_FAIL;
}
if (!(pCaps->MaxTextureBlendStages >= 4))
{
m_strLastError = "Not enough texture blend stages!";
return E_FAIL;
}
if(D3DSHADER_VERSION_MAJOR(pCaps->PixelShaderVersion) < 1)
{
m_strLastError = "Device does not support pixel shaders!";
return E_FAIL;
}
if(!(pCaps->DevCaps & D3DDEVCAPS_RTPATCHES) )
{
m_strLastError = "Device does not support RTPATCHES!";
return E_FAIL;
}
return S_OK;
}
#define STR_INCREASEBUMPSCALE "Bump scale increase (+)"
#define STR_DECREASEBUMPSCALE "Bump scale decrease (-)"
#define STR_RESETPATCH "Reset patch offset (HOME)"
#define STR_MOREOPTION "Hit F1 for more options!"
void NVEffect_DynamicReflection::UpdateProperties()
{
EBEffect::UpdateProperties();
AddProperty(new EBTriggerProperty(STR_INCREASEBUMPSCALE));
AddProperty(new EBTriggerProperty(STR_DECREASEBUMPSCALE));
AddProperty(new EBTriggerProperty(STR_RESETPATCH));
AddProperty(new EBTriggerProperty(STR_MOREOPTION));
EBEnumProperty* pEnumProp = new EBEnumProperty("Display Options", OBJECT_MEMBER(m_eDisplayOption), EBTYPE_DWORD_PROP);
if (m_bSupportsQWVU)
pEnumProp->AddEnumerant(new EBEnumValue(pEnumProp, "8 Bit Signed BumpMap",
(DWORD)DISPLAY_BLINN8BITSIGNED, EBTYPE_DWORD_PROP));
AddProperty(pEnumProp);
if (m_bSupportsPatches)
{
AddProperty(new EBProperty("Show Bezier-Patch", OBJECT_MEMBER(m_bUsePatch), EBTYPE_BOOL_PROP));
}
AddProperty(new EBProperty("Wireframe", OBJECT_MEMBER(m_bWireframe), EBTYPE_BOOL_PROP));
AddProperty(new EBProperty("Pause geometry animation", OBJECT_MEMBER(m_bPause), EBTYPE_BOOL_PROP));
//////////////////////////////////////////////////////////////
string aboutText = "file://";
aboutText += GetFilePath("NVEffectsExplained.htm");
aboutText += "#DynamicTrueReflectiveBumpMapping";
SetAboutInfo( NULL, _T("Dynamic Normal Map"), _T(aboutText.c_str()));
SetAboutInfo( NULL, _T("Developer Relations"), _T("http://www.nvidia.com/developer"));
SetAboutInfo( NULL, _T("NVIDIA Corporation"), _T("http://www.nvidia.com"));
SetAboutInfo( _T("Date"), _T("April 2001"));
//////////////////////////////////////////////////////////////////////////
// Add vertex & pixel shader display to the tabbed text boxes:
// No need to GetFilePath() with these. The Add..() function does it for you
// Vertex shaders
AddShaderCodeFile( SHADERTYPE_VERTEX, "Texture Space", "blinn_reflect.nvv" );
AddShaderCodeFile( SHADERTYPE_VERTEX, "Simple Transform", "dot3_transform.nvv");
// Pixel shaders
AddShaderCodeFile( SHADERTYPE_PIXEL, "Per-pixel Bump Reflections", "blinn_reflect.nvp");
AddShaderCodeFile( SHADERTYPE_PIXEL, "Neighbor Sampling Setup", "TexCoord_4_Offset.nvv");
AddShaderCodeFile( SHADERTYPE_PIXEL, "Force: Step 1", "NeighborForceCalc.nvp");
AddShaderCodeFile( SHADERTYPE_PIXEL, "Force: Step 2", "NeighborForceCalc2.nvp");
AddShaderCodeFile( SHADERTYPE_PIXEL, "Apply Force", "ApplyForceShader.nvp");
AddShaderCodeFile( SHADERTYPE_PIXEL, "Apply Velocity", "ApplyVelocityShader.nvp");
AddShaderCodeFile( SHADERTYPE_PIXEL, "Smooth", "EqualWeightCombine_PostMult.nvp");
AddShaderCodeFile( SHADERTYPE_PIXEL, "Gray to NormalMap", "NormalMapCreate2_Scale.nvp");
}
NVEffect_DynamicReflection::NVEffect_DynamicReflection()
: m_eDisplayOption(DISPLAY_BLINN8BITSIGNED),
m_pPatchBuffer(NULL),
m_pVertexBuffer(NULL),
m_pIndexBuffer(NULL),
m_fAngle(0.0f),
m_pNVDevice(NULL),
m_pBumpMapQWVU(NULL),
m_bUsePatch(true),
m_dwBlinnPixelShader(0),
m_dwBlinnVertexShader(0),
m_dwTransformShader(0),
m_dwBlinnPatchVertexShader(0),
m_dwTransformPatchShader(0),
m_pCubeTexture(NULL),
m_bSupportsPatches(true),
m_pUI(NULL),
m_bWireframe(false),
m_bPause(true),
m_fBumpScale(INIT_BUMPSCALE),
m_pCA_Water(NULL)
{
m_strEffectName = "Dynamic Normal Map"; // A string holding the name of the effect
m_strEffectLocation = "Effects\\Bump Mapping";
m_strEffectPixelShader = GetFilePath("blinn_reflect.nvp");
m_strEffectVertexShader = GetFilePath("blinn_reflect.nvv");
m_strEffectVersion = "1.0";
}
NVEffect_DynamicReflection::~NVEffect_DynamicReflection()
{
Free();
}
#define TEX_SCALE 3.0f
HRESULT NVEffect_DynamicReflection::GenerateSphere(D3DXVECTOR3& vCenter, FLOAT fRadius, WORD wNumRings,
WORD wNumSections, FLOAT scale_x, FLOAT scale_y, FLOAT scale_z)
{
SimpleObject8 * pObj = new SimpleObject8();
assert( pObj != NULL );
pObj->InitSphere( fRadius, wNumRings, wNumSections );
////////////////////////////////////////////////
// Make vertex buffer & index buffer from it
HRESULT hr;
D3DXVECTOR3 vPoint;
DWORD i;
SAFE_RELEASE(m_pVertexBuffer);
SAFE_RELEASE(m_pIndexBuffer);
assert( pObj->m_PrimType == D3DPT_TRIANGLELIST );
DWORD wNumTriangles = pObj->m_wNumInd / 3;
DWORD dwNumIndices = pObj->m_wNumInd;
DWORD dwNumVertices = pObj->m_wNumVerts;
m_dwNumVertices = dwNumVertices;
m_dwNumIndices = wNumTriangles * 3;
m_dwNumFaces = wNumTriangles;
hr = m_pD3DDev->CreateVertexBuffer(dwNumVertices * sizeof(Dot3Vertex), 0, 0, D3DPOOL_DEFAULT,
&m_pVertexBuffer);
ASSERT_IF_FAILED(hr);
if (FAILED(hr))
return hr;
hr = m_pD3DDev->CreateIndexBuffer(3 * wNumTriangles * sizeof(WORD), 0, D3DFMT_INDEX16, D3DPOOL_DEFAULT,
&m_pIndexBuffer);
ASSERT_IF_FAILED(hr);
if (FAILED(hr))
return hr;
Dot3Vertex* pVertices;
WORD* pIndices;
m_pVertexBuffer->Lock(0, 0, (BYTE**)&pVertices, 0);
m_pIndexBuffer->Lock(0, 0, (BYTE**)&pIndices, 0);
float x,y,z, nx, ny, nz, u, v;
// copy positions into VB
for( i = 0; i < dwNumVertices; i++ )
{
x = scale_x * pObj->m_pVertices[i].pos.x + vCenter.x;
y = scale_y * pObj->m_pVertices[i].pos.y + vCenter.y;
z = scale_z * pObj->m_pVertices[i].pos.z + vCenter.z;
nx = pObj->m_pVertices[i].nrm.x;
ny = pObj->m_pVertices[i].nrm.y;
nz = pObj->m_pVertices[i].nrm.z;
u = pObj->m_pVertices[i].t0.x * TEX_SCALE;
v = pObj->m_pVertices[i].t0.y * TEX_SCALE;
pVertices[i] = Dot3Vertex( D3DXVECTOR3( x, y, z ),
D3DXVECTOR3( nx, ny, nz ),
D3DXVECTOR2( u, v ) );
}
// Generate triangle index buffer from simple object's indices
for( i = 0; i < dwNumIndices; i++ )
{
pIndices[i] = pObj->m_pIndices[i];
}
// All done - unlock the buffers:
hr = m_pVertexBuffer->Unlock();
ASSERT_IF_FAILED(hr);
hr = m_pIndexBuffer->Unlock();
ASSERT_IF_FAILED(hr);
// Free the SimpleObject
delete( pObj );
pObj = NULL;
// Compute the tangent space
// Degenerate vertices (same position, different coords) are
// found and averaged in the CreateBasis
hr = CreateBasisVectors( m_pVertexBuffer, m_pIndexBuffer);
ASSERT_IF_FAILED(hr);
return S_OK;
}
HRESULT NVEffect_DynamicReflection::GenerateQuad(D3DXVECTOR3& vCenter, FLOAT fRadius)
{
SAFE_RELEASE(m_pVertexBuffer);
SAFE_RELEASE(m_pIndexBuffer);
m_dwNumVertices = 4;
m_dwNumIndices = 6;
m_dwNumFaces = m_dwNumIndices / 3;
m_pD3DDev->CreateVertexBuffer(m_dwNumVertices * sizeof(Dot3Vertex), 0, 0, D3DPOOL_MANAGED, &m_pVertexBuffer);
m_pD3DDev->CreateIndexBuffer(m_dwNumIndices * sizeof(WORD), 0, D3DFMT_INDEX16, D3DPOOL_MANAGED, &m_pIndexBuffer);
Dot3Vertex* pVertices;
WORD* pIndices;
m_pVertexBuffer->Lock(0, 0, (BYTE**)&pVertices, 0);
m_pIndexBuffer->Lock(0, 0, (BYTE**)&pIndices, 0);
pVertices[0] = Dot3Vertex(D3DXVECTOR3(vCenter.x - fRadius, vCenter.y + fRadius, 0.0f), D3DXVECTOR3(0.0f, 0.0f, -1.0f), D3DXVECTOR2(0.0f, 0.0f));
pVertices[1] = Dot3Vertex(D3DXVECTOR3(vCenter.x + fRadius, vCenter.y + fRadius, 0.0f), D3DXVECTOR3(0.0f, 0.0f, -1.0f), D3DXVECTOR2(1.0f * TEX_SCALE, 0.0f));
pVertices[2] = Dot3Vertex(D3DXVECTOR3(vCenter.x - fRadius, vCenter.y - fRadius, 0.0f), D3DXVECTOR3(0.0f, 0.0f, -1.0f), D3DXVECTOR2(0.0f, 1.0f * TEX_SCALE));
pVertices[3] = Dot3Vertex(D3DXVECTOR3(vCenter.x + fRadius, vCenter.y - fRadius, 0.0f), D3DXVECTOR3(0.0f, 0.0f, -1.0f), D3DXVECTOR2(1.0f * TEX_SCALE, 1.0f * TEX_SCALE));
pIndices[0] = 0;
pIndices[1] = 1;
pIndices[2] = 2;
pIndices[3] = 2;
pIndices[4] = 1;
pIndices[5] = 3;
m_pVertexBuffer->Unlock();
m_pIndexBuffer->Unlock();
return S_OK;
}
HRESULT NVEffect_DynamicReflection::GenerateSplinePatch()
{
HRESULT hr;
SAFE_RELEASE(m_pPatchBuffer);
// first alloc the buffers
int const kNumCtrlPts = 4 * 4;
hr = m_pD3DDev->CreateVertexBuffer(kNumCtrlPts * sizeof(Dot3Vertex),
D3DUSAGE_RTPATCHES|D3DUSAGE_DYNAMIC|D3DUSAGE_WRITEONLY,
0, D3DPOOL_DEFAULT, &m_pPatchBuffer);
// then do not do anything with it: AnimateSplinePatch will generate *all* data!
return hr;
}
HRESULT NVEffect_DynamicReflection::AnimateSplinePatch(EBTimer* pTimer)
{
Dot3Vertex* pVertices;
static const float fZOffset = 0.0f;
m_pPatchBuffer->Lock(0, 0, (BYTE**)&pVertices, D3DLOCK_DISCARD);
// re-initialize positions
int i, j;
for(i = 0; i < 4; i++)
{
for(j = 0; j < 4; j++)
{
pVertices[4*i + j].Position = D3DXVECTOR3(j - 1.5f, 1.5f - i, fZOffset);
pVertices[4*i + j].Position *= 0.25f;
}
}
float anim_disp_scale = 0.65f;
if (!m_bPause)
{
// modify central control points
m_ctrl1 = (fZOffset + anim_disp_scale * sinf(1.0f + 0.5f * pTimer->GetDuration()));
m_ctrl2 = (fZOffset + anim_disp_scale * sinf(2.0f + 0.35f * pTimer->GetDuration()));
m_ctrl3 = (fZOffset + anim_disp_scale * sinf(3.0f + 0.6f * pTimer->GetDuration()));
m_ctrl4 = (fZOffset + anim_disp_scale * sinf(4.0f + 0.1f * pTimer->GetDuration()));
}
pVertices[4*1 + 1].Position.z = m_ctrl1;
pVertices[4*2 + 1].Position.z = m_ctrl2;
pVertices[4*1 + 2].Position.z = m_ctrl3;
pVertices[4*2 + 2].Position.z = m_ctrl4;
// compute d position / dv
D3DXVECTOR3 mesh[16];
for(i=0; i < 3; i++)
for(j=0; j < 4; j++)
mesh[4*i + j] = pVertices[4*(i+1) + j].Position - pVertices[4*i + j].Position;
// If the positions are reversed, the basis will be inverted and "high"
// bumps will appear as depressions instead
// ie, if you were to do:
// mesh[4*i + j] = pVertices[4*i + j].Position - pVertices[4*(i+1) + j].Position;
// the bumps would be reversed in that axis.
ElevateToCubicMesh(mesh, 4, 3);
for(i=0; i < 4; i++)
for(j=0; j < 4; j++)
pVertices[4*i + j].T = mesh[4*i + j];
///////////////////////////////////////////////
// d position / du
for(i=0; i < 4; i++)
for(j=0; j < 3; j++)
mesh[4*i + j] = pVertices[4*i + j+1].Position - pVertices[4*i + j].Position ;
// If the positions are reversed, the basis will be inverted and "high"
// bumps will appear as depressions instead
// ie, if you were to do:
// mesh[4*i + j] = pVertices[4*i + j].Position - pVertices[4*i + j+1].Position;
// the bumps would be reversed in that axis.
ElevateToCubicMesh(mesh, 3, 4);
for(i=0; i < 4; i++)
for(j=0; j < 4; j++)
pVertices[4*i + j].S = mesh[4*i + j];
return S_OK;
}
void NVEffect_DynamicReflection::ElevateToCubicMesh(D3DXVECTOR3 *pControlMesh,
unsigned int uOrder,
unsigned int vOrder) const
{
// Can transform constant, linear, quadratic, or cubic in either u/v
// to fully cubic in both u and v.
assert(uOrder >= 1 && uOrder <= 4);
assert(vOrder >= 1 && vOrder <= 4);
// mesh is assumed to be a 4x4 grid of D3DXVECTOR3, the upper left
// uOrder by vOrder corner is assumed to be populated with values and
// the elevation result is returned in the full 4x4 mesh.
D3DXMATRIX const allElevators[3] = {D3DXMATRIX(1.0f, 1.0f, 1.0f, 1.0f,
0.0f, 0.0f, 0.0f, 0.0f,
0.0f, 0.0f, 0.0f, 0.0f,
0.0f, 0.0f, 0.0f, 0.0f),
D3DXMATRIX(1.0f, 0.75f, 0.25f, 0.0f,
0.0f, 0.25f, 0.75f, 1.0f,
0.0f, 0.0f, 0.0f, 0.0f,
0.0f, 0.0f, 0.0f, 0.0f),
D3DXMATRIX(1.0f, 1.f/3.f, 0.0f, 0.0f,
0.0f, 2.f/3.f, 2.f/3.f, 0.0f,
0.0f, 0.0f, 1.f/3.f, 1.0f,
0.0f, 0.0f, 0.0f, 0.0f) };
D3DXMATRIX const *pElevator;
float const *pConstVec3Base;
float *pVec3Base;
int const kFloatsInVec = 3;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -