Display RGB image using texture with OpenGL - c++

I'm trying to display RGB images in a GtkGLArea using a gtk/epoxy stack in C(/C++) langage brought by vcpkg.
I have no errors but the widget stay white.
Can someone teel me what I'm missing ?
here are the shaders:
#include <gtk/gtk.h>
#include <epoxy/gl.h>
const char* vertexShaderCode =
"#version 330 core\n"
"in vec3 a_position;"
"void main() {"
" gl_Position = vec4(a_position,1.0);"
"}";
const char* fragmentShaderCode =
"#version 330 core\n"
"uniform sampler2D u_texture;"
"in vec2 tex_pos;"
"out vec3 color;"
"void main() {"
" vec3 texel = texture2D(u_texture, tex_pos).rgb;"
" color = texel;"
"}";
used variables (class members):
guint width, height;
guint vao;
guint texture;
guint program;
void* pixels; // image content
some Triangle coordinates:
GLfloat vertices[12] = {
-1, -1, 0,
1, -1, 0,
-1, 1, 0,
1, 1, 0
};
GLfloat textureVertices[8] = {
0, 1,
1, 1,
0, 0,
1, 0
};
Init:
glViewport(0, 0, width, height);
glClearColor(1.0f, 1.0f, 1.0f, 1);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// shaders
guint vshader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vshader, 1, &vertexShaderCode, NULL);
glCompileShader(vshader);
guint fshader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fshader, 1, &fragmentShaderCode, NULL);
glCompileShader(fshader);
//program
program = glCreateProgram();
glAttachShader(program, vshader);
glAttachShader(program, fshader);
glLinkProgram(program);
glUseProgram(program);
glDisable(GL_BLEND);
glDisable(GL_DITHER);
glDisable(GL_DEPTH_TEST);
glDeleteShader(vshader);
glDeleteShader(fshader);
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
GLuint buffers[2];
glGenBuffers(2, &buffers[0]);
glBindBuffer(GL_ARRAY_BUFFER, buffers[0]);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), 0);
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, buffers[1]);
glBufferData(GL_ARRAY_BUFFER, sizeof(textureVertices), textureVertices, GL_STATIC_DRAW);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(float), 0);
glEnableVertexAttribArray(1);
glBindBuffer(GL_ARRAY_BUFFER, 0);
int textureHandle = glGetUniformLocation(program, "u_texture");
glUniform1i(textureHandle, 0);
glBindAttribLocation(program, 0, "a_position");
glBindAttribLocation(program, 1, "tex_pos");
// textures
glActiveTexture(GL_TEXTURE0);
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);// OR LINEAR
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glPixelStorei(GL_PACK_ALIGNMENT, 1);
glTexImage2D(
GL_TEXTURE_2D, 0,
GL_RGB,
width, height, 0,
GL_RGB,
GL_UNSIGNED_BYTE, NULL);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
glDisableVertexAttribArray(0);
glBindTexture(GL_TEXTURE_2D, 0);
glBindVertexArray(0);
glDeleteBuffers(2, &buffers[0]);
update drawing:
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
glBindTexture(GL_TEXTURE_2D, texture);
// Bind the VAO
glViewport(0, 0, areaWidth, areHeight);
glUseProgram(program);
glBindVertexArray(vao);
glBindTexture(GL_TEXTURE_2D, texture);
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RGB, GL_UNSIGNED_BYTE, pixels);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
glBindTexture(GL_TEXTURE_2D, 0);
each time needed data is copied to pixels pointer and rendering is requested:
gtk_gl_area_queue_render(GTK_GL_AREA(widget));
but the image is never rendered

All vertex attributes are inputs to the vertex shader. You need to pass the texture coordinates from the vertex shader to the fragment shader:
#version 330 core
in vec3 a_position;
in vec2 a_tex_pos;
out vec2 tex_pos;
void main() {
tex_pos = a_tex_pos;
gl_Position = vec4(a_position,1.0);
}
glBindAttribLocation(program, 1, "tex_pos");
glBindAttribLocation(program, 1, "a_tex_pos");
Note that the vertex shader runs per vertex, but the fragment shader runs per fragment. The vertex shader outputs are interpolated along the fragments between the vertices. The interpolated outputs are the inputs to the fragment shader. With the interpolated texture coordinates, a different pixel of the image can be looked up for each fragment of the primitive.

I fixed it, there was several mistakes:
mainly:
draw strips without an bound vertice buffer
working example:
here are the shaders:
#include <gtk/gtk.h>
#include <epoxy/gl.h>
const char* vertexShaderCode =
"#version 330 core\n"
"layout(location = 0) in vec3 a_position;"
"in vec2 a_tex_pos;"
"out vec2 tex_pos;"
"void main() {"
" tex_pos = a_tex_pos;"
" gl_Position = vec4(a_position,1.0);"
"}";
const char* fragmentShaderCode =
"#version 330 core\n"
"uniform sampler2D u_texture;"
"in vec2 tex_pos;"
"layout(location = 0) out vec4 color;"
"void main() {"
" vec4 texel = texture2D(u_texture, tex_pos);"
" color = texel;"
"}";
used variables (class members):
guint width, height;
guint vao;
guint texture;
guint program;
guint buffers[2];
void* pixels; // image content
some Triangle coordinates:
GLfloat vertices[12] = {
-1, -1, 0,
1, -1, 0,
-1, 1, 0,
1, 1, 0
};
GLfloat textureVertices[8] = {
0, 1,
1, 1,
0, 0,
1, 0
};
Init:
glViewport(0, 0, width, height);
glClearColor(1.0f, 1.0f, 1.0f, 1);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// shaders
guint vshader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vshader, 1, &vertexShaderCode, NULL);
glCompileShader(vshader);
guint fshader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fshader, 1, &fragmentShaderCode, NULL);
glCompileShader(fshader);
//program
program = glCreateProgram();
glAttachShader(program, vshader);
glAttachShader(program, fshader);
glLinkProgram(program);
glUseProgram(program);
//glDisable(GL_BLEND);
glDisable(GL_DITHER);
//glDisable(GL_DEPTH_TEST);
glDeleteShader(vshader);
glDeleteShader(fshader);
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
fbo = 0;
glGenFramebuffers(1, &fbo);
GLuint buffers[2];
glGenBuffers(2, &buffers[0]);
// I swap buffers order
glBindBuffer(GL_ARRAY_BUFFER, buffers[1]);
glBufferData(GL_ARRAY_BUFFER, sizeof(textureVertices), textureVertices, GL_STATIC_DRAW);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(float), 0);
glEnableVertexAttribArray(1);
glBindBuffer(GL_ARRAY_BUFFER, buffers[0]);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), 0);
glEnableVertexAttribArray(0);
//glBindBuffer(GL_ARRAY_BUFFER, 0); not yet !
int textureHandle = glGetUniformLocation(program, "u_texture");
glUniform1i(textureHandle, 0);
glBindAttribLocation(program, 0, "a_position");
glBindAttribLocation(program, 1, "a_tex_pos");
// textures
glActiveTexture(GL_TEXTURE0);
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);// OR LINEAR
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glPixelStorei(GL_PACK_ALIGNMENT, 1);
glTexImage2D(
GL_TEXTURE_2D, 0,
GL_RGB,
width, height, 0,
GL_RGBA,
GL_UNSIGNED_BYTE, NULL);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); // it is effective now
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
GLenum DrawBuffers[1] = { GL_COLOR_ATTACHMENT0 };
glDrawBuffers(1, DrawBuffers);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glBindBuffer(GL_ARRAY_BUFFER, 0); // unbind now
glDisableVertexAttribArray(0);
glBindTexture(GL_TEXTURE_2D, 0);
glBindVertexArray(0);
//glDeleteBuffers(2, &buffers[0]); no !
update drawing:
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
glBindTexture(GL_TEXTURE_2D, texture);
// Bind the VAO
glViewport(0, 0, areaWidth, areHeight);
glUseProgram(program);
glBindVertexArray(vao);
glBindTexture(GL_TEXTURE_2D, texture);
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RGB, GL_UNSIGNED_BYTE, pixels);
// rebind vertices
glBindBuffer(GL_ARRAY_BUFFER, buffers[0]);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
glEnableVertexAttribArray(0);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
glBindTexture(GL_TEXTURE_2D, 0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
each time needed data is copied to pixels pointer and rendering is requested:
gtk_gl_area_queue_render(GTK_GL_AREA(widget));

Related

Access violation in nvoglv64.dll when using OpenGL

My code is giving me this error:
Exception thrown at 0x00007FFCF428A6CF (nvoglv64.dll) in program.exe:
0xC0000005: Access violation reading location 0x000001D6B603F000.
In the debug output window of Visual Studio I also see pdb not loaded for the nvoglv64.dll file.
since i've added this code to my openGL app:
data = stbi_load("src/pickaxe.png", &width, &height, &nrChannels, 0);
if (!data) {
std::cout << "swords image loaded incorrectly " << std::endl;
}
else {
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
glGenerateMipmap(GL_TEXTURE_2D);
}
Is it caused because of loading the image or by function GLTEXIMAGE_2D ?
Here is my full code:
#include <glad/glad.h>
#include <GLFW/glfw3.h>
#include <iostream>
#define STB_IMAGE_IMPLEMENTATION
#include "stb_image.h"
// global variables
int p_WIDTH = 1280;
int p_HEIGHT = 960;
int succes;
char info[512];
// buffers
// shader sources
const char* vertexShaderSource =
"#version 330 core\n"
"layout(location = 0)in vec3 _verts;\n"
"layout(location = 1)in vec2 _texCoords;\n"
"out vec2 texCoords;\n"
"void main(){\n"
"gl_Position = vec4(_verts, 1.0f);\n"
"texCoords = _texCoords;\n"
"};\0"
;
const char* fragmentShaderSource =
"#version 330 core\n"
"in vec2 texCoords;\n"
"out vec4 fragColor;\n"
"uniform sampler2D _texture1;\n"
"uniform sampler2D _texture2;\n"
"void main(){\n"
"fragColor = mix(texture(_texture1, texCoords), texture(_texture2, texCoords), 0.5f);\n"
"};\0"
;
// functions
void window_resize_callback(GLFWwindow* window, int width, int height) {
glViewport(0, 0, width, height);
}
int main() {
glfwInit();
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_ANY_PROFILE, GLFW_OPENGL_CORE_PROFILE);
GLFWwindow* window = glfwCreateWindow(p_WIDTH, p_HEIGHT, "getting_started_completed", NULL, NULL);
glfwMakeContextCurrent(window);
glfwSetFramebufferSizeCallback(window, window_resize_callback);
if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
{
std::cout << "Failed to initialize GLAD" << std::endl;
return -1;
}
// shaders
GLuint vertexShader, fragmentShader;
vertexShader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertexShader, 1, &vertexShaderSource, NULL);
glCompileShader(vertexShader);
glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &succes);
if (!succes) {
glGetShaderInfoLog(vertexShader, 512, NULL, info);
std::cout << "VERTEX_SHADER_COMP_ERROR: " << info << std::endl;
}
fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentShader, 1, &fragmentShaderSource, NULL);
glCompileShader(fragmentShader);
glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &succes);
if (!succes) {
glGetShaderInfoLog(fragmentShader, 512, NULL, info);
std::cout << "FRAGMENT_SHADER_COMP_ERROR: " << info << std::endl;
}
GLuint program = glCreateProgram();
glAttachShader(program, vertexShader);
glAttachShader(program, fragmentShader);
glLinkProgram(program);
glGetProgramiv(program, GL_COMPILE_STATUS, &succes);
if (!succes) {
glGetProgramInfoLog(program, 512, NULL, info);
std::cout << "PROGRAM_LINK_ERROR: " << info << std::endl;
}
glDeleteShader(vertexShader);
glDeleteShader(fragmentShader);
// vertices
float vertices[] = {
-0.5f, -0.5f, 0.f, 0,0, // 0
0.5f, -0.5f, 0.f, 1,0, // 1
0.5f, 0.5f, 0.f, 1,1, // 2
-0.5f, 0.5f, 0.f, 0,1 // 3
};
unsigned int indices[] = {
0,1,2,
0,2,3
};
// buffers etc.
GLuint vbo, vao, ebo;
glGenVertexArrays(1, &vao);
glGenBuffers(1, &vbo);
glGenBuffers(1, &ebo);
glBindVertexArray(vao);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5*sizeof(float), (void*)0);
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)(3 * sizeof(float)));
// textures
unsigned int texture1, texture2;
glGenTextures(1, &texture1);
glBindTexture(GL_TEXTURE_2D, texture1);
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_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
int width, height, nrChannels;
stbi_set_flip_vertically_on_load(true);
unsigned char* data = stbi_load("src/dirt.jpg", &width, &height, &nrChannels, 0);
if (!data) {
std::cout << "dirt image loaded incorectly " << std::endl;
}
else {
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, data);
glGenerateMipmap(GL_TEXTURE_2D);
}
stbi_image_free(data);
glGenTextures(1, &texture2);
glBindTexture(GL_TEXTURE_2D, texture2);
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_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
data = stbi_load("src/pickaxe.png", &width, &height, &nrChannels, 0);
if (!data) {
std::cout << "swords image loaded incorrectly " << std::endl;
}
else {
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
glGenerateMipmap(GL_TEXTURE_2D);
}
glUseProgram(program);
glUniform1i(glGetUniformLocation(program, "_texture1"), 0);
glUniform1i(glGetUniformLocation(program, "_texture2"), 1);
while (!glfwWindowShouldClose(window)) {
glClearColor(0.f, 0.1f, 0.1f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texture1);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, texture2);
glUseProgram(program);
glBindVertexArray(vao);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
glfwPollEvents();
glfwSwapBuffers(window);
}
glDeleteVertexArrays(1, &vao);
glDeleteBuffers(1, &vbo);
glDeleteBuffers(1, &ebo);
glfwTerminate();
//std::cin.get();
return 0;
}
You want to load and image with 4 channels (GL_RGBA). There is no guarantee that the STB library generates an image with 4 channels. The actual number of channels is returned by the 4th argument of stbi_load. If the image doesn't have 4 channels, the subsequent call of glTexImage2D expects a larger buffer than you actually provide. That causes the access violation.
To solve the problem, you can force stbi_load to generate an image with 4 color channels by explicitly passing 4 as the last parameter:
data = stbi_load("src/pickaxe.png", &width, &height, &nrChannels, 4);

GLFW window only updates when moved with the mouse?

I have two uniform in my shader and i am updating these uniform in my window loop but the window do no get updated with loop instead i have to use my mouse to update the window..
I have upload a vedio to showcase this problem https://youtu.be/jWABZ50HhCE
This is my code::
#define GLEW_STATIC
#include<gl\glew.h>
#include<GLFW\glfw3.h>
#include<iostream>
#include<SOIL.h>
#include<glm/glm.hpp>
#include<glm/gtc/matrix_transform.hpp>
#include<glm/gtc/type_ptr.hpp>
//////////////////////////////////////
static const char* vertexShaderSource = "\n\
#version 150 core\n\
in vec2 position;\n\
in vec3 inColor;\n\
uniform mat4 trans;\n\ ////////////Uniform1/////////////
in vec2 texcoord;\n\
out vec2 Texcoord;\n\
out vec3 Color;\n\
void main(){\n\
Color=inColor;\n\
Texcoord=texcoord;\n\
gl_Position=trans*vec4(position,0,1);\n\
}\n";
static const char* fragmentShaderSource = "\n\
#version 150 core\n\
in vec3 Color;\n\
in vec2 Texcoord;\n\
uniform sampler2D te0;\n\
uniform sampler2D tex1;\n\
out vec4 color;\n\
uniform float mixvalue;\n\ ////////////Uniform2/////////////
void main(){\n\
vec4 color1=texture(te0,Texcoord);\n\
vec4 color2=texture(tex1,Texcoord);\n\
color=mix(color1,color2,mixvalue);\n\
}\n\
";
//////////////////////////////////////
int main() {
if (!glfwInit())
return -1;
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
GLFWwindow* window = glfwCreateWindow(1024, 620, "Window", nullptr, nullptr);
glfwMakeContextCurrent(window);
glewExperimental = GL_TRUE;
if (glewInit() != GLEW_OK)
return -1;
GLfloat triangleVertices[] = {
0.5f,0.5f,1,0,0,1,0,
0.5f,-0.5f,0,1,0,1,1,
-0.5f,-0.5f,0,0,1,0,1,
-0.5f,0.5f,0,0,0,0,0
};
GLuint vao;
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
GLuint vbo;
glGenBuffers(1, &vbo);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(triangleVertices), triangleVertices, GL_STATIC_DRAW);
GLuint elements[] = { 0,1,2 ,3,0,2};
GLuint ebo;
glGenBuffers(1, &ebo);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(elements), elements, GL_STATIC_DRAW);
////////////////////////////////////////////////////////
GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertexShader, 1, &vertexShaderSource, nullptr);
glCompileShader(vertexShader);
GLint statusVertex;
glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &statusVertex);
if (!statusVertex) {
char buffer[1024];
glGetShaderInfoLog(vertexShader, 1024, NULL, buffer);
std::cout << "Error Compiling vertexShader:" << buffer << std::endl;
}
GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentShader, 1, &fragmentShaderSource, nullptr);
glCompileShader(fragmentShader);
GLint statusFrag;
glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &statusFrag);
if (!statusFrag) {
char buffer[1024];
glGetShaderInfoLog(fragmentShader, 1024, NULL, buffer);
std::cout << "Error Compiling fragmentShader:" << buffer << std::endl;
}
GLuint program = glCreateProgram();
glAttachShader(program, vertexShader);
glAttachShader(program, fragmentShader);
glBindFragDataLocation(program, 0, "color");
glLinkProgram(program);
glUseProgram(program);
//////////////////////////////////////////////////////////
GLint positionAttrib = glGetAttribLocation(program, "position");
glVertexAttribPointer(positionAttrib, 2, GL_FLOAT, GL_FALSE, 7 * sizeof(GL_FLOAT), nullptr);
glEnableVertexAttribArray(positionAttrib);
GLint colorAttrib = glGetAttribLocation(program, "inColor");
glVertexAttribPointer(colorAttrib, 3, GL_FLOAT, GL_FALSE, 7 * sizeof(GL_FLOAT), (void*)(2 * sizeof(GL_FLOAT)));
glEnableVertexAttribArray(colorAttrib);
GLint texAttrib = glGetAttribLocation(program, "texcoord");
glVertexAttribPointer(texAttrib, 3, GL_FLOAT, GL_FALSE, 7 * sizeof(GL_FLOAT), (void*)(5 * sizeof(GL_FLOAT)));
glEnableVertexAttribArray(texAttrib);
GLuint textures[2];
glGenTextures(2, textures);
int width, height;
unsigned char* image;
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, textures[0]);
image = SOIL_load_image("1.png", &width, &height, 0, SOIL_LOAD_RGBA);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, image);
glGenerateMipmap(GL_TEXTURE_2D);
glUniform1i(glGetUniformLocation(program, "te0"), 0);
SOIL_free_image_data(image);
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);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, textures[1]);
image = SOIL_load_image("2.png", &width, &height, 0, SOIL_LOAD_RGBA);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, image);
glGenerateMipmap(GL_TEXTURE_2D);
glUniform1i(glGetUniformLocation(program, "tex1"), 1);
SOIL_free_image_data(image);
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);
GLuint mixvalue = glGetUniformLocation(program, "mixvalue");
GLint uniTrans = glGetUniformLocation(program, "trans");
//////These Two uniform/////////////////////
////////////////////////////////////////////
glm::mat4 trans = glm::mat4(1.0f);
float a=0,b=0;
/////////////////////////////////////////////////////////////
while (!glfwWindowShouldClose(window)) {
glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
b += 3;
trans = glm::rotate(trans, glm::radians(b), glm::vec3(0, 0, 1));
glUniformMatrix4fv(uniTrans, 1, GL_FALSE, glm::value_ptr(trans));
if (glfwGetKey(window, GLFW_KEY_E)) {
break;
}
if (a >= 1) a = 0;
a += 0.1f;
glUniform1f(mixvalue, a);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
glfwSwapBuffers(window);
glfwPollEvents();
}
glfwDestroyWindow(window);
glfwTerminate();
return 0;
}
What is wrong here.Is there something that i am doing wrong or is it because of some driver error.
GlfwVersion 3.3.0 32 bit

Why do I only see a single color?

I am trying to put either a color or an image to the background of the rectangle I draw using OpenGL 3.3.
I'm trying to generate the image color myself for testing, but it seems something is wrong with my code and I only see a single color.
Vertex shader:
#version 330 core
layout(location = 0) in vec2 VertexPosition;
layout(location = 1) in vec2 VertexUV;
out vec2 UV;
void main() {
gl_Position = vec4(VertexPosition.x, VertexPosition.y, 0.0, 1.0);
UV = VertexUV;
}
Fragment Shader:
#version 330 core
in vec2 UV;
out vec3 Color;
uniform sampler2D TextureSampler;
void main() {
Color = texture(TextureSampler, UV).rgb;
}
The way I generate textures:
GLuint data[3] = {64, 128, 192};
glGenTextures(1, &tex);
glBindTexture(GL_TEXTURE_2D, tex);
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, GL_RGB, 1, 1, 0, GL_RGB, GL_UNSIGNED_BYTE, data);
glGenerateMipmap(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, 0);
The way I draw my elements:
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, tex);
glUniform1i(TextureSamplerID, 0);
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, VertexBuffer);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, nullptr);
glEnableVertexAttribArray(1);
glBindBuffer(GL_ARRAY_BUFFER, UVBuffer);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, nullptr);
glDrawArrays(GL_TRIANGLES, 0, 6);
glDisableVertexAttribArray(0);
glDisableVertexAttribArray(1);
glBindTexture(GL_TEXTURE_2D, 0);
The way I generate buffers:
glGenBuffers(1, &VertexBuffer);
glGenBuffers(1, &UVBuffer);
glBindBuffer(GL_ARRAY_BUFFER, VertexBuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
const GLfloat uv_coordinates[] = {
0.0f, 0.0f,
1.0f, 0.0f,
1.0f, 1.0f,
1.0f, 1.0f,
0.0f, 1.0f,
0.0f, 0.0f
};
glBindBuffer(GL_ARRAY_BUFFER, UVBuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(uv_coordinates), uv_coordinates, GL_STATIC_DRAW);
When I create and draw a rectangle using these, I see this:
I try to generate texture data with these:
GLuint data2[192];
for(int i = 0; i < 192; i++) data2[i] = i;
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 8, 8, 0, GL_RGB, GL_UNSIGNED_BYTE, data2);
and I see this:
Since the type which enumerator which is passed to glTexImage2D is GL_UNSIGNED_BYTE, the data typo of the array of pixel data has to be GLubyte (which corresponds to GL_UNSIGNED_BYTE) instead of GLuint:
GLubyte data2[192];
for(int i = 0; i < 192; i++) data2[i] = i;
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 8, 8, 0, GL_RGB, GL_UNSIGNED_BYTE, data2);

Why am I failing to display a texture in OpenGL?

I'm trying to load a texture in OpenGL, but all I get is black. I've verified that the shaders are returning GL_TRUE when they compile. So, I don't think that is the issue...
Some things to note:
I have taken and modified code from https://open.gl/content/code/c3_multitexture.txt. This was a tutorial from https://open.gl/textures
The texture I am trying to load is from a 640 x 400 PGM file. You can assume the loader pgmImage correctly loads the file (I have verified it in GDB). PGM is 8-bit B&W data. Here I am trying to just use it as the red channel, although I'd like to be able to eventually display it as B&W, too.
Where am I going wrong?
Thanks!
Code compiled with: -lglut -lGLU -lGL -lm -lGLEW flags in g++ (some aren't necessary, I know).
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <math.h>
// Include GLEW
#include <GL/glew.h>
//Glut
#include <GL/glut.h>
#include "shader.hpp"
#include "PGM.hpp"
GLuint programID;
GLuint output_image;
// Shader sources
const GLchar* vertexSource =
"#version 450 core\n"
"in vec2 position;"
"in vec2 texcoord;"
"out vec2 Texcoord;"
"void main()"
"{"
" Texcoord = texcoord;"
" gl_Position = vec4(position, 0.0, 1.0);"
"}";
const GLchar* fragmentSource =
"#version 450 core\n"
"in vec2 Texcoord;"
"out vec4 outColor;"
"uniform sampler2D texData;"
"void main()"
"{"
" outColor = texture(texData, Texcoord);"
"}";
void display()
{
glClearColor(0.0f, 0.0f, 1.0f, 0.0f);
glClear(GL_COLOR_BUFFER_BIT);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
glFlush();
glutSwapBuffers();
}
void reshape(int width,int height)
{
double w2h = (height>0) ? (double)width/height : 1;
// Set viewport as entire window
glViewport(0,0, width,height);
}
int main(int argc, char** argv)
{
// Image setup
PGM pgmImage;
pgmImage.ReadFile("test.pgm");
// Window Setup
glutInitWindowSize(640, 400);
glutInitWindowPosition (140, 140);
glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE);
glutInit(&argc, argv);
glutCreateWindow( "OpenGL Application" );
glutDisplayFunc(display);
glutReshapeFunc(reshape);
glewExperimental = true; // Needed for core profile
if (glewInit() != GLEW_OK) {
fprintf(stderr, "Failed to initialize GLEW\n");
return -1;
}
// Vertices & texture init
GLuint vao;
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
GLuint vbo;
glGenBuffers(1, &vbo);
GLfloat vertices[] = {
// X Y S T
-0.5f, 0.5f, 0.0f, 0.0f, // Top-left
0.5f, 0.5f, 1.0f, 0.0f, // Top-right
0.5f, -0.5f, 1.0f, 1.0f, // Bottom-right
-0.5f, -0.5f, 0.0f, 1.0f // Bottom-left
};
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
GLuint ebo;
glGenBuffers(1, &ebo);
GLuint elements[] = {
0, 1, 2,
2, 3, 0
};
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(elements), elements, GL_STATIC_DRAW);
// Create shaders
GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertexShader, 1, &vertexSource, NULL);
glCompileShader(vertexShader);
GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentShader, 1, &fragmentSource, NULL);
glCompileShader(fragmentShader);
GLuint shaderProgram = glCreateProgram();
glAttachShader(shaderProgram, vertexShader);
glAttachShader(shaderProgram, fragmentShader);
glBindFragDataLocation(shaderProgram, 0, "outColor");
glLinkProgram(shaderProgram);
glUseProgram(shaderProgram);
// Vertex data specification
GLint posAttrib = glGetAttribLocation(shaderProgram, "position");
glEnableVertexAttribArray(posAttrib);
glVertexAttribPointer(posAttrib, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(GLfloat), 0);
GLint texAttrib = glGetAttribLocation(shaderProgram, "texcoord");
glEnableVertexAttribArray(texAttrib);
glVertexAttribPointer(texAttrib, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(GLfloat), (void *)(2 * sizeof(GLfloat)));
// Load Textures
//TODO: don't really need 2 textures, but just following along with example source code for now...
GLuint textures[2];
unsigned char* image;
int width, height;
width = pgmImage.GetWidth();
height = pgmImage.GetHeight();
image = (unsigned char *)pgmImage.GetData();
glGenTextures(2, textures);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, textures[0]);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RED_INTEGER, GL_UNSIGNED_BYTE, image);
glUniform1i(glGetUniformLocation(shaderProgram, "texData"), 0);
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);
// Start program
glutMainLoop();
// Teardown
glDeleteTextures(2, textures);
glDeleteProgram(shaderProgram);
glDeleteShader(fragmentShader);
glDeleteShader(vertexShader);
glDeleteBuffers(1, &ebo);
glDeleteBuffers(1, &vbo);
glDeleteVertexArrays(1, &vao);
return 0;
}
As you had already found, the internalFormat and format of your glTexImage2D() call are incompatible:
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RED_INTEGER, GL_UNSIGNED_BYTE, image);
GL_RED_INTEGER is for integer texture types. For 1-component texture data with normalized textures, the correct format is GL_RED:
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RED, GL_UNSIGNED_BYTE, image);
For new code, I would always recommend to use sized internal types, even though unsized internal types like GL_RGB are still valid for backwards compatibility. So for a normalized texture with 3 8-bit components:
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8, width, height, 0, GL_RED, GL_UNSIGNED_BYTE, image);
Your attempt at using GL_R8UI as the internal format failed because using integer textures requires additional changes, particularly in the shader code, where you would need to use usampler2D as the sampler type, and deal with getting integer values when you sample the textures. But in your case, that's not really what you wanted in the first place.

Sampler1D mapping blank with no errors

I eventually hope to colorize an image based on 3 1d samplers. I wrote this quick program to test if I could map the red channel of a texture to itself, a so called linear mapping.
Right now the code is showing a blank screen, despite all of my error checking in the program, shader, and general execution. When I don't perform the mapping the texture renders as expected.
I am on a GeForce Ti 550, targeting Windows.
The method was largely inspired from: http://www.arcsynthesis.org/gltut/Texturing/Tutorial%2014.html
Make Texture and Sampler
glActiveTexture(GL_TEXTURE1);
glGenTextures(1,lut);
glBindTexture(GL_TEXTURE_1D,lut[0]);
unsigned char* linear = new unsigned char[256];//should be a 1->1 mapping
for (int i = 0 ;i < 256;i++)
{
linear[i] = i;
}
glTexImage1D(GL_TEXTURE_1D, 0, GL_R8, 256, 0,GL_RED, GL_UNSIGNED_BYTE, linear);
glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_BASE_LEVEL, 0);
glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAX_LEVEL, 0);
glBindTexture(GL_TEXTURE_1D, 0);
delete linear;
glGenSamplers(1,sampler);
glSamplerParameteri(sampler[0], GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glSamplerParameteri(sampler[0], GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glSamplerParameteri(sampler[0], GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glE();// no errors
Make the program, also no errors
const char *vsrc1 =
"attribute vec2 vecPosIn;\n"
"attribute vec4 texPosIn;\n"
"varying vec4 texPosOut;\n"
"void main()\n"
"{\n"
"gl_Position = vec4(vecPosIn, 0.0, 1.0);\n"
"texPosOut = texPosIn;\n"
"}\n";
GLint vsH = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vsH,1,&vsrc1,NULL);
glCompileShader(vsH);
shaderCheck(vsH);
glE();
const char *fsrc1 =
"uniform sampler2D tex0;\n"
"uniform sampler1D tex1;\n"
"varying vec4 texPosOut;\n"
"void main(void)\n"
"{\n"
//" gl_FragColor = texture2D(tex0, texPosOut.st);\n" //ignores texture and does what I expect
" float red = texture2D(tex0, texPosOut.st).r;\n"
" gl_FragColor = texture1D(tex1, red);\n"
"}\n";
GLint fsH = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fsH,1,&fsrc1,NULL);
glCompileShader(fsH);
shaderCheck(fsH);
glE();
//Bind
programHandle = glCreateProgram();
glBindAttribLocation(programHandle,0,"vecPosIn");
glBindAttribLocation(programHandle,1,"texPosIn");
glBindAttribLocation(programHandle,2,"texPosOut");
glE();
//Link
glAttachShader( programHandle, vsH );
glAttachShader( programHandle, fsH );
glLinkProgram( programHandle );
programCheck(programHandle);
glE();
//Set render() invariants
glUseProgram( programHandle );
GLuint idk = glGetUniformLocation(programHandle, "tex1");
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_1D,lut[0]);
glUniform1i(idk,0);
glBindTexture(GL_TEXTURE_1D,0);
glUseProgram( 0 );
glE();
//Pack static data into a VAO
float vecData[] = {
-1, 1,
-1,-1,
1, 1,
-1,-1,
1,-1,
1, 1
};
float texData[] = {
0,1,
0,0,
1,1,
0,0,
1,0,
1,1
};
vboHandles=(GLuint*)malloc(sizeof(int)*2);
glGenBuffers(2,vboHandles);
GLuint vecBuf=vboHandles[0];
GLuint texBuf=vboHandles[1];
glBindBuffer(GL_ARRAY_BUFFER, vecBuf);
glBufferData(GL_ARRAY_BUFFER, 8*2 * sizeof(GLfloat), vecData, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, texBuf);
glBufferData(GL_ARRAY_BUFFER, 8*2 * sizeof(GLfloat), texData, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glE();
glGenVertexArrays( 1, &vaoHandle );
glBindVertexArray(vaoHandle);
glEnableVertexAttribArray(0); // Vertex position
glEnableVertexAttribArray(1); // Vertex color
glBindBuffer(GL_ARRAY_BUFFER, vecBuf);
glVertexAttribPointer( 0, 2, GL_FLOAT, GL_FALSE, 0, (GLubyte *)NULL );
glBindBuffer(GL_ARRAY_BUFFER, texBuf);
glVertexAttribPointer( 1, 2, GL_FLOAT, GL_FALSE, 0, (GLubyte *)NULL ); //2 attribute per vertex
glBindBuffer(GL_ARRAY_BUFFER,0);
glBindVertexArray(0);
glE();
Render Function
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
glE();
//Bind
glUseProgram(programHandle);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D,textures[frame]);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_1D,lut[0]);
GLuint idk = glGetUniformLocation(programHandle, "tex1");
glUniform1i(idk,0);
glBindSampler(0,sampler[0]);glE();
glE();
//Draw
glBindVertexArray(vaoHandle);
glDrawArrays(GL_TRIANGLES,0,8);
glBindVertexArray(0);
glE();
//Unbind
glActiveTexture(GL_TEXTURE1);
glBindSampler(0,0);
glBindTexture(GL_TEXTURE_1D,0);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D,0);
glUseProgram(0);
glE();
//DumpFrame
glFlush();
glFinish();
glE();
You are setting
glUniform1i(idk,0);
so you tell the GL to use texture unit 0 to sample the "tex1" 1D texture, which is just invalid as you have a 2D texture bound there.