www.pudn.com > AndreasHalm-src.zip > ChildView.cpp


// ChildView.cpp : implementation of the CChildView class 
// 
 
#include "stdafx.h" 
#include "OpenGLSLCubizzle.h" 
#include ".\ChildView.h" 
#include ".\SoftwareShaderWarning.h" 
 
using namespace gale; 
 
#include  
#include  
using namespace std; 
 
#pragma comment (lib,"opengl32.lib") 
#pragma comment (lib,"glew32s.lib") 
#pragma comment (lib,"glu32.lib") 
 
 
#ifdef _DEBUG 
#define new DEBUG_NEW 
#endif 
 
 
const int image_width = 256; 
const int image_height = 256; 
 
// CChildView 
 
CChildView::CChildView() 
{ 
   dc = 0; 
   gl_context = 0; 
   cube_program = 0; 
	text_color = Color3f::BLUE(); 
	data = 0; 
   auto_rotation = true; 
   cube_program_edges = 0; 
} 
 
CChildView::~CChildView() 
{ 
	delete [] data; 
} 
 
 
BEGIN_MESSAGE_MAP(CChildView, CWnd) 
   ON_WM_CREATE() 
   ON_WM_ERASEBKGND() 
   ON_WM_DESTROY() 
   ON_WM_TIMER() 
   ON_WM_PAINT() 
	ON_WM_SIZE() 
   ON_COMMAND(ID_SHADER_NOBUMPMAPPING, OnShaderNoBumpmapping) 
   ON_UPDATE_COMMAND_UI(ID_SHADER_NOBUMPMAPPING, OnUpdateShaderNoBumpmapping) 
   ON_COMMAND(ID_SHADER_2PBUMPMAPPING, OnShader2pBumpmapping) 
   ON_UPDATE_COMMAND_UI(ID_SHADER_2PBUMPMAPPING, OnUpdateShader2pBumpmapping) 
   ON_COMMAND(ID_SHADER_4PBUMPMAPPING, OnShader4pBumpmapping) 
   ON_UPDATE_COMMAND_UI(ID_SHADER_4PBUMPMAPPING, OnUpdateShader4pBumpmapping) 
   ON_COMMAND(ID_SHADER_8PBUMPMAPPING, OnShader8pBumpmapping) 
   ON_UPDATE_COMMAND_UI(ID_SHADER_8PBUMPMAPPING, OnUpdateShader8pBumpmapping) 
   ON_COMMAND(ID_SETTINGS_ROTATION, OnSettingsRotation) 
   ON_UPDATE_COMMAND_UI(ID_SETTINGS_ROTATION, OnUpdateSettingsRotation) 
	ON_COMMAND(ID_EDGESHADER_USESIDESHADER, OnEdgeShaderUseSideShader) 
	ON_UPDATE_COMMAND_UI(ID_EDGESHADER_USESIDESHADER, OnUpdateEdgeShaderUseSideShader) 
	ON_COMMAND(ID_EDGESHADER_NOBUMPMAPPING, OnEdgeShaderNoBumpMapping) 
	ON_UPDATE_COMMAND_UI(ID_EDGESHADER_NOBUMPMAPPING, OnUpdateEdgeShaderNoBumpMapping) 
	ON_COMMAND(ID_EDGESHADER_8PBUMPMAPPING, OnEdgeShader8pBumpMapping) 
	ON_UPDATE_COMMAND_UI(ID_EDGESHADER_8PBUMPMAPPING, OnUpdateEdgeShader8pBumpMapping) 
END_MESSAGE_MAP() 
 
inline COLORREF colorref( const Color3f& c ) 
{ 
	return RGB( 
		c.getRed() * 255, 
		c.getGreen() * 255, 
		c.getBlue() * 255 
		); 
} 
 
 
// CChildView message handlers 
 
BOOL CChildView::PreCreateWindow(CREATESTRUCT& cs)  
{ 
   // msdn says: we need this line 
   cs.style |= WS_CLIPSIBLINGS | WS_CLIPCHILDREN ; 
   // allow registering in derived class 
   if (cs.lpszClass == NULL) 
      cs.lpszClass = AfxRegisterWndClass( 
      CS_HREDRAW|CS_VREDRAW|CS_OWNDC, 
      ::LoadCursor(NULL, IDC_ARROW), NULL, NULL); 
 
   return __super::PreCreateWindow(cs); 
} 
 
int CChildView::OnCreate(LPCREATESTRUCT lpCreateStruct) 
{ 
   // CLoadingProgress implements a simple dialog with 
   // a message and a progress bar. every update via 
   // info() sets the info text and advances the  
   // progress bar 10%. 
   CLoadingProgress loading; 
   loading.info("Initializing OpenGL..."); 
 
   if (__super::OnCreate(lpCreateStruct) == -1) 
      return -1; 
 
   dc = ::GetDC(*this); 
 
	PIXELFORMATDESCRIPTOR pfd = {  
		sizeof(PIXELFORMATDESCRIPTOR),   // size of this pfd  
		1,                     // version number  
		PFD_DRAW_TO_WINDOW |   // support window  
		PFD_SUPPORT_OPENGL |   // support OpenGL  
		PFD_DOUBLEBUFFER,      // double buffered  
		PFD_TYPE_RGBA,         // RGBA type  
		24,                    // 24-bit color depth  
		0, 0, 0, 0, 0, 0,      // color bits ignored  
		0,                     // no alpha buffer  
		0,                     // shift bit ignored  
		0,                     // no accumulation buffer  
		0, 0, 0, 0,            // accum bits ignored  
		0,                     // no z-buffer  
		0,                     // no stencil buffer  
		0,                     // no auxiliary buffer  
		PFD_MAIN_PLANE,        // main layer  
		0,                     // reserved: overlay & underlay buffers 
		0, 0, 0                // layer masks ignored  
	};  
	int  iPixelFormat;  
  
	// get the best available match of pixel format for the device context   
	iPixelFormat = ChoosePixelFormat(dc, &pfd);  
   if (iPixelFormat == 0) { 
		MessageBox("ChoosePixelFormat failed"); 
   } 
	// make that the pixel format of the device context  
	if (!SetPixelFormat(dc, iPixelFormat, &pfd)) { 
      MessageBox("SetPixelFormat failed"); 
   } 
	// create a rendering context  
	gl_context = wglCreateContext(dc);  
   if (gl_context == 0) { 
		MessageBox("wglCreateContext failed"); 
   } 
	// make it the calling thread's current rendering context 
   if (!wglMakeCurrent(dc,gl_context)) { 
		MessageBox("wglMakeCurrent failed"); 
   } 
	// init GLEW 
	int err = glewInit(); 
   if (GLEW_OK != err) { 
      MessageBox("GLEW initialization failed"); 
   } 
 
   // loading the cube meshes from resources 
   loading.info("Loading Meshes..."); 
   cube_sides.load(IDR_MESH_SIDES); 
   cube_edges.load(IDR_MESH_EDGES); 
 
   // just some defaults 
   glDrawBuffer(GL_BACK); 
   glClearColor(0,0,0,0); 
   glDisable(GL_DEPTH_TEST); 
   glDepthFunc(GL_LESS); 
   glEnable(GL_CULL_FACE); 
   glFrontFace(GL_CCW); 
 
   // note that lighting is only used if we *don't* 
   // find oglsl support. hopefully you won't need to 
   // see that. 
   glMatrixMode(GL_MODELVIEW); 
   glLoadIdentity(); 
   glEnable(GL_LIGHTING); 
   GLfloat pos[][4] = {  
      { 8,0,24,1}, {-8,0,24,1},  
		{.2f,.2f,.2f,1}, { 0,0,1,1}, 
      { 0.6f,0.7f,0.8f,1}, {0.3f,0.3f,0.3f,1},  
		{ 0.8f,0.8f,0.8f,1} 
	}; 
	glShadeModel (GL_SMOOTH); 
   glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE); 
   glEnable(GL_LIGHT0); 
   glLightfv(GL_LIGHT0, GL_POSITION, pos[3]); 
   glLightfv(GL_LIGHT0, GL_AMBIENT, pos[2]); 
   glLightfv(GL_LIGHT0, GL_DIFFUSE,  pos[5]); 
   glLightfv(GL_LIGHT0, GL_SPECULAR, pos[6]); 
 
   Vector4f color_ambient( 0.1f, 0.1f, 0.1f, 1.0f ); 
   Vector4f color_diffuse( 0.3f, 0.3f, 0.3f, 1.0f ); 
   Vector4f specular( 1.0f, 1.0f, 1.0f, 1.0f ); 
   glMaterialfv(GL_FRONT,GL_AMBIENT,color_ambient); 
   glMaterialfv(GL_FRONT,GL_DIFFUSE,color_diffuse); 
   glMaterialfv(GL_FRONT,GL_SPECULAR,specular); 
   glMaterialf(GL_FRONT,GL_SHININESS,4.0f); 
 
   // setup cube mapping 
   loading.info("Loading Cube Maps..."); 
	cube_mapping = SetupCubeMapping(); 
 
   // setup the oglsl programs 
   glsl = SetupCubeProgram(&loading); 
 
   // create the first texture 
   loading.info("Completing..."); 
	OnNewImage(); 
 
   // redraw timer: 10ms. we will never go beyond 100fps this way. 
	SetTimer(530,10,0); 
   // texture update: once a second 
	SetTimer(550,1000,0); 
 
   loading.DestroyWindow(); 
 
   return 0; 
} 
 
bool CChildView::LoadGLSLProgram( LazyProgramObject& program, UINT vertexshader_id, UINT fragmentshader_id, CLoadingProgress* loading ) 
{ 
   // check extensions 
   if (!GLEW_ARB_shader_objects 
      || !GLEW_ARB_shading_language_100 
      || !GLEW_ARB_vertex_shader 
      || !GLEW_ARB_fragment_shader)  
		return false; 
 
   loading->info("Loading Shader..."); 
 
#ifdef DEBUG 
   string infolog; 
#endif 
 
   // load and compile vertex shader from resource 
   VertexShader vertex_shader(vertexshader_id); 
   if (!vertex_shader.compile()) { 
      string error = vertex_shader.getInfoLog(); 
		MessageBox(error.c_str(),"Vertex Shader Compilation Error"); 
      return false; 
   } 
#ifdef DEBUG 
   infolog += "Vertex Shader Infolog:\n"; 
   infolog += "======================\n"; 
   infolog += vertex_shader.getInfoLog(); 
#endif 
 
   // load and compile fragment shader from resource 
   FragmentShader fragment_shader(fragmentshader_id); 
   if (!fragment_shader.compile()) { 
      string error = fragment_shader.getInfoLog(); 
		MessageBox(error.c_str(),"Fragment Shader Compilation Error"); 
      return false; 
   } 
#ifdef DEBUG 
   infolog += "\n\n"; 
   infolog += "Fragment Shader (sides) Infolog:\n"; 
   infolog += "================================\n"; 
   infolog += fragment_shader.getInfoLog(); 
#endif 
 
   // link them together 
   program.attach(vertex_shader); 
   program.attach(fragment_shader); 
   program.setAttributeIndex("tex0_s",TEX0_S_ATTRIBUTE); 
   program.setAttributeIndex("tex0_t",TEX0_T_ATTRIBUTE); 
   if (!program.link()) { 
      string error = program.getInfoLog(); 
		MessageBox(error.c_str(),"Program Object Linker Error"); 
      return false; 
   } 
#ifdef DEBUG 
   infolog += "\n\n"; 
   infolog += "Linker Infolog:\n"; 
   infolog += "===============\n"; 
   infolog += program.getInfoLog(); 
#endif 
 
   assert(glGetError()==GL_NO_ERROR); 
   return true; 
} 
 
bool CChildView::SetupCubeProgram(CLoadingProgress* loading) 
{ 
   // here we are simply loading the 6 shaders we support. 
   // also, initial parameters are set. 
   // we need different shaders for ATI because they do not 
   // support fwidth() currently. we'll loose some eye candy though... 
	bool ati = GLUtilities::isVendorATI(); 
   bool v1 = LoadGLSLProgram(cube_program_default,IDR_VERTEXSHADER,IDR_FS_CUBESIDES,loading); 
   if (v1) { 
      cube_program_default.setUniform("light",0.0f,0.0f,4.0f,1.0f); 
      cube_program_default.setUniform("tex0",0); 
      cube_program_default.setUniform("texCube",1); 
      cube_program = &cube_program_default; 
   } 
	bool v2 = LoadGLSLProgram(cube_program_bm2p,IDR_VERTEXSHADER,ati?IDR_FS_CUBESIDES_BM2P_ATI:IDR_FS_CUBESIDES_BM2P,loading); 
   if (v2) { 
      cube_program_bm2p.setUniform("light",0.0f,0.0f,4.0f,1.0f); 
      cube_program_bm2p.setUniform("tex0",0); 
      cube_program_bm2p.setUniform("texCube",1); 
   } 
	bool v3 = LoadGLSLProgram(cube_program_bm4p,IDR_VERTEXSHADER,ati?IDR_FS_CUBESIDES_BM4P_ATI:IDR_FS_CUBESIDES_BM4P,loading); 
   if (v3) { 
      cube_program_bm4p.setUniform("light",0.0f,0.0f,4.0f,1.0f); 
      cube_program_bm4p.setUniform("tex0",0); 
      cube_program_bm4p.setUniform("texCube",1); 
   } 
	bool v4 = LoadGLSLProgram(cube_program_bm8p,IDR_VERTEXSHADER,ati?IDR_FS_CUBESIDES_BM8P_ATI:IDR_FS_CUBESIDES_BM8P,loading); 
   if (v4) { 
      cube_program_bm8p.setUniform("light",0.0f,0.0f,4.0f,1.0f); 
      cube_program_bm8p.setUniform("tex0",0); 
      cube_program_bm8p.setUniform("texCube",1); 
   } 
   bool v5 = LoadGLSLProgram(cube_program_edges_default,IDR_VERTEXSHADER,IDR_FS_CUBEEDGES,loading); 
   if (v5) { 
      cube_program_edges_default.setUniform("light",0.0f,0.0f,4.0f,1.0f); 
      cube_program_edges_default.setUniform("texCube",1); 
   } 
	bool v6 = LoadGLSLProgram(cube_program_edges_bm8p,IDR_VERTEXSHADER,ati?IDR_FS_CUBEEDGES_BM8P_ATI:IDR_FS_CUBEEDGES_BM8P,loading); 
   if (v6) { 
      edge_bm_data.loadresource(IDR_EDGES_BM,0,true); 
      edge_bm.load(edge_bm_data,true); 
	   glTexParameteri(GL_TEXTURE_CUBE_MAP_ARB,GL_TEXTURE_WRAP_S,GL_CLAMP_TO_EDGE); 
	   glTexParameteri(GL_TEXTURE_CUBE_MAP_ARB,GL_TEXTURE_WRAP_T,GL_CLAMP_TO_EDGE); 
	   glTexParameteri(GL_TEXTURE_CUBE_MAP_ARB,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_LINEAR); 
	   glTexParameteri(GL_TEXTURE_CUBE_MAP_ARB,GL_TEXTURE_MAG_FILTER,GL_LINEAR); 
      cube_program_edges_bm8p.setUniform("light",0.0f,0.0f,4.0f,1.0f); 
      cube_program_edges_bm8p.setUniform("tex_bm",0); 
      cube_program_edges_bm8p.setUniform("texCube",1); 
   } 
   return v1&&v2&&v3&&v4&&v5&&v6; 
} 
 
bool CChildView::SetupCubeMapping() 
{ 
   // needed:  
   // - ARB_multitexture 
   // - ARB_texture_cube_map 
   if (!GLEW_VERSION_1_3) return false; 
   glActiveTexture(GL_TEXTURE1); 
   glEnable(GL_TEXTURE_CUBE_MAP); 
   // the following just loads 6 textures from resources into a cube map 
	TextureData cube_px; 
	if (!cube_px.loadresource(IDR_CUBE_PX)) return false; 
   gluBuild2DMipmaps(GL_TEXTURE_CUBE_MAP_POSITIVE_X,GL_RGBA,cube_px.width(),cube_px.height(),cube_px.type(),GL_UNSIGNED_BYTE,cube_px.data()); 
   TextureData cube_py; 
	if (!cube_py.loadresource(IDR_CUBE_PY)) return false; 
   gluBuild2DMipmaps(GL_TEXTURE_CUBE_MAP_POSITIVE_Y,GL_RGBA,cube_py.width(),cube_py.height(),cube_py.type(),GL_UNSIGNED_BYTE,cube_py.data()); 
   TextureData cube_pz; 
	if (!cube_pz.loadresource(IDR_CUBE_PZ)) return false; 
   gluBuild2DMipmaps(GL_TEXTURE_CUBE_MAP_POSITIVE_Z,GL_RGBA,cube_pz.width(),cube_pz.height(),cube_pz.type(),GL_UNSIGNED_BYTE,cube_pz.data()); 
   TextureData cube_nx; 
	if (!cube_nx.loadresource(IDR_CUBE_NX)) return false; 
   gluBuild2DMipmaps(GL_TEXTURE_CUBE_MAP_NEGATIVE_X,GL_RGBA,cube_nx.width(),cube_nx.height(),cube_nx.type(),GL_UNSIGNED_BYTE,cube_nx.data()); 
   TextureData cube_ny; 
	if (!cube_ny.loadresource(IDR_CUBE_NY)) return false; 
   gluBuild2DMipmaps(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y,GL_RGBA,cube_ny.width(),cube_ny.height(),cube_ny.type(),GL_UNSIGNED_BYTE,cube_ny.data()); 
   TextureData cube_nz; 
	if (!cube_nz.loadresource(IDR_CUBE_NZ)) return false; 
   gluBuild2DMipmaps(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z,GL_RGBA,cube_nz.width(),cube_nz.height(),cube_nz.type(),GL_UNSIGNED_BYTE,cube_nz.data()); 
   // we're done, set some parameters 
	glTexParameteri(GL_TEXTURE_CUBE_MAP_ARB,GL_TEXTURE_WRAP_S,GL_CLAMP_TO_EDGE); 
	glTexParameteri(GL_TEXTURE_CUBE_MAP_ARB,GL_TEXTURE_WRAP_T,GL_CLAMP_TO_EDGE); 
	glTexParameteri(GL_TEXTURE_CUBE_MAP_ARB,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_LINEAR); 
	glTexParameteri(GL_TEXTURE_CUBE_MAP_ARB,GL_TEXTURE_MAG_FILTER,GL_LINEAR); 
   glActiveTexture(GL_TEXTURE0); 
	assert(glGetError()==GL_NO_ERROR); 
   return true; 
} 
 
BOOL CChildView::OnEraseBkgnd(CDC* pDC) 
{ 
   // we don't erase. never. but we pretend we do. 
   return true; 
} 
 
void CChildView::OnDestroy() 
{ 
   // destroy the rendering context etc. 
   if (gl_context) { 
      wglMakeCurrent(0,0); 
      wglDeleteContext(gl_context); 
      gl_context = 0; 
   } 
   if (dc) { 
      ::ReleaseDC(*this,dc); 
      dc = 0; 
   } 
   __super::OnDestroy(); 
} 
 
void CChildView::OnTimer(UINT nIDEvent) 
{ 
   if (nIDEvent == 530) { 
      Draw(); 
   } 
	else if (nIDEvent == 550) { 
		OnNewImage(); 
	} 
   else 
      __super::OnTimer(nIDEvent); 
} 
 
void CChildView::Draw() 
{ 
   // some rotation. time-based, so this is always 
   // the same regardless of the computer speed 
   if (auto_rotation) { 
      glLoadIdentity(); 
      glTranslatef(0,0,-5); 
      float time = GetTickCount()/10.0f; 
      glRotatef(fmod(time/11,360),1,0,0); 
      glRotatef(fmod(time/12,360),0,1,0); 
      glRotatef(fmod(time/13,360),0,0,1); 
   } 
 
   glClear(GL_COLOR_BUFFER_BIT); 
 
   // the color rotation is also time based 
	text_color.setHue( fmod(GetTickCount()/100000.0f,1.0f) ); 
	Color3f diffuse = text_color*0.3f+0.1f; 
	glColor3fv(diffuse); 
 
	// *** cube sides *** 
   // activate cube side program, if possible 
   if (data && cube_program) 
      cube_program->use(); 
	else glEnable(GL_TEXTURE_2D); 
   // the bumpmap is our dynamic texture 
   glBindTexture(GL_TEXTURE_2D,0); 
   // draw the cube sides 
   cube_sides.draw(); 
 
	// *** edges & corners *** 
   // activate edge+corner program, if possible 
   if (cube_program_edges) 
      cube_program_edges->use(); 
   // activate the edge bumpmap (static) 
   edge_bm.activate(); 
   // draw the cube edges+corners 
   cube_edges.draw(); 
 
   SwapBuffers(dc); 
} 
 
void CChildView::OnPaint() 
{ 
	ValidateRect(0); 
} 
 
bool CChildView::OnNewImage() 
{ 
	if (!data) 
	{ 
		data = new unsigned int [image_width*image_height]; 
		ZeroMemory(data,image_width*image_height*4); 
	} 
   // the date+time texture is in texture 0 
   glBindTexture(GL_TEXTURE_2D,0); 
	{ 
      // create a dib bitmap 
		CDC dc; 
		dc.CreateCompatibleDC(0); 
		BITMAPINFO bmpinfo = { sizeof(BITMAPINFOHEADER),  
			image_width, -image_height, 1, 32 }; 
		unsigned int* pDibData; 
		HBITMAP hBmp = CreateDIBSection(dc,&bmpinfo,0,(void**)&pDibData,0,0); 
		dc.SelectObject(hBmp); 
 
      // generate the string we draw (date+time) 
		CRect r( 0, 0, image_width, image_height );  
		time_t now; 
		time(&now); 
		CString str; 
		if (glsl) { 
			str = ctime(&now); 
			str = str.Left(str.GetLength()-1); 
		} else 
			str = "sorry no pixel shader"; 
		dc.SetBkMode(TRANSPARENT); 
 
      // color rotation 
		text_color.setHue( fmod(GetTickCount()/100000.0f,1.0f) ); 
		dc.SetTextColor(colorref(text_color)); 
 
      // select font 
		CFont font; 
		font.CreateFont(50,0,0,0,0,0,0,0,DEFAULT_CHARSET,0,0,0,0,"Verdena"); 
		dc.SelectObject(font); 
		dc.DrawText(str,&r,DT_CENTER|DT_CALCRECT|DT_WORDBREAK); 
		r.left = (image_width  - r.Width())/2;  r.right += r.left; 
		r.top  = (image_height - r.Height())/2; r.bottom += r.top; 
		dc.DrawText(str,&r,DT_CENTER|DT_WORDBREAK); 
 
      // now copy the dib to our data array. this is because when gdi 
      // draws something (like the text above), it always sets the 
      // alpha value to 0. so if we would use it as a texture directly, 
      // we wouldn't see anything. so we copy all the pixel data and 
      // for all non-black pixels, we set the alpha value to 255. 
		for (int y=0;y 0) { 
               datapixel = pixel + 0xff000000; 
            } 
            else 
               datapixel = 0; 
			} 
		DeleteObject(hBmp); 
 
		// texture settings 
		glTexEnvi(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_DECAL); 
		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP); 
		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP); 
 
      // enable automatic mipmapping, if possible 
		if (GLEW_SGIS_generate_mipmap) { 
			glTexParameteri(GL_TEXTURE_2D,GL_GENERATE_MIPMAP,GL_TRUE); 
			glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_LINEAR); 
			glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR); 
		} 
		else { 
			glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR); 
			glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR); 
		} 
      // enable anisotropic filtering 
		if (GLEW_EXT_texture_filter_anisotropic) { 
			glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MAX_ANISOTROPY_EXT,2.0f); 
		} 
	} 
 
   // finally, update the texture with the stuff we made 
   glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA,image_width,image_height,0,GL_BGRA_EXT,GL_UNSIGNED_BYTE,data); 
   return true; 
} 
 
 
void CChildView::OnSize(UINT nType, int cx, int cy) 
{ 
	CWnd::OnSize(nType, cx, cy); 
 
   GLdouble gldAspect = (GLdouble) cx/ (GLdouble) cy; 
   glMatrixMode(GL_PROJECTION); 
   glLoadIdentity(); 
   gluPerspective(30.0, gldAspect, 1.0, 10.0); 
   glViewport(0,0,cx,cy); 
   glMatrixMode(GL_MODELVIEW); 
   glLoadIdentity(); 
} 
 
void CChildView::OnShaderNoBumpmapping()  
{  
   if (cube_program_default.runsInSoftware()) { 
      CSoftwareShaderWarning warn; 
      warn.m_sInfoLog = cube_program_default.getInfoLog().c_str(); 
      if (warn.DoModal() != IDOK) return; 
   } 
   cube_program = &cube_program_default;  
} 
 
void CChildView::OnUpdateShaderNoBumpmapping(CCmdUI *pCmdUI) 
{  
   pCmdUI->SetRadio(cube_program==&cube_program_default);  
   if (cube_program_default.runsInSoftware()) 
      pCmdUI->SetText("&no Bumpmapping "); 
} 
 
void CChildView::OnShader2pBumpmapping() 
{  
   if (cube_program_bm2p.runsInSoftware()) { 
      CSoftwareShaderWarning warn; 
      warn.m_sInfoLog = cube_program_bm2p.getInfoLog().c_str(); 
      if (warn.DoModal() != IDOK) return; 
   } 
   cube_program = &cube_program_bm2p;  
} 
 
void CChildView::OnUpdateShader2pBumpmapping(CCmdUI *pCmdUI) 
{  
   pCmdUI->SetRadio(cube_program==&cube_program_bm2p);  
   if (cube_program_bm2p.runsInSoftware()) 
      pCmdUI->SetText("&2P Bumpmapping "); 
} 
 
void CChildView::OnShader4pBumpmapping() 
{  
   if (cube_program_bm4p.runsInSoftware()) { 
      CSoftwareShaderWarning warn; 
      warn.m_sInfoLog = cube_program_bm4p.getInfoLog().c_str(); 
      if (warn.DoModal() != IDOK) return; 
   } 
   cube_program = &cube_program_bm4p;  
} 
 
void CChildView::OnUpdateShader4pBumpmapping(CCmdUI *pCmdUI) 
{  
   pCmdUI->SetRadio(cube_program==&cube_program_bm4p);  
   if (cube_program_bm4p.runsInSoftware()) 
      pCmdUI->SetText("&4P Bumpmapping "); 
} 
 
void CChildView::OnShader8pBumpmapping() 
{  
   if (cube_program_bm8p.runsInSoftware()) { 
      CSoftwareShaderWarning warn; 
      warn.m_sInfoLog = cube_program_bm8p.getInfoLog().c_str(); 
      if (warn.DoModal() != IDOK) return; 
   } 
   cube_program = &cube_program_bm8p;  
} 
 
void CChildView::OnUpdateShader8pBumpmapping(CCmdUI *pCmdUI) 
{  
   pCmdUI->SetRadio(cube_program==&cube_program_bm8p);  
   if (cube_program_bm8p.runsInSoftware()) 
      pCmdUI->SetText("&8P Bumpmapping "); 
} 
 
void CChildView::OnSettingsRotation() 
{ auto_rotation = !auto_rotation; } 
 
void CChildView::OnUpdateSettingsRotation(CCmdUI *pCmdUI) 
{ pCmdUI->SetCheck(auto_rotation); } 
 
 
void CChildView::OnEdgeShaderUseSideShader() 
{  
   cube_program_edges = 0; 
} 
 
void CChildView::OnUpdateEdgeShaderUseSideShader(CCmdUI *pCmdUI) 
{  
   pCmdUI->SetRadio( cube_program_edges == 0 ); 
} 
 
void CChildView::OnEdgeShaderNoBumpMapping() 
{  
   if (cube_program_edges_default.runsInSoftware()) { 
      CSoftwareShaderWarning warn; 
      warn.m_sInfoLog = cube_program_edges_default.getInfoLog().c_str(); 
      if (warn.DoModal() != IDOK) return; 
   } 
   cube_program_edges = &cube_program_edges_default; 
} 
 
void CChildView::OnUpdateEdgeShaderNoBumpMapping(CCmdUI *pCmdUI) 
{  
   pCmdUI->SetRadio( cube_program_edges == &cube_program_edges_default ); 
   if (cube_program_edges_default.runsInSoftware()) 
      pCmdUI->SetText("&no Bumpmapping "); 
} 
 
void CChildView::OnEdgeShader8pBumpMapping() 
{  
   if (cube_program_edges_bm8p.runsInSoftware()) { 
      CSoftwareShaderWarning warn; 
      warn.m_sInfoLog = cube_program_edges_bm8p.getInfoLog().c_str(); 
      if (warn.DoModal() != IDOK) return; 
   } 
   cube_program_edges = &cube_program_edges_bm8p; 
} 
 
void CChildView::OnUpdateEdgeShader8pBumpMapping(CCmdUI *pCmdUI) 
{  
   pCmdUI->SetRadio( cube_program_edges == &cube_program_edges_bm8p ); 
   if (cube_program_edges_bm8p.runsInSoftware()) 
      pCmdUI->SetText("&8P Bumpmapping "); 
}