bool OpenGL::InitialiseOpenGL(HWND hWnd, int screenWidth, int screenHeight, float screenDepth, float screenNear, bool vSync) { int attributeListInt[19]; int pixelFormat[1]; unsigned int formatCount; int result; PIXELFORMATDESCRIPTOR pixelFormatDescriptor; int attributList[5]; float fieldOfView, screenAspect; char *vendorString, *rendererString; //Get the device context for this window m_deviceContext = GetDC(hWnd); if (!m_deviceContext) { return false; } //Support for OpenGL rendering attributeListInt[0] = WGL_SUPPORT_OPENGL_ARB; attributeListInt[1] = TRUE; //Support for rendering to a window attributeListInt[2] = WGL_DRAW_TO_WINDOW_ARB; attributeListInt[3] = TRUE; //Support for hardware accelleration attributeListInt[4] = WGL_ACCELERATION_ARB; attributeListInt[5] = WGL_FULL_ACCELERATION_ARB; //Support for 24bit Color attributeListInt[6] = WGL_COLOR_BITS_ARB; attributeListInt[7] = 24; //Support for 24bit depth buffer attributeListInt[8] = WGL_DEPTH_BITS_ARB; attributeListInt[9] = 24; //Support for double buffer attributeListInt[10] = WGL_DOUBLE_BUFFER_ARB; attributeListInt[11] = TRUE; //Support for swapping front and back buffer attributeListInt[12] = WGL_SWAP_METHOD_ARB; attributeListInt[13] = WGL_SWAP_EXCHANGE_ARB; //Support the RGBA pixel Type attributeListInt[14] = WGL_PIXEL_TYPE_ARB; attributeListInt[15] = WGL_TYPE_RGBA_ARB; //Support for 8bit stencil buffer attributeListInt[16] = WGL_STENCIL_BITS_ARB; attributeListInt[17] = 8; //NULL terminate attribute list attributeListInt[18] = 0; //Query for a pixel format that fits the attributes we want result = wglChoosePixelFormatARB(m_deviceContext, attributeListInt, NULL, 1, pixelFormat, &formatCount); if (result != 1) { return false; } //If the video card/display can handle our pixel format set it as the current one result = SetPixelFormat(m_deviceContext, pixelFormat[0], &pixelFormatDescriptor); if (result != 1) { return false; } //Set the 4.0 version of OpenGL in the attribute list attributList[0] = WGL_CONTEXT_MAJOR_VERSION_ARB; attributList[1] = 4; attributList[2] = WGL_CONTEXT_MINOR_VERSION_ARB; attributList[3] = 0; //Null terminate the attribute list attributList[4] = 0; //Create an OpenGL 4.0 Rendering Context m_renderingContext = wglCreateContextAttribsARB(m_deviceContext, 0, attributList); if (m_renderingContext == NULL) { return false; } //Set the rendering context to active result = wglMakeCurrent(m_deviceContext, m_renderingContext); if (result != 1) { return false; } //set the depth buffer to be 1.0f glClearDepth(1.0f); //enable depth testing glEnable(GL_DEPTH_TEST); //set the polygon winding to front facing glFrontFace(GL_CW); //Enable ackface culling glEnable(GL_CULL_FACE); glCullFace(GL_BACK); //initialise the world/model matrix to the identity BuildIdentityMatrix(m_worldMatrix); //Set the FOV and screen aspect ratio fieldOfView = PI / 4.0f; screenAspect = (float)screenWidth / (float)screenHeight; //Build the perspective projection matrix BuildPerspectiveFOVLHMatrix(m_projectionMatrix, fieldOfView, screenAspect, screenNear, screenDepth); //Get the name of the video card vendorString = (char*)glGetString(GL_VENDOR); rendererString = (char*)glGetString(GL_RENDERER); //Store the video card name strcpy_s(m_videoCardDescription, vendorString); strcpy_s(m_videoCardDescription, "-"); strcpy_s(m_videoCardDescription, rendererString); //Turn on vsync depending on the bool value if (vSync) { result = wglSwapIntervalEXT(1); } else { result = wglSwapIntervalEXT(0); } if (result != 1) { return false; } return true; }
/*!\rst Check that ``A * B`` works where ``A, B`` are matrices. Outline: 1. Simple hand-checked test case. 2. Generate a random orthogonal matrix and verify that ``Q * Q^T = I``. 3. Generate a random SPD matrix and guarantee good conditioning: verify ``A * A^-1 = I``. \return number of cases where matrix-matrix multiply failed \endrst*/ OL_WARN_UNUSED_RESULT int TestGeneralMatrixMatrixMultiply() noexcept { int total_errors = 0; // simple, hand-checked problems that are be minimally affected by floating point errors { // hide scope static const int kSize_m = 3; // rows of A, C static const int kSize_k = 5; // cols of A, rows of B static const int kSize_n = 2; // cols of B, C double matrix_A[kSize_m*kSize_k] = {-7.4, 0.1, 9.1, // first COLUMN of A (col-major storage) 1.5, -8.8, -0.3, -2.9, 6.4, -9.7, -9.1, -6.6, 3.1, 4.6, 3.0, -1.0 }; double matrix_B[kSize_k*kSize_n] = {-1.3, -8.1, -7.2, -0.4, -5.5, 7.4, 5.3, -3.1, -2.3, 1.9 }; double matrix_AB_exact[kSize_m*kSize_n] = {-3.309999999999995, 11.210000000000001, 64.700000000000003, -8.150000000000006, -44.860000000000014, 86.789999999999992 }; double matrix_AB_computed[kSize_m*kSize_n]; GeneralMatrixMatrixMultiply(matrix_A, 'N', matrix_B, 1.0, 0.0, kSize_m, kSize_k, kSize_n, matrix_AB_computed); for (int i = 0; i < kSize_m*kSize_n; ++i) { if (!CheckDoubleWithinRelative(matrix_AB_computed[i], matrix_AB_exact[i], 3.0 * std::numeric_limits<double>::epsilon())) { ++total_errors; } } } const int num_tests = 3; const int sizes[num_tests] = {3, 11, 20}; UniformRandomGenerator uniform_generator(34187); // in each iteration, we perform two tests on matrix-matrix multiply. // 1) form a matrix Q such that Q * Q^T = I (orthogonal matrix); nontrivial in that Q != I // Compute Q * Q^T and check the result. // 2) build a random, SPD matrix, A. (ill-conditioned). // Improve A's conditioning: A = A + size*I (condition number near 1 now) // Form A^-1 (this is OK because A is well-conditioned) // Check A * A^-1 is near I. for (int i = 0; i < num_tests; ++i) { std::vector<double> orthog_symm_matrix(sizes[i]*sizes[i]); std::vector<double> orthog_symm_matrix_T(sizes[i]*sizes[i]); std::vector<double> product_matrix(sizes[i]*sizes[i]); std::vector<double> spd_matrix(sizes[i]*sizes[i]); std::vector<double> cholesky_factor(sizes[i]*sizes[i]); std::vector<double> inverse_spd_matrix(sizes[i]*sizes[i]); std::vector<double> identity_matrix(sizes[i]*sizes[i]); BuildIdentityMatrix(sizes[i], identity_matrix.data()); BuildOrthogonalSymmetricMatrix(sizes[i], orthog_symm_matrix.data()); // not technically necessary since this orthog matrix is also symmetric MatrixTranspose(orthog_symm_matrix.data(), sizes[i], sizes[i], orthog_symm_matrix_T.data()); // Q * Q^T = I if Q is orthogonal GeneralMatrixMatrixMultiply(orthog_symm_matrix.data(), 'N', orthog_symm_matrix_T.data(), 1.0, 0.0, sizes[i], sizes[i], sizes[i], product_matrix.data()); VectorAXPY(sizes[i]*sizes[i], -1.0, identity_matrix.data(), product_matrix.data()); for (int j = 0; j < sizes[i]*sizes[i]; ++j) { // do not use relative comparison b/c we're testing against 0 if (!CheckDoubleWithin(product_matrix[j], 0.0, 20*std::numeric_limits<double>::epsilon())) { ++total_errors; } } // and again testing the T version GeneralMatrixMatrixMultiply(orthog_symm_matrix.data(), 'T', orthog_symm_matrix.data(), 1.0, 0.0, sizes[i], sizes[i], sizes[i], product_matrix.data()); VectorAXPY(sizes[i]*sizes[i], -1.0, identity_matrix.data(), product_matrix.data()); for (int j = 0; j < sizes[i]*sizes[i]; ++j) { // do not use relative comparison b/c we're testing against 0 if (!CheckDoubleWithin(product_matrix[j], 0.0, 20*std::numeric_limits<double>::epsilon())) { ++total_errors; } } BuildRandomSPDMatrix(sizes[i], &uniform_generator, spd_matrix.data()); // ensure spd matrix is well-conditioned (or we can't form A^-1 stably) ModifyMatrixDiagonal(sizes[i], static_cast<double>(sizes[i]), spd_matrix.data()); std::copy(spd_matrix.begin(), spd_matrix.end(), cholesky_factor.begin()); if (ComputeCholeskyFactorL(sizes[i], cholesky_factor.data()) != 0) { ++total_errors; } SPDMatrixInverse(cholesky_factor.data(), sizes[i], inverse_spd_matrix.data()); GeneralMatrixMatrixMultiply(spd_matrix.data(), 'N', inverse_spd_matrix.data(), 1.0, 0.0, sizes[i], sizes[i], sizes[i], product_matrix.data()); VectorAXPY(sizes[i]*sizes[i], -1.0, identity_matrix.data(), product_matrix.data()); for (int j = 0; j < sizes[i]*sizes[i]; ++j) { // do not use relative comparison b/c we're testing against 0 if (!CheckDoubleWithin(product_matrix[j], 0.0, 10*std::numeric_limits<double>::epsilon())) { ++total_errors; } } } return total_errors; }
bool GL::Initialize(HWND hwnd, int screenWidth, int screenHeight, float screenDepth, float screenNear, bool vsync) { int attributeListInt[19]; int pixelFormat[1]; unsigned int formatCount; int result; PIXELFORMATDESCRIPTOR pixelFormatDescriptor; int attributeList[5]; float fieldOfView, screenAspect; char *vendorString, *rendererString; InitializeExtensions(hwnd); auto e = glGetError(); // Get the device context for this window. device_context_ = GetDC(hwnd); if(!device_context_) { return false; } // Support for OpenGL rendering. attributeListInt[0] = WGL_SUPPORT_OPENGL_ARB; attributeListInt[1] = TRUE; // Support for rendering to a window. attributeListInt[2] = WGL_DRAW_TO_WINDOW_ARB; attributeListInt[3] = TRUE; // Support for hardware acceleration. attributeListInt[4] = WGL_ACCELERATION_ARB; attributeListInt[5] = WGL_FULL_ACCELERATION_ARB; // Support for 24bit color. attributeListInt[6] = WGL_COLOR_BITS_ARB; attributeListInt[7] = 32; attributeListInt[8] = WGL_PIXEL_TYPE_ARB; attributeListInt[9] = WGL_TYPE_RGBA_ARB; /* // Support for 24 bit depth buffer. attributeListInt[8] = WGL_DEPTH_BITS_ARB; attributeListInt[9] = 24; // Support for double buffer. attributeListInt[10] = WGL_DOUBLE_BUFFER_ARB; attributeListInt[11] = TRUE; // Support for swapping front and back buffer. attributeListInt[8] = WGL_SWAP_METHOD_ARB; attributeListInt[9] = WGL_SWAP_COPY_ARB; // Support for the RGBA pixel type. // Support for a 8 bit stencil buffer. attributeListInt[16] = WGL_STENCIL_BITS_ARB; attributeListInt[17] = 8; */ // Null terminate the attribute list. attributeListInt[10] = 0; // Query for a pixel format that fits the attributes we want. result = 1;//wglChoosePixelFormatARB(device_context_, attributeListInt, NULL, 1, pixelFormat, &formatCount); if(result != 1) { return false; } // If the video card/display can handle our desired pixel format then we set it as the current one. //result = SetPixelFormat(device_context_, pixelFormat[0], &pixelFormatDescriptor); PIXELFORMATDESCRIPTOR pfd; int iFormat; ZeroMemory( &pfd, sizeof( pfd ) ); pfd.nSize = sizeof( pfd ); pfd.nVersion = 1; pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER; pfd.iPixelType = PFD_TYPE_RGBA; pfd.cColorBits = 32; pfd.cDepthBits = 24; pfd.iLayerType = PFD_MAIN_PLANE; iFormat = ChoosePixelFormat( device_context_, &pfd ); e = glGetError(); result = SetPixelFormat( device_context_, iFormat, &pfd ); e = glGetError(); if(result != 1) { return false; } // Set the 4.0 version of OpenGL in the attribute list. attributeList[0] = WGL_CONTEXT_MAJOR_VERSION_ARB; attributeList[1] = 3; attributeList[2] = WGL_CONTEXT_MINOR_VERSION_ARB; attributeList[3] = 0; // Null terminate the attribute list. attributeList[4] = 0; // Create a OpenGL 4.0 rendering context. rendering_context_ = wglCreateContext(device_context_);//wglCreateContextAttribsARB(device_context_, 0, attributeList); if(rendering_context_ == NULL) { return false; } // Set the rendering context to active. result = wglMakeCurrent(device_context_, rendering_context_); if(result != 1) { return false; } // Set the depth buffer to be entirely cleared to 1.0 values. glClearDepth(1.0f); // Enable depth testing. glEnable(GL_DEPTH_TEST); // Set the polygon winding to front facing for the left handed system. glFrontFace(GL_CW); // Enable back face culling. glEnable(GL_CULL_FACE); glCullFace(GL_BACK); // Initialize the world/model matrix to the identity matrix. BuildIdentityMatrix(worldMatrix); // Set the field of view and screen aspect ratio. fieldOfView = 3.14159265358979323846f / 4.0f; screenAspect = (float)screenWidth / (float)screenHeight; // Build the perspective projection matrix. BuildPerspectiveFovLHMatrix(projectionMatrix, fieldOfView, screenAspect, screenNear, screenDepth); // Get the name of the video card. vendorString = (char*)glGetString(GL_VENDOR); rendererString = (char*)glGetString(GL_RENDERER); // Store the video card name in a class member variable so it can be retrieved later. strcpy_s(videoCardDescription, vendorString); strcat_s(videoCardDescription, " - "); strcat_s(videoCardDescription, rendererString); // Turn on or off the vertical sync depending on the input bool value. if(vsync) { result = 1;//wglSwapIntervalEXT(1); } else { result = 1;//wglSwapIntervalEXT(0); } // Check if vsync was set correctly. if(result != 1) { return false; } return true; }