今天是520,20年前肯定没有这个“节日”呢。下面是20年前的一张图,当时用于送给Dudu的生日礼物哦:
Hss:来看看我给你做的生日贺卡。
Dudu:啊,好漂亮,你怎么实现的?
Hss:啊,是这样,在背景放上文字和心形,中间放三个玻璃球,然后指定光源位置,用光线跟踪算法来做光线渲染,然后……
然后,然后就没有然后了。
上图是1996年(20年前)选修了学校的”计算机图形学“课程,其中一个作业是实现光线追踪算法,然后就有了上面的完成的作业。作业的代码原始版本是从师兄那里获得(但原始作者不清楚是不是师兄), 我在原有代码上进行了少许修改,包括:
(1)光线跟踪作业里加入了心形的背景,以及人名的缩写
(2)纹理作业里加入了随机性,用于模拟树木的年轮
恩,其实就是抄作业啦,惭愧!
代码附后(源代码是Turbo C 2.0的工程,这里只是主要源代码):
/**************************************************************************** 我在1996(20年前)年选修学校的计算机图像学课程,课后作业是编程实现一些课上学习的算法 此代码原始版本是从师兄那里获得(但原始作者不清楚是不是师兄) 我在原有代码上进行了少许修改,包括: (1)光线跟踪作业里加入了心形的背景,以及人名的缩写 (2)纹理作业里加入了随机性,用于模拟树木的年轮 Tom Huang 于 2016/5/20 补记 \*******************************************************************************/ #include <windows.h> #include <stdio.h> #include <math.h> #include "cge.h" #include "lut.h" #define ERROR 0.1E-6 #define line1(p) ((p1[0]-p0[0]) * (p[1]-p0[1]) - (p1[1]-p0[1]) * (p[0]-p0[0])) typedef struct tagRGB { unsigned int red , green , blue; }RGB,*PRGB; void CGEWork0(HDC hDC) { int i; int j; SetLUT(hDC); for(j=0;j<256;j++) for(i=0;i<100;i++) { SetPixel(hDC,2*j,i,(0x01000000L |j)); SetPixel(hDC,2*j+1,i,(0x01000000L | j)); } } void ShapeSphere(hDC,kd,ks,n,Xcenter,Ycenter,R) HDC hDC; double ks,kd,Xcenter,Ycenter,R; int n; { int Ilight,Ir,Ig,Ib,Ia; double Hx,Hy,Hz,Lx,Ly,Lz,xn,yn,zn,LN,NHn,NH; double Id,Is,x,y,z,Ka; Ilight = 120; Ia =320; Ka = 0.2; Lx=Ly=Lz=0.57735; Hx = 0.325058; Hy = 0.325058; Hz = 0.888075; SetLUT_GREEN(hDC); for(y = (-R);y <= R ; y++) for( x = (-R);x <= R;x++ ) { if (x*x+y*y <= R*R) { z=sqrt(R*R-x*x-y*y); xn=x/R; yn=y/R; zn=z/R; LN=xn*Lx+yn*Ly+zn*Lz; if(LN>0) { NH=Hx*xn+Hy*yn+Hz*zn; NHn=pow(NH,n); } if(LN<0) { Ig=Ia*Ka; Ir=Ib=0.0; } else { Id=kd*LN*Ilight; Is=ks*NHn*Ilight; Ig=(Ka*Ia+Id+Is); Ir=Ib=0; } SetPixel(hDC,Xcenter+x,Ycenter+y,PALETTERGB(Ir, Ig, Ib)); } } } //Phong void CGEWork1(HDC hDC) { double Kd,Ks,r,X,Y; int i,j; int n; Kd = 0; n = 5; r = 25.0; Y=50; for(i=1;i<=4;i++) { Kd=0; Ks = 1- Kd; X=100; for(j=1;j<=5;j++) { ShapeSphere(hDC,Kd,Ks,n,X,Y,r); Kd += 0.25; Ks = 1-Kd; X+=60; } Y+=60; n *= 2; } } //Cook void CGEWork2(HDC hDC) { int Xcenter,Ycenter; double f,dw,s,d,m,tmp,G0,Gm,Gs,D,G,NV,NH,NL,VH,HL; double x,y,z,xn,yn,zn,Lxn,Lyn,Lzn; double Vx,Vy,Vz,Hxn,Hyn,Hzn,Lx,Ly,Lz,Hx,Hy,Hz; double nr,ng,nb,For,Fog,Fob,Rdr,Rdb,Rdg,Rsr,Rsb,Rsg; double Rar,Rag,Rab,Fr,Fb,Fg,o,or,ob,og; double PI,R; unsigned long Ir,Ig,Ib,Ip,Ia; PI=3.14159265; Ip=600000L; R=100.0; Xcenter=200; Ycenter=150; f=1.0; dw=0.0002; s=0.9; d=0.1; m=0.3; Rdr=For=0.755; Rdb=Fob=0.095; Rdg=Fog=0.490; Ia=0.00006*Ip; Lx =-5.0; Ly=-5; Lz=10.0; Vx = 0.0; Vy = 0.0; Vz = 1.0; Rar=PI*Rdr; Rag=PI*Rdg; Rab=PI*Rdb; nr=(1+sqrt(For))/(1-sqrt(For)); ng=(1+sqrt(Fog))/(1-sqrt(Fog)); nb=(1+sqrt(Fob))/(1-sqrt(Fob)); tmp=sqrt(Lx*Lx+Ly*Ly+Lz*Lz); Lxn=Lx/tmp; Lyn=Ly/tmp; Lzn=Lz/tmp; Hx=(Lx+Vx)/2; //? Hy=(Ly+Vy)/2; //? Hz=(Lz+Vz)/2; //? tmp=sqrt(Hx*Hx+Hy*Hy+Hz*Hz); Hxn=Hx/tmp; Hyn=Hy/tmp; Hzn=Hz/tmp; VH=Vx*Hxn+Vy*Hyn+Vz*Hzn; SetLUT_YELLOW(hDC); for (y=(-R);y<=R;y++) for (x=(-R);x<=R;x++) { if (x*x+y*y<=R*R) { z=sqrt(R*R-x*x-y*y); xn=x/R; yn=y/R; zn=z/R; NL=xn*Lxn+yn*Lyn+zn*Lzn; NV=xn*Vx+yn*Vy+zn*Vz; NH=xn*Hxn+yn*Hyn+zn*Hzn; G0 = 1.0; if((NL>0)&&(NV>0)&&(NH>0)) { Gs=2.0*NH*NL/VH; Gm=2.0*NH*NV/VH; G=min(G0,Gs); G=min(G ,Gm); o = acos(NH); D=(exp(-pow(tan(o),2)/(m*m)))/(m*m*pow(NH,4)); HL=(Lxn*Hxn+Lyn*Hyn+Lzn*Hzn); o=acos(HL); or=asin(sin(o)/nr); Fr=0.5*(pow(sin(o-or),2)/pow(sin(o+or),2) +pow(tan(o-or),2)/pow(tan(o+or),2)); Rsr=Fr*D*G/(NV*NL*PI); og=asin(sin(o)/ng); Fg=0.5*(pow(sin(o-og),2)/pow(sin(o+og),2) +pow(tan(o-og),2)/pow(tan(o+og),2)); Rsg=Fg*D*G/(NV*NL*PI); ob=asin(sin(o)/nb); Fb=0.5*(pow(sin(o-ob),2)/pow(sin(o+ob),2) +pow(tan(o-ob),2)/pow(tan(o+ob),2)); Rsb=Fb*D*G/(NV*NL*PI); Ir=Ia*Rar*f+Ip*NL*dw*(s*Rsr+d*Rdr); Ib=Ia*Rab*f+Ip*NL*dw*(s*Rsb+d*Rdb); Ig=Ia*Rag*f+Ip*NL*dw*(s*Rsg+d*Rdg); if (Ir>255) Ir = 255; if (Ig>255) Ig = 255; if (Ib>255) Ib = 255; } else { Ir=Ia*Rar*f; Ig=Ia*Rag*f; Ib=Ia*Rab*f; } SetPixel(hDC,Xcenter+x,Ycenter+y,PALETTERGB(Ir,Ig,Ib)); } } } double square(double a,double b,double c) { double m; m = sqrt(a*a+b*b+c*c); return m; } //gourand void CGEWork3(HDC hDC) { double PointX[11],PointY[11],PointZ[11]; double R,High,temp1,temp2,temp3,length; double I[11]; double t,Ax,Ay,Az,Bx,By,Bz,Cx,Cy,Cz,Dx,Dy,Dz; double Vx,Vy,Vz,Lx,Ly,Lz,Lxn,Lyn,Lzn; double x0,x1,y0,y1,LNN,NHn,NH; int Xcenter,Ycenter,i,j; float Kd,Ks; long Ilight,Iaka,Ir,Ib,Ig,Id,Is; t = sqrt(3.0); Ax=0.0; Ay=(-t)/2.0; Az=0.5; Bx=(-t)/2.0; By=0.25; Bz=(t)/4.0; Cx=0; Cy=0.5; Cz=t/2.0; Dx=(t)/2.0; Dy=0.25; Dz=(t)/4.0; Vx=0; Vy=0; Vz=1.0; Lx=(Ax+Cx+Bx)/3.0; Ly=(Ay+Cy+By)/3.0; Lz=(Az+Cz+Bz)/3.0; Lxn=Lx/sqrt(Lx*Lx+Ly*Ly+Lz*Lz); Lyn=Ly/sqrt(Lx*Lx+Ly*Ly+Lz*Lz); Lzn=Lz/sqrt(Lx*Lx+Ly*Ly+Lz*Lz); Kd = 0.2; Ks = 0.7; Ilight = 200; Iaka = 50; R=40; High= 150; length=square((Ax-Cx-Dx),(Ay-Cy-Dy),(Az-Cz-Dz)); PointX[1]=(Ax-Cx-Dx)/(length); PointY[1]=(Ay-Cy-Dy)/(length); PointZ[1]=(Az-Cz-Dz)/(length); length=square((Ax-Cx-Bx),(Ay-Cy-By),(Az-Cz-Bz)); PointX[2]=(Ax-Cx-Bx)/(length); PointY[2]=(Ay-Cy-By)/(length); PointZ[2]=(Az-Cz-Bz)/(length); length = square((Ax+Bx-Dx),(Ay+By-Dy),(Az+Bz-Dz)); PointX[3]=(Ax+Bx-Dx)/(length); PointY[3]=(Ay+By-Dy)/(length); PointZ[3]=(Az+Bz-Dz)/(length); length = square((Ax+Dx-Bx),(Ay-By+Dy),(Az-Bz+Dz)); PointX[4]=(Ax+Dx-Bx)/length; PointY[4]=(Ay-By+Dy)/length; PointZ[4]=(Az-Bz+Dz)/length; PointX[5]=Lx;PointY[5]=Ly;PointZ[5]=Lz; length=square((Ax+Cx+Dx),(Ay+Cy+Dy),(Az+Cz+Dz)); PointX[6]=(Ax+Cx+Dx)/length; PointY[6]=(Ay+Cy+Dy)/length; PointZ[6]=(Az+Cz+Dz)/length; length = square((-Ax+Bx-Dx),(-Ay+By-Dy),(-Az+Bz-Dz)); PointX[7]=(-Ax+Bx-Dx)/length; PointY[7]=(-Ay+By-Dy)/length; PointZ[7]=(-Az+Bz-Dz)/length; length=square((-Ax-Bx+Dx),(-Ay-By+Dy),(-Az-Bz+Dz)); PointX[8]=(-Ax-Bx+Dx)/length; PointY[8]=(-Ay-By+Dy)/length; PointZ[8]=(-Az-Bz+Dz)/length; length=square((-Ax+Cx+Bx),(-Ay+Cy+By),(-Az+Cz+Bz)); PointX[9]=(-Ax+Cx+Bx)/length; PointY[9]=(-Ay+Cy+By)/length; PointZ[9]=(-Az+Cz+Bz)/length; length=square((-Ax+Cx+Dx),(-Ay+Cy+Dy),(-Az+Cz+Dz)); PointX[10]=(-Ax+Cx+Dx)/length; PointY[10]=(-Ay+Cy+Dy)/length; PointZ[10]=(-Az+Cz+Dz)/length; SetLUT_GRAY(hDC); Xcenter = 70; Ycenter = 50; y0=Ycenter-R*(t)/4; LNN = Ax*Lxn+Ay*Lyn+Az*Lzn; NH = Ax*Vx+Ay*Vy+Az*Vz; NHn = pow(NH,10); for(j=y0; j<=Ycenter; j++) { y1=2*(j-y0)/(t); x0=Xcenter-R/2-y1; x1=Xcenter+R/2+y1; for(i=x0;i<=x1;i++) { if(LNN<0) Ig=Ib=Ir=Iaka; else { Id=Kd*LNN*Ilight; Is=Ks*NHn*Ilight; Ig=Ir=Ib=Iaka+Id+Is+30; } if(Ig>255) Ib=Ig=Ir=255; SetPixel(hDC,i,j,PALETTERGB(Ir,Ig,Ib)); SetPixel(hDC,i,2*Ycenter-j,PALETTERGB(Ir,Ig,Ib)); } } x0 = Xcenter - R; y0 = High*(t)/2.0; LNN =Bx*Lxn+By*Lyn+Bz*Lzn; NH = Bx*Vx+By*Vy+Bz*Vz; NHn = pow(NH,10); for(i=0;i<=R/2;i++) { y1=i*(t)/2.0+Ycenter; for(j=0;j<=y0;j++) { if(LNN<0) Ig=Ib=Ir=Iaka; else { Id=Kd*LNN*Ilight; Is=Ks*NHn*Ilight; Ig=Ir=Ib=Iaka+Id+Is+30; } if(Ig>250) Ib=Ig=Ir=250; SetPixel(hDC,i+x0,j+y1,PALETTERGB(Ir,Ig,Ib)); } } x0 = Xcenter - R/2; y1 = Ycenter + R*(t)/4.0; LNN =Cx*Lxn+Cy*Lyn+Cz*Lzn; NH = Cx*Vx+Cy*Vy+Cz*Vz; NHn = pow(NH,10); for(i=0;i<=R;i++) { for(j=0;j<=y0;j++) { if(LNN<0) Ig=Ib=Ir=Iaka; else { Id=Kd*LNN*Ilight; Is=Ks*NHn*Ilight; Ig=Ir=Ib=Iaka+Id+Is+30; } if(Ig>250) Ib=Ig=Ir=250; SetPixel(hDC,i+x0,j+y1,PALETTERGB(Ir,Ig,Ib)); } } x0 = Xcenter + R/2; LNN =Dx*Lxn+Dy*Lyn+Dz*Lzn; NH = Dx*Vx+Dy*Vy+Dz*Vz; NHn = pow(NH,10); for(i=0;i<=R/2;i++) { y1 = (R/2-i)*(t)/2+Ycenter; for(j=0;j<=y0;j++) { if(LNN<0) Ig=Ib=Ir=Iaka; else { Id=Kd*LNN*Ilight; Is=Ks*NHn*Ilight; Ig=Ir=Ib=Iaka+Id+Is+30; } if(Ig>250) Ib=Ig=Ir=250; SetPixel(hDC,i+x0,j+y1,PALETTERGB(Ir,Ig,Ib)); } } for ( i=1;i<11;i++) { LNN =PointX[i]*Lxn+PointY[i]*Lyn+PointZ[i]*Lzn; NH = PointX[i]*Vx+PointY[i]*Vy+PointZ[i]*Vz; NHn = pow(NH,10); if(LNN<0) I[i]= Iaka; else { Id = Kd*LNN*Ilight; Is = Ks*NHn*Ilight; I[i]= Iaka+Id+Is+30; } if(I[i]>250) I[i] = 250; } Xcenter = 230; Ycenter= 50; y0=R*(t)/4; temp1 = (I[3]-I[1])/y0; temp2 = (I[4]-I[2])/y0; for(j=0; j<=y0; j++) { y1=R*j/(2*y0); x0=Xcenter-R/2-y1; x1=Xcenter+R/2+y1; Ig = I[1]+temp1*j; Ir = I[2] + temp2*j; for(i=x0;i<=x1;i++) { temp3 = (Ir-Ig )*(i-x0)/(x1-x0); Ib = Ig+temp3; if(Ib>250) Ib=250; SetPixel(hDC,i,Ycenter-y0+j,PALETTERGB(Ib,Ib,Ib)); } } temp1 = (I[3]-I[5])/y0; temp2 = (I[4]-I[6])/y0; for(j=0; j<=y0; j++) { y1=R*(y0-j)/(2*y0); x0=Xcenter-R/2-y1; x1=Xcenter+R/2+y1; Ig = I[3]-temp1*j; Ir = I[4] - temp2*j; for(i=x0;i<=x1;i++) { temp3 = (Ir-Ig )*(i-x0)/(x1-x0); Ib = Ig+temp3; if(Ib>250) Ib=250; SetPixel(hDC,i,j+Ycenter,PALETTERGB(Ib,Ib,Ib)); } } x0 = Xcenter -R; y0 = High*(t)/2.0; temp1=(I[5]-I[3])*2/R; temp2 = (I[9]-I[7])*2/R; for(i=0;i<=R/2;i++) { y1=i*(t)/2.0+Ycenter; Ig = I[3] + temp1*i; Ir = I[7] +temp2*i; for(j=0;j<=y0;j++) { temp3 = (Ir-Ig)*j/y0; Ib = Ig+temp3; if(Ib>250) Ib=250; SetPixel(hDC,i+x0,j+y1,PALETTERGB(Ib,Ib,Ib)); } } x0 = Xcenter - R/2; y1 = Ycenter + R*(t)/4.0; temp1 =(I[6]-I[5])/R; temp2 =(I[10]-I[9])/R; for(i=0;i<=R;i++) { Ig = I[5] + temp1*i; Ir= I[9] +temp2*i; for(j=0;j<=y0;j++) { temp3= (Ir-Ig)*j/y0; Ib = Ig+temp3; if(Ib>250) Ib=250; SetPixel(hDC,i+x0,j+y1,PALETTERGB(Ib,Ib,Ib)); } } x0 = Xcenter + R/2; temp1=(I[4]-I[6])*2/R; temp2=(I[8]-I[10])*2/R; for(i=0;i<=R/2;i++) { y1 = (R/2-i)*(t)/2+Ycenter; Ig = I[6] + temp1*i; Ir= I[10]+temp2*i; for(j=0;j<=y0;j++) { temp3= (Ir-Ig)*j/y0; Ib = Ig+temp3; if(Ib>250) Ib=250; SetPixel(hDC,i+x0,j+y1,PALETTERGB(Ib,Ib,Ib)); } } Xcenter = 400; Ycenter= 50; y0=R*(t)/4; Ax=(PointX[3]-PointX[1])/y0; Ay=(PointY[3]-PointY[1])/y0; Az=(PointZ[3]-PointZ[1])/y0; Bx=(PointX[4]-PointX[2])/y0; By=(PointY[4]-PointY[2])/y0; Bz=(PointZ[4]-PointZ[2])/y0; for(j=0; j<=y0; j++) { y1=R*j/(2*y0); x0=Xcenter-R/2-y1; x1=Xcenter+R/2+y1; Cx=PointX[1]+Ax*j; Cy=PointY[1]+Ay*j; Cz=PointZ[1]+Az*j; Dx=PointX[2]+Bx*j;Dy=PointY[2]+By*j;Dz=PointZ[2]+Bz*j; length=square(Cx,Cy,Cz); Cx=Cx/length;Cy=Cy/length;Cz=Cz/length; length=square(Dx,Dy,Dz); Dx=Dx/length;Dy=Dy/length;Dz=Dz/length; for(i=x0;i<=x1;i++) { I[1]=Cx+(Dx-Cx)*(i-x0)/(x1-x0); I[2]=Cy+(Dy-Cy)*(i-x0)/(x1-x0); I[3]=(Dz-Cz)*(i-x0)/(x1-x0)+Cz; length=square(I[1],I[2],I[3]); I[1]=I[1]/length; I[2]=I[2]/length; I[3]=I[3]/length; LNN =I[1]*Lxn+I[2]*Lyn+I[3]*Lzn; NH = I[1]*Vx+I[2]*Vy+I[3]*Vz; NHn = pow(NH,10); if(LNN<0) Ig=Ib=Ir=Iaka; else { Id=Kd*LNN*Ilight; Is=Ks*NHn*Ilight; Ig=Ib=Ir=Iaka+Id+Is+30; } if(Ib>250) Ib=Ig=Ir=250; SetPixel(hDC,i,Ycenter-y0+j,PALETTERGB(Ir,Ig,Ib)); } } Ax=(PointX[3]-PointX[5])/y0;Ay=(PointY[3]-PointY[5])/y0; Az=(PointZ[3]-PointZ[5])/y0;Bx=(PointX[4]-PointX[6])/y0; By=(PointY[4]-PointY[6])/y0;Bz=(PointZ[4]-PointZ[6])/y0; for(j=0; j<=y0; j++) { y1=R*(y0-j)/(2*y0); x0=Xcenter-R/2-y1; x1=Xcenter+R/2+y1; Cx=PointX[3]-Ax*j;Cy=PointY[3]-Ay*j;Cz=PointZ[3]-Az*j; Dx=PointX[4]-Bx*j;Dy=PointY[4]-By*j;Dz=PointZ[4]-Bz*j; length=square(Cx,Cy,Cz); Cx=Cx/length;Cy=Cy/length;Cz=Cz/length; length=square(Dx,Dy,Dz); Dx=Dx/length;Dy=Dy/length;Dz=Dz/length; for(i=x0;i<=x1;i++) { I[1]=Cx+(Dx-Cx)*(i-x0)/(x1-x0); I[2]=Cy+(Dy-Cy)*(i-x0)/(x1-x0); I[3]=(Dz-Cz)*(i-x0)/(x1-x0)+Cz; length=square(I[1],I[2],I[3]); I[1]=I[1]/length;I[2]=I[2]/length;I[3]=I[3]/length; LNN =I[1]*Lxn+I[2]*Lyn+I[3]*Lzn; NH = I[1]*Vx+I[2]*Vy+I[3]*Vz; NHn = pow(NH,10); if(LNN<0) Ig=Ib=Ir=Iaka; else { Id=Kd*LNN*Ilight; Is=Ks*NHn*Ilight; Ig=Ib=Ir=Iaka+Id+Is+30; } if(Ib>250) Ib=Ig=Ir=250; SetPixel(hDC,i,Ycenter+j,PALETTERGB(Ir,Ig,Ib)); } } x0 = Xcenter -R; y0=High*(t)/2.0; Ax=(PointX[5]-PointX[3])/(R/2.0);Ay=(PointY[5]-PointY[3])/(R/2.0); Az=(PointZ[5]-PointZ[3])/(R/2.0);Bx=(PointX[9]-PointX[7])/(R/2.0); By=(PointY[9]-PointY[7])/(R/2.0);Bz=(PointZ[9]-PointZ[7])/(R/2.0); for(i=0;i<=R/2;i++) { y1=i*(t)/2.0+Ycenter; Cx=PointX[3]+Ax*i;Cy=PointY[3]+Ay*i;Cz=PointZ[3]+Az*i; Dx=PointX[7]+Bx*i;Dy=PointY[7]+By*i;Dz=PointZ[7]+Bz*i; length=square(Cx,Cy,Cz); Cx=Cx/length;Cy=Cy/length;Cz=Cz/length; length=square(Dx,Dy,Dz); Dx=Dx/length;Dy=Dy/length;Dz=Dz/length; for(j=0;j<=y0;j++) { I[1]=Cx+(Dx-Cx)*j/y0; I[2]=Cy+(Dy-Cy)*j/y0; I[3]=(Dz-Cz)*j/y0+Cz; length=square(I[1],I[2],I[3]); I[1]=I[1]/length;I[2]=I[2]/length;I[3]=I[3]/length; LNN =I[1]*Lxn+I[2]*Lyn+I[3]*Lzn; NH = I[1]*Vx+I[2]*Vy+I[3]*Vz; NHn = pow(NH,10); if(LNN<0) Ig=Ib=Ir=Iaka; else { Id=Kd*LNN*Ilight; Is=Ks*NHn*Ilight; Ig=Ib=Ir=Iaka+Id+Is+30; } if(Ib>250) Ib=Ig=Ir=250; SetPixel(hDC,x0+i,y1+j,PALETTERGB(Ir,Ig,Ib)); } } x0 = Xcenter - R/2; y1 = Ycenter + R*(t)/4.0; Ax=(PointX[6]-PointX[5])/R;Ay=(PointY[6]-PointY[5])/R; Az=(PointZ[6]-PointZ[5])/R;Bx=(PointX[10]-PointX[9])/R; By=(PointY[10]-PointY[9])/R;Bz=(PointZ[10]-PointZ[9])/R; for(i=0;i<=R;i++) { Cx=PointX[5]+Ax*i;Cy=PointY[5]+Ay*i;Cz=PointZ[5]+Az*i; Dx=PointX[9]+Bx*i;Dy=PointY[9]+By*i;Dz=PointZ[9]+Bz*i; length=square(Cx,Cy,Cz); Cx=Cx/length;Cy=Cy/length;Cz=Cz/length; length=square(Dx,Dy,Dz); Dx=Dx/length;Dy=Dy/length;Dz=Dz/length; for(j=0;j<=y0;j++) { I[1]=Cx+(Dx-Cx)*j/y0; I[2]=Cy+(Dy-Cy)*j/y0; I[3]=(Dz-Cz)*j/y0+Cz; length=square(I[1],I[2],I[3]); I[1]=I[1]/length;I[2]=I[2]/length;I[3]=I[3]/length; LNN =I[1]*Lxn+I[2]*Lyn+I[3]*Lzn; NH = I[1]*Vx+I[2]*Vy+I[3]*Vz; NHn = pow(NH,10); if(LNN<0) Ig=Ib=Ir=Iaka; else { Id=Kd*LNN*Ilight; Is=Ks*NHn*Ilight; Ig=Ib=Ir=Iaka+Id+Is+30; } if(Ib>250) Ib=Ig=Ir=250; SetPixel(hDC,i+x0,y1+j,PALETTERGB(Ir,Ig,Ib)); } } x0 = Xcenter + R/2; Ax =(PointX[4]-PointX[6])/(R/2.0);Ay=(PointY[4]-PointY[6])/(R/2.0); Az=(PointZ[4]-PointZ[6])/(R/2.0);Bx =(PointX[8]-PointX[10])/(R/2.0); By=(PointY[8]-PointY[10])/(R/2.0);Bz=(PointZ[8]-PointZ[10])/(R/2.0); for(i=0;i<=R/2;i++) { y1 = (R/2-i)*(t)/2+Ycenter; Cx = PointX[6]+Ax*i;Cy=PointY[6]+Ay*i;Cz=PointZ[6]+Az*i; Dx = PointX[10]+Bx*i;Dy=PointY[10]+By*i;Dz=PointZ[10]+Bz*i; length=square(Cx,Cy,Cz); Cx=Cx/length;Cy=Cy/length;Cz=Cz/length; length=square(Dx,Dy,Dz); Dx=Dx/length;Dy=Dy/length;Dz=Dz/length; for(j=0;j<=y0;j++) { I[1]=Cx+(Dx-Cx)*j/y0; I[2]=Cy+(Dy-Cy)*j/y0; I[3]=(Dz-Cz)*j/y0+Cz; length=square(I[1],I[2],I[3]); I[1]=I[1]/length;I[2]=I[2]/length;I[3]=I[3]/length; LNN =I[1]*Lxn+I[2]*Lyn+I[3]*Lzn; NH = I[1]*Vx+I[2]*Vy+I[3]*Vz; NHn = pow(NH,10); if(LNN<0) Ig=Ib=Ir=Iaka; else { Id=Kd*LNN*Ilight; Is=Ks*NHn*Ilight; Ig=Ib=Ir=Iaka+Id+Is+30; } if(Ib>250) Ib=Ig=Ir=250; SetPixel(hDC,i+x0,y1+j,PALETTERGB(Ir,Ig,Ib)); } } } int RayTracing(double sx,double sy,double sz, double dx,double dy,double dz, int depth, double Lx[5],double Ly[5],double Lz[5], long Ilight[5], PRGB pRGB, double BallX[5], double BallY[5], double BallZ[5], double R[5],double ks[5],double kp[5],int Refractionflag ) { RGB Mid,BK; double jx,jy,jz,fx,fy,fz,KS,KP,COSR,Oc,length; double rx,ry,rz,px,py,pz,COSP,min_t,mrx,mry; double Hx[5],Hy[5],Hz[5]; int l,k,i,sign_dx,sign_dy,sign_dz; int flag ; int ui,uj; double LN,NH,NHn,Kd; unsigned int Id,Is; unsigned int sumIr,sumIg,sumIb; BK.red = BK.green = BK.blue = 255; Mid.red = Mid.green = Mid.blue = 0; KP = KS = 0; pRGB->red = pRGB->green = pRGB->blue = 0; if(depth <1 ) return ; min_t = 30000.0; flag = 0; for( i = 1; i < 5; i++) { rx=(sx-BallX[i]); ry=(sy-BallY[i]); rz=(sz-BallZ[i]); COSR = rx*rx+ry*ry+rz*rz-R[i]*R[i]; COSP = 2*(dx*rx+dy*ry+dz*rz); mry = COSP*COSP-4*COSR; if(mry>=0) { mrx=sqrt(mry); px= (mrx-COSP)/2.0; py= (-mrx-COSP)/2.0; if(fabs(px)<ERROR) px=0.0; if(fabs(py)<ERROR) py=0.0; if(px>0 || py>0 ) { if(px >0) pz = px; if((py>0)&&(pz>= py)) pz=py; if(min_t>pz) { flag = 1; min_t = pz; jx=sx+min_t*dx; jy=sy+min_t*dy; jz=sz+min_t*dz; fx= (jx-BallX[i])/R[i]; fy= (jy-BallY[i])/R[i]; fz= (jz-BallZ[i])/R[i]; KS=ks[i]; KP=kp[i]; } } } } if(!flag) { sign_dx = dx*1000; sign_dy = dy*1000; sign_dz = dz*1000; if(sign_dx<0 || sign_dy<0 || sign_dz<0) { if(sign_dx < 0 ) { px=-sx/dx; min_t=px; } if(sign_dy < 0 ) { py=-sy/dy; if( min_t>py) min_t = py; } if(sign_dz < 0 ) { pz=-sz/dz; if( min_t>pz) min_t = pz; } jx=sx+min_t*dx; jy=sy+min_t*dy; jz=sz+min_t*dz; } else return 1; } flag=jx*1000; if(flag==0) { pRGB->red = 255; pRGB->green = 220; pRGB->blue = 255; if ( //这里是文字 HSS (jz<250 && jz>100 && jy>50 && jy<75 ) //h ||(jz>175 && jz<200 && jy>=75 && jy<100)//h ||(jz<250 && jz>100 && jy>=100 && jy<125)//h ||(jz<250 && jz>225 && jy>=150 && jy<225)//s1- ||(jz<200 && jz>175 && jy>=150 && jy<225)//s1- ||(jz<125 && jz>100 && jy>=150 && jy<225)//s1- ||(jz<250 && jz>175 && jy>=200 && jy<225)//s1| ||(jz<175 && jz>100 && jy>=150 && jy<175)//s1| ||(jz<250 && jz>225 && jy>=250 && jy<325)//s2- ||(jz<200 && jz>175 && jy>=250 && jy<325)//s2- ||(jz<125 && jz>100 && jy>=250 && jy<325)//s2- ||(jz<250 && jz>175 && jy>=300 && jy<325)//s2| ||(jz<175 && jz>100 && jy>=250 && jy<275)//s2| ) { pRGB->red = 0; pRGB->green = 0; pRGB->blue = 200; } return 1; } flag=jy*1000; if(flag==0) { pRGB->red =255; pRGB->green = 255; pRGB->blue = 200; if ( //这里是文字DUDU (jz<250 && jz>100 && jx>10 && jx<35 )//d1 ||(pow(jz-175,2)+pow(jx-35,2)<73*73)&& jx>35//d1 && (pow(jz-175,2)+pow(jx-35,2)>50*50)//d1 ||(jz>100 && jz<175 && jx>=110 && jx<135)//u1| ||(jz>100 && jz<175 && jx>=160 && jx<185)//u1| ||(jz>100 && jz<125 && jx>=110 && jx<185)//u1- ||(pow(jz-150,2)+pow(jx-235,2)<47*47)//d2 &&(pow(jz-150,2)+pow(jx-235,2)>23*23)//d2 ||(jz>100 && jz<250 && jx>=260 && jx<285)//d2 ||(jz>100 && jz<175 && jx>=290 && jx<315)//u2| ||(jz>100 && jz<175 && jx>=340 && jx<365)//u2| ||(jz>100 && jz<125 && jx>=290 && jx<365)//u2- ) { pRGB->red = 0; pRGB->green = 200; pRGB->blue = 0; } return 1; } flag=jz*1000; if(flag==0) { //这里是在背景中添加心形图案 pRGB->red = 200; pRGB->green = 255; pRGB->blue = 255; uj=(int)(jx/100); ui=(int)(jy/100); if(jx-(int)(jx/100)*100<50 && jy-(int)(jy/100)*100<50) { pRGB->red=200; pRGB->green = 0; pRGB->blue = 0; } else if( uj!=0 ) { if(pow(jx-uj*100-25,2)+pow(jy-ui*100-100,2)<pow(25,2)) { pRGB->red=200; pRGB->green = 0; pRGB->blue = 0; } else if(ui!=0 && pow(jx-uj*100-50,2)+pow(jy-ui*100-25,2)<pow(25,2)) { pRGB->red=200; pRGB->green = 0; pRGB->blue = 0; } } return 1; } if(Refractionflag == 0) { for(i=1;i<5;i++) { length=square((Lx[i]+dx),(Ly[i]+dy),(Lz[i]+dz)); Hx[i]=(Lx[i]+dx)/length; Hy[i]=(Ly[i]+dy)/length; Hz[i]=(Lz[i]+dz)/length; } sumIr = sumIg = sumIb = 0; for( i = 1;i < 5; i++) { LN=fx*Lx[i]+fy*Ly[i]+fz*Lz[i]; if(LN>0) { NH=Hx[i]*fx+Hy[i]*fy+Hz[i]*fz; NHn=pow(NH,10); } if(LN<0) { Mid.red=0; Mid.green=0; Mid.blue=0; } else { Id=(1-KS)*LN*Ilight[i]; Is=KS*NHn*Ilight[i]; Mid.red=Mid.blue=Mid.green=Id+Is; } sumIr += Mid.red; sumIg += Mid.green; sumIb += Mid.blue; } Mid.red = sumIr ; Mid.green = sumIg ; Mid.blue = sumIb ; COSR=-(fx*dx+fy*dy+fz*dz); rx=dx+2*fx*fabs(COSR); ry=dy+2*fy*fabs(COSR); rz=dz+2*fz*fabs(COSR); RayTracing(jx,jy,jz,rx,ry,rz,depth-1, Lx,Ly,Lz,Ilight,pRGB, BallX,BallY,BallZ,R,ks,kp,0); Mid.red += (0.4*pRGB->red); Mid.green += (0.4*pRGB->green); Mid.blue += (0.4*pRGB->blue); flag=100*KP; if(flag != 0) { COSR=-(fx*dx+fy*dy+fz*dz); COSP=sqrt(1-KP*KP*(1-COSR*COSR)); px=KP*dx-(COSP-KP*COSR)*fx; py=KP*dy-(COSP-KP*COSR)*fy; pz=KP*dz-(COSP-KP*COSR)*fz; RayTracing(jx,jy,jz,px,py,pz,depth-1, Lx,Ly,Lz,Ilight,pRGB, BallX,BallY,BallZ,R,ks,kp,2); Mid.red += (0.65*pRGB->red); Mid.green += (0.65*pRGB->green); Mid.blue += (0.65*pRGB->blue); } } if (Refractionflag == 1 ) { RayTracing(jx,jy,jz,dx,dy,dz,depth-1, Lx,Ly,Lz,Ilight,pRGB, BallX,BallY,BallZ,R,ks,kp,0); Mid.red += (0.65*pRGB->red); Mid.green += (0.65*pRGB->green); Mid.blue += (0.65*pRGB->blue); } if (Refractionflag == 2 ) { flag=100*KP; if(flag != 0) { KP=1/KP; fx = -fx; fy = -fy; fz = -fz; COSR=-(fx*dx+fy*dy+fz*dz); if(acos(COSR)<asin(1/KP)) { COSP=sqrt(1-KP*KP*(1-COSR*COSR)); px=KP*dx-(COSP-KP*COSR)*fx; py=KP*dy-(COSP-KP*COSR)*fy; pz=KP*dz-(COSP-KP*COSR)*fz; RayTracing(jx,jy,jz,px,py,pz,depth-1, Lx,Ly,Lz,Ilight,pRGB, BallX,BallY,BallZ,R,ks,kp,0); } else { px=dx+2*fx*fabs(COSR); py=dy+2*fy*fabs(COSR); pz=dz+2*fz*fabs(COSR); RayTracing(jx,jy,jz,px,py,pz,depth-1, Lx,Ly,Lz,Ilight,pRGB, BallX,BallY,BallZ,R,ks,kp,2); } Mid.red += (0.65*pRGB->red); Mid.green += (0.65*pRGB->green); Mid.blue += (0.65*pRGB->blue); } } pRGB->red = Mid.red; pRGB->green = Mid.green; pRGB->blue = Mid.blue; return (0) ; } //Ray Tracing void CGEWork4(HDC hDC) { double x,y,xbegin,ybegin,zbegin,dx,dy,dz,LX,LY,LZ,length; double o1,o2,o3,sum0,sum1; double Lx[5],Ly[5],Lz[5]; double R[5],BallX[5],BallY[5],BallZ[5]; double Ks[5],Kp[5]; double Tx[4][4],Ty[4][4],Tz[4][4],P[4][4],A[4],A1[4],B[4],B1[4]; long Ilight[5]; RGB RGB_VALUE; PRGB pRGB; int MAXDEPTH,i,j,Xcent,Ycent; pRGB = &RGB_VALUE; /* define ball‘s size . location . Ks . Kp */ R[1]= 50; BallX[1]=80;BallY[1]=80;BallZ[1]=80;Ks[1]=0.9;Kp[1]=0.0; R[2]= 70; BallX[2]=250;BallY[2]=130;BallZ[2]=100;Ks[2]=0.9;Kp[2]=0.0; R[3]= 90; BallX[3]=120;BallY[3]=220;BallZ[3]=170;Ks[3]=0.9;Kp[3]=0.95; R[4]= 120; BallX[4]=370;BallY[4]=350;BallZ[4]=75;Ks[4]=0.9;Kp[4]=0.9; /* define light‘s direction and brightness */ Ilight[1] = 55; Ilight[2] = 55; Ilight[3] = 55; Ilight[4] = 55; LX = LY = LZ = 0.57735; Lx[1] = LX /square(LX,LY,LZ); Ly[1] = LY /square(LX,LY,LZ); Lz[1] = LZ /square(LX,LY,LZ); LX=LY=2.504975;LZ=-0.60; Lx[2] = LX /square(LX,LY,LZ); Ly[2] = LY /square(LX,LY,LZ); Lz[2] = LZ /square(LX,LY,LZ); LX=LZ=3.704975;LY=-0.60; Lx[3] = LX /square(LX,LY,LZ); Ly[3] = LY /square(LX,LY,LZ); Lz[3] = LZ /square(LX,LY,LZ); LZ=LY=3.704975; LX=-0.60; Lx[4] = LX /square(LX,LY,LZ); Ly[4] = LY /square(LX,LY,LZ); Lz[4] = LZ /square(LX,LY,LZ); MAXDEPTH=4; Xcent = 350; Ycent = 260; o1 =0; o2 =3.1415926 / 4.0; o3 =3.1415926 / 4.0; for (i = 0;i<4;i++) for(j=0;j<4;j++) { if(i!=j) { Tx[i][j] = 0.0; Ty[i][j] = 0.0; Tz[i][j] = 0.0; P[i][j] = 0.0; } else { Tx[i][j] = 1.0; Ty[i][j] = 1.0; Tz[i][j] = 1.0; P[i][j] = 1.0;} } Tx[1][1] = Tx[2][2]=cos(o1); Tx[1][2] = sin(o1); Tx[2][1] = -sin(o1); Ty[0][0] = Ty[2][2]=cos(o2); Ty[2][0] = sin(o2); Ty[0][2] = -sin(o2); Tz[1][1] = Tz[0][0]=cos(o3); Tz[0][1] = sin(o3); Tz[1][0] = -sin(o3); P[3][0] = 500; P[3][1] = 500; P[3][2] = 500; for(y=-260;y<250;y++) { for(x=-350;x<500;x++) { B[0] = A[0] = x; B[1] = A[1] = y; A[2] = 1; B[2] = 0; B[3] = A[3] = 1; for(i=0;i<4;i++) { sum0 = sum1 = 0.0; for(j=0;j<4;j++) { sum0 = sum0+A[j]*Ty[j][i]; sum1 = sum1+B[j]*Ty[j][i]; } A1[i] = sum0; B1[i] = sum1; } for(i=0;i<4;i++) { sum0 = sum1 = 0.0; for(j=0;j<4;j++) { sum0 = sum0+A1[j]*Tz[j][i]; sum1 = sum1+B1[j]*Tz[j][i]; } A[i] = sum0; B[i] = sum1; } for(i=0;i<4;i++) { sum0 = sum1 = 0.0; for(j=0;j<4;j++) { sum0 = sum0+A[j]*Tx[j][i]; sum1 = sum1+B[j]*Tx[j][i]; } A1[i] = sum0; B1[i] = sum1; } for(i=0;i<4;i++) { sum0 = sum1 = 0.0; for(j=0;j<4;j++) { sum0 = sum0+A1[j]* P[j][i]; sum1 = sum1+B1[j]* P[j][i]; } A[i] = sum0; B[i] = sum1; } xbegin = A[0]; ybegin = A[1]; zbegin = A[2]; dx = B[0] - A[0]; dy = B[1] - A[1]; dz = B[2] - A[2]; length = square(dx,dy,dz); dx = dx/length; dy = dy/length; dz = dz/length; RayTracing( xbegin,ybegin,zbegin, dx,dy,dz, // direction MAXDEPTH, // depth control Lx,Ly,Lz, // light direction Ilight, // brightness of light pRGB, // return RGB values BallX,BallY,BallZ,R, // Ball location and its size Ks,Kp, // Each ball‘s Ks and Kp 0); // Refraction control SetPixel(hDC,x+Xcent,y+Ycent,PALETTERGB(pRGB->red,pRGB->green,pRGB->blue)); } } } //Texture void CGEWork55(HDC hDC) { int Ilight,Ir,Ig,Ib,Ia; double Hx,Hy,Hz,Lx,Ly,Lz,xn,yn,zn,LN,NHn,NH; double Id,Is,x,y,z,Ka; double kd; double ks,Xcenter,Ycenter,R; int n; double PI=3.1415926; double dis_to_length; Ilight = 200; Ia =320; Ka = 0.2; Lx=Ly=-0.57735; Lz=0.57735; Hx = -0.57735; Hy = -0.57735; Hz = 0.57735; kd=0; R=100; Xcenter=150; Ycenter=150; SetLUT_GRAY(hDC); for(y = (-R);y <= R ; y++) for( x = (-R);x <= R;x++ ) { if (x*x+y*y <= R*R) { z=sqrt(R*R-x*x-y*y); xn=x/R; yn=y/R; zn=z/R; if (x>0) { dis_to_length=pow(pow(x,2)+pow(z,2),.5)*sin(PI/4-atan(z/x)); kd=0.7+.2*sin(2*dis_to_length)+0.05*sin(x); } else if (x<0) { dis_to_length=pow(pow(x,2)+pow(z,2),.5)*sin(PI/4-atan(z/x)); kd=0.7+.2*sin(-2*dis_to_length)+0.05*sin(x); } else { dis_to_length=pow(pow(x,2)+pow(z,2),.5)*sin(PI/4); kd=0.7+.2*sin(-2*dis_to_length)+0.05*sin(x); } ks=.01; // ks=1-kd; LN=xn*Lx+yn*Ly+zn*Lz; if(LN>0) { NH=Hx*xn+Hy*yn+Hz*zn; NHn=pow(NH,n); } if(LN<0) { Ig=Ia*Ka; if (Ig>240)Ig=240; Ir=Ib=Ig; } else { Id=kd*LN*Ilight; Is=ks*NHn*Ilight; Ig=(Ka*Ia+Id+Is); if (Ig>240)Ig=240; Ir=Ib=Ig; } SetPixel(hDC,Xcenter+x,Ycenter+y,PALETTERGB(Ir, Ig, Ib)); } } } //Texture void CGEWork5(HDC hDC) { int Ilight,Ir,Ig,Ib,Ia; double Hx,Hy,Hz,Lx,Ly,Lz,xn,yn,zn,LN,NHn,NH; double Id,Is,x,y,z,Ka,xi,yi,zi; double kd,alpha; double ks,Xcenter,Ycenter,R; int n; double PI=3.1415926; double dis_to_root; float G0=13; int grain; int Kz=25; Ilight = 200; Ia =300; Ka = 0.2; Lx=.8; Ly=.56; Lz=.7; dis_to_root=sqrt(Lx*Lx+Ly*Ly+Lz*Lz); Lx=Lx/dis_to_root; Ly=Ly/dis_to_root; Lz=Lz/dis_to_root; Hx = -0.57735; Hy = -0.57735; Hz = 0.57735; kd=0; R=100; Xcenter=150; Ycenter=250; SetLUT_GRAY(hDC); xn=0; yn=0; zn=1; for(y = -HalfEdge;y <=HalfEdge ; y++) for( x = -HalfEdge;x <= HalfEdge;x++ ) { z=0; dis_to_root=pow(pow(x,2)+pow(y,2),.5); if(x!=0) alpha=atan(y/x); else alpha=PI/2; R =dis_to_root + 1.0*sin(Kal*alpha)+.4*sin(3*Kal*alpha); grain = R-(int)(R / G0)*G0; if (grain < G0/3) kd = light; else kd = dark; // ks=.01; ks=1-kd; LN=xn*Lx+yn*Ly+zn*Lz; if(LN>0) { NH=Hx*xn+Hy*yn+Hz*zn; NHn=pow(NH,n); } if(LN<0) { Ig=Ia*Ka; if (Ig>255)Ig=255; Ib=Ir=Ig; } else { Id=kd*LN*Ilight; Is=ks*NHn*Ilight; Ig=(Ka*Ia+Id+Is); if (Ig>255)Ig=255; Ib=Ir=Ig; } SetPixel(hDC,Xcenter+x,Ycenter+y,PALETTERGB(Ir, Ig, Ib)); } xn=1; yn=0; zn=0; for(yi = 0;yi <=HalfEdge*2+Length*.8; yi++) for( xi = 0;xi <=Length*.8;xi++ ) { if (yi>xi) if (yi<xi+2*HalfEdge+1) if (xi<Length*cos(PI/4)) { y=yi-xi-HalfEdge; z=xi/cos(PI/4); x=HalfEdge; dis_to_root=pow(pow(x,2)+pow(y,2),.5); if(x!=0) alpha=atan(y/x); else alpha=PI/2; R =dis_to_root +z/(.8*Kz)+ 1.0*sin(Kal*alpha+z/Kz)+.4*sin(3*Kal*alpha); grain = R-(int)(R / G0)*G0; if (grain < G0/3) kd = light; else kd = dark; // ks=.01; ks=1-kd; LN=xn*Lx+yn*Ly+zn*Lz; if(LN>0) { NH=Hx*xn+Hy*yn+Hz*zn; NHn=pow(NH,n); } if(LN<0) { Ig=Ia*Ka; if (Ig>240)Ig=240; Ir=Ib=Ig; } else { Id=kd*LN*Ilight; Is=ks*NHn*Ilight; Ig=(Ka*Ia+Id+Is); if (Ig>240)Ig=240; Ir=Ib=Ig;//(Id+Is); } SetPixel(hDC,Xcenter+HalfEdge+xi,Ycenter+HalfEdge-yi,PALETTERGB(Ir, Ig, Ib)); } } xn=0; yn=1; zn=0; for(yi = 0;yi <=Length*.8 ; yi++) for( xi = 0;xi <= HalfEdge*2+Length*.8;xi++ ) { if (yi<xi) if (yi>xi-2*HalfEdge) if (yi<Length*cos(PI/4)) { x=xi-yi-HalfEdge; z=yi/cos(PI/4); y=HalfEdge; dis_to_root=pow(pow(x,2)+pow(y,2),.5); if(x!=0) alpha=atan(y/x); else alpha=PI/2; R =dis_to_root + z/(.8*Kz)+1.0*sin(Kal*alpha+z/Kz)+.5*sin(3*Kal*alpha); grain = R-(int)(R / G0)*G0; if (grain < G0/3) kd = light; else kd = dark; // ks=.01; ks=1-kd; LN=xn*Lx+yn*Ly+zn*Lz; if(LN>0) { NH=Hx*xn+Hy*yn+Hz*zn; NHn=pow(NH,n); } if(LN<0) { Ig=Ia*Ka; if (Ig>240)Ig=240; Ir=Ib=Ig; } else { Id=kd*LN*Ilight; Is=ks*NHn*Ilight; Ig=(Ka*Ia+Id+Is); if (Ig>240)Ig=240; Ir=Ib=Ig;//(Id+Is); } SetPixel(hDC,Xcenter-HalfEdge+xi,Ycenter-HalfEdge-yi,PALETTERGB(Ir, Ig, Ib)); } } }
关于光线跟踪算法,可以参考碧云涛在雷锋网的文章《视觉技术的圣杯:光线追踪如何再现真实世界?》
时间: 2024-10-01 07:56:54