SegFault after calling glDrawArrays - c++

I am attempting to write a sprite batcher.
Originally, I was uploading the following data to openGL in order to see if I could get anything to the screen:
static GLfloat const vertexData[] = {
//Position //Color //UV Coords
0.5f, 0.5f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
-0.5f, 0.5f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f,
0.5f, -0.5f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f,
-0.5f, -0.5f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f,
-0.5f, 0.5f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f,
0.5f, -0.5f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f
};
These are my Vertex and Fragment Shaders:
const char* vert = "#version 330 core\n"
"layout (location = 0) in vec2 vPos;\n"
"layout (location = 1) in vec4 vColor;\n"
"layout (location = 2) in vec2 vTexPos;\n"
"\n"
"out vec4 fColor;\n"
"out vec2 fTexPos;\n"
"\n"
"void main() {\n"
" gl_Position = vec4(vPos.xy, 0.0, 1.0);\n"
" fColor = vColor;\n"
" fTexPos = vec2(vTexPos.s, 1.0 - vTexPos.t);\n"
"}";
const char* frag = "#version 330 core\n"
"in vec4 fColor;\n"
"in vec2 fTexPos;\n"
"out vec4 finalColor;\n"
"\n"
"uniform sampler2D textureUniform;\n"
"\n"
"void main() {\n"
" vec4 textureColor = texture(textureUniform, fTexPos);"
" finalColor = fColor * textureColor;\n"
"}";
I set up the VAO and VBO like so:
auto vaoID_ = 0;
auto vboID_ = 0;
glGenVertexArrays(1, &vaoID_);
glGenBuffers(1, &vboID_);
glBindVertexArray(vaoID_);
glBindBuffer(GL_ARRAY_BUFFER, vboID_);
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
glEnableVertexAttribArray(2);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 8, (void*)0); // Screen Position
glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, 8, (void*)(2 *sizeof(GL_FLOAT)); //Color
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8, (void*)(6 * sizeof(GL_FLOAT)); //UV
And finally, on each loop, I would orphan the buffer and then sub the data in.
glBufferData(GL_ARRAY_BUFFER, sizeof(vertexData), nullptr, GL_DYNAMIC_DRAW);
glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(vertexData), vertexData);
glDrawArrays(GL_TRIANGLES, 0, 6);
This worked fine!
So, I attempted to begin to write a basic sprite batch.
I grouped my vertex data into a POD struct:
struct VertexData {
struct {
GLfloat screenx;
GLfloat screeny;
} position;
struct {
GLfloat r;
GLfloat g;
GLfloat b;
GLfloat a;
} color;
struct {
GLfloat texu;
GLfloat texv;
} uv;
}
And used a vector to batch everything together:
std::vector<VertexData> spritebatch_
I changed the calls to glVertexAttribPointer to match this struct (although I think this change was unneeded?)
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(VertexData), (void*)offsetof(VertexData, position)); // Screen Position
glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, sizeof(VertexData), (void*)offsetof(VertexData, color)); //Color
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, sizeof(VertexData), (void*)offsetof(VertexData, uv)); //UV
To test it, on every loop I would feed it the same data that was in the static GLfloat array:
spritebatch_.push_back({0.5f, 0.5f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f});
spritebatch_.push_back({-0.5f, 0.5f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f});
spritebatch_.push_back({0.5f, -0.5f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f});
spritebatch_.push_back({-0.5f, -0.5f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f});
spritebatch_.push_back({-0.5f, 0.5f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f});
spritebatch_.push_back({0.5f, -0.5f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f});
And then attempt to orphan the buffer and sub the data in:
glBufferData(GL_VERTEX_ARRAY, spritebatch_.size() * sizeof(VertexData), nullptr, GL_DYNAMIC_DRAW);
glBufferSubData(GL_VERTEX_ARRAY, 0, spritebatch_.size() * sizeof(VertexData), spritebatch_.data());
glDrawArrays(GL_TRIANGLES, 0, spritebatch_.size());
Finally, I would reset the spritebatch_: spritebatch_.clear();
However, this segfaults. Am I doing something incorrect when I go to orphan the buffer and sub the data in? The data formats still match (VertexData POD members are all GLfloats still), the size of spritebatch_ is still 6 (6 vertices to make a square), and the location of that data is still the same within each vertex.

The 5th parameter of glVertexAttribPointer is the "stride", the byte offset between consecutive generic vertex attributes.
So the change from
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 8, (void*)0); // Screen Position
glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, 8, (void*)(2 *sizeof(GL_FLOAT)); //Color
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8, (void*)(6 * sizeof(GL_FLOAT)); //UV
to
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(VertexData), (void*)offsetof(VertexData, position)); // Screen Position
glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, sizeof(VertexData), (void*)offsetof(VertexData, color)); //Color
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, sizeof(VertexData), (void*)offsetof(VertexData, uv)); //UV
is important, because sizeof(VertexData) is not 8, but it is 8*sizeof(GL_FLOAT) .
The first parameter of glBufferData respectively glBufferSubData has to be the enumerator constant for the target, which is one of GL_ARRAY_BUFFER, GL_ELEMENT_ARRAY_BUFFER, ... .
GL_VERTEX_ARRAY identifies the vertex array for the fixed function client-side capability - See glEnableClientState.
Change:
glBufferData(GL_VERTEX_ARRAY, ...);
glBufferData(GL_ARRAY_BUFFER, ...);
glBufferSubData(GL_VERTEX_ARRAY, ...);
glBufferSubData(GL_ARRAY_BUFFER, ...);
Note, if you would check for OpenGL errors (glGetError or Debug Output), you would get a GL_INVALID_ENUM error.
The data store for the array buffer is not created, this causes the segment fault.

Related

array of sampler2D uses last bound texture [duplicate]

This question already has answers here:
Will any of the following texture lookups cause undefined behavior, non-uniform flow, or both?
(1 answer)
Why are Uniform variables not working in GLSL?
(1 answer)
Closed 10 months ago.
I am trying to implement a simple batchrenderer. I am using an array of sampler2D for it. however, the array is using the last bound texture instead of using the texture bound to the texture unit. I would really appreciate if anyone can help me out. here's my code:
Edit: the sampler2d array index is working fine. when i used FragColor = vec4(t, 0, 0, 0); it gave me a black quad and a red quad. But for some, it is using the last bound texture. both the quads are using texture2.
main.cpp
int main()
{
Window window("DJROXZHIA", 800, 600, true);
Shader shader("res/shaders/vertex.glsl", "res/shaders/fragment.glsl");
shader.enable();
float vertices[] = {
0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f,
1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f,
1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
-0.5f, -0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f,
-1.0f, -0.5f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f,
-1.0f, -1.0f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
-0.5f, -1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f
};
unsigned int indices[] = {
0, 1, 2, 2, 3, 0,
4, 5, 6, 6, 7, 4
};
Texture texture("res/texture/DodgerCover.png");
Texture texture2("res/texture/game-play-image.png"); //both the quads are using texture2
GLuint vao, vbo, ibo;
glGenVertexArrays(1, &vao);
glGenBuffers(1, &vbo);
glGenBuffers(1, &ibo);
glBindVertexArray(vao);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
glEnableVertexAttribArray(2);
glEnableVertexAttribArray(3);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(DJROXZHIA::maths::Vertex2D), (void*)offsetof(DJROXZHIA::maths::Vertex2D, pos));
glVertexAttribPointer(1, 1, GL_FLOAT, GL_FALSE, sizeof(DJROXZHIA::maths::Vertex2D), (void*)offsetof(DJROXZHIA::maths::Vertex2D, texture));
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, sizeof(DJROXZHIA::maths::Vertex2D), (void*)offsetof(DJROXZHIA::maths::Vertex2D, texCoords));
glVertexAttribPointer(3, 4, GL_FLOAT, GL_FALSE, sizeof(DJROXZHIA::maths::Vertex2D), (void*)offsetof(DJROXZHIA::maths::Vertex2D, color));
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
GLfloat t[2] = { 0.0f, 1.0f };
glUniform1fv(glGetUniformLocation(shader.getID(), "u_texture"), 2, t);
while (!window.closed())
{
window.clear(glm::vec4(0.0f));
glActiveTexture(GL_TEXTURE + 0);
glBindTexture(GL_TEXTURE_2D, texture.getTextureID());
glActiveTexture(GL_TEXTURE + 1);
glBindTexture(GL_TEXTURE_2D, texture2.getTextureID());
glBindVertexArray(vao);
glDrawElements(GL_TRIANGLES, 12, GL_UNSIGNED_INT, 0);
glBindVertexArray(0);
window.tick();
}
return 0;
}
vertex.glsl
#version 330 core
layout (location = 0) in vec3 aPos;
layout (location = 1) in float aTexture;
layout (location = 2) in vec2 aTexCoords;
layout (location = 3) in vec4 aColor;
out float tex;
out vec2 texCoords;
out vec4 color;
out vec3 pos;
//uniform mat4 u_ProjView;
void main()
{
gl_Position = vec4(aPos, 1.0);
tex = aTexture;
texCoords = aTexCoords;
color = aColor;
pos = aPos;
}
fragment.glsl
#version 330 core
in float tex;
in vec2 texCoords;
in vec4 color;
in vec3 pos;
uniform sampler2D u_texture[2];
out vec4 FragColor;
void main()
{
int t = int(tex);
FragColor = texture(u_texture[t], texCoords) * color;
}
Thanks in advance

When my quad draws in OpenGl, the texture stretches oddly, i need it to morph to the shape of the quad uniformly, not as shown below. How do I do so? [duplicate]

I wanna make the OpenGL program can present images and warp the images presented.
Although I achieved image rendering using OpenGL, I don't know how to warp an image.
An warpable example I want is (Reference):
But a picture I got is:
As I know, this problem is related to perspective correction mapping.
But I don't know about that well.
Here is my source code.
void imageRender(Shader initShader, Shader imgShader, char *path){
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST);
float positions = { 0.5f, 1.0f, 0.0f,
1.0f, -1.0f, 0.0f,
-1.0f, -1.0f, 0.0f,
-1.0f, 1.0f, 0.0f };
float vertices[] = {
// positions // colors // texture coords
position[0], position[1], position[2], 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, // top right
position[3], position[4], position[5], 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, // bottom right
position[6], position[7], position[8], 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, // bottom left
position[9], position[10],position[11], 1.0f, 1.0f, 0.0f, 0.0f, 1.0f // top left
};
unsigned int indices[] = {
0, 1, 3,
1, 2, 3
};
unsigned int VAO, VBO, EBO;
glGenVertexArrays(1, &VAO);
glBindVertexArray(VAO);
glGenBuffers(1, &VBO);
glGenBuffers(1, &EBO);
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);
// position attribute
//glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)0);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)0);
glEnableVertexAttribArray(1);
// color attribute
glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(3 * sizeof(float)));
glEnableVertexAttribArray(2);
//texture attribute
glVertexAttribPointer(3, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(6 * sizeof(float)));
glEnableVertexAttribArray(3);
FREE_IMAGE_FORMAT format = FreeImage_GetFileType(path, 0);
if (format == -1){
cerr << BOLDRED << "[ERROR] IMAGE_NOT_FOUND" << RESET << endl;
exit(1);
}
if (format == FIF_UNKNOWN){
cerr << BOLDRED << "[ERROR] UNKNOWN_IMAGE_FORMAT" << RESET << endl;
format = FreeImage_GetFIFFromFilename(path);
if (!FreeImage_FIFSupportsReading(format)){
cerr << BOLDRED << "[ERROR] IMAGE_FORMAT_NOT_READABLE" << RESET << endl;
exit(1);
}
}
FIBITMAP *bitmap = FreeImage_Load(format, path);
FIBITMAP *bitmap32;
int bitsPerPixel = FreeImage_GetBPP(bitmap);
bitmap32 = FreeImage_ConvertTo32Bits(bitmap);
int imageWidth = FreeImage_GetWidth(bitmap32);
int imageHeight = FreeImage_GetHeight(bitmap32);
GLubyte *textureData = FreeImage_GetBits(bitmap32);
GLuint texture1;
glGenTextures(1, &texture1);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texture1);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, imageWidth, imageHeight, 0, GL_BGRA, GL_UNSIGNED_BYTE, textureData);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); // set texture wrapping to GL_REPEAT (default wrapping method)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
initShader.use();
glBindVertexArray(VAO);
int initalTime = time(NULL);
while(1){
glBindVertexArray(VAO);
int timecal = time(NULL);
//glDrawElements(GL_TRIANGLE_STRIP, 6, GL_UNSIGNED_INT, 0);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
glfwSwapBuffers(window);
glfwPollEvents();
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
if ((timecal - initalTime) > imageTime) // imageTime value is 10
break;
}
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
glDeleteTextures(1, &texture1);// image
glDisable(GL_TEXTURE_2D);//image
FreeImage_Unload(bitmap32);
FreeImage_Unload(bitmap);
glDeleteVertexArrays(1, &VAO);
glDeleteBuffers(1, &VBO);
glDeleteBuffers(1, &EBO);
}
}
Shader code is like that
//shader.vs
#version 330 core
layout(location = 1) in vec3 position;
layout(location = 2) in vec3 color;
layout(location = 3) in vec2 texcoord;
out vec3 Color;
out vec2 Texcoord;
void main()
{
gl_Position = vec4(position, 1.0);
Texcoord = texcoord;
}
//shader.fs
#version 330 core
in vec3 Color;
in vec2 Texcoord;
out vec4 outColor;
uniform sampler2D texture5;
void main()
{
outColor = texture2D(texture5, Texcoord);
}
How can I warp texture?
And then Is it correct to use position value to warp texture image?
The issue has nothing to do with perspective projection. You draw a polygon with 4 vertices parallel to the XY plane of the view, but the polygon is not a quad! Change the x coordinate of the 1st vertex (0.5f -> 1.0f). Perspective projection works with Homogeneous coordinates.
In generalperspective projection is achieved by a Perspective projection matrix. Of course you can define homogeneous vertices to inspect the behavior:
Define an attribute tuple with homogenous vertices (4 components):
float vertices[] = {
// positions // colors // texture coords
1.0f, 1.0f, 0.5f, 2.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, // top right
1.0f, -1.0f, -0.5f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, // bottom right
-1.0f, -1.0f, -0.5f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, // bottom left
-1.0f, 1.0f, 0.5f, 2.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f // top left
};
Adapt the vertex specification and the vertex shader:
// position attribute
glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, 9 * sizeof(float), (void*)0);
glEnableVertexAttribArray(1);
// color attribute
glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, 9 * sizeof(float), (void*)(4 * sizeof(float)));
glEnableVertexAttribArray(2);
//texture attribute
glVertexAttribPointer(3, 2, GL_FLOAT, GL_FALSE, 9 * sizeof(float), (void*)(7 * sizeof(float)));
glEnableVertexAttribArray(3);
#version 330 core
layout(location = 1) in vec4 position;
layout(location = 2) in vec3 color;
layout(location = 3) in vec2 texcoord;
out vec3 Color;
out vec2 Texcoord;
void main()
{
gl_Position = position;
Texcoord = texcoord;
}
Another option to achieve the effect is, to a an Z component to the geometry. e.g:
float positions = { 1.0f, 1.0f, 0.5f,
1.0f, -1.0f, 0.0f,
-1.0f, -1.0f, -0.5f,
-1.0f, 1.0f, 0.0f };
and to compute the w component dependent on z in the vertex shader (e.g. w = z + 2.5:
#version 330 core
layout(location = 1) in vec3 position;
layout(location = 2) in vec3 color;
layout(location = 3) in vec2 texcoord;
out vec3 Color;
out vec2 Texcoord;
void main()
{
gl_Position = vec4(position, position.z + 2.5);
Texcoord = texcoord;
}

how to warp texture in openGL? (Perspective correction?)

I wanna make the OpenGL program can present images and warp the images presented.
Although I achieved image rendering using OpenGL, I don't know how to warp an image.
An warpable example I want is (Reference):
But a picture I got is:
As I know, this problem is related to perspective correction mapping.
But I don't know about that well.
Here is my source code.
void imageRender(Shader initShader, Shader imgShader, char *path){
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST);
float positions = { 0.5f, 1.0f, 0.0f,
1.0f, -1.0f, 0.0f,
-1.0f, -1.0f, 0.0f,
-1.0f, 1.0f, 0.0f };
float vertices[] = {
// positions // colors // texture coords
position[0], position[1], position[2], 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, // top right
position[3], position[4], position[5], 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, // bottom right
position[6], position[7], position[8], 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, // bottom left
position[9], position[10],position[11], 1.0f, 1.0f, 0.0f, 0.0f, 1.0f // top left
};
unsigned int indices[] = {
0, 1, 3,
1, 2, 3
};
unsigned int VAO, VBO, EBO;
glGenVertexArrays(1, &VAO);
glBindVertexArray(VAO);
glGenBuffers(1, &VBO);
glGenBuffers(1, &EBO);
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);
// position attribute
//glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)0);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)0);
glEnableVertexAttribArray(1);
// color attribute
glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(3 * sizeof(float)));
glEnableVertexAttribArray(2);
//texture attribute
glVertexAttribPointer(3, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(6 * sizeof(float)));
glEnableVertexAttribArray(3);
FREE_IMAGE_FORMAT format = FreeImage_GetFileType(path, 0);
if (format == -1){
cerr << BOLDRED << "[ERROR] IMAGE_NOT_FOUND" << RESET << endl;
exit(1);
}
if (format == FIF_UNKNOWN){
cerr << BOLDRED << "[ERROR] UNKNOWN_IMAGE_FORMAT" << RESET << endl;
format = FreeImage_GetFIFFromFilename(path);
if (!FreeImage_FIFSupportsReading(format)){
cerr << BOLDRED << "[ERROR] IMAGE_FORMAT_NOT_READABLE" << RESET << endl;
exit(1);
}
}
FIBITMAP *bitmap = FreeImage_Load(format, path);
FIBITMAP *bitmap32;
int bitsPerPixel = FreeImage_GetBPP(bitmap);
bitmap32 = FreeImage_ConvertTo32Bits(bitmap);
int imageWidth = FreeImage_GetWidth(bitmap32);
int imageHeight = FreeImage_GetHeight(bitmap32);
GLubyte *textureData = FreeImage_GetBits(bitmap32);
GLuint texture1;
glGenTextures(1, &texture1);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texture1);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, imageWidth, imageHeight, 0, GL_BGRA, GL_UNSIGNED_BYTE, textureData);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); // set texture wrapping to GL_REPEAT (default wrapping method)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
initShader.use();
glBindVertexArray(VAO);
int initalTime = time(NULL);
while(1){
glBindVertexArray(VAO);
int timecal = time(NULL);
//glDrawElements(GL_TRIANGLE_STRIP, 6, GL_UNSIGNED_INT, 0);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
glfwSwapBuffers(window);
glfwPollEvents();
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
if ((timecal - initalTime) > imageTime) // imageTime value is 10
break;
}
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
glDeleteTextures(1, &texture1);// image
glDisable(GL_TEXTURE_2D);//image
FreeImage_Unload(bitmap32);
FreeImage_Unload(bitmap);
glDeleteVertexArrays(1, &VAO);
glDeleteBuffers(1, &VBO);
glDeleteBuffers(1, &EBO);
}
}
Shader code is like that
//shader.vs
#version 330 core
layout(location = 1) in vec3 position;
layout(location = 2) in vec3 color;
layout(location = 3) in vec2 texcoord;
out vec3 Color;
out vec2 Texcoord;
void main()
{
gl_Position = vec4(position, 1.0);
Texcoord = texcoord;
}
//shader.fs
#version 330 core
in vec3 Color;
in vec2 Texcoord;
out vec4 outColor;
uniform sampler2D texture5;
void main()
{
outColor = texture2D(texture5, Texcoord);
}
How can I warp texture?
And then Is it correct to use position value to warp texture image?
The issue has nothing to do with perspective projection. You draw a polygon with 4 vertices parallel to the XY plane of the view, but the polygon is not a quad! Change the x coordinate of the 1st vertex (0.5f -> 1.0f). Perspective projection works with Homogeneous coordinates.
In generalperspective projection is achieved by a Perspective projection matrix. Of course you can define homogeneous vertices to inspect the behavior:
Define an attribute tuple with homogenous vertices (4 components):
float vertices[] = {
// positions // colors // texture coords
1.0f, 1.0f, 0.5f, 2.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, // top right
1.0f, -1.0f, -0.5f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, // bottom right
-1.0f, -1.0f, -0.5f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, // bottom left
-1.0f, 1.0f, 0.5f, 2.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f // top left
};
Adapt the vertex specification and the vertex shader:
// position attribute
glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, 9 * sizeof(float), (void*)0);
glEnableVertexAttribArray(1);
// color attribute
glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, 9 * sizeof(float), (void*)(4 * sizeof(float)));
glEnableVertexAttribArray(2);
//texture attribute
glVertexAttribPointer(3, 2, GL_FLOAT, GL_FALSE, 9 * sizeof(float), (void*)(7 * sizeof(float)));
glEnableVertexAttribArray(3);
#version 330 core
layout(location = 1) in vec4 position;
layout(location = 2) in vec3 color;
layout(location = 3) in vec2 texcoord;
out vec3 Color;
out vec2 Texcoord;
void main()
{
gl_Position = position;
Texcoord = texcoord;
}
Another option to achieve the effect is, to a an Z component to the geometry. e.g:
float positions = { 1.0f, 1.0f, 0.5f,
1.0f, -1.0f, 0.0f,
-1.0f, -1.0f, -0.5f,
-1.0f, 1.0f, 0.0f };
and to compute the w component dependent on z in the vertex shader (e.g. w = z + 2.5:
#version 330 core
layout(location = 1) in vec3 position;
layout(location = 2) in vec3 color;
layout(location = 3) in vec2 texcoord;
out vec3 Color;
out vec2 Texcoord;
void main()
{
gl_Position = vec4(position, position.z + 2.5);
Texcoord = texcoord;
}

OpenGL rendering black square

I am attempting to render a colored rectangle, but I just end up with a black one.
My shaders and shader program do not produce any errors when compiling or linking, so I am sure there is something going wrong when I am attempting to buffer the data. But, everything looks correct to me.
Shader sources
std::string const fragment_shader_source = "#version 330 core\n"
""
"in vec4 fColor;\n"
"\n"
"out vec4 finalColor;\n"
"\n"
"void main() {\n"
" finalColor = fColor;\n"
"}";
std::string const vertex_shader_source = "#version 330 core\n"
""
"layout (location = 0) in vec2 vPos;\n"
"layout (location = 1) in vec4 vColor;\n"
"\n"
"out vec4 fColor;\n"
"void main() {\n"
" gl_Position = vec4(vPos.xy, 1.0, 1.0);\n"
" fColor = vColor;\n"
"}";
Vertex data
static GLfloat const vertex_data[] = {
// //Position //Color //UV Coords
0.5f, 0.5f, 1.0f, 0.0f, 1.0f, 1.0f,
-0.5f, 0.5f, 1.0f, 0.0f, 0.0f, 1.0f,
0.5f, -0.5f, 1.0f, 1.0f, 0.0f, 1.0f,
-0.5f, -0.5f, 0.0f, 1.0f, 1.0f, 1.0f,
-0.5f, 0.5f, 0.0f, 0.0f, 1.0f, 1.0f,
0.5f, -0.5f, 0.0f, 1.0f, 0.0f, 1.0f
};
Here is my main loop:
int SDLApp::AppMain(int argc, char** argv) {
if(sdl_window_ == nullptr) {
acorn::Log(acorn::LoggingLevel::Fatal, "Could not initialize the window.");
return -1;
}
if(sdl_gl_context_ == nullptr) {
acorn::Log(acorn::LoggingLevel::Fatal, "Could not create an OpenGL context.");
return -1;
}
acorn::shader::FragmentShader f(fragment_shader_source);
acorn::shader::VertexShader v(vertex_shader_source);
acorn::shader::Program shader_program(f, v);
shader_program.Link();
shader_program.Use();
GLuint vao_;
glGenVertexArrays(1, &vao_);
GLuint vbo_;
glGenBuffers(1, &vbo_);
glBindVertexArray(vao_);
glBindBuffer(GL_ARRAY_BUFFER, vbo_);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), (void*)0);
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), (void*)2);
glBufferData(GL_ARRAY_BUFFER, 6 * sizeof(GLfloat) * 6, vertex_data, GL_STATIC_DRAW);
glClearColor(1.0f, 0.0f, 0.0f,1.0f);
SDL_Event event;
while (true) {
while (SDL_PollEvent(&event)) {
if (event.type == SDL_QUIT) {
return 0;
}
}
glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
glDrawArrays(GL_TRIANGLES, 0, 6);
SDL_GL_SwapWindow(sdl_window_);
}
}
The last parameter of glVertexAttribPointer is treated as a byte offset into the buffer object's data store.
So the offset has to be 8, 2*sizeof(float):
glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, 6*sizeof(GLfloat),
(void*)(2*sizeof(GLfloat)));
After changing that, your code works fine

glGetAttribLocation returns -1 when retrieving existing shader attribute

I'm trying to pass in attributes to my vertex shader but for some reason it keeps giving me a -1 on the 3rd attribute location I'm asking openGl to retrieve via glGetAttribLocation(). Currently it keeps giving me a -1 for the texCoord attribute and if I switch the texAttrib and colAttrib around (switching the lines in code) it gives me a -1 on the color property instead of the texture and I have no idea why? Since a -1 is being passed to glVertexAttribPointer I get the 1281 OpenGL error: GL_INVALID_VALUE.
My vertex shader:
#version 150
in vec3 position;
in vec3 color;
in vec2 texcoord;
out vec3 Color;
out vec2 Texcoord;
void main()
{
Color = color;
Texcoord = texcoord;
gl_Position = vec4(position.x, position.y, position.z, 1.0);
}
OpenGL code:
basicShader.Use();
// Buffers and shaders
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
glGenBuffers(1, &vbo);
// Make it active vbo
glBindBuffer(GL_ARRAY_BUFFER, vbo);
// Build basic triangle
float vertices[] = {
// position // color // textures
-0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, // Top-left
0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, // Top-right
0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, // Bottom-right
-0.5f, -0.5f, 0.5f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f// Bottom-left
};
GLuint elements[] = {
0, 1, 2,
2, 3, 0
};
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
GLint posAttrib = glGetAttribLocation(basicShader.shaderProgram, "position");
glEnableVertexAttribArray(posAttrib); // Enable attribute first before specifiying attributes
glVertexAttribPointer(posAttrib, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), 0); // 6 float sizes is every new vertex
GLint colAttrib = glGetAttribLocation(basicShader.shaderProgram, "color");
glEnableVertexAttribArray(colAttrib);
glVertexAttribPointer(colAttrib, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(3 * sizeof(float))); // same for color + offset
GLint texAttrib = glGetAttribLocation(basicShader.shaderProgram, "texcoord"); // Returns -1
glEnableVertexAttribArray(texAttrib);
glVertexAttribPointer(texAttrib, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(6 * sizeof(float))); // 6 offset from beginning
[..]
You should stop using glGetAttribLocation. Assign each attribute a location, either with glBindAttribLocation before linking the program or with explicit attribute locations, if that's available to you.
That way, if the compiler optimizes an attribute away (which is what's happening here; your fragment shader probably doesn't use one of the interpolated values), you won't care. You'll set up your arrays as normal, using a standard convention for attribute indices. Plus, you won't have to keep asking what an attribute location is every time you want to render with a different program; you know what location it is because you assigned it.
If you can't/won't, then there's nothing you can do. The compiler will optimize away attributes if you're not actually using them. The only thing you can do is detect that it returns -1 and not set up the array for that attribute.