影の中に立っていないと影の効果は完璧に見えますが、影の中にいると影が消えてしまいます。
これがシャドウ効果を実現するための私のコードです。
void CastShadow(SECTOR &sec, float *lp)
{//lp is the relative position to the sec
unsigned int i, j, k, jj;
unsigned int p1, p2;
VECTOR v1, v2;
float side;
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, 1, 0xffffffff);
// first pass, stencil operation decreases stencil value
glFrontFace(GL_CCW);
glStencilOp(GL_KEEP, GL_KEEP, GL_INCR);
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();
}
}
}
// second pass, stencil operation increases stencil value
glFrontFace(GL_CW);//这句表示画的多边形,只看到里面
glStencilOp(GL_KEEP, GL_KEEP, GL_DECR);
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();
}
}
}
glFrontFace(GL_CCW);
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);
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);
}
クラスSECTORは次のようになります。
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;
};