阴影技术

喜欢OpenGL编程,现在在学习阴影技术。

在OpenGL超级宝典(人民邮电出版社,第三版)中有阴影图的介绍和示例代码。我从这本书的讲述开始学习,已经能够在简单的场景中实现正确的阴影。

但是遇到一个问题始终不明白!

这个问题是:如果给场景中的物体渲染颜色可以得到正确的阴影,如果给场景中的物体贴上纹理,阴影效果就看不到了,而且物体的纹理也不见了。起初我以为是纹理操作出问题,进行尝试性修改,现在物体的纹理可以显示出来,但是阴影效果仍然见不到,并且阴影图要操作纹理矩阵,我明明绑定了阴影图纹理之后才进行纹理矩阵的操作,可实际结果是物体的纹理随光源位置变化(光源位置变化则纹理矩阵变化)而变化。我始终没弄明白这是为什么?
附上我的代码。请大家指教!
=========================================
CView类
=========================================
// ShadowTestView.cpp : implementation of the CShadowTestView class
//
#include "stdafx.h"
#include "ShadowTest.h"
#include "ShadowTestDoc.h"
#include "ShadowTestView.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/
// CShadowTestView
IMPLEMENT_DYNCREATE(CShadowTestView, CView)
BEGIN_MESSAGE_MAP(CShadowTestView, CView)
 //{{AFX_MSG_MAP(CShadowTestView)
 ON_WM_CREATE()
 ON_WM_DESTROY()
 ON_WM_SIZE()
 ON_WM_TIMER()
 ON_COMMAND(ID_SHOW_SHADOW, OnShowShadow)
 ON_COMMAND(ID_SHOW_SHADOWMAP, OnShowShadowmap)
 ON_COMMAND(ID_FILE_OPEN, OnFileOpen)
 ON_COMMAND(ID_DEM_GRADCOLOR, OnDemGradcolor)
 ON_WM_LBUTTONDOWN()
 ON_WM_RBUTTONDOWN()
 ON_WM_MOUSEMOVE()
 ON_COMMAND(ID_DEM_TEXTURE, OnDemTexture)
 ON_COMMAND(ID_MOVE_MODEL, OnMoveModel)
 ON_COMMAND(ID_MOVE_LIGHT, OnMoveLight)
 ON_COMMAND(ID_MOVE_CAMERA, OnMoveCamera)
 ON_COMMAND(ID_MOVE_VIEW, OnMoveView)
 ON_WM_KEYDOWN()
 ON_WM_LBUTTONDBLCLK()
 ON_WM_LBUTTONUP()
 ON_WM_MOUSEWHEEL()
 ON_WM_RBUTTONDBLCLK()
 ON_WM_RBUTTONUP()
 //}}AFX_MSG_MAP
 // Standard printing commands
 ON_COMMAND(ID_FILE_PRINT, CView::OnFilePrint)
 ON_COMMAND(ID_FILE_PRINT_DIRECT, CView::OnFilePrint)
 ON_COMMAND(ID_FILE_PRINT_PREVIEW, CView::OnFilePrintPreview)
END_MESSAGE_MAP()
/
// CShadowTestView construction/destruction
CShadowTestView::CShadowTestView()
{
}
CShadowTestView::~CShadowTestView()
{
}
BOOL CShadowTestView::PreCreateWindow(CREATESTRUCT& cs)
{
// cs.cx = cs.cy = m_iShadowSize;
 return CView::PreCreateWindow(cs);
}
/
// CShadowTestView printing
BOOL CShadowTestView::OnPreparePrinting(CPrintInfo* pInfo)
{
 // default preparation
 return DoPreparePrinting(pInfo);
}
void CShadowTestView::OnBeginPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
{
 // TODO: add extra initialization before printing
}
void CShadowTestView::OnEndPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
{
 // TODO: add cleanup after printing
}
/
// CShadowTestView diagnostics
#ifdef _DEBUG
void CShadowTestView::AssertValid() const
{
 CView::AssertValid();
}
void CShadowTestView::Dump(CDumpContext& dc) const
{
 CView::Dump(dc);
}
CShadowTestDoc* CShadowTestView::GetDocument() // non-debug version is inline
{
 ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CShadowTestDoc)));
 return (CShadowTestDoc*)m_pDocument;
}
#endif //_DEBUG
/
// CShadowTestView message handlers
void CShadowTestView::OnDestroy()
{
 CView::OnDestroy();
 
 ::wglMakeCurrent(0,0);
 ::wglDeleteContext(m_hrc);
 if(m_hPalette)
 {
  DeleteObject(m_hPalette);
 }
 if(m_pDC)
 {
  delete m_pDC;
 }
 KillTimer(1); 
}
void CShadowTestView::OnTimer(UINT nIDEvent)
{
 Invalidate(FALSE);
 
 CView::OnTimer(nIDEvent);
}
void CShadowTestView::SetLogicalPalette(void)
{
 struct
 {
  WORD Version;
  WORD NumberOfEntries;
  PALETTEENTRY aEntries[256];
 }logicalPalette = {0x300,256};
 BYTE reds[] = {0,36,72,109,145,182,218,255};
 BYTE greens[]={0,36,72,109,145,182,218,255};
 BYTE blues[]={0,85,170,255};
 
 for (int colorNum=0; colorNum<256; ++colorNum)
    {
        logicalPalette.aEntries[colorNum].peRed =
            reds[colorNum & 0x07];
        logicalPalette.aEntries[colorNum].peGreen =
            greens[(colorNum >> 0x03) & 0x07];
        logicalPalette.aEntries[colorNum].peBlue =
            blues[(colorNum >> 0x06) & 0x03];
        logicalPalette.aEntries[colorNum].peFlags = 0;
    }
    m_hPalette = CreatePalette ((LOGPALETTE*)&logicalPalette);
}
BOOL CShadowTestView::SetupPixelFormat()
{
 PIXELFORMATDESCRIPTOR pfd = {
     sizeof(PIXELFORMATDESCRIPTOR),    // pfd结构的大小
     1,                                // 版本号
     PFD_DRAW_TO_WINDOW |              // 支持在窗口中绘图
     PFD_SUPPORT_OPENGL |              // 支持 OpenGL
     PFD_DOUBLEBUFFER,                 // 双缓存模式
     PFD_TYPE_RGBA,                    // RGBA 颜色模式
     32,                               // 24 位颜色深度
     0, 0, 0, 0, 0, 0,                 // 忽略颜色位
     0,                                // 没有非透明度缓存
     0,                                // 忽略移位位
     0,                                // 无累加缓存
     0, 0, 0, 0,                       // 忽略累加位
     32,                               // 32 位深度缓存    
     0,                                // 无模板缓存
     0,                                // 无辅助缓存
     PFD_MAIN_PLANE,                   // 主层
     0,                                // 保留
     0, 0, 0                           // 忽略层,可见性和损毁掩模
 };  
 int pixelformat;
 pixelformat = ::ChoosePixelFormat(m_pDC->GetSafeHdc(), &pfd);//选择像素格式
 ::SetPixelFormat(m_pDC->GetSafeHdc(), pixelformat, &pfd); //设置像素格式
 if(pfd.dwFlags & PFD_NEED_PALETTE)
  SetLogicalPalette(); //设置逻辑调色板
 return TRUE;
}
int IsExtSupported(const char *extension)
{
 GLubyte *extensions = NULL;
 const GLubyte *start;
 GLubyte *where, *terminator;
 where = (GLubyte *) strchr(extension, ' ');
 if (where || *extension == '/0')
  return 0;
 extensions = (GLubyte *)glGetString(GL_EXTENSIONS);
 start = extensions;
 for (;;)
 {
  where = (GLubyte *) strstr((const char *) start, extension);
  if (!where) break;
  terminator = where + strlen(extension);
  if (where == start || *(where - 1) == ' ')
  {
   if (*terminator == ' ' || *terminator == '/0')
    return 1;
  }
  start = terminator;
 }
 return 0;
}
void CShadowTestView::OnFileOpen()
{
}

void CShadowTestView::OnDemGradcolor()
{
 m_bDemGraduColor = TRUE;
 m_bDemTexture = FALSE;
}
void CShadowTestView::OnDemTexture()
{
 m_bDemTexture = TRUE;
 m_bDemGraduColor = FALSE;
}
void CShadowTestView::OnShowShadow()
{
 m_bNoShadows = !m_bNoShadows;
 m_bShowShadowMap = FALSE;
}
void CShadowTestView::OnShowShadowmap()
{
 m_bShowShadowMap = !m_bShowShadowMap;
}
void CShadowTestView::OnMoveModel()
{
 m_bChooseModel = TRUE;
 m_bChooseCamera = m_bChooseView = m_bChooseLight = FALSE;
}
void CShadowTestView::OnMoveLight()
{
 m_bChooseLight = TRUE;
 m_bChooseCamera = m_bChooseView = m_bChooseModel = FALSE;
}
void CShadowTestView::OnMoveCamera()
{
 m_bChooseCamera = TRUE;
 m_bChooseModel = m_bChooseView = m_bChooseLight = FALSE;
}
void CShadowTestView::OnMoveView()
{
 m_bChooseView = TRUE;
 m_bChooseCamera = m_bChooseLight = m_bChooseModel = FALSE;
}
void CShadowTestView::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
{
 if (nChar == VK_UP)
 {
  if (m_bChooseModel)
  {
   modelxrot += 10;
   modelyrot += 20;
   modelzrot += 30;
   if (modelxrot > 360) modelxrot = 0;
   if (modelyrot > 360) modelyrot = 0;
   if (modelzrot > 360) modelzrot = 0;
   RegenerateShadowMap();
  }
  if (m_bChooseLight)
  {
   m_fv4LightPos[0] += lightxmove;
   m_fv4LightPos[1] += lightymove;
   m_fv4LightPos[2] += lightzmove;
   RegenerateShadowMap();
  } 
  if (m_bChooseCamera)
  {
   m_v3CameraPos.x += cameraxmove;
//   m_v3CameraPos.y += cameraymove;
   m_v3CameraPos.z += camerazmove;
  }
  if (m_bChooseView)
  {
   m_v3ViewPos.x += viewxmove;
//   m_v3ViewPos.y += viewymove;
   m_v3ViewPos.z += viewzmove;
  }
 }
 if (nChar == VK_DOWN)
 {
  if (m_bChooseModel)
  {
   modelxrot -= 10;
   modelyrot -= 20;
   modelzrot -= 30;
   if (modelxrot < 0) modelxrot = 360;
   if (modelyrot < 0) modelyrot = 360;
   if (modelzrot < 0) modelzrot = 360;
   RegenerateShadowMap();
  }
  if (m_bChooseLight)
  {
   m_fv4LightPos[0] -= lightxmove;
   m_fv4LightPos[1] -= lightymove;
   m_fv4LightPos[2] -= lightzmove;
   RegenerateShadowMap();
  } 
  if (m_bChooseCamera)
  {
   m_v3CameraPos.x -= cameraxmove;
//   m_v3CameraPos.y -= cameraymove;
   m_v3CameraPos.z -= camerazmove;
  }
  if (m_bChooseView)
  {
   m_v3ViewPos.x -= viewxmove;
//   m_v3ViewPos.y -= viewymove;
   m_v3ViewPos.z -= viewzmove;
  }
 }
 CView::OnKeyDown(nChar, nRepCnt, nFlags);
}
void CShadowTestView::OnLButtonDown(UINT nFlags, CPoint point)
{
// m_Camera.MouseL_Dowm = true;
 
 CView::OnLButtonDown(nFlags, point);
}
void CShadowTestView::OnLButtonUp(UINT nFlags, CPoint point)
{
// if(m_Camera.Role_Flag)
//  m_Camera.MouseL_Dowm = false;
 
 CView::OnLButtonUp(nFlags, point);
}
void CShadowTestView::OnLButtonDblClk(UINT nFlags, CPoint point)
{
// m_Camera.Role_Flag = !m_Camera.Role_Flag;
// if(m_Camera.Role_Flag)
//  ShowCursor(false);
// else
//  ShowCursor(true);
 
 CView::OnLButtonDblClk(nFlags, point);
}
BOOL CShadowTestView::OnMouseWheel(UINT nFlags, short zDelta, CPoint pt)
{
// if(m_Camera.Role_Flag)
// {
//  if(zDelta>0)
//   m_Camera.m_Speed = m_Camera.m_Speed*1.05;
//  else
//   m_Camera.m_Speed = m_Camera.m_Speed*0.95;
// }
 return CView::OnMouseWheel(nFlags, zDelta, pt);
}
void CShadowTestView::OnMouseMove(UINT nFlags, CPoint point)
{
 CView::OnMouseMove(nFlags, point);
}
void CShadowTestView::OnRButtonDblClk(UINT nFlags, CPoint point)
{
// m_Camera.Fly_Flag = !m_Camera.Fly_Flag;
 
 CView::OnRButtonDblClk(nFlags, point);
}
void CShadowTestView::OnRButtonDown(UINT nFlags, CPoint point)
{
// if(m_Camera.Role_Flag)
//  m_Camera.MouseR_Dowm = true;
 
 CView::OnRButtonDown(nFlags, point);
}
void CShadowTestView::OnRButtonUp(UINT nFlags, CPoint point)
{
// m_Camera.MouseR_Dowm = false;
 
 CView::OnRButtonUp(nFlags, point);
}
int CShadowTestView::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
 if (CView::OnCreate(lpCreateStruct) == -1)
  return -1;
 m_pDC = new CClientDC(this);
 InitializeOpenGL(m_pDC);
 InitializeScene();
 InitializeShadow(m_pDC);
 RegenerateShadowMap();
 SetTimer(1,20,NULL);
 
 return 0;
}
BOOL CShadowTestView::InitializeOpenGL(CDC* pDC)
{
 m_pDC = pDC;
 SetupPixelFormat();
 //生成绘制描述表
 m_hrc = ::wglCreateContext(m_pDC->GetSafeHdc());
 //置当前绘制描述表
 ::wglMakeCurrent(m_pDC->GetSafeHdc(), m_hrc);
// glActiveTexture = (PFNGLACTIVETEXTUREPROC)wglGetProcAddress("glActiveTexture");
 return TRUE;
}
void CShadowTestView::InitializeScene()

 // 状态控制
 m_bDemFileOpen = m_bDemTexture = FALSE;
 m_bDemGraduColor = TRUE;
 m_bAmbientShadowAvailable = GL_FALSE;
 m_bNoShadows = m_bShowShadowMap = GL_FALSE;
 m_bChooseCamera = m_bChooseView = m_bChooseLight = FALSE;
 m_bChooseModel = TRUE;
 if(m_Dem.LoadGRDFile("DEM//part.grd"))
 {
  m_bDemFileOpen = TRUE;
  m_Dem.CreateColorList();
  if (m_Dem.LoadGRDTex("DEM//part.bmp")) 
   m_Dem.CreatTextureList();
  else
   MessageBox("地形纹理“DEM//part.bmp”初始化错误", NULL, MB_OK);
  // 根据地形设置场景包围盒的大小和中心
  m_v3SceneCenter = m_Dem.m_v3DemCenter;
  m_v3SceneSize = m_Dem.m_v3DemSize*2;
  // 根据地形设置光源位置
  m_fv4LightPos[0] = m_Dem.m_v3DemCenter.x-m_Dem.m_v3DemSize.x/3;
  m_fv4LightPos[1] = m_Dem.m_v3DemCenter.y+m_Dem.m_v3DemSize.y*5;
  m_fv4LightPos[2] = m_Dem.m_v3DemCenter.z-m_Dem.m_v3DemSize.z/3;
  m_fv4LightPos[3] = 1.0;
  // 根据地形设置相机初始位置
  m_v3CameraPos.x = m_Dem.m_v3DemCenter.x+m_Dem.m_v3DemSize.x/3;
  m_v3CameraPos.y = m_Dem.m_v3DemCenter.y+m_Dem.m_v3DemSize.y;
  m_v3CameraPos.z = m_Dem.m_v3DemCenter.z+m_Dem.m_v3DemSize.z/3;
  //
  m_v3ViewPos = m_v3SceneCenter;
  // 使用相机控制视点
//  m_Camera.InitCamera(m_v3CameraPos.x, m_v3CameraPos.y, m_v3CameraPos.z,
//       m_v3ViewPos.x, m_v3ViewPos.y, m_v3ViewPos.z,
//       0, 1, 0,
//       m_Dem.Header.m_fIntervalRow/100);
  // 根据地形设置裁剪面和视角  
  float m_fLight2Scene = sqrt(pow((m_fv4LightPos[0]-m_v3SceneCenter.x), 2) +
         pow((m_fv4LightPos[1]-m_v3SceneCenter.y), 2) +
         pow((m_fv4LightPos[2]-m_v3SceneCenter.z), 2) );
  m_lfZNear = m_fLight2Scene-m_v3SceneSize.x; 
  if (m_lfZNear < 1.0) m_lfZNear = 1.0;
  m_lfZFar = m_fLight2Scene +m_v3SceneSize.x;
  // 视锥角度--场景外接球的半径与视点到场景中心距离的比值,求反正切角度
  m_lfFovxy = atan2(sqrt((m_v3SceneSize.x*m_v3SceneSize.x/4)+
      (m_v3SceneSize.y*m_v3SceneSize.y/4)+
      (m_v3SceneSize.z*m_v3SceneSize.z)),
      m_fLight2Scene);
  m_lfFovxy = m_lfFovxy/3.1415926535897*180;
  // 设置场景其他信息
  lightxmove = lightymove = lightzmove = 100;
  modelxrot = modelyrot = modelzrot = 100;
  cameraxmove = cameraymove = camerazmove = 100;
  viewxmove = viewymove = viewzmove = 100;
  // 多边形偏移量
  m_fFactor = 4.0f;
  // 阴影图大小
  m_iShadowSize = 512;
  // 环境光和反射光RGBA
  m_fvAmbientLight[0] = 0.2f; m_fvAmbientLight[1] = 0.2f;
  m_fvAmbientLight[2] = 0.2f; m_fvAmbientLight[3] = 1.0f;
  m_fvDiffuseLight[0] = 0.7f; m_fvDiffuseLight[1] = 0.7f;
  m_fvDiffuseLight[2] = 0.7f; m_fvDiffuseLight[3] = 1.0f;
 }
 else
 {
  m_bDemFileOpen = FALSE;
  MessageBox("地形数据“DEM//part.grd”初始化出错", NULL, MB_OK);
 }
}
void CShadowTestView::InitializeShadow(CDC* pDC)
{
 //检查扩展是否可用
 if (IsExtSupported("GL_ARB_shadow_ambient"))
  m_bAmbientShadowAvailable = GL_TRUE;
 
 // 隐藏面剔除
 glEnable(GL_DEPTH_TEST);
 glDepthFunc(GL_LEQUAL);
 // 设置光照状态(不变)
 glShadeModel(GL_SMOOTH);
 glEnable(GL_LIGHTING);
 glEnable(GL_COLOR_MATERIAL);
 glEnable(GL_NORMALIZE);
 glEnable(GL_LIGHT0);
 glPolygonOffset(m_fFactor, 0.0f);
 
 unsigned int *pTexture = NULL;
 pTexture = new unsigned int [m_iShadowSize*m_iShadowSize];
 memset(pTexture, 0, m_iShadowSize*m_iShadowSize*sizeof(unsigned int)); 
 // 设置纹理状态(不变)
 glGenTextures(1, &m_iShadowTextureID);
 glBindTexture(GL_TEXTURE_2D, m_iShadowTextureID);
// glActiveTexture(GL_TEXTURE1);
 glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, m_iShadowSize, m_iShadowSize,
    0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, pTexture); 
 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 
 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
 glTexParameteri(GL_TEXTURE_2D, GL_DEPTH_TEXTURE_MODE, GL_INTENSITY);
 if (m_bAmbientShadowAvailable)
  glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FAIL_VALUE_ARB, 0.5f);
 
 delete [] pTexture;                
}
void CShadowTestView::RegenerateShadowMap()
{
 // 存储视点在光源的透视矩阵和模型视图矩阵
 glMatrixMode(GL_PROJECTION);
 glLoadIdentity();
 gluPerspective(m_lfFovxy, 1.0f, m_lfZNear, m_lfZFar);
 glGetFloatv(GL_PROJECTION_MATRIX, m_fv16LightProjection);
 glMatrixMode(GL_MODELVIEW);
 glLoadIdentity();
 gluLookAt(m_fv4LightPos[0], m_fv4LightPos[1], m_fv4LightPos[2],
   m_v3ViewPos.x, m_v3ViewPos.y, m_v3ViewPos.z,
  0.0f, 1.0f, 0.0f);
 glGetFloatv(GL_MODELVIEW_MATRIX, m_fv16LightModelview);
 
 // 保持视口和阴影图大小一致
 glViewport(0, 0, m_iShadowSize, m_iShadowSize);
 //只清除深度缓存
 glClear(GL_DEPTH_BUFFER_BIT);
 //只关心最终的深度值
 glShadeModel(GL_FLAT);
 glDisable(GL_LIGHTING);
 glDisable(GL_COLOR_MATERIAL);
 glDisable(GL_NORMALIZE);
 glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
 //避免不精确
 glEnable(GL_POLYGON_OFFSET_FILL);
 //绘制场景中的物体
 DrawBackground(); //分层设色地形
 DrawModels();
 //将深度值复制到深度纹理中
 glBindTexture(GL_TEXTURE_2D, m_iShadowTextureID);
 glEnable(GL_TEXTURE_2D);
 glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT,
      0, 0, m_iShadowSize, m_iShadowSize, 0);
 //恢复正常绘制状态
 glShadeModel(GL_SMOOTH);
 glEnable(GL_LIGHTING);
 glEnable(GL_COLOR_MATERIAL);
 glEnable(GL_NORMALIZE);
 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
 
 glDisable(GL_POLYGON_OFFSET_FILL);
}
void CShadowTestView::OnDraw(CDC* pDC)
{
 CShadowTestDoc* pDoc = GetDocument();
 ASSERT_VALID(pDoc); 
 RenderScene();
}
BOOL CShadowTestView::RenderScene()
{
 wglMakeCurrent(m_pDC->GetSafeHdc(), m_hrc);
 CRect ClientRect;
 GetClientRect(&ClientRect);
 glClearColor(0.38f, 0.415f, 0.743f, 0.0f);
 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
 // 观察设置
 // 跟踪相机
 glMatrixMode(GL_PROJECTION);
 glLoadIdentity(); 
 gluPerspective(m_lfFovxy, 1.0, m_lfZNear, m_lfZFar);
 glMatrixMode(GL_MODELVIEW);
 glLoadIdentity();
 gluLookAt(m_v3CameraPos.x, m_v3CameraPos.y+3000, m_v3CameraPos.z,
  m_v3ViewPos.x, m_v3ViewPos.y, m_v3ViewPos.z,
  0, 1, 0);
 //
// m_Camera.UpdateCamera(ClientRect);
// m_Camera.RenderCamera();
 m_iWindowHeight = ClientRect.Height();
 m_iWindowWidth = ClientRect.Width();
 glViewport(0, 0, m_iWindowWidth, m_iWindowHeight);
 // 跟踪光源
 glLightfv(GL_LIGHT0, GL_POSITION, m_fv4LightPos);
 DrawLight();
//
// if (m_bShowShadowMap)
// {
//  //显示阴影图
//  glMatrixMode(GL_PROJECTION);
//  glLoadIdentity();
//  glMatrixMode(GL_MODELVIEW);
//  glLoadIdentity();
//  glMatrixMode(GL_TEXTURE);
//
//  glPushMatrix();
//   glLoadIdentity();
//   glEnable(GL_TEXTURE_2D);
//   glDisable(GL_LIGHTING);
//   glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
//   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_NONE);
//   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
//   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
//   //显示阴影贴图,按照它相对于窗口的实际大小
//    glBindTexture(GL_TEXTURE_2D, m_iShadowTextureID);
//   glBegin(GL_QUADS);
//    glTexCoord2f(0.0f, 0.0f);
//    glVertex2f(-1.0f, -1.0f);
//    glTexCoord2f(1.0f, 0.0f);
//    glVertex2f(((GLfloat)m_iShadowSize/(GLfloat)m_iWindowWidth)*2.0-1.0f, -1.0f);
//    glTexCoord2f(1.0f, 1.0f);
//    glVertex2f(((GLfloat)m_iShadowSize/(GLfloat)m_iWindowWidth)*2.0-1.0f,
//         ((GLfloat)m_iShadowSize/(GLfloat)m_iWindowHeight)*2.0-1.0f);
//    glTexCoord2f(0.0f, 1.0f);
//    glVertex2f(-1.0f,((GLfloat)m_iShadowSize/(GLfloat)m_iWindowHeight)*2.0-1.0f);
//   glEnd();
//   glDisable(GL_TEXTURE_2D);
//   glEnable(GL_LIGHTING);
//  glPopMatrix();
//  glMatrixMode(GL_PROJECTION);
//  gluPerspective(45.0f, 1.0f, 1.0f, 1000.0f);
//  glMatrixMode(GL_MODELVIEW);
// }
// else if (m_bNoShadows)
 if (m_bNoShadows)
 {
  //设置一些简单的光照
  glLightfv(GL_LIGHT0, GL_AMBIENT, m_fvAmbientLight);
  glLightfv(GL_LIGHT0, GL_DIFFUSE, m_fvDiffuseLight);
  //绘制场景中的物体
  DrawBackground();
  DrawModels();
 }
 else
 {  
  GLfloat sPlane[4] = {1.0f, 0.0f, 0.0f, 0.0f};
  GLfloat tPlane[4] = {0.0f, 1.0f, 0.0f, 0.0f};
  GLfloat rPlane[4] = {0.0f, 0.0f, 1.0f, 0.0f};
  GLfloat qPlane[4] = {0.0f, 0.0f, 0.0f, 1.0f};
  if (!m_bAmbientShadowAvailable)
  {
   GLfloat lowAmbient[4] = {0.1f, 0.1f, 0.1f, 1.0f};
   GLfloat lowDiffuse[4] = {0.35f, 0.35f, 0.35f, 1.0f};
   //由于不存在让“让环境光”比较失败的值
   //必须首先设置环境光下的场景
   glLightfv(GL_LIGHT0, GL_AMBIENT, lowAmbient);
   glLightfv(GL_LIGHT0, GL_DIFFUSE, lowDiffuse);
   
   DrawBackground();
   DrawModels();
   //启用Alpha检测,丢弃被阴影遮挡的片段
   glAlphaFunc(GL_GREATER, 0.9f);
   glEnable(GL_ALPHA_TEST);
  }
  glLightfv(GL_LIGHT0, GL_AMBIENT, m_fvAmbientLight);
  glLightfv(GL_LIGHT0, GL_DIFFUSE, m_fvDiffuseLight);
 
  //设置阴影比较
  glBindTexture(GL_TEXTURE_2D, m_iShadowTextureID);
  glEnable(GL_TEXTURE_2D);
  glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE,
      GL_COMPARE_R_TO_TEXTURE);
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
  //设置视觉平面,用于场景上阴影贴图的投影
  glEnable(GL_TEXTURE_GEN_S);
  glEnable(GL_TEXTURE_GEN_T);
  glEnable(GL_TEXTURE_GEN_R);
  glEnable(GL_TEXTURE_GEN_Q);
  glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
  glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
  glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
  glTexGeni(GL_Q, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
  glTexGenfv(GL_S, GL_EYE_PLANE, sPlane);
  glTexGenfv(GL_T, GL_EYE_PLANE, tPlane);
  glTexGenfv(GL_R, GL_EYE_PLANE, rPlane);
  glTexGenfv(GL_Q, GL_EYE_PLANE, qPlane);
  //设置纹理矩阵用于阴影贴图投影
  glMatrixMode(GL_TEXTURE);
  glLoadIdentity();
  glTranslatef(0.5f, 0.5f, 0.5f);
  glScalef(0.5f, 0.5f, 0.5f);  
  glMultMatrixf(m_fv16LightProjection);
  glMultMatrixf(m_fv16LightModelview);
  
  DrawBackground();
 
  DrawModels();
  glDisable(GL_ALPHA_TEST);
  glDisable(GL_TEXTURE_2D);
  glDisable(GL_TEXTURE_GEN_S);
  glDisable(GL_TEXTURE_GEN_T);
  glDisable(GL_TEXTURE_GEN_R);
  glDisable(GL_TEXTURE_GEN_Q);
 }   
//
// m_Camera.UpdateCamera(ClientRect);
// m_Camera.RenderCamera();
 
 ::SwapBuffers(m_pDC->GetSafeHdc());
 return true;
}
void  CShadowTestView::DrawLight()
{
 if (m_bDemFileOpen)
 {
  glPushMatrix();
   glColor3f(1,0,1);
   glTranslatef(m_fv4LightPos[0],
    m_fv4LightPos[1]+800,
    m_fv4LightPos[2]);
   glutWireCube(500);
  glPopMatrix();
 }
}
void CShadowTestView::DrawBackground()
{
 if(m_bDemFileOpen)
 {
  if (m_bDemGraduColor)
  {
   //绘制分层设色地形
   glPushMatrix();
   glPolygonMode(GL_FRONT_AND_BACK,GL_FILL);
    m_Dem.DisplayColorList();
   glPopMatrix();
  }
  if (m_bDemTexture)
  {
   glPushMatrix();
    m_Dem.DisplayTextureList();
   glPopMatrix();
  }
  // 在地形中心作一标记
  glPushMatrix();
   glColor3f(0, 1, 0);
   glTranslatef(m_Dem.m_v3DemCenter.x, m_Dem.m_v3DemCenter.y+500, m_Dem.m_v3DemCenter.z);
   glRotatef(90, 1, 0, 0);
   glutSolidCone(100, 1000, 50, 50);
  glPopMatrix();
 }
}
void CShadowTestView::DrawModels()
{
 glPushMatrix();
  glColor3f(1,1,1);
  glTranslatef(m_v3SceneCenter.x-800, m_v3SceneCenter.y+2400, m_v3SceneCenter.z-800);
  glutSolidTorus(100, 400, 50, 50);
 glPopMatrix();
 // 圆环
 glPushMatrix();
  glColor3f(1.0f, 1.0f, 1.0f);
  glTranslatef(m_v3SceneCenter.x, m_v3SceneCenter.y+1600, m_v3SceneCenter.z);
  glRotatef(modelxrot, 1, 0, 0);
  glRotatef(modelyrot, 0, 1, 0);
  glRotatef(modelzrot, 0, 0, 1);
  glutSolidTorus(200, 800, 50, 50);
 glPopMatrix(); 
}
void CShadowTestView::OnSize(UINT nType, int cx, int cy)
{
 CView::OnSize(nType, cx, cy);
 if (cy == 0) cy = 1;
 glMatrixMode(GL_PROJECTION); 
 glLoadIdentity();
 gluPerspective(m_lfFovxy, 1.0, m_lfZNear, m_lfZFar);
 glMatrixMode(GL_MODELVIEW);
 glLoadIdentity();
 glViewport(0,0,cx, cy);
}
================================================
CDEM类
================================================
// DEM.cpp : implementation of the CDEM class
//
#include "stdafx.h"
#include "DEM.h"

//
// Construction/Destruction
//
CDEM::CDEM()
{
 Header.m_fLeftUpX      = 0;
 Header.m_fLeftUpY      = 0;
 Header.m_iRow          = 0;
 Header.m_iCol          = 0;
 Header.m_fIntervalRow  = 0;
 Header.m_fIntervalCol  = 0;
 Header.m_iMax_Height   = 0;
 Header.m_iMin_Height   = 0;  
 m_pfHeight             = NULL;
}
CDEM::~CDEM()
{
 if(m_pfHeight)
  delete []m_pfHeight;
}
BOOL CDEM::LoadGRDFile(CString filename)
{
 //文件格式:文件头(结构体)<CR>数据体(每行十个高程数据<CR>)
 FILE* fp;
 fp = fopen(filename, "r"); 
 // 判断文件是否存在
 if ( fp == NULL ) 
 {
  // 如果文件没有打开,显示错误信息
  MessageBox(NULL, "Can't find the height map!", "Error", MB_OK);
  return FALSE;
 }
 
 //读取文件头
 fscanf(fp, "DataMark:NSDTF-%s/n", &Header.DataMark);
 fscanf(fp, "Version:%f/n",        &Header.Vesion);
 fscanf(fp, "Unit:%c/n",           &Header.Unit);
 fscanf(fp, "Alpha:%f/n",          &Header.Alpha);
 fscanf(fp, "Compress:%d/n",       &Header.Compress);
 fscanf(fp, "X0:%f/n",             &Header.m_fLeftUpX);
 fscanf(fp, "Y0:%f/n",             &Header.m_fLeftUpY);
 fscanf(fp, "DX:%f/n",             &Header.m_fIntervalRow);
 fscanf(fp, "DY:%f/n",             &Header.m_fIntervalCol);
 fscanf(fp, "Row:%d/n",            &Header.m_iRow);
 fscanf(fp, "Col:%d/n",            &Header.m_iCol);
 fscanf(fp, "ValueType:%s/n",      &Header.ValueType);
 fscanf(fp, "Hzoom:%d/n",          &Header.HZoom);
 fscanf(fp, "MinV:%f/n",           &Header.m_iMin_Height);
 fscanf(fp, "MaxV:%f/n",           &Header.m_iMax_Height);
 //读取数据体
 //高程值按列存储
 m_pfHeight = new float[Header.m_iRow * Header.m_iCol];
 for (int i=0; i<Header.m_iRow * Header.m_iCol; i++)
 {
  fscanf(fp, "%f", &m_pfHeight[i]);
  m_pfHeight[i] /= Header.HZoom;//高程换算为真实值
  m_pfHeight[i] *= 2;//临时处理
 }
 // 判断操作是否成功
 int result = ferror( fp );
 // 如果收到错误信息
 if (result)
 {
  MessageBox(NULL, "Can't get data!", "Error", MB_OK);
  return FALSE;
 }
 Header.m_iMin_Height /= Header.HZoom;//最小高程换算为真实值
 Header.m_iMax_Height /= Header.HZoom;//最大高程换算为真实值

 //格网间距从度换算成米
 Header.m_fIntervalRow = (float)193.0;
 Header.m_fIntervalCol = (float)222.0;
// Header.m_fIntervalRow = (float)120;//临时处理
// Header.m_fIntervalCol = (float)120;//临时处理
 // 
 m_v3DemCenter.x = ((Header.m_iRow /2)*Header.m_fIntervalRow);
 m_v3DemCenter.y = m_pfHeight[(Header.m_iCol /2)*Header.m_iRow + Header.m_iRow/2];
 m_v3DemCenter.z = ((Header.m_iCol /2)*Header.m_fIntervalCol);
 m_v3DemSize.x = Header.m_iRow*Header.m_fIntervalRow;
 m_v3DemSize.y = Header.m_iMax_Height-Header.m_iMin_Height;
 m_v3DemSize.z = Header.m_iCol*Header.m_fIntervalCol;
 fclose(fp);
 return TRUE;
}

BOOL CDEM::LoadGRDTex(CString filename)
{
 _AUX_RGBImageRec *Image;    
    if(Image = auxDIBImageLoadA( (const char*) filename ))
 {
  glGenTextures(1, &m_iDemTextureID);
  glBindTexture(GL_TEXTURE_2D, m_iDemTextureID);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S,GL_REPEAT);
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,GL_REPEAT);
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,GL_LINEAR_MIPMAP_NEAREST);
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_NEAREST);
  glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
  glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
  gluBuild2DMipmaps(GL_TEXTURE_2D, 3, Image->sizeX, Image->sizeY, GL_RGB,
                              GL_UNSIGNED_BYTE, Image->data);
 }
 
 if(Image)
 {          
  if (Image->data)
   delete Image->data;   
  delete Image;
 }
 if (m_iDemTextureID !=0) return TRUE;
 else return FALSE;
}
void CDEM::CreateColorList()
{
 DemColorList = glGenLists(1);
 glNewList(DemColorList, GL_COMPILE); 
  glBegin(GL_TRIANGLES);
   CS3dVector pTriangle[4];//逆时针四个端点
   int i = 0, j = 0;
   for ( i=0; i<Header.m_iRow-1; i++)
   {
    for ( j=0; j<Header.m_iCol-1; j++)
    {
     pTriangle[0].x = j*Header.m_fIntervalRow;
     pTriangle[0].y = m_pfHeight[(i*Header.m_iCol) + j];
     pTriangle[0].z = i*Header.m_fIntervalCol;
     pTriangle[1].x = (j + 1)*Header.m_fIntervalRow;
     pTriangle[1].y = m_pfHeight[(i*Header.m_iCol) + (j + 1)];
     pTriangle[1].z = i*Header.m_fIntervalCol;
     pTriangle[2].x = (j + 1)*Header.m_fIntervalRow;
     pTriangle[2].y = m_pfHeight[(i + 1)*Header.m_iCol + (j + 1)];
     pTriangle[2].z = (i + 1)*Header.m_fIntervalCol;
     pTriangle[3].x = j*Header.m_fIntervalRow;
     pTriangle[3].y = m_pfHeight[((i + 1)*Header.m_iCol) + j];
     pTriangle[3].z = (i + 1)*Header.m_fIntervalCol;
     
     glColor3f(0.5, 0.3, 0);
//     SetColor(pTriangle[0].z);
     glVertex3f(pTriangle[0].x, pTriangle[0].y, pTriangle[0].z);
//     SetColor(pTriangle[1].z);
     glVertex3f(pTriangle[1].x, pTriangle[1].y, pTriangle[1].z);
//     SetColor(pTriangle[2].z);
     glVertex3f(pTriangle[2].x, pTriangle[2].y, pTriangle[2].z);
     glColor3f(0, 0.5, 0.3);
//     SetColor(pTriangle[0].z);
     glVertex3f(pTriangle[0].x, pTriangle[0].y, pTriangle[0].z);
//     SetColor(pTriangle[2].z);
     glVertex3f(pTriangle[2].x, pTriangle[2].y, pTriangle[2].z);
//     SetColor(pTriangle[3].z);
     glVertex3f(pTriangle[3].x, pTriangle[3].y, pTriangle[3].z);
    }
   }
  glEnd();
 glEndList();
}

void CDEM::CreatTextureList()
{
 float r[4], s[4];
 
 DemTextureList = glGenLists(1);
 glNewList(DemTextureList, GL_COMPILE);
// glColor3f(1,1,1);
// glNormal3f(0,0,1);
 glBindTexture(GL_TEXTURE_2D, m_iDemTextureID);
 glEnable(GL_TEXTURE_2D); 
  glBegin(GL_TRIANGLES);
   CS3dVector pTriangle[4];//逆时针四个端点
   int i = 0, j = 0;
   for ( i=0; i<Header.m_iRow-1; i++)
   {
    for ( j=0; j<Header.m_iCol-1; j++)
    {
     pTriangle[0].x = j*Header.m_fIntervalRow;
     pTriangle[0].y = m_pfHeight[(i*Header.m_iCol) + j];
     pTriangle[0].z = i*Header.m_fIntervalCol;
     pTriangle[1].x = (j + 1)*Header.m_fIntervalRow;
     pTriangle[1].y = m_pfHeight[(i*Header.m_iCol) + (j + 1)];
     pTriangle[1].z = i*Header.m_fIntervalCol;
     pTriangle[2].x = (j + 1)*Header.m_fIntervalRow;
     pTriangle[2].y = m_pfHeight[(i + 1)*Header.m_iCol + (j + 1)];
     pTriangle[2].z = (i + 1)*Header.m_fIntervalCol;
     pTriangle[3].x = j*Header.m_fIntervalRow;
     pTriangle[3].y = m_pfHeight[((i + 1)*Header.m_iCol) + j];
     pTriangle[3].z = (i + 1)*Header.m_fIntervalCol;
     
     r[0]=pTriangle[0].x/m_v3DemSize.x;
     r[1]=pTriangle[1].x/m_v3DemSize.x;
     r[2]=pTriangle[2].x/m_v3DemSize.x;
     r[3]=pTriangle[3].x/m_v3DemSize.x;
     s[0]=pTriangle[0].z/m_v3DemSize.z;
     s[1]=pTriangle[1].z/m_v3DemSize.z;
     s[2]=pTriangle[2].z/m_v3DemSize.z;
     s[3]=pTriangle[3].z/m_v3DemSize.z;
     
     glTexCoord2f(r[0],s[0]);
     glVertex3f(pTriangle[0].x, pTriangle[0].y, pTriangle[0].z);
     glTexCoord2f(r[1],s[1]);
     glVertex3f(pTriangle[1].x, pTriangle[1].y, pTriangle[1].z);
     glTexCoord2f(r[2],s[2]);
     glVertex3f(pTriangle[2].x, pTriangle[2].y, pTriangle[2].z);
     glTexCoord2f(r[0],s[0]);
     glVertex3f(pTriangle[0].x, pTriangle[0].y, pTriangle[0].z);
     glTexCoord2f(r[2],s[2]);
     glVertex3f(pTriangle[2].x, pTriangle[2].y, pTriangle[2].z);
     glTexCoord2f(r[3],s[3]);
     glVertex3f(pTriangle[3].x, pTriangle[3].y, pTriangle[3].z);
    }
   }
  glEnd();
  glDisable(GL_TEXTURE_2D);
 glEndList();
}
void CDEM::DisplayColorList()
{
 glCallList(DemColorList);
}
void CDEM::DisplayTextureList()
{
 glBindTexture(GL_TEXTURE_2D, m_iDemTextureID);
 glEnable(GL_TEXTURE_2D);
 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
 glDisable(GL_LIGHTING);
 glColor3f(1,1,1);
 glCallList(DemTextureList);
 glEnable(GL_LIGHTING);
}
void CDEM::SetColor(float height)
{
// height /= 2;
 float r, g, b;
 float rH = 51, rL = 204;
 float gH = 91, gL = 173;
 float bH = 51, bL = 92;
 r = (rL + (rH - rL)*(height - Header.m_iMin_Height)/(Header.m_iMax_Height- Header.m_iMin_Height))/255;
 g = (gL + (gH - gL)*(height - Header.m_iMin_Height)/(Header.m_iMax_Height- Header.m_iMin_Height))/255;
 b = (bL + (bH - bL)*(height - Header.m_iMin_Height)/(Header.m_iMax_Height- Header.m_iMin_Height))/255;
 glColor3f(r, g, b);
}
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值