3D+OpenGL里的光照平面镜面反射以及漫游移动物体位置等的具体实现

3D+OpenGL里的光照平面镜面反射以及漫游移动物体位置等的具体实现

在实现过程中涉及到

1.opengl里的蒙版缓冲等相关知识

2.观察坐标系的转换摄像漫游等

3.此外图中的mirror图片为导入的mirror.jpg文件

4.在纹理贴图中

unsigned int ATLLoadTexture(const char* fileName)函数实现了jpg/bmp等图片的加载<pre name="code" class="cpp">//加载jpg/bmp等各种纹理返回纹理id

 


#define GLUT_DISABLE_ATEXIT_HACK 
#include <gl/glew.h>/*GL_BGR*/
#include <atlimage.h>
#include <GL/glut.h>


//全局变量设置
// 旋转变量
static float g_xRot = 0.0f;
static float g_yRot = 0.0f;

float g_lightPos[] = { 4.0f, 4.0f,2.0f, 1.0f };
float g_ambientLight[] = { 0.0f, 0.0f, 1.0f, 1.0f };

float g_cameraX = 0.0, g_cameraY = 0.0, g_cameraZ = 10.0;

unsigned int g_mirrorTex;


//加载jpg/bmp等各种纹理返回纹理id
unsigned int ATLLoadTexture(const char* fileName)
{
	BITMAP bm;
	GLuint idTexture = 0;
	CImage img;             //需要头文件atlimage.h  
	HRESULT hr = img.Load(fileName);
	if (!SUCCEEDED(hr))   //文件加载失败  
	{
		MessageBox(NULL, "文件加载失败", "ERROR", 0);
		return NULL;
	}
	HBITMAP hbmp = img;
	if (!GetObject(hbmp, sizeof(bm), &bm))
		return 0;

	glGenTextures(1, &idTexture);
	if (idTexture)
	{
		glBindTexture(GL_TEXTURE_2D, idTexture);
		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);
		glPixelStoref(GL_PACK_ALIGNMENT, 1);
		glTexImage2D(GL_TEXTURE_2D, 0, 3, bm.bmWidth, bm.bmHeight, 0, GL_BGR, GL_UNSIGNED_BYTE, bm.bmBits); //这里不是GL_RGB  
	}
	return idTexture;
}


void init()
{
	glClearColor(0.0, 0.0, 0.0, 0.0);
	glShadeModel(GL_SMOOTH);
	g_mirrorTex = ATLLoadTexture("data/mirror.jpg");
}

//绘制球体的函数
void drawSphere()
{
	//光源设置
	glEnable(GL_LIGHT0);
	glEnable(GL_LIGHTING);
	glEnable(GL_COLOR_MATERIAL);
	glLightfv(GL_LIGHT0, GL_POSITION, g_lightPos);
	glLightfv(GL_LIGHT0, GL_AMBIENT, g_ambientLight);

	
	glPushMatrix();
	glPushAttrib(GL_CURRENT_BIT);
	glColor3f(0.0, 0.5,0.8);
	glTranslatef(g_xRot, g_yRot, 4);//物体位置
	glutSolidSphere(0.3, 20, 20);
	glPopMatrix();
	glPopAttrib();
}

void display()
{
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

	//设置观察点
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	gluPerspective(60, 1, 0.1, 500);
	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();
	gluLookAt(g_cameraX,g_cameraY,g_cameraZ, 0, 0, 0, 0, 1, 0);
	glEnable(GL_DEPTH_TEST);
	glDisable(GL_STENCIL_TEST);
	drawSphere();

	glClearStencil(0x0);
	glClear(GL_STENCIL_BUFFER_BIT);
	glStencilFunc(GL_ALWAYS, 1, 0xFF);
	glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
	glEnable(GL_STENCIL_TEST);
	glDisable(GL_LIGHTING);


	
	/*绘制平面镜子*/
	glPushMatrix();
	glPushAttrib(GL_CURRENT_BIT);
	glColor3f(1.0f, 1.0f, 1.0f);
	glDepthMask(GL_FALSE);//设置深度缓冲区为只读
	glEnable(GL_TEXTURE_2D);
	glBindTexture(GL_TEXTURE_2D, g_mirrorTex);
	glBegin(GL_QUADS);
	//前面
	glTexCoord2f(0.0f, 0.0f); glVertex3f(-2.0f, -2.0f, 1.0f);	// 纹理和四边形的左下
	glTexCoord2f(1.0f, 0.0f); glVertex3f(2.0f, -2.0f, 1.0f);	// 纹理和四边形的右下
	glTexCoord2f(1.0f, 1.0f); glVertex3f(2.0f, 2.0f, 1.0f);	    // 纹理和四边形的右上
	glTexCoord2f(0.0f, 1.0f); glVertex3f(-2.0f, 2.0f, 1.0f);	// 纹理和四边形的左上
	glEnd();
	glDisable(GL_TEXTURE_2D);
	glPopMatrix();
	glPopAttrib();

	/*绘制光源体*/

	glPushMatrix();
	glTranslatef(g_lightPos[0], g_lightPos[1], g_lightPos[2]);
	glColor3f(1.0, 1.0, 1.0);
	glutSolidSphere(0.1f, 20, 20);
	glPopMatrix();


	glDepthMask(GL_TRUE);//重新启用深度缓冲区
	///明确说明函数的测试功能GL_NEVER,,GL_LESS, GL_LEQUAL,
	//GL_GREATER, GL_GEQUAL,,GL_EQUAL, GL_NOTEQUAL和 GL_ALWAYS。
	//初始化的值是GL_ALWAYS
	//ref
	//明确说明该模板测试的引用值。 ref 值被限制在0~2 ^ (n - 1)间,
	//其中n是模板缓存中位平面数。初始化值是0
	//mask
	//	该参数表示一个模板,用来和ref值以及存储的模板值做与运算。初始化值是全1
	//要允许或禁止该测试的话,使用glEnable(GL_STENCIL_TEST)或glDisable(GL_STENCIL_TEST)
	glStencilFunc(GL_EQUAL, 1, 0xFF);//0xff==255
	//glStencilOp函数,它用来根据比较结果修改蒙板缓存区中的值
	//sfail当蒙板测试失败时所执行的操作
	//zfail当蒙板测试通过,深度测试失败时所执行的操作
    //zpass当蒙板测试通过,深度测试通过时所执行的操作
	glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
	glScalef(1.0f, 1.0f, -1.0f);//镜子里的影子方向取反
	glPushAttrib(GL_CURRENT_BIT);
	drawSphere();
	glPopAttrib();

	glutSwapBuffers();
}



void NormalKeys(unsigned char key, int x, int y)
{
	switch (key) {
	case VK_ESCAPE:exit(0); break;
		/*摄像机移动命令*/
	case 'w': g_cameraZ -= 1.0; glutPostRedisplay(); break;
	case 's': g_cameraZ += 1.0; glutPostRedisplay(); break;
	case 'a': g_cameraX += 1.0; glutPostRedisplay(); break;
	case 'd': g_cameraX -= 1.0; glutPostRedisplay(); break; 
	default:break;

	}
}


void SpecialKeys(int key, int x, int y)
{
	if (key == GLUT_KEY_UP)
		g_yRot += 0.1f;
	if (key == GLUT_KEY_DOWN)
		g_yRot -= 0.1f;
	if (key == GLUT_KEY_LEFT)
		g_xRot -= 0.1f;
	if (key == GLUT_KEY_RIGHT)
		g_xRot += 0.1f;
	

	// Refresh the Window
	glutPostRedisplay();
}

int main(int argc, char** argv)
{
	glutInit(&argc, argv);
	glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_STENCIL | GLUT_DEPTH);
	glutInitWindowSize(1376, 768);
	glutInitWindowPosition(0, 0);
	glutCreateWindow("镜面反射");
	init();
	glutDisplayFunc(display);
	//glutReshapeFunc(reshape);
	glutKeyboardFunc(NormalKeys);
	glutSpecialFunc(SpecialKeys);
	glutMainLoop();
	return 0;
}
镜面反射实现的结果截图:



  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值