- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我按照NeHe导师Lesson27告诉我的那样编码,但它是一个z-pass算法。当我在阴影中时,阴影就消失了。有人告诉我我可以使用z-fail算法来解决这个问题。所以我花了两天时间研究z-fail算法。最后我想不通。我的程序从来没有按照我的想法运行。
wiki 列出的 z-fail 算法:
深度失败2000 年左右,一些人发现通过反转深度,可以使海德曼的方法适用于所有相机位置。与计算对象表面前面的阴影表面不同,可以同样轻松地计算对象表面后面的阴影表面,并获得相同的最终结果。这解决了眼睛处于阴影中的问题,因为眼睛和物体之间的阴影体积不被计算在内,但引入了阴影体积的后端必须被盖住的条件,否则阴影最终会在体积点处丢失向后无穷远。
禁用对深度和颜色缓冲区的写入。
使用正面剔除。
将模板操作设置为在深度失败时递增(仅计算对象后面的阴影)。
渲染阴影体积。
使用背面剔除。
将模板操作设置为在深度失败时递减。
渲染阴影体积。
我认为主要问题是深度测试。在步骤3和6中,模板操作是基于深度失败的。虽然它可以显示阴影,但它可能会阴影在它之前的对象上(即:深度缓冲区值小于它的对象)。所以所有阴影效果看起来很困惑。
但是在z-pass算法中,模板操作是基于深度pass的,这意味着它不仅可以显示阴影,而且只能在其后面的物体上转换阴影,这符合眼睛系统。
那么如何解决这个问题,使我的深度失败算法在正确的对象上显示阴影。
这是我的z-fail算法代码(可能在某个地方,请帮我找出来,阴影效果很糟糕)
VECTOR vec;
void shadowvolume(SECTOR &sec,float *lp)
{
unsigned int p1, p2;
VECTOR v1, v2;
int i, j, k, jj;
for (i=0; i<sec.numplanes;i++)
{
if (sec.planes[i].visible)
{
for (j=0;j<3;j++)
{
k = sec.planes[i].neigh[j];
if ((!k) || (!sec.planes[k-1].visible))//如果以第k个点开始的邻边没有相邻平面或者相邻平面不可见
{
// here we have an edge, we must draw a polygon
p1 = sec.planes[i].p[j]-1;//邻边的起点
jj = (j+1)%3;
p2 = sec.planes[i].p[jj]-1;//邻边的终点
//calculate the length of the vector
v1.x = (sec.points[p1].vec.x - lp[0])*100;
v1.y = (sec.points[p1].vec.y - lp[1])*100;
v1.z = (sec.points[p1].vec.z - lp[2])*100;
v2.x = (sec.points[p2].vec.x - lp[0])*100;
v2.y = (sec.points[p2].vec.y - lp[1])*100;
v2.z = (sec.points[p2].vec.z - lp[2])*100;
glBegin(GL_TRIANGLE_STRIP);//将光源连到邻边的起点并延长,将光源连到邻边的终点的并延长,最后延长出来的梯形,画了过后模板缓冲区的值加1
glVertex3f(sec.points[p1].vec.x,sec.points[p1].vec.y,sec.points[p1].vec.z);
glVertex3f(sec.points[p1].vec.x + v1.x,sec.points[p1].vec.y + v1.y,sec.points[p1].vec.z + v1.z);
glVertex3f(sec.points[p2].vec.x,sec.points[p2].vec.y,sec.points[p2].vec.z);
glVertex3f(sec.points[p2].vec.x + v2.x,sec.points[p2].vec.y + v2.y,sec.points[p2].vec.z + v2.z);
glEnd();
}
}
// caps
glBegin(GL_TRIANGLES);
for(k=0;k<3;k++)
glVertex3fv((float*)&sec.points[sec.planes[i].p[k]-1].vec);
glEnd();
glBegin(GL_TRIANGLES);
for(k=2;k>=0;k--)
{
vec.x=sec.points[sec.planes[i].p[k]-1].vec.x+(sec.points[sec.planes[i].p[k]-1].vec.x-lp[0])*100;
vec.y=sec.points[sec.planes[i].p[k]-1].vec.y+(sec.points[sec.planes[i].p[k]-1].vec.y-lp[1])*100;
vec.z=sec.points[sec.planes[i].p[k]-1].vec.z+(sec.points[sec.planes[i].p[k]-1].vec.z-lp[2])*100;
glVertex3fv((float*)&vec);
}
glEnd();
}
}
}
void CastShadow(SECTOR &sec, float *lp)
{//lp是光源相对于物体的位置
float side;
glEnable(GL_CULL_FACE);
int i;
for (i=0;i<sec.numplanes;i++)
{
side =sec.planes[i].planeeq.a*lp[0]+sec.planes[i].planeeq.b*lp[1]+sec.planes[i].planeeq.c*lp[2]+sec.planes[i].planeeq.d*lp[3];
if (side>0)
sec.planes[i].visible = TRUE;
else
sec.planes[i].visible = FALSE;
}
glDisable(GL_LIGHTING);
glDepthMask(GL_FALSE);
glDepthFunc(GL_LEQUAL);
glEnable(GL_STENCIL_TEST);
glColorMask(0, 0, 0, 0);
glStencilFunc(GL_ALWAYS, 0, 0xffffffff);
glCullFace(GL_FRONT);
glStencilOp(GL_KEEP, GL_INCR, GL_KEEP);
//glStencilOp(GL_KEEP, GL_KEEP, GL_DECR);
shadowvolume(sec,lp);
glCullFace(GL_BACK);
glStencilOp(GL_KEEP, GL_DECR, GL_KEEP);
//glStencilOp(GL_KEEP,GL_KEEP, GL_INCR);
shadowvolume(sec,lp);
glColorMask(1, 1, 1, 1);
//draw a shadowing rectangle covering the entire screen
glColor4f(0.0f, 0.0f, 0.0f,0.4f);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glStencilFunc(GL_NOTEQUAL, 0, 0xffffffff);
//glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE);
glPushMatrix();
glLoadIdentity();
glBegin(GL_TRIANGLE_STRIP);
glVertex3f(-0.1f, 0.1f,-0.0010f);
glVertex3f(-0.1f,-0.1f,-0.0010f);
glVertex3f( 0.1f, 0.1f,-0.0010f);
glVertex3f( 0.1f,-0.1f,-0.0010f);
glEnd();
glPopMatrix();
glDisable(GL_BLEND);
glDepthFunc(GL_LEQUAL);
glDepthMask(GL_TRUE);
glEnable(GL_LIGHTING);
glDisable(GL_STENCIL_TEST);
glShadeModel(GL_SMOOTH);
glDisable(GL_CULL_FACE);
}
VECTOR 类是这样的:
class VECTOR
{
public:
float x,y,z;
bool operator==(VECTOR vec)
{
if(x==vec.x && y==vec.y && z==vec.z)
return true;
return false;
}
};
SECTOR 类和其他类是这样的:
class PLANEEQ
{
public:
float a,b,c,d;
};
class PLANE
{
public:
unsigned int p[3];//点的序号
VECTOR normal[3];
unsigned int neigh[3];//平面3个相依平面的序号
PLANEEQ planeeq;
bool visible;
PLANE()
{
neigh[0]=0;
neigh[1]=0;
neigh[2]=0;
planeeq.a=0;
planeeq.b=0;
planeeq.c=0;
planeeq.d=0;
visible=false;
}
};
class SECTOR
{
public:
int numpoints;
int numplanes;
vector<VERTEX> points;
vector<PLANE> planes;
MATERIAL material;
bool read();
bool loadtexture();
bool build();
bool plane_calc();
void SetConnectivity();
SECTOR& SECTOR::subdivide(long depth);
SECTOR(string str1,string str2):modelfilename(str1),texturefilename(str2)
{
numpoints=0;
numplanes=0;
}
SECTOR()
{
numpoints=0;
numplanes=0;
}
private:
FILE *modelfilein,*texturefilein;
string modelfilename,texturefilename;
char oneline[255];
UINT texturename;
AUX_RGBImageRec *TextureImage;
};
class POSITION
{
public:
float x,y,z,w;
};
我的main.cpp中的DrawGLScene函数是这样的:
int DrawGLScene(GLvoid)
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT |GL_STENCIL_BUFFER_BIT);
glLoadIdentity();
DrawGLRoom();
glLoadIdentity();
GLfloat xtrans = -xpos;
GLfloat ztrans = -zpos;
GLfloat ytrans = -ypos-1.2f;
GLfloat sceneroty = 360.0f - yrot;
glRotatef(lookupdown,1.0f,0,0);
glRotatef(sceneroty,0,1.0f,0);
glTranslatef(xtrans, ytrans, ztrans);
brick_sec.build();
floor_sec.build();
//wall_sec.build();
//CastShadow(wall_sec,(float *)&lightgroup.lights[0].pos);
CastShadow(brick_sec,(float*)&lightgroup.lights[0].pos);
CastShadow(floor_sec,(float*)&lightgroup.lights[0].pos);
lightgroup.build();
glColor4f(0.7f, 0.4f, 0.0f, 1.0f);
glDisable(GL_LIGHTING);
glDepthMask(GL_FALSE);
glTranslatef(lightgroup.lights[0].pos.x, lightgroup.lights[0].pos.y, lightgroup.lights[0].pos.z);
gluSphere(q, 0.2f, 16, 8);
glEnable(GL_LIGHTING);
glDepthMask(GL_TRUE);
if(space_time>0)
{
ypos=sin(space_time*3.1415926/180);
space_time-=4;
}
else
{
sp=false;
}
//glFlush();
return TRUE; // Everything Went OK
}
由于我的声誉低于 10,我无法捕捉阴影效果来向您展示它看起来有多糟糕!请帮助我,感谢您的关注和时间!!!
感谢 Najzero 给了我 5 声望,现在我可以截屏来展示效果了。下面我会附上详细的描述。
z-pass算法效果:当我不在效果中时,没关系!(橙色 jar 代表光)
但是当我在 wall_shadow 中时,就不行了!wall_shadow 消失了,尽管 brick_shadow 还在那里。
所以我需要z-fail算法来解决这个问题。但是我的代码最后实现的效果是这样的: 打勾代表阴影效果正确,十字代表阴影不应该出现在物体上。
另一张截图,
最佳答案
哈哈,终于在我的代码中找到了问题,我太高兴了,哈哈!!!!!!!!!
问题是 gluPerspective(45.0f,(GLfloat)width/(GLfloat)height,0.001f,100.0f);
正如 GuentherKrass 在 http://www.opengl.org/discussion_boards/showthread.php/146157-Z-Fail-Stencil-Shadow-Volumes 中所说的那样
如果您这样做,请务必使用具有无限远平面的透视投影矩阵或使用 GL_DEPTH_CLAMP 以避免后盖被远剪裁平面剔除。
所以我只需将上面的代码更改为
gluPerspective(45.0f,(GLfloat)宽度/(GLfloat)高度,0.001f,1000000.0f);
好吧,看起来很完美!!!!!!!!!!!!!!!!!!111 哈哈哈哈
两天,熬夜,方便面..太他妈值了!!
好的,我会把最后的效果图放出来。如果有人想要我的代码,请发电子邮件给我(nomorefancy@gmail.com)
注意:砖 block 阴影独立于墙壁阴影。
关于opengl - 如何在opengl中实现z-fail算法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12551060/
我是一名优秀的程序员,十分优秀!