Using OpenGL core profile, I'm trying to create a texture that fills the screen and displays a white square in the middle of the texture.
#include <SDL2/SDL.h>
#include "glad/glad.h"
#define SIMPLE_VERTEX_SHADER "#version 330 core \n \
layout (location = 0) in vec3 aPos; \n \
layout (location = 1) in vec2 aTexCoord; \n \
out vec2 TexCoord; \n \
void main() { \n \
gl_Position = vec4(aPos, 1.0f); \n \
TexCoord = vec2(aTexCoord.x, aTexCoord.y); \n \
}\n\0"
#define SIMPLE_FRAGMENT_SHADER "#version 330 core \n \
out vec4 FragColor; \n \
in vec3 ourColor; \n \
in vec2 TexCoord; \n \
uniform sampler2D tex; \n \
void main() { \n \
FragColor = texture(tex, TexCoord); \n \
}\n\0"
int main(int argv, char** args) {
SDL_Window *window;
SDL_GLContext glcontext;
if (SDL_Init(SDL_INIT_VIDEO)) {
printf("Unable to initialise SDL: %s\n", SDL_GetError());
SDL_Quit();
exit(1);
}
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3);
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
int screen_width, screen_height;
screen_height = screen_width = 500;
window = SDL_CreateWindow("Texture Test", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, screen_width, screen_height, SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN);
if (!window) {
printf("Unable to create window: %s\n", SDL_GetError());
SDL_Quit();
exit(1);
}
glcontext = SDL_GL_CreateContext(window);
SDL_GL_SetSwapInterval(1);
if (!gladLoadGLLoader((GLADloadproc)SDL_GL_GetProcAddress))
{
printf("Failed to initialize GLAD\n");
}
const GLchar* vertexShaderSource = SIMPLE_VERTEX_SHADER;
GLuint vertexShader;
vertexShader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertexShader, 1, &vertexShaderSource, NULL);
glCompileShader(vertexShader);
int success;
char infoLog[512];
glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &success);
if (!success)
{
glGetShaderInfoLog(vertexShader, 512, NULL, infoLog);
printf("ERROR::SHADER::VERTEX::COMPILATION_FAILED\n%s\n", infoLog);
}
const GLchar* fragmentShaderSource = SIMPLE_FRAGMENT_SHADER;
GLuint fragmentShader;
fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentShader, 1, &fragmentShaderSource, NULL);
glCompileShader(fragmentShader);
glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &success);
if (!success)
{
glGetShaderInfoLog(fragmentShader, 512, NULL, infoLog);
printf("ERROR::SHADER::FRAGMENT::COMPILATION_FAILED\n%s\n", infoLog);
}
GLuint shaderProgram;
shaderProgram = glCreateProgram();
glAttachShader(shaderProgram, vertexShader);
glAttachShader(shaderProgram, fragmentShader);
glLinkProgram(shaderProgram);
glGetProgramiv(shaderProgram, GL_LINK_STATUS, &success);
if (!success) {
glGetProgramInfoLog(shaderProgram, 512, NULL, infoLog);
printf("ERROR::SHADER::PROGRAM::LINKING_FAILED\n%s\n", infoLog);
}
glDeleteShader(vertexShader);
glDeleteShader(fragmentShader);
GLfloat vertices[] = {
1.0f, 1.0f, 0.0f, 1.0, 0.0f,
1.0f, -1.0f, 0.0f, 1.0, 1.0f,
-1.0f, -1.0f, 0.0f, 0.0, 1.0f,
-1.0f, 1.0f, 0.0f, 0.0, 0.0f
};
GLfloat indices[] = {
0, 1, 3,
1, 2, 3
};
bool running;
running = true;
GLuint VAO, VBO, EBO;
SDL_Surface* surface;
SDL_Event e;
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);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), (void*)0);
glEnableVertexAttribArray(0);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), (GLvoid*)(3 * sizeof(GLfloat)));
glEnableVertexAttribArray(1);
glBindVertexArray(0);
GLuint texture;
glGenTextures(1, &texture);
surface = SDL_CreateRGBSurface(0, screen_width, screen_height, 32, 0, 0, 0, 0);
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
SDL_GL_SwapWindow(window);
while(running) {
while(SDL_PollEvent(&e)) {
if (e.type == SDL_QUIT) {
running = false;
}
if (e.type == SDL_KEYDOWN)
{
switch (e.key.keysym.sym)
{
case SDLK_ESCAPE:
running = false;
break;
default:
break;
}
}
}
if (SDL_MUSTLOCK(surface)) {
SDL_LockSurface(surface);
}
uint8_t* pixel_data = (uint8_t*)surface->pixels;
for (int y = screen_height * 0.25; y < screen_height * 0.75; ++y) {
for (int x = screen_width * 0.25; x < screen_width * 0.75; ++x) {
pixel_data[4 * (y * surface -> w + x) + 0] = 0xFF;
pixel_data[4 * (y * surface -> w + x) + 1] = 0xFF;
pixel_data[4 * (y * surface -> w + x) + 2] = 0xFF;
pixel_data[4 * (y * surface -> w + x) + 3] = 0xFF;
}
}
if (SDL_MUSTLOCK(surface)) {
SDL_UnlockSurface(surface);
}
glBindTexture(GL_TEXTURE_2D, texture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, screen_width, screen_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, surface->pixels);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glBindTexture(GL_TEXTURE_2D, 0);
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
glUseProgram(shaderProgram);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texture);
glUniform1i(glGetUniformLocation(shaderProgram, "tex"), 0);
glBindVertexArray(VAO);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
glBindVertexArray(0);
glUseProgram(0);
SDL_GL_SwapWindow(window) ;
}
SDL_GL_DeleteContext(glcontext);
SDL_DestroyWindow(window);
SDL_Quit();
return 0;
}
It displays a white screen when it opens (as though I set the clear colour to white), and then it changes to a black screen almost immediately, and then stays like that.
I'm clearly doing something wrong, but I cannot work out. I get the feeling that my shaders are the problem. But I don't know for sure.
Is someone able to give me a pointer on what I'm doing wrong?
Thanks.
Indices defined as
GLfloat indices[] = {
0, 1, 3,
1, 2, 3
};
However, indices must be integer. Later when drawing it is said indices are GLuint:
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
And float bits are interpreted as uint, giving invalid values like 1065353216, 1077936128, ..., which greatly exceeds vertex buffer size.
Define indices as GLuint (or uint32_t).
I am adding an answer based on keltar's answer in the comment to take this question out of the unanswered tab. If keltar answers I will delete my answer.
The issue is that the vertex attributes are qualified as floats in the lines:
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), (void*)0);
glEnableVertexAttribArray(0);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), (GLvoid*)(3 * sizeof(GLfloat)));
glEnableVertexAttribArray(1);
But the texture is expecting unsigned bytes:
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, screen_width, screen_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, surface->pixels);
So changing the vertex attributes fixes the problem.
Related
I am trying to display a texture, but for some reason it's not shown correctly it's distorted.
This is my source code:
#include <glad/glad.h>
#include <GLFW/glfw3.h>
#include <iostream>
#define STB_IMAGE_IMPLEMENTATION
#include "stb_image.h"
void processInput(GLFWwindow *window)
{
if(glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
glfwSetWindowShouldClose(window, true);
}
void framebuffer_size_callback(GLFWwindow* window, int width, int height)
{
glViewport(0, 0, width, height);
}
int main(void)
{
int success;
char infoLog[512];
glfwInit();
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
GLFWwindow* window = glfwCreateWindow(800, 600, "LearnOpenGL", NULL, NULL);
if (window == NULL)
{
std::cout << "Failed to create GLFW window" << std::endl;
glfwTerminate();
return -1;
}
glfwMakeContextCurrent(window);
if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
{
std::cout << "Failed to initialize GLAD" << std::endl;
return -1;
}
glViewport(0, 0, 800, 600);
glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);
const char *vertexShaderSource = "#version 330 core\n"
"layout (location = 0) in vec3 aPos;\n"
"layout (location = 1) in vec2 aTexCoord;\n"
"out vec2 TexCoord;\n"
"void main()\n"
"{\n"
" gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0);\n"
"TexCoord = aTexCoord;"
"}\0";
unsigned int vertexShader;
vertexShader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertexShader, 1, &vertexShaderSource, NULL);
glCompileShader(vertexShader);
glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &success);
if(!success)
{
glGetShaderInfoLog(vertexShader, 512, NULL, infoLog);
std::cout << "ERROR::SHADER::VERTEX::COMPILATION_FAILED\n" << infoLog << std::endl;
}
const char* fragmentShaderSource = "#version 330 core\n"
"out vec4 FragColor;\n"
"in vec2 TexCoord;\n"
"uniform sampler2D ourTexture;\n"
"void main()\n"
"{\n"
"FragColor = texture(ourTexture, TexCoord);\n"
"}\0";
unsigned int fragmentShader;
fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentShader, 1, &fragmentShaderSource, NULL);
glCompileShader(fragmentShader);
glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &success);
if(!success)
{
glGetShaderInfoLog(vertexShader, 512, NULL, infoLog);
std::cout << "ERROR::SHADER::VERTEX::COMPILATION_FAILED\n" << infoLog << std::endl;
}
unsigned int shaderProgram;
shaderProgram = glCreateProgram();
glAttachShader(shaderProgram, vertexShader);
glAttachShader(shaderProgram, fragmentShader);
glLinkProgram(shaderProgram);
glGetProgramiv(shaderProgram, GL_LINK_STATUS, &success);
if(!success) {
glGetProgramInfoLog(shaderProgram, 512, NULL, infoLog);
}
float vertices[] = {
//positions //texture coords
1.0f, 1.0f, 0.0f, 1.0f, 1.0f,// top right
1.0f, -1.0f, 0.0f, 1.0f, 0.0f,// bottom right
-1.0f, -1.0f, 0.0f, 0.0f, 0.0f,// bottom left
-1.0f, 1.0f, 0.0f, 0.0f, 1.0f// top left
};
unsigned int indices[] = {
0, 1, 3, // first triangle
1, 2, 3 // second triangle
};
unsigned int VBO;
unsigned int EBO;
unsigned int VAO;
glGenVertexArrays(1, &VAO);
glGenBuffers(1, &EBO);
glGenBuffers(1, &VBO);
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);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)0);
glEnableVertexAttribArray(0);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)(3 * sizeof(float)));
glEnableVertexAttribArray(1);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
unsigned int texture;
glGenTextures(1, &texture);
//glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_TEXTURE_WRAP_S);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_TEXTURE_WRAP_T);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
int width, height, nrChannels;
stbi_set_flip_vertically_on_load(1);
unsigned char *data = stbi_load("../asd.jpg", &width, &height,&nrChannels, 0);
if (data)
{
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, data);
glGenerateMipmap(GL_TEXTURE_2D);
}
else
{
if(stbi_failure_reason())
std::cout << stbi_failure_reason();
}
while(!glfwWindowShouldClose(window))
{
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
glBindTexture(GL_TEXTURE_2D, texture);
glUseProgram(shaderProgram);
glBindVertexArray(VAO);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
processInput(window);
glfwSwapBuffers(window);
glfwPollEvents();
}
glDeleteShader(vertexShader);
glDeleteShader(fragmentShader);
glfwTerminate();
return 0;
}
Result:
Expected result:
I checked all coordinates and positions and everything looks correct. I have no idea why the texture is not shown correctly.
The vertex and fragment shaders also seems to be correct.
By default OpenGL assumes that the start of each row of an image is aligned to 4 bytes. This is because the GL_UNPACK_ALIGNMENT parameter by default is 4. Since the image has 3 color channels (GL_RGB), and is tightly packed the size of a row of the image may not be aligned to 4 bytes.
When a RGB image with 3 color channels is loaded to a texture object and 3*width is not divisible by 4, GL_UNPACK_ALIGNMENT has to be set to 1, before specifying the texture image with glTexImage2D:
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, data);
I'm trying to render JPG image using "stb_image.h" library. Im using GLEW and GLFW, here is the code:
#include "glew.h"
#include "glfw3.h"
#include <iostream>
#define STB_IMAGE_IMPLEMENTATION
#include "stb_image.h"
#define WIDTH 800
#define HEIGHT 600
void framebuffer_size_callback(GLFWwindow* window, int width, int height);
int main(){
GLFWwindow *window;
if (!glfwInit())
{
std::cout << "Failed to Init GLFW" << std::endl;
return -1;
}
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
window = glfwCreateWindow(WIDTH, HEIGHT, "OpenGL CPP", NULL, NULL);
if (!window)
{
std::cout << "Failed to create GLFW Window" << std::endl;
glfwTerminate();
return -1;
}
glfwMakeContextCurrent(window);
glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);
GLenum err = glewInit();
if (GLEW_OK != err)
{
std::cout << "Failed to Init GLEW" << std::endl;
glfwTerminate();
return -1;
}
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 indices[] = {
0, 1, 3, // first triangle
1, 2, 3 // second triangle
};
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 = vec2(aTexCoord.x, aTexCoord.y);\n"
"}\0";
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\0";
unsigned int vertexShader;
vertexShader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertexShader, 1, &vertexShaderSource, NULL);
glCompileShader(vertexShader);
int success;
char infoLog[512];
glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &success);
if (!success)
{
glGetShaderInfoLog(vertexShader, 512, NULL, infoLog);
std::cout << "ERROR COMPILING VERTEX SHADER" << infoLog << std::endl;
}
unsigned int fragmentShader;
fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentShader, 1, &fragmentShaderSource, NULL);
glCompileShader(fragmentShader);
glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &success);
if (!success)
{
glGetShaderInfoLog(fragmentShader, 512, NULL, infoLog);
std::cout << "ERROR COMPILING FRAGMENT SHADER" << infoLog << std::endl;
}
unsigned int shaderProgram;
shaderProgram = glCreateProgram();
glAttachShader(shaderProgram, vertexShader);
glAttachShader(shaderProgram, fragmentShader);
glLinkProgram(shaderProgram);
glDeleteShader(vertexShader);
glDeleteShader(fragmentShader);
unsigned int 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);
// position attribute
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)0);
glEnableVertexAttribArray(0);
// color attribute
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(3 * sizeof(float)));
glEnableVertexAttribArray(1);
// texture coord attribute
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(6 * sizeof(float)));
glEnableVertexAttribArray(2);
unsigned int texture;
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);
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);
// set texture filtering parameters
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
int width, height, nrChannels;
unsigned char *data = stbi_load("C:/Users/user3/Documents/cppopengl/res/container.jpg", &width, &height, &nrChannels, 0);
if (data)
{
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, data);
glGenerateMipmap(GL_TEXTURE_2D);
std::cout << "data loaded successfully"<< std::endl;
}
else
{
std::cout << "Failed to load texture" << std::endl;
}
stbi_image_free(data);
glUseProgram(shaderProgram);
//std::cout << glGetUniformLocation(shaderProgram, "ourTexture") << std::endl;
glUniform1i(glGetUniformLocation(shaderProgram, "ourTexture"), 0);
while (!glfwWindowShouldClose(window))
{
err = glGetError();
glClearColor(0.5, 0.5, 0.5, 1);
glClear(GL_COLOR_BUFFER_BIT);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texture);
glUseProgram(shaderProgram);
glBindVertexArray(VAO);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
glfwPollEvents();
if (((err = glGetError()) != GL_NO_ERROR))
{
std::cout << err << std::endl;
}
}
glDeleteShader(vertexShader);
glDeleteShader(fragmentShader);
glDeleteProgram(shaderProgram);
return 0;
}
void framebuffer_size_callback(GLFWwindow* window, int width, int height)
{
glViewport(0, 0, width, height);
}
Code compiles just fine, without errors and warnings. When I start the executable it shows white screen. Both vertex shader and fragment shader compile and link without errors. stbi_load() does not return error and glGetError() does not return error, glGetUniformLocation() returns uniform location just fine. Can you please help me out? Thanks in advance.
EDIT:
indices must be unsigned int instead of float, thanks #Rabbid76
unsigned int indices[] = {
0, 1, 3, // first triangle
1, 2, 3 // second triangle
};
This is an error that appears when trying to load the texture:
This is my working directory:
Down below is the location of my texture images
I tried adding a texture to a triangle however something seems to go wrong. When trying to run debug there is no error and no warning however it shows an grey window with no triangle and no texture whatsoever. Here is a part of my code, what is wrong?
#include <iostream>
#include <fstream>
#include <string>
#include <sstream>
#define GLEW_STATIC
#include "GL/glew.h"
#include "GLFW/glfw3.h"
#include "SOIL2/SOIL2.h"
int glWindowWidth = 640;
int glWindowHeight = 480;
int retina_width, retina_height;
GLFWwindow* glWindow = NULL;
GLfloat vertexCoordinates[] = {
//position //color //texture
0.5f,0.5f,0.0f, 1.0f,0.0f,0.0f, 1.0f ,1.0f,
0.5f,-0.5f,0.0f, 1.0f,1.0f,1.0f, 1.0f,0.0f
-0.5f,-0.5f,0.0f, 1.0f,0.0f,0.0f, 0.0f ,0.0f,
-0.5f,0.5f,0.0f, 1.0f,0.0f,1.0f, 0.0f ,1.0f,
};
GLuint indices[] =
{
0,1,2,
1,2,3
};
GLuint verticesVBO;
GLuint triangleVAO;
GLuint EBO;
GLuint triangleVAO2;
GLuint verticesVBO2;
GLuint shaderProgram;
GLuint shaderProgram2;
void windowResizeCallback(GLFWwindow* window, int width, int height)
{
fprintf(stdout, "window resized to width: %d , and height: %d\n", width, height);
//TODO
}
void initObjects()
{
//genereaza un ID unic pentru verticesVBO
glGenBuffers(1, &verticesVBO);
glGenBuffers(1, &EBO);
glGenVertexArrays(1, &triangleVAO);
glBindBuffer(GL_ARRAY_BUFFER, verticesVBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertexCoordinates), vertexCoordinates, GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
//genereaza un ID unic, care corespunde obiectului triangleVAO
glBindVertexArray(triangleVAO);
glBindBuffer(GL_ARRAY_BUFFER, verticesVBO);
//seteaza pointer-ul atributelor de varf
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8*sizeof(GLfloat), (GLvoid *)0);
glEnableVertexAttribArray(0);
//color attribute
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (GLvoid*)(3*sizeof(GLfloat)));
glEnableVertexAttribArray(1);
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (GLvoid*)(6 * sizeof(GLfloat)));
glEnableVertexAttribArray(2);
//de-selecteaza obiectul triangleVAO
glBindVertexArray(0);
}
bool initOpenGLWindow()
{
if (!glfwInit()) {
fprintf(stderr, "ERROR: could not start GLFW3\n");
return false;
}
//for Mac OS X
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 1);
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
glfwWindowHint(GLFW_RESIZABLE,GL_FALSE);
glWindow = glfwCreateWindow(glWindowWidth, glWindowHeight, "OpenGL Shader Example", NULL, NULL);
if (!glWindow) {
fprintf(stderr, "ERROR: could not open window with GLFW3\n");
glfwTerminate();
return false;
}
glfwSetWindowSizeCallback(glWindow, windowResizeCallback);
glfwMakeContextCurrent(glWindow);
glfwWindowHint(GLFW_SAMPLES, 4);
// start GLEW extension handler
glewExperimental = GL_TRUE;
glewInit();
// get version info
const GLubyte* renderer = glGetString(GL_RENDERER); // get renderer string
const GLubyte* version = glGetString(GL_VERSION); // version as a string
printf("Renderer: %s\n", renderer);
printf("OpenGL version supported %s\n", version);
//for RETINA display
glfwGetFramebufferSize(glWindow, &retina_width, &retina_height);
return true;
}
void renderScene()
{
//initializeaza buffer-ele de culoare si adancime inainte de a rasteriza cadrul curent
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
//defineste culoarea de fundal
glClearColor(0.8, 0.8, 0.8, 1.0);
//specifica locatia si dimensiunea ferestrei
glViewport(0, 0, retina_width, retina_height);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
if (glfwGetKey(glWindow, GLFW_KEY_D)) {
//TODO
}
//activeaza program shader-ul; apeluri ulterioare de rasterizare vor utiliza acest program
glUseProgram(shaderProgram); /**/
//activeaza VAO
glBindVertexArray(triangleVAO);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
glBindVertexArray(0);
//specifica tipul primitiei, indicele de inceput si numarul de indici utilizati pentru rasterizare
//glDrawArrays(GL_TRIANGLES, 0, 3);
//glDrawArrays(GL_TRIANGLES, 0, 3); /**/
}
std::string readShaderFile(std::string fileName)
{
std::ifstream shaderFile;
std::string shaderString;
//open shader file
shaderFile.open(fileName);
std::stringstream shaderStringStream;
//read shader content into stream
shaderStringStream << shaderFile.rdbuf();
//close shader file
shaderFile.close();
//convert stream into GLchar array
shaderString = shaderStringStream.str();
return shaderString;
}
void shaderCompileLog(GLuint shaderId)
{
GLint success;
GLchar infoLog[512];
//check compilation info
glGetShaderiv(shaderId, GL_COMPILE_STATUS, &success);
if (!success)
{
glGetShaderInfoLog(shaderId, 512, NULL, infoLog);
std::cout << "Shader compilation error\n" << infoLog << std::endl;
}
}
void shaderLinkLog(GLuint shaderProgramId)
{
GLint success;
GLchar infoLog[512];
//check linking info
glGetProgramiv(shaderProgramId, GL_LINK_STATUS, &success);
if (!success) {
glGetProgramInfoLog(shaderProgram, 512, NULL, infoLog);
std::cout << "Shader linking error\n" << infoLog << std::endl;
}
}
GLuint initBasicShader(std::string vertexShaderFileName, std::string fragmentShaderFileName, GLuint shaderProgram)
{
//read, parse and compile the vertex shader
std::string v = readShaderFile(vertexShaderFileName);
const GLchar* vertexShaderString = v.c_str();
GLuint vertexShader;
vertexShader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertexShader, 1, &vertexShaderString, NULL);
glCompileShader(vertexShader);
//check compilation status
shaderCompileLog(vertexShader);
//read, parse and compile the vertex shader
std::string f = readShaderFile(fragmentShaderFileName);
const GLchar* fragmentShaderString = f.c_str();
GLuint fragmentShader;
fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentShader, 1, &fragmentShaderString, NULL);
glCompileShader(fragmentShader);
//check compilation status
shaderCompileLog(fragmentShader);
//attach and link the shader programs
shaderProgram = glCreateProgram();
glAttachShader(shaderProgram, vertexShader);
glAttachShader(shaderProgram, fragmentShader);
glLinkProgram(shaderProgram);
glDeleteShader(vertexShader);
glDeleteShader(fragmentShader);
//check linking info
shaderLinkLog(shaderProgram);
return shaderProgram;
}
int main(int argc, const char * argv[]) {
initOpenGLWindow();
initObjects();
shaderProgram = initBasicShader("shaders/shader.vert", "shaders/shader.frag",shaderProgram);
shaderProgram2 = initBasicShader("shaders/shader2.vert", "shaders/shader2.frag",shaderProgram2);
int width, height;
GLuint texture;
glGenTextures(1, &texture);
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);
unsigned char* image = SOIL_load_image("res/images/image1.jpg", &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);
SOIL_free_image_data(image);
glBindTexture(GL_TEXTURE_2D, 0);
while (!glfwWindowShouldClose(glWindow)) {
glActiveTexture(GL_TEXTURE0);
glfwPollEvents();
renderScene();
glBindTexture(GL_TEXTURE_2D, texture);
glUniform1i(glGetUniformLocation(shaderProgram, "diffuseTexture"), 0);
glBindVertexArray(triangleVAO);
glfwSwapBuffers(glWindow);
}
//close GL context and any other GLFW resources
glfwTerminate();
return 0;
}
This is the fragment shader
#version 400
in vec3 colour;
in vec2 passTexture;
out vec4 fragmentColour;
uniform sampler2D dif;
void main() {
fragmentColour = texture(dif, passTexture);
}
This is the vertex shader:
#version 400
layout(location = 0) in vec3 vertexPosition;
layout(location = 1) in vec3 vertexNormal;
layout(location = 2) in vec2 textcoord;
out vec3 colour;
out vec2 passTexture;
uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;
void main() {
colour = vertexNormal;
passTexture = textcoord;
gl_Position = projection * view * model * vec4(vertexPosition, 1.0);
}
By default all fields of the matrices in the vertex are shader are initialized by 0.0.
To make the code run you've to skip the matrices:
gl_Position = vec4(vertexPosition, 1.0);
Or initialize them by the Identity matrix in renderScene:
GLint model_loc = glGetUniformLocation(shaderProgram, "model");
GLint view_loc = glGetUniformLocation(shaderProgram, "view");
GLint proj_loc = glGetUniformLocation(shaderProgram, "projection");
GLint tex_loc = glGetUniformLocation(shaderProgram, "diffuseTexture");
float identity_matrix[] = {1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1};
Note, uniforms have to be set, after the program is installed by glUseProgram.
glUseProgram(shaderProgram);
glUniformMatrix4fv(model_loc, 1, GL_FALSE, identity_matrix);
glUniformMatrix4fv(view_loc, 1, GL_FALSE, identity_matrix);
glUniformMatrix4fv(proj_loc, 1, GL_FALSE, identity_matrix);
glUniform1i(tex_loc, 0); // unnecessary, because 0 is default.
Since the Index buffers is stated in the Vertex Array Object, the VAO has to be bound, before the index buffer can be bound:
glGenVertexArrays(1, &triangleVAO);
glBindVertexArray(triangleVAO);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
Set all the necessary states, and bind the necessary objects, before you do the draw call.
The viewport rectangle and the clear color should be set before glClear.
The texture should be bound before the mesh is drawn.
while (!glfwWindowShouldClose(glWindow)) {
glfwPollEvents();
renderScene();
glfwSwapBuffers(glWindow);
}
void renderScene()
{
glViewport(0, 0, retina_width, retina_height);
glClearColor(0.8, 0.8, 0.8, 1.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texture);
glBindVertexArray(triangleVAO);
glUseProgram(shaderProgram);
// set the uniforms as described above
// [...]
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
}
Furthermore there is missing a comma (,) int the 2nd row of the array of vertex array attributes and the indices do not form a quad. Change it:
GLfloat vertexCoordinates[] = {
//position //color //texture
0.5f, 0.5f,0.0f, 1.0f,0.0f,0.0f, 1.0f ,1.0f,
0.5f,-0.5f,0.0f, 1.0f,1.0f,1.0f, 1.0f ,0.0f,
-0.5f,-0.5f,0.0f, 1.0f,0.0f,0.0f, 0.0f ,0.0f,
-0.5f, 0.5f,0.0f, 1.0f,0.0f,1.0f, 0.0f ,1.0f,
};
GLuint indices[] = { 0,1,2, 0,2,3 };
Finally, if you want to use mipmaping, then the texture minification filter has to be one of GL_NEAREST_MIPMAP_NEAREST, GL_LINEAR_MIPMAP_NEAREST, GL_NEAREST_MIPMAP_LINEAR or GL_LINEAR_MIPMAP_LINEAR.
Full code:
#include <iostream>
#include <fstream>
#include <string>
#include <sstream>
#define GLEW_STATIC
#include "GL/glew.h"
#include "GLFW/glfw3.h"
#include "SOIL2/SOIL2.h"
int glWindowWidth = 640;
int glWindowHeight = 480;
int retina_width, retina_height;
GLFWwindow* glWindow = NULL;
GLfloat vertexCoordinates[] = {
//position //color //texture
0.5f, 0.5f,0.0f, 1.0f,0.0f,0.0f, 1.0f ,1.0f,
0.5f,-0.5f,0.0f, 1.0f,1.0f,1.0f, 1.0f ,0.0f,
-0.5f,-0.5f,0.0f, 1.0f,0.0f,0.0f, 0.0f ,0.0f,
-0.5f, 0.5f,0.0f, 1.0f,0.0f,1.0f, 0.0f ,1.0f,
};
GLuint indices[] = { 0,1,2, 0,2,3 };
GLuint verticesVBO;
GLuint triangleVAO;
GLuint EBO;
GLuint triangleVAO2;
GLuint verticesVBO2;
GLuint shaderProgram;
GLuint shaderProgram2;
GLuint texture;
GLint model_loc, view_loc, proj_loc, tex_loc;
float identity_matrix[] = {1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1};
void windowResizeCallback(GLFWwindow* window, int width, int height)
{
fprintf(stdout, "window resized to width: %d , and height: %d\n", width, height);
//TODO
}
void initObjects()
{
//genereaza un ID unic pentru verticesVBO
glGenBuffers(1, &verticesVBO);
glGenBuffers(1, &EBO);
glGenVertexArrays(1, &triangleVAO);
glBindVertexArray(triangleVAO);
glBindBuffer(GL_ARRAY_BUFFER, verticesVBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertexCoordinates), vertexCoordinates, GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
//genereaza un ID unic, care corespunde obiectului triangleVAO
glBindBuffer(GL_ARRAY_BUFFER, verticesVBO);
//seteaza pointer-ul atributelor de varf
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8*sizeof(GLfloat), (GLvoid *)0);
glEnableVertexAttribArray(0);
//color attribute
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (GLvoid*)(3*sizeof(GLfloat)));
glEnableVertexAttribArray(1);
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (GLvoid*)(6 * sizeof(GLfloat)));
glEnableVertexAttribArray(2);
//de-selecteaza obiectul triangleVAO
glBindVertexArray(0);
}
bool initOpenGLWindow()
{
if (!glfwInit()) {
fprintf(stderr, "ERROR: could not start GLFW3\n");
return false;
}
//for Mac OS X
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 1);
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
glfwWindowHint(GLFW_RESIZABLE,GL_FALSE);
glWindow = glfwCreateWindow(glWindowWidth, glWindowHeight, "OpenGL Shader Example", NULL, NULL);
if (!glWindow) {
fprintf(stderr, "ERROR: could not open window with GLFW3\n");
glfwTerminate();
return false;
}
glfwSetWindowSizeCallback(glWindow, windowResizeCallback);
glfwMakeContextCurrent(glWindow);
glfwWindowHint(GLFW_SAMPLES, 4);
// start GLEW extension handler
glewExperimental = GL_TRUE;
glewInit();
// get version info
const GLubyte* renderer = glGetString(GL_RENDERER); // get renderer string
const GLubyte* version = glGetString(GL_VERSION); // version as a string
printf("Renderer: %s\n", renderer);
printf("OpenGL version supported %s\n", version);
//for RETINA display
glfwGetFramebufferSize(glWindow, &retina_width, &retina_height);
return true;
}
void renderScene()
{
glViewport(0, 0, retina_width, retina_height);
glClearColor(0.8, 0.8, 0.8, 1.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texture);
glBindVertexArray(triangleVAO);
if (glfwGetKey(glWindow, GLFW_KEY_D)) {
//TODO
}
glUseProgram(shaderProgram);
glUniformMatrix4fv(model_loc, 1, GL_FALSE, identity_matrix);
glUniformMatrix4fv(view_loc, 1, GL_FALSE, identity_matrix);
glUniformMatrix4fv(proj_loc, 1, GL_FALSE, identity_matrix);
glUniform1i(tex_loc, 0); // unnecessary, because 0 is default.
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
}
std::string readShaderFile(std::string fileName)
{
std::ifstream shaderFile;
std::string shaderString;
//open shader file
shaderFile.open(fileName);
std::stringstream shaderStringStream;
//read shader content into stream
shaderStringStream << shaderFile.rdbuf();
//close shader file
shaderFile.close();
//convert stream into GLchar array
shaderString = shaderStringStream.str();
return shaderString;
}
void shaderCompileLog(GLuint shaderId)
{
GLint success;
GLchar infoLog[512];
//check compilation info
glGetShaderiv(shaderId, GL_COMPILE_STATUS, &success);
if (!success)
{
glGetShaderInfoLog(shaderId, 512, NULL, infoLog);
std::cout << "Shader compilation error\n" << infoLog << std::endl;
}
}
void shaderLinkLog(GLuint shaderProgramId)
{
GLint success;
GLchar infoLog[512];
//check linking info
glGetProgramiv(shaderProgramId, GL_LINK_STATUS, &success);
if (!success) {
glGetProgramInfoLog(shaderProgram, 512, NULL, infoLog);
std::cout << "Shader linking error\n" << infoLog << std::endl;
}
}
GLuint initBasicShader(std::string vertexShaderFileName, std::string fragmentShaderFileName, GLuint shaderProgram)
{
//read, parse and compile the vertex shader
std::string v = readShaderFile( vertexShaderFileName );
const GLchar* vertexShaderString = v.c_str();
GLuint vertexShader;
vertexShader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertexShader, 1, &vertexShaderString, NULL);
glCompileShader(vertexShader);
//check compilation status
shaderCompileLog(vertexShader);
//read, parse and compile the vertex shader
std::string f = readShaderFile( fragmentShaderFileName );
const GLchar* fragmentShaderString = f.c_str();
GLuint fragmentShader;
fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentShader, 1, &fragmentShaderString, NULL);
glCompileShader(fragmentShader);
//check compilation status
shaderCompileLog(fragmentShader);
//attach and link the shader programs
shaderProgram = glCreateProgram();
glAttachShader(shaderProgram, vertexShader);
glAttachShader(shaderProgram, fragmentShader);
glLinkProgram(shaderProgram);
glDeleteShader(vertexShader);
glDeleteShader(fragmentShader);
//check linking info
shaderLinkLog(shaderProgram);
return shaderProgram;
}
int main(int argc, const char * argv[]) {
initOpenGLWindow();
initObjects();
shaderProgram = initBasicShader("shaders/shader.vert", "shaders/shader.frag",shaderProgram);
model_loc = glGetUniformLocation(shaderProgram, "model");
view_loc = glGetUniformLocation(shaderProgram, "view");
proj_loc = glGetUniformLocation(shaderProgram, "projection");
tex_loc = glGetUniformLocation(shaderProgram, "diffuseTexture");
shaderProgram2 = initBasicShader("shaders/shader2.vert", "shaders/shader2.frag",shaderProgram2);
int width, height;
glGenTextures(1, &texture);
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_MIPMAP_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
unsigned char* image = SOIL_load_image("SOIL2/res/images/image1.jpg", &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);
SOIL_free_image_data(image);
glBindTexture(GL_TEXTURE_2D, 0);
while (!glfwWindowShouldClose(glWindow)) {
glfwPollEvents();
renderScene();
glfwSwapBuffers(glWindow);
}
//close GL context and any other GLFW resources
glfwTerminate();
return 0;
}
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
//genereaza un ID unic, care corespunde obiectului triangleVAO
glBindVertexArray(triangleVAO);
You need to bind the vertex array object before you bind the index buffer, so you need to swap this around.
Edit: The vertex array bind needs to go above
glBindBuffer(GL_ARRAY_BUFFER, verticesVBO);
as well.
I try to give a data to uniform variable from c++,but the variable is always 0;
Who can help me. I use shader compiler.There is no error in shader
c++ code vbo and vao in this function,I try to give a matrix,but it got error,so i try to give a point like a GLfloat first. I didn't give create and compile shader code,because i am sure that is correct.
void initVBO()
{
// Create and populate the buffer objects
GLuint vboHandles[4];
glGenBuffers(3, vboHandles);
GLuint positionBufferHandle = vboHandles[0];
GLuint colorBufferHandle = vboHandles[1];
GLuint textureBufferHandle = vboHandles[2];
GLuint mvphandle = vboHandles[3];
glBindBuffer(GL_ARRAY_BUFFER, positionBufferHandle);
glBufferData(GL_ARRAY_BUFFER, sizeof(positionData),
positionData, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, colorBufferHandle);
glBufferData(GL_ARRAY_BUFFER, sizeof(colorData),
colorData, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, textureBufferHandle);
glBufferData(GL_ARRAY_BUFFER, 6 * sizeof (float),
texCoords, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, mvphandle);
glBufferData(GL_ARRAY_BUFFER, sizeof(g_vertex_buffer_data),
g_vertex_buffer_data, GL_STATIC_DRAW);
GLuint ebo;
glGenBuffers(1, &ebo);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(elements), elements, GL_STATIC_DRAW);
glGenVertexArrays(1, &vaoHandle);
glBindVertexArray(vaoHandle);
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
glEnableVertexAttribArray(2); //texture
glBindBuffer(GL_ARRAY_BUFFER, positionBufferHandle);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (GLubyte *)NULL);
glBindBuffer(GL_ARRAY_BUFFER, colorBufferHandle);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, (GLubyte *)NULL);
glBindBuffer(GL_ARRAY_BUFFER, textureBufferHandle);
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 0, (GLubyte *)NULL);
errno_t err;
// Data read from the header of the BMP file
unsigned char header[54];
unsigned int dataPos;
unsigned int imageSize;
//unsigned int width, height;
// Actual RGB data
unsigned char * data;
int width, height, nrChannels;
//data = SOIL_load_image("wall.bmp", &width, &height, 0, SOIL_LOAD_RGB);
FILE * file;
const char imagepath[] = "sample.bmp";
if (err = fopen_s(&file, imagepath, "rb")){ printf("%s could not be opened. Are you in the right directory ? Don't forget to read the FAQ !\n", imagepath); }
if (fread(header, 1, 54, file) != 54){
printf("Not a correct BMP file\n");
}
// A BMP files always begins with "BM"
if (header[0] != 'B' || header[1] != 'M'){
printf("Not a correct BMP file\n");
}
// Make sure this is a 24bpp file
if (*(int*)&(header[0x1E]) != 0) { printf("Not a correct BMP file\n"); }
if (*(int*)&(header[0x1C]) != 24) { printf("Not a correct BMP file\n"); }
dataPos = *(int*)&(header[0x0A]);
imageSize = *(int*)&(header[0x22]);
width = *(int*)&(header[0x12]);
height = *(int*)&(header[0x16]);
printf("width : %d hight : %d\n", width, height);
data = new unsigned char[imageSize];
// Read the actual data from the file into the buffer
fread(data, 1, imageSize, file);
// Everything is in memory now, the file wan be closed
fclose(file);
GLuint textureID;
glGenTextures(1, &textureID);
// "Bind" the newly created texture : all future texture functions will modify this texture
glBindTexture(GL_TEXTURE_2D, textureID);
// Give the image to OpenGL
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_BGR, GL_UNSIGNED_BYTE, data);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, textureID);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, data);
//glUniform1i(glGetUniformLocation(fShader, "tex"), 0);
// Poor filtering, or ...
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
// ... nice trilinear filtering.
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
//GLuint MatrixID = glGetUniformLocation(vShader, "p");
//glUniformMatrix4fv(MatrixID, 1, GL_FALSE, glm::value_ptr(trans));
//glUniform1f(MatrixID, 1.0);
}
void init()
{
GLenum err = glewInit();
if (GLEW_OK != err)
{
cout << "Error initializing GLEW: " << glewGetErrorString(err) << endl;
}
initShader("vert.txt", "frag.txt");
initVBO();
//glClearDepth(1.0f);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LEQUAL);
//glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
glClearColor(1.0, 1.0, 1.0, 1.0);
glShadeModel(GL_SMOOTH);
}
void display()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glm::mat4 Projection = glm::perspective(glm::radians(45.0f), (float)600 / (float)600, 0.0f, 10.0f);
glm::mat4 View = glm::lookAt(
glm::vec3(0, 0, 10), // Camera is at (4,3,3), in World Space
glm::vec3(0, 0, 0), // and looks at the origin
glm::vec3(0, 1, 0) // Head is up (set to 0,-1,0 to look upside-down)
);
glm::mat4 Model = glm::mat4(1.0f);
glm::mat4 mvp = Projection * View * Model;
glm::mat4 trans = glm::mat4(1.0f);
trans = glm::rotate(
trans,
glm::radians(180.0f),
glm::vec3(0.0f, 0.0f, 1.0f)
);
glm::mat4 test = glm::mat4(1.0f);
test[0][0] = 1;
test[1][1] = 1;
test[2][2] = 1;
//test[1][3] = 0.5;
test[3][3] = 1;
GLfloat aaa[4][4] = {0.0f};
aaa[0][0] = 1;
aaa[1][1] = 1;
aaa[2][2] = 1;
aaa[3][3] = 1;
cout << "test[2][2] = " << trans[0][0] << endl;
//glGetActiveUniform();
GLuint MatrixID = glGetUniformLocation(vShader, "mvp");
if (MatrixID > 0)cout << "Loacation = "<<MatrixID << endl;
else cout << "fail" << endl;
//glUniform1f(glGetUniformLocation(vShader, "test"), 1.0);
GLfloat a = 1.0f;
GLint asize;
//glGetActiveUniform(vShader, MatrixID, 1, NULL, &asize, NULL, NULL);
glUniformMatrix4fv(MatrixID, 1, GL_FALSE, glm::value_ptr(trans));
MatrixID = glGetUniformLocation(vShader, "p");
glUniform1f(MatrixID, 10);
glBindVertexArray(vaoHandle);
glDrawArrays(GL_TRIANGLES, 0, 3);
glBindVertexArray(0);
glutSwapBuffers();
}
void Reshape(int w, int h)
{
if (h == 0)
h = 1;
glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(45, (float)w / (float)h, 0, 10);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
void keyboard(unsigned char key, int x, int y)
{
switch (key)
{
case 27:
glDeleteShader(vShader);
glUseProgram(0);
exit(0);
break;
}
}
int main(int argc, char ** argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB |GLUT_DEPTH);
glutInitWindowSize(600, 600);
glutInitWindowPosition(100, 100);
glutCreateWindow("GLSL Test : Draw a triangle");
glutReshapeFunc(Reshape);
init();
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LESS);
glutDisplayFunc(display);
glutKeyboardFunc(keyboard);
glutMainLoop();
return 0;
}
fragment code
#version 400
uniform float p;
in vec3 Color;
in vec2 texcoord;
out vec4 FragColor
uniform sampler2D tex;
uniform vec3 bbb;
uniform mat4 mvp;
void main()
{
if(p==0)
FragColor = vec4(1.0,0.0,0.0, 1.0);
else
FragColor = vec4(mvp[0][0],Color.y,Color.z, 1.0);
//texture(tex, vec2(1-texcoord.x,texcoord.y))*
}
version and my uniform location
OpenGL 4.6 API Compatibility Profile Specification; 7.6. UNIFORM VARIABLE; page 134:
To determine the set of active uniform variables used by a program, applications can query the properties and active resources of the UNIFORM interface of a program.
Additionally, several dedicated commands are provided to query properties of
active uniforms.
int GetUniformLocation( uint program, const char *name );
A uniform variable is a program resource. This means the parameter for glGetUniformLocation has to be a successfully linked program object (glCreateProgram) and not a shader object (glCreateShader).
Create a program object:
GLuint prog = glCreateProgram();
Attach the shader objects:
glAttachShader(prog, vShader);
....
Link the program:
glLinkProgram(prog);
GLint status;
glGetProgramiv(prog, GL_LINK_STATUS, &status);
if ( status == GL_FALSE )
..... // error handling
Get the uniform location:
GLuint location_p = glGetUniformLocation(prog, "p");
"Use" the program:
glUseProgram(prog);
Set the uniform:
glUniform1f(location_p, 10);
This question already has an answer here:
OpenGL texture tilted
(1 answer)
Closed 1 year ago.
I'm trying to upload a texture in OpenGL but the texture is crooked.
#include <iostream>
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <glm/glm.hpp>
#include <SOIL/SOIL.h>
#define GLSL(version, shader) "#version " #version "\n" #shader
const char * vertShader = GLSL(430,
in vec2 position;
in vec2 texcoord;
out vec2 coordinates;
void main() {
coordinates = texcoord;
gl_Position = vec4(position, 0.0, 1.0);
}
);
const char * fragShader = GLSL(430,
in vec2 coordinates;
out vec4 color;
uniform sampler2D texture;
void main() {
color = texture(texture, coordinates);
}
);
int main(int argc, char ** argv)
{
if (not glfwInit())
{
std::cerr << "Failed to initialize GLFW" << std::endl;
return -1;
}
GLFWwindow *window;
window = glfwCreateWindow(720, 480, "Textures", 0, 0);
if (not window)
{
std::cerr << "Failed to open GLFW window" << std::endl;
glfwTerminate();
return -1;
}
glfwMakeContextCurrent(window);
glewExperimental = true;
if (glewInit() != GLEW_OK)
{
std::cerr << "Failed to initialize GLEW" << std::endl;
return -1;
}
glfwSetInputMode(window, GLFW_STICKY_KEYS, GL_TRUE);
GLuint vao;
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
GLuint vbo;
glGenBuffers(1, &vbo);
GLfloat vertices[] = {
-1.0f, +1.0f, 0.0f, 0.0f,
+1.0f, +1.0f, 1.0f, 0.0f,
+1.0f, -1.0f, 1.0f, 1.0f,
-1.0f, -1.0f, 0.0f, 1.0f,
};
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);
GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertexShader, 1, &vertShader, 0);
glCompileShader(vertexShader);
GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentShader, 1, &fragShader, NULL);
glCompileShader(fragmentShader);
GLuint shaderProgram = glCreateProgram();
glAttachShader(shaderProgram, vertexShader);
glAttachShader(shaderProgram, fragmentShader);
glLinkProgram(shaderProgram);
glUseProgram(shaderProgram);
GLint posAttrib = glGetAttribLocation(shaderProgram, "position");
GLint texAttrib = glGetAttribLocation(shaderProgram, "texcoord");
glVertexAttribPointer(posAttrib, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), 0);
glEnableVertexAttribArray(posAttrib);
glVertexAttribPointer(texAttrib, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), (void *)(2 * sizeof(float)));
glEnableVertexAttribArray(texAttrib);
GLuint tex;
glGenTextures(1, &tex);
glBindTexture(GL_TEXTURE_2D, tex);
int width, height;
unsigned char * image = SOIL_load_image("happyface.png", &width, &height, 0, SOIL_LOAD_RGB);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, image);
SOIL_free_image_data(image);
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);
do {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
glfwPollEvents();
glfwSwapBuffers(window);
} while (glfwGetKey(window, GLFW_KEY_ESCAPE) != GLFW_PRESS
&& glfwWindowShouldClose(window) == 0);
glDeleteTextures(1, &tex);
glDeleteProgram(shaderProgram);
glDeleteShader(fragmentShader);
glDeleteShader(vertexShader);
glDeleteBuffers(1, &ebo);
glDeleteBuffers(1, &vbo);
glDeleteVertexArrays(1, &vao);
glfwTerminate();
return 0;
}
What am I doing wrong? As you can see the texture is crooked and repeating, but the texture is just one smiley face.
That is the result:
And that is the texture:
I'm no OpenGL guru, but some graphics systems require textures that are multiples of 2 or 4 pixels wide.
Your texture is 479 wide - add another column of pixels and I think you'll be fine.