【3D技术宅公社】XR数字艺术论坛  XR技术讨论 XR互动电影 定格动画

 找回密码
 立即注册

QQ登录

只需一步,快速开始

调查问卷
论坛即将给大家带来全新的技术服务,面向三围图形学、游戏、动画的全新服务论坛升级为UTF8版本后,中文用户名和用户密码中有中文的都无法登陆,请发邮件到324007255(at)QQ.com联系手动修改密码

3D技术论坛将以计算机图形学为核心,面向教育 推出国内的三维教育引擎该项目在持续研发当中,感谢大家的关注。

查看: 8816|回复: 31

[转帖]D3D中的渲染到纹理

[复制链接]
发表于 2009-1-4 00:51:22 | 显示全部楼层 |阅读模式
渲染到纹理是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()->resent(NULL,NULL,NULL,NULL);
  最后我们通过调用Release()方法释放Surface对象。
  pRenderSurface->Release();
  pRenderSurface = NULL;
  pBackBuffer->Release();
  pBackBuffer = NULL;
  渲染到纹理能让你做很多事情,但是你必须注意一些限制。首先深度缓冲区必须总是大于或等于渲染对象的大小。此外,渲染对象和深度缓冲区的格式必须一致。
发表于 2009-2-2 23:57:00 | 显示全部楼层

速度哦。。。你们俩都没有考虑过速度问题吗??

在内存中使用 LOCK,UNLOCK,来实现透明,是非常慢的啊。。。。(我在一篇文章中看见的,不过忘记出处了。。。)

发表于 2009-1-4 09:13:21 | 显示全部楼层

不是吧。。。你的这个帖子,和我在网上找到的资料是同一个出处。。。。

我正在完成第一个RTT,应该很快

我俩真是心有灵犀啊。。。。找资料都找一样的。。。。。

发表于 2009-1-5 14:45:08 | 显示全部楼层

这是我的源代码,就是在以前那个立方体上面改的:

 

oOjfQNFj.rar (38.84 KB, 下载次数: 0)

发表于 2009-1-6 17:22:03 | 显示全部楼层

32色??不知道你指的什么?

我把 RTT.BMP 分别设置成 “单色”,“16位色”,“24位色”,程序都可以正常运行

而且,我在创建 TEXTURE 的时候,没有指定它的像素格式,我用的“D3DFMT_UNKNOWN”指定的像素格式

发表于 2009-1-6 17:39:22 | 显示全部楼层

一般情况下 图形只需要支持 R5G6B5  16色 就可以了   0x00000000 需要的打开Alpha 通道 那么就需更多的色彩支持

D3DFMT_UNKNOWN 可用是你本身显卡就支持Alpha 通道,有的显卡不支持16色以上的图形显示,那么你的代码就不能用了

 楼主| 发表于 2009-1-6 18:22:07 | 显示全部楼层
 首先祝贺drucula成功!
看了你给的连接,我知道原因了~~多谢!哈哈
我是习惯像素拷贝了,因为用API操作不知道它里面做了什么,我像素拷贝已经做了很多次了,还是自己动手最放心
其实也不一定要32色  只要支持Alpha 通道 就行了;像素拷贝通用性强,没有任何限制 我比较喜欢
看个人爱好啦~~在实际项目中,只要解决问题就是好办法!
发表于 2009-1-4 09:30:46 | 显示全部楼层

成功了~~~~鼹鼠~~~~

完成了一个RTT,在一个 TEXTURE 中渲染任意的一个3D模型,然后用 SPRITE 把他画出来,这样,就可以利用 SPRITE 的 RECT 把这个3D模型定位到屏幕上指定的地方了~~~~YEAH~~~~

发表于 2009-1-4 09:34:53 | 显示全部楼层
还有就是不需要考虑缩放问题,因为作为RTT的那个目标 TEXTURE ,可以给它自己一个单独的 MATRIX 体系,和 BACKBUFFER 的 METRIX 不相干,就象我们找的这篇文章里说的,RTT之前,保存 BACKBUFFER 的 METRIX,RTT 以后还原它就可以了
发表于 2009-1-4 09:47:40 | 显示全部楼层

我晕啊。。。我用 SPRITE 绘制的 TEXTURE ,背景色是黑色,把 PRESENT 画出来的东西挡住啦。。。

到网上找了一下,如何设置 TEXTURE 的透明色,结果找到的都是 CreateTextureFromFile 这个函数中,有参数可以设置透明色,这个我也知道啊。。

那么我用 CreateTexture 这个函数创建的 TEXTURE 如何设置透明色呢???

 楼主| 发表于 2009-1-4 10:16:28 | 显示全部楼层

哈哈 真的是这样啊

 

渲染到纹理我刚才已经测试通过了~~

主要是中间要生成一个临时缓冲

把纹理渲染到这个临时缓冲中

我一会整理一下 写一个文章来专门讨论这个问题。

 

你说纹理透明,我个人喜欢直接锁定内存操作,当然你也可以用这个函数试试  D3DXCreateTextureFromResourceEx

发表于 2009-1-4 10:19:28 | 显示全部楼层
把程序发上来你看下,左上角那个 MESH 就是用 RTT 画上去的,当大方块移动到左上角时。。。。被 RTT 所绘制的 TEXTURE 的黑色背景挡住了。。。。。 upehup5q.rar (23.82 KB, 下载次数: 0)
发表于 2009-1-4 10:25:26 | 显示全部楼层

我用来 RTT 操作的 TEXTURE 是通过 CreateTexture 这个函数来创建的。。。不是通过 D3DXCreateTextureFromResourceEx 这个函数创建的。。。

在 CreateTexture 这个函数的参数中,没有设置透明色的选项啊。。。

 楼主| 发表于 2009-1-4 10:27:30 | 显示全部楼层

看到了 效果就是这样的~~~

纹理的背景很好处理的

我一般内存背景处理都是锁定内存直接拷贝去掉背景的

D3DXCreateTextureFromResourceEx  里面有个参数可以设定关键色~~应该是可以

发表于 2009-1-4 10:53:22 | 显示全部楼层

我晕哦。。。难道是我们发帖的时间差???早叫你告诉我一个可以即时通讯联络的方法。。。。(QQ.MSN,或者其他的,如果你不想让别人知道,把联系方式发到我的邮箱。。。)

 

在使用RTT的时候,不是需要一个空的 TEXTURE 吗??

这个 TEXTURE ,我是通过 CreateText 这个函数来创建的:

Device->CreateTexture(128,128,1,D3DUSAGE_RENDERTARGET,D3DFMT_R5G6B5,D3DPOOL_DEFAULT,&pRenderTexture,NULL);

 

你说的 D3DXCreateTextureFromResourceEx 不是要读一个图片文件进来???

难道说在使用RTT的时候要用 D3DXCreateTextureFromResourceEx 来创建一个非空的纹理,然后把东西渲染到它上面??不会吧。。。

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|3D数字艺术论坛 ( 沪ICP备14023054号 )

GMT+8, 2025-2-6 11:40

Powered by Discuz! X3.4

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表