OpenGL 3.3: Issues Displaying 2D Texture over 3D scene - c++

I have been trying to display a 2D image over a 3D scene and have had absolutely no results (as in nothing is displayed over the 3D scene at all). I have tried normal gdb debugging, and using APITrace to make sure all the OpenGL calls are working properly. I have no idea why the image is not displaying. After some more tests, I believe the issue is not the texture itself, but something about the rendering of the 2 triangles which the texture is on. Below is all the relevant code:
// Constants
const int COORD_LOCATION = 10;
const int UV_LOCATION = 5;
// Program Loading
uint program = loadShaders("2d.fs","2d.vs") // Same function used for loading shaders for 3D objects, so the function itself should work
// Texture creation
GLuint texture;
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, temp_width, temp_height, 0, GL_RGB, GL_UNSIGNED_BYTE, image_data); // image_data is generated by libpng earlier, and it is valid according to apitrace
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
/* Later, when texture rendering is started... */
uint UV_BUFFER, cb;
glGenBuffers(1, &UV_BUFFER);
glGenBuffers(1, &cb);
const float data[] = { 0.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, 0.0f };
glBindBuffer(GL_ARRAY_BUFFER, UV_BUFFER);
glBufferData(GL_ARRAY_BUFFER, sizeof(data), &data[0], GL_STATIC_DRAW);
vec2 f1 = vec2(-0.5f, -0.5f);
vec2 f2 = vec2(0.5f, 0.5f);
// Set the 2d coordinates for the shader
const float data2[] = { f1.x, f1.y,
f1.x, f2.y,
f2.x, f1.y,
f2.x, f1.y,
f1.x, f2.y,
f2.x, f2.y };
// Load into buffer
glBindBuffer(GL_ARRAY_BUFFER, cb);
glBufferData(GL_ARRAY_BUFFER, sizeof(data2), &data2[0], GL_STATIC_DRAW);
// During rendering...
glUseProgram(program);
glEnableVertexAttribArray(COORD_LOCATION);
glBindBuffer(GL_ARRAY_BUFFER, cb);
glVertexAttribPointer(
COORD_LOCATION, // attribute. No particular reason for 0, but must match the layout in the shader.
2, // size
GL_FLOAT, // type
GL_FALSE, // normalized?
0, // stride
(void*)0 // array buffer offset
);
// Send uniform texture
uint tex = glGetUniformLocation(program, TEXTURE_UNIFORM);
// Bind our texture in Texture Unit 0
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texture);
// Set our "myTextureSampler" sampler to user Texture Unit 0
glUniform1i(tex, 0);
// Send UVs to the location
glEnableVertexAttribArray(UV_LOCATION);
glBindBuffer(GL_ARRAY_BUFFER, UV_BUFFER);
glVertexAttribPointer(
UV_LOCATION, // attribute. No particular reason for 0, but must match the layout in the shader.
2, // size
GL_FLOAT, // type
GL_FALSE, // normalized?
0, // stride
(void*)0 // array buffer offset
);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glDrawArrays(GL_TRIANGLES, 0, 6);
glDisable(GL_BLEND);
glDisableVertexAttribArray(COORD_LOCATION);
glDisableVertexAttribArray(UV_LOCATION);
2D Vertex Shader:
#version 330 core
layout(location = 10) in vec2 coords;
layout(location = 5) in vec2 inUV;
out vec2 UV;
void main(){
gl_Position.x = coords.x;
gl_Position.y = coords.y;
gl_Position.z = 0;
gl_Position.w = 1;
UV = inUV;
}
2D Fragment Shader:
#version 330 core
in vec2 UV;
uniform sampler2D tex;
out vec3 color;
void main(){
color = texture(tex, UV);
}
The code is actually quite a bit more scattered than this, but this is what I have confirmed it comes down to. See the full code in our VCS (this is just a random game my friend and I decided to develop to practice OpenGL, we dont even have a real name for it yet).

vec2 f1 = vec2(-0.5f, -0.5f);
vec2 f2 = vec2(-0.5f, -0.5f);
Those look like the same point. Zero-(screenspace-)area triangles generally aren't rasterized.
Try changing f2 to this:
vec2 f2 = vec2(0.5f, 0.5f);
glDrawArrays(GL_TRIANGLES, 0, 10000);
^^^^^
Try changing that 10000 to 6. Since you only have 6 vertices in your VBOs.

Related

How to get camera movement when using openGL framebuffers

I have been writing a program to visualize a fractal point cloud and so far everything has been working, camera movement is using arc-ball movement centered on the origin and points are being rendered. However, I am needing to output the scene into an integrated window inside a UI so i have been trying to get frame buffers to work.
So far i have got a texture to be successfully rendered onto a quad that i am then outputting to the screen which for testing purposes is basically the same as when i was not using a fbo. My issue comes when trying to get camera movement to also display using the rendered texture. i know this is definitely possible as there are lots of examples of this but i haven't been able to get any to work with my code. I'm fairly certain my issue is with my shaders but i have scoured lots of websites, YouTube tutorials, openGL examples and found nothing that works. to the best of my knowledge i have to render the scene as normal so i have been using the same shaders that have worked for me previously for the initial rendering step but i have using my fbo instead of the default fbo
for simplicity's sake, i have just been rendering a point cube as it is faster than generating a fractal each time.
here is the main setup of the fbo, texture and rbo:
GLuint fbo;
GLuint texturebuffer;
GLuint rbo;
void initFBO(){
glGenFramebuffers(1, &fbo);
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
glGenTextures(1, &texturebuffer);
glBindTexture(GL_TEXTURE_2D, texturebuffer);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, WINDOW_WIDTH, WINDOW_HEIGHT, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texturebuffer, 0);
glGenRenderbuffers(1, &rbo);
glBindRenderbuffer(GL_RENDERBUFFER, rbo);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, WINDOW_WIDTH, WINDOW_HEIGHT);
glBindRenderbuffer(GL_RENDERBUFFER, 0); // once rbo memory allocated unbind
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, rbo);
}
here is the main and the draw loop:
int main(){
if(!setup())
return -1;
// // white background
glClearColor(1.0f, 1.0f, 1.0f, 0.0f);
GLuint VertexArrayID;
glGenVertexArrays(1, &VertexArrayID);
glBindVertexArray(VertexArrayID);
// GLuint programID = LoadShaders( "new_vertex_shader", "new_fragment_shader" ); // custom shader
GLuint programID = LoadShaders("new_vertex_shader", "new_fragment_shader");
GLuint modelMatrixID = glGetUniformLocation(programID, "model");
GLuint viewMatrixID = glGetUniformLocation(programID, "view");
GLuint matrixID = glGetUniformLocation(programID, "MVP");
GLuint quad_programID = LoadShaders( "screen_vertex_shader", "screen_fragment_shader" );
GLuint textureID = glGetUniformLocation(quad_programID, "screenTexture");
// initialise mvp matrices
glm::mat4 ProjectionMatrix = perspective(radians(45.0f), 4.0f / 3.0f, 0.1f, 100.0f);
glm::mat4 ViewMatrix = translate(mat4(1.0f), vec3(0,0,-RADIUS));
glm::mat4 ModelMatrix = mat4(1.0f);
glm::mat4 MVP;
GLuint vertexbuffer;
glGenBuffers(1, &vertexbuffer);
glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
GLfloat cube[24] = {
0.5,0.5,0.5,
0.5,-0.5,0.5,
-0.5,0.5,0.5,
-0.5,-0.5,0.5,
0.5,0.5,-0.5,
0.5,-0.5,-0.5,
-0.5,-0.5,-0.5,
-0.5,0.5,-0.5
};
glBufferData(GL_ARRAY_BUFFER, sizeof(cube),cube, GL_STATIC_DRAW);
glfwSetMouseButtonCallback(window, mouseCallback);
// ################# main draw loop #######################
while( glfwGetKey(window, GLFW_KEY_ESCAPE ) != GLFW_PRESS && glfwWindowShouldClose(window) == 0 ){
// render to fbo first
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
glEnable(GL_DEPTH_TEST);
glClearColor(0.1f, 0.1f, 0.1f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
computeMatricesFromInputs();
ProjectionMatrix = getProjectionMatrix();
ViewMatrix = getViewMatrix();
ModelMatrix = getModelMatrix();
MVP = ProjectionMatrix * ViewMatrix * ModelMatrix;
// Use our shader
glUseProgram(programID);
// Send our transformation to the currently bound shader in the "MVP" uniform
glUniformMatrix4fv(matrixID, 1, GL_FALSE, &MVP[0][0]);
glUniformMatrix4fv(modelMatrixID, 1, GL_FALSE, &ModelMatrix[0][0]);
glUniformMatrix4fv(viewMatrixID, 1, GL_FALSE, &ViewMatrix[0][0]);
// render scene as normal
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer); // index buffer
glVertexAttribPointer(
0, // attribute 0. No particular reason for 0, but must match the layout in the shader.
3, // size
GL_FLOAT, // type
GL_FALSE, // normalized?
0, // stride
(void*)0 // array buffer offset
);
glPointSize(POINT_SIZE);
glDrawArrays(GL_POINTS, 0, sizeof(cube));
glDisableVertexAttribArray(0);
// bind back to default frame buffer to show on screen
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glDisable(GL_DEPTH_TEST);
glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glUseProgram(quad_programID);
glEnableVertexAttribArray(0);
glBindVertexArray(quad_vertex_buffer);
glVertexAttribPointer(
0, // attribute 0. No particular reason for 0, but must match the layout in the shader.
3, // size
GL_FLOAT, // type
GL_FALSE, // normalized?
0, // stride
(void*)0 // array buffer offset
);
glDrawArrays(GL_POINTS, 0, sizeof(cube));
glDisableVertexAttribArray(0);
// Swap buffers
glfwSwapBuffers(window);
glfwPollEvents();
}
vertex shader:
#version 330 core
// Input vertex data, different for all executions of this shader.
layout(location = 0) in vec3 vertexPosition_modelspace;
// Values that stay constant for the whole mesh.
uniform mat4 MVP;
uniform mat4 view;
uniform mat4 model;
void main(){
// Output position of the vertex, in clip space : MVP * position
gl_Position = MVP * vec4(vertexPosition_modelspace,1.0);
}
fragment shader:
#version 330 core
// Output data
out vec3 color;
void main(){
// Output color = black
color = vec3(0,0,0);
}
screen quad vertex shader:
#version 330 core
layout (location = 0) in vec2 aPos;
layout (location = 1) in vec2 aTexCoords;
out vec2 TexCoords;
void main()
{
TexCoords = aTexCoords;
gl_Position = vec4(aPos.x, aPos.y, 0.0, 1.0);
}
screen quad fragment shader:
#version 330 core
out vec4 FragColour;
in vec2 TexCoords;
uniform sampler2D screenTexture;
void main()
{
FragColour = texture(screenTexture, TexCoords);
}
sorry if this is quite a big block of code, im not entirely sure where the error would lie and im somewhat new to using openGL. many thanks in advance for anyhelp.
glEnableVertexAttribArray changes a state in the Vertex Array Object. It has to be done after binding the VAO by glBindVertexArray.
I assume that quad_vertex_buffer is a Vertex Array Object, even though the name "vertex_buffer" is misleading.
glBindVertexArray(quad_vertex_buffer);
glEnableVertexAttribArray(0);
When you draw the screen space quad (2nd pass), then you have to use a primitive type which generates a (filled) polygon (probably GL_TRIANGLES or GL_TRIANGLE_STRIP), rather than the point primitive type GL_POINTS:
glDrawArrays(GL_POINTS, 0, sizeof(cube));
glDrawArrays(GL_TRIANGLE_STRIP, 0, sizeof(cube))

Textures not drawing OpenGL

I am having some strange behavior when trying to draw a texture in OpenGL. Currently all this program does for me is draw the background color with no indication of a texture being drawn. I have just moved from Visual Studio (where this code produces the correct output) to compiling in the command prompt. This code should color the background and draw one texture in the center of the screen.
I am concerned that I may have supplied the incorrect libraries for compilation since as far as I am concerned everything I am doing is the same. Different libraries, however, always said that they were incompatible.
Main code:
#define GLEW_STATIC
#include <GL/glew.h> // window management library
#include <GL/glfw3.h>
#include <GL/glm.hpp>
#include <GL/gtc/matrix_transform.hpp> //
#define STB_IMAGE_IMPLEMENTATION
#include "stb_image.h"
int main(int argc, char** argv){
//Initialize GLFW and GLEW...
//Setup and combine shaders...
GLint vertex_att = glGetAttribLocation(program, "vertex");
glVertexAttribPointer(vertex_att, 2, GL_FLOAT, GL_FALSE, 7*sizeof(GLfloat), 0);
glEnableVertexAttribArray(vertex_att);
GLint color_att = glGetAttribLocation(program, "color");
glVertexAttribPointer(color_att, 3, GL_FLOAT, GL_FALSE, 7*sizeof(GLfloat), (void *) (2 *sizeof(GLfloat)));
glEnableVertexAttribArray(color_att);
GLint tex_att = glGetAttribLocation(program, "uv");
glVertexAttribPointer(tex_att, 2, GL_FLOAT, GL_FALSE, 7*sizeof(GLfloat), (void *) (5 *sizeof(GLfloat)));
glEnableVertexAttribArray(tex_att);
glUseProgram(program);
GLuint texture;
glGenTextures(1, &texture);
setthisTexture(texture, "./black.png");
// Create geometry of the square
int size = CreateSquare();
while (!glfwWindowShouldClose(window)){
// Clear background
glClearColor(viewport_background_color_g[0],
viewport_background_color_g[1],
viewport_background_color_g[2], 0.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
//set displacement - 'program' being the shader program
int matrixLocation = glGetUniformLocation(program, "x");
glm::mat4 translate = glm::mat4();
translate = glm::translate(translate, glm::vec3(0.0f, 0.0f, 0.0f));
glUniformMatrix4fv(matrixLocation, 1, GL_FALSE, &translate[0][0]);
glBindTexture(GL_TEXTURE_2D, texture);
glDrawElements(GL_TRIANGLES, size, GL_UNSIGNED_INT, 0);
glfwPollEvents();
glfwSwapBuffers(window);
}
}
Vertex Shader:
#version 130
in vec2 vertex;
in vec3 color;
in vec2 uv;
out vec2 uv_interp;
// Uniform (global) buffer
uniform mat4 x;
// Attributes forwarded to the fragment shader
out vec4 color_interp;
void main(){
vec4 t;
t = vec4(vertex, 0.0, 1.0);
gl_Position = x*t;
color_interp = vec4(color, 1.0);
uv_interp = uv;
}
Fragment Shader:
#version 130
in vec4 color_interp;
in vec2 uv_interp;
uniform sampler2D onetex;
void main(){
vec4 color = texture2D(onetex, uv_interp);
gl_FragColor = vec4(color.r,color.g,color.b,color.a);
if(gl_FragColor.a < 0.9){
discard;
}
}
setthisTexture:
void setthisTexture(GLuint w, const char *fname)
{
glBindTexture(GL_TEXTURE_2D, w);
int width, height, nrChannels;
unsigned char* image = stbi_load(fname, &width, &height, &nrChannels, 0);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, image);
stbi_image_free(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);
}
CreateSquare:
int CreateSquare(void) {
// The face of the square is defined by four vertices and two triangles
// Number of attributes for vertices and faces
// const int vertex_att = 7; // 7 attributes per vertex: 2D (or 3D) position (2), RGB color (3), 2D texture coordinates (2)
// const int face_att = 3; // Vertex indices (3)
GLfloat vertex[] = {
// square (two triangles)
// Position Color Texcoords
-0.5f, 0.5f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, // Top-left
0.5f, 0.5f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, // Top-right
0.5f, -0.5f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, // Bottom-right
-0.5f, -0.5f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f // Bottom-left
};
GLuint face[] = {
0, 1, 2, // t1
2, 3, 0 //t2
};
GLuint vbo, ebo;
// Create buffer for vertices
glGenBuffers(1, &vbo);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertex), vertex, GL_STATIC_DRAW);
// Create buffer for faces (index buffer)
glGenBuffers(1, &ebo);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(face), face, GL_STATIC_DRAW);
// Return number of elements in array buffer
return sizeof(face);
}
For the use of glVertexAttribPointer either a named GL_ARRAY_BUFFER buffer object has to be bound or a pointer to the vertex data has to be passed.
In your case this means, that
int size = CreateSquare();
has to be done before
GLint vertex_att = glGetAttribLocation(program, "vertex");
glVertexAttribPointer(vertex_att, 2, GL_FLOAT, GL_FALSE, 7*sizeof(GLfloat), 0);
glEnableVertexAttribArray(vertex_att);
.....
Note in the function CreateSquare, the named buffer object vbo is bound:
glBindBuffer(GL_ARRAY_BUFFER, vbo);
which is used by the glVertexAttribPointer calls.
See OpenGL 4.6 API Compatibility Profile Specification; 10.3.9 Vertex Arrays in Buffer Objects; page 409:
A buffer object binding point is added to the client state associated with each
vertex array type and index. The commands that specify the locations and organizations
of vertex arrays copy the buffer object name that is bound to ARRAY_-
BUFFER to the binding point corresponding to the vertex array type or index being
specified. For example, the VertexAttribPointer command copies the value of
ARRAY_BUFFER_BINDING (the queriable name of the buffer binding corresponding
to the target ARRAY_BUFFER) to the client state variable VERTEX_ATTRIB_-
ARRAY_BUFFER_BINDING for the specified index.

OpenGL GLSL texture function always returning vec4(1,1,1,1), white triangle

I'm trying to work on a texture mapping 2D to a triangle. But currently, I can only get a triangle that has a gradient colour without any texture on it. Which means, my texture function in glsl always return vec4(1,1,1,1) and my textCoords is working. How should I fix it? Any suggestions would be helpful to try!
By the way, have been working on this for 3 days.
in texture class:
constructor:
Texture::Texture(const std::string& fileName){
int width, height, numComponents;
//float* imageData = stbi_loadf(fileName.c_str(), &width, &height, &numComponents, 4);
unsigned char* imageData = stbi_load(fileName.c_str(), &width, &height, &numComponents, 4);
if(imageData == NULL){
cerr << "Texture loading failed for "<<fileName<< endl;
}
glGenTextures(1, &m_texture);
glBindTexture(GL_TEXTURE_2D, m_texture);
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_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA8,width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, imageData);
stbi_image_free(imageData);
}
Texture binding function:
void Texture::Bind(){
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, m_texture);
}
In my main.cpp:
m_shader.generateProgramObject();
m_shader.attachVertexShader( getAssetFilePath("VertexShader.vs").c_str() );
m_shader.attachFragmentShader( getAssetFilePath("FragmentShader.fs").c_str() );
m_shader.link();
// texture created here
texture = Texture("Assets/bricks.jpg");
// enable vertex attribute indices
glGenVertexArrays(1, &m_vao_triangle);
glBindVertexArray(m_vao_triangle);
// Enable the attribute index location for "position" when rendering.
GLint positionAttribLocation = m_shader.getAttribLocation( "position" );
glEnableVertexAttribArray(positionAttribLocation);
GLint textCoordLocation = m_shader.getAttribLocation( "atextCoord" );
glEnableVertexAttribArray(textCoordLocation);
// Restore defaults
glBindVertexArray(0);
CHECK_GL_ERRORS;
uploade triangle data to buffer
vec3 triangleVertices[] = {
// Construct equalaterial triangle
vec3(0.0f, 0.0f, 0.0f),
vec3(0.25f, 1.0f, 0.0),
vec3(0.5f, 0.0f, 0.0f)
};
vec2 textCoords[] = {
vec2(1.0f, 0.0f),
vec2(0.25f, 1.0f),
vec2(0.5f, 0.0f)};
// Generate a vertex buffer object to hold the triangle's vertex data.
glGenBuffers(1, &m_vbo_triangle);
//-- Upload triangle vertex data to the vertex buffer:
glBindBuffer(GL_ARRAY_BUFFER, m_vbo_triangle);
glBufferData(GL_ARRAY_BUFFER, sizeof(triangleVertices), triangleVertices,
GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
CHECK_GL_ERRORS;
//====generate buffer for holding texture coordinates====
glGenBuffers(1, &m_uv_triangle);
glBindBuffer(GL_ARRAY_BUFFER, m_uv_triangle);
glBufferData(GL_ARRAY_BUFFER, sizeof(textCoords), textCoords,
GL_STATIC_DRAW);
// Unbind the target GL_ARRAY_BUFFER, now that we are finished using it.
glBindBuffer(GL_ARRAY_BUFFER, 0);
CHECK_GL_ERRORS;
map buffer data to shader
glBindVertexArray(m_vao_triangle);
glBindBuffer(GL_ARRAY_BUFFER, m_vbo_triangle);
GLint positionAttribLocation = m_shader.getAttribLocation( "position" );
glVertexAttribPointer(positionAttribLocation, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
glBindBuffer(GL_ARRAY_BUFFER, m_uv_triangle);
GLint textCoordLocation = m_shader.getAttribLocation( "atextCoord" );
glVertexAttribPointer(textCoordLocation,2, GL_FLOAT, GL_FALSE, 0, nullptr);
//-- Unbind target, and restore default values:
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
CHECK_GL_ERRORS;
upload uniform to shader
m_shader.enable();
...
GLint uniformLocation_diffuse = m_shader.getUniformLocation("diffuse");
glUniform1i(uniformLocation_diffuse, 0);
CHECK_GL_ERRORS;
m_shader.disable();
CHECK_GL_ERRORS;
And in my draw function:
glBindVertexArray(m_vao_triangle);
// below I tried, but didn't work
// glClear(GL_STENCIL_BUFFER_BIT);
// glEnable(GL_BLEND);
// glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
// glEnable(GL_DEPTH_TEST);
texture.Bind();
// do these below:
// glActiveTexture(GL_TEXTURE0);
// glBindTexture(GL_TEXTURE_2D, texture.m_texture);
m_shader.enable();
glDrawArrays(GL_TRIANGLES, 0, 3);
m_shader.disable();
// Restore defaults
glBindVertexArray(0);
CHECK_GL_ERRORS;
Here I will also attach my shaders
vertex shader:
#version 330
in vec3 position;
in vec2 atextCoord;
uniform mat4 transform;
out vec2 textCoord;
void main() {
gl_Position = transform * vec4(position, 1.0);
textCoord = atextCoord;
}
And my fragment shader:
#version 330
uniform sampler2D diffuse;
out vec4 fragColor;
in vec2 textCoord;
void main() {
fragColor = vec4(texture(diffuse, textCoord).rgb,1.0) * vec4(textCoord,0.0,1.0);
// texture(...) shows vec4(1,1,1,1)
// radiant colour can only prove my textCoord is working
// fragColor = texture(diffuse, textCoord); <- only shows a default texture
}
here is the running result
Here is the texture image
I found one way to make it work.
I copy every lines in Texture constructor and paste it to draw(), instead calling texture.Bind().
Looks like I make a texture just before it's ready to draw a geometry and this way is working.
But I still have to know why it happens like that. For coding style, I still have to put my code in Texture class. Would you mind to provide a solution that what happened before?
it looks like this right now

OpenGL 3.3 2D Rendering: VAO not properly configured?

I can't seem to get this OpenGL program to render a quad after I add a VAO.
Assuming the program is correctly initialized without errors, the following is the code that fills the VAO.
float quad[] =
{
//verts colors
32.0f, 0.0f, 1.0f, 0.0f, 0.0f, // Top-left
32.0f, 32.0f, 0.0f, 1.0f, 0.0f, // Top-right
0.0f, 32.0f, 0.0f, 0.0f, 1.0f, // Bottom-right
0.0f, 0.0f, 1.0f, 1.0f, 1.0f // Bottom-left
};
float textureCoords[] =
{
0.0f, 0.0f, //x
0.5f, 0.0f, //w
0.5f, 0.5f, //y
0.0f, 0.5f //h
};
float elements[] =
{
0,1,2,
2,3,0
};
//loadShaders compiles and links both shaders
GLuint shaders = loadShaders("vertexShader.c", "fragmentShader.c");
GLuint VAO, VBO[2], EBO;
glGenVertexArrays(1, &VAO);
glGenBuffers(2, VBO);
glGenBuffers(1, &EBO);
//bind VAO
glBindVertexArray(VAO);
glUseProgram(shaders);
//quad and color data
glBindBuffer(GL_ARRAY_BUFFER, VBO[0]);
glBufferData(GL_ARRAY_BUFFER, sizeof(quad), quad, GL_STATIC_DRAW);
GLint quadAttrib = glGetAttribLocation(shaders, "quad");
glEnableVertexAttribArray(quadAttrib);//target 'quad' in shader
glVertexAttribPointer(quadAttrib, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), 0);
//color data
GLint colorAttrib = glGetAttribLocation(shaders, "color");
glEnableVertexAttribArray(colorAttrib);//target 'color' in shader
glVertexAttribPointer(colorAttrib, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), (void*)(2 * sizeof(GLfloat)));
//UV data
glBindBuffer(GL_ARRAY_BUFFER, VBO[1]);
glBufferData(GL_ARRAY_BUFFER, sizeof(textureCoords), textureCoords, GL_STATIC_DRAW);
GLint uvAttrib = glGetAttribLocation(shaders, "uvCoords");//target 'uvCoords' in shaders
glEnableVertexAttribArray(uvAttrib);
glVertexAttribPointer(uvAttrib, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(GLfloat), 0);
//TEXTURES
//laod and use textures
GLuint textures[2];
glGenTextures(2, textures);
int texWidth, texHeigth;
unsigned char *image;
//activate texture 0
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, textures[0]);
image = SOIL_load_image("atlas.png", &texWidth, &texHeigth, 0, SOIL_LOAD_RGB);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, texWidth, texHeigth, 0, GL_RGB, GL_UNSIGNED_BYTE, image);
SOIL_free_image_data(image);
glUniform1i(glGetUniformLocation(shaders, "img1"), 0);
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_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
//element buffer data
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(elements), elements, GL_STATIC_DRAW);
//UNIFORMS
//projection matrix
GLint projectionUniform = glGetUniformLocation(shaders, "projection");
glm::mat4 orthoProjection = glm::ortho( 0.0f, static_cast<float>(480), 0.0f, static_cast<float>(272));
glUniformMatrix4fv(projectionUniform, 1, GL_FALSE, glm::value_ptr(orthoProjection));
//model view projection
GLint modelViewUniform = glGetUniformLocation(shaders, "modelView");
//unbind VAO and current shader, the VAO remembers the bound shader
glBindVertexArray(0);
glUseProgram(0);
I'm assuming that the VAO has now kept track of the following:
The quad buffer 'VBO[0]' and its corresponding attribPointer 'quadAttrib' to "quad" in the shader
The color buffer 'same VBO[0]' and its corresponding attribPointer 'colorAttrib' to 'color' in shader
The UV buffer 'VBO[1]' and its corresponding attribPointer 'uvAttrib' to 'uvCoords' in shader
That the current texture unit (0) corresponds to the loaded texture and the bind to "img1" in the fragment shader as well as its parameters
The EBO that is bounded to GL_ELEMENT_ARRAY_BUFFER
The projection matrix and its uniform
The handler to the model matrix
The shader program that was in use while the VAO was bound? Not sure, I still explicitly use the only shader program in the program
Later in the main loop, if I attempt the following, nothing gets drawn:
// Clear the screen to black
glClearColor(0.2f, 0.0f, 0.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
//draw the quad within this VAO
glBindVertexArray(VAO);
glUseProgram(shaders);
glm::mat4 model;
model = glm::translate(glm::mat4(1.0f), glm::vec3(newTransX, newTransY, newTransZ));
model = glm::scale(model, glm::vec3(newScale));
model = glm::rotate(
model,
(GLfloat)clock() / (GLfloat)CLOCKS_PER_SEC * 10000.0f,
glm::vec3(0.0f, 0.0f, 1.0f)
);
// upload the uniform matrix, modelViewUniform should be already linked to the shader uniform through the VAO
glUniformMatrix4fv(modelViewUniform, 1, GL_FALSE, glm::value_ptr(model));
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
glBindVertexArray(0);
SDL_GL_SwapWindow(window);
Vertex shader:
#version 330
in vec2 quad;
in vec3 color;
in vec2 uvCoords;
out vec3 Color;
out vec2 UVCoords;
uniform mat4 modelView;
uniform mat4 projection;
void main()
{
Color = color;
UVCoords = uvCoords;
gl_Position = projection * modelView * vec4(quad, 0.0f, 1.0f);
}
Fragment shader:
#version 330
in vec3 Color;//not in use, simple pipeline test
in vec2 UVCoords;
out vec4 outColor;
uniform sampler2D img1;
void main()
{
vec4 finalTexture = texture(img1, UVCoords);
outColor = finalTexture;
}
What am I doing wrong? I know for a fact that the values in the modelView and projection matrix are correct, since the program works If I never use a VAO.
Am I assuming that the VAO remembers more than it actually does? If not, what am I doing wrong?
This can't be right:
float elements[] =
{
0,1,2,
2,3,0
};
You can't use floats for vertex indices. Based on the type you pass to glDrawElements(), this should be:
GLuint elements[] =
{
0,1,2,
2,3,0
};
As for the state tracked in a VAO: No, it does not hold on to all that state. It only tracks the vertex attribute setup state. From your list:
The quad buffer 'VBO[0]' and its corresponding attribPointer 'quadAttrib' to "quad" in the shader
Yes. More precisely, the VBO/pointer are associated with the location quadAttrib, and that association is tracked in the VAO. You queried quadAttrib from your shader, but the VAO state does not contain any direct association with the shader.
The color buffer 'same VBO[0]' and its corresponding attribPointer 'colorAttrib' to 'color' in shader
Same here.
The UV buffer 'VBO[1]' and its corresponding attribPointer 'uvAttrib' to 'uvCoords' in shader
And here.
That the current texture unit (0) corresponds to the loaded texture and the bind to "img1" in the fragment shader as well as its parameters
No. That has nothing to do with the vertex attribute state.
The EBO that is bounded to GL_ELEMENT_ARRAY_BUFFER
Yes.
The projection matrix and its uniform
No. The uniform value is part of the program state.
The handler to the model matrix
No.
The shader program that was in use while the VAO was bound?
No.

opengl 3.1 textures not loading

I've been trying to get texturing working under opengl 3.1 on an intel HD graphics 2000/3000 graphics card running on ubuntu 13.04. The issue i'm running into is textures either dont load and the basic triangle i'm trying to texture comes up black, or some color from the texture will get loaded but not the entire image. I get the same outcomes using a raw image file as the source or loading a jpeg with libjpeg.
My shaders are as follows:
Vertex shader
#version 130
in vec3 vert;
in vec2 vertTextCoord;
out vec2 fragTexCoord;
void main(){
fragTexCoord = vertTextCoord;
gl_Position = vec4(vert,1);
}
Fragment shader
#version 130
uniform sampler2D tex;
in vec2 fragTexCoord;
out vec4 finalColor;
void main() {
finalColor = texture(tex, fragTexCoord);
}
code for creating the texture
glGenTextures( 1, &texture);
glBindTexture( GL_TEXTURE_2D, texture);
imgdata image_data = loadRaw("texture.bmp", 256, 256);
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,GL_LINEAR );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,GL_LINEAR );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S,GL_CLAMP_TO_EDGE);
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,GL_CLAMP_TO_EDGE);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 256, 256, 0, GL_RGB, GL_UNSIGNED_BYTE,image_data.data);
and the render function
void display(void){
glClearColor( 1.f, 0.f, 0.f, 0.f);
glClear(GL_COLOR_BUFFER_BIT );
//load program to use
glUseProgram(shaderprogram);
GLint uniform = glGetUniformLocation(shaderprogram, "tex");
if(uniform == -1){
throw std::runtime_error(std::string("program uniform not found: tex"));
}
// bind the texture
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texture);
glUniform1i(uniform, 0);
//load vertex array to use
glBindVertexArray(cubeVAO);
//draw triangle
glDrawArrays(GL_TRIANGLES, 0, 3);
//unbind for next pass
glBindVertexArray(0);
glUseProgram(0);
glfwSwapBuffers();
}
the geometry and texture coordinates
GLfloat data[] = {
//X Y Z U V
0.0f, 0.8f, 0.0f, 0.5f, 1.0f,
-0.8f, -0.8f, 0.0f, 0.0f, 0.0f,
0.8f, -0.8f, 0.0f, 1.0f, 0.0f
};
VBO and VAO being setup
glGenVertexArrays(1, &cubeVAO);
glBindVertexArray(cubeVAO);
glGenBuffers(1, &cubeVBO);
glBindBuffer(GL_ARRAY_BUFFER, cubeVBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
glEnableVertexAttribArray(vertprog);
glVertexAttribPointer(vertprog, 3, GL_FLOAT, GL_FALSE, 5*sizeof(GLfloat), NULL);
glEnableVertexAttribArray(verttexprog);
glVertexAttribPointer(verttexprog, 2, GL_FLOAT, GL_TRUE, 5*sizeof(GLfloat), (const GLvoid*)(3*sizeof(GLfloat)));
glBindVertexArray(0);
You have not shown the code where you determine the value of verttexprog. From the code you have currently, I have to assume that verttexprog (this is a terrible variable name, by the way) is uninitialized.
You should initialize verttexprog to glGetAttribLocation (program, "vertTextCoord"); after you link your program. Likewise, do not query uniform locations each frame, the only time they change is after you (re-)link a GLSL program.
Your texture is being loaded correctly, but your texture coordinates are not. If you want to see this in action, you can replace:
finalColor = texture(tex, fragTexCoord);
with:
finalColor = texture(tex, gl_FragCoord.st);
This is not the behavior you want, but it is a great way to show that your texture is loaded fine.