📄 shader_dot3_point.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_Directional.h"
#include "shader_Dot3_Point.h"
#include "dot3.h"
#include "nvtexture.h"
using namespace nv_objects;
using namespace std;
void CShaderDot3Point::UpdateProperties()
{
EBEffect::UpdateProperties();
EBEnumProperty* pEnumProp = new EBEnumProperty("Display Options", OBJECT_MEMBER(m_eDisplayOption), EBTYPE_DWORD_PROP);
pEnumProp->AddEnumerant(new EBEnumValue(pEnumProp, "Show Bump Map", (DWORD)POINTDISPLAY_BUMPMAP, EBTYPE_DWORD_PROP));
pEnumProp->AddEnumerant(new EBEnumValue(pEnumProp, "Show Base Texture", (DWORD)POINTDISPLAY_BASETEXTURE, EBTYPE_DWORD_PROP));
pEnumProp->AddEnumerant(new EBEnumValue(pEnumProp, "Show Attenuation", (DWORD)POINTDISPLAY_LIGHTATTENUATION, EBTYPE_DWORD_PROP));
pEnumProp->AddEnumerant(new EBEnumValue(pEnumProp, "Show Normalized Texture Space Light Vector", (DWORD)POINTDISPLAY_TEXTURESPACELIGHTVECTOR, EBTYPE_DWORD_PROP));
pEnumProp->AddEnumerant(new EBEnumValue(pEnumProp, "Show Bumped Light", (DWORD)POINTDISPLAY_LIGHTBUMP, EBTYPE_DWORD_PROP));
pEnumProp->AddEnumerant(new EBEnumValue(pEnumProp, "Show Bumped Light + Base Texture", (DWORD)POINTDISPLAY_LIGHTBUMPBASE, EBTYPE_DWORD_PROP));
pEnumProp->AddEnumerant(new EBEnumValue(pEnumProp, "Show Bumped Light + Base Texture + Directional", (DWORD)POINTDISPLAY_RESULT, EBTYPE_DWORD_PROP));
AddProperty(new EBTriggerProperty("Change light color..."));
AddProperty(pEnumProp);
// Vertex shaders
m_pVertexShaderEnum->AddEnumerant(new EBEnumValue(m_pVertexShaderEnum, "Point Texture Space", GetFilePath("dot3_point.nvv"), EBTYPE_STRING_PROP));
m_pVertexShaderEnum->AddEnumerant(new EBEnumValue(m_pVertexShaderEnum, "Simple Transform", GetFilePath("dot3_transform.nvv"), EBTYPE_STRING_PROP));
m_pVertexShaderEnum->AddEnumerant(new EBEnumValue(m_pVertexShaderEnum, "Directional Texture Space", GetFilePath("dot3_directional.nvv"), EBTYPE_STRING_PROP));
m_pVertexShaderEnum->AddEnumerant(new EBEnumValue(m_pVertexShaderEnum, "Attenuation Setup", GetFilePath("dot3_point_atten.nvv"), EBTYPE_STRING_PROP));
AddProperty(new EBProperty("Wireframe", OBJECT_MEMBER(m_bWireframe), EBTYPE_BOOL_PROP));
AddProperty(new EBProperty("Pause lights", OBJECT_MEMBER(m_bPause), EBTYPE_BOOL_PROP));
}
void CShaderDot3Point::PropertyUpdateCallback(const EBProperty* pProperty, bool bWritten)
{
if (!bWritten)
return;
if (pProperty->IsKindOf(EBTYPE_TRIGGER_PROP))
{
// We only support one trigger property - the Light color one
CHOOSECOLOR cc;
COLORREF crSavedCustom[16];
for (int i = 0; i < sizeof(crSavedCustom) / sizeof(COLORREF); i++)
{
crSavedCustom[i] = RGB(255, 255, 255);
}
ZeroMemory(&cc, sizeof(CHOOSECOLOR));
cc.lStructSize = sizeof(CHOOSECOLOR);
cc.rgbResult = 0xFFFFFF;
cc.lpCustColors = &crSavedCustom[0];
cc.Flags = CC_ANYCOLOR;
if (::ChooseColor(&cc))
{
for (int i = 0; i < NUM_DOT3_POINTLIGHTS; i++)
{
m_LightColor[i].z = ((cc.rgbResult & 0xFF0000) >> 16);
m_LightColor[i].y = ((cc.rgbResult & 0x00FF00) >> 8);
m_LightColor[i].x = ((cc.rgbResult & 0x0000FF));
m_LightColor[i] /= 255.0f;
}
}
}
}
CShaderDot3Point::CShaderDot3Point()
: m_eDisplayOption(POINTDISPLAY_RESULT),
m_pSphereVertexBuffer(NULL),
m_pSphereIndexBuffer(NULL),
m_fAngle(0.0f),
m_pLightMesh(NULL),
m_pNVDevice(NULL),
m_pBumpMap(NULL),
m_pBaseTexture(NULL),
m_pAttenuate2D(NULL),
m_dwLightShader(0),
m_dwTransformShader(0),
m_dwDot3PointLightAttenuationShader(0),
m_dwDot3PointLightBumpShader(0),
m_dwDot3DirectionalLightBumpShader(0),
m_pNormalizationCubeMap(NULL),
m_pUI(NULL),
m_bWireframe(false),
m_bPause(false),
m_fDuration(0.0f)
{
m_strEffectName = "Dot3 Bump Point Light"; // A string holding the name of the effect
m_strEffectLocation = "Vertex Shaders\\Bump Mapping";
m_strEffectPixelShader = "";
m_strEffectVertexShader = GetFilePath("dot3_point.nvv");
}
CShaderDot3Point::~CShaderDot3Point()
{
Free();
}
HRESULT CShaderDot3Point::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_pSphereVertexBuffer);
SAFE_RELEASE(m_pSphereIndexBuffer);
//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_pSphereVertexBuffer);
if (FAILED(hr))
{
return hr;
}
hr = m_pD3DDev->CreateIndexBuffer(3 * wNumTriangles * sizeof(WORD), 0, D3DFMT_INDEX16, D3DPOOL_MANAGED, &m_pSphereIndexBuffer);
if (FAILED(hr))
{
return hr;
}
Dot3Vertex* pVertices;
WORD* pIndices;
hr = m_pSphereVertexBuffer->Lock(0, 0, (BYTE**)&pVertices, 0);
if (FAILED(hr))
return hr;
m_pSphereIndexBuffer->Lock(0, 0, (BYTE**)&pIndices, 0);
if (FAILED(hr))
return hr;
// 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, v) );
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_pSphereVertexBuffer->Unlock();
m_pSphereIndexBuffer->Unlock();
return S_OK;
}
// This takes the color channel of an 8888 texture and puts it in the alpha channel.
// We use this for the attenuation maps.
HRESULT CShaderDot3Point::FixAlpha(LPDIRECT3DTEXTURE8 pTexture)
{
D3DSURFACE_DESC ddsdDesc;
pTexture->GetLevelDesc(0, &ddsdDesc);
D3DLOCKED_RECT Locked;
if (ddsdDesc.Format != D3DFMT_A8R8G8B8)
{
return E_FAIL;
}
HRESULT hr = pTexture->LockRect(0, &Locked, NULL, 0);
for (int y = 0; y < ddsdDesc.Height; y++)
{
for (int x = 0; x < ddsdDesc.Width; x++)
{
DWORD* pBits = (DWORD*)((BYTE*)Locked.pBits + (y * Locked.Pitch));
pBits += x;
*pBits &= 0x00FFFFFF;
*pBits |= ((*pBits & 0xFF) << 24);
}
}
hr = pTexture->UnlockRect(NULL);
return hr;
}
HRESULT CShaderDot3Point::Initialize(IDirect3DDevice8* pDev)
{
HRESULT hr;
vector<DWORD> Declaration;
m_pD3DDev = pDev;
pDev->AddRef();
m_pNVDevice = new NVDot3PointDevice(pDev, this);
m_pLightMesh = new NVMesh();
hr = m_pLightMesh->Create(m_pNVDevice, GetFilePath("sphere.x"));
if (FAILED(hr))
{
m_strLastError = "Could not load arrow.x";
return hr;
}
m_pLightMesh->SetFVF(m_pNVDevice, D3DFVF_NORMAL | D3DFVF_XYZ | D3DFVF_TEX1);
hr = GenerateSphere(D3DXVECTOR3(0.0f, 0.0f, 0.0f), 1.0f, 10, 20, 1.0f, 1.0f, 1.0f);
if (FAILED(hr))
{
m_strLastError = "Could not generate sphere";
return hr;
}
//initialize mouse UI
RECT rect;
rect.left = rect.top = 0;
D3DVIEWPORT8 viewport;
m_pD3DDev->GetViewport(&viewport);
rect.bottom = viewport.Height;
rect.right = viewport.Width;
m_pUI = new MouseUI((const RECT)rect);
Declaration.clear();
Declaration.push_back(D3DVSD_STREAM(0));
Declaration.push_back(D3DVSD_REG(0, D3DVSDT_FLOAT3)); // Pos
Declaration.push_back(D3DVSD_REG(1, D3DVSDT_FLOAT3)); // Normal
Declaration.push_back(D3DVSD_REG(2, D3DVSDT_FLOAT2)); // Texture
Declaration.push_back(D3DVSD_END());
hr = LoadAndCreateShader(GetFilePath("dot3_lightobject.vso"), &Declaration[0], 0, SHADERTYPE_VERTEX, &m_dwLightShader);
if (FAILED(hr))
return hr;
m_pLightMesh->SetVertexShader(m_dwLightShader);
Declaration.clear();
Declaration.push_back(D3DVSD_STREAM(0));
Declaration.push_back(D3DVSD_REG(0, D3DVSDT_FLOAT3)); // Position
Declaration.push_back(D3DVSD_REG(1, D3DVSDT_FLOAT3)); // Normal
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -