在基于shader的D3D程序中实现2D面板
2009-04-23 18:49
211 查看
3D游戏中,很多东西都需要以2D的形式展现,比如人物的状态栏,物品栏等,那么如何才能在3D场景中放置它们呢?我在这里介绍一种通过简化变换过程而实现的方法.
大家知道,一个模型顶点在显示到屏幕上,一共要经过4次变换,分别是世界变换,摄象机变换,投影变换以及视口变换.在世界变换中,我们通过一个仿射矩阵把这个顶点放置到世界的相应位置;在摄象机变换中,我们以摄象机作为原点把顶点放置到相应位置;而在投影变换中,若我们选择z = 1作为投影面,我们相当于把z = z的平面上的点映射到了z = 1上,比如点( x, y, z, z )就投影为( x / z, y / z, 1 );最后,我们又利用视口变换,把这个点映射到屏幕象素坐标上,如( 0, 0 )映射为(
screenX / 2, screenY / 2 ).
我说了这么多,无非就是想告诉大家,我们在把顶点传递后,会经过前三次变换映射到( -1, -1, 0 )以及( 1, 1, 1 )的立方体内( 视口变换暂时不去考虑 ),也就是说D3D的近截面从0开始.
一张前景图,必然是遮挡所有3D实体与环境的东东,那么我们就可以知道在三次变换后的顶点的坐标设为( x, y , 0 ),注意-1<x,y<1,那么,如果我们不去执行三次变换,将模型坐标设为这样直接传给光栅器,就可以得到一个伪装的完成3次变换的顶点映射后的象素了.
例如:我定义:
//前景图的四个顶点以及相应索引
VERTEX v1( D3DXVECTOR3( 0, 0, 0 ), D3DXVECTOR2( 0 ,1 ) );
VERTEX v2( D3DXVECTOR3( 0, 0.6, 0 ), D3DXVECTOR2( 0 ,0 ) );
VERTEX v3( D3DXVECTOR3( 0.4, 0, 0 ), D3DXVECTOR2( 1 ,1 ) );
VERTEX v4( D3DXVECTOR3( 0.4, 0.6, 0 ), D3DXVECTOR2( 1 ,0 ) );
那么如果不进行前三次变换,这个矩形的就会直接被映射到屏幕上变成一个正方形,为什么是正方形呢?这是因为如果在800*600的分辨率下,必须设置水平与垂直缩放值,他们的比值为4 : 3.
本方法经测试有效,似乎在D3D中还有一种方法是通过把顶点位置声明设置为已变换,但是我想既然其他3D实体的顶点都需要进行变换的洗礼,那我还是如乡随俗吧...
在shader中,可以直接如下:
void VS(float3 Pos : POSITION, float4 Color : COLOR, float3 normal : NORMAL, float2 texCoord : TEXCOORD0,
out float4 oPosition : POSITION, out float4 oColor : COLOR, out float2 oTexCoord : TEXCOORD0,
out float oFogExponent : TEXCOORD1 )
{
oPosition =float4( Pos, 1 ); //直接使用,不需要变换
//oPosition = mul( float4( Pos, 1 ), matWorldViewProj );
float4 P = mul( float4( Pos, 1 ), matWorld );
float3 No = normalize( mul( normal, matWorld ) );
ComputeFogExponent( P.xyz, eyePos.xyz, oFogExponent );
oColor = float4( 1, 0, 0, 1 );
oTexCoord = texCoord;
}
大家知道,一个模型顶点在显示到屏幕上,一共要经过4次变换,分别是世界变换,摄象机变换,投影变换以及视口变换.在世界变换中,我们通过一个仿射矩阵把这个顶点放置到世界的相应位置;在摄象机变换中,我们以摄象机作为原点把顶点放置到相应位置;而在投影变换中,若我们选择z = 1作为投影面,我们相当于把z = z的平面上的点映射到了z = 1上,比如点( x, y, z, z )就投影为( x / z, y / z, 1 );最后,我们又利用视口变换,把这个点映射到屏幕象素坐标上,如( 0, 0 )映射为(
screenX / 2, screenY / 2 ).
我说了这么多,无非就是想告诉大家,我们在把顶点传递后,会经过前三次变换映射到( -1, -1, 0 )以及( 1, 1, 1 )的立方体内( 视口变换暂时不去考虑 ),也就是说D3D的近截面从0开始.
一张前景图,必然是遮挡所有3D实体与环境的东东,那么我们就可以知道在三次变换后的顶点的坐标设为( x, y , 0 ),注意-1<x,y<1,那么,如果我们不去执行三次变换,将模型坐标设为这样直接传给光栅器,就可以得到一个伪装的完成3次变换的顶点映射后的象素了.
例如:我定义:
//前景图的四个顶点以及相应索引
VERTEX v1( D3DXVECTOR3( 0, 0, 0 ), D3DXVECTOR2( 0 ,1 ) );
VERTEX v2( D3DXVECTOR3( 0, 0.6, 0 ), D3DXVECTOR2( 0 ,0 ) );
VERTEX v3( D3DXVECTOR3( 0.4, 0, 0 ), D3DXVECTOR2( 1 ,1 ) );
VERTEX v4( D3DXVECTOR3( 0.4, 0.6, 0 ), D3DXVECTOR2( 1 ,0 ) );
那么如果不进行前三次变换,这个矩形的就会直接被映射到屏幕上变成一个正方形,为什么是正方形呢?这是因为如果在800*600的分辨率下,必须设置水平与垂直缩放值,他们的比值为4 : 3.
本方法经测试有效,似乎在D3D中还有一种方法是通过把顶点位置声明设置为已变换,但是我想既然其他3D实体的顶点都需要进行变换的洗礼,那我还是如乡随俗吧...
在shader中,可以直接如下:
void VS(float3 Pos : POSITION, float4 Color : COLOR, float3 normal : NORMAL, float2 texCoord : TEXCOORD0,
out float4 oPosition : POSITION, out float4 oColor : COLOR, out float2 oTexCoord : TEXCOORD0,
out float oFogExponent : TEXCOORD1 )
{
oPosition =float4( Pos, 1 ); //直接使用,不需要变换
//oPosition = mul( float4( Pos, 1 ), matWorldViewProj );
float4 P = mul( float4( Pos, 1 ), matWorld );
float3 No = normalize( mul( normal, matWorld ) );
ComputeFogExponent( P.xyz, eyePos.xyz, oFogExponent );
oColor = float4( 1, 0, 0, 1 );
oTexCoord = texCoord;
}
相关文章推荐
- 在基于shader的D3D程序中实现2D面板
- 内存管理器(八)基于Glibc malloc 实现内存管理程序
- 基于angular实现模拟微信小程序swiper组件
- 分享一个用Xcode4实现基于Webservice用户登录的iphone程序
- python中的 \r以及基于此实现简单的倒计时小程序
- Shader特效——实现“Environment Mapping模拟反射和折射”【基于RenderMonkey】
- Java网络编程 - 基于UDP协议 实现简单的聊天室程序
- 基于Visual C++之Windows核心编程代码分析(3)实现程序自动安装
- python实现基于UDP的视频直播程序
- 基于D3D技术实现的九宫格算法绘制图片
- 创建一个基于套接字的bufferevent实例-echo程序的实现
- MFC基于对话框程序启动时隐藏窗口的实现
- 基于GCCAVR的TLC2543读写程序----模拟SPI方式实现
- 基于libpcap实现抓包程序
- 基于嵌入式linux的usb摄像头的驱动及采集程序的实现
- 基于gin框架和jwt-go中间件实现小程序用户登陆和token验证
- 基于Cy68013的USB设备在VC程序中热插拔的实现
- 基于C语言实现的Ping程序
- 基于netty框架实现的TCP服务端程序
- 神经网络与深度学习 1.6 使用Python实现基于梯度下降算法的神经网络和MNIST数据集的手写数字分类程序