📄 shader_blinnreflect.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 "nvdevice.h"
#include "nvmesh.h"
#include "shader_dot3_util.h"
#include "shader_BlinnReflect.h"
#include "blinn_reflect.h"
#include "nvtexture.h"
#include <vector>
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 CShaderBlinnReflect();
}
}
HRESULT CShaderBlinnReflect::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)"
void CShaderBlinnReflect::UpdateProperties()
{
EBEffect::UpdateProperties();
AddProperty(new EBTriggerProperty(STR_INCREASEBUMPSCALE));
AddProperty(new EBTriggerProperty(STR_DECREASEBUMPSCALE));
AddProperty(new EBTriggerProperty(STR_RESETPATCH));
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));
if (m_bSupportsHILO)
pEnumProp->AddEnumerant(new EBEnumValue(pEnumProp, "16:16 HILO BumpMap", (DWORD)DISPLAY_BLINNHILOSIGNED, 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", OBJECT_MEMBER(m_bPause), EBTYPE_BOOL_PROP));
// Vertex shaders
m_pVertexShaderEnum->AddEnumerant(new EBEnumValue(m_pVertexShaderEnum, "Texture Space", GetFilePath("blinn_reflect.nvv"), EBTYPE_STRING_PROP));
m_pVertexShaderEnum->AddEnumerant(new EBEnumValue(m_pVertexShaderEnum, "Simple Transform", GetFilePath("dot3_transform.nvv"), EBTYPE_STRING_PROP));
// Pixel shaders
m_pPixelShaderEnum->AddEnumerant(new EBEnumValue(m_pPixelShaderEnum, "Per-pixel Bump Reflections", GetFilePath("blinn_reflect.nvp"), EBTYPE_STRING_PROP));
}
CShaderBlinnReflect::CShaderBlinnReflect()
: m_eDisplayOption(DISPLAY_BLINNHILOSIGNED),
m_pPatchBuffer(NULL),
m_pVertexBuffer(NULL),
m_pIndexBuffer(NULL),
m_fAngle(0.0f),
m_pLightMesh(NULL),
m_pNVDevice(NULL),
m_pBumpMapQWVU(NULL),
m_pBumpMapHILO(NULL),
m_pGlossMap(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(false),
m_fBumpScale(0.25f)
{
m_strEffectName = "Blinn Bump Reflection"; // A string holding the name of the effect
m_strEffectLocation = "Pixel Shaders\\Bump Mapping";
m_strEffectPixelShader = GetFilePath("blinn_reflect.nvp");
m_strEffectVertexShader = GetFilePath("blinn_reflect.nvv");
}
CShaderBlinnReflect::~CShaderBlinnReflect()
{
Free();
}
#define TEX_SCALE 3.0f
HRESULT CShaderBlinnReflect::GenerateSphere(D3DXVECTOR3& vCenter, FLOAT fRadius, WORD wNumRings, WORD wNumSections, FLOAT sx, FLOAT sy, FLOAT sz)
{
FLOAT x, y, z, v, rsintheta; // Temporary variables
WORD i, j, n, m; // counters
D3DXVECTOR3 vPoint;
HRESULT hr;
SAFE_RELEASE(m_pVertexBuffer);
SAFE_RELEASE(m_pIndexBuffer);
//Generate space for the required triangles and vertices.
WORD wNumTriangles = (wNumRings + 1) * wNumSections * 2;
DWORD dwNumIndices = wNumTriangles*3;
DWORD dwNumVertices = (wNumRings + 1) * wNumSections + 2;
m_dwNumVertices = dwNumVertices;
m_dwNumIndices = wNumTriangles * 3;
m_dwNumFaces = wNumTriangles;
hr = m_pD3DDev->CreateVertexBuffer(dwNumVertices * sizeof(Dot3Vertex), 0, 0, D3DPOOL_MANAGED, &m_pVertexBuffer);
if (FAILED(hr))
{
return hr;
}
hr = m_pD3DDev->CreateIndexBuffer(3 * wNumTriangles * sizeof(WORD), 0, D3DFMT_INDEX16, D3DPOOL_MANAGED, &m_pIndexBuffer);
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);
// Generate vertices at the top and bottom points.
D3DXVECTOR3 vTopPoint = vCenter + D3DXVECTOR3( 0.0f, +sy*fRadius, 0.0f);
D3DXVECTOR3 vBotPoint = vCenter + D3DXVECTOR3( 0.0f, -sy*fRadius, 0.0f);
D3DXVECTOR3 vNormal = D3DXVECTOR3( 0.0f, 1.0f, 0.0f );
pVertices[0] = Dot3Vertex( D3DXVECTOR3(vTopPoint.x, vTopPoint.y, vTopPoint.z), D3DXVECTOR3(vNormal.x, vNormal.y, vNormal.z), D3DXVECTOR2(0.0f, 0.0f) );
pVertices[dwNumVertices-1] = Dot3Vertex( D3DXVECTOR3(vBotPoint.x, vBotPoint.y, vBotPoint.z), D3DXVECTOR3(-vNormal.x, -vNormal.y, -vNormal.z), D3DXVECTOR2(0.0f, 0.0f) );
// Generate vertex points for rings
FLOAT dtheta = (float)(D3DX_PI / (wNumRings + 2)); //Angle between each ring
FLOAT dphi = (float)(2*D3DX_PI / (wNumSections)); //Angle between each section
FLOAT theta = dtheta;
n = 1; //vertex being generated, begins at 1 to skip top point
for( i = 0; i < (wNumRings+1); i++ )
{
y = fRadius * (float)cos(theta); // y is the same for each ring
v = theta / D3DX_PI; // v is the same for each ring
rsintheta = fRadius * (float)sin(theta);
FLOAT phi = 0.0f;
for( j = 0; j < wNumSections; j++ )
{
x = rsintheta * (float)sin(phi);
z = rsintheta * (float)cos(phi);
FLOAT u = 1.0f - (FLOAT)(phi / (2 * D3DX_PI) );
assert(u <= 1.001f);
assert(u >= 0.0f);
vPoint = vCenter + D3DXVECTOR3( sx*x, sy*y, sz*z );
vNormal = D3DXVECTOR3( x/fRadius, y/fRadius, z/fRadius );
D3DXVec3Normalize(&vNormal, &vNormal);
pVertices[n] = Dot3Vertex( D3DXVECTOR3(vPoint.x, vPoint.y, vPoint.z), D3DXVECTOR3(vNormal.x, vNormal.y, vNormal.z), D3DXVECTOR2(u * TEX_SCALE, v * TEX_SCALE) );
phi += dphi;
++n;
}
theta += dtheta;
}
// Generate triangles for top and bottom caps.
for( i = 0; i < wNumSections; i++ )
{
pIndices[3*i+0] = 0;
pIndices[3*i+1] = i + 1;
pIndices[3*i+2] = 1 + ((i + 1) % wNumSections);
pIndices[3*(wNumTriangles - wNumSections + i)+0] = (WORD)( dwNumVertices - 1 );
pIndices[3*(wNumTriangles - wNumSections + i)+1] = (WORD)( dwNumVertices - 2 - i );
pIndices[3*(wNumTriangles - wNumSections + i)+2] = (WORD)( dwNumVertices - 2 -
((1 + i) % wNumSections) );
}
// Generate triangles for the rings
m = 1; // first vertex in current ring,begins at 1 to skip top point
n = wNumSections; // triangle being generated, skip the top cap
for( i = 0; i < wNumRings; i++ )
{
for( j = 0; j < (wNumSections); j++ )
{
pIndices[3*n+0] = m + j;
pIndices[3*n+1] = m + wNumSections + j;
pIndices[3*n+2] = m + wNumSections + ((j + 1) % wNumSections);
pIndices[3*(n+1)+0] = pIndices[3*n+0];
pIndices[3*(n+1)+1] = pIndices[3*n+2];
pIndices[3*(n+1)+2] = m + ((j + 1) % wNumSections);
n += 2;
}
m += wNumSections;
}
m_pVertexBuffer->Unlock();
m_pIndexBuffer->Unlock();
return S_OK;
}
HRESULT CShaderBlinnReflect::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 CShaderBlinnReflect::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 CShaderBlinnReflect::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;
}
}
if (!m_bPause)
{
// modify central control points
m_ctrl1 = (fZOffset + sinf(1.0f + 0.5f * pTimer->GetDuration()));
m_ctrl2 = (fZOffset + sinf(2.0f + 0.35f * pTimer->GetDuration()));
m_ctrl3 = (fZOffset + sinf(3.0f + 0.6f * pTimer->GetDuration()));
m_ctrl4 = (fZOffset + 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/dv Position
D3DXVECTOR3 mesh[16];
for(i=0; i < 3; i++)
for(j=0; j < 4; j++)
mesh[4*i + j] = pVertices[4*i + j].Position - pVertices[4*(i+1) + j].Position;
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];
// dp/du
for(i=0; i < 4; i++)
for(j=0; j < 3; j++)
mesh[4*i + j] = pVertices[4*i + j].Position - pVertices[4*i + j+1].Position;
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 CShaderBlinnReflect::ElevateToCubicMesh(D3DXVECTOR3 *pControlMesh,
unsigned int uOrder,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -