Spherical Harmonics Lighting的代码实现(基于OpenGL)
2012-05-31 16:52
447 查看
1、二维空间的勒让德多项式
勒让德多项式定义在[-1,1]范围内,其递归式是
下面这个函数的参数是给定的x,给定的l和m,其中l必须是正整数,而且m在[-l,l]范围内。
下面是利用勒让德多项式进行绘制
2、三维空间的Spherical Harmonics
在三维空间下绘制SH基函数,使用的是球坐标。
下面将会引进几个函数
绘制SH的函数传递theta和phi值循环调用evaluateSH(),计算返回值,之后使用四边形绘制网格。
3、使用SH基函数重构复合函数
我们已经创建了SH的基函数,现在要使用它们来重构一个给定的复合函数(也就是求出因子c),这个复合函数将会被用来描述光线在半球上的分布。
下面将会引进两个函数。
接下来还要定义一些数据结构。首先定义一个结构SHVector3d,容纳向量或顶点的笛卡尔坐标;同样定义一个结构,容纳分层取样(stratified sampling)的信息,即单位球坐标,样品的三维坐标,和SH因子。
勒让德多项式定义在[-1,1]范围内,其递归式是
下面这个函数的参数是给定的x,给定的l和m,其中l必须是正整数,而且m在[-l,l]范围内。
//勒让德多项式计算方法 double ALPStd(float x,int l,int m) { if(l==m) //doubleFactorial(x)计算x!! return (pow(-1,m)*doubleFactorial(2*m-1)*pow(sqrt(l-x*x),m)); if(l==m+1) return (x*(2*m+1)*ALPStd(x,m,m)); return ((x*(2*l-1)*ALPStd(x,l-1,m)-(l+m-1)*ALPStd(x,l-2,m))/(l-m)); }
int doubleFactorial(int x) { int result; if(x==0 || x==-1) return 1; result=x; while((x-=2)>0) result*=x; return result; }
下面是利用勒让德多项式进行绘制
void display() { glColor3f(r,v,b); glBegin(GL_LINE_STRIP); for(i=0;i<=samples,++i) { glVertex2f(x,ALPStd(x,l,m)); x+=step; } glEnd(); }
2、三维空间的Spherical Harmonics
在三维空间下绘制SH基函数,使用的是球坐标。
下面将会引进几个函数
//计算整数的阶乘,即x!=x*(x-1)*(x-2)*...*2*1 int factorial(int); //给定带宽l和m,计算阶乘因子K double evaluateK(int,int); //给定带宽l和m,以及球坐标的两个角度,计算SH基函数的值 double evaluateSH(int,int,double,double);
int factorial(int x) { int result; if(x==0 || x==-1) return 1; result=x; while((x-=1)>0) result*=x; return result; } double evaluateK(int l,int m) { double result; result=(2.0*l+1.1)*factorial(l-m)/(4*PI*factorial(l+m)); result=sqrt(result); return result; } double evaluateSH(int l,int m,double theta,double phi) { double SH=0.0; if(m==0) SH=evaluateK(l,0)*ALPStd(cos(theta),l,0); else if(m>0) SH=sqrt(2)*evaluateK(l,m)*cos(m*phi)*ALPStd(cos(theta),l,m); else SH=sqrt(2)*evaluateK(l,-m)*sin(-m*phi)*ALPStd(cos(theta),l,-m); return SH; }
绘制SH的函数传递theta和phi值循环调用evaluateSH(),计算返回值,之后使用四边形绘制网格。
3、使用SH基函数重构复合函数
我们已经创建了SH的基函数,现在要使用它们来重构一个给定的复合函数(也就是求出因子c),这个复合函数将会被用来描述光线在半球上的分布。
下面将会引进两个函数。
//计算spherical stratified sampling sphericalStratifiedSampling(); //将输入的函数投影到SH基上,即计算因子 SHProjectionSphericalFunction();
接下来还要定义一些数据结构。首先定义一个结构SHVector3d,容纳向量或顶点的笛卡尔坐标;同样定义一个结构,容纳分层取样(stratified sampling)的信息,即单位球坐标,样品的三维坐标,和SH因子。
typedef struct { double x,y,z; }SHVector3d; typedef struct { SHVector3d sph; SHVector3d vec; double *coeff; }SHSample; void sphericalStratifiedSampling(SHSample* samples,int sqrtNumSamples, int nBands) { //Indexes int a,b,index,l,m; //Loop Index int i=0; //Inverse of the number of samples double invNumSamples=1.0/sqrtNumSamples; //Cartesian and spherical coordinates double x,y,theta,phi; //Loop on width of grid for(a=0;a<sqrtNumSamples,++a) { //Loop on height of grid for(b=0;b<sqrtNumSamples;++b) { //jitter center of current cell x=(a+rnd())*invNumSamples; y=(b+rnd())*invNumSamples; //Calculate corresponding spherical angles theta=2.0*acos(sqrt(1.0-x)); phi=2.0*PI*y; //Sample spherical coordinates samples[i].sph.x=theta; samples[i].shp.y=phi; samples[i].shp.z=1.0; //Sample normal samples[i].vec.x=sin(theta)*cos(phi); samples[i].vec.y=sin(theta)*sin(phi); samples[i].vec.z=cos(theta); //Calculate SH coefficients of current sample for(l=0;l<nBands;++l) { for(m=-l;m<=l;++m) { index=l*(l+1)+m; samples[i].coeff[index]=evaluateSH(l,m,theta,phi); } } ++i; } } } //复合函数的定义 typedef double (*SphericalFunction)(double theta,double phi); void SHProjectSphericalFunction(SphericalFunction mySPFunc, SHSample* samples,double *result,int numSamples,int numCoeffs) { //Weighting factor double dWeight=4.0*PI; double factor=dWeight/numSamples; //Spherical angles double theta,phi; //Loop indexes int i,n; //Loop through all samples for(i=0;i<numSamples;++i) { //Get current sample spherical coordinates theta=samples[i].sph.x; phi=samples[i].sph.y; //Update SH coefficients for(n=0;n<numCoeffs;++n) { result +=mySPFunc(theta,phi)*samples[i].coeff ; } } for(n=0;n<numCoeffs;++n) result *=factor; }
相关文章推荐
- Spherical Harmonics Lighting的代码实现(基于OpenGL)
- Spherical Harmonics Lighting代码实现(续)
- Spherical Harmonics Lighting代码实现(续)
- 基于DotNetOpenAuth的OAuth实现示例代码: 获取access token
- Hadoop基于Protocol Buffer的RPC实现代码分析-Server端
- 看opengl写代码(3) 实现矩阵的旋转
- 基于jQuery的360图片展示实现代码
- 基于JQuery的一句代码实现表格的简单筛选
- android平台基于sip协议的网络电话实现(知识点及核心代码)
- JAVA实现基于可视化的代码,可以实现商品总计,很方便。
- 《推荐系统实践》——基于物品的协同过滤算法(代码实现)
- 基于JS实现EOS隐藏错误提示层代码
- java实现基于TCP协议带界面的多人聊天代码
- 基于nginx的C模块代码实现获取POST请求参数并回传给客户端
- 基于Jquery的动态添加控件并取值的实现代码
- 基于纯Java代码的Spring容器和Web容器零配置的思考和实现(1) - 数据源与事务管理
- 基于OpenGL动画设计研究与实现
- 基于Spark实现随机森林代码
- 基于jQuery实现交互体验社会化分享代码附源码下载
- 基于jQuery的360图片展示实现代码