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 "); }