D3D11教程三十之ProjectiveTexturing(投影纹理)
来源:互联网 发布:php获取qq信息 编辑:程序博客网 时间:2024/05/18 02:46
这节教程是介绍有关ProjectiveTexturing(投影纹理)技术的,结构如下
一,ProjectiveTexturing(投影纹理)的简介.
ProjectiveTexturing(投影纹理)是实现3D实时渲染的最重要的技术之一,很多高级效果,如SoftShadow(软弱阴影),Water,ProjecvtiveLightMap(投影光照图),Reflection等效果都需要用到投影纹理技术。投影纹理意思就是将一张2D纹理投影到3D物体上或者换一个说法就是用一个特别的相机(建立单独的相机变换矩阵和透视投影矩阵)来获取世界空间3D物体投射在某张2D纹理上的UV坐标值。纹理投影技术经常和RTT(渲染到纹理技术)一起搭配使用,可以看看教程:D3D11教程二十一之Water(水的实现)以及D3D11教程三十一之ShadowMap(阴影贴图)之聚光灯成影,还有 D3D11教程十九之PlannarReflection(基于RTT技术和投影纹理技术)都是投影纹理技术搭配RTT技术使用的典型例子,那两个教程中折射的物体和反射的物体的实现其实是投影纹理.
在来看看一个使用投影纹理的例子:
看上面这张有一个骷颅头的2D纹理贴图,利用这张2D纹理贴图我们可以生成下面的图形效果:
看这张图里面的骷髅头实际上仅仅是一张2D纹理贴图的效果,而不是真正地将一个3D骷颅头进行渲染的效果。
为了下面更好地讲述有关概念,我只好自创两个概念, ViewCamera(观察照相机)和ProjectorCamera(投影照相机或者投影幻灯机)
ViewCamera提供了我们在3D程序中的人眼观察的视角。
ProjectorCamera提供了投影机观察3D物体的角度,决定了世界空间(WorldSpace)中每个顶点对应于投影纹理坐标系(ProjectiveTextureCoordinate)相应的2D纹理坐标(U,V).
在世界空间中(WorldSpace),我们是如何得到每个顶点对应于投影纹理坐标系(ProjectiveTextureCoordinate)相应的2D纹理坐标(U,V)呢?
来看一张图:
看图中,这个视截体是ProjectorCamera(投影幻灯机)的视截体,点P是在世界空间的一个点(Xp,Yp,Zp,1.0),如何求出相应的(u,v)坐标呢?
要求投影纹理坐标系(ProjectiveTextureCoordinate)相应的2D纹理坐标(U,V),首先得熟悉D3D11的3D渲染流水线:
我在D3D11教程二十五之DepthBuffer(深度缓存)论述过3D渲染流水线,求纹理坐标系(ProjectiveTextureCoordinate)相应的2D纹理坐标(U,V)分为两步:
(1) 假设在世界空间上,点P坐标为(Xp,Yp,Zp,1.0),乘以ProjectorCamera(注意不是ViewCamera)生成的相机变换矩阵和透视投影矩阵,变换到齐次裁剪空间
在齐次裁剪空P点相应的坐标值为
ColorShader.fx
(Xp,Yp,Zp,Wp) -Wp=<Xp<=Wp -Wp=<Yp<=Wp 0=<Zp<=Wp,
(2)由于我们不标记“”SV_POSITION“”,显卡不会自动进行透视除法(当然显卡也不会自动进行裁剪算法),所以我们手动计算
-1<=Xp/Wp<=1 -1<=Yp/Wp<=1, 0=<{0.5*(Xp/Wp)+0.5}<=1, 0=<{-0.5*(Yp/Wp)+0.5}<=1 又由于投影纹理坐标系中 0=<U<=1 0=<V<=1,并且U坐标方向和X坐标方向相同,而V坐标方向和Y坐标相反,所以我们得出结果: U= 0.5*(Xp/Wp)+0.5; V=-0.5*(Yp/Wp)+0.5;
下面我们放出投影幻灯机的类:
ViewPointClass.h
#pragma once#ifndef _VIEW_POINT_CLASS_H#define _VIEW_POINT_CLASS_H#include<Windows.h>#include<xnamath.h>class ViewPointClass{private:XMFLOAT3 mPostion; //投影相机的位置XMFLOAT3 mLookAt; //投影相机看到的位置XMMATRIX mProjectorViewMatirx, mProjectorProjMatrix; //投影相机的相机变换矩阵和投影矩阵float mFieldOfView; //Fov视角大小float mAspectRatio; //屏幕宽高比float mNearPlane, mFarPlane; //视截体的近截面和远截面public:ViewPointClass();ViewPointClass(const ViewPointClass&);~ViewPointClass();public://Set函数void SetPostion(float,float,float);void SetLookAt(float,float,float);void SetProjectionParameters(float, float, float, float);//生成相机矩阵和投影矩阵void GenerateViewMatrix();void GenerateProjMatrix();//Get函数XMMATRIX GetViewMatrix();XMMATRIX GetProjMatrix();};#endif
ViewPointClass.CPP
#include"ViewPointClass.h"ViewPointClass::ViewPointClass(){}ViewPointClass::~ViewPointClass(){}ViewPointClass::ViewPointClass(const ViewPointClass&other){}void ViewPointClass::SetPostion(float x, float y, float z){mPostion = XMFLOAT3(x, y, z);}void ViewPointClass::SetLookAt(float x, float y, float z){mLookAt = XMFLOAT3(x, y, z);}void ViewPointClass::SetProjectionParameters(float FieldOfView, float AspectRatio, float NearPlane, float FarPlane){mFieldOfView = FieldOfView;mAspectRatio = AspectRatio;mNearPlane = NearPlane;mFarPlane = FarPlane;}void ViewPointClass::GenerateViewMatrix(){XMVECTOR EyePostion = XMLoadFloat3(&mPostion);XMVECTOR LookAt = XMLoadFloat3(&mLookAt);XMVECTOR Up = XMVectorSet(0.0f, 1.0f, 0.0f,0.0f);mProjectorViewMatirx = XMMatrixLookAtLH(EyePostion,LookAt,Up);}//近平面不变的条件下,远平面只影响远处看到物体的范围void ViewPointClass::GenerateProjMatrix(){mProjectorProjMatrix = XMMatrixPerspectiveFovLH(mFieldOfView,mAspectRatio,mNearPlane,mFarPlane);}XMMATRIX ViewPointClass::GetViewMatrix(){return mProjectorViewMatirx;}XMMATRIX ViewPointClass::GetProjMatrix(){return mProjectorProjMatrix; }
Texture2D BaseTexture:register(t0); //基础纹理Texture2D ProjectiveTexture:register(t1); //投影纹理SamplerState SampleType:register(s0); //采样方式//VertexShadercbuffer CBMatrix:register(b0){matrix World;matrix View;matrix Proj;matrix WorldInvTranspose;matrix ProjectorView;matrix ProjectorProj;};cbuffer CBLight:register(b1){float4 DiffuseColor;float3 LightDirection;float pad;}struct VertexIn{float3 Pos:POSITION;float2 Tex:TEXCOORD0; //多重纹理可以用其它数字float3 Normal:NORMAL;};struct VertexOut{float4 Pos:SV_POSITION;float4 ProjPos:POSITION; //投影坐标,投影在齐次裁剪空间float2 Tex:TEXCOORD0;float3 W_Normal:NORMAL; //世界空间的法线};VertexOut VS(VertexIn ina){VertexOut outa;//将坐标变换到观察相机下的齐次裁剪空间outa.Pos = mul(float4(ina.Pos,1.0f), World);outa.Pos = mul(outa.Pos, View);outa.Pos = mul(outa.Pos, Proj);//将顶点法向量由局部坐标变换到世界坐标outa.W_Normal = mul(ina.Normal, (float3x3)WorldInvTranspose); //此事世界逆转置矩阵的第四行本来就没啥用//对世界空间的顶点法向量进行规格化outa.W_Normal = normalize(outa.W_Normal);//获取纹理坐标outa.Tex= ina.Tex;//将坐标变换到投影相机下的齐次裁剪空间outa.ProjPos= mul(float4(ina.Pos, 1.0f), World);outa.ProjPos = mul(outa.ProjPos, ProjectorView);outa.ProjPos = mul(outa.ProjPos, ProjectorProj);return outa;}float4 PS(VertexOut outa) : SV_Target{float4 TexColor; //采集基础纹理颜色 float2 ProjTex; //投影纹理坐标float4 color = {0.0f,0.0f,0.0f,0.0f}; //最终输出的颜色//第一,获取采样颜色 TexColor = BaseTexture.Sample(SampleType, outa.Tex);//第二,获取投影相机下的投影纹理空间的坐标值[0.0,1.0] u=0.5*x+0.5; v=-0.5*y+0.5; -w<=x<=w -w<=y<=w ProjTex.x =(outa.ProjPos.x/outa.ProjPos.w)*0.5f + 0.5f;ProjTex.y= (outa.ProjPos.y/outa.ProjPos.w)*(-0.5f) + 0.5f;//第三,由于3D模型可能超出投影相机下的视截体,其投影纹理可能不在[0.0,1.0],所以得进行判定这个3D物体投影的部分是否在视截体内 (没SV_POSITION签名 显卡不会进行裁剪)if (saturate(ProjTex.x) == ProjTex.x&&saturate(ProjTex.y) == ProjTex.y){TexColor= ProjectiveTexture.Sample(SampleType, ProjTex);}color = TexColor;return color;}
下面是我将用到的投射到3D物体上的2D纹理:
这是没用投射纹理技术的
这是我们用了投影纹理技术的:观察相机位置A(0.0f, 6.0f, -12.0f) 投影相机(投影机)的位置B(2.0f, 5.0f, -2.0f),好吧,
在下图我做出辅助线来,观察相机A点的视截体我就不作辅助线了,作投影相机B的辅助线,红色的点为投影相机的视截体和平面的交点,画画水平有点糟糕,请见谅:
最后注意的是,在Shader可以看到我们的判定:由于我们 float4 ProjPos:POSITION 没标记“”POSTION“” 而不是“”SV_POSITION“”,显卡不会进行视截体内外面部分的裁剪,所以求得的UV坐标值可能超过[0,1]范围,所以有下面的判定
//第三,由于3D模型可能超出投影相机下的视截体,其投影纹理可能不在[0.0,1.0],所以得进行判定这个3D物体投影的部分是否在视截体内 (没SV_POSITION签名 显卡不会进行裁剪)if (saturate(ProjTex.x) == ProjTex.x&&saturate(ProjTex.y) == ProjTex.y){TexColor= ProjectiveTexture.Sample(SampleType, ProjTex);}
下面给我的源代码:
http://download.csdn.net/detail/qq_29523119/9670555
0 0
- D3D11教程三十之ProjectiveTexturing(投影纹理)
- D3D11教程十九之PlannarReflection(基于RTT技术和投影纹理技术)
- D3D11教程三十四之ProjectiveLightMap(投影光照图)
- D3D11教程十七之TextureTranslation(纹理动画技术)
- D3D11地形渲染教程十四之TerrainDetailMap(地形的细节纹理)
- D3D11教程九之多重纹理和纹理数组
- D3D11基础教程四之Texture(纹理)
- D3D11教程六之AmbientLight
- D3D11教程三十二之MultipleLightShadowMapping
- D3D11修改纹理数据
- D3D11的纹理
- 投影纹理
- D3D11教程五之DiffuseLight(漫射光)
- D3D11教程七之2D渲染
- D3D11教程八之FontEngine(字体实现)
- D3D11教程十之LighhtMap(光照贴图)
- D3D11教程十一之AlphaMap(混合贴图)
- D3D11教程十二之NormalMap(法线贴图)
- mysql ---创建简单的数据库
- Android监听网络变化
- CSS3 中的取值和单位
- Android7.0 多窗口特性
- Fragment间通信
- D3D11教程三十之ProjectiveTexturing(投影纹理)
- Python中的 __all__和__path__ 解析
- HDU 4135:Co-prime (容斥原理)
- 怎么参与到百度的开源项目中来
- PHP中关于composer那点事
- 静态函数和静态成员
- VS下用C++实现的简单3D射击游戏(附游戏文件与源工程代码)
- 校验码(奇偶码、海明码和循环冗余码)图片版
- LeetCode 319. Bulb Switcher 题解(C++)