前几天看到张赐大牛写的一篇文章:《光线追踪技术的理论和实现》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;}
如图:

解决方案 »

  1.   

    图挂了,直接上网址吧http://fmn.xnimg.cn/fmn044/20100623/1315/p_large_hIt4_5e720002766e2d12.jpg
      

  2.   

    楼主确定纹理保存时正确的吗?或者你可以渲染一个简单的场面试一下,一个球,只计算diffuse
      

  3.   

    找到一部分原因了,原来是std::vector的问题,具体原因没详细去查,估计是容量的问题。发出的射线有几十万条,vector储存这么大的数据时出问题了,用全局数组后基本显示正常
      

  4.   

    您好!最近我也在研究OGRE下实现光线跟踪,理论大概明白的,因为我是个新人,实现起来感觉力不从心。很多东西不太懂。您能把源代码给我发一下吗?真的很感谢!邮箱是[email protected]