主题:[原创]Shadow Mapping
最近在学习Shadow Mapping,其原理很简单,在网上找了一个教程http://www.paulsprojects.net/tutorials/smt/smt.html,发现这个教程对于没有贴纹理的场景work,但对于那些贴有纹理的场景就束手无策了。OK,这是我想做的:
[b] (1)把红色的圆环换成一个大立方体,并且贴上纹理
(2)把四个绿球中两个对角的绿球换成两个小立方体并贴上纹理
(3)要求产生正确的阴影(包括球和小立方体在大立方体上的阴影和在平面上的阴影)[/b]
注:可以读入一幅图像作为纹理,图片(bmp格式)任意
我倒腾了很久,发现要么就是贴入了纹理shadow不正确,要么就是shadow正确了纹理却不对了,在网上找了很多资料,说的都不是很全,没有仔细说明怎么解决,经过我的摸爬滚打慢慢摸索,发现问题出在此:贴纹理和Display函数中第一步产生的depth map(纹理形式保存)都是以GL_TEXTURE_0作为当前活动纹理单元,这样导致了混淆,应该用glActiveTexture把他们分开,具体参见scene.cpp中的drawCube函数。
此贴是我此前发的提问帖的答案http://bbs.pfan.cn/post-373100.html,最终还是自己解决了,天助自助者,呵呵,还是要感谢ZJU的杨瑞健学长的指点,指出我问题的所在,衷心感谢!!!
[b]在paulsprojects的Shadow Mapping原程序上的改动:
(1)修改了main.cpp里的Display函数(把glEnable (GL_CULL_FACE)换成glEnable (GL_POLYGON_FILL),glCullFace(GL_FRONT)换成glPolygonOffset(1.0,1.0),glCullFace(GL_BACK)换成glPolygonOffset(0.0,0.0),目的是为了在绘制立方体的时候避免某些免被CULL掉)。
(2)修改了main。cpp里的int main(int argc, char** argv)函数,在glutDisplayFunc(Display);这句前加上InitTexture();表示载入三幅bmp图片作为纹理。[/b]
[b](3)修改了scene.h函数,如下:[/b]
//////////////////////////////////////////////////////////////////////////////////////////
// scene.h
// Draw scene for shadow mapping
// Downloaded from: www.paulsprojects.net
// Created: 16th September 2003
//
// Copyright (c) 2006, Paul Baker
// Distributed under the New BSD Licence. (See accompanying file License.txt or copy at
// http://www.paulsprojects.net/NewBSDLicense.txt)
//////////////////////////////////////////////////////////////////////////////////////////
#ifndef SCENE_H
#define SCENE_H
void InitTexture();
void drawBox();
void DrawScene(float angle);
#endif //SCENE_H
[b](4)修改了Scene.cpp,如下:[/b]
//////////////////////////////////////////////////////////////////////////////////////////
// Scene.cpp
// Draw the scene for shadow mapping
// Downloaded from: www.paulsprojects.net
// Created: 16th September 2003
//
// Copyright (c) 2006, Paul Baker
// Distributed under the New BSD Licence. (See accompanying file License.txt or copy at
// http://www.paulsprojects.net/NewBSDLicense.txt)
//////////////////////////////////////////////////////////////////////////////////////////
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <stdio.h>
#include "GLee/GLee.h"
#include <GL/glut.h>
#include <GL/glaux.h>
#include "Maths/Maths.h"
#include "scene.h"
#pragma comment(lib, "glaux.lib")
#pragma comment(lib, "Glee.lib")
GLuint texID[3];
AUX_RGBImageRec *TextureImage[3];
void InitTexture()
{
glClearColor(0.0,0.0,0.0,0.0);
glShadeModel(GL_SMOOTH);
glEnable(GL_DEPTH_TEST);
//load first texture image
TextureImage[0]=auxDIBImageLoad("earth.bmp");
glPixelStorei(GL_UNPACK_ALIGNMENT,1);
glGenTextures(1,&texID[0]);
glBindTexture(GL_TEXTURE_2D,texID[0]);
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_NEAREST);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);
glTexImage2D(GL_TEXTURE_2D, 0,GL_RGB, TextureImage[0]->sizeX, TextureImage[0]->sizeY,0, GL_RGB, GL_UNSIGNED_BYTE, TextureImage[0]->data);
//load second texture image
TextureImage[1]=auxDIBImageLoad("castle.bmp");
glPixelStorei(GL_UNPACK_ALIGNMENT,1);
glGenTextures(1,&texID[1]);
glBindTexture(GL_TEXTURE_2D,texID[1]);
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_NEAREST);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);
glTexImage2D(GL_TEXTURE_2D, 0,GL_RGB, TextureImage[1]->sizeX, TextureImage[1]->sizeY,0, GL_RGB, GL_UNSIGNED_BYTE, TextureImage[1]->data);
//load third texture image
TextureImage[2]=auxDIBImageLoad("sea.bmp");
glPixelStorei(GL_UNPACK_ALIGNMENT,1);
glGenTextures(1,&texID[2]);
glBindTexture(GL_TEXTURE_2D,texID[2]);
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_NEAREST);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);
glTexImage2D(GL_TEXTURE_2D, 0,GL_RGB, TextureImage[2]->sizeX, TextureImage[2]->sizeY,0, GL_RGB, GL_UNSIGNED_BYTE, TextureImage[2]->data);
}
void drawCube(GLfloat width,GLuint texName)//draw a cube with a specific texture
{
GLfloat t=width/2;
GLfloat point1[]={-t, t, t};
GLfloat point2[]={ t, t, t};
GLfloat point3[]={ t, t,-t};
GLfloat point4[]={-t, t,-t};
GLfloat point5[]={-t,-t, t};
GLfloat point6[]={ t,-t, t};
GLfloat point7[]={ t,-t,-t};
GLfloat point8[]={-t,-t,-t};
glActiveTexture(GL_TEXTURE0);//key step!!!========================
glEnable(GL_TEXTURE_2D);
//glTexEnvf(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_MODULATE);
glBindTexture(GL_TEXTURE_2D,texName);
glBegin(GL_QUADS);
//top face
glNormal3f(0.0,1.0,0.0);
glTexCoord2f(0.0,0.0); glVertex3fv(point1);
glTexCoord2f(1.0,0.0); glVertex3fv(point2);
glTexCoord2f(1.0,1.0); glVertex3fv(point3);
glTexCoord2f(0.0,1.0); glVertex3fv(point4);
//bottom face
glNormal3f(0.0,-1.0,0.0);
glTexCoord2f(0.0,0.0); glVertex3fv(point5);
glTexCoord2f(1.0,0.0); glVertex3fv(point6);
glTexCoord2f(1.0,1.0); glVertex3fv(point7);
glTexCoord2f(0.0,1.0); glVertex3fv(point8);
//left face
glNormal3f(-1.0,0.0,0.0);
glTexCoord2f(0.0,0.0); glVertex3fv(point8);
glTexCoord2f(1.0,0.0); glVertex3fv(point5);
glTexCoord2f(1.0,1.0); glVertex3fv(point1);
glTexCoord2f(0.0,1.0); glVertex3fv(point4);
//right face
glNormal3f(1.0,0.0,0.0);
glTexCoord2f(0.0,0.0); glVertex3fv(point6);
glTexCoord2f(1.0,0.0); glVertex3fv(point7);
glTexCoord2f(1.0,1.0); glVertex3fv(point3);
glTexCoord2f(0.0,1.0); glVertex3fv(point2);
//front face
glNormal3f(0.0,0.0,1.0);
glTexCoord2f(0.0,0.0); glVertex3fv(point5);
glTexCoord2f(1.0,0.0); glVertex3fv(point6);
glTexCoord2f(1.0,1.0); glVertex3fv(point2);
glTexCoord2f(0.0,1.0); glVertex3fv(point1);
//back face
glNormal3f(0.0,0.0,-1.0);
glTexCoord2f(0.0,0.0); glVertex3fv(point8);
glTexCoord2f(1.0,0.0); glVertex3fv(point7);
glTexCoord2f(1.0,1.0); glVertex3fv(point3);
glTexCoord2f(0.0,1.0); glVertex3fv(point4);
glEnd();
glDisable(GL_TEXTURE_2D);
glActiveTexture(GL_TEXTURE1);//key step!!!========================
}
void DrawScene(float angle)
{
//Display lists for objects
static GLuint spheresList=0, cubeList=0, baseList=0;
//Create spheres list if necessary
if(!spheresList)
{
spheresList=glGenLists(1);
glNewList(spheresList, GL_COMPILE);
{
glPushMatrix();
glTranslatef(0.45f, 1.0f, 0.45f);
glColor3f(0.0f, 1.0f, 0.0f);
glutSolidSphere(0.2, 24, 24);
glTranslatef(-0.9f, 0.0f, 0.0f);
glColor3f(1.0f, 1.0f, 1.0f);
drawCube(0.4,texID[1]);//draw first small cube
glTranslatef(0.0f, 0.0f,-0.9f);
glColor3f(0.0f, 1.0f, 0.0f);
glutSolidSphere(0.2, 24, 24);
glTranslatef(0.9f, 0.0f, 0.0f);
glColor3f(1.0f, 1.0f, 1.0f);
drawCube(0.4,texID[2]);//draw second small cube
glPopMatrix();
}
glEndList();
}
//Create torus if necessary
if(!cubeList)
{
cubeList=glGenLists(1);
glNewList(cubeList, GL_COMPILE);
{
glColor3f(1.0f, 1.0f, 1.0f);
glPushMatrix();
drawCube(1.0,texID[0]);//draw big cube
glPopMatrix();
}
glEndList();
}
//Create base if necessary
if(!baseList)
{
baseList=glGenLists(1);
glNewList(baseList, GL_COMPILE);
{
glColor3f(0.0f, 0.0f, 1.0f);
glPushMatrix();
glTranslatef(0.0,-1.5,0.0);
glScalef(3.0f, 0.05f, 3.0f);
glutSolidCube(2.0f);
glPopMatrix();
}
glEndList();
}
////Draw objects
//glCallList(baseList);
//glCallList(cubeList);
//glPushMatrix();
// glRotatef(angle, 0.0f, 1.0f, 0.0f);
// glCallList(spheresList);
//glPopMatrix();
//Draw objects
glCallList(baseList);
glPushMatrix();
glRotatef(0.4*angle, 0.0f, 1.0f, 0.0f);
glCallList(cubeList);
glRotatef(0.6*angle, 0.0f, 1.0f, 0.0f);
glCallList(spheresList);
glPopMatrix();
}
[b] (1)把红色的圆环换成一个大立方体,并且贴上纹理
(2)把四个绿球中两个对角的绿球换成两个小立方体并贴上纹理
(3)要求产生正确的阴影(包括球和小立方体在大立方体上的阴影和在平面上的阴影)[/b]
注:可以读入一幅图像作为纹理,图片(bmp格式)任意
我倒腾了很久,发现要么就是贴入了纹理shadow不正确,要么就是shadow正确了纹理却不对了,在网上找了很多资料,说的都不是很全,没有仔细说明怎么解决,经过我的摸爬滚打慢慢摸索,发现问题出在此:贴纹理和Display函数中第一步产生的depth map(纹理形式保存)都是以GL_TEXTURE_0作为当前活动纹理单元,这样导致了混淆,应该用glActiveTexture把他们分开,具体参见scene.cpp中的drawCube函数。
此贴是我此前发的提问帖的答案http://bbs.pfan.cn/post-373100.html,最终还是自己解决了,天助自助者,呵呵,还是要感谢ZJU的杨瑞健学长的指点,指出我问题的所在,衷心感谢!!!
[b]在paulsprojects的Shadow Mapping原程序上的改动:
(1)修改了main.cpp里的Display函数(把glEnable (GL_CULL_FACE)换成glEnable (GL_POLYGON_FILL),glCullFace(GL_FRONT)换成glPolygonOffset(1.0,1.0),glCullFace(GL_BACK)换成glPolygonOffset(0.0,0.0),目的是为了在绘制立方体的时候避免某些免被CULL掉)。
(2)修改了main。cpp里的int main(int argc, char** argv)函数,在glutDisplayFunc(Display);这句前加上InitTexture();表示载入三幅bmp图片作为纹理。[/b]
[b](3)修改了scene.h函数,如下:[/b]
//////////////////////////////////////////////////////////////////////////////////////////
// scene.h
// Draw scene for shadow mapping
// Downloaded from: www.paulsprojects.net
// Created: 16th September 2003
//
// Copyright (c) 2006, Paul Baker
// Distributed under the New BSD Licence. (See accompanying file License.txt or copy at
// http://www.paulsprojects.net/NewBSDLicense.txt)
//////////////////////////////////////////////////////////////////////////////////////////
#ifndef SCENE_H
#define SCENE_H
void InitTexture();
void drawBox();
void DrawScene(float angle);
#endif //SCENE_H
[b](4)修改了Scene.cpp,如下:[/b]
//////////////////////////////////////////////////////////////////////////////////////////
// Scene.cpp
// Draw the scene for shadow mapping
// Downloaded from: www.paulsprojects.net
// Created: 16th September 2003
//
// Copyright (c) 2006, Paul Baker
// Distributed under the New BSD Licence. (See accompanying file License.txt or copy at
// http://www.paulsprojects.net/NewBSDLicense.txt)
//////////////////////////////////////////////////////////////////////////////////////////
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <stdio.h>
#include "GLee/GLee.h"
#include <GL/glut.h>
#include <GL/glaux.h>
#include "Maths/Maths.h"
#include "scene.h"
#pragma comment(lib, "glaux.lib")
#pragma comment(lib, "Glee.lib")
GLuint texID[3];
AUX_RGBImageRec *TextureImage[3];
void InitTexture()
{
glClearColor(0.0,0.0,0.0,0.0);
glShadeModel(GL_SMOOTH);
glEnable(GL_DEPTH_TEST);
//load first texture image
TextureImage[0]=auxDIBImageLoad("earth.bmp");
glPixelStorei(GL_UNPACK_ALIGNMENT,1);
glGenTextures(1,&texID[0]);
glBindTexture(GL_TEXTURE_2D,texID[0]);
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_NEAREST);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);
glTexImage2D(GL_TEXTURE_2D, 0,GL_RGB, TextureImage[0]->sizeX, TextureImage[0]->sizeY,0, GL_RGB, GL_UNSIGNED_BYTE, TextureImage[0]->data);
//load second texture image
TextureImage[1]=auxDIBImageLoad("castle.bmp");
glPixelStorei(GL_UNPACK_ALIGNMENT,1);
glGenTextures(1,&texID[1]);
glBindTexture(GL_TEXTURE_2D,texID[1]);
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_NEAREST);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);
glTexImage2D(GL_TEXTURE_2D, 0,GL_RGB, TextureImage[1]->sizeX, TextureImage[1]->sizeY,0, GL_RGB, GL_UNSIGNED_BYTE, TextureImage[1]->data);
//load third texture image
TextureImage[2]=auxDIBImageLoad("sea.bmp");
glPixelStorei(GL_UNPACK_ALIGNMENT,1);
glGenTextures(1,&texID[2]);
glBindTexture(GL_TEXTURE_2D,texID[2]);
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_NEAREST);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);
glTexImage2D(GL_TEXTURE_2D, 0,GL_RGB, TextureImage[2]->sizeX, TextureImage[2]->sizeY,0, GL_RGB, GL_UNSIGNED_BYTE, TextureImage[2]->data);
}
void drawCube(GLfloat width,GLuint texName)//draw a cube with a specific texture
{
GLfloat t=width/2;
GLfloat point1[]={-t, t, t};
GLfloat point2[]={ t, t, t};
GLfloat point3[]={ t, t,-t};
GLfloat point4[]={-t, t,-t};
GLfloat point5[]={-t,-t, t};
GLfloat point6[]={ t,-t, t};
GLfloat point7[]={ t,-t,-t};
GLfloat point8[]={-t,-t,-t};
glActiveTexture(GL_TEXTURE0);//key step!!!========================
glEnable(GL_TEXTURE_2D);
//glTexEnvf(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_MODULATE);
glBindTexture(GL_TEXTURE_2D,texName);
glBegin(GL_QUADS);
//top face
glNormal3f(0.0,1.0,0.0);
glTexCoord2f(0.0,0.0); glVertex3fv(point1);
glTexCoord2f(1.0,0.0); glVertex3fv(point2);
glTexCoord2f(1.0,1.0); glVertex3fv(point3);
glTexCoord2f(0.0,1.0); glVertex3fv(point4);
//bottom face
glNormal3f(0.0,-1.0,0.0);
glTexCoord2f(0.0,0.0); glVertex3fv(point5);
glTexCoord2f(1.0,0.0); glVertex3fv(point6);
glTexCoord2f(1.0,1.0); glVertex3fv(point7);
glTexCoord2f(0.0,1.0); glVertex3fv(point8);
//left face
glNormal3f(-1.0,0.0,0.0);
glTexCoord2f(0.0,0.0); glVertex3fv(point8);
glTexCoord2f(1.0,0.0); glVertex3fv(point5);
glTexCoord2f(1.0,1.0); glVertex3fv(point1);
glTexCoord2f(0.0,1.0); glVertex3fv(point4);
//right face
glNormal3f(1.0,0.0,0.0);
glTexCoord2f(0.0,0.0); glVertex3fv(point6);
glTexCoord2f(1.0,0.0); glVertex3fv(point7);
glTexCoord2f(1.0,1.0); glVertex3fv(point3);
glTexCoord2f(0.0,1.0); glVertex3fv(point2);
//front face
glNormal3f(0.0,0.0,1.0);
glTexCoord2f(0.0,0.0); glVertex3fv(point5);
glTexCoord2f(1.0,0.0); glVertex3fv(point6);
glTexCoord2f(1.0,1.0); glVertex3fv(point2);
glTexCoord2f(0.0,1.0); glVertex3fv(point1);
//back face
glNormal3f(0.0,0.0,-1.0);
glTexCoord2f(0.0,0.0); glVertex3fv(point8);
glTexCoord2f(1.0,0.0); glVertex3fv(point7);
glTexCoord2f(1.0,1.0); glVertex3fv(point3);
glTexCoord2f(0.0,1.0); glVertex3fv(point4);
glEnd();
glDisable(GL_TEXTURE_2D);
glActiveTexture(GL_TEXTURE1);//key step!!!========================
}
void DrawScene(float angle)
{
//Display lists for objects
static GLuint spheresList=0, cubeList=0, baseList=0;
//Create spheres list if necessary
if(!spheresList)
{
spheresList=glGenLists(1);
glNewList(spheresList, GL_COMPILE);
{
glPushMatrix();
glTranslatef(0.45f, 1.0f, 0.45f);
glColor3f(0.0f, 1.0f, 0.0f);
glutSolidSphere(0.2, 24, 24);
glTranslatef(-0.9f, 0.0f, 0.0f);
glColor3f(1.0f, 1.0f, 1.0f);
drawCube(0.4,texID[1]);//draw first small cube
glTranslatef(0.0f, 0.0f,-0.9f);
glColor3f(0.0f, 1.0f, 0.0f);
glutSolidSphere(0.2, 24, 24);
glTranslatef(0.9f, 0.0f, 0.0f);
glColor3f(1.0f, 1.0f, 1.0f);
drawCube(0.4,texID[2]);//draw second small cube
glPopMatrix();
}
glEndList();
}
//Create torus if necessary
if(!cubeList)
{
cubeList=glGenLists(1);
glNewList(cubeList, GL_COMPILE);
{
glColor3f(1.0f, 1.0f, 1.0f);
glPushMatrix();
drawCube(1.0,texID[0]);//draw big cube
glPopMatrix();
}
glEndList();
}
//Create base if necessary
if(!baseList)
{
baseList=glGenLists(1);
glNewList(baseList, GL_COMPILE);
{
glColor3f(0.0f, 0.0f, 1.0f);
glPushMatrix();
glTranslatef(0.0,-1.5,0.0);
glScalef(3.0f, 0.05f, 3.0f);
glutSolidCube(2.0f);
glPopMatrix();
}
glEndList();
}
////Draw objects
//glCallList(baseList);
//glCallList(cubeList);
//glPushMatrix();
// glRotatef(angle, 0.0f, 1.0f, 0.0f);
// glCallList(spheresList);
//glPopMatrix();
//Draw objects
glCallList(baseList);
glPushMatrix();
glRotatef(0.4*angle, 0.0f, 1.0f, 0.0f);
glCallList(cubeList);
glRotatef(0.6*angle, 0.0f, 1.0f, 0.0f);
glCallList(spheresList);
glPopMatrix();
}