微软的vista 带了个大家伙 这个可能会导致硬件升级,开发人员为之疯狂的的大家伙。
Direct3D 10 要来了 这不仅仅是两位数的飞跃,D3D10图形流水线给出了绘制架构的根本性变化,为了增强了下一代游戏和3D多媒体程序的绘制能力,它的软件和硬件都由底层重新构建。
蜕变
它基于Windows Vista显示驱动模型(WDDM)构建,增强了功能和性能,保证了GPU显存的完全虚拟化(应该指从编程角度可以无视内存和显存差别)。相比Direct3D 9 有几个主要变化:
1 利用 Geometry-Shader 更灵活处理(带邻接点)的原始数据 以后慢慢讲 这是重点
2 利用Stream-Output Stage 把管线产生的vertex 数据传入内存 重点2:)
3 固定管线成为历史,取而代之的是完全的HLSL可编程管线,完全的HLSL集成。所有 D3D10 Shader使用HLSL编写,使用通用Shader核心实现。
4 提供新的对象和输入模板来减小运行时使驱动生效处理数据的CPU消耗。
5 把Shader常数变量组织到常数缓存中,减少了给Shader提供常数的带宽。
6 使用GS能够执行逐图元的材质变换和构建。
7 新的资源类型(包括Shader可读取的带索引的纹理数组)和资源格式。
8 增加内存资源的通用性,资源使用统一格式(资源视图)来读取在内存中不同类型和格式的资源。
9 一系列完整的功能需求:legacy hardware capability bits (caps)被移除并引入了更为丰富的性能验证功能;为了使以上设计生效,D3D10 API只对将来D3D10类的硬件生效。
10 层次运行。D3D10 API由几个层次构成,从核心层次使用D3D10最基本的功能,在其他层次构建可选择的和辅助开发的功能(比如调试D3D10等)。
11 增加了绘制对象(窗口),纹理和纹理采样的数量,Shader没有指令数限制。
12 完全支持Shader整数和位操作;在Shader中读回Depth和Stencil值和多采样资源;多采样 Alpha覆盖。
图形管线
通用Shader核心(椭圆框部分)使用HLSL编程实现。这样你会发现绘制流水线非常灵活机动。每个阶段的设计目标在下面列出。
Input Assembler Stage 输入集成阶段 - 输入集成阶段负责为绘制流水线提供数据(三角形,线,点等)。
Vertex Shader Stage VS阶段 -VS阶段处理顶点,做坐标变换,表面细节和逐顶点光照计算。VS输入为一个顶点,输出也是一个顶点。
Geometry Shader Stage GS阶段-GS处理完整的图元。它的输入是图元(包括三角形三个顶点,或者直线的两个顶点,或者点绘制的一个顶点)。同时,每个图元还可以包含它邻接边的顶点信息。对于三角形可以附加三个顶点,而对于直线,可以附加两个顶点。GS同样提供简单的几何膨胀和收缩操作。给定一个输入图元,GS能够取消绘制这个图元,或者产生更多的新图元。
Stream Output Stage - 流输出阶段:流输出阶段为了让图元数据在光栅化过程中可以从流水线输出到显存中而设计。数据能被输出或者输入光栅化。输出到显存的流数据可以作为流水线输入数据循环使用,或者读回到CPU。
Rasterizer Stage - 光栅化阶段-光栅化对裁减后的图元起作用,它把图元输出到PS,并确定使用什么PS绘制。
Pixel Shader Stage -PS阶段:PS阶段接受图元光栅化时的插值数据并生成逐像素的数据(比如颜色)。
Output Merger Stage - 输出合并阶段-输出合并阶段把不同的数据数据(PS颜色,深度和模板缓存信息)和绘制对象及Depth/Stencil缓存中的数据合并,并输出最终结果。
热身从哪开始呢?(光说不练可不行)那我们从第一个程序 初始化窗口开始入手~分三节讲
我们先看头文件引用
#include
#include
#include
#include "resource.h"
看出来什么了吗?呵呵:0 两个问题
1 vista的基本机制还是当年win95的原理,2,d3d10.h与d3dx10.h 有什么不同呢?
go on~ 再看全局变量
HINSTANCE g_hInst = NULL;
HWND g_hWnd = NULL;
D3D10_DRIVER_TYPE g_driverType = D3D10_DRIVER_TYPE_NULL;
ID3D10Device* g_pd3dDevice = NULL;
IDXGISwapChain* g_pSwapChain = NULL;
ID3D10RenderTargetView* g_pRenderTargetView = NULL;
句柄(面熟啊~)
D3D10_DRIVER_TYPE 这个D3D9 没有呀 不急脱了衣服就知道多面熟了-。-
typedef ID3D10Device Interface 接口 :)
typedef enum D3D10_DRIVER_TYPE
{D3D10_DRIVER_TYPE_HARDWARE = 0,通过直接接口访问硬件
D3D10_DRIVER_TYPE_REFERENCE = 1,通过直接接口访问创建的软件仿真设备
D3D10_DRIVER_TYPE_NULL = 2, 使用参考设备,但不能用于渲染
D3D10_DRIVER_TYPE_SOFTWARE = 3,留着以后用
} D3D10_DRIVER_TYPE;
还记得CreateDevice( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd,
D3DCREATE_SOFTWARE_VERTEXPROCESSING,&d3dpp, &g_pd3dDevice ) ) )
熟悉D3D9的朋友想起了吧~
下面看这两个带I开头的接口,更符合COM规范的命名方式,赞~
ID3D10Device* 用来画基于原始数据的渲染,创建资源,与系统变量协同工作,创建shader
ID3D10RenderTargetView*
ID3D10RenderTargetView : public ID3D10View
{
public:
virtual void STDMETHODCALLTYPE GetDesc(
__out D3D10_RENDER_TARGET_VIEW_DESC *pDesc) = 0;
};
ID3D10View 是所有view 对象的父接口 本质上用来指定管线渲染中将会用到一部分资源。
__out 是COM的参数进出约定,COM要讲明白就太难了,沉思状(K~“你自己也不明白” 打~~)
#define STDMETHODCALLTYPE __stdcall
给自己充一下电,补充点新知识
__cdecl是C/C++和MFC程序默认使用的调用约定,也可以在函数声明时加上__cdecl关键字来手工指定。采用__cdecl约定时,函数参数按照从右到左的顺序入栈,并且由函数调用者把参数弹出栈以清理堆栈。因此,实现可变参数的函数只能使用该调用约定。由于每一个使用__cdecl约定的函数都要包含清理堆栈的代码,所以产生的可执行文件大小会比较大。__cdecl可以写成_cdecl。
__stdcall调用约定用于调用Win32 API函数。采用__stdcal约定时,函数参数按照从右到左的顺序入栈,被调用的函数在返回前清理传送参数的栈,函数参数个数固定。由于函数体本身知道传进来的参数个数,因此被调用的函数可以在返回前用一条ret n指令直接清理传递参数的堆栈。__stdcall可以写成_stdcall。
__fastcall约定用于对性能要求非常高的场合。__fastcall约定将函数的从左边开始的两个大小不大于4个字节(DWORD)的参数分别放在ECX和EDX寄存器,其余的参数仍旧自右向左压栈传送,被调用的函数在返回前清理传送参数的堆栈。__fastcall可以写成_fastcall。
本次的重点来了 DXGI~~~~ (DirectX Graphics Infrastructure )
DXGI 是为以后 DX11等后续版本公共基础,它封装了一些基本底层的常量和操作,这样可以使以后不同API能够共享一部分资源。
还记得以前D3D9时
if( NULL == ( g_pD3D = Direct3DCreate9( D3D_SDK_VERSION ) ) )吗?
以后像硬件列举,控制gamma,全屏转化等下贱工作就交给他来做了:)
当然他还要负责与核心驱动模式和系统硬件打交道(真人不露像呀)
当然我们还是可以操作DXGI的,just like before~~ (微软呀~那你干嘛变得这么快嘛~)
具体DXGI的操作 我们在实做中慢慢描述。比如下面这个例子,你还是会发现图形学基本原理万古长青
IDXGISwapChain* 实现用一个和多个surface在输出之前储存渲染数据
书接上回~ 我们首先看一下如何使用D3D设备,主要分为3步
1.初始化D3D设备(初始化方法很多,这里要对一些重要的D3D参数指定)
2.渲染(可以在各种设备,各种视口,使用各种设备,选用各种方法来渲染)
3.清除设备(这里的设备必须和初始化的设备对应)
1.初始化D3D设备
(1)渲染一个物体,首先要创建两个object,device 和 SwapChain
隆重登场的是一个非常重要的函数,也是本节第一个重点
使用这个函数前我们要对它使用的各个设备接口,enum,struct进行初始化
首先要初始化上回说的D3D10_DRIVER_TYPE,接着我们要初始化一个非常重要的struct
DXGI_SWAP_CHAIN_DESC,其实它就是当年D3DDISPLAYMODE。
typedef struct DXGI_SWAP_CHAIN_DESC { DXGI_MODE_DESC BufferDesc; DXGI_SAMPLE_DESC SampleDesc; DXGI_USAGE BufferUsage; UINT BufferCount; HWND OutputWindow; BOOL Windowed; DXGI_SWAP_EFFECT SwapEffect; UINT Flags;} DXGI_SWAP_CHAIN_DESC, *LPDXGI_SWAP_CHAIN_DESC;
第一个参数 DXGI_MODE_DESC BufferDesc 后置缓冲的显示模式
typedef struct DXGI_MODE_DESC { UINT Width; 屏幕宽度 UINT Height; 屏幕高度 DXGI_RATIONAL RefreshRate; 刷新率 numerator/denominotor DXGI_FORMAT Format; 显示格式96种 DXGI_MODE_SCANLINE_ORDER ScanlineOrdering; 0隔行;1逐行;2/3 隔行上行/下行 DXGI_MODE_SCALING Scaling; 指定图像适应屏幕变化的方式 如下:} DXGI_MODE_DESC, *LPDXGI_MODE_DESC;
typedef enum DXGI_MODE_SCALING{ DXGI_MODE_SCALING_UNSPECIFIED = 0,未指定方式 DXGI_MODE_SCALING_CENTERED = 1, 图像一直在屏幕中间 DXGI_MODE_SCALING_STRETCHED = 2,图像跟随窗口缩放而变化} DXGI_MODE_SCALING, *LPDXGI_MODE_SCALING;
第二个参数 DXGI_SAMPLE_DESC SampleDesc 指定resource的多采样参数
typedef struct DXGI_SAMPLE_DESC { UINT Count; 每像素多采样的数量 UINT Quality; 图像质量等级} DXGI_SAMPLE_DESC, *LPDXGI_SAMPLE_DESC;
第三个参数 DXGI_USAGE BufferUsage 指定Surface的用法和CPU存取方式
DXGI_USAGE_SHADER_INPUT | Use the surface or resource as a input to a shader. | ( 1L << (0 + 4) ) |
DXGI_USAGE_RENDER_TARGET_OUTPUT | Use the surface or resource as an output render target. | ( 1L << (1 + 4) ) |
DXGI_USAGE_BACK_BUFFER | Use the surface or resource as back buffer. | ( 1L << (2 + 4) ) |
DXGI_USAGE_SHARED | Share the surface or resource. | ( 1L << (3 + 4) ) |
DXGI_USAGE_READ_ONLY | Use the surface or resource for reading only. | ( 1L << (4 + 4) ) |
可以使用IDXGIDevice::CreateSurface来修改这个flag
第四个参数 UINT BufferCount 后置缓冲的数量
第五个参数 HWND OutputWindow 指定输出窗口的句柄 0代表主父窗口
第六个参数 BOOL Windowed TRUE/FALSE 窗口模式/全屏幕
第七个参数 DXGI_SWAP_EFFECT SwapEffect 指定SwapChain 的工作方式
typedef enum DXGI_SWAP_EFFECT{ DXGI_SWAP_EFFECT_DISCARD = 0, 不考虑后置缓冲内容全部刷新显示 DXGI_SWAP_EFFECT_SEQUENTIAL = 1,当包含多个后置缓冲时,可以指定那些缓存在使用IDXGISwapChain::Present后不更新} DXGI_SWAP_EFFECT, *LPDXGI_SWAP_EFFECT;
SwapChain是现代API采取的一个经典机制,是光栅图形学基本原理的体现。简单来说就是用前后置两个或多个缓存来显示
前置缓存是我们直接看到的但它是只读的,后置缓存是device可以改变的rendertarget,利用present交替显示就是我们看到的画面了
IDXGISwapChain::Present 是IDXGISwapChain接口中比较重要的函数
HRESULT Present( UINT SyncInterval,指定所要表达的空白同步IDXGIOutput对象的间隔粒度,多个时它和最大窗口参数一致 UINT Flags0 or DXGI_PRESENT_TEST用来测试SwapChain状态和相关连错误);
第八个参数 UINT Flags
typedef enum DXGI_SWAP_CHAIN_FLAG{ DXGI_SWAP_CHAIN_FLAG_NONPREROTATED = 1,//关闭自动图像旋转,只能在全屏模式 DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH = 2,//全屏时自动改变显示模式适用窗口尺寸} DXGI_SWAP_CHAIN_FLAG, *LPDXGI_SWAP_CHAIN_FLAG;
(2)创建一个render target view
1.创建一个后置缓存
比如我们用 ID3D10Texture2D *pBackBuffer; 2D texture resource的接口的后置缓存
g_pSwapChain->GetBuffer( 0, __uuidof( ID3D10Texture2D ), (LPVOID*)&pBackBuffer );
HRESULT GetBuffer(
UINT Buffer, [in]buffer 编号
REFIID riid, [in]buffer类型(COM机制的体现)
void ** ppSurface [in out]SwapChain后置缓存的地址
);
Method | Description |
---|---|
IDXGISwapChain::GetBuffer | 取得后置缓存 |
IDXGISwapChain::GetContainingOutput | 取得输出量. |
IDXGISwapChain::GetDesc | 取得swapchain的描述. |
IDXGISwapChain::GetFrameStatistics | 取得渲染状态 |
IDXGISwapChain::GetFullscreenState | 取得输出量(only for full-screen mode). |
IDXGISwapChain::GetLastPresentCount | 得到上一帧调用Present的数量 |
IDXGISwapChain::Present | Presents the frame buffer to the output.(详细见上) |
IDXGISwapChain::ResizeBuffers | 改变后置缓存大小和格式 |
IDXGISwapChain::ResizeTarget | 改变输出量属性 |
IDXGISwapChain::SetFullscreenState |
改变输出量的窗口和全屏模式 (输出量IDXGIOutput 接口) |
2.使用ID3D10Device接口创建render target
hr = g_pd3dDevice->CreateRenderTargetView( pBackBuffer,NULL,&g_pRenderTargetView );
pBackBuffer->Release();
HRESULT CreateRenderTargetView(
ID3D10Resource * pResource,
const D3D10_RENDER_TARGET_VIEW_DESC * pDesc,
ID3D10RenderTargetView ** ppRTView ID3D10RenderTargetView接口地址
);
坐下来来详细讲讲ID3D10Resource 接口 Direct3D10的资源接口 这是本节第二个重点
3.指定render target
g_pd3dDevice->OMSetRenderTargets( 1, &g_pRenderTargetView, NULL );
这里我们可以看到一个D3D10重要的命名方式OM开头代表Output-Merge阶段这样能够清晰的看到D3D个函数在流水线的工作位置。
(3)创建一个viewport(视口)
Direct3D9视口是默认与主窗口一致,Direct3D10必须要手工指定
typedef struct D3D10_VIEWPORT {
INT TopLeftX; 右上角x坐标
INT TopLeftY; 右上角y坐标
UINT Width; 宽度
UINT Height; 高度
FLOAT MinDepth;最小深度
FLOAT MaxDepth;最大深度
} D3D10_VIEWPORT;
g_pd3dDevice->RSSetViewports( 1, &vp );
void RSGetViewports(
UINT * NumViewports, //取得矩形视口数目
D3D10_VIEWPORT * pViewports //视口结构体指针
);
2.渲染
我们把画面涂成黑色
float ClearColor[4] = { 0.0f, 0.0f, 0.0f, 1.0f };
g_pd3dDevice->ClearRenderTargetView( g_pRenderTargetView, ClearColor );
g_pSwapChain->Present( 0, 0 );
3.清除设备
以后创造的各种设备和借口都要从这释放掉
if( g_pd3dDevice ) g_pd3dDevice->ClearState();
if( g_pRenderTargetView ) g_pRenderTargetView->Release();
if( g_pSwapChain ) g_pSwapChain->Release();
if( g_pd3dDevice ) g_pd3dDevice->Release();
先复习一下,D3D使用三步曲:
1.初始化D3D设备(初始化方法很多,这里要对一些重要的D3D参数指定)
2.渲染(可以在各种设备,各种视口,使用各种设备,选用各种方法来渲染)
3.清除设备(这里的设备必须和初始化的设备对应)
在渲染中我们要画一个正方形,常规思路,给出四个点的坐标,连成面,画出来,涂上颜色.
Input Assembler stage 是整个渲染流水线的开始也是绘制基本图形的开始.先看第一步:
(1)Create the buffer
buffer 分两种,vertex buffer,index buffer后者是可选的,后面我们画正方体可以用到.
<1>初始化primitive
定义一个点的结构.
struct SimpleVertex{ D3DXVECTOR3 Pos; };
SimpleVertex vertices[] =
{D3DXVECTOR3( -0.5f, -0.5f, 0.5f ), D3DXVECTOR3( -0.5f, 0.5f, 0.5f ),
D3DXVECTOR3( 0.5f, -0.5f, 0.5f ), D3DXVECTOR3( 0.5f, 0.5f, 0.5f ),};
<2>定义buffer
这里要先介绍两个重要的结构体D3D10_BUFFER_DESC和D3D10_SUBRESOURCE_DATA
typedef struct D3D10_BUFFER_DESC {
UINT ByteWidth; //buffer的大小
D3D10_USAGE Usage; //指定CPU或GPU读取资源的方式
UINT BindFlags; //指定buffer的绑定方式
UINT CPUAccessFlags; //指定CPU访问权限
UINT MiscFlags; //指定其他buffer选项,比如是否共享
} D3D10_BUFFER_DESC;
typedef struct D3D10_SUBRESOURCE_DATA {
const void *pSysMem;
UINT SysMemPitch;
UINT SysMemSlicePitch;
} D3D10_SUBRESOURCE_DATA;
对要用到的结构体有一个清晰了解后,我们用如下代码完成这一步工作
D3D10_BUFFER_DESC bd;
bd.Usage = D3D10_USAGE_DEFAULT;
bd.ByteWidth = sizeof( SimpleVertex ) * 4;
bd.BindFlags = D3D10_BIND_VERTEX_BUFFER;
bd.CPUAccessFlags = 0;
bd.MiscFlags = 0;
D3D10_SUBRESOURCE_DATA InitData;
InitData.pSysMem = vertices;
<3> 创建buffer
g_pd3dDevice->CreateBuffer( &bd, &InitData, &g_pVertexBuffer );
<4> 设置buffer
UINT stride = sizeof( SimpleVertex );
UINT offset = 0;
g_pd3dDevice->IASetVertexBuffers( 0, 1, &g_pVertexBuffer, &stride, &offset );
g_pd3dDevice->IASetPrimitiveTopology(D3D10_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);//制定定点组织方式,我们选择STRIP~
下面我们会看到D3D10一个明显的变化,如何全面取代固定流水线。也是我们的第二步
(2) create Input layout
<1> 定义 input layout,又要介绍一个结构体
typedef struct D3D10_INPUT_ELEMENT_DESC { LPCSTR SemanticName; //shader输入部分关联的语义 UINT SemanticIndex; //语义编号 DXGI_FORMAT Format; //输入部分的格式 UINT InputSlot; //IA stage的位置 UINT AlignedByteOffset; //位置的偏移 D3D10_INPUT_CLASSIFICATION InputSlotClass;//输入的单顶点还是复合数据实例 UINT InstanceDataStepRate;//使用复合数据实例时的步进} D3D10_INPUT_ELEMENT_DESC;
这一部分要牵涉到HLSL语言,这里暂时不系统的讲,她和CG是姐妹语言,大家可以参照NV的官方教程
我们画四边形可以简单如下定义一个input layout
D3D10_INPUT_ELEMENT_DESC layout[] =
{
{ "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D10_INPUT_PER_VERTEX_DATA, 0 },
};
UINT numElements = sizeof(layout)/sizeof(layout[0]);
从这里可以看出,原来的语义变得非常灵活,虽然给开发提高的工作量,但几乎使得一切几何数据全部可控,更先进的算法,更优秀的思路,将带来更加完美的画面质量和图形效果,全新的时代开启了~
<2> 创建 input layout
g_pTechnique = g_pEffect->GetTechniqueByName( "Render" );
D3D10_PASS_DESC PassDesc;
g_pTechnique->GetPassByIndex( 0 )->GetDesc( &PassDesc );
g_pd3dDevice->CreateInputLayout( layout, numElements, PassDesc.pIAInputSignature, PassDesc.IAInputSignatureSize, &g_pVertexLayout );
<3>设置 input layout
g_pd3dDevice->IASetInputLayout( g_pVertexLayout );
(3) 渲染吧~
D3D10_TECHNIQUE_DESC techDesc;
g_pTechnique->GetDesc( &techDesc );
for( UINT p = 0; p < techDesc.Passes; ++p )
{
g_pTechnique->GetPassByIndex( p )->Apply(0);
g_pd3dDevice->Draw( 4, 0 );
}
先来个一片红,赶明儿贴个国旗:)并初步了解一下effect系统构架的基本思路。
Direct3D 10的effect 系统看似变得很繁琐,层次增多,细细分析起来结构更加清晰,使用更加灵活。书接上回,我们就以上回画的矩形上贴一张图为例,初步了解一下effect 系统。
fx文件一般分为四个部分,我们以一个最简单的贴图shader为例
//--------------------------------------------------------------------------------------
// 第一部分:Constant Buffer Variables
//--------------------------------------------------------------------------------------
Texture2D txDiffuse;
SamplerState samLinear
{
Filter = MIN_MAG_MIP_LINEAR;
AddressU = Wrap;
AddressV = Wrap;
};
cbuffer cbNeverChanges
{
matrix View;
};
cbuffer cbChangeOnResize
{
matrix Projection;
};
cbuffer cbChangesEveryFrame
{
matrix World;
float4 vMeshColor;
};
//--------------------------------------------------------------------------------------
// 第二部分: 函数申明 包括PS VS GS的input 和output 结构 包括要用到的函数
//--------------------------------------------------------------------------------------
struct VS_INPUT
{
float4 Pos : POSITION;
float2 Tex : TEXCOORD;
};
struct PS_INPUT
{
float4 Pos : SV_POSITION;
float2 Tex : TEXCOORD0;
};
//--------------------------------------------------------------------------------------
// 第三部分 Vertex Shader Pixel Shader Geometry shader
//--------------------------------------------------------------------------------------
PS_INPUT VS( VS_INPUT input )
{
PS_INPUT output = (PS_INPUT)0;
output.Pos = mul( input.Pos, World );
output.Pos = mul( output.Pos, View );
output.Pos = mul( output.Pos, Projection );
output.Tex = input.Tex;
return output;
}
float4 PS( PS_INPUT input) : SV_Target
{
return txDiffuse.Sample( samLinear, input.Tex );
}
//--------------------------------------------------------------------------------------
// 第四部分:technique系统申明
//--------------------------------------------------------------------------------------
technique10 Render
{
pass P0
{
SetVertexShader( CompileShader( vs_4_0, VS() ) );
SetGeometryShader( NULL );
SetPixelShader( CompileShader( ps_4_0, PS() ) );
}
}
Directx 系统通过effect接口和fx文件进行交换,fx的内容通过Directx API 与低层硬件进行交互.
<1> 创建effect(用来读取fx文件)
D3DX10CreateEffectFromFile( L"HLSL.fx", NULL, NULL, D3D10_SHADER_ENABLE_STRICTNESS, 0,
g_pd3dDevice, NULL, NULL, &g_pEffect, NULL );
<2> 从effect文件中获取Technique
g_pTechnique = g_pEffect->GetTechniqueByName( "Render" );
可以看出前部分与DX9没有什么区别。
<3> 获取effect文件中需要的变量(使fx的变量与DX中变量一一对应)
g_pWorldVariable = g_pEffect->GetVariableByName( "World" )->AsMatrix();
g_pViewVariable = g_pEffect->GetVariableByName( "View" )->AsMatrix();
g_pProjectionVariable = g_pEffect->GetVariableByName( "Projection" )->AsMatrix();
g_pDiffuseVariable = g_pEffect->GetVariableByName( "txDiffuse" )->AsShaderResource();
我们首先看看变量申明:
ID3D10Effect* g_pEffect = NULL;
ID3D10EffectTechnique* g_pTechnique = NULL;
ID3D10EffectMatrixVariable* g_pWorldVariable = NULL;
ID3D10EffectMatrixVariable* g_pViewVariable = NULL;
ID3D10EffectMatrixVariable* g_pProjectionVariable = NULL;
D3DXMATRIX g_World;
D3DXMATRIX g_View;
D3DXMATRIX g_Projection;
ID3D10ShaderResourceView* g_pTextureRV = NULL;
ID3D10EffectShaderResourceVariable* g_pDiffuseVariable = NULL;
<4>初始化变量
D3DXMatrixIdentity( &g_World );
D3DXVECTOR3 Eye( 0.0f, 0.0f, -6.0f );
D3DXVECTOR3 At( 0.0f, 0.0f, 0.0f );
D3DXVECTOR3 Up( 0.0f, 1.0f, 0.0f );
D3DXMatrixLookAtLH( &g_View, &Eye, &At, &Up );
D3DXMatrixPerspectiveFovLH( &g_Projection, (float)D3DX_PI * 0.25f, width/(FLOAT)height, 0.1f, 100.0f );
hr = D3DX10CreateShaderResourceViewFromFile( g_pd3dDevice, L"China.jpg", NULL, NULL, &g_pTextureRV );
if( FAILED(hr) )
<5>设置变量
g_pWorldVariable->SetMatrix( (float*)&g_World );
g_pViewVariable->SetMatrix( (float*)&g_View );
g_pProjectionVariable->SetMatrix( (float*)&g_Projection );
g_pDiffuseVariable->SetResource( g_pTextureRV );