环境映射

// WinMain.cpp : 定义应用程序的入口点。
//
#pragma region 头文件,宏定义
//include
#include "stdafx.h"
#include "WinMain.h"
#include 

#include 
#include 

#include 
#include 
#include 
#include 
#include "bitmap.h"
//define
#define MAX_LOADSTRING 100
#define  BITMAP_ID 0X4D42		//位图标识ID
// 全局变量:
HDC g_HDC;
bool fullScreen = false;
//鼠标,视点变量
int mouseX, mouseY;		//鼠标坐标
float cameraX, cameraY, cameraZ; //视点坐标

//变量定义
typedef struct  
{
	int width;
	int height;
	unsigned int texID;
	unsigned char *data;
}texture_t;
float angle = 0.0f;				//圆环旋转角度

texture_t *envTex;
texture_t *skyTex;

texture_t *LoadTextureFile(char *filename)
{
	BITMAPINFOHEADER texInfo;
	texture_t *thisTex;
	//为纹理数据结构分配内存
	thisTex = (texture_t*)malloc(sizeof(texture_t));
	if(thisTex == NULL)
		return NULL;
	//载入纹理数据并检查其有效性
	thisTex->data = LoadBitmapFile(filename, &texInfo);
	if (thisTex->data == NULL)
	{
		free(thisTex);
		return NULL;
	}
	//为纹理设置相应的宽度和高度信息
	thisTex->width = texInfo.biWidth;
	thisTex->height = texInfo.biHeight;
	//为此纹理生成相应的纹理对象
	glGenTextures(1,&thisTex->texID);
	return thisTex;
}
bool loadAllTextures()
{
	//载入环境纹理数据
	envTex = LoadTextureFile("darksky-sphere.bmp");
	if(envTex == NULL)
		return false;
	skyTex = LoadTextureFile("darksky.bmp");
	if(skyTex == NULL)
		return false;
	//将环境纹理设置为进行双线性插值过滤处理的mipmap
	glBindTexture(GL_TEXTURE_2D , envTex->texID);
	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_REPEAT);
	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT);
	gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGB, envTex->width, envTex->height,GL_RGB,GL_UNSIGNED_BYTE,envTex->data);
	//设置天空背景纹理
	glBindTexture(GL_TEXTURE_2D, skyTex->texID);
	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_REPEAT);
	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT);
	gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGB, skyTex->width, skyTex->height,GL_RGB,GL_UNSIGNED_BYTE,skyTex->data);

}

void Render()
{
	if (angle > 360.0f)
	{
		angle = .0f;
	}
	angle += 0.2f;
	//清理屏幕和深度缓存
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
	glLoadIdentity();
	//绘制天空背景纹理
	glBindTexture(GL_TEXTURE_2D, skyTex->texID);
	glBegin(GL_QUADS);
		glTexCoord2f(.0f, .0f);
		glVertex3f(-200.0f , -200.0f , -120.0f);
		glTexCoord2f(1.0f, 1.0f);
		glVertex3f(200.0f, -200.0f , -120.0f);
		glTexCoord2f(1.0f, 1.0f);
		glVertex3f(200.0f, 200.0f, -120.0f);
		glTexCoord2f(.0f, 1.0f);
		glVertex3f(-200.0f, 200.0f, -120.0f);
	glEnd();
	//后移物体并绕着三个轴旋转
	glTranslatef(.0f, .0f, -100.0f);
	glRotatef(angle, 1.0f, .0f, .0f);
	glRotatef(angle, .0f, 1.0f, .0f);
	glRotatef(angle , .0f, .0f, 1.0f);
	//设置环境映射,主要就是这几句,注意是sphere
	glTexGenf(GL_S, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);
	glTexGenf(GL_T, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);
	glEnable(GL_TEXTURE_GEN_S);
	glEnable(GL_TEXTURE_GEN_T);
	//绑定纹理映射
	glBindTexture(GL_TEXTURE_2D,envTex->texID);
	//实体圆环:内径10,外径20
	//auxSolidTeapot(5.0);
	auxSolidTorus(10.0f, 20.0f);
	glFlush();
	SwapBuffers(g_HDC);
}
// 此代码模块中包含的函数的前向声明:
LRESULT CALLBACK	WndProc(HWND, UINT, WPARAM, LPARAM);
//此函数用于应用程序的初始化和设置
void Initilize()
{
	glClearColor(.0f,.0f,.0f,.0f);		//背景色清理为黑色
	glShadeModel(GL_SMOOTH);	//使用平滑底纹
	glEnable(GL_DEPTH_TEST);	
	glEnable(GL_CULL_FACE);
	glFrontFace(GL_CCW);	//多边形逆时针方向为正面
	// glPolygonMode(GL_FRONT_AND_BACK ,GL_LINE );
	glEnable(GL_TEXTURE_2D);//启用2D纹理
//	InitializeTerrain();
	loadAllTextures();
}
void SetupPixelFormat(HDC hDC)
{
	int nPixelFormat;	//像素格式变量
	static PIXELFORMATDESCRIPTOR pfd = 
	{
		sizeof(PIXELFORMATDESCRIPTOR),
		1,		//版本号,总为1
		PFD_DRAW_TO_WINDOW |
		PFD_SUPPORT_OPENGL	   |
		PFD_DOUBLEBUFFER,
		PFD_TYPE_RGBA,
		32,
		0,0,0,0,0,0,
		0,
		0,
		0,
		0,0,0,0,
		16,
		0,
		0,
		PFD_MAIN_PLANE,
		0,
		0,0,0
	};
	//选择最匹配的像素格式,返回索引值
	nPixelFormat = ChoosePixelFormat(hDC,&pfd);
	//设置设备环境的像素格式
	SetPixelFormat(hDC,nPixelFormat,&pfd);
}
LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
	static HGLRC hRC;				//绘制环境
	static HDC hDC;					//设备环境
	int width,height;					//窗口宽高
	int oldMouseX, oldMouseY;	//旧的鼠标坐标
	switch (message)
	{
	case WM_CREATE:		//创建窗口
		hDC = GetDC(hwnd);
		g_HDC = hDC;
		SetupPixelFormat(hDC);
		//创建绘制环境,并将其设置为当前绘制环境
		hRC = wglCreateContext(hDC);
		wglMakeCurrent(hDC,hRC);
		return 0;
		break;
	case WM_CLOSE:
		//取消对绘图环境的选定并将其删除
		wglMakeCurrent(hDC,NULL);
		wglDeleteContext(hRC);
		//发送消息到消息队列
		PostQuitMessage(0);
		return 0;
		break;
	case WM_SIZE:
		height = HIWORD(lParam);		//得到窗口宽度和高度
		width = LOWORD(lParam);
		if (height == 0)
		{
			height = 1;
		}
		//重置窗口尺寸
		glViewport(0,0,width,height);
		glMatrixMode(GL_PROJECTION);	//设定投影矩阵
		glLoadIdentity();							//复位投影矩阵
		//计算窗口尺寸比例
		gluPerspective(54.0f,(GLfloat)width/(GLfloat)height,1.0f,1000.0f);
		glMatrixMode(GL_MODELVIEW);	//设定模型视图矩阵
		glLoadIdentity();	//复位模型视图矩阵
		return 0;
		break;
	case WM_MOUSEMOVE:
		oldMouseX = mouseX;
		oldMouseY = mouseY;
		//从windows系统得到鼠标坐标
		mouseX = LOWORD(lParam);
		mouseY = HIWORD(lParam);
		//限定视点的活动范围
		if(mouseY < 200)
			mouseY = 200;
		if (mouseY > 450)
		{
			mouseY = 450;
		}
		//鼠标向右移动
		if ( ( mouseX - oldMouseX) > 0)
		{
			angle += 3.0f;
		}
		else if(  ( mouseX - oldMouseX) < 0 )
			angle -= 3.0f;
		return 0;
		break;

	case WM_DESTROY:
		PostQuitMessage(0);
		break;
	default:
		break;
	}
	return DefWindowProc(hwnd, message, wParam, lParam);
	//return 0;
}
//计算三个点形成的面的法向量
//入口函数
int APIENTRY _tWinMain(
	HINSTANCE hInstance,
	HINSTANCE hPrevInstance,
	LPTSTR    lpCmdLine,
	int       nCmdShow
	)
{
	MSG msg;
	//HACCEL hAccelTable;
	bool done;	//应用程序退出标记
	HWND hWnd;
	WNDCLASSEX wcex;

	wcex.cbSize = sizeof(WNDCLASSEX);

	wcex.style			= CS_HREDRAW | CS_VREDRAW;
	wcex.lpfnWndProc	= WndProc;
	wcex.cbClsExtra		= 0;
	wcex.cbWndExtra		= 0;
	wcex.hInstance		= hInstance;
	wcex.hIcon			= LoadIcon(hInstance, MAKEINTRESOURCE(IDI_WINMAIN));
	wcex.hCursor		= LoadCursor(NULL, IDC_ARROW);
	wcex.hbrBackground	=NULL;// (HBRUSH)(COLOR_WINDOW+1);
	wcex.lpszMenuName	= NULL;//MAKEINTRESOURCE(IDC_WINMAIN);
	wcex.lpszClassName	= "MyClass";//szWindowClass;
	wcex.hIconSm		= LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));

	if (!RegisterClassEx(&wcex))
	{
		return 0;
	}
	// 初始化全局字符串
	//	LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
	//	LoadString(hInstance, IDC_WINMAIN, szWindowClass, MAX_LOADSTRING);

	hWnd = CreateWindowEx
		(
		NULL,
		"MyClass",
		"The OpenGL Game",
		WS_OVERLAPPEDWINDOW,
		100,100,
		800,800,
		NULL,
		NULL,
		hInstance,
		NULL
		);
	if (!hWnd)
	{
		MessageBox(NULL,"create error","Game",NULL);
		return FALSE;//创建窗口失败
	}

	ShowWindow(hWnd, SW_SHOW);
	UpdateWindow(hWnd);
	// 执行应用程序初始化:
	// 主消息循环:
	//这里最好还是用peekmessage函数。该函数虽然与getmessage功能相似,但是更适合于游戏程序 
	//如果只是消息队列中没有消息,getmessage函数会使应用程序挂起直到出现一个消息。而使用运行时函数peekmessage时,即使
	//消息队列中没有消息,也会让应用程序继续运行。这对于游戏程序来说很有用。
	done = false;
	Initilize();
	while( !done )
	{
		PeekMessage(&msg,hWnd,NULL,NULL,PM_REMOVE);
		if (msg.message == WM_QUIT)
		{
			done = true;
		}
		else
		{
			Render();
			TranslateMessage(&msg);	//翻译消息并分发到事件队列中
			DispatchMessage(&msg);
		}
	}
	return (int) msg.wParam;
}


环境映射_第1张图片

你可能感兴趣的:(OpenGL)