⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 shadow.c

📁 游戏编程精粹,对刚入门的游戏开发者很有帮助
💻 C
字号:
/* Copyright (C) Gabor Nagy, 2000.  * All rights reserved worldwide. * * This software is provided "as is" without express or implied * warranties. You may freely copy and compile this source into * applications you distribute provided that the copyright text * below is included in the resulting source code, for example: * "Portions Copyright (C) Gabor Nagy, 2000" *//*==============================================================================*//* Real-time cast shadows							*//*										*//* - Shadow map generation							*//* - Shadow-matix generation							*//*										*//* AUTHOR:	Gabor Nagy, Sony Computer Entertainment America			*//* DATE:	2000-May-02 03:15:35						*//*  v1.0									*//*										*//* For Game Programming Graphics Gems						*//*==============================================================================*/#include <math.h>#include <stdio.h>#include <stdlib.h>#include <GL/glut.h>#include "geo.h"#include "shadow.h"// Shadow map//extern unsigned long*	Sh_ShadowMapImage;extern int		Sh_ShadowMapXSize,Sh_ShadowMapYSize;#define ABS(x)	(((x<0)?(-x):(x)))/*==============================*//* Create the shadow map	*//*==============================*/void Sh_CreateShadowMap(GLuint LShadowMapTexId, int LMapXSize, int LMapYSize, E3dMesh* LBlockerMesh, E3dMatrix LBlockerMatrix){ E3dVertexNode*	LVertexNode; E3dPolygon*	LPolygon; E3dPolyGroup*	LPolyGroup; unsigned long	LC,LN,LPCnt,LPNum; E3dMatrix	LTmpMatrix; glViewport(0, 0, LMapXSize, LMapYSize); glEnable(GL_SCISSOR_TEST); glScissor(0, 0, LMapXSize, LMapYSize);// We will make a dark grey on white shadow-map,// so clear the buffer with white// glClearColor(1.0, 1.0, 1.0, 0.0); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);// Save OpenGL's old PROJECTION matrix// glMatrixMode(GL_PROJECTION); glGetFloatv(GL_MODELVIEW_MATRIX,LTmpMatrix);// Clear OpenGL's PROJECTION matrix// glLoadIdentity();// Load BlockerLocalToShadowMap matrix// glMatrixMode(GL_MODELVIEW); glPushMatrix(); glLoadMatrixf(LBlockerMatrix); glDisable(GL_LIGHTING); glDisable(GL_TEXTURE_2D);// We will draw the blocker object on// the shadow-map with this color// glColor3f(0.5f, 0.5f, 0.5f);  LN=LBlockerMesh->NumOfPolyGroups;  for(LC=0;LC<LN;LC++)  {   LPolyGroup=LBlockerMesh->PolyGroups[LC];   LPNum=LPolyGroup->NumOfPolygons;   LPolygon=LPolyGroup->Polygons;// Start drawing shadow-map//   glBegin(GL_TRIANGLES);    for(LPCnt=0;LPCnt<LPNum;LPCnt++,LPolygon++)    {     LVertexNode=LPolygon->VertexNodes;     glVertex3fv( LVertexNode->GLVertex );LVertexNode++;     glVertex3fv( LVertexNode->GLVertex );LVertexNode++;     glVertex3fv( LVertexNode->GLVertex );    }   glEnd();  } glPopMatrix();// Restore OpenGL's PROJECTION matrix// glMatrixMode(GL_PROJECTION); glLoadMatrixf(LTmpMatrix); glDisable(GL_SCISSOR_TEST);// Make the image we just rendered (the shadow-map) an OpenGL texture// if(Sh_ShadowMapImage!=NULL) {   glReadBuffer(GL_BACK);   glReadPixels(0, 0, LMapXSize, LMapYSize, GL_RGBA, GL_UNSIGNED_BYTE, Sh_ShadowMapImage);// Send the shadow map to OpenGL//   glBindTexture(GL_TEXTURE_2D, LShadowMapTexId);   glTexImage2D(GL_TEXTURE_2D, 0, 4, LMapXSize, LMapYSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, Sh_ShadowMapImage ); }}/*======================================================================*//* Compute the shadow projection matrices for a given Light and Model	*//*======================================================================*/void E3d_ShadowMatrix(E3dLight* LLight,E3dModel* LModel,E3dMatrix LBlockerMatrix,E3dMatrix LReceiverUVMatrix){ unsigned long		LGmNum,LVn,LVC; E3dType		Mx,My,Mz,LPlightX,LPlightY,LPlightZ,			LRX,LRY,LRZ,			// "Right" vector			LUPX,LUPY,LUPZ,			// "Up" vector			LMDVX,LMDVY,LMDVZ,		// Mean Direction Vector			LVF,LX,LY,LZ,LXMax,LYMax,LXProj,LYProj,			LZNear,LZFar; E3dMesh*		LMesh; E3dPolyGroup**		LPolyGroups; E3dVertex*		LVertex; E3dMatrix		LBlockerLocalToWorldMatrix,LTmpMatrix,LViewMatrix; LPlightX=LLight->Position.X; LPlightY=LLight->Position.Y; LPlightZ=LLight->Position.Z; E3d_MatrixCopy(LModel->LocalToWorldMatrix,LBlockerLocalToWorldMatrix); LGmNum=LModel->NumOfGeometries;LMesh=(E3dMesh*)(LModel->Geometry);// Reset Mean Direction Vector// LMDVX=LMDVY=LMDVZ=0.0; if(LMesh->NumOfPolyGroups==0) return; LPolyGroups=LMesh->PolyGroups; LVertex=LMesh->Vertices;// Average vertex-to-light vectors// LVn=LMesh->NumOfVertices; LMDVX=LPlightX*LVn; LMDVY=LPlightY*LVn; LMDVZ=LPlightZ*LVn; for(LVC=0;LVC<LVn;LVC++,LVertex++) {  Mx=LVertex->X;My=LVertex->Y;Mz=LVertex->Z;  E3dM_MatrixTransform3x4(LBlockerLocalToWorldMatrix,LX,LY,LZ);  LMDVX-=LX;  LMDVY-=LY;  LMDVZ-=LZ; }// Normalize Mean Direction Vector (MDV)// LVF=sqrt(LMDVX*LMDVX+LMDVY*LMDVY+LMDVZ*LMDVZ);LVF=1.0/LVF; LMDVX*=LVF; LMDVY*=LVF; LMDVZ*=LVF;// Get smallest component of MDV (Z axis of the light coordinate system), make a vector with that// component as 1, the others 0 (L)// The RIGHT vector (X axis of the camera transform) will be: LRV = LMDV x L// The UP-vector (Y axis of the camera transform) will be: LUPV = LMDV x LRV// if(LMDVX<=LMDVY) {  if(LMDVZ<=LMDVX) { LX=0.0;LY=0.0;LZ=1.0; }	// LMDVZ is smallest  else { LX=1.0;LY=0.0;LZ=0.0; }		// LMDVX is smallest } else {  if(LMDVZ<=LMDVY) { LX=0.0;LY=0.0;LZ=1.0; }	// LMDVZ is smallest  else { LX=0.0;LY=1.0;LZ=0.0; }		// LMDVX is smallest }// LR = LMDV x L// E3dM_VectorCrossProduct(LMDVX,LMDVY,LMDVZ,LX,LY,LZ,LRX,LRY,LRZ);// Normalize Right vector// LVF=sqrt(LRX*LRX+LRY*LRY+LRZ*LRZ);LVF=1.0/LVF; LRX*=LVF;LRY*=LVF;LRZ*=LVF;// LUP = LR x LMDV// E3dM_VectorCrossProduct(LMDVX,LMDVY,LMDVZ,LRX,LRY,LRZ,LUPX,LUPY,LUPZ);// Build view-transformation matrix// LViewMatrix[M00]=LRX;LViewMatrix[M01]=LUPX;LViewMatrix[M02]=LMDVX;LViewMatrix[M03]=0.0; LViewMatrix[M10]=LRY;LViewMatrix[M11]=LUPY;LViewMatrix[M12]=LMDVY;LViewMatrix[M13]=0.0; LViewMatrix[M20]=LRZ;LViewMatrix[M21]=LUPZ;LViewMatrix[M22]=LMDVZ;LViewMatrix[M23]=0.0; LViewMatrix[M30]=0.0;LViewMatrix[M31]=0.0;LViewMatrix[M32]=0.0;LViewMatrix[M33]=1.0; E3d_MatrixTranslate(LViewMatrix,-LPlightX,-LPlightY,-LPlightZ); E3d_MatrixCopy(LViewMatrix,LTmpMatrix); E3d_MatrixMult(LBlockerLocalToWorldMatrix,LTmpMatrix); // Find the horizontal and vertical angular spreads to find out FOV and aspect ratio// LVertex=LMesh->Vertices; LXMax=LYMax=0.0; for(LVC=0,LVn=LMesh->NumOfVertices;LVC<LVn;LVC++,LVertex++) {  Mx=LVertex->X;My=LVertex->Y;Mz=LVertex->Z;  E3dM_MatrixTransform3x4(LTmpMatrix,LX,LY,LZ);  LZ=1.0/LZ;  LX*=LZ;LY*=LZ;  if(ABS(LX)>LXMax) LXMax=ABS(LX);  if(ABS(LY)>LYMax) LYMax=ABS(LY); } LZNear=0.1;LZFar=1000.0;// Set up the perspective-projection matrix////    f = cotangent(Field-of-view) = 1.0/LYMax//    f/aspect=1.0/LXMax////	| f/aspect   0	     0.0	0.0   |//	|				      |//	|				      |//	|				      |//	|    0       f	     0.0	0.0   |//	|				      |//	|				      |//	|                 Zfar+Znear	      |//	|    0       0    ----------   -1.0   |//	|	          Znear-Zfar	      |//	|				      |//	|	         2*Zfar*Znear	      |//	|    0       0   ------------   0.0   |//	|                 Znear-Zfar	      |// Leave a pixel or two around the edges of the// shadow map for texture clamping// LXProj=(0.995-1.0/(float)Sh_ShadowMapXSize)/LXMax; LYProj=(0.995-1.0/(float)Sh_ShadowMapYSize)/LYMax; LBlockerMatrix[M00]=LXProj;LBlockerMatrix[M01]=   0.0;LBlockerMatrix[M02]=0.0;LBlockerMatrix[M03]=0.0; LBlockerMatrix[M10]=   0.0;LBlockerMatrix[M11]=LYProj;LBlockerMatrix[M12]=0.0;LBlockerMatrix[M13]=0.0; LBlockerMatrix[M20]=   0.0;LBlockerMatrix[M21]=   0.0;LBlockerMatrix[M22]=(LZFar+LZNear)/(LZNear-LZFar);LBlockerMatrix[M23]=-1.0; LBlockerMatrix[M30]=   0.0;LBlockerMatrix[M31]=   0.0;LBlockerMatrix[M32]=2.0*LZFar*LZNear/(LZNear-LZFar);LBlockerMatrix[M33]=0.0;// ViewMatrix = Projection * ViewTransformMatrix * LocalToWorld// E3d_MatrixMult(LViewMatrix,LBlockerMatrix); E3d_MatrixMult(LBlockerLocalToWorldMatrix,LBlockerMatrix);// Projection matrix for computing UVs on the receiver object// LReceiverUVMatrix[M00]=LXProj*0.5;LReceiverUVMatrix[M01]=       0.0;LReceiverUVMatrix[M02]=0.0;LReceiverUVMatrix[M03]=0.0; LReceiverUVMatrix[M10]=       0.0;LReceiverUVMatrix[M11]=LYProj*0.5;LReceiverUVMatrix[M12]=0.0;LReceiverUVMatrix[M13]=0.0; LReceiverUVMatrix[M20]=      -0.5;LReceiverUVMatrix[M21]=      -0.5;LReceiverUVMatrix[M22]=(LZFar+LZNear)/(LZNear-LZFar);LReceiverUVMatrix[M23]=-1.0; LReceiverUVMatrix[M30]=       0.0;LReceiverUVMatrix[M31]=       0.0;LReceiverUVMatrix[M32]=2.0*LZFar*LZNear/(LZNear-LZFar);LReceiverUVMatrix[M33]=0.0; E3d_MatrixMult(LViewMatrix,LReceiverUVMatrix);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -