Rendering white box textures in STB/Opengl - c++

Program compiles fine. Quads print. Trying to insert a 32 bit png, but it only prints a white box. What am I doing wrong? I've spent a few days trying to figure it out doing countless tutorials. I don't want to give up.
GLfloat cancelButtonVert[]
{
0.1367f, -0.928f, 0.0f, 0.0f, 0.0f,
0.4833f, -0.928f, 0.0f, 1.0f, 0.0f,
0.4833f, -0.744f, 0.0f, 1.0f, 1.0f,
0.1367f, -0.744f, 0.0f, 0.0f, 1.0f
};
const unsigned int buttonIndices[]
{
0, 1, 2,
2, 3, 0,
};
......
It's all set up with in classes and functions, but I will try to show the whole draw.
.....
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(m_vertices[0]) * 5, 0);
glEnableVertexAttribArray(0);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(m_vertices[0]) * 5, (void*)(sizeof(m_vertices[0]) * 3));
glEnableVertexAttribArray(1);
.....
void Texture::loadTexture()
{
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 *texData = stbi_load(m_fileLocation.c_str(), &m_width, &m_height, &m_bitDepth, 0);
if (!texData)
{
printf("Failed to find: %s\n", m_fileLocation.c_str());
return;
}
glGenTextures(1, &m_textureId);
glBindTexture(GL_TEXTURE_2D, m_textureId);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, m_width, m_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, texData);
glGenerateMipmap(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, 0);
stbi_image_free(texData);
}
void Texture::useTexture()
{
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, m_textureId);
}
shaderList[0].useShader();
uniformModel = shaderList[0].getModelLocation();
uniformTexture = shaderList[0].getUniformTexture();
//Draw Boxes
model = glm::mat4();
model = glm::translate(model, glm::vec3(0.0f, 0.0f, 0.0f));
model = glm::scale(model, glm::vec3(1.0f, 1.0f, 1.0f));
glUniformMatrix4fv(uniformModel, 3, GL_FALSE, glm::value_ptr(model));
cancelButton.useTexture();
glUniform1i(uniformTexture, 0);
meshlist[0]->renderMesh();
The fragment shader.
#version 330
in vec4 vCol;
in vec2 TexCoord;
out vec4 color;
uniform sampler2D theTexture;
void main()
{
color = texture(theTexture, TexCoord);
}
The Vertex Shader.
#version 330
layout (location = 0) in vec3 pos;
layout (location = 1) in vec2 tex;
out vec4 vCol;
out vec2 TexCoord;
uniform mat4 model;
uniform mat4 projection;
void main()
{
gl_Position = projection * model * vec4(pos, 1.0);
vCol = vec4(clamp(pos, 0.0f, 1.0f), 1.0f);
TexCoord = tex;
}

Projection was out of wack. The reason I was getting all of those 1281 and 12 82 GLerrors was the fact that I was calling the wrong vector index, so I could see a draw. I saw a draw and assumed I was heading in the right direction.
If I called what I knew was right, all the drawing happened off screen.
What I did was delete the projection matrix in my shader since all I wanted was a 2d rendering of a gui window with calculated pixel ratios in a calculated position.
I will keep model in the shader if I want to tweak things in the future.
All of your help made me a better programmer. #Rabbid76 all of your suggestions were things I needed to do. Ty all.
Corrected Shader
#version 330
layout (location = 0) in vec3 pos;
layout (location = 1) in vec2 tex;
out vec4 vCol;
out vec2 TexCoord;
uniform mat4 model;
void main()
{
gl_Position = model * vec4(pos, 1.0);
vCol = vec4(clamp(pos, 0.0f, 1.0f), 1.0f);
TexCoord = tex;
}

Related

Why is this texture not showing up?

I am following the tutorial from learnopengl.com to make a game engine.
I am using stb_image.h to load the textures, and my own header file to compile and link the shaders.
I got to the part in Getting Started/Textures where the container.jpg texture is supposed to fill up the rectangle on the window. But whenever I compile and run the code the texture does not appear anywhere in the window. This is my texture loading code:
// Load and create a texture
unsigned int texture1;
glGenTextures(1, &texture1);
glBindTexture(GL_TEXTURE_2D, texture1);
// Set the texture wrapping parameters
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
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);
// Load image, create texture, and generate minmaps
int width, height, nrChannels;
unsigned char* data = stbi_load("C:\\Users\\Lucas\\OneDrive\\Desktop\\C++ Projects\\Working Game Engine\\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);
}
else {
std::cout << "Failed to load texture(s)\n";
}
These are the quad's coords:
float vertices[] = {
// Positions // Colors // Texture Coords
0.5f, 0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f,
0.5f, -0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f,
-0.5f, -0.5f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f,
-0.5f, 0.5f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f
};
unsigned int indices[] = {
0, 1, 3,
1, 2, 3
};
Render code:
// Process inputs
processInput(window);
// Render
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
// Bind Texture
glBindTexture(GL_TEXTURE_2D, texture1);
// Render Container
ourShader.use();
glBindVertexArray(VAO);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
// Swap buffers and poll IO events (Key pressed/released, mouse moved etc.)
glfwSwapBuffers(window);
glfwPollEvents();
Vertex shader code:
#version 460 core
layout (location = 0) in vec3 aPos;
layout (location = 1) in vec3 aColor;
layout (location = 2) in vec2 aTexCoord;
out vec3 ourColor;
out vec2 TexCoord;
void main()
{
gl_Position = vec4(aPos, 1.0);
ourColor = aColor;
TexCoord = vec2(aTexCoord.x, aTexCoord.y);
}
Fragment shader code:
#version 460 core
out vec4 FragColor;
in vec3 ourColor;
in vec2 TexCoord;
uniform sampler2D texture1;
void main()
{
FragColor = texture(texture1, TexCoord);
}
Note that no error codes are returned from the image loader or shader compilers.
The rectangle appears like this.
You need to update the texture1 uniform like this:
glUniform1i(glGetUniformLocation(program_id, "texture1"), 0);
So it turns out I didn't glEnableVertexAttribArray(); the texture coords. Quite embarrassing.

STB Loading png to OpenGl Texture results in black or white backgroud

Hello I've got weird problem with my code, i've been looking for some time on stack and found no answer, there was few similar problems, but they didn't solve anything.
int createTexture(const char* path) {
unsigned int texture;
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);
int width, height, nrChannels;
unsigned char* data = stbi_load(path, &width, &height, &nrChannels, 0);
int colorMode = nrChannels == 3 ? GL_RGB : GL_RGBA;
if (data) {
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, colorMode, GL_UNSIGNED_BYTE, data);
glGenerateMipmap(GL_TEXTURE_2D);
} else {
std::cout << "Failed to load texture" << std::endl;
}
stbi_image_free(data);
return texture;
}
Here i have function loading texture, I choose GL_RGB or GL_RGBA depending on number of channels. I've good results of 3 and 4 channels depending on jpg/png image i use. Anyways i have white background, ( it was black before i edited it in GIMP )
// set the texture wrapping/filtering options (on currently bound 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);
// load and create a texture
// -------------------------
unsigned int texture1 = createTexture("brick.jpg");
unsigned int texture2 = createTexture("grafiti.png");
// Mode
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
// Shader Class
Shader currentShader("vertexShader.glsl", "fragmentShader.glsl");
currentShader.use();
currentShader.setInt("texture1", 0);
currentShader.setInt("texture2", 1);
while (!glfwWindowShouldClose(window)) {
processInput(window);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texture1);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, texture2);
currentShader.use();
glBindVertexArray(VAO);
glDrawElements(GL_TRIANGLES, sizeof(indices) / sizeof(int), GL_UNSIGNED_INT, 0);
glBindVertexArray(0);
glfwSwapBuffers(window);
glfwPollEvents();
}
Then I use this textures together with this shaders
Fragment
#version 330 core
out vec4 FragColor;
in vec3 ourColor;
in vec2 TexCoord;
uniform sampler2D texture1;
uniform sampler2D texture2;
void main()
{
FragColor = mix(texture(texture1, TexCoord), texture(texture2, TexCoord), 1);
}
Vertex
#version 330 core
layout (location = 0) in vec3 aPos;
layout (location = 1) in vec3 aColor;
layout (location = 2) in vec2 aTexCoord;
out vec3 ourColor;
out vec2 TexCoord;
void main()
{
gl_Position = vec4(aPos, 1.0);
ourColor = aColor;
TexCoord = aTexCoord;
}
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
};
unsigned int indices[] = {
0, 1, 3,
1, 2, 3,
};
unsigned int VBO;
glGenBuffers(1, &VBO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
unsigned int VAO;
glGenVertexArrays(1, &VAO);
glBindVertexArray(VAO);
unsigned int EBO;
glGenBuffers(1, &EBO);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)0);
glEnableVertexAttribArray(0);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(3 * sizeof(float)));
glEnableVertexAttribArray(1);
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(6 * sizeof(float)));
glEnableVertexAttribArray(2);
I'm sorry if my english is hideous but it's middle of the night and i'm struggling with this for hours right now
I found solution, enabling blend was not satisfying so i wrote fragmentShader in different way
#version 330 core
out vec4 FragColor;
in vec3 ourColor;
in vec2 TexCoord;
uniform sampler2D texture1;
uniform sampler2D texture2;
void main()
{
vec4 AlphaColor = texture(texture2, TexCoord);
if(AlphaColor.a < 0.1) {
FragColor = texture(texture1, TexCoord);
} else {
FragColor = mix(texture(texture1, TexCoord), AlphaColor, 0.9);
}
}
Right now FragmentShader understands alpha channel and will mix only pixels without alpha

Texture mapping results in solid color of 1 pixel from texture

Beforehand, sorry for a lot of posted code. I will try to be as straightforward as possible.
My texture is 4x4 texture image in bmp format (if someone interested here it is ->). And as a result of mapping i get color of top leftpixel (0.0, 1.0) (i checked it, it is always color of top left pixel) and my triangle color results in color of that pixel, which is white.
I tried changing GL_NEARESTtoGL_LINEAR in GL_TEXTURE_MAG_FILTER
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
and i get bottom right pixel (1.0, 0.0), which is some kind of green:
I am loading texture using stb_image. So in my Texture.cpp:
Texture::Texture(const std::string& fileName)
{
int width, height, numComponents;
unsigned char* imageData = stbi_load(fileName.c_str(), &width, &height, &numComponents, 4);
if (imageData == NULL)
{
std::cerr << "Error: Texture load failed for texture: " << fileName << std::endl;
}
glEnable(GL_TEXTURE_2D);
glGenTextures(1, &_texture);
glBindTexture(GL_TEXTURE_2D, _texture);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, imageData);
stbi_image_free(imageData);
}
Texture::~Texture(void)
{
glDeleteTextures(1, &_texture);
}
void Texture::Bind(unsigned int unit)
{
assert(unit >= 0 && unit <= 31);
glActiveTexture(GL_TEXTURE0 + unit);
glBindTexture(GL_TEXTURE_2D, _texture);
}
In my vertex shader:
#version 150
in vec3 position;
in vec2 texCoord;
out vec2 texCoord0;
void main(void)
{
texCoord0 = texCoord;
gl_Position = vec4(position, 1.0);
}
In my fragment shader:
#version 150
in vec2 textCoord0;
uniform sampler2D texture;
void main(void)
{
gl_FragColor = texture2D(texture, textCoord0);
}
In my main.cpp
#include <iostream>
#include <GL/glew.h>
#include "Display.h"
#include "Shader.h"
#include "Mesh.h"
#include "Texture.h"
int main(int argc, char** argv)
{
Display display(800, 600, " ");
display.Clear(0.0f, 0.15f, 0.3f, 1.0f);
Vertex vertices[] = {
Vertex(glm::vec3(-1.0f, -1.0f, 0.0f), glm::vec2(0.0f, 0.0f)),
Vertex(glm::vec3( 0.0f, 1.0f, 0.0f), glm::vec2(0.5f, 1.0f)),
Vertex(glm::vec3( 1.0f, -1.0f, 0.0f), glm::vec2(1.0f, 0.0f))
};
Texture texture("./res/a.bmp");
Shader shader("./res/testShader");
Mesh mesh(vertices, sizeof(vertices) / sizeof(vertices[0]));
while (display.IsClosed() != true)
{
shader.Bind();
texture.Bind(0);
mesh.Draw();
display.Update();
}
return 0;
}
In Mesh.cpp i am splitting Vertices attributes (glm::vec3 _position and glm::vec2 _texture) into 2 stl vectors and using 2 buffers ("0" - for position of vertex and "1" - for texture) :
Mesh::Mesh(Vertex* vertices, unsigned int numVertices, GLenum usage)
{
_drawCount = numVertices;
glGenVertexArrays(1, &_vertexArrayObject);
glBindVertexArray(_vertexArrayObject);
std::vector<glm::vec3> positions;
std::vector<glm::vec2> texCoords;
positions.reserve(numVertices);
texCoords.reserve(numVertices);
for (unsigned int i = 0; i < numVertices; ++i)
{
positions.push_back(*vertices[i].Position());
texCoords.push_back(*vertices[i].TexCoord());
}
glGenBuffers(NUM_BUFFERS, _vertexArrayBuffers);
glBindBuffer(GL_ARRAY_BUFFER, _vertexArrayBuffers[POSITION_VB]);
glBufferData(GL_ARRAY_BUFFER, numVertices * sizeof(positions[0]), positions.data(), usage);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
glBindBuffer(GL_ARRAY_BUFFER, _vertexArrayBuffers[TEXCOORD_VB]);
glBufferData(GL_ARRAY_BUFFER, numVertices * sizeof(texCoords[0]), texCoords.data(), usage);
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, 0);
glBindVertexArray(0);
}
Mesh::~Mesh(void)
{
glDeleteVertexArrays(1, &_vertexArrayObject);
}
void Mesh::Draw(GLenum mode)
{
glBindVertexArray(_vertexArrayObject);
glDrawArrays(mode, 0, _drawCount);
glBindVertexArray(0);
}
In Shader.cpp i binded atributes like this:
glBindAttribLocation(_program, 0, "position");
glBindAttribLocation(_program, 1, "texCoord");
----------------------------EDIT---------------------------------
After changing vertex shader to:
#version 330 core
layout (location = 0) in vec3 position;
layout (location = 1) in vec2 texCoord;
out vec2 TexCoord;
void main()
{
gl_Position = vec4(position, 1.0f);
TexCoord = texCoord;
}
and fragment shader to:
#version 330 core
in vec2 TexCoord;
out vec4 color;
uniform sampler2D ourTexture;
void main()
{
color = texture(ourTexture, TexCoord);
}
texture is mapped correctly.
But i still want to know why my first solution doesn't work.
But i still want to know why my first solution doesn't work.
Because you're using
#version 330 core
and texture2D is deprecated since version 130
The shader compiler should've warned or errored about that. Check your shader logs via glGetShaderInfoLog and glGetProgramInfoLog.

OpenGL sprite draws in low quality

I am trying to render a sprite using opengl glsl and glm library.
when i render sprite in legacy pipeline using glBegin, glEnd everything is fine but when i use shaders, after rotating sprite its draws in really poor quality as you can see in the picture:
http://sm.uploads.im/t/I3lpf.png
My rendering code:
GLuint p;
GLuint vertex_shader, fragment_shader;
GLuint VBO, VAO;
glm::mat4 projection_matrix = glm::ortho(0.0F, 640.0F, 480.0F, 0.0F, -1.0F, 1.0F);
void sprite_init()
{
p = glCreateProgram();
// LOAD VERTEX SHADER //
std::ifstream vf("E:\\vertex.sh");
std::stringstream vs;
vs << vf.rdbuf();
std::ifstream ff("E:\\fraqment.sh");
std::stringstream fs;
fs << ff.rdbuf();
vertex_shader = glCreateShader(GL_VERTEX_SHADER);
fragment_shader = glCreateShader(GL_FRAGMENT_SHADER);
char* buffer = new char[vs.str().size() + 1];
memcpy(buffer, vs.str().c_str(), vs.str().size() + 1);
glShaderSource(vertex_shader, 1, &buffer, NULL);
free(buffer);
buffer = new char[fs.str().size() + 1];
memcpy(buffer, fs.str().c_str(), fs.str().size() + 1);
glShaderSource(fragment_shader, 1, &buffer, NULL);
free(buffer);
glCompileShader(vertex_shader);
glCompileShader(fragment_shader);
glAttachShader(p, vertex_shader);
glAttachShader(p, fragment_shader);
glLinkProgram(p);
GLfloat vertices[] =
{
// POS // // TEX //
0.0F, 1.0F, 0.0F, 1.0F,
1.0F, 0.0F, 1.0F, 0.0F,
0.0F, 0.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, 1.0F, 0.0F
};
glGenVertexArrays(1, &VAO);
glGenBuffers(1, &VBO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
glBindVertexArray(VAO);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 4 * sizeof(GLfloat), (GLvoid*)0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
}
void sprite_draw()
{
glUseProgram(p);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texture);
glUniform1i(glGetUniformLocation(p, "image"), 0);
// SET MATRIX //
glm::vec2 size = glm::vec2(width, height);
glm::vec2 position = glm::vec2(pos.x - 0.5F * size.x, pos.y - 0.5F * size.y);
glm::vec3 col = glm::vec3(1.0F, 1.0F, 1.0F);
glm::mat4 model_matrix;
model_matrix = glm::translate(model_matrix, glm::vec3(position, 0.0f));
model_matrix = glm::translate(model_matrix, glm::vec3(0.5F * size.x, 0.5F * size.y, 0.0f));
model_matrix = glm::rotate(model_matrix, glm::radians(rotate), glm::vec3(0.0f, 0.0f, 1.0f));
model_matrix = glm::translate(model_matrix, glm::vec3(-0.5F * size.x, -0.5F * size.y, 0.0f));
model_matrix = glm::scale(model_matrix, glm::vec3(size, 1.0F));
glUniformMatrix4fv(glGetUniformLocation(p, "projection"), 1, GL_FALSE, glm::value_ptr(projection_matrix));
glUniformMatrix4fv(glGetUniformLocation(p, "model"), 1, GL_FALSE, glm::value_ptr(model_matrix));
glUniform3f(glGetUniformLocation(p, "spriteColor"), col.x, col.y, col.z);
glBindVertexArray(VAO);
glDrawArrays(GL_TRIANGLES, 0, 6);
glBindVertexArray(0);
glUseProgram(0);
}
Vertex Shader:
#version 330 core
layout (location = 0) in vec4 vertex; // <vec2 position, vec2 texCoords>
out vec2 TexCoords;
uniform mat4 model;
uniform mat4 projection;
void main()
{
TexCoords = vertex.zw;
gl_Position = projection * model * vec4(vertex.xy, 0.0, 1.0);
}
Fragment Shader:
#version 330 core
in vec2 TexCoords;
out vec4 color;
uniform sampler2D image;
uniform vec3 spriteColor;
void main()
{
color = vec4(spriteColor, 1.0) * texture(image, TexCoords);
}
Texture setup:
unsigned int texture;
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
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_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
this->textures.push_back(texture);
Thanks
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
You should use GL_LINEAR filtering, not GL_NEAREST.

OpenGL Shadow Map

I am trying to do a basic shadow map but for some reason, It doesn't render properly.
Video of the Problem
I render the house using a flat shader:
int shadowMapWidth = WINDOW_SIZE_X * (int)SHADOW_MAP_RATIO;
int shadowMapHeight = WINDOW_SIZE_Y * (int)SHADOW_MAP_RATIO;
// Rendering into the shadow texture.
glActiveTexture(GL_TEXTURE0);
CALL_GL(glBindTexture(GL_TEXTURE_2D, shadowTexture));
// Bind the framebuffer.
CALL_GL(glBindFramebuffer(GL_FRAMEBUFFER, shadowFBO));
//Clear it
CALL_GL(glClear(GL_DEPTH_BUFFER_BIT));
CALL_GL(glViewport(0, 0, shadowMapWidth, shadowMapHeight));
CALL_GL(glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE));
//Render stuff
flatShader.use();
flatShader["baseColor"] = glm::vec4(1.0f,1.0f,1.0f,1.0f);
flatShader["pvm"] = projectionMatrix*pointLight.viewMatrix*cursor.modelMatrix;
cursor.draw(); //binds the vao and draws
// Revert for the scene.
CALL_GL(glBindFramebuffer(GL_FRAMEBUFFER, 0));
CALL_GL(glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE));
CALL_GL(glViewport(0, 0, WINDOW_SIZE_X, WINDOW_SIZE_Y));
Notice that I only render the house. I don't render the floor in the depth-buffer pass.
Following this I render the quad that represents the floor using the following shader pair:
/* [VERT] */
#version 330
in vec3 in_Position;
in vec2 in_TexCoord;
uniform mat4 shadowMatrix;
uniform mat4 mvp;
out vec2 UV;
out vec4 shadowProj;
void main()
{
gl_Position = mvp*vec4(in_Position,1.0);
shadowProj = shadowMatrix*vec4(in_Position,1.0);
UV = in_TexCoord;
}
And the Fragment Shader:
/* [FRAG] */
#version 330
in vec2 UV;
in vec4 shadowProj;
out vec4 fragColor;
uniform sampler2D texturex;
uniform sampler2DShadow shadowMap;
void main()
{
fragColor = vec4(texture(texturex, UV).rgb,1);
float shadow = 1.0;
shadow = textureProj(shadowMap,shadowProj);
fragColor *= shadow;
}
I then draw the house again in color and ... the floor:
textureShader.use();
glUniform1i(baseImageLoc, 0); //Texture unit 0 is for base images.
glUniform1i(shadowMapLoc, 1); //Texture unit 1 is for shadow maps.
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, floorTexture);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, shadowTexture);
textureShader["shadowMatrix"] = projectionMatrix*pointLight.viewMatrix*floorMatrix;
textureShader["mvp"] = projectionMatrix*viewMatrix*floorMatrix;
CALL_GL(glBindVertexArray(floorVAO));
CALL_GL(glDrawArrays(GL_TRIANGLES,0,18));
glfwSwapBuffers();
Has anybody seen this behavior before? Any idea what could be wrong? By the way, the light's coordinates place it directly on top of the house so the shadow should be directly below the house on the floor (but it ends up sideways).
For reference here is how I generate the shadow FBO:
int shadowMapWidth = WINDOW_SIZE_X * (int)SHADOW_MAP_RATIO;
int shadowMapHeight = WINDOW_SIZE_Y * (int)SHADOW_MAP_RATIO;
glGenTextures(1, &shadowTexture);
glBindTexture(GL_TEXTURE_2D, shadowTexture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, shadowMapWidth, shadowMapHeight, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, 0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, GL_LESS);
glTexImage2D(GL_TEXTURE_2D,0,GL_DEPTH_COMPONENT,shadowMapWidth,shadowMapHeight,0,GL_DEPTH_COMPONENT,GL_FLOAT,NULL);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_COMPARE_MODE,GL_COMPARE_R_TO_TEXTURE);
glBindTexture(GL_TEXTURE_2D, 0); //unbind the texture
glGenFramebuffers(1, &shadowFBO);
glBindFramebuffer(GL_FRAMEBUFFER, shadowFBO);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, shadowTexture, 0);
glDrawBuffer(GL_NONE);
glReadBuffer(GL_NONE);
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
{ printf("GL_FRAMEBUFFER_COMPLETE error 0x%x", glCheckFramebufferStatus(GL_FRAMEBUFFER)); }
glClearDepth(1.0f); glEnable(GL_DEPTH_TEST);
// Needed when rendering the shadow map. This will avoid artifacts.
glPolygonOffset(1.0f, 0.0f); glBindFramebuffer(GL_FRAMEBUFFER, 0);
//to convert the texture coordinates to -1 ~ 1
GLfloat biasMatrixf[] = {
0.5f, 0.0f, 0.0f, 0.0f,
0.0f, 0.5f, 0.0f, 0.0f,
0.0f, 0.0f, 0.5f, 0.0f,
0.5f, 0.5f, 0.5f, 1.0f };
biasMatrix = glm::make_mat4(biasMatrixf);
It looks like you forgot to multiply your shadow matrix by the bias matrix.