好吧,一个古老且已经回答的问题,但我想添加我的解决方案以供初学者考虑。玩了很长时间的大气散射和 GLSL,开发了这个 VEEERRRYYY 大气散射的简化版本(如果动画停止刷新页面或以更堕落的方式查看GIF ):
[
- 行星是和椭球体(中心
x,y,
z 和半径rx,ry,rz
)
- 大气也是椭球体(相同但大气高度更大)
- 所有渲染都正常完成,但最重要的是为近观察者星球添加了 1 个通道
- 该通行证是覆盖整个屏幕的单四边形
- 在片段内部,它计算像素射线与这两个椭球的交点
- 取可见部分(不是在后面,不是在地面之后)
- 计算大气层内的射线长度
- 通过光线长度将原始颜色扭曲为
r,g,b
缩放参数的函数(类似于沿路径积分)
- 一些颜色是给定的......
- 极大地影响颜色,因此只需几个属性就可以模拟不同的气氛
- 它在大气层内外(从远处)都能很好地工作
- 可以添加近恒星作为光源(我使用最大 3 星系统)
结果令人惊叹,请参见下图:
顶点:
/* SSH GLSL Atmospheric Ray light scattering ver 3.0
glEnable(GL_BLEND);
glBlendFunc(GL_ONE,GL_ONE);
use with single quad covering whole screen
no Modelview/Projection/Texture matrixes used
gl_Normal is camera direction in ellipsoid space
gl_Vertex is pixel in ellipsoid space
gl_Color is pixel pos in screen space <-1,+1>
const int _lights=3;
uniform vec3 light_dir[_lights]; // direction to local star in ellipsoid space
uniform vec3 light_col[_lights]; // local star color * visual intensity
uniform vec4 light_posr[_lights]; // local star position and radius^-2 in ellipsoid space
uniform vec4 B0; // atmosphere scattering coefficient (affects color) (r,g,b,-)
[ToDo:]
add light map texture for light source instead of uniform star colide parameters
- all stars and distant planets as dots
- near planets ??? maybe too slow for reading pixels
aspect ratio correction
*/
varying vec3 pixel_nor; // camera direction in ellipsoid space
varying vec4 pixel_pos; // pixel in ellipsoid space
void main(void)
{
pixel_nor=gl_Normal;
pixel_pos=gl_Vertex;
gl_Position=gl_Color;
}
分段:
varying vec3 pixel_nor; // camera direction in ellipsoid space
varying vec4 pixel_pos; // pixel in ellipsoid space
uniform vec3 planet_r; // rx^-2,ry^-2,rz^-2 - surface
uniform vec3 planet_R; // Rx^-2,Ry^-2,Rz^-2 - atmosphere
uniform float planet_h; // atmoshere height [m]
uniform float view_depth; // max. optical path length [m] ... saturation
// lights are only for local stars-atmosphere ray colision to set start color to star color
const int _lights=3;
uniform vec3 light_dir[_lights]; // direction to local star in ellipsoid space
uniform vec3 light_col[_lights]; // local star color * visual intensity
uniform vec4 light_posr[_lights]; // local star position and radius^-2 in ellipsoid space
uniform vec4 B0; // atmosphere scattering coefficient (affects color) (r,g,b,-)
// compute length of ray(p0,dp) to intersection with ellipsoid((0,0,0),r) -> view_depth_l0,1
// where r.x is elipsoid rx^-2, r.y = ry^-2 and r.z=rz^-2
float view_depth_l0=-1.0,view_depth_l1=-1.0;
bool _view_depth(vec3 p0,vec3 dp,vec3 r)
{
float a,b,c,d,l0,l1;
view_depth_l0=-1.0;
view_depth_l1=-1.0;
a=(dp.x*dp.x*r.x)
+(dp.y*dp.y*r.y)
+(dp.z*dp.z*r.z); a*=2.0;
b=(p0.x*dp.x*r.x)
+(p0.y*dp.y*r.y)
+(p0.z*dp.z*r.z); b*=2.0;
c=(p0.x*p0.x*r.x)
+(p0.y*p0.y*r.y)
+(p0.z*p0.z*r.z)-1.0;
d=((b*b)-(2.0*a*c));
if (d<0.0) return false;
d=sqrt(d);
l0=(-b+d)/a;
l1=(-b-d)/a;
if (abs(l0)>abs(l1)) { a=l0; l0=l1; l1=a; }
if (l0<0.0) { a=l0; l0=l1; l1=a; }
if (l0<0.0) return false;
view_depth_l0=l0;
view_depth_l1=l1;
return true;
}
// determine if ray (p0,dp) hits a sphere ((0,0,0),r)
// where r is (sphere radius)^-2
bool _star_colide(vec3 p0,vec3 dp,float r)
{
float a,b,c,d,l0,l1;
a=(dp.x*dp.x*r)
+(dp.y*dp.y*r)
+(dp.z*dp.z*r); a*=2.0;
b=(p0.x*dp.x*r)
+(p0.y*dp.y*r)
+(p0.z*dp.z*r); b*=2.0;
c=(p0.x*p0.x*r)
+(p0.y*p0.y*r)
+(p0.z*p0.z*r)-1.0;
d=((b*b)-(2.0*a*c));
if (d<0.0) return false;
d=sqrt(d);
l0=(-b+d)/a;
l1=(-b-d)/a;
if (abs(l0)>abs(l1)) { a=l0; l0=l1; l1=a; }
if (l0<0.0) { a=l0; l0=l1; l1=a; }
if (l0<0.0) return false;
return true;
}
// compute atmosphere color between ellipsoids (planet_pos,planet_r) and (planet_pos,planet_R) for ray(pixel_pos,pixel_nor)
vec3 atmosphere()
{
const int n=8;
const float _n=1.0/float(n);
int i;
bool b0,b1;
vec3 p0,p1,dp,p,c,b;
// c - color of pixel from start to end
float l0,l1,l2,h,dl;
c=vec3(0.0,0.0,0.0);
b0=_view_depth(pixel_pos.xyz,pixel_nor,planet_r);
if ((b0)&&(view_depth_l0>0.0)&&(view_depth_l1<0.0)) return c;
l0=view_depth_l0;
b1=_view_depth(pixel_pos.xyz,pixel_nor,planet_R);
l1=view_depth_l0;
l2=view_depth_l1;
dp=pixel_nor;
p0=pixel_pos.xyz;
if (!b0)
{ // outside surface
if (!b1) return c; // completly outside planet
if (l2<=0.0) // inside atmosphere to its boundary
{
l0=l1;
}
else{ // throu atmosphere from boundary to boundary
p0=p0+(l1*dp);
l0=l2-l1;
}
// if a light source is in visible path then start color is light source color
for (i=0;i<_lights;i++)
if (light_posr[i].a<=1.0)
if (_star_colide(p0-light_posr[i].xyz,dp,light_posr[i].a))
c+=light_col[i];
}
else{ // into surface
if (l0<l1) b1=false; // atmosphere is behind surface
if (!b1) // inside atmosphere to surface
{
l0=l0;
}
else{ // from atmosphere boundary to surface
p0=p0+(l1*dp);
l0=l0-l1;
}
}
dp*=l0;
p1=p0+dp;
dp*=_n;
/*
p=normalize(p1);
h=0.0; l2=0.0;
for (i=0;i<_lights;i++)
if (light_posr[i].a<=1.0)
{
dl=dot(pixel_nor,light_dir[i]); // cos(ang: light-eye)
if (dl<0.0) dl=0.0;
h+=dl;
dl=dot(p,light_dir[i]); // normal shading
if (dl<0.0) dl=0.0;
l2+=dl;
}
if (h>1.0) h=1.0;
if (l2>1.0) l2=1.0;
h=0.5*(2.0+(h*h));
*/
float qqq=dot(normalize(p1),light_dir[0]);
dl=l0*_n/view_depth;
for (p=p1,i=0;i<n;p-=dp,i++) // p1->p0 path throu atmosphere from ground
{
_view_depth(p,normalize(p),planet_R); // view_depth_l0=depth above atmosphere top [m]
h=exp(view_depth_l0/planet_h)/2.78;
b=B0.rgb*h*dl;
c.r*=1.0-b.r;
c.g*=1.0-b.g;
c.b*=1.0-b.b;
c+=b*qqq;
}
if (c.r<0.0) c.r=0.0;
if (c.g<0.0) c.g=0.0;
if (c.b<0.0) c.b=0.0;
h=0.0;
if (h<c.r) h=c.r;
if (h<c.g) h=c.g;
if (h<c.b) h=c.b;
if (h>1.0)
{
h=1.0/h;
c.r*=h;
c.g*=h;
c.b*=h;
}
return c;
}
void main(void)
{
gl_FragColor.rgb=atmosphere();
}
对不起,但它是我的一个非常古老的来源......应该可能转换为核心配置文件
[编辑 1]抱歉忘记为地球大气添加我的输入散射常数
double view_depth=1000000.0; // [m] ... longer path is saturated atmosphere color
double ha=40000.0; // [m] ... usable atmosphere height (higher is too low pressure)
// this is how B0 should be computed (for real atmospheric scattering with nested volume integration)
// const float lambdar=650.0*0.000000001; // wavelengths for R,G,B rays
// const float lambdag=525.0*0.000000001;
// const float lambdab=450.0*0.000000001;
// double r=1.0/(lambdar*lambdar*lambdar*lambdar); // B0 coefficients
// double g=1.0/(lambdag*lambdag*lambdag*lambdag);
// double b=1.0/(lambdab*lambdab*lambdab*lambdab);
// and these are my empirical coefficients for earth like
// blue atmosphere with my simplified integration style
// images above are rendered with this:
float r=0.198141888310295;
float g=0.465578010163675;
float b=0.862540960504986;
float B0=2.50000E-25;
i=glGetUniformLocation(ShaderProgram,"planet_h"); glUniform1f(i,ha);
i=glGetUniformLocation(ShaderProgram,"view_depth"); glUniform1f(i,view_depth);
i=glGetUniformLocation(ShaderProgram,"B0"); glUniform4f(i,r,g,b,B0);
// all other atributes are based on position and size of planet and are
// pretty straightforward so here is just the earth size i use ...
double r_equator=6378141.2; // [m]
double r_poles=6356754.8; // [m]
[edit2] 3.9.2014 新源代码
我最近有一些时间来实现对我的引擎的缩放,并发现原始源代码从 0.002 AU 以上的距离不是很精确。没有缩放,它只有几个像素,所以什么都看不到,但是缩放所有变化,所以我尽量提高准确性。
经过一些更多的调整后,我发现它可以使用高达 25.0 AU,并且插值伪影高达 50.0-100.0 AU。这是当前硬件的限制,因为我无法将非flat fp64
从顶点传递到片段的插值器。一种解决方法可能是将坐标系变换移动到片段但尚未尝试过。以下是一些变化:
- 新源使用 64 位浮点数
- 并添加
uniform int lights
这是使用过的灯的数量
- B0 含义也有一些变化(它们不再是依赖于波长的常数,而是颜色),因此您需要稍微更改 CPU 代码中的统一值填充。
- 添加了一些性能改进
[顶点]
/* SSH GLSL Atmospheric Ray light scattering ver 3.1
glEnable(GL_BLEND);
glBlendFunc(GL_ONE,GL_ONE_MINUS_SRC_ALPHA);
use with single quad covering whole screen
no Modelview/Projection/Texture matrixes used
gl_Normal is camera direction in ellipsoid space
gl_Vertex is pixel in ellipsoid space
gl_Color is pixel pos in screen space <-1,+1>
const int _lights=3;
uniform int lights; // actual number of lights
uniform vec3 light_dir[_lights]; // direction to local star in ellipsoid space
uniform vec3 light_col[_lights]; // local star color * visual intensity
uniform vec4 light_posr[_lights]; // local star position and radius^-2 in ellipsoid space
uniform vec4 B0; // atmosphere scattering coefficient (affects color) (r,g,b,-)
[ToDo:]
add light map texture for light source instead of uniform star colide parameters
- all stars and distant planets as dots
- near planets ??? maybe too slow for reading pixels
aspect ratio correction
*/
varying vec3 pixel_nor; // camera direction in ellipsoid space
varying vec4 pixel_pos; // pixel in ellipsoid space
varying vec4 pixel_scr; // pixel in screen space <-1,+1>
varying vec3 p_r; // rx,ry,rz
uniform vec3 planet_r; // rx^-2,ry^-2,rz^-2 - surface
void main(void)
{
p_r.x=1.0/sqrt(planet_r.x);
p_r.y=1.0/sqrt(planet_r.y);
p_r.z=1.0/sqrt(planet_r.z);
pixel_nor=gl_Normal;
pixel_pos=gl_Vertex;
pixel_scr=gl_Color;
gl_Position=gl_Color;
}
[分段]
#extension GL_ARB_gpu_shader_fp64 : enable
double abs(double x) { if (x<0.0) x=-x; return x; }
varying vec3 pixel_nor; // camera direction in ellipsoid space
varying vec4 pixel_pos; // pixel in ellipsoid space
varying vec4 pixel_scr; // pixel in screen space
varying vec3 p_r; // rx,ry,rz
uniform vec3 planet_r; // rx^-2,ry^-2,rz^-2 - surface
uniform vec3 planet_R; // Rx^-2,Ry^-2,Rz^-2 - atmosphere
uniform float planet_h; // atmoshere height [m]
uniform float view_depth; // max. optical path length [m] ... saturation
// lights are only for local stars-atmosphere ray colision to set start color to star color
const int _lights=3;
uniform int lights; // actual number of lights
uniform vec3 light_dir[_lights]; // direction to local star in ellipsoid space
uniform vec3 light_col[_lights]; // local star color * visual intensity
uniform vec4 light_posr[_lights]; // local star position and radius^-2 in ellipsoid space
uniform vec4 B0; // atmosphere scattering color coefficients (r,g,b,ambient)
// compute length of ray(p0,dp) to intersection with ellipsoid((0,0,0),r) -> view_depth_l0,1
// where r.x is elipsoid rx^-2, r.y = ry^-2 and r.z=rz^-2
const double view_depth_max=100000000.0; // > max view depth
double view_depth_l0=-1.0, // view_depth_l0 first hit
view_depth_l1=-1.0; // view_depth_l1 second hit
bool _view_depth_l0=false;
bool _view_depth_l1=false;
bool _view_depth(vec3 _p0,vec3 _dp,vec3 _r)
{
dvec3 p0,dp,r;
double a,b,c,d,l0,l1;
view_depth_l0=-1.0; _view_depth_l0=false;
view_depth_l1=-1.0; _view_depth_l1=false;
// conversion to double
p0=dvec3(_p0);
dp=dvec3(_dp);
r =dvec3(_r );
// quadratic equation a.l.l+b.l+c=0; l0,l1=?;
a=(dp.x*dp.x*r.x)
+(dp.y*dp.y*r.y)
+(dp.z*dp.z*r.z);
b=(p0.x*dp.x*r.x)
+(p0.y*dp.y*r.y)
+(p0.z*dp.z*r.z); b*=2.0;
c=(p0.x*p0.x*r.x)
+(p0.y*p0.y*r.y)
+(p0.z*p0.z*r.z)-1.0;
// discriminant d=sqrt(b.b-4.a.c)
d=((b*b)-(4.0*a*c));
if (d<0.0) return false;
d=sqrt(d);
// standard solution l0,l1=(-b +/- d)/2.a
a*=2.0;
l0=(-b+d)/a;
l1=(-b-d)/a;
// alternative solution q=-0.5*(b+sign(b).d) l0=q/a; l1=c/q; (should be more accurate sometimes)
// if (b<0.0) d=-d; d=-0.5*(b+d);
// l0=d/a;
// l1=c/d;
// sort l0,l1 asc
if ((l0<0.0)||((l1<l0)&&(l1>=0.0))) { a=l0; l0=l1; l1=a; }
// exit
if (l1>=0.0) { view_depth_l1=l1; _view_depth_l1=true; }
if (l0>=0.0) { view_depth_l0=l0; _view_depth_l0=true; return true; }
return false;
}
// determine if ray (p0,dp) hits a sphere ((0,0,0),r)
// where r is (sphere radius)^-2
bool _star_colide(vec3 _p0,vec3 _dp,float _r)
{
dvec3 p0,dp,r;
double a,b,c,d,l0,l1;
// conversion to double
p0=dvec3(_p0);
dp=dvec3(_dp);
r =dvec3(_r );
// quadratic equation a.l.l+b.l+c=0; l0,l1=?;
a=(dp.x*dp.x*r)
+(dp.y*dp.y*r)
+(dp.z*dp.z*r);
b=(p0.x*dp.x*r)
+(p0.y*dp.y*r)
+(p0.z*dp.z*r); b*=2.0;
c=(p0.x*p0.x*r)
+(p0.y*p0.y*r)
+(p0.z*p0.z*r)-1.0;
// discriminant d=sqrt(b.b-4.a.c)
d=((b*b)-(4.0*a*c));
if (d<0.0) return false;
d=sqrt(d);
// standard solution l0,l1=(-b +/- d)/2.a
a*=2.0;
l0=(-b+d)/a;
l1=(-b-d)/a;
// alternative solution q=-0.5*(b+sign(b).d) l0=q/a; l1=c/q; (should be more accurate sometimes)
// if (b<0.0) d=-d; d=-0.5*(b+d);
// l0=d/a;
// l1=c/d;
// sort l0,l1 asc
if (abs(l0)>abs(l1)) { a=l0; l0=l1; l1=a; }
if (l0<0.0) { a=l0; l0=l1; l1=a; }
if (l0<0.0) return false;
return true;
}
// compute atmosphere color between ellipsoids (planet_pos,planet_r) and (planet_pos,planet_R) for ray(pixel_pos,pixel_nor)
vec4 atmosphere()
{
const int n=8;
const float _n=1.0/float(n);
int i;
bool b0,b1;
vec3 p0,p1,dp,p,b;
vec4 c; // c - color of pixel from start to end
float h,dl,ll;
double l0,l1,l2;
bool e0,e1,e2;
c=vec4(0.0,0.0,0.0,0.0); // a=0.0 full background color, a=1.0 no background color (ignore star)
b1=_view_depth(pixel_pos.xyz,pixel_nor,planet_R);
if (!b1) return c; // completly outside atmosphere
e1=_view_depth_l0; l1=view_depth_l0; // first atmosphere hit
e2=_view_depth_l1; l2=view_depth_l1; // second atmosphere hit
b0=_view_depth(pixel_pos.xyz,pixel_nor,planet_r);
e0=_view_depth_l0; l0=view_depth_l0; // first surface hit
if ((b0)&&(view_depth_l1<0.0)) return c; // under ground
// set l0 to view depth and p0 to start point
dp=pixel_nor;
p0=pixel_pos.xyz;
if (!b0) // outside surface
{
if (!e2) // inside atmosphere to its boundary
{
l0=l1;
}
else{ // throu atmosphere from boundary to boundary
p0=vec3(dvec3(p0)+(dvec3(dp)*l1));
l0=l2-l1;
}
// if a light source is in visible path then start color is light source color
for (i=0;i<lights;i++)
if (_star_colide(p0.xyz-light_posr[i].xyz,dp.xyz,light_posr[i].a*0.75)) // 0.75 is enlargment to hide star texture corona
{
c.rgb+=light_col[i];
c.a=1.0; // ignore already drawed local star color
}
}
else{ // into surface
if (l1<l0) // from atmosphere boundary to surface
{
p0=vec3(dvec3(p0)+(dvec3(dp)*l1));
l0=l0-l1;
}
else{ // inside atmosphere to surface
l0=l0;
}
}
// set p1 to end of view depth, dp to intergral step
p1=vec3(dvec3(p0)+(dvec3(dp)*l0)); dp=p1-p0;
dp*=_n;
dl=float(l0)*_n/view_depth;
ll=B0.a; for (i=0;i<lights;i++) // compute normal shaded combined light sources into ll
ll+=dot(normalize(p1),light_dir[0]);
for (p=p1,i=0;i<n;p-=dp,i++) // p1->p0 path throu atmosphere from ground
{
// _view_depth(p,normalize(p),planet_R); // too slow... view_depth_l0=depth above atmosphere top [m]
// h=exp(view_depth_l0/planet_h)/2.78;
b=normalize(p)*p_r; // much much faster
h=length(p-b);
h=exp(h/planet_h)/2.78;
b=B0.rgb*h*dl;
c.r*=1.0-b.r;
c.g*=1.0-b.g;
c.b*=1.0-b.b;
c.rgb+=b*ll;
}
if (c.r<0.0) c.r=0.0;
if (c.g<0.0) c.g=0.0;
if (c.b<0.0) c.b=0.0;
h=0.0;
if (h<c.r) h=c.r;
if (h<c.g) h=c.g;
if (h<c.b) h=c.b;
if (h>1.0)
{
h=1.0/h;
c.r*=h;
c.g*=h;
c.b*=h;
}
return c;
}
void main(void)
{
gl_FragColor.rgba=atmosphere();
}
[统一值]
// Earth
re=6378141.2 // equatoreal radius r.x,r.y
rp=6356754.79506139 // polar radius r.z
planet_h=60000 // atmosphere thickness R(r.x+planet_h,r.y+planet_h,r.z+planet_h)
view_depth=250000 // max view distance before 100% scattering occur
B0.r=0.1981 // 100% scattered atmosphere color
B0.g=0.4656
B0.b=0.8625
B0.a=0.75 // overglow (sky is lighter before Sun actually rise) it is added to light dot product
// Mars
re=3397000
rp=3374919.5
ha=30000
view_depth=300000
B0.r=0.4314
B0.g=0.3216
B0.b=0.196
B0.a=0.5
有关更多信息(和更新的图像),另请参阅相关:
[编辑3]
这是我在引擎中使用上面的着色器渲染气氛的一个小的CPU端代码:
if (sys->_enable_bodya) // has planet atmosphere?
if (view_depth>=0.0)
{
glColor4f(1.0,1.0,1.0,1.0);
double a,b,p[3],d[3];
sys->shd_engine.unbind();
sys->shd_scatter.bind(); // this is the atmospheric shader
if (1) //*** GLSL_uniform_supported (leftover from old GL engine version)
{
int j;
double *w;
AnsiString s;
a=re; b=rp; a=divide(1.0,a*a); b=divide(1.0,b*b); // radius of planet re equatoral and rp polar and ha is atmosphere thickness
sys->shd_scatter.set3f("planet_r",a,a,b);
a=re+ha; b=rp+ha; a=divide(1.0,a*a); b=divide(1.0,b*b);
sys->shd_scatter.set3f("planet_R" ,a,a,b);
sys->shd_scatter.set1f("planet_h" ,ha);
sys->shd_scatter.set1f("view_depth",view_depth); // visibility distance
sys->shd_scatter.set4f("B0",B0[0],B0[1],B0[2],B0[3]); // saturated atmosphere color and overglow
sys->shd_scatter.set1i("lights",sys->local_star.num); // local stars
for (j=0;j<sys->local_star.num;j++)
{
a=sys->local_star[j].r;
w=sys->local_star[j].p;
s=AnsiString().sprintf("light_posr[%i]",j);
sys->shd_scatter.set4f(s,w[0],w[1],w[2],divide(1.0,a*a));
w=sys->local_star[j].d;
s=AnsiString().sprintf("light_dir[%i]",j);
sys->shd_scatter.set3f(s,w[0],w[1],w[2]);
vector_mul(p,sys->local_star[j].col,10.0);
s=AnsiString().sprintf("light_col[%i]",j);
sys->shd_scatter.set3f(s,p[0],p[1],p[2]);
}
}
glEnable(GL_BLEND);
glBlendFunc(GL_ONE,GL_ONE_MINUS_SRC_ALPHA);
a=1.0;
b=-2.0*view.scr->views[view.scr->view].znear;
// color = pixel pos in screen space <-1,+1> ... no Projection/ModelView is used :)
// vertex = pixel pos in elypsoid space
// normal = eye-pixel direction in elypsoid space
zsort.rep0.g2l_dir(d,zsort.obj_pos0);
glDepthMask(0);
glBegin(GL_QUADS);
a=divide(1.0,view.zoom);
glColor4d(-1.0,-1.0,0.0,1.0); vector_ld(p,-a,-a,b); view.scr->fromscr(p,p); view.eye0.l2g(q,p); zsort.rep0.g2l_dir(q,q); vector_sub(p,q,d); vector_one(q,q); glNormal3dv(q); glVertex3dv(p);
glColor4d(+1.0,-1.0,0.0,1.0); vector_ld(p,+a,-a,b); view.scr->fromscr(p,p); view.eye0.l2g(q,p); zsort.rep0.g2l_dir(q,q); vector_sub(p,q,d); vector_one(q,q); glNormal3dv(q); glVertex3dv(p);
glColor4d(+1.0,+1.0,0.0,1.0); vector_ld(p,+a,+a,b); view.scr->fromscr(p,p); view.eye0.l2g(q,p); zsort.rep0.g2l_dir(q,q); vector_sub(p,q,d); vector_one(q,q); glNormal3dv(q); glVertex3dv(p);
glColor4d(-1.0,+1.0,0.0,1.0); vector_ld(p,-a,+a,b); view.scr->fromscr(p,p); view.eye0.l2g(q,p); zsort.rep0.g2l_dir(q,q); vector_sub(p,q,d); vector_one(q,q); glNormal3dv(q); glVertex3dv(p);
glEnd();
glDepthMask(1);
glDisable(GL_BLEND);
sys->shd_scatter.unbind();
sys->shd_engine.bind();
}
它是从我的引擎中提取的,所以它使用了很多你没有的东西,但你知道这些东西是如何使用的……顺便说一句l2g
,意思是从局部坐标转换到全局坐标,g2l
反之亦然。如果_dir
存在,l2g_dir
则表示变换正在处理矢量而不是位置,因此没有平移。将fromscr
屏幕转换<-1,+1>
为 3D(相机本地)并将vector_one
矢量标准化为单位一。希望我没有忘记解释一些事情......