基于OGRE实现的光线跟踪算法的问题

luyt86 2010-06-23 01:32:46
前几天看到张赐大牛写的一篇文章:《光线追踪技术的理论和实现》http://blog.csdn.net/zhangci226/archive/2010/06/11/5664313.aspx,与是一时兴起就用OGRE实现了一下,但最后渲染时有问题,找了半天还是找不出原因 ,请高手解答,实现流程和上面博客说的差不多,我是用一张纹理来存储每束光线的结果。

bool CMyTraceListener::FillPixelBuffer(size_t &width,size_t &height)
{
Ogre::TexturePtr texPtr=Ogre::TextureManager::getSingleton().getByName("MyTraceTex");
if(!texPtr.isNull())
{
texPtr->getBuffer(0,0)->lock(Ogre::HardwareBuffer::HBL_DISCARD);
const Ogre::PixelBox &pb=texPtr->getBuffer(0,0)->getCurrentLock();

Ogre::uint32 *data = static_cast<Ogre::uint32*>(pb.data);

height= pb.getHeight();
width = pb.getWidth();
size_t pitch = pb.rowPitch;


for(size_t y=0; y<height && y<512; ++y)
{
for(size_t x=0;x<width && x<512 ;++x)
{
Vector3 color=Tracer(m_vecRay[512*y +x],1); //开始光线跟踪
data[pitch*y +x]=D3DXCOLOR(color[0],color[1],color[2],1.0);
}
}


texPtr->getBuffer(0,0)->unlock();
}else
{
texPtr = Ogre::TextureManager::getSingleton().createManual(
"MyTraceTex",
"General",
Ogre::TEX_TYPE_2D,
600, 600,
0, Ogre::PF_A8R8G8B8);
if(texPtr.isNull())
return false;

texPtr->getBuffer(0,0)->lock(Ogre::HardwareBuffer::HBL_DISCARD);
const Ogre::PixelBox &pb=texPtr->getBuffer(0,0)->getCurrentLock();

Ogre::uint32 *data = static_cast<Ogre::uint32*>(pb.data);
height= pb.getHeight();
width = pb.getWidth();
size_t pitch = pb.rowPitch;


for(size_t y=0; /*y<height && */y<=512; ++y)
{
for(size_t x=0;/*x<width &&*/ x<=512 ;++x)
{
Vector3 color=Tracer(m_vecRay[512*y +x],1);//开始光线跟踪
data[pitch*y +x]=D3DXCOLOR(color[0],color[1],color[2],1.0);
}
}


texPtr->getBuffer(0,0)->unlock();
}
IDirect3DTexture9 *pTex = static_cast<Ogre::D3D9Texture *>(&*texPtr)->getNormTexture();
char buf[100];
int i=0;
sprintf_s( buf , "../auto_texture_%d.png" , i ) ;
D3DXSaveTextureToFileA( buf , D3DXIFF_PNG , pTex , NULL ) ;//保存结果到文件

//创建OGRE材质
Ogre::MaterialPtr pMat=Ogre::MaterialManager::getSingleton().create("MytraceMat",Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
if(pMat.isNull())
return false;


pMat->getTechnique(0)->getPass(0)->createTextureUnitState("MyTraceTex");
pMat->getTechnique(0)->getPass(0)->getTextureUnitState(0)->setTextureFiltering(Ogre::FO_LINEAR,Ogre::FO_LINEAR,Ogre::FO_NONE);
pMat->getTechnique(0)->getPass(0)->getTextureUnitState(0)->setColourOperation(Ogre::LBO_ALPHA_BLEND);
pMat->getTechnique(0)->getPass(0)->setSceneBlending(Ogre::SBT_TRANSPARENT_ALPHA);

pMat->getTechnique(0)->getPass(0)->setCullingMode(Ogre::CULL_NONE);

return true;
}


光线跟踪的函数:

Vector3 CMyTraceListener::Tracer(Ray ray,int depth)
{
Vector3 color=Vector3::ZERO;
Ray Reflect;
double distance = 10000;
for(int i=0;i<m_vecObject.size();++i)
{
if(m_vecObject[i]->isIntersected(ray,distance) == CGObject::INTERSECTED)
{
Vector3 p = ray.getPoint(distance);
Reflect.setOrigin(p);

Vector3 rayDir = ray.getDirection();

Vector3 N = m_vecObject[i]->GetNormal(p);

Vector3 rayRelDir=rayDir.reflect(N);
//rayRelDir = -rayRelDir;
Reflect.setDirection(rayRelDir);

N.normalise();
for(int j=0;j<m_vecLight.size();++j)
{
Vector3 ambient = m_vecLight[j]->EvalAmbient(m_vecObject[i]->GetKa());
Vector3 L = m_vecLight[j]->GetPosition() - p;
L.normalise();
Vector3 diffuse = m_vecLight[j]->EvalDiffuse(m_vecObject[i]->GetKd(),
N,L);
Vector3 V = m_vCamPos - p;
V.normalise();
Vector3 specular = m_vecLight[j]->EvalSpecular(m_vecObject[i]->GetKs(),
m_vecObject[i]->GetSininess(),N,L,V);

color = ambient+diffuse+specular;
}
}
}

if(m_iTotalDepth == depth)
return color;
else
{
Vector3 c = Tracer(Reflect,++depth);
color += color*c;
return color;
}
}


//创建用于查询的光线的函数

bool CMyTraceListener::InitTraceRay(float width,float height)
{
for(int y=0;y<=height;++y)
for(int x=0;x<=width;++x)
{
float pixel_x = -20.0 + 40.0/width*x;
float pixel_y = 20.0 - 40.0/height*y;

Vector3 dir = Vector3(pixel_x,pixel_y,0) - m_vCamPos;
dir.normalise();
Ray ray;
ray.setDirection(dir);
ray.setOrigin(m_vCamPos);
m_vecRay.push_back(ray);
}

return true;

}


如图:
...全文
571 9 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
9 条回复
切换为时间正序
请发表友善的回复…
发表回复
s亮 2013-01-23
  • 打赏
  • 举报
回复
正在实现这个。。。
dudubingbing 2012-03-07
  • 打赏
  • 举报
回复
您好!最近我也在研究OGRE下实现光线跟踪,理论大概明白的,因为我是个新人,实现起来感觉力不从心。很多东西不太懂。您能把源代码给我发一下吗?真的很感谢!邮箱是815351222@qq.com
TaChenngg 2011-02-19
  • 打赏
  • 举报
回复
参考一下, 最近也学到这里。
luyt86 2010-06-28
  • 打赏
  • 举报
回复
找到一部分原因了,原来是std::vector的问题,具体原因没详细去查,估计是容量的问题。发出的射线有几十万条,vector储存这么大的数据时出问题了,用全局数组后基本显示正常
luyt86 2010-06-23
  • 打赏
  • 举报
回复
我的虚拟的窗口大小是40x40,实际创建的窗口大小是512x512,都是1:1,这个感觉应该没什么问题,纹理保存的代码就在上面,我看了几次还是看不出什么问题,射线和球的交点用的是您贴的那个函数,而且是用的第一个交点。我再仔细看看吧,再次谢谢
张赐 2010-06-23
  • 打赏
  • 举报
回复
球是椭圆的,有可能是你的画面窗口大小比例和虚拟的那个屏幕的大小比例不一致

从画面看来,像是纹理保存也问题,球被分成了2部分,要不然就是射线和球的交点问题
luyt86 2010-06-23
  • 打赏
  • 举报
回复
嗯,好的,我先试下。首先主要问题是我在场景中渲染了两个球,但渲染出来的结果变成了椭圆,谢谢楼上的回答
张赐 2010-06-23
  • 打赏
  • 举报
回复
楼主确定纹理保存时正确的吗?

或者你可以渲染一个简单的场面试一下,一个球,只计算diffuse
luyt86 2010-06-23
  • 打赏
  • 举报
回复
图挂了,直接上网址吧http://fmn.xnimg.cn/fmn044/20100623/1315/p_large_hIt4_5e720002766e2d12.jpg

19,471

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 图形处理/算法
社区管理员
  • 图形处理/算法社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧