I am fairly new to OpenGL and i was following this tutorial on Shaders https://learnopengl.com/Getting-started/Textures. I can't get mine to work, as the screen ends up just being entirely black. This code uses glew and glut instead of glfw like in the tutorial.
What is going on?
- I have a list of vertices, which i then store in the VBO, and it's attributes bind by VAO
- Setting vertex attributes in order 3 vertex + 3 colors + 2 tex coords
glEnable(GL_TEXTURE_2D);
- made sure to make
GL_TEXTURE0
active so the next call to glBindTexture(GL_TEXTURE_2D, texture)
is referenced to this texture unit.- I load the texture with
stbi_load
function - Load up texture with
glTexImage2D
with parameters (width
,height
,texture_data
) that was passed on tostbi_load
beforehand as pointers so it loads them. - Create vertex shader, attach source (in VertexShaders.h), compile shader, print shader errors (none show up)
- Create fragment shader, attach source(in FragmentShaders.h), compile shader, print shader errors(none show up)
- Create a shader program (
ourShader
), attach vertex shader and fragment shader. Link "ourShader" program, and again print errors (none show up).
Considerations:
- Projection is made with
gluPerspective
, near clipping plane 0.1 and far 1000 (since it's looking down -z it's shouldn't clipp the object, i also translate the object like soglTranslatef(0, 0, -10)
) - Texture is being loaded (the file existsts, it generates byte data when i load it, as to texture image it is this one (512x512) https://github.com/JoeyDeVries/LearnOpenGL/blob/master/resources/textures/container.jpg
This is myDisplay callback:
void myDisplay(void)
{
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glDisable(GL_DEPTH_TEST);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texture);
glEnable(GL_TEXTURE_2D);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(0, 0, -10);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
glUseProgram(ourShader);
glBindVertexArray(VAO);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
glutSwapBuffers();
}
Main setup
int main(){
//glut initialization stuff...left this out
float vertices[] = {
// positions // colors // texture coords
0.5f, 0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, // top right
0.5f, -0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, // bottom right
-0.5f, -0.5f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, // bottom left
-0.5f, 0.5f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f // top left
};
float texCoords[] = {
0.0f, 0.0f, // lower-left corner
1.0f, 0.0f, // lower-right corner
0.5f, 1.0f // top-center corner
};
unsigned int indices[] = {
0, 1, 3, // first triangle
1, 2, 3 // second triangle
};
//frameBuffer
glGenBuffers(1, &FBO);
glBindFramebuffer(GL_FRAMEBUFFER, FBO);
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
std::cout << "ERROR: Framebuffer not bound" << std::endl;
glBindFramebuffer(GL_FRAMEBUFFER, 0);
//glDeleteFramebuffers(1, &fbo);
//VAO
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);
// Vertex Attributes
glEnableVertexAttribArray(0); //pozicija
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (void*)(0));
glEnableVertexAttribArray(1); //boja
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (void*)(3 * sizeof(GLfloat)));
glEnableVertexAttribArray(2); //boja
glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (void*)(6 * sizeof(GLfloat)));
glEnable(GL_TEXTURE_2D);
glGenTextures(1, &texture);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, 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);
std::string path = "C:\\Projects\\Myproj\\container.jpg";
bool success = loadTexture(path,texture_data,&tex_width, &tex_height, &nchannels);
if (success)
{
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, tex_width, tex_height, 0, GL_RGB, GL_UNSIGNED_BYTE, texture_data);
glGenerateMipmap(GL_TEXTURE_2D);
}
else
{
std::cout << "ERROR::STBI::FAILED TO LOAD TEXTURE" << std::endl;
}
stbi_image_free(texture_data);
int success_f;
char infoLog[512];
vertexShader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertexShader, 1, &vertexShaderSource, NULL);
glCompileShader(vertexShader);
getShaderStatus(vertexShader, &success_f, infoLog);
fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentShader, 1, &fragmentShaderSource, NULL);
glCompileShader(fragmentShader);
getShaderStatus(fragmentShader, &success_f, infoLog);
ourShader = glCreateProgram();
glAttachShader(ourShader, vertexShader);
glAttachShader(ourShader, fragmentShader);
glLinkProgram(ourShader);
getShaderStatus(ourShader, &success_f, infoLog);
glUseProgram(ourShader);
glUniform1i(glGetUniformLocation(ourShader, "ourTexture"), 0);
glDeleteShader(vertexShader);
glDeleteShader(fragmentShader);
glutMainLoop();
}
Vertex Shader
const char* vertexShaderSource =
"#version 330 core\n"
"layout(location = 0) in vec3 aPos;\n"
"layout(location = 1) in vec3 aColor;\n"
"layout(location = 2) in vec2 aTexCoord;\n"
"out vec3 ourColor;\n"
"out vec2 TexCoord;\n"
"void main()\n"
"{\n"
"gl_Position = vec4(aPos, 1.0);\n"
"ourColor = aColor;\n"
"TexCoord = aTexCoord;\n"
"}\n";
Fragment Shader
const char* fragmentShaderSource =
"#version 330 core\n"
"out vec4 FragColor;\n"
"in vec3 ourColor;\n"
"in vec2 TexCoord;\n"
"uniform sampler2D ourTexture;\n"
"void main()\n"
"{\n"
"FragColor = texture(ourTexture, TexCoord);\n"
"}\n";
UPDATE LOG - SOLVED
- Don't need glEnable(GL_TEXTURE_2D) when implementing shader
Projection, View & Model transform go inside the shader, use
glm::projection glm::lookat
Enable attributes (color, texture) before render
- Freeglut support for OpenGL API (>=3.2)
glutInitContextVersion(3, 3);
glutInitContextProfile(GLUT_CORE_PROFILE);
Final code is here : [ https://pastebin.com/D8DgPqaT ]
Psychedelic Shaders: [ https://pastebin.com/vtJ3Cr6i ]
glEnable(GL_TEXTURE_2D);
is deprecated and makes no sens when using a shader. Also using the fixed function matrix stack (glMatrixMode
,glLoadIdentity
, ...) is useless. You have to use Uniform variables (of typemat4
) – Rabbid76