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

📄 opengl.cpp

📁 小型的3D游戏引擎
💻 CPP
字号:
 #include "opengl.h"
#include "../global.h"

////////////////////////////////////////////////////////////////////////////////////

GcOpenGL::GcOpenGL():
hRC(NULL),
hDC(NULL),
m_hWnd(NULL),
m_multiTextureSupport(false),
m_vertexArraySupport(false),
m_fogSupport(false)
{
	// Constructing the OpenGL object
}

////////////////////////////////////////////////////////////////////////////////////

GcOpenGL::~GcOpenGL()
{
	// Destroying the OpenGL object
}

////////////////////////////////////////////////////////////////////////////////////

bool GcOpenGL::Init( HWND hParent, int width, int height, int depth )
{
	m_screenWidth = width;
	m_screenHeight = height;
	m_screenDepth = depth;

	// Check for a legal window handle
	if(!hParent) {
		return false;
	}

	m_hWnd = hParent;
		

	// Set the pixel format
	if(!SetupPixelFormat())	
	{
		Close();
		return false;
	}

	// Set up the OpenGL window
	if(!SetupGLWindow()) 
	{
		Close();
		return false;
	}

	// Set up the OpenGL state machine
	SetupGLState();

	return true;
}

////////////////////////////////////////////////////////////////////////////////////

bool GcOpenGL::Close()
{
	/* Do We Have A Rendering Context? */
	if(hRC)
	{
		/* Are We Able To Release The DC And RC Contexts? */
		if(!wglMakeCurrent(NULL, NULL))
		{
			MessageBox(NULL, "Release of DC and RC failed.", "SHUTDOWN ERROR", 
					   MB_OK | MB_ICONINFORMATION );

			g_Debug->Log("Release of DC and RC failed.\n");
		}

		// Are We Able To Delete The RC?
		if(!wglDeleteContext(hRC))
		{
			MessageBox(NULL, "Release rendering context failed.", "SHUTDOWN ERROR", 
					   MB_OK | MB_ICONINFORMATION );

			g_Debug->Log("Release rendering context failed.\n");
		}

		// Set RC To NULL
		hRC = NULL;
	}

	/* Are We Able To Release The DC */
	if(hDC && m_hWnd)
	{
		if(!ReleaseDC(m_hWnd, hDC))
		{
			MessageBox(NULL, "Release device context failed.", "SHUTDOWN ERROR", 
					   MB_OK | MB_ICONINFORMATION );

			g_Debug->Log("Release device context failed.\n");

			// Set DC To NULL
			hDC = NULL;
			m_hWnd = NULL;
		}
	}

	return true;
}

////////////////////////////////////////////////////////////////////////////////////

void GcOpenGL::SetPerspective(int iWidth, int iHeight)
{
	m_screenWidth = iWidth;
	m_screenHeight = iHeight;

	/* Reset The Current Viewport */
	glViewport( 0, 0, iWidth, iHeight );

	/* Select The Projection Matrix */
	glMatrixMode(GL_PROJECTION);
	
	/* Reset The Projection Matrix */
	glLoadIdentity();

	/* Calculate The Aspect Ratio Of The Window */
	gluPerspective(45.0f, (GLfloat)iWidth / (GLfloat)iHeight, 4.0f, 15000.0f);

	/* Select The Modelview Matrix */
	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();
}

////////////////////////////////////////////////////////////////////////////////////

bool GcOpenGL::SetupPixelFormat()
{
	/* Setup the PIXELFORMATDESCRIPTOR */
	m_pfd.nSize = sizeof( PIXELFORMATDESCRIPTOR );		/* Size Of This Pixel Format Descriptor */
  	m_pfd.nVersion = 1;							/* Version Number */
	m_pfd.dwFlags =	PFD_DRAW_TO_WINDOW			/* Format Must Support Window */
					| PFD_SUPPORT_OPENGL		/* Format Must Support OpenGL */
					| PFD_DOUBLEBUFFER;			/* Must Support Double Buffering */
	m_pfd.iPixelType = PFD_TYPE_RGBA;			/* Request An RGBA Format */
	m_pfd.cColorBits = m_screenDepth;		/* Select Our Color Depth */
	m_pfd.cRedBits = 0;							/* Color Bits Ignored */
	m_pfd.cRedShift = 0;
	m_pfd.cGreenBits = 0;
	m_pfd.cGreenShift = 0;
	m_pfd.cBlueBits = 0;
	m_pfd.cBlueShift = 0;
	m_pfd.cAlphaBits = 0;					/* No Alpha Buffer */
	m_pfd.cAlphaShift = 0;					/* Shift Bit Ignored */
	m_pfd.cAccumBits = 0;					/* No Accumulation Buffer */
	m_pfd.cAccumRedBits = 0;				/* Accumulation Bits Ignored */
	m_pfd.cAccumGreenBits = 0;
	m_pfd.cAccumBlueBits = 0;
	m_pfd.cAccumAlphaBits = 0;
	m_pfd.cDepthBits = 16;					/* 16Bit Z-Buffer (Depth Buffer) */
	m_pfd.cStencilBits = 0;					/* No Stencil Buffer */
	m_pfd.cAuxBuffers = 0;					/* No Auxiliary Buffer */
	m_pfd.iLayerType = PFD_MAIN_PLANE;		/* Main Drawing Layer */
	m_pfd.bReserved = 0;					/* Reserved */
	m_pfd.dwLayerMask = 0;					/* Layer Masks Ignored */
	m_pfd.dwVisibleMask = 0;
	m_pfd.dwDamageMask = 0;
		
	if(!(hDC = GetDC(m_hWnd)))
	{
		Close();
		MessageBox(NULL, "Can't create a gl device context.", "ERROR", MB_OK | MB_ICONEXCLAMATION );
		g_Debug->Log("Can't create a gl device context.\n");
		return false;
	}

	/* Did Windows Find A Matching Pixel Format? */
	if(!( iPixelFormat = ChoosePixelFormat( hDC, &m_pfd)))
	{
		Close();
		MessageBox(NULL, "Can't find a suitable pixel format.", "ERROR", MB_OK | MB_ICONEXCLAMATION );
		g_Debug->Log("Can't find a suitable pixel format.\n");
		return false;
	}

	/* Are We Able To Set The Pixel Format? */
	if(!SetPixelFormat(hDC, iPixelFormat, &m_pfd))
	{
		Close();
		MessageBox(NULL, "Can't set the pixel format.", "ERROR", MB_OK | MB_ICONEXCLAMATION );
		g_Debug->Log("Can't set the pixel format.\n");
		return false;
	}

	return true;
}

////////////////////////////////////////////////////////////////////////////////////

bool GcOpenGL::SetupGLWindow()
{
		/* Are We Able To Get A Rendering Context? */
	if(!(hRC = wglCreateContext(hDC)))
	{
		Close();

		MessageBox(NULL, "Can't create a GL Rendering context.", "ERROR", 
				   MB_OK | MB_ICONEXCLAMATION );

		g_Debug->Log("Can't create a GL Rendering context.\n");
		return false;
	}

	/* Try To Activate The Rendering Context */
	if(!wglMakeCurrent(hDC, hRC))
	{
		Close();

		MessageBox(NULL, "Can't activate the GL Rendering context.", "ERROR", 
				   MB_OK | MB_ICONEXCLAMATION );

		g_Debug->Log("Can't activate the GL Rendering context.\n");
		return false;
	}

	// Set Up Our Perspective GL Screen
	SetPerspective(m_screenWidth, m_screenHeight);

	return true;
}

////////////////////////////////////////////////////////////////////////////////////

void GcOpenGL::SetupGLState()
{
	// Clear background to black
	glClearColor(0.0f, 0.0f, 0.0f, 0.0f);

	// Use smooth shading
	glShadeModel(GL_SMOOTH);

	glEnable(GL_DEPTH_TEST);

	// Don't calculate inside of polys
	glEnable(GL_CULL_FACE);

	// Counter clockwise polygones cut
	glFrontFace(GL_CCW);

	// Enable the "colorkey"
	glEnable(GL_ALPHA_TEST);
	glAlphaFunc(GL_GREATER, 0.0f);

	// Enable 2D texturing
	glEnable(GL_TEXTURE_2D);

	// Enable detail texturing if suported
	SetupMultitexturing();

	// Enable volumetric fog if suported and desiered
	SetupFog();

	// Eanble video memory if suported
	SetupVertexArrayRange();

	// Enable vertex and texture coord arrays
	if(GcSettings::Light()) {
		glEnableClientState(GL_NORMAL_ARRAY);

		glEnable(GL_LIGHT0);					// Turn on a light with defaults set
		glEnable(GL_LIGHTING);					// Turn on lighting
		glEnable(GL_COLOR_MATERIAL);			// Allow color
	}

	if(GcSettings::ColorArray()) {
		glEnableClientState(GL_COLOR_ARRAY);
	}
}

////////////////////////////////////////////////////////////////////////////////////

void GcOpenGL::SetupMultitexturing()
{
	// Find out if the card suport multitexturing
	GcSettings::MultiTexture(CheckSupport("GL_ARB_multitexture", 
						 (char*)glGetString(GL_EXTENSIONS)));
	m_multiTextureSupport = CheckSupport("GL_ARB_multitexture", (char *)glGetString(GL_EXTENSIONS));

	// Initialize the multi texturing
	if(GcSettings::MultiTexture()) // FIX ME: Multitexture?
	{
		glMultiTexCoord2fARB	 = (PFNGLMULTITEXCOORD2FARBPROC)
									wglGetProcAddress("glMultiTexCoord2fARB");

		glActiveTextureARB		 = (PFNGLACTIVETEXTUREARBPROC)
									wglGetProcAddress("glActiveTextureARB");

		glClientActiveTextureARB = (PFNGLCLIENTACTIVETEXTUREARBPROC)
									wglGetProcAddress("glClientActiveTextureARB");
	}
	else {
		g_Debug->Log("Multitexturing not suported\n");
	}
}

////////////////////////////////////////////////////////////////////////////////////

void GcOpenGL::SetupFog()
{
	// Find out if volumetric fog is supported
	m_fogSupport = CheckSupport("GL_EXT_fog_coord", (char*)glGetString(GL_EXTENSIONS));

	// Use fog?
	if(GcSettings::Fog() && m_fogSupport)
	{

		// Get the extension for the volumetric fog
		glFogCoordPointerEXT = (PFNGLFOGCOORDPOINTEREXTPROC)
								wglGetProcAddress("glFogCoordPointerEXT");

		glFogCoordfEXT		 = (PFNGLFOGCOORDFEXTPROC)
								wglGetProcAddress("glFogCoordfEXT");

		float color[4] = { 0.8f, 0.8f, 0.8f, 1.0f };
		glClearColor(0.8f, 0.8f, 0.8f, 1.0f);

		glEnable(GL_FOG);
		glFogfv(GL_FOG_COLOR, color);
		glFogf(GL_FOG_MODE, GL_LINEAR);
		glFogf(GL_FOG_START, 0.0f);
		glFogf(GL_FOG_END, 1000.0f);
		glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FOG_COORDINATE_EXT);

		glEnableClientState(GL_FOG_COORDINATE_ARRAY_EXT);
	}
	else
	{
		GcSettings::Fog(false);
	}
}

////////////////////////////////////////////////////////////////////////////////////

void GcOpenGL::SetupVertexArrayRange()
{
	// Find out if the vertex data can be stored on the gfx card
	//settings.VideoMemory();
	m_vertexArraySupport = CheckSupport("GL_NV_vertex_array_range", (char *)glGetString(GL_EXTENSIONS));
	GcSettings::VideoMemory(m_vertexArraySupport);

	if(m_vertexArraySupport)
	{
		glFlushVertexArrayRangeNV = (PFNGLFLUSHVERTEXARRAYRANGENVPROC)
									wglGetProcAddress("glFlushVertexArrayRangeNV");

		glVertexArrayRangeNV	  = (PFNGLVERTEXARRAYRANGENVPROC)
									wglGetProcAddress("glVertexArrayRangeNV");

		wglAllocateMemoryNV		  = (PFNWGLALLOCATEMEMORYNVPROC)
									wglGetProcAddress("wglAllocateMemoryNV");

		wglFreeMemoryNV			  = (PFNWGLFREEMEMORYNVPROC)
									wglGetProcAddress("wglFreeMemoryNV");
	}

	glEnableClientState(GL_VERTEX_ARRAY);
	glEnableClientState(GL_TEXTURE_COORD_ARRAY);
}

////////////////////////////////////////////////////////////////////////////////////

bool GcOpenGL::CheckSupport(char *check, char *str)
{
	char *endOfStr;
	uint  i = 0;

	// Last char of the string
	endOfStr = str + strlen(str);

	while(str < endOfStr)
	{
		// Find a space
		i = strcspn(str, " ");

		// Check to see if the string match the one looked for
		if((strlen(check) == i) && (strncmp(check, str, i) == 0)) {
			return true;
		}

		str += i + 1;
	}

	return false;
}

////////////////////////////////////////////////////////////////////////////////////

⌨️ 快捷键说明

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