试验报告光线跟踪的实现.docx

上传人:b****4 文档编号:24268234 上传时间:2023-05-25 格式:DOCX 页数:13 大小:579.41KB
下载 相关 举报
试验报告光线跟踪的实现.docx_第1页
第1页 / 共13页
试验报告光线跟踪的实现.docx_第2页
第2页 / 共13页
试验报告光线跟踪的实现.docx_第3页
第3页 / 共13页
试验报告光线跟踪的实现.docx_第4页
第4页 / 共13页
试验报告光线跟踪的实现.docx_第5页
第5页 / 共13页
点击查看更多>>
下载资源
资源描述

试验报告光线跟踪的实现.docx

《试验报告光线跟踪的实现.docx》由会员分享,可在线阅读,更多相关《试验报告光线跟踪的实现.docx(13页珍藏版)》请在冰豆网上搜索。

试验报告光线跟踪的实现.docx

试验报告光线跟踪的实现

实验报告:

光线跟踪的实现

学号:

2111112041姓名:

李伟明

实验思想

从眼睛出发计算通过每个像素的光线方程,光线方程与场景中最近物体相交,计算各光源在该交点处的漫反射分量,镜面反射分量,并且叠加这些分量,递归计算光线在交点处的反射和折射光线,并且也将计算得到的各分量叠加到像素中,将该像素最后得到的总光强存储到一个二维数组里。

计算完所有像素后,使用opengl将这些像素点绘制出来。

一.创建场景

场景中创建了三个平面,七个球(其中两个大球,五个小球),两个光源。

定义一个800*800的二维数组:

rgbColorPixelColor[PixelH][PixelW],用于存储像素值。

PixelH和PixelW的预定义值为800。

二.计算光线方程

屏幕的大小为8*8,分辨率为800*800,屏幕在xoy平面上,屏幕中心位置是坐标原点。

眼睛的位置O(0,0,4),屏幕上一点D(image_x,image_y,0),光线的方向为V=D–O。

由此可以确定一条光线Ray(O,dir)。

然后求出该光线与场景中最近物体的交点。

三.光线与物体相交

1.光线与球体相交

球体方程:

(x-x1)^2+(y-y1)^2+(z-z1)^2=R^2

光线方程:

O+Vt=0;

V为单位向量,球心c(x1,y1,z1)。

由两方程可得

t^2+2V*(O-c)*t+[(O-c)*(O-c)-R^2]=0

根据方程计算出t的实数解。

具体实现如下:

//tmin就是float,inp变量在折射时用到

boolSphere:

:

intersect(Ray&r,tmin&T,bool&inp)

{

floatA=1.0;

vec3fE_C=r.getOrigin()-_center;

floatB=2*dot(r.getDirection(),E_C);

floatC=power(E_C)-pow(_radius,2);

floatD=pow(B,2)-4*A*C;

inp=false;

boolreslut=false;

if(D<0)

{

return0;

}

else

{

D=sqrtf(D);

floatt1=(-B+D)/2*A;

floatt2=(-B-D)/2*A;

if(t1>0)

{

if(t2<0.001)//问题一所在

{

if(t1

{

T=t1;

reslut=true;

inp=true;

}

}

else

{

if(t2

{

T=t2;

reslut=true;

}

}

}

}

returnreslut;

}

2.光线平面相交

首先平面的法向量N与光线方向向量V点乘,如果结果不为0,则光线与平面有交点,计算出对应交点的t值

具体实现如下

boolPlane:

:

intersect(Ray&r,tmin&T,bool&inp)

{

vec3ftmp=r.getOrigin()-_center;

floatcosV_N=-dot(r.getDirection(),_normal);

boolreslut=false;

inp=false;

if(cosV_N!

=0)

{

floatt=dot(tmp,_normal)/cosV_N;

if(t>0)

{

if(t

{

T=t;

reslut=true;

}

}

}

returnreslut;

}

四.慢反射光的计算

漫反射的计算公式为

,为了实现方便,我将Kd设置成了浮点型,表示对RGB三个分量的反射强度相同,同时为了反映出物体本身的颜色属性,在计算时乘上了物体本身的颜色。

1.具体实现代码为

if(prim->_pMat.GetDiffuse()>0)//首先判断物体的漫反射系数是否大于0

{

floatcosN_L=dot(N,L);//光线与交点法线的夹角的余弦值

if(cosN_L>0)

{//shade是阴影开关,如果交点在阴影中则shade=0,否则shade=1

color=color+shade*cosN_L*prim->_pMat.GetDiffuse()*prim->_pMat.GetColor()*lig->_pMat.GetColor();//物体的颜色与光源的颜色混合

}

}

以上代码中N为交点处的单位法向量,L为交点到光源的单位向量,dot(N,L)表示点成两个向量,prim->_pMat.GetDiffuse()为物体的慢反射系数,prim->_pMat.GetColor()为物体的颜色值,含RGB三个分量,lig->_pMat.GetColor()是光源的颜色值,含RGB三个分量。

2.效果如下

五.阴影的计算

对于场景中的每个光源创建一条阴影测试光线,判断对场景中的所有球体是否有相交,因为我的程序中平面作为了边界,所以不用考虑再内。

如果相交,则说明物体在阴影中,光线照射不到该点,设置shade=0;否则说明物体不在阴影中,光线能够照射到该点,设置shade=1。

1.具体实现代码如下

floatshade=1.0;//shade是阴影开关,如果交点在阴影中则shade=0,否则shade=1

Rayrtest(pi+SMALLF*L,L);

floatmtest=10000.0;

boolintest=true;

for(intk=1;k<7;k++)//只测试场景中的7个球体,不测试边界的平面

{

objec3D*p1=_scene->_objlist[k];

if(p1->intersect(rtest,mtest,intest))

{

shade=0.0;

break;

}

}

2.效果如下

六.Phong高光的计算

根据Phong光照模型得到的公式为

其中r=(2*dot(N,L))*N–L,我的程序中把Ks设置成浮点型,表示对RGB三个分量的镜面反射相同。

1.具体代码为

vec3fR=(2*dot(N,L))*N-L;

floatcosR_V=dot(R,V);

if(cosR_V>0)

{

floatphong=powf(cosR_V,30);

color=color+shade*phong*prim->_pMat.GetSpecular()*lig->_pMat.GetColor();

}

以上代码中R为光源光线的反射向量,V为视线的方向,N为交点法向量,L为光源光线向量。

Phong的指数设置为30,prim->_pMat.GetSpecular()为镜面反射系数。

2.效果如下

七.反射光的计算

反射光线的计算公式为:

Reflection_V=V-(2.0*dot(N,V))*N

其中Reflection_V为反射光的方向,V为入射光线,即视线,N为交点处的法向量。

计算反射光线并递归跟踪,其中depth是递归深度值。

还设置了一个inp变量,用于判断光线是否在物体内与物体相交,如果inp=true,则说明光线是在物体与之相交,那么就不计算它的反射分量。

1.具体代码如下

if((prim->_pMat.GetReflection()>0)&&(depth<4))

{

if(!

inp)

{

vec3fReflection_V=V-(2.0*dot(N,V))*N;

pi=pi+SMALLF*Reflection_V;//问题二所在

Rayr2(pi,Reflection_V);

vec3fcolorR(0.0,0.0,0.0);

trace(r2,colorR,depth+1);

color=color+prim->_pMat.GetReflection()*colorR*prim->_pMat.GetColor();

}

}

以上代码中prim->_pMat.GetReflection()是物体的反射系数。

2.效果如下

八.折射光的计算

根据折射定理可以得到公式

其中T为折射光线的方向向量,I为入射光线,n为交点处的法向量,

我的程序中,物体的折射率事先给定。

计算反射光线并递归跟踪,其中depth是递归深度值。

1.具体实现代码如下

if((prim->_pMat.GetTransmit()>0)&&(depth<4))

{

floatk_n=prim->_pMat.GetN();

floatk_tran=prim->_pMat.GetTransmit();

floatn;

floatcosN_V=-dot(N,V);

if(inp)

{

n=k_n;

}

else

{

n=1.0/k_n;

}

floattmp=n*cosN_V-sqrtf(1+pow(n,2)*(pow(cosN_V,2)-1));

vec3fT=n*V+tmp*N;

T.normal();

pi=pi+SMALLF*T;//问题二所在

Rayr1(pi,T);

vec3fcolorT(0.0,0.0,0.0);

trace(r1,colorT,depth+1);

color=color+k_tran*colorT;

}

以上代码中prim->_pMat.GetN()是得到折射率,prim->_pMat.GetTransmit()是得到物体的透明系数,N是交点的法向量,V是入射光向量。

2.效果如下

左边大球后面有一个红色小球,右边打球后面有四个蓝色小球。

左边的球透明系数为0,所以没有折射效果,右边的球透明系数不为0,所以能折射出后面四个小球。

九.绘制

在main函数中使用glut创建初始化窗口,利用OpenGL绘制点的函数将存储在数组PixelColor[PixelH][PixelW]中的值绘制出来。

具体绘制代码如下:

voiddraw()

{

floatdx=2.0/PixelW;

floatdy=2.0/PixelH;

GLfloatx=-1.0;

GLfloaty=-1.0;

glBegin(GL_POINTS);

for(inti=0;i

{

x=-1.0f;

for(intj=0;j

{

glColor3f(rayT.PixelColor[i][j].x,rayT.PixelColor[i][j].y,rayT.PixelColor[i][j].z);

glVertex2f(x,y);

x+=dx;

}

y+=dy;

}

glEnd();

}

一十.遇到的问题

1.问题一

计算光线在球体内与球相交时,理论上得到的两个交点的其中一个交点是光线的原点,所以得到的t值中其中一个应该是为0,我的程序中是交点为t2的值。

但是在程序实现中,由于计算精度误差的原因,计算得到的t2会是一个略大于0的值,因此如果在判断是为“t2<=0”,则程序运行后球体上会出现一些噪点。

如下图所示:

所以在判断是若设定t2小于一个小的浮点数,则这个问题就能解决。

我的程序中设置了“t2<0.0001”。

3.问题二

在计算反射光和折射光中,递归跟踪光线时,若直接以交点作为观察原点计算光线,则结果也会出现很多噪点。

如下图所示:

其原因也是因为求光线与球的交点时,得到的t值的精度问题。

计算得到的点,理论上应该是球表面的点,但实际是位于球内,所以计算反射光线时,刚好又与球相交。

计算折射光线时也是同样的原因。

只要在计算光线前,观察原点加上观察方向上的一个小分量作为修正,问题就能解决。

我的程序中是预定义一个小的浮点数SMALLF=0.00001,然后在递归跟踪光线中,SMALLF乘上光线方向,并加到观察点上。

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 职业教育 > 其它

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1