nvidia opengl framebuffer object forces vsync on - c

Basically I implemented gamma correction into a q3 based game to get rid of the annoying SetDeviceGammaRamp.
I'm using GL_EXT_framebuffer_object for a post process vertex shader.
It works pretty fine except that it has some weird behavior on nvidia gpus:
It forces vsync to be enabled except when it is explicitly disabled in the control panel. If I use the standard control panel's settings and the framebuffer is enabled vsync is forced, but if I remove the framebuffer it goes back to normal behavior.
wglSwapIntervalEXT does nothing
I tested it on an nvidia mobile GPU, someone could reproduce it on a desktop GPU
I also tested an integrated intel gpu and two different amd gpu's and all of them didn't have the issue.
initialization: (unrelevant i guess)
// ouned: gamma correction
const char *g_GammaVertexShaderARB = {
"void main(void)" "\n"
"{" "\n"
"gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;" "\n"
"gl_TexCoord[0] = gl_MultiTexCoord0;" "\n"
"}"
};
const char *g_GammaFragmentShaderARB = {
"uniform sampler2D sceneBuffer;" "\n"
"uniform float gamma;" "\n"
"\n"
"void main(void)" "\n"
"{" "\n"
"vec2 uv = gl_TexCoord[0].xy;" "\n"
"vec3 color = texture2D(sceneBuffer, uv).rgb;" "\n"
"if (uv.x<0.50)" "\n"
"gl_FragColor.rgb = pow(color, vec3(1.0 / 1.5));" "\n"
"else" "\n"
"gl_FragColor.rgb = color;" "\n"
"gl_FragColor.a = 1.0;" "\n"
"}"
};
tr.m_hVShader = qglCreateShaderObjectARB(GL_VERTEX_SHADER_ARB);
qglShaderSourceARB(tr.m_hVShader, 1, (const GLcharARB **)&g_GammaVertexShaderARB, NULL);
qglCompileShaderARB(tr.m_hVShader);
if (qglGetError() != GL_NO_ERROR) {
ri.Printf(PRINT_ERROR, "Failed compiling gamma vertrex shader\n");
}
tr.m_hFShader = qglCreateShaderObjectARB(GL_FRAGMENT_SHADER_ARB);
qglShaderSourceARB(tr.m_hFShader, 1, (const GLcharARB **)&g_GammaFragmentShaderARB, NULL);
qglCompileShaderARB(tr.m_hFShader);
if (qglGetError() != GL_NO_ERROR) {
ri.Printf(PRINT_ERROR, "Failed compiling gamma fragment shader\n");
}
tr.gammaProgram = qglCreateProgramObjectARB();
qglAttachObjectARB(tr.gammaProgram, tr.m_hVShader);
qglAttachObjectARB(tr.gammaProgram, tr.m_hFShader);
qglLinkProgramARB(tr.gammaProgram);
if (qglGetError() != GL_NO_ERROR) {
ri.Printf(PRINT_ERROR, "Failed linking shaders\n");
}
qglUseProgramObjectARB(tr.gammaProgram);
tr.gammaUniformLoc = qglGetUniformLocationARB(tr.gammaProgram, "gamma");
tr.gammaSceneBufferLoc = qglGetUniformLocationARB(tr.gammaProgram, "sceneBuffer");
qglValidateProgramARB(tr.gammaProgram);
qglUseProgramObjectARB(0);
// framebuffer object
tr.gammaFramebuffer = 0;
qglGenFramebuffersEXT(1, &tr.gammaFramebuffer);
qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, tr.gammaFramebuffer);
// depth buffer
tr.gammaRenderDepthBuffer = 0;
qglGenRenderbuffersEXT(1, &tr.gammaRenderDepthBuffer);
qglBindRenderbufferEXT(GL_RENDERBUFFER_EXT, tr.gammaRenderDepthBuffer);
qglRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT, glConfig.vidWidth, glConfig.vidHeight);
tr.gammaRenderTarget = 0;
qglGenTextures(1, &tr.gammaRenderTarget);
qglBindTexture(GL_TEXTURE_2D, tr.gammaRenderTarget);
qglTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, glConfig.vidWidth, glConfig.vidHeight, 0, GL_RGB, GL_UNSIGNED_BYTE, 0);
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
qglGenerateMipmapEXT(GL_TEXTURE_2D);
qglBindTexture(GL_TEXTURE_2D, 0);
qglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, tr.gammaRenderTarget, 0);
qglFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, tr.gammaRenderDepthBuffer);
qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
On the beginning of a frame:
qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, tr.gammaFramebuffer);
qglBindRenderbufferEXT(GL_RENDERBUFFER_EXT, tr.gammaRenderDepthBuffer);
qglDrawBuffer(GL_COLOR_ATTACHMENT0_EXT);
on the end of a frame:
qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
qglBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0);
if (!backEnd.projection2D) {
qglViewport(0, 0, glConfig.vidWidth, glConfig.vidHeight);
qglScissor(0, 0, glConfig.vidWidth, glConfig.vidHeight);
qglMatrixMode(GL_PROJECTION);
qglLoadIdentity();
qglOrtho(0, glConfig.vidWidth, glConfig.vidHeight, 0, 0, 1);
qglMatrixMode(GL_MODELVIEW);
qglLoadIdentity();
GL_State(GLS_DEPTHTEST_DISABLE);
}
qglUseProgramObjectARB(tr.gammaProgram);
qglEnable(GL_TEXTURE_2D);
qglUniform1iARB(tr.gammaSceneBufferLoc, 0);
qglColor3f(tr.identityLight, tr.identityLight, tr.identityLight);
qglActiveTextureARB(GL_TEXTURE0);
qglBindTexture(GL_TEXTURE_2D, tr.gammaRenderTarget);
qglBegin(GL_QUADS);
qglTexCoord2f(0, 1);
qglVertex2f(0, 0);
qglTexCoord2f(1, 1);
qglVertex2f(glConfig.vidWidth, 0);
qglTexCoord2f(1, 0);
qglVertex2f(glConfig.vidWidth, glConfig.vidHeight);
qglTexCoord2f(0, 0);
qglVertex2f(0, glConfig.vidHeight);
qglEnd();
qglUseProgramObjectARB(0);
So, what else can cause vsync to be enabled?

Related

Texture doesn't get updated after applying a compute shader

I'm trying to apply a compute shader to a texture to update its values. I know it's not a very good question to just state something doesn't work, but I did spend a lot of hours trying to get this work.
The shader program compiles well. Changing the glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT); line to glMemoryBarrier(GL_ALL_BARRIER_BITS); glFinish(); doesn't make a difference.
Below is a minimal program to show the issue. SDL is merely for creating an invisible window for the GL context. The program is expected fill the texture with 0.5s and print them, but only 0s are printed..
#define SDL_MAIN_HANDLED
#include <stdio.h>
#include <assert.h>
#include <GL/glew.h>
#include <SDL2/SDL.h>
#define WIDTH 512
#define HEIGHT WIDTH
static const char *SHADER =
"#version 430\n" // "#version 310 es\n"
"layout (local_size_x = 1, local_size_y = 1) in;\n"
"layout (rgba32f, binding = 0) uniform image2D image;\n"
"void main() {\n"
"imageStore(image, ivec2(gl_GlobalInvocationID.xy), vec4(0.5f));\n"
"}\n";
int main() {
SDL_SetMainReady();
assert(!SDL_Init(SDL_INIT_VIDEO));
SDL_Window *window = SDL_CreateWindow("", SDL_WINDOWPOS_UNDEFINED,
SDL_WINDOWPOS_UNDEFINED, 0, 0, SDL_WINDOW_HIDDEN | SDL_WINDOW_OPENGL);
assert(window);
SDL_GLContext gl = SDL_GL_CreateContext(window);
assert(gl);
assert(glewInit() == GLEW_OK);
GLuint tex;
glGenTextures(1, &tex);
glBindTexture(GL_TEXTURE_2D, tex);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, WIDTH, HEIGHT, 0, GL_RGBA,
GL_FLOAT, 0);
glBindImageTexture(0, tex, 0, 0, 0, GL_READ_WRITE, GL_RGBA32F);
GLuint shader = glCreateShader(GL_COMPUTE_SHADER);
glShaderSource(shader, 1, &SHADER, 0);
glCompileShader(shader);
GLuint program = glCreateProgram();
glAttachShader(program, shader);
glLinkProgram(program);
glUseProgram(program);
glDispatchCompute(WIDTH, HEIGHT, 1);
glMemoryBarrier(GL_ALL_BARRIER_BITS);
glFinish();
static float a[WIDTH * HEIGHT * 4];
glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_FLOAT, a);
puts((const char *)glGetString(GL_VERSION));
for (int i = 0; i < 16; ++i) printf("%f\n", a[i]);
return 0;
}
If you do not generate mipmaps (with glGenerateMipmap), you have to change the GL_TEXTURE_MIN_FILTER. Since the default filter is GL_NEAREST_MIPMAP_LINEAR, the texture would be "Mipmap Incomplete" if you do not change the minimize function to GL_NEAREST or GL_LINEAR.
glBindTexture(GL_TEXTURE_2D, tex);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, WIDTH, HEIGHT, 0, GL_RGBA, GL_FLOAT, 0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glBindImageTexture(0, tex, 0, 0, 0, GL_READ_WRITE, GL_RGBA32F);

OpenGL SL barrel distortion: what's wrong with this SDL2 code

UPDATE
Ok, I read Learn OpenGL book from https://learnopengl.com/ and changed the OP code in order to support OpenGL 3.3 and later. I don't have the time now for writing the complete solution but if someone is interested ask!
OLD OP
I wrote an emulator using SDL2 and what I want is to add a barrel distortion, like an old CRT, to final rectangular video frame texture.
OpenGL SL vertex and fragment shaders come from here.
This is the code, icon.bmp is here:
#include <stdio.h>
#include "SDL.h"
#include "SDL_opengl.h"
static SDL_bool shaders_supported;
static int current_shader = 0;
enum
{
SHADER_1,
SHADER_2,
NUM_SHADERS
};
typedef struct
{
GLhandleARB program;
GLhandleARB vert_shader;
GLhandleARB frag_shader;
const char *vert_source;
const char *frag_source;
} ShaderData;
static ShaderData shaders[NUM_SHADERS] =
{
// SHADER_1
{0, 0, 0,
/* vertex shader */
"varying vec4 v_color;\n"
"varying vec2 v_texCoord;\n"
"\n"
"void main()\n"
"{\n"
" gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;\n"
" v_color = gl_Color;\n"
" v_texCoord = vec2(gl_MultiTexCoord0);\n"
"}",
/* fragment shader */
"varying vec4 v_color;\n"
"varying vec2 v_texCoord;\n"
"uniform sampler2D tex0;\n"
"\n"
"void main()\n"
"{\n"
" gl_FragColor = texture2D(tex0, v_texCoord) * v_color;\n"
"}"
},
// SHADER_2
{0, 0, 0,
/* vertex shader */
"varying vec4 Vertex_UV;\n"
"uniform mat4 gxl3d_ModelViewProjectionMatrix;\n"
"void main()\n"
"{\n"
" gl_Position = gxl3d_ModelViewProjectionMatrix * gl_Vertex;\n"
" Vertex_UV = gl_MultiTexCoord0;\n"
"}",
/* fragment shader */
"uniform sampler2D tex0;\n"
"varying vec4 Vertex_UV;\n"
"const float PI = 3.1415926535;\n"
"uniform float BarrelPower;\n"
"\n"
"vec2 Distort(vec2 p)\n"
"{\n"
" float theta = atan(p.y, p.x);\n"
" float radius = length(p);\n"
" radius = pow(radius, BarrelPower);\n"
" p.x = radius * cos(theta);\n"
" p.y = radius * sin(theta);\n"
" return 0.5 * (p + 1.0);\n"
"}\n"
"\n"
"void main()\n"
"{\n"
" vec2 xy = 2.0 * Vertex_UV.xy - 1.0;\n"
" vec2 uv;\n"
" float d = length(xy);\n"
" if (d < 1.0)\n"
" {\n"
" uv = Distort(xy);\n"
" }\n"
" else\n"
" {\n"
" uv = Vertex_UV.xy;\n"
" }\n"
" vec4 c = texture2D(tex0, uv);\n"
" gl_FragColor = c;\n"
"}"
}
};
static PFNGLATTACHOBJECTARBPROC glAttachObjectARB;
static PFNGLCOMPILESHADERARBPROC glCompileShaderARB;
static PFNGLCREATEPROGRAMOBJECTARBPROC glCreateProgramObjectARB;
static PFNGLCREATESHADEROBJECTARBPROC glCreateShaderObjectARB;
static PFNGLDELETEOBJECTARBPROC glDeleteObjectARB;
static PFNGLGETINFOLOGARBPROC glGetInfoLogARB;
static PFNGLGETOBJECTPARAMETERIVARBPROC glGetObjectParameterivARB;
static PFNGLGETUNIFORMLOCATIONARBPROC glGetUniformLocationARB;
static PFNGLLINKPROGRAMARBPROC glLinkProgramARB;
static PFNGLSHADERSOURCEARBPROC glShaderSourceARB;
static PFNGLUNIFORM1IARBPROC glUniform1iARB;
static PFNGLUSEPROGRAMOBJECTARBPROC glUseProgramObjectARB;
static SDL_bool CompileShader(GLhandleARB shader, const char *source)
{
GLint status = 0;
glShaderSourceARB(shader, 1, &source, NULL);
glCompileShaderARB(shader);
glGetObjectParameterivARB(shader, GL_OBJECT_COMPILE_STATUS_ARB, &status);
if (status == 0)
{
GLint length = 0;
char *info;
glGetObjectParameterivARB(shader, GL_OBJECT_INFO_LOG_LENGTH_ARB, &length);
info = (char *)SDL_malloc(length + 1);
if (!info)
{
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Out of memory!");
}
else
{
glGetInfoLogARB(shader, length, NULL, info);
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Failed to compile shader:\n%s\n%s", source, info);
SDL_free(info);
}
return SDL_FALSE;
}
else
return SDL_TRUE;
}
static SDL_bool LinkProgram(ShaderData *data)
{
GLint status = 0;
glAttachObjectARB(data->program, data->vert_shader);
glAttachObjectARB(data->program, data->frag_shader);
glLinkProgramARB(data->program);
glGetObjectParameterivARB(data->program, GL_OBJECT_LINK_STATUS_ARB, &status);
if (status == 0)
{
GLint length = 0;
char *info;
glGetObjectParameterivARB(data->program, GL_OBJECT_INFO_LOG_LENGTH_ARB, &length);
info = (char *) SDL_malloc(length + 1);
if (!info)
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Out of memory!");
else
{
glGetInfoLogARB(data->program, length, NULL, info);
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Failed to link program:\n%s", info);
SDL_free(info);
}
return SDL_FALSE;
}
else
return SDL_TRUE;
}
static SDL_bool CompileShaderProgram(ShaderData *data)
{
const int num_tmus_bound = 4;
int i;
GLint location;
glGetError();
/* Create one program object to rule them all */
data->program = glCreateProgramObjectARB();
/* Create the vertex shader */
data->vert_shader = glCreateShaderObjectARB(GL_VERTEX_SHADER_ARB);
if (!CompileShader(data->vert_shader, data->vert_source))
return SDL_FALSE;
/* Create the fragment shader */
data->frag_shader = glCreateShaderObjectARB(GL_FRAGMENT_SHADER_ARB);
if (!CompileShader(data->frag_shader, data->frag_source))
return SDL_FALSE;
/* ... and in the darkness bind them */
if (!LinkProgram(data))
return SDL_FALSE;
/* Set up some uniform variables */
glUseProgramObjectARB(data->program);
for (i = 0; i < num_tmus_bound; ++i)
{
char tex_name[5];
SDL_snprintf(tex_name, SDL_arraysize(tex_name), "tex%d", i);
location = glGetUniformLocationARB(data->program, tex_name);
if (location >= 0)
glUniform1iARB(location, i);
}
glUseProgramObjectARB(0);
return (glGetError() == GL_NO_ERROR) ? SDL_TRUE : SDL_FALSE;
}
static void DestroyShaderProgram(ShaderData *data)
{
if (shaders_supported)
{
glDeleteObjectARB(data->vert_shader);
glDeleteObjectARB(data->frag_shader);
glDeleteObjectARB(data->program);
}
}
static SDL_bool InitShaders()
{
int i;
/* Check for shader support */
shaders_supported = SDL_FALSE;
if (SDL_GL_ExtensionSupported("GL_ARB_shader_objects") &&
SDL_GL_ExtensionSupported("GL_ARB_shading_language_100") &&
SDL_GL_ExtensionSupported("GL_ARB_vertex_shader") &&
SDL_GL_ExtensionSupported("GL_ARB_fragment_shader"))
{
glAttachObjectARB = (PFNGLATTACHOBJECTARBPROC) SDL_GL_GetProcAddress("glAttachObjectARB");
glCompileShaderARB = (PFNGLCOMPILESHADERARBPROC) SDL_GL_GetProcAddress("glCompileShaderARB");
glCreateProgramObjectARB = (PFNGLCREATEPROGRAMOBJECTARBPROC) SDL_GL_GetProcAddress("glCreateProgramObjectARB");
glCreateShaderObjectARB = (PFNGLCREATESHADEROBJECTARBPROC) SDL_GL_GetProcAddress("glCreateShaderObjectARB");
glDeleteObjectARB = (PFNGLDELETEOBJECTARBPROC) SDL_GL_GetProcAddress("glDeleteObjectARB");
glGetInfoLogARB = (PFNGLGETINFOLOGARBPROC) SDL_GL_GetProcAddress("glGetInfoLogARB");
glGetObjectParameterivARB = (PFNGLGETOBJECTPARAMETERIVARBPROC) SDL_GL_GetProcAddress("glGetObjectParameterivARB");
glGetUniformLocationARB = (PFNGLGETUNIFORMLOCATIONARBPROC) SDL_GL_GetProcAddress("glGetUniformLocationARB");
glLinkProgramARB = (PFNGLLINKPROGRAMARBPROC) SDL_GL_GetProcAddress("glLinkProgramARB");
glShaderSourceARB = (PFNGLSHADERSOURCEARBPROC) SDL_GL_GetProcAddress("glShaderSourceARB");
glUniform1iARB = (PFNGLUNIFORM1IARBPROC) SDL_GL_GetProcAddress("glUniform1iARB");
glUseProgramObjectARB = (PFNGLUSEPROGRAMOBJECTARBPROC) SDL_GL_GetProcAddress("glUseProgramObjectARB");
if (glAttachObjectARB && glCompileShaderARB && glCreateProgramObjectARB && glCreateShaderObjectARB &&
glDeleteObjectARB && glGetInfoLogARB && glGetObjectParameterivARB && glGetUniformLocationARB &&
glLinkProgramARB && glShaderSourceARB && glUniform1iARB && glUseProgramObjectARB)
shaders_supported = SDL_TRUE;
}
if (!shaders_supported)
return SDL_FALSE;
/* Compile all the shaders */
for (i = 0; i < NUM_SHADERS; ++i)
{
if (!CompileShaderProgram(&shaders[i]))
{
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Unable to compile shader!\n");
return SDL_FALSE;
}
}
/* We're done! */
return SDL_TRUE;
}
static void QuitShaders()
{
int i;
for (i = 0; i < NUM_SHADERS; ++i)
DestroyShaderProgram(&shaders[i]);
}
/* Quick utility function for texture creation */
static int power_of_two(int input)
{
int value = 1;
while (value < input)
value <<= 1;
return value;
}
GLuint
SDL_GL_LoadTexture(SDL_Surface * surface, GLfloat * texcoord)
{
GLuint texture;
int w, h;
SDL_Surface *image;
SDL_Rect area;
SDL_BlendMode saved_mode;
/* Use the surface width and height expanded to powers of 2 */
w = power_of_two(surface->w);
h = power_of_two(surface->h);
texcoord[0] = 0.0f; /* Min X */
texcoord[1] = 0.0f; /* Min Y */
texcoord[2] = (GLfloat) surface->w / w; /* Max X */
texcoord[3] = (GLfloat) surface->h / h; /* Max Y */
image = SDL_CreateRGBSurface(SDL_SWSURFACE, w, h, 32,
#if SDL_BYTEORDER == SDL_LIL_ENDIAN /* OpenGL RGBA masks */
0x000000FF,
0x0000FF00,
0x00FF0000,
0xFF000000
#else
0xFF000000,
0x00FF0000,
0x0000FF00,
0x000000FF
#endif
);
if (image == NULL)
return 1;
/* Save the alpha blending attributes */
SDL_GetSurfaceBlendMode(surface, &saved_mode);
SDL_SetSurfaceBlendMode(surface, SDL_BLENDMODE_NONE);
/* Copy the surface into the GL texture image */
area.x = 0;
area.y = 0;
area.w = surface->w;
area.h = surface->h;
SDL_BlitSurface(surface, &area, image, &area);
/* Restore the alpha blending attributes */
SDL_SetSurfaceBlendMode(surface, saved_mode);
/* Create an OpenGL texture for the image */
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexImage2D(GL_TEXTURE_2D,
0,
GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, image->pixels);
SDL_FreeSurface(image); /* No longer needed */
return texture;
}
/* A general OpenGL initialization function. Sets all of the initial parameters. */
void InitGL(int Width, int Height) /* We call this right after our OpenGL window is created. */
{
GLdouble aspect;
glViewport(0, 0, Width, Height);
glClearColor(0.0f, 0.0f, 0.0f, 0.0f); /* This Will Clear The Background Color To Black */
glClearDepth(1.0); /* Enables Clearing Of The Depth Buffer */
glDepthFunc(GL_LESS); /* The Type Of Depth Test To Do */
glEnable(GL_DEPTH_TEST); /* Enables Depth Testing */
glShadeModel(GL_SMOOTH); /* Enables Smooth Color Shading */
glMatrixMode(GL_PROJECTION);
glLoadIdentity(); /* Reset The Projection Matrix */
aspect = (GLdouble)Width / Height;
glOrtho(-1.0, 1.0, -1.0 / aspect, 1.0 / aspect, 0.0, 1.0);
glMatrixMode(GL_MODELVIEW);
}
/* The main drawing function. */
void DrawGLScene(SDL_Window *window, GLuint texture, GLfloat * texcoord)
{
/* Texture coordinate lookup, to make it simple */
enum
{
MINX,
MINY,
MAXX,
MAXY
};
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); /* Clear The Screen And The Depth Buffer */
glLoadIdentity(); /* Reset The View */
/* Enable blending */
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
/* draw a textured square (quadrilateral) */
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, texture);
glColor3f(0.5f, 0.5f, 0.5f);
if (shaders_supported)
glUseProgramObjectARB(shaders[current_shader].program);
glBegin(GL_QUADS); /* start drawing a polygon (4 sided) */
glTexCoord2f(texcoord[MINX], texcoord[MINY]);
glVertex3f(-1.0f, 1.0f, 0.0f); /* Top Left */
glTexCoord2f(texcoord[MAXX], texcoord[MINY]);
glVertex3f( 1.0f, 1.0f, 0.0f); /* Top Right */
glTexCoord2f(texcoord[MAXX], texcoord[MAXY]);
glVertex3f( 1.0f,-1.0f, 0.0f); /* Bottom Right */
glTexCoord2f(texcoord[MINX], texcoord[MAXY]);
glVertex3f(-1.0f,-1.0f, 0.0f); /* Bottom Left */
glEnd(); /* done with the polygon */
if (shaders_supported)
glUseProgramObjectARB(0);
glDisable(GL_TEXTURE_2D);
/* swap buffers to display, since we're double buffered. */
SDL_GL_SwapWindow(window);
}
int main(int argc, char **argv)
{
int done;
SDL_Window *window;
SDL_Surface *surface;
GLuint texture;
GLfloat texcoords[4];
/* Enable standard application logging */
SDL_LogSetPriority(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO);
/* Initialize SDL for video output */
if ( SDL_Init(SDL_INIT_VIDEO) < 0 )
{
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Unable to initialize SDL: %s\n", SDL_GetError());
exit(1);
}
/* Create a 500x500 OpenGL screen */
window = SDL_CreateWindow( "Shader Demo", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 500, 500, SDL_WINDOW_OPENGL );
if ( !window )
{
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Unable to create OpenGL window: %s\n", SDL_GetError());
SDL_Quit();
exit(2);
}
if ( !SDL_GL_CreateContext(window))
{
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Unable to create OpenGL context: %s\n", SDL_GetError());
SDL_Quit();
exit(3);
}
printf("Vendor graphic card: %s\n", glGetString(GL_VENDOR));
printf("Renderer: %s\n", glGetString(GL_RENDERER));
printf("Version GL: %s\n", glGetString(GL_VERSION));
printf("Version GLSL: %s\n", glGetString(GL_SHADING_LANGUAGE_VERSION));
surface = SDL_LoadBMP("icon.bmp");
if ( ! surface )
{
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Unable to load icon.bmp: %s\n", SDL_GetError());
SDL_Quit();
exit(4);
}
texture = SDL_GL_LoadTexture(surface, texcoords);
SDL_FreeSurface(surface);
/* Loop, drawing and checking events */
InitGL(500, 500);
if (InitShaders())
SDL_Log("Shaders supported, press SPACE to cycle them.\n");
else
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Shaders not supported!\n");
done = 0;
while ( ! done )
{
DrawGLScene(window, texture, texcoords);
/* This could go in a separate function */
{ SDL_Event event;
while ( SDL_PollEvent(&event) )
{
if ( event.type == SDL_QUIT )
done = 1;
if ( event.type == SDL_KEYDOWN )
{
if ( event.key.keysym.sym == SDLK_SPACE )
current_shader = (current_shader + 1) % NUM_SHADERS;
if ( event.key.keysym.sym == SDLK_ESCAPE )
done = 1;
}
}
}
}
QuitShaders();
SDL_Quit();
return 0;
}
As you can see when you press SPACE on keyboard the second shader shows a black window. I tried many barrel/fish eye shaders from internet but I always got the same behaviour, so something is wrong in this code.
I used to develop with SDL2 so I know only the theory behind OpenGL SL and I don't want to learn all OpenGL.
Really appreciate any suggestion.
So the source you've used is not using modern OpenGL as you've noted. I've taken it as an example and nabbed some of your code to get a basic version working with modern OpenGL which I believe has the effect you're looking for. Note that I've used GLEW to write my version so I can get access to all the OpenGL functions.
Here is what happens when you press the spacebar in my version. I have the BarrelPower set at 2 as a constant in my shader, but you can play around with that value to inspect the results. You could also quite easily pass it in as an attribute for better configurability.
Below is my source code which I have commented up to explain the changes. I figure that's better than listing them here since you can take a local copy and study it. Between this and LearnOpenGL.com it should be enough to get you up and running.
Let me know if this helps!
#include <stdio.h>
#include <stdbool.h>
#include <GL/glew.h>
#include <SDL.h>
#include <SDL_opengl.h>
#define WINDOW_WIDTH 640
#define WINDOW_HEIGHT 480
#define NUM_SHADERS 2
// Some globals since this is an example
SDL_Window* window = NULL;
SDL_GLContext glContext;
// Vertices (and texture coords) and indices
// See "SetupDrawing" function for their initialisation
float vertices[20];
int indices[6];
// Handles for out VBO and IBO
int vbo = -1;
int ibo = -1;
// Existing shader structure (unchanged)
typedef struct
{
GLhandleARB program;
GLhandleARB vert_shader;
GLhandleARB frag_shader;
const char* vert_source;
const char* frag_source;
} ShaderData;
// Array of shaders - see comments for updates
static ShaderData shaders[NUM_SHADERS] =
{
// SHADER_1
{0, 0, 0,
/* vertex shader - In our basic vertex shader you can see we take
* position and textureCoord attributes. These are setup from our
* global vertices array later in the code. You can also see that
* we are passing out a textureCoord value which is picked up by
* the fragment shader later on in the pipeline
*/
"#version 330\n"
"attribute vec3 position;\n"
"attribute vec2 texCoord;\n"
"out vec2 textureCoord;\n"
"\n"
"void main()\n"
"{\n"
" gl_Position = vec4(position, 1.0);\n"
" textureCoord = texCoord;\n"
"}",
/* fragment shader - Our fragment shader is very basic. It gets texture
coords passed through our vertex shader and a texture. We then use the
glsl texture function to perform our texturing. When you initially run
the app, this is the fragment shader that will be in use
*/
"#version 330\n"
"in vec2 textureCoord;\n"
"uniform sampler2D theTexture;\n"
"void main()\n"
"{\n"
" gl_FragColor = texture(theTexture, textureCoord);\n"
"}"
},
// SHADER_2
{0, 0, 0,
/* vertex shader - Our vertex shader remains unchanged for the second program.
The barrel distortion effect is being applied in the fragment shader only
*/
"#version 330\n"
"attribute vec3 position;\n"
"attribute vec2 texCoord;\n"
"out vec2 textureCoord;\n"
"\n"
"void main()\n"
"{\n"
" gl_Position = vec4(position, 1.0);\n"
" textureCoord = texCoord;\n"
"}",
/* fragment shader - Here is the barrel distortion fragment shader. Not
too much has changed here. The updates are simply to the expected inputs
which are the same as our basic fragment shader. Barrel power has been
made constant for simplicity. You can increase and decrease this value to
observe the effects. In the main the code is essentially the same, I've
just changed the Vertex_UV.xy to textureCoord since that's what would've
been in the Vertex_UV.x and .y variables in the old version. */
"#version 330\n"
"in vec2 textureCoord;\n"
"uniform sampler2D theTexture;\n"
"const float PI = 3.1415926535;\n"
"const float BarrelPower = 2.0;\n"
"\n"
"vec2 Distort(vec2 p)\n"
"{\n"
" float theta = atan(p.y, p.x);\n"
" float radius = length(p);\n"
" radius = pow(radius, BarrelPower);\n"
" p.x = radius * cos(theta);\n"
" p.y = radius * sin(theta);\n"
" return 0.5 * (p + 1.0);\n"
"}\n"
"\n"
"void main()\n"
"{\n"
" vec2 xy = 2.0 * textureCoord - 1.0;\n"
" vec2 uv;\n"
" float d = length(xy);\n"
" if (d < 1.0)\n"
" {\n"
" uv = Distort(xy);\n"
" }\n"
" else\n"
" {\n"
" uv = textureCoord;\n"
" }\n"
" vec4 c = texture2D(theTexture, uv);\n"
" gl_FragColor = c;\n"
"}"
}
};
bool Setup()
{
bool setupSuccess = false;
bool sdlInitialised = SDL_Init(SDL_INIT_VIDEO | SDL_INIT_EVENTS) == 0;
if (sdlInitialised)
{
window = SDL_CreateWindow("Barrel Distortion Test", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, WINDOW_WIDTH, WINDOW_HEIGHT, SDL_WINDOW_OPENGL);
if (window)
{
glContext = SDL_GL_CreateContext(window);
glewInit();
glViewport(0, 0, WINDOW_WIDTH, WINDOW_HEIGHT);
glClearColor(0.9f, 0.9f, 0.9f, 0.f);
setupSuccess = true;
}
else
{
printf("Could not initialise GL window\n");
}
}
else
{
printf("Could not initialise SDL\n");
}
return setupSuccess;
}
void Teardown()
{
SDL_DestroyWindow(window);
window = NULL;
glDeleteBuffers(1, &vbo);
glDeleteBuffers(1, &ibo);
}
void SetupDrawing()
{
// Setup vertices and texture coords. We setup a stride later for indexing these. The
// first three values on each line are the vertices, the last two are the texture
// coordinates (U, V)
vertices[0] = 1.0f; vertices[1] = 1.0f; vertices[2] = 0.0f; vertices[3] = 0.f; vertices[4] = 0.f;
vertices[5] = 1.0f; vertices[6] = -1.0f; vertices[7] = 0.0f; vertices[8] = 0.f; vertices[9] = 1.f;
vertices[10] = -1.0f; vertices[11] = -1.0f; vertices[12] = 0.0f; vertices[13] = 1.f; vertices[14] = 1.f;
vertices[15] = -1.0f; vertices[16] = 1.0f; vertices[17] = 0.0f; vertices[18] = 1.f; vertices[19] = 0.f;
// Setup indices
indices[0] = 0; indices[1] = 1; indices[2] = 3;
indices[3] = 1; indices[4] = 2; indices[5] = 3;
// Setup buffers
glGenBuffers(1, &vbo);
glGenBuffers(1, &ibo);
}
static SDL_bool CompileShader(GLhandleARB shader, const char* source)
{
GLint status = 0;
glShaderSource(shader, 1, &source, NULL);
glCompileShader(shader);
glGetShaderiv(shader, GL_COMPILE_STATUS, &status);
if (status == 0)
{
GLint length = 0;
char* info;
glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &length);
info = (char*)SDL_malloc(length + 1);
if (!info)
{
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Out of memory!");
}
else
{
glGetInfoLogARB(shader, length, NULL, info);
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Failed to compile shader:\n%s\n%s", source, info);
//SDL_free(info);
}
return SDL_FALSE;
}
else
return SDL_TRUE;
}
static SDL_bool LinkProgram(ShaderData* data)
{
GLint status = 0;
glAttachShader(data->program, data->vert_shader);
glAttachShader(data->program, data->frag_shader);
glLinkProgram(data->program);
glGetProgramiv(data->program, GL_LINK_STATUS, &status);
if (status == 0)
{
GLint length = 0;
char* info;
glGetProgramiv(data->program, GL_INFO_LOG_LENGTH, &length);
info = (char*)SDL_malloc(length + 1);
if (!info)
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Out of memory!");
else
{
glGetProgramInfoLog(data->program, length, NULL, info);
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Failed to link program:\n%s", info);
SDL_free(info);
}
return SDL_FALSE;
}
else
return SDL_TRUE;
}
static SDL_bool CompileShaderProgram(ShaderData* data)
{
const int num_tmus_bound = 4;
int i;
GLint location;
glGetError();
/* Create one program object to rule them all */
data->program = glCreateProgram();
/* Create the vertex shader */
data->vert_shader = glCreateShader(GL_VERTEX_SHADER);
if (!CompileShader(data->vert_shader, data->vert_source))
return SDL_FALSE;
/* Create the fragment shader */
data->frag_shader = glCreateShader(GL_FRAGMENT_SHADER);
if (!CompileShader(data->frag_shader, data->frag_source))
return SDL_FALSE;
/* ... and in the darkness bind them */
if (!LinkProgram(data))
return SDL_FALSE;
return (glGetError() == GL_NO_ERROR) ? SDL_TRUE : SDL_FALSE;
}
static void DestroyShaderProgram(ShaderData* data)
{
glDeleteShader(data->vert_shader);
glDeleteShader(data->frag_shader);
glDeleteProgram(data->program);
}
/* Quick utility function for texture creation */
static int power_of_two(int input)
{
int value = 1;
while (value < input)
value <<= 1;
return value;
}
GLuint SDL_GL_LoadTexture(SDL_Surface* surface/*, GLfloat* texcoord*/)
{
GLuint texture;
int w, h;
SDL_Surface* image;
SDL_Rect area;
SDL_BlendMode saved_mode;
/* Use the surface width and height expanded to powers of 2 */
w = power_of_two(surface->w);
h = power_of_two(surface->h);
image = SDL_CreateRGBSurface(SDL_SWSURFACE, w, h, 32,
#if SDL_BYTEORDER == SDL_LIL_ENDIAN /* OpenGL RGBA masks */
0x000000FF,
0x0000FF00,
0x00FF0000,
0xFF000000
#else
0xFF000000,
0x00FF0000,
0x0000FF00,
0x000000FF
#endif
);
if (image == NULL)
return 1;
/* Save the alpha blending attributes */
SDL_GetSurfaceBlendMode(surface, &saved_mode);
SDL_SetSurfaceBlendMode(surface, SDL_BLENDMODE_NONE);
/* Copy the surface into the GL texture image */
area.x = 0;
area.y = 0;
area.w = surface->w;
area.h = surface->h;
SDL_BlitSurface(surface, &area, image, &area);
/* Restore the alpha blending attributes */
SDL_SetSurfaceBlendMode(surface, saved_mode);
/* Create an OpenGL texture for the image */
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, image->pixels);
SDL_FreeSurface(image); /* No longer needed */
return texture;
}
static SDL_bool InitShaders()
{
int i;
/* Compile all the shaders */
for (i = 0; i < NUM_SHADERS; ++i)
{
if (!CompileShaderProgram(&shaders[i]))
{
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Unable to compile shader!\n");
return SDL_FALSE;
}
}
/* We're done! */
return SDL_TRUE;
}
static void QuitShaders()
{
int i;
for (i = 0; i < NUM_SHADERS; ++i)
DestroyShaderProgram(&shaders[i]);
}
void Run()
{
bool shadersInitialised = InitShaders();
if (!shadersInitialised)
return;
SetupDrawing();
int texture = -1;
SDL_Surface* surface = SDL_LoadBMP("icon.bmp");
if (surface)
{
texture = SDL_GL_LoadTexture(surface);
}
int shaderIndex = 0;
SDL_Event e;
bool run = true;
while (run)
{
while (SDL_PollEvent(&e))
{
if (e.type == SDL_QUIT)
{
run = false;
}
else if (e.type == SDL_KEYDOWN & e.key.keysym.sym == SDLK_SPACE)
{
if (shaderIndex == 0)
{
shaderIndex = 1;
}
else if (shaderIndex == 1)
{
shaderIndex = 0;
}
}
}
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glUseProgram(shaders[shaderIndex].program);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texture);
// Bind our vertices to our array
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_DYNAMIC_DRAW);
// Find our attributes in the current shader program and once found setup the
// attribute pointers
int position = glGetAttribLocation(shaders[shaderIndex].program, "position");
if (position != -1)
{
glVertexAttribPointer(position, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void *)0);
}
int textureCoord = glGetAttribLocation(shaders[shaderIndex].program, "texCoord");
if (textureCoord != -1)
{
glVertexAttribPointer(textureCoord, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void *)(3 * sizeof(float)));
}
// Bind our indices to our array
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_DYNAMIC_DRAW);
// Enable vertex attrib array
glEnableVertexAttribArray(position);
glEnableVertexAttribArray(textureCoord);
// Draw
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
// Disable vertex attrib array
glDisableVertexAttribArray(position);
glDisableVertexAttribArray(textureCoord);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
SDL_GL_SwapWindow(window);
}
}
int main(int argc, char** argv)
{
bool setupSuccess = Setup();
if (setupSuccess)
{
Run();
}
Teardown();
return 0;
}

Why is no character being rendered

So I am trying to render a character in OpenGL using freetype2. If I replace the variable vertex_location in my code with 0 I can see some kind of pixelated thing being rendered but it seems wrong because every time I restart the application the pixelated thing is different... So I am guessing it's just some random bytes or something.
Note: I am using GLEW, freetype2, glfw3, cglm
Anyways, here is my code:
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <stdio.h>
#include <cglm/cglm.h>
#include <cglm/call.h>
#include <math.h>
#include <ft2build.h>
#include FT_FREETYPE_H
/**
* Capture errors from glfw.
*/
static void error_callback(int error, const char* description)
{
fprintf(stderr, "Error: %s\n", description);
}
/**
* Capture key callbacks from glfw
*/
static void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods)
{
if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS)
glfwSetWindowShouldClose(window, GLFW_TRUE);
}
typedef struct CHARACTER_STRUCT
{
GLuint texture; // ID handle of the glyph texture
vec2 size; // Size of glyph
float width;
float height;
float bearing_left;
float bearing_top;
GLuint advance; // Horizontal offset to advance to next glyph
} character_T;
character_T* get_character(char c)
{
// FreeType
FT_Library ft;
// All functions return a value different than 0 whenever an error occurred
if (FT_Init_FreeType(&ft))
perror("ERROR::FREETYPE: Could not init FreeType Library");
// Load font as face
FT_Face face;
if (FT_New_Face(ft, "/usr/share/fonts/truetype/lato/Lato-Medium.ttf", 0, &face))
perror("ERROR::FREETYPE: Failed to load font");
// Set size to load glyphs as
FT_Set_Pixel_Sizes(face, 0, 32);
// Disable byte-alignment restriction
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
// Load character glyph
if (FT_Load_Char(face, c, FT_LOAD_RENDER))
perror("ERROR::FREETYTPE: Failed to load Glyph");
// Generate texture
GLuint texture;
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);
glTexImage2D(
GL_TEXTURE_2D,
0,
GL_RED,
face->glyph->bitmap.width,
face->glyph->bitmap.rows,
0,
GL_RED,
GL_UNSIGNED_BYTE,
face->glyph->bitmap.buffer
);
// Set texture options
/*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);*/
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
// Now store character for later use
character_T* character = calloc(1, sizeof(struct CHARACTER_STRUCT));
character->texture = texture;
character->width = face->glyph->bitmap.width;
character->height = face->glyph->bitmap.rows;
character->bearing_left = face->glyph->bitmap_left;
character->bearing_top = face->glyph->bitmap_top;
character->advance = face->glyph->advance.x;
glBindTexture(GL_TEXTURE_2D, 0);
// Destroy FreeType once we're finished
FT_Done_Face(face);
FT_Done_FreeType(ft);
return character;
}
int main(int argc, char* argv[])
{
glfwSetErrorCallback(error_callback);
/**
* Initialize glfw to be able to use it.
*/
if (!glfwInit())
perror("Failed to initialize glfw.\n");
/**
* Setting some parameters to the window,
* using OpenGL 3.3
*/
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
glfwWindowHint(GLFW_FLOATING, GL_TRUE);
glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);
/**
* Creating our window
*/
GLFWwindow* window = glfwCreateWindow(640, 480, "My Title", NULL, NULL);
if (!window)
perror("Failed to create window.\n");
glfwSetKeyCallback(window, key_callback);
/**
* Enable OpenGL as current context
*/
glfwMakeContextCurrent(window);
/**
* Initialize glew and check for errors
*/
GLenum err = glewInit();
if (GLEW_OK != err)
fprintf(stderr, "Error: %s\n", glewGetErrorString(err));
fprintf(stdout, "Status: Using GLEW %s\n", glewGetString(GLEW_VERSION));
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
unsigned int VAO;
glGenVertexArrays(1, &VAO);
unsigned int VBO;
glGenBuffers(1, &VBO);
GLuint vertex_shader, fragment_shader, program;
GLint mvp_location, vertex_location;
/**
* Vertex Shader
*/
static const char* vertex_shader_text =
"#version 330 core\n"
"uniform mat4 MVP;\n"
"attribute vec4 thevertex;\n"
"out vec2 TexCoord;\n"
"void main()\n"
"{\n"
" gl_Position = MVP * vec4(thevertex.xy, 0.0, 1.0);\n"
" TexCoord = thevertex.zw;"
"}\n";
/**
* Fragment Shader
*/
static const char* fragment_shader_text =
"#version 330 core\n"
"varying vec3 color;\n"
"in vec2 TexCoord;\n"
"uniform sampler2D ourTexture;\n"
"void main()\n"
"{\n"
" vec4 sampled = vec4(1.0, 1.0, 1.0, texture(ourTexture, TexCoord).r);\n"
" gl_FragColor = vec4(vec3(1, 1, 1), 1.0) * sampled;\n"
"}\n";
int success;
char infoLog[512];
/**
* Compile vertex shader and check for errors
*/
vertex_shader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertex_shader, 1, &vertex_shader_text, NULL);
glCompileShader(vertex_shader);
glGetShaderiv(vertex_shader, GL_COMPILE_STATUS, &success);
if(!success)
{
printf("Vertex Shader Error\n");
glGetShaderInfoLog(vertex_shader, 512, NULL, infoLog);
perror(infoLog);
}
/**
* Compile fragment shader and check for errors
*/
fragment_shader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragment_shader, 1, &fragment_shader_text, NULL);
glCompileShader(fragment_shader);
glGetShaderiv(fragment_shader, GL_COMPILE_STATUS, &success);
if(!success)
{
printf("Fragment Shader Error\n");
glGetShaderInfoLog(fragment_shader, 512, NULL, infoLog);
perror(infoLog);
}
/**
* Create shader program and check for errors
*/
program = glCreateProgram();
glAttachShader(program, vertex_shader);
glAttachShader(program, fragment_shader);
glLinkProgram(program);
glGetProgramiv(program, GL_LINK_STATUS, &success);
if(!success)
{
glGetProgramInfoLog(program, 512, NULL, infoLog);
perror(infoLog);
}
/**
* Grab locations from shader
*/
vertex_location = glGetUniformLocation(program, "thevertex");
mvp_location = glGetUniformLocation(program, "MVP");
glBindVertexArray(VAO);
/**
* Create and bind texture
*/
character_T* character = get_character('s');
unsigned int texture = character->texture;
float scale = 1.0f;
GLfloat xpos = 0;
GLfloat ypos = 0;
GLfloat w = character->width * scale;
GLfloat h = character->height * scale;
GLfloat vertices[6][4] = {
{ xpos, ypos + h, 0.0, 0.0 },
{ xpos, ypos, 0.0, 1.0 },
{ xpos + w, ypos, 1.0, 1.0 },
{ xpos, ypos + h, 0.0, 0.0 },
{ xpos + w, ypos, 1.0, 1.0 },
{ xpos + w, ypos + h, 1.0, 0.0 }
};
/**
* Main loop
*/
while (!glfwWindowShouldClose(window))
{
int width, height;
mat4 p, mvp;
double t = glfwGetTime();
glfwGetFramebufferSize(window, &width, &height);
glViewport(0, 0, width, height);
glClear(GL_COLOR_BUFFER_BIT);
mat4 m = GLM_MAT4_IDENTITY_INIT;
glm_translate(m, (vec3){ -sin(t), -cos(t), 0 });
glm_ortho_default(width / (float) height, p);
glm_mat4_mul(p, m, mvp);
glUseProgram(program);
glUniformMatrix4fv(mvp_location, 1, GL_FALSE, (const GLfloat*) mvp);
/**
* Draw texture
*/
glActiveTexture(GL_TEXTURE0);
glBindVertexArray(VAO);
glBindTexture(GL_TEXTURE_2D, texture);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * 6 * 4, vertices, GL_STATIC_DRAW);
glEnableVertexAttribArray(vertex_location);
glVertexAttribPointer(vertex_location, 4, GL_FLOAT, GL_FALSE, 4 * sizeof(GLfloat), 0);
glDrawArrays(GL_TRIANGLES, 0, 6);
glfwSwapBuffers(window);
glfwPollEvents();
}
glfwDestroyWindow(window);
glfwTerminate();
return 0;
}
thevertex is a vertex attribute.
attribute vec4 thevertex;
thus you have to get the resource index of the attribute by glGetAttribLocation rather than glGetUniformLocation.
vertex_location = glGetUniformLocation(program, "thevertex");
vertex_location = glGetAttribLocation(program, "thevertex");
glGetUniformLocation is meant to retrieve the the active resource index (location) of an uniform variable.

Exception thrown at 0x69F1454A (nvoglv32.dll) in Playground.exe: 0xC0000005: Access violation reading location 0x0A08D000

I want to display a texture but the compiler (Visual Studio 2017) gives me this error:
Exception thrown at 0x69F1454A (nvoglv32.dll) in Playground.exe: 0xC0000005: Access violation reading location 0x0A08D000.
The loadBMP_custom function has been taken from this website:
http://www.opengl-tutorial.org/beginners-tutorials/tutorial-5-a-textured-cube/
Any help is going to be appreciated.
This is my code:
#include <GL\freeglut.h>
#include <stdio.h>
GLuint loadBMP_custom(const char * imagepath) {
unsigned char header[54];
unsigned int width, height;
unsigned int imageSize;
GLuint textureID;
unsigned char * data;
FILE * file;
file = fopen(imagepath, "rb");
printf("%s\n", imagepath);
if (!file) {
printf("Image could not be opened\n");
return 0;
}
if (fread(header, 1, 54, file) != 54) {
printf("Not a correct BMP file\n");
}
if (header[0] != 'B' || header[1] != 'M') {
printf("Not a correct BMP file\n");
}
imageSize = *(int*)&(header[0x22]); //34
width = *(int*)&(header[0x12]); //18
height = *(int*)&(header[0x16]); //22
if (imageSize == 0) imageSize = width*height * 3;
data = (unsigned char* )malloc(imageSize);
fread(data, 1, imageSize, file);
fclose(file);
for (int i = 0; i < width * height; ++i)
{
int index = i * 3;
unsigned char B, R;
B = data[index];
R = data[index + 2];
data[index] = R;
data[index + 2] = B;
}
glGenTextures(1, &textureID);
glBindTexture(GL_TEXTURE_2D, textureID);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGBA,
GL_UNSIGNED_BYTE, data);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
return textureID;
}
void displayMe(void) {
GLuint bmp;
glClear(GL_COLOR_BUFFER_BIT);
glEnable(GL_TEXTURE_2D);
glPushMatrix();
bmp = loadBMP_custom("C:\\Dev\\Playground\\Release\\template.bmp");
glBindTexture(GL_TEXTURE_2D, bmp);
glBegin(GL_POLYGON);
glTexCoord2f(0.0, 0.0);
glVertex2f(0.0, 0.0);
glTexCoord2f(0.1, 0.0);
glVertex2f(0.1, 0.0);
glTexCoord2f(0.1, 0.1);
glVertex2f(0.1, 0.1);
glTexCoord2f(0.0, 0.1);
glVertex2f(0.0, 0.1);
glEnd();
glPopMatrix();
glutSwapBuffers();
}
void reshape(int w, int h) {
glViewport(0, 0, (GLsizei)w, (GLsizei)h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(60.0, (GLfloat)w / (GLfloat)h, 1.0, 30.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(0.0, 0.0, -3.6);
}
int main(int argc, char** argv) {
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);
glutInitWindowSize(800, 800);
glutCreateWindow("hi");
glutDisplayFunc(displayMe);
glutReshapeFunc(reshape);
glutMainLoop();
return 0;
}
if (imageSize == 0) imageSize = width*height * 3;
[...]
data = (unsigned char* )malloc(imageSize);
[...]
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
You are telling OpenGL that it should interpret the data pointer as describing an image with RGBA components at each pixel, each as bytes, but you provide only RGB data, which means that the GL will access beyond the end of your buffer.
The last three parameters of glTexImage describe the image data in client memory: the numer and order of the channels, the data format for each channel, and the pointer to the first pixel. The GL_RGB you use as internalFormat just describes the format the GL shall internally store the texture at.
The correct code should be
glPixelStorei(GL_UNPACK_ALIGNMENT, 1); // use tightly-packed data buffer with no padding between image rows
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, data);

opengl Soil texture

Here is the error message I am recieving from VS2010:
Unhandled exception at 0x77358dc9 in AzimuthalEqui.exe:
0xC0000005: Access violation writing location 0x00000014.
The line of code generating this error is:
texture[1] = SOIL_load_OGL_texture
(
texture_filename,
SOIL_LOAD_AUTO,
SOIL_CREATE_NEW_ID, // create ID automatically
SOIL_flags
);
before entering this function:
texture_filename = "Data/texture.jpg"
SOIL_LOAD_AUTO (= 0)
SOIL_CREATE_NEW_ID (=0)
SOIL_flags = 16 (=SOIL_FLAG_INVERT_Y)
The problem is that when I include a file I have written to parse some information in a text file an error is generated, otherwise the texture loads and is displayed. The prob is most likely caused by one function as when this particular function is removed the code loads and displays the texture.
Here is the function that when added to my project makes the error occur:
[CODE]
void get_user_points(double *lats, double *longs){
char buffer[BUFFSIZE_PARSE];
char *p_buff = buffer;
FILE *fp;
const char *filename = "Points.txt";
double temp;
double *tmp_p = &temp;
fp = fopen(filename,"r+");
if (fp == NULL)
{
sprintf(buffer, "Can't Find File: %s", filename);
MessageBoxA(NULL, buffer, "ERROR", MB_OK|MB_ICONEXCLAMATION);
exit(0);
}
fgets(buffer, BUFFSIZE_PARSE, fp);
while (*(p_buff+1) != '\0'){
p_buff = get_next_letter(p_buff);
switch (tolower(*p_buff)){
case 'n':
putchar(*p_buff);
p_buff++;
p_buff=get_next_double(lats, p_buff);
printf(" = %f\n", *lats);
break;
case 's':
...
...
}
}
putchar('\n');
fclose(fp);
}
It has something to do with opening the file for reading... if I comment out these lines the texture loads correctly:
//fpr = fopen(filename2,"rb");
...
...
...
//fclose(fpr);
Here is my reduced code (i don't think this is the issue but just in case). [There may be some remanants of my full code]:
int main(int argc, char** argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
{
printf("Initialising...\n");
glutInitWindowSize(700, 700);
glutInitWindowPosition(0, 0);
glutCreateWindow ("SOIL Texture Test");
}
InitGL();
glutDisplayFunc(DrawGLScene);
glutReshapeFunc(ReSizeGLScene);
glutMainLoop();
return 0;
}
int InitGL(GLvoid) // Setup OpenGL
{
//Load textures
if (!LoadGLTextures()) // Jump To Texture Loading Routine ( NEW )
{
MessageBox(NULL,TEXT("Cannot Load Image for Texture Map"),TEXT("Error!"),MB_OK | MB_ICONINFORMATION);
//return false; // If Texture Didn't Load Return FALSE ( NEW )
}
else
glEnable(GL_TEXTURE_2D); // Enable texture mapping
glShadeModel(GL_SMOOTH); // Enable Smooth Shading
glClearColor(0.0f, 0.0f, 0.0f, 0.0f); // Set the background colour (to black)
glClearDepth(1.0f); // Depth Buffer Setup
glEnable(GL_DEPTH_TEST); // Enables Depth Testing
glDepthFunc(GL_LEQUAL); // Select testing type
//get_user_points(&user_lat[0], &user_long[0]);
return true; // Initialization went OK
}
void DrawGLScene(GLvoid) // OpenGL drawing function
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Clear the Screen and the Depth Buffer
glLoadIdentity();
glTranslatef(0.0f,0.0f,z);
glBindTexture (GL_TEXTURE_2D, texture[filter]);
glBegin (GL_QUADS);
glNormal3f(0, 0, 1);
glTexCoord2f (0,0);
glVertex3f (-3,-3 ,0);
glTexCoord2f (1,0 );
glVertex3f (3,-3 , 0);
glTexCoord2f (1, 1);
glVertex3f (3,3 , 0);
glTexCoord2f (0,1 );
glVertex3f (-3,3 ,0 );
glEnd();
glFlush();
}
void ReSizeGLScene(int w, int h) // Code to resize (and initialise) the OpenGL scene (run once when in fullscreen mode)
{
// Set up perspective view matrix
glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(45.0f, (GLfloat)w/(GLfloat)h, 0.1f, 100.0f);
//glOrtho(-50.0, 50.0, -50.0, 50.0, -50.0, 50.0);
// Set up modelview matrix
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
int LoadGLTextures(void) // Load Bitmaps And Convert To Textures
{
unsigned int SOIL_flags;
GLint mag_param;
GLint min_param;
printf("Loading Textures... ");
SOIL_flags = SOIL_FLAG_INVERT_Y;
mag_param = GL_NEAREST;
min_param = GL_NEAREST;
texture[1] = SOIL_load_OGL_texture
(
texture_filename,
SOIL_LOAD_AUTO,
SOIL_CREATE_NEW_ID, // create ID automatically
SOIL_flags
);
if(texture[1] == 0)
return false;
glBindTexture(GL_TEXTURE_2D, texture[1]);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,mag_param);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,min_param);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
printf("Textures Loaded\n");
return true;
}
Including the .c files in my project instead of the .lib file fixed the problem.

Resources