3DShader之投影贴图(Projective Texturing)
相信大家都应该玩过CS或者CF吧,游戏里面有个喷图功能,就是按一个T键就能在墙上或者地板上喷出自己预先设定的图案.
而刚好这就是我们这个Shader所需实现的内容.由于没有潜伏者的贴图,我只有从这个图里用PS扣一个Alpha通道出来,我后面会讲具体操作
下面就起跟我一起进入亮瞎氪金狗眼的3D世界吧
国际惯例上图先:
怎么样?过瘾吧,这样的话,到处乱喷,估计保卫者都快疯掉了,呵呵!!!!!!!!!
好了,进入正题,讲下原理:
投影贴图是从灯光处看到世界坐标系的原点从而建立VIEW矩阵,物体在灯光中视椎体的位置仍然由物体的MODEL矩阵来控制,然后通过PROJECTION矩阵转成标准设备坐标,由于标准设备坐标的范围为(-1,1),但是纹理坐标的范围为(0,1),所以我们需要将其移动到(0,1)
投影贴图的矩阵变换
In the rendering pipeline, geometry outside the frustum is clipped. However, when we generate projective texture coordinates by projecting the geometry from the
point of view of the light projector, no clipping is done — we simply project vertices. Consequently, geometry outside the projector's frustum receives projective texture coordinates outside the [0, 1] range.
这里有两种方法来处理位于视椎体外面的点,一种方法:就是为灯光设置一个锥形照射范围,这样超过这个范围的点将不会映射,第二种方法,我们检测纹理坐标,如何超出了(0,1)的范围,我们就不要映射了.
这里我们采用了第二种方法:
float2 uv = texCoordProj.xy / texCoordProj.w;
if( uv.x < 0.0f || uv.x > 1.0f || uv.y < 0.0f || uv.y > 1.0f )
{
return diffuseLighting;
}
另外,我们会发现,视椎体的前后都会投影,
The second issue is that back-projection artifacts can appear when the q coordinate is negative.
Back-projection refers to the texture being projected on surfaces that are behind the light source (or
projector).
There are several ways to avoid artifacts when q is negative:
1.Use culling to draw only geometry that is in front of the light source.
2.Use clip planes to remove geometry that is behind the light source.
3.Fold the back-projection factor into a 3D attenuation texture.
4.Use a fragment program to check when q is negative.
The first two solutions are tedious to implement; the fragment program solution is simple and efficient but
requires an advanced fragment profile. Just check the value of the q coordinate. If q is negative, you can
ignore the projective texture computation and output black.
这里我们采用第4种方法
if( texCoordProj.w < 0 )
{
return diffuseLighting;
}
好了,这里讲下PS相关的内容,为了将潜伏者从原图中扣出来,去掉背景的影响,我们需要新建一个Alpha通道,然后在Alpha通道里用多边形套索工具,自己慢慢把它扣出来,最后保存为32位的tga格式,将alpha通道保存进去
alpha通道
然后在片断着色器中,我们采用混合的方式,将其显示出来
return textureColor * textureColor.w + (1.0 - textureColor.w) * diffuseLighting;
最后再来一个暴雪的LOGO吧
是不是有点像放电影的赶脚,呵呵.
好了,贴下源代码
/*------------------------------------------------------------
3D_Shader_ProjectivetTexturing.cpp -- achieve projective texturing
(c) Seamanj.2013/8/30
------------------------------------------------------------*/
#include "DXUT.h"
#include "resource.h" // phase1 : add camera
// phase2 : add wall
// phase3 : add light and shader
// phase4 : add animation
// phase5 : add objects in space
// phase6 : add projective texture
#define phase1 1
#define phase2 1
#define phase3 1
#define phase4 1
#define phase5 1
#define phase6 1
#if phase1
#include "DXUTcamera.h"
CModelViewerCamera g_Camera;
#endif #if phase2
// Vertex Buffer
LPDIRECT3DVERTEXBUFFER9 g_pVB = NULL;
// Index Buffer
LPDIRECT3DINDEXBUFFER9 g_pIB = NULL;
#endif #if phase3
#include "SDKmisc.h"//加载文件时会用到
ID3DXEffect* g_pEffect = NULL; // D3DX effect interface
D3DXHANDLE g_hTech = 0;
D3DXHANDLE g_hWorldViewProj = NULL;
D3DXHANDLE g_hWorld = NULL;
D3DXHANDLE g_hWorldInv = NULL;
D3DXHANDLE g_hLightPosition = NULL; ID3DXMesh* g_pLightSphereMesh = 0;
static float g_fLightAngle = -0.4; /* Angle light rotates around scene. */
static float g_fLightHeight = 2.0f; /* Vertical height of light. */ #endif #if phase4
static bool g_bAnimation = false;
short g_sDirection = 1;
#endif #if phase5
ID3DXMesh* g_pSphereMesh = 0;
ID3DXMesh* g_pTeapotMesh = 0;
#endif #if phase6
IDirect3DTexture9* g_pTex = NULL;
D3DXHANDLE g_hTex = NULL;
D3DXHANDLE g_hTextureMatrix = NULL;
#endif
//--------------------------------------------------------------------------------------
// Rejects any D3D9 devices that aren't acceptable to the app by returning false
//--------------------------------------------------------------------------------------
bool CALLBACK IsD3D9DeviceAcceptable( D3DCAPS9* pCaps, D3DFORMAT AdapterFormat, D3DFORMAT BackBufferFormat,
bool bWindowed, void* pUserContext )
{
// Typically want to skip back buffer formats that don't support alpha blending
IDirect3D9* pD3D = DXUTGetD3D9Object();
if( FAILED( pD3D->CheckDeviceFormat( pCaps->AdapterOrdinal, pCaps->DeviceType,
AdapterFormat, D3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING,
D3DRTYPE_TEXTURE, BackBufferFormat ) ) )
return false; return true;
} //--------------------------------------------------------------------------------------
// Before a device is created, modify the device settings as needed
//--------------------------------------------------------------------------------------
bool CALLBACK ModifyDeviceSettings( DXUTDeviceSettings* pDeviceSettings, void* pUserContext )
{
#if phase1
pDeviceSettings->d3d9.pp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;
#endif return true;
} //--------------------------------------------------------------------------------------
// Create any D3D9 resources that will live through a device reset (D3DPOOL_MANAGED)
// and aren't tied to the back buffer size
//--------------------------------------------------------------------------------------
HRESULT CALLBACK OnD3D9CreateDevice( IDirect3DDevice9* pd3dDevice, const D3DSURFACE_DESC* pBackBufferSurfaceDesc,
void* pUserContext )
{
#if phase1
// Setup the camera's view parameters
D3DXVECTOR3 vecEye( 0.0f, 0.0f, -5.0f );
D3DXVECTOR3 vecAt ( 0.0f, 0.0f, -0.0f );
g_Camera.SetViewParams( &vecEye, &vecAt );
FLOAT fObjectRadius=1;
//摄像机缩放的3个参数
g_Camera.SetRadius( fObjectRadius * 3.0f, fObjectRadius * 0.5f, fObjectRadius * 20.0f );
g_Camera.SetEnablePositionMovement( true ); #endif
#if phase3
HRESULT hr;
// Create vertex shader
WCHAR str[MAX_PATH];
// Read the D3DX effect file
V_RETURN( DXUTFindDXSDKMediaFileCch( str, MAX_PATH, L"ProjectiveTexturing.fx" ) );
// Create the effect
LPD3DXBUFFER pErrorBuff;
V_RETURN( D3DXCreateEffectFromFile(
pd3dDevice, // associated device
str, // effect filename
NULL, // no preprocessor definitions
NULL, // no ID3DXInclude interface
D3DXSHADER_DEBUG, // compile flags
NULL, // don't share parameters
&g_pEffect, // return effect
&pErrorBuff // return error messages
) );
//pErrorBuff
// Get handle
g_hTech = g_pEffect->GetTechniqueByName("MyTechnique"); g_hWorldViewProj = g_pEffect->GetParameterByName(0, "g_mWorldViewProj");
g_hLightPosition = g_pEffect->GetParameterByName(0, "g_lightPosition");
g_hWorld = g_pEffect->GetParameterByName(0, "g_mWorld");
g_hWorldInv = g_pEffect->GetParameterByName(0, "g_mWorldInv"); D3DXCreateSphere(pd3dDevice, 0.15, 30, 30, &g_pLightSphereMesh, 0); #endif
#if phase5
D3DXCreateSphere(pd3dDevice, 2.0f, 40, 40, &g_pSphereMesh, 0);
D3DXCreateTeapot(pd3dDevice, &g_pTeapotMesh, 0);
#endif
#if phase6 g_hTextureMatrix = g_pEffect->GetParameterByName(0, "g_mTextureMatrix");
g_hTex = g_pEffect->GetParameterByName(0, "g_tex");
D3DXCreateTextureFromFile(pd3dDevice, L"cf.tga", &g_pTex);
#endif
return S_OK;
} #if phase2
struct MyVertexFormat
{
FLOAT x, y, z;
FLOAT nx, ny, nz;
};
#define FVF_VERTEX (D3DFVF_XYZ | D3DFVF_NORMAL )
static HRESULT initVertexIndexBuffer(IDirect3DDevice9* pd3dDevice)
{
static const MyVertexFormat Vertices[] =
{
//floor
{ 12, -2, -12, 0, 1, 0 },
{ -12, -2, -12, 0, 1, 0 },
{ -12, -2, 12 , 0, 1, 0 },
{ 12, -2, 12, 0, 1, 0 },
//front
{ -12, -2, -12,0, 0, 1 },
{ 12, -2, -12,0, 0, 1 },
{ 12, 10, -12,0, 0, 1 },
{ -12, 10, -12, 0, 0, 1},
//back
{ 12, -2, 12 ,0, 0, -1 },
{ -12, -2, 12 ,0, 0, -1 },
{ -12, 10, 12 ,0, 0, -1},
{ 12, 10, 12,0, 0, -1 },
//ceiling { -12, 10, -12,0, -1, 0 },
{ 12, 10, -12,0, -1, 0 },
{ 12, 10, 12,0, -1, 0 },
{ -12, 10, 12,0, -1, 0},
//left
{ -12, -2, 12,1, 0, 0 },
{ -12, -2, -12,1, 0, 0 },
{ -12, 10, -12,1, 0, 0 },
{-12, 10, 12,1, 0, 0 },
//-right
{ 12, -2, -12,-1, 0, 0 },
{ 12, -2, 12,-1, 0, 0 },
{12, 10, 12,-1, 0, 0},
{12, 10, -12,-1, 0, 0 }
};
if (FAILED(pd3dDevice->CreateVertexBuffer(sizeof(Vertices),
0, FVF_VERTEX,
D3DPOOL_DEFAULT,
&g_pVB, NULL))) {
return E_FAIL;
}
void* pVertices;
if (FAILED(g_pVB->Lock(0, 0, /* map entire buffer */
&pVertices, 0))) {
return E_FAIL;
}
memcpy(pVertices, Vertices, sizeof(Vertices));
g_pVB->Unlock(); // Create and initialize index buffer
static const WORD Indices[] =
{
0, 1, 2,
0, 2, 3, 4, 5, 6,
4, 6, 7, 8, 9, 10,
8,10, 11, 12,13,14,
12,14,15, 16,17,18,
16,18,19, 20,21,22,
20,22,23
};
if (FAILED(pd3dDevice->CreateIndexBuffer(sizeof(Indices),
D3DUSAGE_WRITEONLY,
D3DFMT_INDEX16,
D3DPOOL_DEFAULT,
&g_pIB, NULL))) {
return E_FAIL;
}
void* pIndices;
if (FAILED(g_pIB->Lock(0, 0, /* map entire buffer */
&pIndices, 0))) {
return E_FAIL;
}
memcpy(pIndices, Indices, sizeof(Indices));
g_pIB->Unlock();
return S_OK;
} #endif
//--------------------------------------------------------------------------------------
// Create any D3D9 resources that won't live through a device reset (D3DPOOL_DEFAULT)
// or that are tied to the back buffer size
//--------------------------------------------------------------------------------------
HRESULT CALLBACK OnD3D9ResetDevice( IDirect3DDevice9* pd3dDevice, const D3DSURFACE_DESC* pBackBufferSurfaceDesc,
void* pUserContext )
{
#if phase3
HRESULT hr;
if( g_pEffect )
V_RETURN( g_pEffect->OnResetDevice() );
#endif
#if phase2
pd3dDevice->SetRenderState( D3DRS_CULLMODE, D3DCULL_NONE );
//Setup the camera's projection parameters
float fAspectRatio = pBackBufferSurfaceDesc->Width / ( FLOAT )pBackBufferSurfaceDesc->Height; g_Camera.SetProjParams( D3DX_PI / 2, fAspectRatio, 0.1f, 5000.0f );
g_Camera.SetWindow( pBackBufferSurfaceDesc->Width, pBackBufferSurfaceDesc->Height );
g_Camera.SetButtonMasks( MOUSE_LEFT_BUTTON, MOUSE_WHEEL, MOUSE_RIGHT_BUTTON );
#endif
#if !phase1
return S_OK;
#else
return initVertexIndexBuffer(pd3dDevice);
#endif } #if phase4
static const double my2Pi = 2.0 * 3.14159265358979323846;
#endif
//--------------------------------------------------------------------------------------
// Handle updates to the scene. This is called regardless of which D3D API is used
//--------------------------------------------------------------------------------------
void CALLBACK OnFrameMove( double fTime, float fElapsedTime, void* pUserContext )
{
#if phase1
g_Camera.FrameMove( fElapsedTime );
#endif
#if phase4
if( g_bAnimation )
{
if( g_fLightHeight > 9.0f)
g_sDirection = -1;
else if( g_fLightHeight < -1.5f )
g_sDirection = 1;
g_fLightHeight += 0.0002 * g_sDirection;
g_fLightAngle += 0.0002;
if( g_fLightAngle > my2Pi)
{
g_fLightAngle -= my2Pi;
} }
#endif
} #if phase6
static void buildTextureMatrix(D3DXMATRIXA16& textureMatrix,
const D3DXMATRIXA16& modelMatrix,
const D3DXMATRIXA16& viewMatrix
)//需要modelMatrix是因为需要了解物体在灯光的视椎体里面的位置
{
D3DXMATRIXA16 projMatrix;
D3DXMATRIXA16 RangeMappingMatrix(
0.5, 0, 0, 0,
0, 0.5, 0, 0,
0, 0,0.5, 0,
0.5, 0.5,0.5, 1);
D3DXMatrixPerspectiveFovLH(&projMatrix, 50.0f * 3.14f / 180.0f , 1.72f, 0.25, 20.0);
textureMatrix = modelMatrix * viewMatrix * projMatrix * RangeMappingMatrix;
}
static void buildLightViewMatrix(D3DXMATRIXA16& lightViewMatrix,const D3DXVECTOR3 *pLightPosition )
{
D3DXMatrixLookAtLH(&lightViewMatrix, pLightPosition,
&D3DXVECTOR3(0, 0, 0), &D3DXVECTOR3(0, -1, 0));//看世界坐标系中的原点
}
#endif
//--------------------------------------------------------------------------------------
// Render the scene using the D3D9 device
//--------------------------------------------------------------------------------------
void CALLBACK OnD3D9FrameRender( IDirect3DDevice9* pd3dDevice, double fTime, float fElapsedTime, void* pUserContext )
{
HRESULT hr;
#if phase3
const float lightPosition[4] = { 6*sin(g_fLightAngle),
g_fLightHeight,
6*cos(g_fLightAngle), 1 };
#endif
// Clear the render target and the zbuffer
V( pd3dDevice->Clear( 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_ARGB( 0, 45, 50, 170 ), 1.0f, 0 ) ); // Render the scene
if( SUCCEEDED( pd3dDevice->BeginScene() ) )
{
#if phase3
UINT iPass, cPasses;
D3DXMATRIXA16 mWorldViewProjection,mWorld,mWorldInv;
#if phase6
D3DXMATRIXA16 mLightViewMatrix, mTextureMatrix;
#endif
V(g_pEffect->SetTechnique(g_hTech));
V( g_pEffect->Begin( &cPasses, 0 ) );
for( iPass = 0; iPass < cPasses; iPass++ )
{
V( g_pEffect->BeginPass( iPass ) ); //set light position
V( g_pEffect->SetFloatArray( g_hLightPosition, lightPosition, 4) );
#if phase6
//set texture
V( g_pEffect->SetTexture( g_hTex, g_pTex) );
#endif
#if phase2//build wall
#if phase5
// Set world matrix
D3DXMatrixIdentity(&mWorld);
V( g_pEffect->SetMatrix( g_hWorld, &mWorld) );
// Set world inverse matrix
D3DXMatrixInverse(&mWorldInv, NULL, &mWorld);
V( g_pEffect->SetMatrix( g_hWorldInv, &mWorldInv) );
// set worldviewproj matrix
mWorldViewProjection = mWorld * *g_Camera.GetViewMatrix() * *g_Camera.GetProjMatrix();
V( g_pEffect->SetMatrix( g_hWorldViewProj, &mWorldViewProjection) );
#endif
#if phase6
// set light view matrix
buildLightViewMatrix(mLightViewMatrix, &D3DXVECTOR3(lightPosition[0], lightPosition[1], lightPosition[2]) );
// set texture matrix
buildTextureMatrix(mTextureMatrix, mWorld, mLightViewMatrix);
V( g_pEffect->SetMatrix( g_hTextureMatrix, &mTextureMatrix) );
#endif pd3dDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_CCW);
V( g_pEffect->CommitChanges() );
pd3dDevice->SetStreamSource(0, g_pVB, 0, sizeof(MyVertexFormat));
pd3dDevice->SetIndices(g_pIB);//sets the current index buffer.
pd3dDevice->SetFVF(FVF_VERTEX);//Sets the current vertex stream declaration.
pd3dDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 0, 24, 0, 12);
#endif
#if phase5
// Set world matrix
D3DXMatrixTranslation(&mWorld, 2, 0, 0);
V( g_pEffect->SetMatrix( g_hWorld, &mWorld) ); // Set world inverse matrix
D3DXMatrixInverse(&mWorldInv, NULL, &mWorld);
V( g_pEffect->SetMatrix( g_hWorldInv, &mWorldInv) ); // set worldviewproj matrix
mWorldViewProjection = mWorld * *g_Camera.GetViewMatrix() * *g_Camera.GetProjMatrix();
V( g_pEffect->SetMatrix( g_hWorldViewProj, &mWorldViewProjection) );
#if phase6
// set light view matrix
buildLightViewMatrix(mLightViewMatrix, &D3DXVECTOR3(lightPosition[0], lightPosition[1], lightPosition[2]) );
// set texture matrix
buildTextureMatrix(mTextureMatrix, mWorld, mLightViewMatrix);
V( g_pEffect->SetMatrix( g_hTextureMatrix, &mTextureMatrix) );
#endif V( g_pEffect->CommitChanges() );
g_pSphereMesh->DrawSubset(0);
// set teapot world matrix
// Set world matrix
D3DXMatrixTranslation(&mWorld, -2, 1, 0);
V( g_pEffect->SetMatrix( g_hWorld, &mWorld) ); // Set world inverse matrix
D3DXMatrixInverse(&mWorldInv, NULL, &mWorld);
V( g_pEffect->SetMatrix( g_hWorldInv, &mWorldInv) ); // set worldviewproj matrix
mWorldViewProjection = mWorld * *g_Camera.GetViewMatrix() * *g_Camera.GetProjMatrix();
V( g_pEffect->SetMatrix( g_hWorldViewProj, &mWorldViewProjection) ); #if phase6
// set light view matrix
buildLightViewMatrix(mLightViewMatrix, &D3DXVECTOR3(lightPosition[0], lightPosition[1], lightPosition[2]) );
// set texture matrix
buildTextureMatrix(mTextureMatrix, mWorld, mLightViewMatrix);
V( g_pEffect->SetMatrix( g_hTextureMatrix, &mTextureMatrix) );
#endif
V( g_pEffect->CommitChanges() );
g_pTeapotMesh->DrawSubset(0); #endif
V( g_pEffect->EndPass() );
}
V( g_pEffect->End() );
#endif #if phase3
pd3dDevice->SetRenderState(D3DRS_LIGHTING, false);
// Set world matrix
D3DXMATRIX M;
D3DXMatrixIdentity( &M ); // M = identity matrix
D3DXMatrixTranslation(&M, lightPosition[0], lightPosition[1], lightPosition[2]);
pd3dDevice->SetTransform(D3DTS_WORLD, &M) ;
//这里三角形更像是世界坐标中静止的物体(比如墙)因为按W它会相对与摄像机会动,不像茶壶总在摄像机前面,相对于摄像机静止
// Set view matrix
D3DXMATRIX view = *g_Camera.GetViewMatrix() ;
pd3dDevice->SetTransform(D3DTS_VIEW, &view) ;
// Set projection matrix
D3DXMATRIX proj = *g_Camera.GetProjMatrix() ;
pd3dDevice->SetTransform(D3DTS_PROJECTION, &proj) ;
g_pLightSphereMesh->DrawSubset(0);
#endif
V( pd3dDevice->EndScene() );
}
} //--------------------------------------------------------------------------------------
// Handle messages to the application
//--------------------------------------------------------------------------------------
LRESULT CALLBACK MsgProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam,
bool* pbNoFurtherProcessing, void* pUserContext )
{
#if phase1
g_Camera.HandleMessages( hWnd, uMsg, wParam, lParam );
#endif
return 0;
} //--------------------------------------------------------------------------------------
// Release D3D9 resources created in the OnD3D9ResetDevice callback
//--------------------------------------------------------------------------------------
void CALLBACK OnD3D9LostDevice( void* pUserContext )
{
#if phase1
SAFE_RELEASE(g_pVB);
SAFE_RELEASE(g_pIB);
#endif
#if phase3
if( g_pEffect )
g_pEffect->OnLostDevice();
#endif
} //--------------------------------------------------------------------------------------
// Release D3D9 resources created in the OnD3D9CreateDevice callback
//--------------------------------------------------------------------------------------
void CALLBACK OnD3D9DestroyDevice( void* pUserContext )
{
#if phase3 SAFE_RELEASE(g_pEffect);
SAFE_RELEASE(g_pLightSphereMesh); #endif
#if phase5
SAFE_RELEASE(g_pSphereMesh);
SAFE_RELEASE(g_pTeapotMesh);
#endif
#if phase6
SAFE_RELEASE(g_pTex);
#endif
}
#if phase4
void CALLBACK OnKeyboardProc(UINT character, bool is_key_down, bool is_alt_down, void* user_context)
{
if(is_key_down)
{
switch(character)
{
case VK_SPACE:
g_bAnimation = !g_bAnimation;
break;
}
}
}
#endif //--------------------------------------------------------------------------------------
// Initialize everything and go into a render loop
//--------------------------------------------------------------------------------------
INT WINAPI wWinMain( HINSTANCE, HINSTANCE, LPWSTR, int )
{
// Enable run-time memory check for debug builds.
#if defined(DEBUG) | defined(_DEBUG)
_CrtSetDbgFlag( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF );
#endif // Set the callback functions
DXUTSetCallbackD3D9DeviceAcceptable( IsD3D9DeviceAcceptable );
DXUTSetCallbackD3D9DeviceCreated( OnD3D9CreateDevice );
DXUTSetCallbackD3D9DeviceReset( OnD3D9ResetDevice );
DXUTSetCallbackD3D9FrameRender( OnD3D9FrameRender );
DXUTSetCallbackD3D9DeviceLost( OnD3D9LostDevice );
DXUTSetCallbackD3D9DeviceDestroyed( OnD3D9DestroyDevice );
DXUTSetCallbackDeviceChanging( ModifyDeviceSettings );
DXUTSetCallbackMsgProc( MsgProc );
DXUTSetCallbackFrameMove( OnFrameMove );
#if phase4
DXUTSetCallbackKeyboard( OnKeyboardProc );
#endif
// TODO: Perform any application-level initialization here // Initialize DXUT and create the desired Win32 window and Direct3D device for the application
DXUTInit( true, true ); // Parse the command line and show msgboxes
DXUTSetHotkeyHandling( true, true, true ); // handle the default hotkeys
DXUTSetCursorSettings( true, true ); // Show the cursor and clip it when in full screen
DXUTCreateWindow( L"3D_Shader_ProjectivetTexturing" );
DXUTCreateDevice( true, 640, 480 ); // Start the render loop
DXUTMainLoop(); // TODO: Perform any application-level cleanup here return DXUTGetExitCode();
}
/*--------------------------------------------------------------------------
ProjectiveTexturing.fx -- Projective texturing shader
(c) Seamanj.2013/8/30
--------------------------------------------------------------------------*/ //--------------------------------------------------------------------------------------
// Global variables
//--------------------------------------------------------------------------------------
float4x4 g_mWorldViewProj;
float4x4 g_mWorld;
float4x4 g_mWorldInv;
float4x4 g_mTextureMatrix;
float3 g_lightPosition; texture g_tex;
//-----------------------------------------------------------------------------
// Sampler
//----------------------------------------------------------------------------- sampler2D g_sam =
sampler_state
{
Texture = <g_tex>;
MinFilter = Linear;
MagFilter = Linear;
MipFilter = Linear;
AddressU = Border;
AddressV = Border;
};
//--------------------------------------------------------------------------------------
// Vertex shader output structure
//--------------------------------------------------------------------------------------
struct VS_Output {
float4 position : POSITION;
float4 diffuseLighting : COLOR;
float4 texCoordProj : TEXCOORD0;
}; //--------------------------------------------------------------------------------------
// Vertex shader
//--------------------------------------------------------------------------------------
VS_Output MyVertexEntry(float4 position : POSITION,float3 normal : NORMAL)
{
VS_Output OUT; OUT.position = mul ( position, g_mWorldViewProj); OUT.texCoordProj = mul(position, g_mTextureMatrix); // Compute diffuse lighting
normal = mul(normal, transpose((float3x3)g_mWorldInv));
float3 N = normalize(normal);
position = mul( position, g_mWorld );//在世界坐标系中计算光照
float3 L = normalize(g_lightPosition - position.xyz);
OUT.diffuseLighting = float4(1,1,1,1) * max(dot(N, L), 0); return OUT;
} //--------------------------------------------------------------------------------------
// Pixel shader
//--------------------------------------------------------------------------------------
float4 MyPixelEntry(float4 diffuseLighting : COLOR, float4 texCoordProj : TEXCOORD0) : COLOR
{
float2 uv = texCoordProj.xy / texCoordProj.w;
//如果纹理坐标超出了(0,1)范围以及投影椎体的后面都不要映射
if( uv.x < 0.0f || uv.x > 1.0f || uv.y < 0.0f || uv.y > 1.0f || texCoordProj.w < 0 )
{
return diffuseLighting;
}
uv.x = 1 - uv.x;//由于建立灯光的view矩阵时采用的是左手坐标系,所以转成纹理坐标需要左右相反
float4 textureColor = tex2D(g_sam, uv); return textureColor * textureColor.w + (1.0 - textureColor.w) * diffuseLighting;
} //--------------------------------------------------------------------------------------
// Renders scene to render target
//--------------------------------------------------------------------------------------
technique MyTechnique
{
pass P0
{
VertexShader = compile vs_2_0 MyVertexEntry();
PixelShader = compile ps_2_0 MyPixelEntry();
}
}
3DShader之投影贴图(Projective Texturing)的更多相关文章
- 投影纹理映射(Projective Texture Mapping)
摘抄“GPU Programming And Cg Language Primer 1rd Edition” 中文名“GPU编程与CG语言之阳春白雪下里巴人” 投影纹理映射( Projective ...
- OpenGL 4.0 GLSL 实现 投影纹理映射(Projective Texture Mapping) (转)
http://blog.csdn.net/zhuyingqingfen/article/details/19331721 分类: GLSL 投影纹理映射 (projective texture ...
- 投影纹理映射(Projective Texture Mapping) 【转】
摘抄“GPU Programming And Cg Language Primer 1rd Edition” 中文名“GPU编程与CG语言之阳春白雪下里巴人” 投影纹理映射( Projective ...
- 3DShader之移位贴图(Displacement Mapping)
我们知道法线贴图是只是改了物体的法线属性,用来计算光照,但是并没有改变物体本身的网格.但是移位贴图就不一样了,它会移动物体的顶点.我用移位贴图做了个海洋,好了,上了图再讲: 注意看海的边缘的顶点,已经 ...
- 3DShader之法线贴图(normal mapping)
凹凸贴图(bump mapping)实现的技术有几种,normal mapping属于其中的一种,这里实现在物体的坐标系空间中实现的,国际惯例,上图先: 好了讲下原理 可以根据高度图生成法线量图,生成 ...
- 根据花瓶的侧面投影图,用Matlab绘制花瓶的三维立体图
现有一花瓶侧面投影如图 问题: 1) 做出该花瓶三维立体图: 2) 计算其表面积: 计算其体积. 第一次参加数学建模,从来没有接触过Matlab语言,一上来就碰到这种数字图像处理的问题就 ...
- uv纹理坐标设定与贴图规则
1.什么是UV? 对于三维模型,有两个最重要的坐标系统,一是顶点的位置(X,Y,Z)坐标,另一个就是UV坐标.什么是UV?简单的说,就是贴图影射到模型表面的依据. 完整的说,其实应该是UVW(因为 ...
- 【ZZ】 DShader之位移贴图(Displacement Mapping)
http://www.myexception.cn/other/1397638.html DShader之位移贴图(Displacement Mapping) www.MyException.Cn ...
- [比较老的文章]三维渲染引擎 OGRE 与 OSG 的比较综述
1 .引言随着计算机可视化.虚拟现实技术的飞速发展,人们对实时真实感渲染以及场景复杂度提出了更高的要求.传统的直接使用底层图形接口如OpenGL.DirectX开发图形应用的模式越来越暴露出开发复杂性 ...
随机推荐
- Codecs是以plugin的形式被调用的(显示中文的codec plugin文件是qcncodecs4.dll),可静态载入和动态载入
作为非英语国家人员开发的类库,QT有充分的理由优先考虑支持Unicode和各国自定义字库编码.大家也知道了QT对软件Internationalization有一套完整的开发模型,包括专门为此写的lin ...
- C++标准程序库的输入输出流(I/O Stream)复制文件(4种方法)
使用C++标准程序库的输入输出流(I/O Stream)复制文件,存在许多的方法, 方法一:逐个字符复制#include < fstream > std::ifstream ...
- (C#)Windows Shell 编程系列3 - 上下文菜单(iContextMenu)(一)右键菜单
原文 (C#)Windows Shell 编程系列3 - 上下文菜单(iContextMenu)(一)右键菜单 接上一节:(C#)Windows Shell 编程系列2 - 解释,从“桌面”开始展开这 ...
- ThinkPHP 3.1.2 查询方式的一般使用2
//select id1> and id2< 默认是and $data['id']=array(array('gt',$id1),array('lt',$id2)); // $data[' ...
- 九款让WordPress成为赚钱利器的广告插件
Blog有了很不错的流量后,看到别人博客挂的广告挣$,是否也有挂广告的冲动,但是,修改wordpress模版去让人不厌其烦,布局.样式都的重新修改一下,为了不那么麻烦,笔者整理的几款wordpress ...
- vs2013搭建团队版本控制 TFS、SVN
项目使用vs2013开发,之前使用过svn进行版本控制,由于长时间未使用,记录备用. 一.TFS Team Foundation Server(TFS) 是微软提供的一个团队协同办公的管理工具,项目总 ...
- Foundation Sorting: Single List Insertion Sort
/* List Insertion Sorting. * Implementation history:. * 2013-09-15, Mars Fu, first version. */ #incl ...
- Js动态设置Img大小
function ResizePic() { $('img').each(function () { var maxWidth = 450; // 图片最大宽度 ...
- WPF自学笔记
WPF使用哪几种元素作为顶级元素: 1. Window元素 2. Page元素(与Window元素类似,用于可导航的应用程序) 3. Application元素(定义应用程序资源和启动设置) PS:在 ...
- jquery选择器控制Html元素
1.JQuery中有addClass,removeClass,toggleClass addClass(class):为每个匹配的元素添加指定的类名 removeClass(class):从所有匹配的 ...