GL_INVALID_OPERATION after calling glBindVertexArray(VAO) - c

Everything works up until this step where I get a GL_INVALID_OPERATION error (code 1282). I've confirmed that every opengl function before glBindVertexArray(VAO) return no error codes. I'm also sure that my context is okay because I'm able to draw a simple clearcolor to the screen just fine.
#include <windows.h>
#include <GL/glcorearb.h>
#include <GL/wglext.h>
#include <stdbool.h>
#include <stdio.h>
LRESULT CALLBACK window_procedure(HWND, UINT, WPARAM, LPARAM);
void *get_proc(const char *);
HMODULE gl_module;
bool quit = false;
PFNWGLGETEXTENSIONSSTRINGARBPROC wglGetExtensionsStringARB;
PFNWGLCHOOSEPIXELFORMATARBPROC wglChoosePixelFormatARB;
PFNWGLCREATECONTEXTATTRIBSARBPROC wglCreateContextAttribsARB;
PFNGLGETSTRINGPROC glGetString;
PFNGLCLEARCOLORPROC glClearColor;
PFNGLCLEARPROC glClear;
PFNGLVIEWPORTPROC glViewport;
PFNGLGENBUFFERSPROC glGenBuffers;
PFNGLBINDBUFFERPROC glBindBuffer;
PFNGLBUFFERDATAPROC glBufferData;
PFNGLCREATESHADERPROC glCreateShader;
PFNGLSHADERSOURCEPROC glShaderSource;
PFNGLCOMPILESHADERPROC glCompileShader;
PFNGLGETSHADERIVPROC glGetShaderiv;
PFNGLGETSHADERINFOLOGPROC glGetShaderInfoLog;
PFNGLCREATEPROGRAMPROC glCreateProgram;
PFNGLATTACHSHADERPROC glAttachShader;
PFNGLLINKPROGRAMPROC glLinkProgram;
PFNGLUSEPROGRAMPROC glUseProgram;
PFNGLDELETESHADERPROC glDeleteShader;
PFNGLVERTEXATTRIBPOINTERPROC glVertexAttribPointer;
PFNGLENABLEVERTEXATTRIBARRAYPROC glEnableVertexAttribArray;
PFNGLGENVERTEXARRAYSPROC glGenVertexArrays;
PFNGLBINDVERTEXARRAYPROC glBindVertexArray;
PFNGLDRAWARRAYSPROC glDrawArrays;
PFNGLGETSHADERIVPROC glGetProgramiv;
PFNGLGETSHADERINFOLOGPROC glGetShaderInfoLog;
PFNGLGETPROGRAMINFOLOGPROC glGetProgramInfoLog;
PFNGLGETERRORPROC glGetError;
int WINAPI WinMain(HINSTANCE instance_handle, HINSTANCE prev_instance_handle, PSTR cmd_line, int cmd_show)
{
// Create Window and register it
WNDCLASS window_class;
ZeroMemory(&window_class, sizeof(window_class));
window_class.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
window_class.lpfnWndProc = window_procedure;
window_class.hInstance = instance_handle;
window_class.lpszClassName = TEXT("OPENGL_WINDOW");
RegisterClass(&window_class);
///////////////////////////////////
/* CREATE DUMMY WINDOW TO MAKE DC */
HWND window_handle = CreateWindowEx(WS_EX_OVERLAPPEDWINDOW,
TEXT("OPENGL_WINDOW"),
TEXT("OPENGL_WINDOW"),
WS_OVERLAPPEDWINDOW,
0, 0,
0, 0,
NULL,
NULL,
instance_handle,
NULL);
HDC dc = GetDC(window_handle);
PIXELFORMATDESCRIPTOR descriptor;
ZeroMemory(&descriptor, sizeof(descriptor));
descriptor.nSize = sizeof(descriptor);
descriptor.nVersion = 1;
descriptor.dwFlags = PFD_DRAW_TO_WINDOW | PFD_DRAW_TO_BITMAP | PFD_SUPPORT_OPENGL | PFD_GENERIC_ACCELERATED | PFD_DOUBLEBUFFER | PFD_SWAP_LAYER_BUFFERS;
descriptor.iPixelType = PFD_TYPE_RGBA;
descriptor.cColorBits = 32;
descriptor.cRedBits = 8;
descriptor.cGreenBits = 8;
descriptor.cBlueBits = 8;
descriptor.cAlphaBits = 8;
descriptor.cDepthBits = 32;
descriptor.cStencilBits = 8;
int pixel_format = ChoosePixelFormat(dc, &descriptor);
SetPixelFormat(dc, pixel_format, &descriptor);
HGLRC rc = wglCreateContext(dc);
wglMakeCurrent(dc, rc);
gl_module = LoadLibrary(TEXT("opengl32.dll"));
wglGetExtensionsStringARB = (PFNWGLGETEXTENSIONSSTRINGARBPROC)get_proc("wglGetExtensionsStringARB");
wglChoosePixelFormatARB = (PFNWGLCHOOSEPIXELFORMATARBPROC)get_proc("wglChoosePixelFormatARB");
wglCreateContextAttribsARB = (PFNWGLCREATECONTEXTATTRIBSARBPROC)get_proc("wglCreateContextAttribsARB");
glGetString = (PFNGLGETSTRINGPROC)get_proc("glGetString"); //
glClearColor = (PFNGLCLEARCOLORPROC)get_proc("glClearColor"); //
glClear = (PFNGLCLEARPROC)get_proc("glClear"); //
glViewport = (PFNGLVIEWPORTPROC)get_proc("glViewport"); //
glGenBuffers = (PFNGLGENBUFFERSPROC)get_proc("glGenBuffers");
glBindBuffer = (PFNGLBINDBUFFERPROC)get_proc("glBindBuffer");
glBufferData = (PFNGLBUFFERDATAPROC)get_proc("glBufferData");
glCreateShader = (PFNGLCREATESHADERPROC)get_proc("glCreateShader");
glShaderSource = (PFNGLSHADERSOURCEPROC)get_proc("glShaderSource");
glCompileShader = (PFNGLCOMPILESHADERPROC)get_proc("glCompileShader");
glGetShaderiv = (PFNGLGETSHADERIVPROC)get_proc("glGetShaderiv");
glGetShaderInfoLog = (PFNGLGETSHADERINFOLOGPROC)get_proc("glGetShaderInfoLog");
glCreateProgram = (PFNGLCREATEPROGRAMPROC)get_proc("glCreateProgram");
glAttachShader = (PFNGLATTACHSHADERPROC)get_proc("glAttachShader");
glLinkProgram = (PFNGLLINKPROGRAMPROC)get_proc("glLinkProgram");
glVertexAttribPointer = (PFNGLVERTEXATTRIBPOINTERPROC)get_proc("glVertexAttribPointer");
glEnableVertexAttribArray = (PFNGLENABLEVERTEXATTRIBARRAYPROC)get_proc("glEnableVertexAttribArray");
glGenVertexArrays = (PFNGLGENVERTEXARRAYSPROC)get_proc("glEnableVertexAttribArray");
glBindVertexArray = (PFNGLBINDVERTEXARRAYPROC)get_proc("glBindVertexArray");
glDrawArrays = (PFNGLDRAWARRAYSPROC)get_proc("glDrawArrays");
glGetProgramiv = (PFNGLGETPROGRAMIVPROC)get_proc("glGetProgramiv");
glGetShaderInfoLog = (PFNGLGETSHADERINFOLOGPROC)get_proc("glGetShaderInfoLog");
glGetProgramInfoLog = (PFNGLGETPROGRAMINFOLOGPROC)get_proc(("glGetProgramInfoLog"));
glUseProgram = (PFNGLUSEPROGRAMPROC)get_proc("glUseProgram");
glDeleteShader = (PFNGLDELETESHADERPROC)get_proc(("glDeleteShader"));
glGetError = (PFNGLGETERRORPROC)get_proc("glGetError");
FreeLibrary(gl_module);
int pixel_format_arb = 0;
UINT pixel_formats_found = 0;
int pixel_attributes[] = {
WGL_SUPPORT_OPENGL_ARB, 1,
WGL_DRAW_TO_WINDOW_ARB, 1,
WGL_DRAW_TO_BITMAP_ARB, 1,
WGL_DOUBLE_BUFFER_ARB, 1,
WGL_SWAP_LAYER_BUFFERS_ARB, 1,
WGL_COLOR_BITS_ARB, 32,
WGL_RED_BITS_ARB, 8,
WGL_GREEN_BITS_ARB, 8,
WGL_BLUE_BITS_ARB, 8,
WGL_ALPHA_BITS_ARB, 8,
WGL_DEPTH_BITS_ARB, 32,
WGL_STENCIL_BITS_ARB, 8,
WGL_ACCELERATION_ARB, WGL_FULL_ACCELERATION_ARB,
WGL_PIXEL_TYPE_ARB, WGL_TYPE_RGBA_ARB,
0};
BOOL result = wglChoosePixelFormatARB(dc, pixel_attributes, NULL, 1, &pixel_format_arb, &pixel_formats_found);
/* RECREATE WINDOW */
wglMakeCurrent(dc, NULL);
wglDeleteContext(rc);
ReleaseDC(window_handle, dc);
DestroyWindow(window_handle);
window_handle = CreateWindowEx(WS_EX_OVERLAPPEDWINDOW,
TEXT("OPENGL_WINDOW"),
TEXT("OPENGL_WINDOW"),
WS_OVERLAPPEDWINDOW,
((GetSystemMetrics(SM_CXSCREEN) - 800) / 2), ((GetSystemMetrics(SM_CYSCREEN) - 600) / 2),
800, 600,
NULL,
NULL,
instance_handle,
NULL);
dc = GetDC(window_handle);
SetPixelFormat(dc, pixel_format, &descriptor);
ShowWindow(window_handle, SW_SHOW);
/* NEW CONTEXT */
GLint context_attributes[] = {
WGL_CONTEXT_MAJOR_VERSION_ARB, 3,
WGL_CONTEXT_MINOR_VERSION_ARB, 3,
WGL_CONTEXT_PROFILE_MASK_ARB, WGL_CONTEXT_CORE_PROFILE_BIT_ARB,
0};
rc = wglCreateContextAttribsARB(dc, 0, context_attributes);
wglMakeCurrent(dc, rc);
const char *vertexShaderSource = "#version 330 core\n"
"layout (location = 0) in vec3 aPos;\n"
"void main()\n"
"{\n"
" gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0);\n"
"}\0";
const char *fragmentShaderSource = "#version 330 core\n"
"out vec4 FragColor;\n"
"void main()\n"
"{\n"
" FragColor = vec4(1.0f, 0.5f, 0.2f, 1.0f);\n"
"}\n\0";
unsigned int vertexShader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertexShader, 1, &vertexShaderSource, NULL);
glCompileShader(vertexShader);
// fragment shader
unsigned int fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentShader, 1, &fragmentShaderSource, NULL);
glCompileShader(fragmentShader);
// link shaders
unsigned int shaderProgram = glCreateProgram();
glAttachShader(shaderProgram, vertexShader);
glAttachShader(shaderProgram, fragmentShader);
glLinkProgram(shaderProgram);
glDeleteShader(vertexShader);
glDeleteShader(fragmentShader);
// set up vertex data (and buffer(s)) and configure vertex attributes
// ------------------------------------------------------------------
float vertices[] = {
-0.5f, -0.5f, 0.0f, // left
0.5f, -0.5f, 0.0f, // right
0.0f, 0.5f, 0.0f // top
};
GLuint VBO, VAO;
glGenVertexArrays(1, &VAO);
printf("%d\n", VAO);
glGenBuffers(1, &VBO);
// bind the Vertex Array Object first, then bind and set vertex buffer(s), and then configure vertex attributes(s).
glBindVertexArray(VAO);
GLenum error = glGetError();
printf("%d", error);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void *)0);
glEnableVertexAttribArray(0);
// note that this is allowed, the call to glVertexAttribPointer registered VBO as the vertex attribute's bound vertex buffer object so afterwards we can safely unbind
glBindBuffer(GL_ARRAY_BUFFER, 0);
// You can unbind the VAO afterwards so other VAO calls won't accidentally modify this VAO, but this rarely happens. Modifying other
// VAOs requires a call to glBindVertexArray anyways so we generally don't unbind VAOs (nor VBOs) when it's not directly necessary.
glBindVertexArray(0);
/* EVENT PUMP */
MSG msg;
while (true)
{
if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
if (msg.message == WM_QUIT)
break;
TranslateMessage(&msg);
DispatchMessage(&msg);
}
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
glUseProgram(shaderProgram);
glBindVertexArray(VAO); // seeing as we only have a single VAO there's no need to bind it every time, but we'll do so to keep things a bit more organized
glDrawArrays(GL_TRIANGLES, 0, 3);
SwapBuffers(dc);
}
return 0;
}
// Procedure that processes window events
LRESULT CALLBACK window_procedure(HWND window_handle, UINT message, WPARAM param_w, LPARAM param_l)
{
return DefWindowProc(window_handle, message, param_w, param_l);
}
/* A procedure for getting OpenGL functions and OpenGL or WGL extensions.
When looking for OpenGL 1.2 and above, or extensions, it uses wglGetProcAddress,
otherwise it falls back to GetProcAddress. */
void *get_proc(const char *proc_name)
{
void *proc = (void *)wglGetProcAddress(proc_name);
if (!proc)
{
proc = (void *)GetProcAddress(gl_module, proc_name);
}
return proc;
}

Related

Why my openGL program shows a blank screen?

I created this simple hello triangle program from internet samples, but no matter how I try, I always get a blank screen. I would appreciate any help.
The development environment is Visual Studio on Windows 10 with CUDA 10.
The glGetError at the display callback return 0.
Here is the full source code:
#pragma comment(lib, "C:\\GL\\GLUT\\lib\\x64\\freeglut.lib")
#define GLEW_STATIC
#include <stdio.h>
#include <stdlib.h>
#include <GL/glew.h>
#include <GL/glut.h>
const char* vertexShaderSource = "#version 460 core\n"
"layout(location = 0) in vec3 aPos;\n"
"layout(location = 1) in vec3 aColor;\n"
"out vec4 vertexColor;\n"
"void main()\n"
"{\n"
" gl_Position = vec4(aPos, 1.0);\n"
" vertexColor = vec4(aColor, 1.0);\n"
"}\0";
unsigned int vertexShader;
const char* fragmentShaderSource = "#version 460 core\n"
"in vec4 vertexColor;\n"
"out vec4 FragColor;\n"
"void main()\n"
"{\n"
" FragColor = vertexColor;\n"
"}\0";
unsigned int shaderProgram;
unsigned int VAO;
void keyboard(unsigned char key, int x, int y)
{
switch (key)
{
/* Exit on escape key press */
case '\x1B':
{
exit(EXIT_SUCCESS);
break;
}
}
}
void display()
{
glUseProgram(shaderProgram);
glClear(GL_COLOR_BUFFER_BIT);
glBindVertexArray(VAO);
glDrawArrays(GL_TRIANGLES, 0, 3);
printf("GL error=%d\n", glGetError()); fflush(stdout);
}
/* Main method */
int main(int argc, char** argv)
{
glutInitContextVersion(4, 6);
glutInit(&argc, argv);
glutInitWindowSize(800, 600);
glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH);
glutCreateWindow("Automaton");
printf("%s\n", glGetString(GL_VERSION));
glViewport(0, 0, 800, 600);
GLenum err = glewInit();
if (GLEW_OK != err)
{
printf("glew init %s\n", glewGetErrorString(err)); fflush(stdout);
return -1;
}
//
// Create shaders
//
int success;
char infoLog[512];
vertexShader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertexShader, 1, &vertexShaderSource, NULL);
glCompileShader(vertexShader);
glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &success);
if (!success)
{
glGetShaderInfoLog(vertexShader, 512, NULL, infoLog);
perror("Vertex shader failed.\n");
return -1;
}
unsigned int fragmentShader;
fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentShader, 1, &fragmentShaderSource, NULL);
glCompileShader(fragmentShader);
glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &success);
if (!success)
{
glGetShaderInfoLog(vertexShader, 512, NULL, infoLog);
perror("Vertex shader failed.\n");
return -1;
}
//
// Link shaders
//
shaderProgram = glCreateProgram();
glAttachShader(shaderProgram, vertexShader);
glAttachShader(shaderProgram, fragmentShader);
glLinkProgram(shaderProgram);
glGetProgramiv(shaderProgram, GL_LINK_STATUS, &success);
if (!success)
{
glGetProgramInfoLog(shaderProgram, 512, NULL, infoLog);
perror("Linking error.\n");
return -1;
}
glDeleteShader(vertexShader);
glDeleteShader(fragmentShader);
//
float vertices[] =
{
-1.0f, -1.0f, 0.0f, 1.0f, 0.0f, 0.0f,
1.0f, -1.0f, 0.0f, 0.0f, 1.0f, 0.0f,
0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f
};
GLuint attribPos = 0;
GLuint attribCol = 1;
//
unsigned int VBO;
glCreateBuffers(1, &VBO);
glCreateVertexArrays(1, &VAO);
glNamedBufferStorage(VBO, sizeof(vertices), vertices, GL_DYNAMIC_STORAGE_BIT);
GLuint vaoBindingPoint = 0;
glVertexArrayVertexBuffer(VAO, vaoBindingPoint, VBO, 0, 6 * sizeof(float));
glEnableVertexArrayAttrib(VAO, attribPos);
glEnableVertexArrayAttrib(VAO, attribCol);
glVertexArrayAttribFormat(VAO, attribPos, 3, GL_FLOAT, 0/*false*/, 0);
glVertexArrayAttribFormat(VAO, attribCol, 3, GL_FLOAT, 0/*false*/, 3 * sizeof(float));
glVertexArrayAttribBinding(VAO, attribPos, vaoBindingPoint);
glVertexArrayAttribBinding(VAO, attribCol, vaoBindingPoint);
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
glutKeyboardFunc(&keyboard);
glutDisplayFunc(&display);
glutMainLoop();
return EXIT_SUCCESS;
}
The program is running in a DELL PC with NVIDIA GPU 1050.
You have to call glutSwapBuffers to flush the display respectively perform a buffer swap:
void display()
{
glUseProgram(shaderProgram);
glClear(GL_COLOR_BUFFER_BIT);
glBindVertexArray(VAO);
glDrawArrays(GL_TRIANGLES, 0, 3);
printf("GL error=%d\n", glGetError()); fflush(stdout);
glutSwapBuffers();
}

OpenGL context creation with ARB fails

I am trying to create an OpenGL context with the ARB extention. I read lots of documentations, posts and the khronos wiki about that. But i can't make the final context current, as you see in the code, the second wglMakeCurrent() call is commented out, which means that the context that is acctualy used is the first one created, without the extention. If I uncomment that, the window doesn't displays.
I did some error testing with the ARB functions, it seems that the problem comes from the attribute list or the wglChoosePixelFormatARB() call.
The code :
#include <stdio.h>
#define UNICODE
#include <windows.h>
#include <dwmapi.h>
#define GLEW_STATIC
#include <glew.h>
#include <GL\wglext.h>
LRESULT CALLBACK WindowProcedure(HWND hWnd, UINT uMsg, WPARAM wp, LPARAM lp);
unsigned int CreateShaderProgram(char* VertexSource, char* FragmentSource);
int main(void){
WNDCLASSEX wcx = {};
wcx.cbSize = sizeof(WNDCLASSEX);
wcx.style = CS_OWNDC;
wcx.lpfnWndProc = WindowProcedure;
wcx.lpszClassName = L"Win32Class";
RegisterClassEx(&wcx);
HWND hWnd = CreateWindowEx(WS_EX_APPWINDOW | WS_EX_LAYERED, wcx.lpszClassName, L"Title",
WS_POPUP, 400, 300, 800, 400, NULL, NULL, NULL, NULL);
DWM_BLURBEHIND blur = {};
blur.dwFlags = DWM_BB_ENABLE | DWM_BB_BLURREGION;
blur.fEnable = 1;
blur.hRgnBlur = CreateRectRgn(0, 0, -1, -1);
DwmEnableBlurBehindWindow(hWnd, &blur);
SetLayeredWindowAttributes(hWnd, RGB(0, 0, 0), 255, LWA_COLORKEY);
PIXELFORMATDESCRIPTOR pfd = {};
pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR);
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.cStencilBits = 8;
pfd.iLayerType = PFD_MAIN_PLANE;
HDC DeviceContext = GetDC(hWnd);
int PixelFormat = ChoosePixelFormat(DeviceContext, &pfd);
SetPixelFormat(DeviceContext, PixelFormat, &pfd);
HGLRC RenderingContext = wglCreateContext(DeviceContext);
wglMakeCurrent(DeviceContext, RenderingContext);
glewInit();
int Attributes[] = {
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_CONTEXT_MAJOR_VERSION_ARB, 4,
WGL_CONTEXT_MINOR_VERSION_ARB, 4,
WGL_CONTEXT_PROFILE_MASK_ARB, WGL_CONTEXT_CORE_PROFILE_BIT_ARB,
0,
};
PFNWGLCHOOSEPIXELFORMATARBPROC wglChoosePixelFormatARB =
wglGetProcAddress("wglChoosePixelFormatARB");
PFNWGLCREATECONTEXTATTRIBSARBPROC wglCreateContextAttribsARB =
(PFNWGLCREATECONTEXTATTRIBSARBPROC)
wglGetProcAddress("wglCreateContextAttribsARB");
wglChoosePixelFormatARB(DeviceContext, Attributes, NULL, 1, &PixelFormat,
NULL);
SetPixelFormat(DeviceContext, PixelFormat, &pfd);
RenderingContext = wglCreateContextAttribsARB(DeviceContext, NULL,
Attributes);
//wglMakeCurrent(DeviceContext, RenderingContext);
char VertexShaderSource[] =
"#version 440 core\n"
"\n"
"layout(location = 0) in vec4 position;\n"
"\n"
"void main(){\n"
" gl_Position = position;\n"
"}";
char FragmentShaderSource[] =
"#version 440 core\n"
"\n"
"layout(location = 0) out vec4 colour;\n"
"\n"
"void main(){\n"
" colour = vec4(0.5, 0.5, 0.5, 1.0);\n"
"}";
float Verticies[] = {
0.0f, 0.5f, // top : 0
0.5f, 0.0f, // right : 1
0.0f, -0.5f, // bottom : 2
-0.5f, 0.0f // left : 3
};
unsigned int Indices[] = {
3, 0, 1, // top
3, 2, 1 // bottom
};
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
unsigned int VertexArray;
glGenVertexArrays(1, &VertexArray);
glBindVertexArray(VertexArray);
unsigned int VertexBuffer;
glGenBuffers(1, &VertexBuffer);
glBindBuffer(GL_ARRAY_BUFFER, VertexBuffer);
glBufferData(GL_ARRAY_BUFFER, 8 * sizeof(float), Verticies, GL_STATIC_DRAW);
unsigned int IndexBuffer;
glGenBuffers(1, &IndexBuffer);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, IndexBuffer);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, 6 * sizeof(unsigned int), Indices,
GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(float) * 2, 0);
unsigned int ShaderProgram = CreateShaderProgram(VertexShaderSource,
FragmentShaderSource);
glUseProgram(ShaderProgram);
glViewport(0, 0, 800, 400);
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
ShowWindow(hWnd, 1);
MSG msg;
while(GetMessage(&msg, NULL, 0, 0)){
DispatchMessage(&msg);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, NULL);
wglSwapLayerBuffers(DeviceContext, WGL_SWAP_MAIN_PLANE);
}
}
LRESULT CALLBACK WindowProcedure(HWND hWnd, UINT uMsg, WPARAM wp, LPARAM lp){
switch(uMsg){
case WM_NCHITTEST: return HTCAPTION;
case WM_DESTROY: PostQuitMessage(0); return 0;
default: return DefWindowProc(hWnd, uMsg, wp, lp);
}
}
unsigned int CreateShader(char* Source, unsigned int Type);
unsigned int CreateShaderProgram(char* VertexSource,
char* FragmentSource){
unsigned int ShaderProgram = glCreateProgram(),
VertexShader = CreateShader(VertexSource, GL_VERTEX_SHADER),
FragmentShader = CreateShader(FragmentSource, GL_FRAGMENT_SHADER);
glAttachShader(ShaderProgram, VertexShader);
glAttachShader(ShaderProgram, FragmentShader);
glLinkProgram(ShaderProgram);
glValidateProgram(ShaderProgram);
return ShaderProgram;
}
unsigned int CreateShader(char* Source, unsigned int Type){
unsigned int Shader = glCreateShader(Type);
glShaderSource(Shader, 1, (const char* const*)&Source, NULL);
glCompileShader(Shader);
return Shader;
}
Note : The cast of the result of the second call to wglGetProcAdress() produces a warning if the -Wextra flag is set ( for the gcc compiler ). I don't know how to fix it.
Update : This still not works : "Choosing the final window pixel format failed." and "Creating the final rendering context failed." are printed (see the code) below. And the window does not displays.
The new code : (the big comment is the old code) :
#include <stdio.h>
#define UNICODE
#include <windows.h>
#include <dwmapi.h>
#define GLEW_STATIC
#include <glew.h>
#include <GL\wglext.h>
LRESULT CALLBACK FirstWindowProcedure(HWND hWnd, UINT uMsg, WPARAM wp,
LPARAM lp);
LRESULT CALLBACK FinalWindowProcedure(HWND hWnd, UINT uMsg, WPARAM wp,
LPARAM lp);
unsigned int CreateShaderProgram(char* VertexSource, char* FragmentSource);
int main(void){
WNDCLASSEX FirstWindowClass = {};
FirstWindowClass.cbSize = sizeof(WNDCLASSEX);
FirstWindowClass.style = CS_OWNDC;
FirstWindowClass.lpfnWndProc = FirstWindowProcedure;
FirstWindowClass.lpszClassName = L"FirstWindowClass";
if(!RegisterClassEx(&FirstWindowClass))
puts("Registration of the first window class failed.\n");
HWND FirstWindow = CreateWindowEx(WS_EX_APPWINDOW,
FirstWindowClass.lpszClassName, L"FirstWindow", WS_POPUP, 0, 0, 10, 10,
NULL, NULL, NULL, NULL);
if(FirstWindow == NULL)
puts("Creation of the first window failed.\n");
PIXELFORMATDESCRIPTOR FirstWindowPixelFormatDescriptor = {};
FirstWindowPixelFormatDescriptor.nSize = sizeof(PIXELFORMATDESCRIPTOR);
FirstWindowPixelFormatDescriptor.nVersion = 1;
FirstWindowPixelFormatDescriptor.dwFlags = PFD_DRAW_TO_WINDOW |
PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
FirstWindowPixelFormatDescriptor.iPixelType = PFD_TYPE_RGBA;
FirstWindowPixelFormatDescriptor.cColorBits = 32;
FirstWindowPixelFormatDescriptor.cDepthBits = 24;
FirstWindowPixelFormatDescriptor.cStencilBits = 8;
FirstWindowPixelFormatDescriptor.iLayerType = PFD_MAIN_PLANE;
HDC FirstWindowDeviceContext = GetDC(FirstWindow);
if(FirstWindowDeviceContext == NULL)
puts("First window device context retrieving failed.\n");
int FirstWindowPixelFormat = ChoosePixelFormat(FirstWindowDeviceContext,
&FirstWindowPixelFormatDescriptor);
if(FirstWindowPixelFormat == 0)
puts("Choosing the first pixel format failed.\n");
if(SetPixelFormat(FirstWindowDeviceContext, FirstWindowPixelFormat,
&FirstWindowPixelFormatDescriptor) == FALSE)
puts("Setting the first pixel format failed.\n");
HGLRC FirstWindowRenderingContext =
wglCreateContext(FirstWindowDeviceContext);
if(FirstWindowRenderingContext == NULL)
puts("Creating the first rendering context failed.\n");
if(wglMakeCurrent(FirstWindowDeviceContext, FirstWindowRenderingContext) ==
FALSE)
puts("Making the first context current failed.\n");
if(glewInit() != GLEW_OK)
puts("Initialisation of GLEW failed.\n");
WNDCLASSEX FinalWindowClass = {};
FinalWindowClass.cbSize = sizeof(WNDCLASSEX);
FinalWindowClass.style = CS_OWNDC;
FinalWindowClass.lpfnWndProc = FinalWindowProcedure;
FinalWindowClass.lpszClassName = L"FinalWindowClass";
if(!RegisterClassEx(&FinalWindowClass))
puts("Registration of the final window class failed\n");
HWND FinalWindow = CreateWindowEx(WS_EX_APPWINDOW,
FinalWindowClass.lpszClassName, L"FinalWindow", WS_POPUP, 0, 0, 10, 10,
NULL, NULL, NULL, NULL);
if(FinalWindow == NULL)
puts("Creation of the final window failed.\n");
PFNWGLCHOOSEPIXELFORMATARBPROC wglChoosePixelFormatARB =
wglGetProcAddress("wglChoosePixelFormatARB");
if(wglChoosePixelFormatARB == NULL)
puts("Getting the wglChoosePixelFormatARB function pointer failed.\n");
PFNWGLCREATECONTEXTATTRIBSARBPROC wglCreateContextAttribsARB =
(PFNWGLCREATECONTEXTATTRIBSARBPROC)
wglGetProcAddress("wglCreateContextAttribsARB");
if(wglCreateContextAttribsARB == NULL)
puts("Getting the wglCreateContextAttribsARB function pointer"
"failed.\n");
int FinalWindowContextAttributes[] = {
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_CONTEXT_MAJOR_VERSION_ARB, 4,
WGL_CONTEXT_MINOR_VERSION_ARB, 4,
WGL_CONTEXT_PROFILE_MASK_ARB, WGL_CONTEXT_CORE_PROFILE_BIT_ARB,
0,
};
HDC FinalWindowDeviceContext = GetDC(FinalWindow);
if(FinalWindowDeviceContext == NULL)
puts("Retrieving the final window device cotext failed.\n");
int FinalWindowPixelFormat;
if(FALSE == wglChoosePixelFormatARB(FinalWindowDeviceContext,
FinalWindowContextAttributes, NULL, 1, &FinalWindowPixelFormat, NULL))
puts("Choosing the final window pixel format failed.\n");
HGLRC FinalWindowRenderingContext =
wglCreateContextAttribsARB(FinalWindowDeviceContext, NULL,
FinalWindowContextAttributes);
if(FinalWindowRenderingContext == NULL)
puts("Creating the final rendering context failed.\n");
if(FALSE == wglMakeCurrent(FinalWindowDeviceContext,
FinalWindowRenderingContext))
puts("Making the final context current failed.\n");
DWM_BLURBEHIND blur = {};
blur.dwFlags = DWM_BB_ENABLE | DWM_BB_BLURREGION;
blur.fEnable = 1;
blur.hRgnBlur = CreateRectRgn(0, 0, -1, -1);
DwmEnableBlurBehindWindow(FinalWindow, &blur);
SetLayeredWindowAttributes(FinalWindow, RGB(0, 0, 0), 255, LWA_COLORKEY);
// ----- ----- ----- //
/*WNDCLASSEX wcx = {};
wcx.cbSize = sizeof(WNDCLASSEX);
wcx.style = CS_OWNDC;
wcx.lpfnWndProc = WindowProcedure;
wcx.lpszClassName = L"Win32Class";
RegisterClassEx(&wcx);
HWND hWnd = CreateWindowEx(WS_EX_APPWINDOW | WS_EX_LAYERED, wcx.lpszClassName, L"Title",
WS_POPUP, 400, 300, 800, 400, NULL, NULL, NULL, NULL);
DWM_BLURBEHIND blur = {};
blur.dwFlags = DWM_BB_ENABLE | DWM_BB_BLURREGION;
blur.fEnable = 1;
blur.hRgnBlur = CreateRectRgn(0, 0, -1, -1);
DwmEnableBlurBehindWindow(hWnd, &blur);
SetLayeredWindowAttributes(hWnd, RGB(0, 0, 0), 255, LWA_COLORKEY);
PIXELFORMATDESCRIPTOR pfd = {};
pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR);
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.cStencilBits = 8;
pfd.iLayerType = PFD_MAIN_PLANE;
HDC DeviceContext = GetDC(hWnd);
int PixelFormat = ChoosePixelFormat(DeviceContext, &pfd);
SetPixelFormat(DeviceContext, PixelFormat, &pfd);
HGLRC RenderingContext = wglCreateContext(DeviceContext);
wglMakeCurrent(DeviceContext, RenderingContext);
glewInit();
int Attributes[] = {
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_CONTEXT_MAJOR_VERSION_ARB, 4,
WGL_CONTEXT_MINOR_VERSION_ARB, 4,
WGL_CONTEXT_PROFILE_MASK_ARB, WGL_CONTEXT_CORE_PROFILE_BIT_ARB,
0,
};
PFNWGLCHOOSEPIXELFORMATARBPROC wglChoosePixelFormatARB =
wglGetProcAddress("wglChoosePixelFormatARB");
PFNWGLCREATECONTEXTATTRIBSARBPROC wglCreateContextAttribsARB =
(PFNWGLCREATECONTEXTATTRIBSARBPROC)
wglGetProcAddress("wglCreateContextAttribsARB");
wglChoosePixelFormatARB(DeviceContext, Attributes, NULL, 1, &PixelFormat,
NULL);
RenderingContext = wglCreateContextAttribsARB(DeviceContext, NULL,
Attributes);
wglMakeCurrent(DeviceContext, RenderingContext);*/
char VertexShaderSource[] =
"#version 440 core\n"
"\n"
"layout(location = 0) in vec4 position;\n"
"\n"
"void main(){\n"
" gl_Position = position;\n"
"}";
char FragmentShaderSource[] =
"#version 440 core\n"
"\n"
"layout(location = 0) out vec4 colour;\n"
"\n"
"void main(){\n"
" colour = vec4(0.5, 0.5, 0.5, 1.0);\n"
"}";
float Verticies[] = {
0.0f, 0.5f, // top : 0
0.5f, 0.0f, // right : 1
0.0f, -0.5f, // bottom : 2
-0.5f, 0.0f // left : 3
};
unsigned int Indices[] = {
3, 0, 1, // top
3, 2, 1 // bottom
};
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
unsigned int VertexArray;
glGenVertexArrays(1, &VertexArray);
glBindVertexArray(VertexArray);
unsigned int VertexBuffer;
glGenBuffers(1, &VertexBuffer);
glBindBuffer(GL_ARRAY_BUFFER, VertexBuffer);
glBufferData(GL_ARRAY_BUFFER, 8 * sizeof(float), Verticies, GL_STATIC_DRAW);
unsigned int IndexBuffer;
glGenBuffers(1, &IndexBuffer);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, IndexBuffer);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, 6 * sizeof(unsigned int), Indices,
GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(float) * 2, 0);
unsigned int ShaderProgram = CreateShaderProgram(VertexShaderSource,
FragmentShaderSource);
glUseProgram(ShaderProgram);
glViewport(0, 0, 800, 400);
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
ShowWindow(FinalWindow, 1);
MSG msg;
while(GetMessage(&msg, NULL, 0, 0)){
DispatchMessage(&msg);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, NULL);
wglSwapLayerBuffers(FinalWindowDeviceContext, WGL_SWAP_MAIN_PLANE);
}
}
LRESULT CALLBACK FirstWindowProcedure(HWND hWnd, UINT uMsg, WPARAM wp, LPARAM lp){
return DefWindowProc(hWnd, uMsg, wp, lp);
}
LRESULT CALLBACK FinalWindowProcedure(HWND hWnd, UINT uMsg, WPARAM wp, LPARAM lp){
switch(uMsg){
case WM_NCHITTEST: return HTCAPTION;
case WM_DESTROY: PostQuitMessage(0); return 0;
default: return DefWindowProc(hWnd, uMsg, wp, lp);
}
}
unsigned int CreateShader(char* Source, unsigned int Type);
unsigned int CreateShaderProgram(char* VertexSource,
char* FragmentSource){
unsigned int ShaderProgram = glCreateProgram(),
VertexShader = CreateShader(VertexSource, GL_VERTEX_SHADER),
FragmentShader = CreateShader(FragmentSource, GL_FRAGMENT_SHADER);
glAttachShader(ShaderProgram, VertexShader);
glAttachShader(ShaderProgram, FragmentShader);
glLinkProgram(ShaderProgram);
glValidateProgram(ShaderProgram);
return ShaderProgram;
}
unsigned int CreateShader(char* Source, unsigned int Type){
unsigned int Shader = glCreateShader(Type);
glShaderSource(Shader, 1, (const char* const*)&Source, NULL);
glCompileShader(Shader);
return Shader;
}
SetPixelFormat(DeviceContext, PixelFormat, &pfd);
You can't do SetPixelFormat() twice for the same window - this is described in WinAPI documentation and elaborated in every article describing usage of wglChoosePixelFormatARB/wglCreateContextAttribsARB on Windows platform that I've seen:
Once a window's pixel format is set, it cannot be changed.
The only way is creating a temporary OpenGL context on temporary window and then making an OpenGL context for a final window.
Add verbose checks to your code to see where it fails - don't ignore NULL checks and BOOL results of WinAPI functions.

Why am I getting a black screen with this opengl application?

I must be missing something really simple here, I've been staring at my code for the last hour and just can't see it. The code should just create a texture with random pure color or pure black pixels, then draw it to the screen. Right now though it's just producing a black screen...
My guess is it has something to with my vertex or uv positions.
#include <time.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <GL/glew.h>
#include <GLFW/glfw3.h>
const char TITLE[] = "GL TEST";
const int WIDTH = 800;
const int HEIGHT = 600;
const char BASIC_VERT_SHADER[] =
"#version 330\n"
"in vec2 vs_position;"
"in vec2 vs_uvCoord;"
"out vec2 fs_uvCoord;"
"void main()"
"{"
"fs_uvCoord = vs_uvCoord;"
"gl_Position = vec4(vs_position, 1.f, 1.f);"
"}";
const char BASIC_FRAG_SHADER[] =
"#version 330\n"
"uniform sampler2D texture;"
"in vec2 fs_uvCoord;"
"out vec4 frag_color;"
"void main()"
"{"
"frag_color = texture2D(texture, fs_uvCoord);"
"}";
const float TEXTURE_UV[] =
{
0.f, 0.f,
1.f, 0.f,
1.f, 1.f,
0.f, 1.f
};
const float VERT_POS[] =
{
-1.f, -1.f,
1.f, -1.f,
1.f, 1.f,
-1.f, 1.f
};
GLFWwindow* setupGraphics()
{
GLFWwindow* window;
if ( !glfwInit() )
{
fputs("failed to initialize glfw!\n", stderr);
exit(1);
}
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); // opengl 3.x
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); // opengl 3.3
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); // needed for osx
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
window = glfwCreateWindow(WIDTH, HEIGHT, TITLE, NULL, NULL);
if (!window)
{
fputs("failed to create window!\n", stderr);
exit(1);
}
glfwMakeContextCurrent(window);
glewExperimental = true;
if ( glewInit() != GLEW_OK )
{
fputs("failed to initialize glew!\n", stderr);
exit(1);
}
if ( !GLEW_VERSION_3_3 )
{
fputs("opengl 3.3 support is required!\n", stderr);
exit(1);
}
return window;
};
unsigned int compileShader(const char* shaderSource, GLenum type)
{
unsigned int shaderID = glCreateShader(type);
glShaderSource(shaderID, 1, &shaderSource , NULL);
glCompileShader(shaderID);
int status;
glGetShaderiv(shaderID, GL_COMPILE_STATUS, &status);
if ( status == GL_FALSE )
{
int errorLength;
glGetShaderiv(shaderID, GL_INFO_LOG_LENGTH, &errorLength);
char errorString[errorLength+1];
glGetShaderInfoLog(shaderID, errorLength, NULL, errorString);
fprintf(stderr, "glsl compile error: %s", errorString);
exit(1);
}
return shaderID;
}
unsigned int compileShaderProgram(const char* vsSource, const char* fsSource)
{
unsigned int programID = glCreateProgram();
unsigned int vsID = compileShader(vsSource, GL_VERTEX_SHADER);
unsigned int fsID = compileShader(fsSource, GL_FRAGMENT_SHADER);
glAttachShader(programID, vsID);
glAttachShader(programID, fsID);
glLinkProgram(programID);
int status;
glGetProgramiv(programID, GL_LINK_STATUS, &status);
if ( status == GL_FALSE )
{
int errorLength;
glGetProgramiv(programID, GL_INFO_LOG_LENGTH, &errorLength);
char errorString[errorLength+1];
glGetProgramInfoLog(programID, errorLength, NULL, errorString);
fprintf(stderr, "glsl linking error: %s", errorString);
exit(1);
}
glDetachShader(programID, vsID);
glDetachShader(programID, fsID);
glDeleteShader(vsID);
glDeleteShader(fsID);
return programID;
}
unsigned int randomTexture(int width, int height)
{
unsigned int textureID;
int size = width * height;
unsigned char* buffer = malloc( size * sizeof(unsigned char) );
for (int i = 0; i < size; i++)
{
if ( rand() & 1 )
{
buffer[i] = 0x00;
}
else
{
buffer[i] = 0xFF;
}
}
glGenTextures(1, &textureID);
glBindTexture(GL_TEXTURE_2D, textureID);
glTexImage2D(
GL_TEXTURE_2D, 0, GL_R8,
width, height, 0, GL_RED,
GL_UNSIGNED_BYTE, buffer
);
free(buffer);
return textureID;
}
int main()
{
GLenum glError;
GLFWwindow* window;
unsigned int shader;
unsigned int texture;
unsigned int vertPosBuffer;
unsigned int uvCoordBuffer;
unsigned int vertexArray;
int textureUniform;
int vertPosAttribute;
int uvCoordAttribute;
srand( time(NULL) );
window = setupGraphics();
shader = compileShaderProgram(BASIC_VERT_SHADER, BASIC_FRAG_SHADER);
textureUniform = glGetUniformLocation(shader, "texture");
vertPosAttribute = glGetAttribLocation(shader, "vs_position");
uvCoordAttribute = glGetAttribLocation(shader, "vs_uvCoord");
texture = randomTexture(WIDTH, HEIGHT);
glGenVertexArrays(1, &vertexArray);
glBindVertexArray(vertexArray);
glGenBuffers(1, &vertPosBuffer);
glBindBuffer(GL_ARRAY_BUFFER, vertPosBuffer);
glBufferData(GL_ARRAY_BUFFER, 8*sizeof(float), VERT_POS, GL_STATIC_DRAW);
glVertexAttribPointer(vertPosAttribute, 2, GL_FLOAT, GL_FALSE, 0, 0);
glGenBuffers(1, &uvCoordBuffer);
glBindBuffer(GL_ARRAY_BUFFER, uvCoordBuffer);
glBufferData(GL_ARRAY_BUFFER, 8*sizeof(float), TEXTURE_UV, GL_STATIC_DRAW);
glVertexAttribPointer(uvCoordAttribute, 2, GL_FLOAT, GL_FALSE, 0, 0);
while ( !glfwWindowShouldClose(window) )
{
glClear( GL_COLOR_BUFFER_BIT );
glClearColor(0.f, 0.f, 0.f, 1.f);
glUseProgram(shader);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texture);
glUniform1i(textureUniform, 0);
glBindVertexArray(vertexArray);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
glfwSwapBuffers(window);
glfwPollEvents();
while((glError = glGetError()) != GL_NO_ERROR)
{
fprintf(stderr, "gl error: %d\n", glError);
exit(1);
}
}
glDeleteVertexArrays(1, &vertexArray);
glDeleteBuffers(1, &vertPosBuffer);
glDeleteBuffers(1, &uvCoordBuffer);
glDeleteTextures(1, &texture);
glDeleteProgram(shader);
return 0;
}
The major issue is that you have forgotten to enable the generic vertex attribute arrays. See glEnableVertexAttribArray
glGenBuffers(1, &vertPosBuffer);
glBindBuffer(GL_ARRAY_BUFFER, vertPosBuffer);
glBufferData(GL_ARRAY_BUFFER, 8*sizeof(float), VERT_POS, GL_STATIC_DRAW);
glVertexAttribPointer(vertPosAttribute, 2, GL_FLOAT, GL_FALSE, 0, 0);
glEnableVertexAttribArray( vertPosAttribute ); // <-----------------
glGenBuffers(1, &uvCoordBuffer);
glBindBuffer(GL_ARRAY_BUFFER, uvCoordBuffer);
glBufferData(GL_ARRAY_BUFFER, 8*sizeof(float), TEXTURE_UV, GL_STATIC_DRAW);
glVertexAttribPointer(uvCoordAttribute, 2, GL_FLOAT, GL_FALSE, 0, 0);
glEnableVertexAttribArray( uvCoordAttribute ); // <-----------------
As mentioned in the comments to your question you should set the textue minifying filter to GL_LINEAR or GL_NEAREST, since you do not use mipmaps:
glGenTextures(1, &textureID);
glBindTexture(GL_TEXTURE_2D, textureID);
glTexImage2D(
GL_TEXTURE_2D, 0, GL_R8,
width, height, 0, GL_RED,
GL_UNSIGNED_BYTE, buffer.data()
);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
A triangle stripe which creates a quad is setup like this:
const float TEXTURE_UV[] =
{
0.f, 0.f,
1.f, 0.f,
0.f, 1.f,
1.f, 1.f
};
const float VERT_POS[] =
{
-1.f, -1.f,
1.f, -1.f,
-1.f, 1.f,
1.f, 1.f
};
But you can draw a trangle fan instead:
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);

glTexImage2d and GL_R8UI fails on some GPUs

I'm trying to use GL_R8UI to pass unsigned, unnormalized data to a shader, but have found that on at least one GPU it doesn't work.
ie: this works:
glTexImage2D(GL_TEXTURE_2D, 0, GL_R8, 32, 32, 0, GL_RED, GL_UNSIGNED_BYTE, pData);
but this doesn't:
glTexImage2D(GL_TEXTURE_2D, 0, GL_R8UI, 32, 32, 0, GL_RED_INTEGER, GL_UNSIGNED_BYTE, pData);
I'm also changing the shader to use sampler2D vs usampler2D and updating the math in the shader appropriately, but finding it works on AMD/Radeon cards but fails on Intel and NVidia cards - the usampler2D always seems to return zero.
I've put together a minimal sample program here. The #define NORMALIZED switches between the two approaches.
So... my main question is: is this simply a driver problem or is there something else wrong in my code that's causing this?
To ask this question another way... what else needs to be changed to switch from GL_R8 normalized data to GL_R8UI unnormalized data, besides:
changing the call to glTextImage2D
changing from sampler2D to usampler2D in the shader
changing the shader to work with uint's instead of floats
changing the math in the shader to deal with normalized vs unnormalized data.
I've now logged an bug report with Intel: https://software.intel.com/en-us/forums/graphics-driver-bug-reporting/topic/748843
Since it was asked for here's the full example program source:
// ShaderTest.cpp : Defines the entry point for the application.
//
#include "stdafx.h"
#include "ShaderTest.h"
#include <stdlib.h>
#include <stdint.h>
#include <GL/gl3w.h>
#pragma comment(lib, "opengl32.lib")
#define NORMALIZED
const char* pszVertexShader = R"***(
#version 150
uniform mat4 transform;
attribute vec3 position;
varying vec2 vPosition;
void main()
{
gl_Position = transform * vec4(position,1.);
vPosition = position.xy;
}
)***";
#ifdef NORMALIZED
const char* pszFragmentShader = R"***(
#version 150
uniform sampler2D TextureData;
varying vec2 vPosition;
void main()
{
float red = texelFetch(TextureData, ivec2(0, 0), 0).r;
gl_FragColor = vec4(red , 0, 0, 1);
}
)***";
#else
const char* pszFragmentShader = R"***(
#version 150
uniform usampler2D TextureData;
varying vec2 vPosition;
void main()
{
// Original post had this wrong
// float red = float(texelFetch(TextureData, ivec2(0, 0), 0)).r/255.0;
// Fixed version - still fails on Intel GPUs though
float red = float(texelFetch(TextureData, ivec2(0, 0), 0).r)/255.0;
gl_FragColor = vec4(red, 0, 0, 1);
}
)***";
#endif
int CompileShader(GLenum type, const char* pszSource)
{
int iShader = glCreateShader(type);
glShaderSource(iShader, 1, &pszSource, NULL);
glCompileShader(iShader);
// Dump log
int length;
glGetShaderiv(iShader, GL_INFO_LOG_LENGTH, &length);
if (length != 0)
{
char* pszLog = (char*)_alloca((sizeof(char) + 10) * length);
GLsizei len;
glGetShaderInfoLog(iShader, length, &len, pszLog);
OutputDebugStringA(pszLog);
}
// Check for error
int status;
glGetShaderiv(iShader, GL_COMPILE_STATUS, &status);
if (status == 0)
{
// Clean up after failuer
glDeleteShader(iShader);
return 0;
}
// Success
return iShader;
}
// Globals
HINSTANCE hInst;
HGLRC g_hRC;
GLint g_iVertexShader = 0;
GLint g_iFragmentShader = 0;
GLint g_iShaderProgram = 0;
GLuint g_iTexture = 0;
GLuint g_iVertexBuffer = 0;
#define glCheck() assert(glGetError() == 0)
struct VERTEX
{
float x;
float y;
float z;
};
bool Setup()
{
// Compile shaders
g_iVertexShader = CompileShader(GL_VERTEX_SHADER, pszVertexShader);
g_iFragmentShader = CompileShader(GL_FRAGMENT_SHADER, pszFragmentShader);
// Link program
g_iShaderProgram = glCreateProgram();
glAttachShader(g_iShaderProgram, g_iVertexShader);
glAttachShader(g_iShaderProgram, g_iFragmentShader);
glLinkProgram(g_iShaderProgram);
// Dump log
int length;
glGetProgramiv(g_iShaderProgram, GL_INFO_LOG_LENGTH, &length);
if (length != 0)
{
char* pszLog = (char*)_alloca((sizeof(char) + 10) * length);
GLsizei len;
glGetProgramInfoLog(g_iShaderProgram, length, &len, pszLog);
OutputDebugStringA(pszLog);
}
// Check for error
int status;
glGetProgramiv(g_iShaderProgram, GL_LINK_STATUS, &status);
if (status == 0)
return false;
// Create texture
glGenTextures(1, &g_iTexture);
glBindTexture(GL_TEXTURE_2D, g_iTexture);
uint8_t* pData = (uint8_t*)_alloca(32 * 32 * sizeof(uint8_t));
memset(pData, 128, 32 * 32 * sizeof(uint8_t));
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
#ifdef NORMALIZED
glTexImage2D(GL_TEXTURE_2D, 0, GL_R8, 32, 32, 0, GL_RED, GL_UNSIGNED_BYTE, pData);
#else
glTexImage2D(GL_TEXTURE_2D, 0, GL_R8UI, 32, 32, 0, GL_RED_INTEGER, GL_UNSIGNED_BYTE, pData);
#endif
glBindTexture(GL_TEXTURE_2D, 0);
// Create vertex buffer
glGenBuffers(1, &g_iVertexBuffer);
glBindBuffer(GL_ARRAY_BUFFER, g_iVertexBuffer);
VERTEX v[] = {
{ 10, 10, 0, },
{ 10, 230, 0, },
{ 310, 10, 0, },
{ 310, 230, 0, },
};
glBufferData(GL_ARRAY_BUFFER, sizeof(v), v, GL_STATIC_DRAW);
// Done
return true;
}
void Cleanup()
{
if (g_iVertexBuffer)
glDeleteBuffers(1, &g_iVertexBuffer);
if (g_iTexture)
glDeleteTextures(1, &g_iTexture);
if (g_iShaderProgram)
glDeleteProgram(g_iShaderProgram);
if (g_iVertexShader)
glDeleteShader(g_iVertexShader);
if (g_iFragmentShader)
glDeleteShader(g_iFragmentShader);
}
void Display(RECT* prc)
{
// Setup viewport
glViewport(0, 0, prc->right, prc->bottom);
// Clear background
glClearColor(0, 0, 0.5f, 1);
glClear(GL_COLOR_BUFFER_BIT);
// Setup program
glUseProgram(g_iShaderProgram);
// Bind vertex buffer
glBindBuffer(GL_ARRAY_BUFFER, g_iVertexBuffer);
// Setup vertex buffer
int aPosition = glGetAttribLocation(g_iShaderProgram, "position");
glEnableVertexAttribArray(aPosition);
glVertexAttribPointer(aPosition, 3, GL_FLOAT, false, sizeof(VERTEX), 0);
// Setup texture
glActiveTexture(GL_TEXTURE0 + 0);
glBindTexture(GL_TEXTURE_2D, g_iTexture);
int uTextureData = glGetUniformLocation(g_iShaderProgram, "TextureData");
glUniform1i(uTextureData, 0);
// Setup ortho projection
float left = 0;
float right = 320;
float top = 0;
float bottom = 240;
float fnear = -1;
float ffar = 1;
float proj[] = {
(float)(2.0 / (right - left)), 0.0f, 0.0f, 0.0f,
0.0f, (float)(2.0 / (top - bottom)), 0.0f, 0.0f,
0.0f, 0.0f, (float)(-2.0 / (ffar - fnear)), 0.0f,
(float)(-(right + left) / (right - left)), (float)(-(top + bottom) / (top - bottom)), (float)(-(ffar + fnear) / (ffar - fnear)), 1.0f
};
int uTransform = glGetUniformLocation(g_iShaderProgram, "transform");
glUniformMatrix4fv(uTransform, 1, false, proj);
// Draw
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
glFlush();
}
bool InitOpenGLContext(HWND hWnd)
{
// Setup pixel format
HDC hDC = GetDC(hWnd);
PIXELFORMATDESCRIPTOR pfd;
memset(&pfd, 0, sizeof(pfd));
pfd.nSize = sizeof(pfd);
pfd.nVersion = 1;
pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL;
pfd.iPixelType = PFD_TYPE_RGBA;
pfd.cColorBits = 32;
int pf = ChoosePixelFormat(hDC, &pfd);
if (pf == 0 || !SetPixelFormat(hDC, pf, &pfd))
return false;
DescribePixelFormat(hDC, pf, sizeof(PIXELFORMATDESCRIPTOR), &pfd);
g_hRC = wglCreateContext(hDC);
if (!g_hRC)
return false;
// Init gl3w
wglMakeCurrent(hDC, g_hRC);
int err = gl3wInit();
if (err)
{
wglMakeCurrent(NULL, NULL);
wglDeleteContext(g_hRC);
g_hRC = NULL;
return false;
}
// Setup
if (!Setup())
{
assert(false);
Cleanup();
wglMakeCurrent(NULL, NULL);
wglDeleteContext(g_hRC);
g_hRC = NULL;
return false;
}
ReleaseDC(hWnd, hDC);
return true;
}
void CleanupOpenGLContext(HWND hWnd)
{
HDC hDC = GetDC(hWnd);
wglMakeCurrent(hDC, g_hRC);
Cleanup();
wglMakeCurrent(NULL, NULL);
ReleaseDC(hWnd, hDC);
wglDeleteContext(g_hRC);
}
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_PAINT:
{
PAINTSTRUCT ps;
RECT rc;
GetClientRect(hWnd, &rc);
HDC hdc = BeginPaint(hWnd, &ps);
wglMakeCurrent(hdc, g_hRC);
Display(&rc);
wglMakeCurrent(NULL, NULL);
EndPaint(hWnd, &ps);
}
break;
case WM_CLOSE:
PostQuitMessage(0);
break;
case WM_ERASEBKGND:
return 0;
}
return DefWindowProc(hWnd, message, wParam, lParam);
}
int APIENTRY wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, int nCmdShow)
{
// Register Class
WNDCLASSEXW wcex;
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = WndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInstance;
wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_SHADERTEST));
wcex.hCursor = LoadCursor(nullptr, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
wcex.lpszMenuName = NULL;
wcex.lpszClassName = L"ShaderTest";
wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));
RegisterClassExW(&wcex);
// Create Window
HWND hWnd = CreateWindowW(L"ShaderTest", L"ShaderTest", WS_OVERLAPPEDWINDOW,
50, 50, 100, 100, nullptr, nullptr, hInstance, nullptr);
if (!hWnd)
return 7;
RECT rc;
rc.left = 0;
rc.top = 0;
rc.right = 320;
rc.bottom = 240;
AdjustWindowRect(&rc, GetWindowLong(hWnd, GWL_STYLE), FALSE);
SetWindowPos(hWnd, NULL, 0, 0, rc.right - rc.left, rc.bottom - rc.top, SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE);
if (!InitOpenGLContext(hWnd))
{
DestroyWindow(hWnd);
return 7;
}
// Show window
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
// Main message loop:
MSG msg;
while (GetMessage(&msg, nullptr, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
CleanupOpenGLContext(hWnd);
DestroyWindow(hWnd);
return (int) msg.wParam;
}
Integer textures need to have nearest filtering (not linear or mipmap):
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);

OpenGL 4.x textures not working

I'm new here.
I'm having trouble with textures in OpenGL 4.4, I just get a black screen.
Here's my code (I suspect everything before glGenBuffers() is unimportant but you never know):
#include <stdio.h>
#include <stdlib.h>
#include <inttypes.h>
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include "eternity.h"
#include "error.h"
#define STB_IMAGE_IMPLEMENTATION
#define STBI_FAILURE_USERMSG
#include "stb_image.h"
int main(int argc, char *argv[])
{
if (argc < 2)
DIE("%s\n", "not enough arguments");
GLuint width = 0, height = 0, bpp = 0;
unsigned char *image_raw;
if ((image_raw = stbi_load("image.jpg", &width, &height, &bpp, 0)) == NULL)
DIE("stbi error: %s\n", stbi_failure_reason());
uint8_t rv;
if (rv = initialize_glfw())
DIE("%s%" PRIu8 "\n", "initialize_glfw() failed with code ", rv);
glfwSetErrorCallback(glfw_error_callback);
glfw *glfw = malloc(sizeof(glfw));
if (!(glfw->window = glfwCreateWindow(
width,
height,
"Eternity",
NULL,
NULL)))
{
glfwTerminate();
DIE("%s\n", "glfwCreateWindow failed");
}
glfwMakeContextCurrent(glfw->window);
glfwSetKeyCallback(glfw->window, glfw_key_callback);
glewExperimental = GL_TRUE;
if (glewInit() != GLEW_OK)
{
eternity_cleanup(glfw);
DIE("%s\n", "glewInit() failed");
}
printf("OpenGL %s\n", glGetString(GL_VERSION));
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LESS);
GLshort vertices[] = {
-1, 1, 0,
1, 1, 0,
-1, -1, 0,
1, -1, 0
};
GLushort texcoords[] = {
0, 0,
1, 0,
0, 1,
1, 1
};
gl gl = {0}; // This is just a struct
glGenBuffers(1, &(gl.points_vbo));
glBindBuffer(GL_ARRAY_BUFFER, gl.points_vbo);
glBufferData(GL_ARRAY_BUFFER, 12 * sizeof(GLshort), vertices, GL_STATIC_DRAW);
glGenBuffers(1, &(gl.texcoords_vbo));
glBindBuffer(GL_ARRAY_BUFFER, gl.texcoords_vbo);
glBufferData(GL_ARRAY_BUFFER, 8 * sizeof(GLushort), texcoords, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, gl.points_vbo); // EDIT: I added this line
glGenVertexArrays(1, &(gl.vao));
glBindVertexArray(gl.vao);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_SHORT, GL_FALSE, 0, NULL);
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 3, GL_UNSIGNED_SHORT, GL_FALSE, 0, NULL);
setup_shaders(&gl);
GLenum format;
switch (bpp * 8)
{
case 24:
format = GL_RGB;
break;
case 32:
format = GL_RGBA;
break;
}
GLuint texture_id = 0;
glGenTextures(1, &texture_id);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texture_id);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, (GLint)format, width, height, 0, format, GL_UNSIGNED_BYTE, image_raw);
stbi_image_free(image_raw);
glBindTexture(GL_TEXTURE_2D, texture_id);
check_error();
while (!glfwWindowShouldClose(glfw->window))
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glUseProgram(gl.shader_program);
glBindVertexArray(gl.vao);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
glfwSwapBuffers(glfw->window);
glfwPollEvents();
}
glDeleteTextures(1, &texture_id);
eternity_cleanup(glfw);
}
void setup_shaders(gl *gl)
{
const GLchar *vs_source =
"#version 440\n"
"layout(location = 0) in vec3 vp;"
"layout(location = 1) in vec2 vt;"
"out vec2 texcoord;"
"void main() { gl_Position = vec4(vp, 1.0);"
"texcoord = vt; }",
*fs_source =
"#version 440\n"
"out vec4 frag_color;"
"in vec2 texcoord;"
"uniform sampler2D texture;"
"void main() { frag_color = texture2D(texture, texcoord); }";
GLuint vs = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vs, 1, &vs_source, NULL);
glCompileShader(vs);
GLuint fs = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fs, 1, &fs_source, NULL);
glCompileShader(fs);
gl->shader_program = glCreateProgram();
glAttachShader(gl->shader_program, fs);
glAttachShader(gl->shader_program, vs);
glLinkProgram(gl->shader_program);
glDeleteShader(vs);
glDeleteShader(fs);
}
uint8_t initialize_glfw(void)
{
int major = 0, minor = 0, rev = 0;
glfwGetVersion(&major, &minor, &rev);
printf("GLFW %d.%d rev %d\n", major, minor, rev);
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, major);
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, minor);
glfwWindowHint(GLFW_CONTEXT_REVISION, rev);
glfwWindowHint(GLFW_SAMPLES, 8);
if (!glfwInit())
return 1;
return 0;
}
void glfw_error_callback(int error, const char *description)
{
printf("glfw error callback triggered\n");
fprintf(stderr, "%d: %s\n", error, description);
}
void glfw_key_callback(GLFWwindow *window, int key, int scancode, int action, int mods)
{
if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS)
glfwSetWindowShouldClose(window, GL_TRUE);
}
void eternity_cleanup(glfw* glfw)
{
glfwDestroyWindow(glfw->window);
free(glfw);
glfwTerminate();
}
I'm not sure if I've forgotten to do something here or if I'm doing something incorrectly, I have tried very hard to fix this but the black screen persists.
I feel like the problem is in my shaders (hardcoded in setup_shaders()), or maybe around glTexImage2D()?
edit:
I found that if I call glBindBuffer again right before glGenVertexArrays, then I get a light blue screen, and the specific image that I am loading is predominantly this exact shade of blue, so I believe I am sampling a single pixel.
I have updated the source code with a comment where I added a line.
My problem is now that I am sampling only one pixel.

Resources