文档章节

Render to Texture(渲染到纹理) [ZZ]

rise-worlds
 rise-worlds
发布于 2016/06/20 13:38
字数 1081
阅读 2
收藏 0
渲染到纹理是D3D中的一项高级技术。一方面,它很简单,另一方面它很强大并能产生很多特殊效果。 比如说发光效果,环境映射,阴影映射,都可以通过它来实现。渲染到纹理只是渲染到表面的一个延伸。我们只需再加些东西就可以了。首先,我们要创造一个纹理,并且做好一些防范措施。第二步我们就可以把适当的场景渲染到我们创建的纹理上了。然后,我们把这个纹理用在最后的渲染上。

·main.cpp
   首先我们得声明所需要的对象。当然我们需要一张用来渲染的纹理。此外,我们还需要两个Surface对象。一个是用来存储后台缓冲区,一个用来当纹理的渲染对象。后面我再详细介绍它们。另外我们还需要两个矩阵,一个是用来当纹理的投影矩阵,另一个是存储原来的矩阵。

LPDIRECT3DTEXTURE9 pRenderTexture = NULL;
LPDIRECT3DSURFACE9 pRenderSurface = NULL,pBackBuffer = NULL;
D3DXMATRIX matProjection,matOldProjection;

   现在我们来创建纹理。前两个参数是纹理的宽度和高度,第三个参数是纹理的多级渐进纹理序列参数,在这里是设为1,第四个参数非常重要而且必须设为D3DUSAGE_RENDERTARGET,表明我们所创建的纹理是用来渲染的。剩下的参数就是指纹理格式,顶点缓冲区的内存位置,和一个指向纹理的指针。当纹理是用来当渲染对象时,顶点缓冲区的内存位置必须设为D3D_DEFAILT。

g_App.GetDevice()->CreateTexture(256,256,1,D3DUSAGE_RENDERTARGET,D3DFMT_R5G6B5,D3DPOOL_DEFAULT,&pRenderTexture,NULL);

   为了访问纹理内存对象,我们需要一个Surface对象,因为D3D中的纹理是用这样的一个Surface来存储纹理数据的。为了得到纹理表面的Surface,我们需要调用方法GetSurfaceLevel() 。第一个参数我们设为0,第二个参数为一个指向surface对象的指针。

pRenderTexture->GetSurfaceLevel(0,&pRenderSurface);

下一步就是创建一个适合纹理维数的投影矩阵,因为纹理的横纵比和后台缓冲区的不一样。

D3DXMatrixPerspectiveFovLH(&matProjection,D3DX_PI / 4.0f,1,1,100);

在我们的循环渲染之前,我们必须保存后台缓冲区和它的投影矩阵。

g_App.GetDevice()->GetTransform(D3DTS_PROJECTION,&matOldProjection);
g_App.GetDevice()->GetRenderTarget(0,&pBackBuffer);

   渲染循环函数可以分为两个部分。第一部分是渲染到纹理的过程。因此,渲染对象必须设为纹理表面。然后我们就可以把东西渲染到这个对象上了。渲染到另一个表面上和正常地渲染到后台缓冲区差不多。只有一点不同,那就是先不调用Prensent()函数,因为纹理上的内容并不需要显示在屏幕上。象平时一样,我们先要重置表面颜色缓冲区,并且调用BeginSence()和EndSence()方法。为了能够适当的渲染,我们必须设置和纹理表面相符的投影矩阵。否则最后的图象可能被扭曲

//render-to-texture
g_App.GetDevice()->SetRenderTarget(0,pRenderSurface); //set new render target
g_App.GetDevice()->Clear(0,NULL,D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER,D3DCOLOR_XRGB(100,100,100),1.0f,0); //clear texture
g_App.GetDevice()->BeginScene();

g_App.GetDevice()->SetTexture(0,pPyramideTexture);

D3DXMatrixRotationY(&matRotationY,fRotation);
D3DXMatrixTranslation(&matTranslation,0.0f,0.0f,5.0f);
g_App.GetDevice()->SetTransform(D3DTS_WORLD,&(matRotationY * matTranslation));
g_App.GetDevice()->SetTransform(D3DTS_PROJECTION,&matProjection); //set projection matrix

g_App.GetDevice()->SetStreamSource(0,pTriangleVB,0,sizeof(D3DVERTEX));
g_App.GetDevice()->DrawPrimitive(D3DPT_TRIANGLELIST,0,4);

g_App.GetDevice()->EndScene();

   渲染循环的第二部分就是渲染最后场景的过程(也就是显示到屏幕上的过程)。渲染对象重新设为后台缓冲区,投影矩阵重新设为原来的投影矩阵。由于纹理已经准备好了,所以它和纹理层0相关联。

//render scene with texture
g_App.GetDevice()->SetRenderTarget(0,pBackBuffer); //set back buffer
g_App.GetDevice()->Clear(0,NULL,D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER,D3DCOLOR_XRGB(0,0,0),1.0f,0);
g_App.GetDevice()->BeginScene();

g_App.GetDevice()->SetTexture(0,pRenderTexture); //set rendered texture

g_App.GetDevice()->SetTransform(D3DTS_WORLD,&matTranslation);
g_App.GetDevice()->SetTransform(D3DTS_PROJECTION,&matOldProjection); //restore projection matrix

g_App.GetDevice()->SetStreamSource(0,pQuadVB,0,sizeof(D3DVERTEX));
g_App.GetDevice()->DrawPrimitive(D3DPT_TRIANGLESTRIP,0,2);

g_App.GetDevice()->EndScene();
g_App.GetDevice()->Present(NULL,NULL,NULL,NULL);

最后我们通过调用Release()方法释放Surface对象。

pRenderSurface->Release();
pRenderSurface = NULL;

pBackBuffer->Release();
pBackBuffer = NULL;

   渲染到纹理能让你做很多事情,但是你必须注意一些限制。首先深度缓冲区必须总是大于或等于渲染对象的大小。此外,渲染对象和深度缓冲区的格式必须一致。

本文转载自:http://www.cnblogs.com/flying_bat/archive/2008/08/09/1264280.html

共有 人打赏支持
rise-worlds

rise-worlds

粉丝 2
博文 1755
码字总数 0
作品 0
深圳
程序员
私信 提问
SDL2源代码分析4:纹理(SDL_Texture)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/leixiaohua1020/article/details/40743061 ===================================================== SDL源代码......

雷霄骅
2014/11/05
0
0
RenderTexture 渲染到纹理

cocos2d里面有个CCRenderTexture,用于将指定对象渲染到纹理。在unity3d里面也有同样的技术。 今天查阅了相关资料,再看了一下cocos2d的源码,发现他实际上用的是FBO(帧缓存对象)渲染到纹理...

yizhangxyz
2016/07/01
167
0
SDL2源代码分析6:复制到渲染器(SDL_RenderCopy())

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/leixiaohua1020/article/details/40895593 ===================================================== SDL源代码......

雷霄骅
2014/11/08
0
0
SDL2源代码分析5:更新纹理(SDL_UpdateTexture())

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/leixiaohua1020/article/details/40876089 ===================================================== SDL源代码......

雷霄骅
2014/11/07
0
0
HGE基本渲染图元

2011.9.23 HGE基本的渲染图元是hgeQuad (Quad is the basic HGE graphic primitive),其中有一个hgeVertex成员结构,它用来描述图元顶点信息。The hgeVertex structure is used to descri...

晨曦之光
2012/04/13
346
0

没有更多内容

加载失败,请刷新页面

加载更多

Confluence 6 升级中的一些常见问题

升级的时候遇到了问题了吗? 如果你想尝试重新进行升级的话,你需要首先重新恢复老的备份。不要尝试再次对 Confluence 进行升级或者在升级失败后重新启动老的 Confluence。 在升级过程中的一...

honeymoose
今天
2
0
C++随笔(四)Nuget打包

首先把自己编译好的包全部准备到一个文件夹 像这样 接下来新建一个文本文档,后缀名叫.nuspec 填写内容 <?xml version="1.0"?><package xmlns="http://schemas.microsoft.com/packaging/201......

Pulsar-V
今天
2
0
再谈使用开源软件搭建数据分析平台

三年前,我写了这篇博客使用开源软件快速搭建数据分析平台, 当时收到了许多的反馈,有50个点赞和300+的收藏。到现在我还能收到一些关于dataplay2的问题。在过去的三年,开源社区和新技术的发...

naughty
今天
3
0
Python3的日期和时间

python 中处理日期时间数据通常使用datetime和time库 因为这两个库中的一些功能有些重复,所以,首先我们来比较一下这两个库的区别,这可以帮助我们在适当的情况下时候合适的库。 在Python文...

编程老陆
今天
2
0
分布式面试整理

并发和并行 并行是两个任务同时进行,而并发呢,则是一会做一个任务一会又切换做另一个任务。 临界区 临界区用来表示一种公共资源或者说是共享数据,可以被多个线程使用,但是每一次,只能有...

群星纪元
今天
3
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部