How to implement z-fail algorithm in opengl?

I program as teachers NeHe Lesson27 told me, but this is the z-pass.When the algorithm is in the shadow, the shadow is gone. I was told that I can use the z-fail algorithm to solve this problem. therefore, I spend two days to explore the z-fail algorithm. Finally, I cannot figure it out. My program never starts, as I think.

The z-fail algorithm on the wiki list:

Depth Error Around the year 2000, several people discovered that the Heidman method could be made to work in all camera positions by changing depth. Instead of counting the surface of the shadows in front of the surface of the object, the surfaces behind it can be considered just as easily, with the same end result. This solves the problem that the eye is in the shadow, since the shadow volumes between the eye and the object are not taken into account, but it introduces the condition that the back end of the shadow volume should be closed, or there will be no shadow if the points of the volume are back to infinity.

  • Disable recording in depth and color buffers.

  • Use discarding the front panel.

  • Set the stencil operation to increase in depth (just mark the shadows behind the object).

  • Display shadow volumes.

  • Use knock back.

  • Set the stencil operation to a decrease in depth.

  • Display shadow volumes.

The main question that I think is a depth test. In steps 3 and 6, the stencil operation is based on a depth error. Although it can display a shadow, it can be obscured by the object in front of it (that is, an object whose buffer depth value is less than it). the shadow effect looks messy.

But in the z-pass algorithm, the stencil operation is based on a depth transition, which means that it can not only display the shadow, but also shade only the object behind it that matches the eye system.

therefore, how to solve this problem, to make my algorithm with a depth error, you can see the shadow on the correct objects.

here is my z-fail algorithm code (maybe somewhere, where please help me find out the shadow effect is terrible)

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); } 

the VECTOR class is as follows:

 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 and others such:

 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; }; 

the DrawGLScene function in my main.cpp looks like this:

 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 } 

Since my reputation is less than 10, I can’t capture the shadow effect to show how strong it looks! Pls help me i thanks u for ur attention and ur time!

thanks Najzero for giving me 5 rep, now I can capture the screen to show the effect. I will add a detailed description.

z-pass algorithm effect: when I’m not valid, it’s normal! (orange pot represents light) enter image description here

but when I am in wall_shadow, this is not normal! wall_shadow is gone, although brick_shadow is still there.

enter image description here

so I need a z-fail algorithm to solve this problem. But the last effect that my code implements looks like this: enter image description here the checkmark represents the effect of the shadow, it is correct, the cross means that the shadow should not appear on the object.

another screenshot enter image description here

+6
source share
1 answer

a ha; Finally, I find a problem in my code. I'm so happy lol !!!!!!!!!

gluPerspective problem (45.0f, (GLfloat) width / (GLfloat) height, 0.001f, 100.0f);

as GuentherKrass said at http://www.opengl.org/discussion_boards/showthread.php/146157-Z-Fail-Stencil-Shadow-Volumes

If you do so, be sure to use a perspective projection matrix with infinite range or use GL_DEPTH_CLAMP to avoid the back cover being selected with a flat clipping environment.

so I just changed the code above to

gluPerspective (45.0f, (GLfloat) width / (GLfloat) height, 0.001f, 1000000.0f);

ok, that looks perfect !!!!!!!!!!!!!!!!!!! 111 hahahahaaa

two days, no sleep, instant noodles .. damn it, it’s worth it !!

ok, I will post the last efft file. If someone wants my code just write me ( nomorefancy@gmail.com )

enter image description hereenter image description hereenter image description hereenter image description here

attention: the brick shadow does not depend on the shadow of the wall.

+2
source

Source: https://habr.com/ru/post/926042/


All Articles