Thanks again Dark Photon:
This is my prime suspect.
As I stated in this thread’s original post, the code in my init_opengl() was lifted from this tutorial. I’d read about the need to create a fake window to initialize GLEW before creating the context used by the application. It got me started and I’m grateful for the way it laid out the issues.
I don’t have a solid understanding of the pixel format and context attributes. I’ve needed to alter the context attributes.
Here’s the OpenGL initialization code:
#include "stdafx.h"
#include <windows.h>
#include <iostream>
// GLEW
#define GLEW_STATIC
#include <GL/glew.h>
#include <GL/wglew.h>
#include <opengl_utilities.h>
#include "initializing_and_terminating_openglP.h"
const char *FAKE_OPENGL_CLASS_NAME = "FAKE_OPENGL_CLASS";
// This code was lifted, with a little reorganization, from
// http://www.mbsoftworks.sk/index.php?page=tutorials&series=1&tutorial=2
// The OpenGL groupdescribes what's happening here:
// https://www.khronos.org/opengl/wiki/Creating_an_OpenGL_Context_(WGL)#Pixel_Format
HGLRC init_opengl(HWND hwnd, HDC *hdc_ptr, HINSTANCE hinstance, int major_version,
int minor_version, const int *PixelFormatAttribList_ptr, std::string *message_string_ptr)
{
int gl_errors_found_count = 0;
std::string gl_error_message;
HGLRC return_val = NULL;
bool error_found = false;
std::string local_message_string;
PIXELFORMATDESCRIPTOR pfd;
int pixel_format = 0;
int number_of_formats_found = 0;
HDC hdc = GetDC(hwnd);
HWND fake_window = NULL;
std::string text_buffer;
DWORD callers_error = GetLastError();
DWORD error_code = 0;
std::string string_buffer;
SetLastError(0);
if (!init_glew(hinstance, &local_message_string))
{
gl_errors_found_count = gl_error_to_text(&gl_error_message);
error_found = true;
if (message_string_ptr != NULL)
{
*message_string_ptr += "init_opengl()
";
*message_string_ptr += " Failed to initialize glew.
";
*message_string_ptr += local_message_string.c_str();
}
}
else
{
if (major_version <= 2)
{
memset(&pfd, 0, sizeof(PIXELFORMATDESCRIPTOR));
pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR);
pfd.nVersion = 1;
pfd.dwFlags = PFD_DOUBLEBUFFER | PFD_SUPPORT_OPENGL | PFD_DRAW_TO_WINDOW;
pfd.iPixelType = PFD_TYPE_RGBA;
pfd.cColorBits = 32;
pfd.cDepthBits = 32;
pfd.iLayerType = PFD_MAIN_PLANE;
pixel_format = ChoosePixelFormat(hdc, &pfd);
if (pixel_format == 0)
{
error_found = true;
if (message_string_ptr != NULL)
{
*message_string_ptr += "init_opengl()
";
*message_string_ptr += " Failed to choose pixel format.
";
error_code = GetLastError();
if (error_code == 0)
{
*message_string_ptr += "Error code is 0
";
}
else
{
*message_string_ptr += error_code_to_string(error_code, &string_buffer)->c_str();
*message_string_ptr += "
";
}
}
}
else
{
if (!SetPixelFormat(hdc, pixel_format, &pfd))
{
error_found = true;
if (message_string_ptr != NULL)
{
*message_string_ptr += "init_opengl()
";
*message_string_ptr += " Failed to set pixel format.
";
error_code = GetLastError();
if (error_code == 0)
{
*message_string_ptr += "Error code is 0
";
}
else
{
*message_string_ptr += error_code_to_string(error_code, &string_buffer)->c_str();
*message_string_ptr += "
";
}
}
}
else
{
// Create the old style context (OpenGL 2.1 and before)
return_val = wglCreateContext(hdc);
if (return_val == NULL)
{
error_found = true;
if (message_string_ptr != NULL)
{
*message_string_ptr += "init_opengl()
";
*message_string_ptr += " Failed to create context.
";
error_code = GetLastError();
if (error_code == 0)
{
*message_string_ptr += "Error code is 0
";
}
else
{
*message_string_ptr += error_code_to_string(error_code, &string_buffer)->c_str();
*message_string_ptr += "
";
}
}
}
else
{
if(!wglMakeCurrent(hdc, return_val))
{
error_found = true;
if (message_string_ptr != NULL)
{
*message_string_ptr += "init_opengl()
";
*message_string_ptr += " wglMakeCurrent() failed.
";
error_code = GetLastError();
if (error_code == 0)
{
*message_string_ptr += "Error code is 0
";
}
else
{
*message_string_ptr += error_code_to_string(error_code, &string_buffer)->c_str();
*message_string_ptr += "
";
}
}
}
}
}
}
}
else
{
// Version number > 2
if (WGLEW_ARB_create_context && WGLEW_ARB_pixel_format)
{
const int iPixelFormatAttribList[] =
{
WGL_DRAW_TO_WINDOW_ARB, GL_TRUE,
WGL_SUPPORT_OPENGL_ARB, GL_TRUE,
WGL_DOUBLE_BUFFER_ARB, GL_TRUE,
WGL_PIXEL_TYPE_ARB, WGL_TYPE_RGBA_ARB,
WGL_COLOR_BITS_ARB, 32,
WGL_DEPTH_BITS_ARB, 24,
WGL_STENCIL_BITS_ARB, 8,
WGL_SAMPLE_BUFFERS_ARB, GL_TRUE,
WGL_SAMPLES_ARB, 16,
0 // End of attributes list
};
if (PixelFormatAttribList_ptr == NULL)
{
PixelFormatAttribList_ptr = iPixelFormatAttribList;
}
int iContextAttribs[] =
{
WGL_CONTEXT_MAJOR_VERSION_ARB, major_version,
WGL_CONTEXT_MINOR_VERSION_ARB, minor_version,
// WGL_CONTEXT_FLAGS_ARB,
WGL_CONTEXT_PROFILE_MASK_ARB,
WGL_CONTEXT_CORE_PROFILE_BIT_ARB,
// WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB,
0 // End of attributes list
};
if (!wglChoosePixelFormatARB(hdc,
PixelFormatAttribList_ptr,
// iPixelFormatAttribList, // Integer attribute pairs
NULL, // Floating attribute pairs
1, // Max num of formats that can be stored next argument.
&pixel_format, // List of acceptable formats go here.
(UINT*)&number_of_formats_found)) // Number of formats saved in list.
{
error_found = true;
if (message_string_ptr != NULL)
{
*message_string_ptr += "init_opengl()
";
*message_string_ptr += " Failed to choose pixel format.
";
error_code = GetLastError();
if (error_code == 0)
{
*message_string_ptr += "Error code is 0
";
}
else
{
*message_string_ptr += error_code_to_string(error_code, &string_buffer)->c_str();
*message_string_ptr += "
";
}
}
}
else
{
// PFD seems to be only redundant parameter now
// Apparently the PIXELFORMATDESCRIPTOR isn't necessary for SetPixelFormat():
// https://msdn.microsoft.com/en-us/library/windows/desktop/dd369049%28v=vs.85%29.aspx?f=255&MSPPError=-2147217396
if (!SetPixelFormat(hdc, pixel_format, NULL))
{
error_found = true;
if (message_string_ptr != NULL)
{
*message_string_ptr += "init_opengl()
";
*message_string_ptr += " Failed to set pixel format.
";
error_code = GetLastError();
if (error_code == 0)
{
*message_string_ptr += "Error code is 0
";
}
else
{
*message_string_ptr += error_code_to_string(error_code, &string_buffer)->c_str();
*message_string_ptr += "
";
}
}
}
else
{
return_val = wglCreateContextAttribsARB(hdc, 0, iContextAttribs);
// If everything went OK
if (return_val == NULL)
{
error_found = true;
if (message_string_ptr != NULL)
{
*message_string_ptr += "init_opengl()
";
*message_string_ptr += " Faild to create OpenGL context.
";
*message_string_ptr += " OpelGL version:";
totext_s(major_version, &text_buffer, 10);
*message_string_ptr += text_buffer.c_str();
*message_string_ptr += ".";
totext_s(minor_version, &text_buffer, 10);
*message_string_ptr += text_buffer.c_str();
*message_string_ptr += "
";
error_code = GetLastError();
if (error_code == 0)
{
*message_string_ptr += "Error code is 0
";
}
else
{
*message_string_ptr += error_code_to_string(error_code, &string_buffer)->c_str();
*message_string_ptr += "
";
}
}
}
else
{
if(!wglMakeCurrent(hdc, return_val))
{
error_found = true;
if (message_string_ptr != NULL)
{
*message_string_ptr += "init_opengl()
";
*message_string_ptr += " wglMakeCurrent() failed.
";
error_code = GetLastError();
if (error_code == 0)
{
*message_string_ptr += "Error code is 0
";
}
else
{
*message_string_ptr += error_code_to_string(error_code, &string_buffer)->c_str();
*message_string_ptr += "
";
}
}
}
gl_errors_found_count = gl_error_to_text(&gl_error_message);
}
}
}
}
}
}
gl_errors_found_count = gl_error_to_text(&gl_error_message);
if (hdc_ptr != NULL)
{
*hdc_ptr = hdc;
}
// Restore caller's error code, if any.
SetLastError(callers_error);
gl_errors_found_count = gl_error_to_text(&gl_error_message);
return return_val;
}
bool init_glew(HINSTANCE hinstance, std::string *message_string_ptr)
{
// This code is inspired by http://www.mbsoftworks.sk/index.php?page=tutorials&series=1&tutorial=2
// From https://www.khronos.org/opengl/wiki/Creating_an_OpenGL_Context_(WGL)
// The key problem is this: the function you use to get WGL extensions is,
// itself, an OpenGL extension. Thus like any OpenGL function, it requires an
// OpenGL context to call it. So in order to get the functions we need to
// create a context, we have to... create a context.
bool error_found = false;
WNDCLASS fake_window_class;
HDC hdc = NULL;
HGLRC fake_hglrc = NULL;
DWORD error_code = 0;
std::string string_buffer;
memset(&fake_window_class, 0x00, sizeof fake_window_class);
fake_window_class.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC; // Redraw On Move, And Own DC For Window
fake_window_class.lpfnWndProc = fake_WndProc;
fake_window_class.cbClsExtra = 0; // No Extra Window Data
fake_window_class.cbWndExtra = 0; // No Extra Window Data
fake_window_class.hInstance = hinstance; // Set The Instance
fake_window_class.hIcon = NULL; // Load The Default Icon
fake_window_class.hCursor = NULL; // Load The Arrow Pointer
fake_window_class.hbrBackground = HBRUSH(BLACK_BRUSH); // No Background Required For GL
fake_window_class.lpszMenuName = NULL;
fake_window_class.lpszClassName = FAKE_OPENGL_CLASS_NAME; // Set The Class Name
if (!RegisterClass(&fake_window_class)) // Attempt To Register The Window Class
{
error_found = true;
if (message_string_ptr != NULL)
{
*message_string_ptr += "init_glew()
";
*message_string_ptr += " Failed To Register The Window Class ";
*message_string_ptr += FAKE_OPENGL_CLASS_NAME;
*message_string_ptr += ".
";
error_code = GetLastError();
if (error_code == 0)
{
*message_string_ptr += "Error code is 0
";
}
else
{
*message_string_ptr += error_code_to_string(error_code, &string_buffer)->c_str();
*message_string_ptr += "
";
}
}
}
HWND fake_window_handle = CreateWindow(FAKE_OPENGL_CLASS_NAME,
"FAKE",
WS_OVERLAPPEDWINDOW | WS_MAXIMIZE | WS_CLIPCHILDREN,
0,
0,
CW_USEDEFAULT,
CW_USEDEFAULT,
NULL,
NULL,
hinstance,
NULL);
if (fake_window_handle == NULL)
{
error_found = true;
if (message_string_ptr != NULL)
{
*message_string_ptr += "init_glew()
";
*message_string_ptr += " Failed To create ";
*message_string_ptr += FAKE_OPENGL_CLASS_NAME;
*message_string_ptr += " class window.
";
*message_string_ptr += " Hinstance ";
*message_string_ptr += totext_s(int(hinstance), &string_buffer, 16, 8, '0')->c_str();
*message_string_ptr += ".
";
error_code = GetLastError();
if (error_code == 0)
{
*message_string_ptr += "Error code is 0
";
}
else
{
*message_string_ptr += error_code_to_string(error_code, &string_buffer)->c_str();
*message_string_ptr += "
";
}
}
}
else
{
hdc = GetDC(fake_window_handle);
if(hdc == NULL)
{
error_found = true;
if (message_string_ptr != NULL)
{
*message_string_ptr += "init_glew()
";
*message_string_ptr += " GetDC() returned NULL.
";
}
}
else
{
// Choose a pixel format
PIXELFORMATDESCRIPTOR pfd;
memset(&pfd, 0, sizeof(PIXELFORMATDESCRIPTOR));
pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR);
pfd.nVersion = 1;
pfd.dwFlags = PFD_DOUBLEBUFFER | PFD_SUPPORT_OPENGL | PFD_DRAW_TO_WINDOW;
pfd.iPixelType = PFD_TYPE_RGBA;
pfd.cColorBits = 32;
pfd.cDepthBits = 32;
pfd.iLayerType = PFD_MAIN_PLANE;
int pixel_format = ChoosePixelFormat(hdc, &pfd);
if (pixel_format == 0)
{
error_found = true;
if (message_string_ptr != NULL)
{
*message_string_ptr += "init_glew()
";
*message_string_ptr += " ChoosePixelFormat() failed.
";
error_code = GetLastError();
if (error_code == 0)
{
*message_string_ptr += "Error code is 0
";
}
else
{
*message_string_ptr += error_code_to_string(error_code, &string_buffer)->c_str();
*message_string_ptr += "
";
}
}
}
else
{
if (!SetPixelFormat(hdc, pixel_format, &pfd))
{
error_found = true;
if (message_string_ptr != NULL)
{
*message_string_ptr += "init_glew()
";
*message_string_ptr += " SetPixelFormat() failed.
";
error_code = GetLastError();
if (error_code == 0)
{
*message_string_ptr += "Error code is 0
";
}
else
{
*message_string_ptr += error_code_to_string(error_code, &string_buffer)->c_str();
*message_string_ptr += "
";
}
}
}
else
{
// Create the false, old style context (OpenGL 2.1 and before)
fake_hglrc = wglCreateContext(hdc);
if(fake_hglrc == NULL)
{
error_found = true;
if (message_string_ptr != NULL)
{
*message_string_ptr += "init_glew()
";
*message_string_ptr += " wglCreateContext() failed.
";
error_code = GetLastError();
if (error_code == 0)
{
*message_string_ptr += "Error code is 0
";
}
else
{
*message_string_ptr += error_code_to_string(error_code, &string_buffer)->c_str();
*message_string_ptr += "
";
}
}
}
else
{
wglMakeCurrent(hdc, fake_hglrc);
if (glewInit() != GLEW_OK)
{
error_found = true;
if (message_string_ptr != NULL)
{
*message_string_ptr += "init_glew()
";
*message_string_ptr += " Couldn't initialize GLEW!
";
error_code = GetLastError();
if (error_code == 0)
{
*message_string_ptr += "Error code is 0
";
}
else
{
*message_string_ptr += error_code_to_string(error_code, &string_buffer)->c_str();
*message_string_ptr += "
";
}
}
}
}
}
}
}
}
wglMakeCurrent(NULL, NULL);
wglDeleteContext(fake_hglrc);
DestroyWindow(fake_window_handle);
return !error_found;
}
LRESULT CALLBACK fake_WndProc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_CREATE:
return 0;
}
return DefWindowProc(hdlg, message, wParam, lParam);
}
I see where, because of the cut and paste, I did pass a different window size to glViewport() before setting up the buffers. That doesn’t seem to be the source of my problem. glRenderbufferStorageMultisample() and glTexImage2DMultisample() are being passed the same width and height.
Here’s the graphic C++ module. It in no way represents coding practices I use. Most notably, I have a strong aversion to passing global arguments.
For reference I’ve preserved, in commented out form, the original GLFW code.
This is basically a cut and paste of the tutorial’s sample code which can be found here, altered to use WGL instead of GLFW and broken into a function, main_from_tutorial_with_wgl(), called by the window procedure’s message loop’s WM_CREATE clause. The sample’s game loop code is loop_from_tutorial_with_wgl(), which is called when the message loop’s WM_TIMER is serviced.
// GLEW
#define GLEW_STATIC
#include <GL/glew.h>
// GLFW
// #include <GLFW/glfw3.h>
// GL includes
#include "Shader.h"
#include "Camera.h"
// GLM Mathemtics
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
#include <opengl_utilities.h>
#include "learn_opengl_common.h"
// Properties
GLuint screenWidth = 800, screenHeight = 600;
#if 0
// Function prototypes
void key_callback(GLFWwindow* window, int key, int scancode, int action, int mode);
void mouse_callback(GLFWwindow* window, double xpos, double ypos);
void scroll_callback(GLFWwindow* window, double xoffset, double yoffset);
#endif
void Do_Movement();
GLuint generateMultiSampleTexture(GLuint samples);
// Camera
Camera camera(glm::vec3(0.0f, 0.0f, 3.0f));
bool keys[1024];
GLfloat lastX = 400, lastY = 300;
bool firstMouse = true;
GLfloat deltaTime = 0.0f;
GLfloat lastFrame = 0.0f;
// New globals for seperate loop function
GLuint framebuffer;
// GLFWwindow* window;
GLuint cubeVAO;
Shader *shader_ptr = NULL;
// The MAIN function, from here we start our application and run our Game loop
GRAPHICS_PARAMETER *main_from_tutorial_with_wgl(HWND hdlg, HINSTANCE hinstance,
std::string *message_string_ptr)
{
#if 0
// Init GLFW
glfwInit();
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);
window = glfwCreateWindow(screenWidth, screenHeight, "LearnOpenGL", nullptr, nullptr); // Windowed
glfwMakeContextCurrent(window);
// Set the required callback functions
glfwSetKeyCallback(window, key_callback);
glfwSetCursorPosCallback(window, mouse_callback);
glfwSetScrollCallback(window, scroll_callback);
// Options
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
#endif
int gl_errors_found_count = 0;
std::string gl_error_message;
bool error_found = false;
GRAPHICS_PARAMETER *graphics_parameter_ptr = new GRAPHICS_PARAMETER();
windows_camera_wrapper_basic::CAMERA_WRAPPER *free_camera_wrapper_ptr = NULL;
opengl_camera::CAMERA *camera_ptr = NULL;
vector<Mesh> *meshes_vector_ptr = NULL;
HDC hdc = NULL;
std::string local_message_string;
RECT client_rect;
int width = 0;
int height = 0;
graphics_parameter_ptr->set_hwnd(hdlg);
graphics_parameter_ptr->set_hrc(init_opengl(hdlg, &hdc, hinstance, 3, 3,
NULL,
&local_message_string));
if (graphics_parameter_ptr->get_hrc() == NULL)
{
error_found = true;
if (message_string_ptr != NULL)
{
*message_string_ptr += "setup_splash_screen()
";
*message_string_ptr += " HRC is NULL.
";
*message_string_ptr += local_message_string.c_str();
local_message_string.erase();
}
}
else
{
graphics_parameter_ptr->set_hdc(hdc);
if (graphics_parameter_ptr->get_hrc() == NULL)
{
error_found = true;
if (message_string_ptr != NULL)
{
*message_string_ptr += "setup_splash_screen()
";
*message_string_ptr += " OpenGL failed to open.
";
*message_string_ptr += local_message_string.c_str();
local_message_string.erase();
}
}
else
{
GetClientRect(hdlg, &client_rect);
width = client_rect.right - client_rect.left;
height = client_rect.bottom - client_rect.top;
graphics_parameter_ptr->set_client_rect(&client_rect);
glViewport(0, 0, width, height);
initialize_cameras(graphics_parameter_ptr, width, height, VK_TAB, VK_TAB, 0.001);
}
}
screenWidth = width;
screenHeight = height;
// Initialize GLEW to setup the OpenGL Function pointers
glewExperimental = GL_TRUE;
glewInit();
// Define the viewport dimensions
glViewport(0, 0, screenWidth, screenHeight);
// Setup OpenGL options
glEnable(GL_MULTISAMPLE); // Enabled by default on some drivers, but not all so always enable to make sure
glEnable(GL_DEPTH_TEST);
// Setup and compile our shaders
// Shader shader("advanced.shv", "advanced.shf");
// shader_ptr = &shader;
shader_ptr = new Shader("advanced.shv", "advanced.shf");
#pragma region "object_initialization"
// Set the object data (buffers, vertex attributes)
GLfloat cubeVertices[] = {
// Positions
-0.5f, -0.5f, -0.5f,
0.5f, -0.5f, -0.5f,
0.5f, 0.5f, -0.5f,
0.5f, 0.5f, -0.5f,
-0.5f, 0.5f, -0.5f,
-0.5f, -0.5f, -0.5f,
-0.5f, -0.5f, 0.5f,
0.5f, -0.5f, 0.5f,
0.5f, 0.5f, 0.5f,
0.5f, 0.5f, 0.5f,
-0.5f, 0.5f, 0.5f,
-0.5f, -0.5f, 0.5f,
-0.5f, 0.5f, 0.5f,
-0.5f, 0.5f, -0.5f,
-0.5f, -0.5f, -0.5f,
-0.5f, -0.5f, -0.5f,
-0.5f, -0.5f, 0.5f,
-0.5f, 0.5f, 0.5f,
0.5f, 0.5f, 0.5f,
0.5f, 0.5f, -0.5f,
0.5f, -0.5f, -0.5f,
0.5f, -0.5f, -0.5f,
0.5f, -0.5f, 0.5f,
0.5f, 0.5f, 0.5f,
-0.5f, -0.5f, -0.5f,
0.5f, -0.5f, -0.5f,
0.5f, -0.5f, 0.5f,
0.5f, -0.5f, 0.5f,
-0.5f, -0.5f, 0.5f,
-0.5f, -0.5f, -0.5f,
-0.5f, 0.5f, -0.5f,
0.5f, 0.5f, -0.5f,
0.5f, 0.5f, 0.5f,
0.5f, 0.5f, 0.5f,
-0.5f, 0.5f, 0.5f,
-0.5f, 0.5f, -0.5f
};
// Setup cube VAO
GLuint cubeVBO;
glGenVertexArrays(1, &cubeVAO);
glGenBuffers(1, &cubeVBO);
glBindVertexArray(cubeVAO);
glBindBuffer(GL_ARRAY_BUFFER, cubeVBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(cubeVertices), &cubeVertices, GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), (GLvoid*)0);
glBindVertexArray(0);
#pragma endregion
// Framebuffers
glGenFramebuffers(1, &framebuffer);
glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
// Create a multisampled color attachment texture
GLuint textureColorBufferMultiSampled = generateMultiSampleTexture(4);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE, textureColorBufferMultiSampled, 0);
// Create a renderbuffer object for depth and stencil attachments
GLuint rbo;
glGenRenderbuffers(1, &rbo);
glBindRenderbuffer(GL_RENDERBUFFER, rbo);
glRenderbufferStorageMultisample(GL_RENDERBUFFER, 4, GL_DEPTH24_STENCIL8, screenWidth, screenHeight);
glBindRenderbuffer(GL_RENDERBUFFER, 0);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, rbo);
if(glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
std::cout << "ERROR::FRAMEBUFFER:: Framebuffer is not complete!" << std::endl;
glBindFramebuffer(GL_FRAMEBUFFER, 0);
return graphics_parameter_ptr;
}
void loop_from_tutorial_with_wgl(HWND hdlg, GRAPHICS_PARAMETER *graphics_parameter_ptr)
{
#if 0
// Set frame time
GLfloat currentFrame = glfwGetTime();
deltaTime = currentFrame - lastFrame;
lastFrame = currentFrame;
#endif
// Check and call events
// glfwPollEvents();
// Do_Movement();
report_opengl_error_in_popup(hdlg, "After glfwPollEvents()");
// 1. Draw scene as normal in multisampled buffers
glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
glClearColor(0.1f, 0.1f, 0.1f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
report_opengl_error_in_popup(hdlg, "After glClear()");
// Set transformation matrices
shader_ptr->Use();
report_opengl_error_in_popup(hdlg, "After shader_ptr->Use()");
glm::mat4 projection = glm::perspective(camera.Zoom, (GLfloat)screenWidth/(GLfloat)screenHeight, 0.1f, 1000.0f);
glUniformMatrix4fv(glGetUniformLocation(shader_ptr->Program, "projection"), 1, GL_FALSE, glm::value_ptr(projection));
glUniformMatrix4fv(glGetUniformLocation(shader_ptr->Program, "view"), 1, GL_FALSE, glm::value_ptr(camera.GetViewMatrix()));
glUniformMatrix4fv(glGetUniformLocation(shader_ptr->Program, "model"), 1, GL_FALSE, glm::value_ptr(glm::mat4()));
glBindVertexArray(cubeVAO);
glDrawArrays(GL_TRIANGLES, 0, 36);
report_opengl_error_in_popup(hdlg, "After glDrawArrays()");
glBindVertexArray(0);
// 2. Now blit multisampled buffer(s) to default framebuffers
glBindFramebuffer(GL_READ_FRAMEBUFFER, framebuffer);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
report_opengl_error_in_popup(hdlg, "After glBindFramebuffer(GL_READ_FRAMEBUFFER) and glBindFramebuffer(GL_DRAW_FRAMEBUFFER)");
glBlitFramebuffer(0, 0, screenWidth, screenHeight, 0, 0, screenWidth, screenHeight, GL_COLOR_BUFFER_BIT, GL_NEAREST);
report_opengl_error_in_popup(hdlg, "After glBlitFramebuffer()");
// Swap the buffers
// glfwSwapBuffers(window);
SwapBuffers(graphics_parameter_ptr->get_hdc());
report_opengl_error_in_popup(hdlg, "At end of loop, after SwapBuffers()");
}
GLuint generateMultiSampleTexture(GLuint samples)
{
GLuint texture;
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, texture);
glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, samples, GL_RGB8, screenWidth, screenHeight, GL_TRUE);
glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, 0);
return texture;
}
As always Dark Photon, I appreciate your assistance.
Thanks
Larry