I'm following this tutorial step by step and I even copy-pasted the entire code but it still fails to load the texture. Here's my code, the parts that concern the question:
GLuint texture;
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture); // All upcoming GL_TEXTURE_2D operations now have effect on this texture object
// Set the texture wrapping parameters
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); // Set texture wrapping to GL_REPEAT (usually basic 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);
// Load image, create texture and generate mipmaps
int width, height;
unsigned char* image = SOIL_load_image("container.jpg", &width, &height, 0, SOIL_LOAD_RGB);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, image);
glGenerateMipmap(GL_TEXTURE_2D);
SOIL_free_image_data(image);
glBindTexture(GL_TEXTURE_2D, 0); // Unbind texture when done, so we won't accidentily mess up our texture.
And here are my shaders:
#version 330 core
in vec3 ourColor;
in vec2 TexCoord;
out vec4 color;
uniform sampler2D ourTexture;
void main()
{
color = texture(ourTexture, TexCoord);
}
And
#version 330 core
layout (location = 0) in vec3 position;
layout (location = 1) in vec3 color;
layout (location = 2) in vec2 texCoord;
out vec3 ourColor;
out vec2 TexCoord;
void main()
{
gl_Position = vec4(position, 1.0f);
ourColor = color;
TexCoord = texCoord;
}
I'm using SOIL to load image data. Is it too outdated? What should I do?
The tutorial code you are following seems to be wrong since it does not call glActiveTexture nor glUniform. See the game loop code of the other file at end of the tutorial.
Maybe you are missing something like this:
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texture);
glUniform1i(glGetUniformLocation(ourShader.Program, "ourTexture"), 0);
Related
I'm making a 3d game using OpenGL and I have encountered a problem I can't find the answer to. For some reason, when I load the textures it is still interpolated.
My image loading:
glGenTextures(1, &chunkTex);
glBindTexture(GL_TEXTURE_2D, chunkTex);
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_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glBindTexture(GL_TEXTURE_2D, 0);
int width, height, chan;
stbi_set_flip_vertically_on_load(true);
unsigned char *data = stbi_load("res/images/atlas.png", &width, &height, &chan, 0);
if (data)
{
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE,
data);
glGenerateMipmap(GL_TEXTURE_2D);
} else {
std::cout << "Failed to load texture" << std::endl;
}
stbi_image_free(data);
My vertex shader:
#version 330 core
in vec3 aPos;
in vec3 aColor;
in vec3 aNormal;
in vec2 uv;
uniform mat4 mvp;
out vec3 ourColor;
out vec2 puv;
out vec3 pNormal;
void main()
{
gl_Position = mvp * vec4(aPos, 1.0);
ourColor = aColor;
puv = uv;
pNormal = aNormal;
}
My fragment shader:
#version 330 core
out vec4 col;
in vec3 ourColor;
in vec2 puv;
in vec3 pNormal;
uniform sampler2D tex;
uniform vec3 lightDir;
void main()
{
col = texture(tex, puv) * max(dot(pNormal, -lightDir), 0.1);
}
If you could help me fix this I would appreciate it!
Edit: Here are my window hints:
glfwInit();
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
#ifdef __APPLE__
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
#endif
Here you create a nex texture object and set the texture parameters for it:
glGenTextures(1, &chunkTex);
glBindTexture(GL_TEXTURE_2D, chunkTex);
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_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
But here you unbind it and bind texture object 0 instead:
glBindTexture(GL_TEXTURE_2D, 0);
and load the texture image to that one:
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
glGenerateMipmap(GL_TEXTURE_2D);
Now, in legacy and compatibility profile GL, texture object 0 even exists (actually, there even do exist different texture objects named 0 for different texture types), and is usable. But for that one, you never have set the texture filters and will use the default ones. And it looks like you keep textur eobject 0 bound also for rendering, and not the (empty and incomplete) chunkTex one.
I am trying to implement a color picking algorithm, so I render my entities with a unique color on a different Framebuffer, so I can then query that Framebuffer on the pixel my mouse is on (using glReadPixels) and select the entity under the mouse cursor.
This works fine on my integrated Intel HD Graphics 4600. I am able to read back the exact value I sent on the GPU.
However running the application using my Nvidia GTX 860M, the results are not consistent. A few random pixels have the original color but most of them have the color a bit altered.
The same thing happens on another computer that has a Geforce 8600 GT.
I tried running it using NSight Graphics, which allows me to view the memory of the Textures.
The arrow points to the correct pixel color. I would expect every pixel to have the same color.
I use this union to create a unique color...
union u_picking_color {
struct s_entity *ep;
glm::vec3 color;
};
then I query the Framebuffer like this:
struct s_entity *Renderer::GetEntity(int x, int y) {
union u_picking_color picking_color = { 0 };
m_picking_fbo.SetReadTarget();
glReadPixels(x, y, 1, 1, GL_RGB, GL_FLOAT, &picking_color.color);
return picking_color.ep;
}
here are the API calls used to create the Framebuffer:
glGenFramebuffers(1, &m_frameBufferId);
glBindFramebuffer(GL_FRAMEBUFFER, m_frameBufferId);
glGenTextures(1, &m_colorTextureId);
glBindTexture(GL_TEXTURE_2D, m_colorTextureId);
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_RGBA32F, width, height, 0, GL_RGBA, GL_FLOAT, nullptr);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_colorTextureId, 0);
glGenTextures(1, &m_depthTextureId);
glBindTexture(GL_TEXTURE_2D, m_depthTextureId);
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_DEPTH_COMPONENT24, width, height, 0, GL_DEPTH_COMPONENT, GL_FLOAT, nullptr);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, m_depthTextureId, 0);
Also, here are the shaders used to draw on the framebuffer. They do not change the color. They only pass it through the pipeline.
Vertex:
#version 330 core
layout(location = 0) in vec3 v_Position;
//layout(location = 1) in vec3 v_Normal;
//layout(location = 2) in vec4 v_Color;
layout(location = 3) in vec3 v_PickingColor;
out vec4 color;
uniform mat4 u_ViewProjection;
void main()
{
color = vec4(v_PickingColor, 1);
gl_Position = u_ViewProjection * vec4(v_Position.x, v_Position.y, v_Position.z, 1.0f);
}
Fragment:
#version 330 core
out vec4 fragColor;
in vec4 color;
void main()
{
fragColor = color;
}
I tried disabling GL_BLEND and GL_DITHER with no success.
Turns out, even though I was using the same colour per-vertex, I should have used the 'flat' keyword on my shaders to prevent interpolation and avoid precision errors.
Vertex Shader:
flat out vec4 color;
Fragment Shader:
flat in vec4 color;
I'm trying to add a texture to my square displayed on the screen, but after i've done all the code the square is still white, and I cant figure out what's wrong, I think I might be missing something after I've loaded the texture.
this is the code I use for creating the texture:
void textureManager::createTexture(const char* fileName) {
GLuint textureID = SOIL_load_OGL_texture(fileName, SOIL_LOAD_AUTO, SOIL_CREATE_NEW_ID, SOIL_FLAG_INVERT_Y);
if (0 == textureID) {
cout << "error" << endl;
}
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, textureID);
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);
}
And I call this function after the vertex and index buffer data, before the shaders compile
this is my vertex and fragment shader code:
#version 430
in layout(location = 0) vec2 position;
in layout(location = 1) vec2 texCoord;
out vec2 vertex_texCoord;
void main()
{
gl_Position = vec4(position, 0.0, 1.0);
vertex_texCoord = texCoord;
}
#version 430
out vec4 fragmentColor;
in vec2 vertex_texCoord;
uniform sampler2d textureSampler;
void main()
{
fragmentColor = texture(textureSampler, vertex_texCoord);
}
can someone help me please
Your shaders look fine. You are making the GLuint id too. Hm, are you sending it to the shader in your drawcall?
It should look something like this:
glBindTexture(GL_TEXTURE_2D, textureID); //texture uniform
and be called when you fill the vbos before the final draw.
A few day ago i applied the latest Window 8.1 update to my Laptop, when restarting as part of the process i got a bluescreen and so did i when i tried to manually restart etc. In the end i had to do the partial reset (it removes anything windows recognizes as an app but leaves your data intact) you are offered because i could not lose the data.
Before that incident my code for displaying textured and animated models worked but after that i got new errors from my GLSL compilers because of deprecated keywords. When those were fixed my program won't show me textures and instead just display everything black.
I have 2 older projects using the same glsl code and they also have the same problem (although they did not have any deprecated keywords in the shader).
The code worked like this ~2 hours before i did the update.
Initialising:
void TestWindow::initialize()
{
initSkybox();
initVAO();
initVBO();
m_program = new QOpenGLShaderProgram(this);
m_program->addShaderFromSourceFile(QOpenGLShader::Vertex ,"../Qt_Flyff_1/Simple_VertexShader.vert");
m_program->addShaderFromSourceFile(QOpenGLShader::Fragment ,"../Qt_Flyff_1/Simple_FragmentShader.frag");
m_program->link();
qDebug("log: %s",m_program->log().toStdString().c_str());
m_posAttr = m_program->attributeLocation("position");
m_texPos = m_program->attributeLocation("texcoord");
m_colorUniform = m_program->uniformLocation("color");
m_matrixUniform = m_program->uniformLocation("matrix");
int asdf=m_program->uniformLocation("tex");
GLuint tex;
glGenTextures(1, &tex);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, tex);
QImage img("../skybox01_big.png");
glTexImage2D(GL_TEXTURE_2D, 0, GL_BGRA, img.width(), img.height(), 0, GL_BGRA, GL_UNSIGNED_BYTE, img.bits());
glGenerateMipmap(GL_TEXTURE_2D);
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_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR_MIPMAP_NEAREST);
glEnable(GL_DEPTH_TEST);
// glEnable(GL_CULL_FACE);
glClearColor(0.5,0.5,0.5,1.0);
m_program->setUniformValue(asdf,0);
}
Vertex Shader:
#version 400 core
uniform mediump mat4 matrix;
uniform mediump vec3 color;
in vec4 position;
in vec2 texcoord;
out vec3 Color;
out vec2 Texcoord;
void main()
{
Color = color;
Texcoord = texcoord;
gl_Position = matrix*position;
}
Fragment Shader:
#version 400 core
in vec3 Color;
in vec2 Texcoord;
out vec4 outColor;
uniform sampler2D tex;
void main()
{
outColor = texture(tex, Texcoord) * vec4(Color, 1.0);
}
I've also compared my code to various tutorials and could not find any difference.
When simply using "outColor = vec4(Color,1.0)" my model is completly white as expected and when displaying the texture coordinates as color i also get the expected results.
In case it matters my Laptop has a GeForce GT 740M.
Ok i found the solution.
What i didn't know is that there is a difference between internalformat and format for glTexImage2D.
The format specifies what the data you send to the GPU looks like and the internalformat is what the GPU uses internally and this allows less formats. My texture was stored as BGRA in the memory but OpenGL does not allow that format.
Basicly i had to change:
glTexImage2D(GL_TEXTURE_2D, 0, GL_BGRA, img.width(), img.height(), 0, GL_BGRA, GL_UNSIGNED_BYTE, img.bits());
to
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, img.width(), img.height(), 0, GL_BGRA, GL_UNSIGNED_BYTE, img.bits());
(3rd parameter from GL_BGRA to GL_RGBA)
Info on what types can be used for internalformat can be found here:
https://www.opengl.org/sdk/docs/man/html/glTexImage2D.xhtml
I've been trying to add SSAO (based on the tutorial here: http://john-chapman-graphics.blogspot.co.nz/2013/01/ssao-tutorial.html) to a project of mine and I've gotten stuck on rendering the depth correctly.
I have created a framebuffer texture to draw the depth to each frame. The texture itself looks correct when I draw it to a quad but I can't figure out how to correctly apply it to the whole scene.
Here's what the regular scene looks like:
And here's the applied depth texture:
Currently in my fragment shader I just use my regular texture coordinates (TexCoord0) to draw the depth texture. I'm guessing I need to change this but I don't have a clue what to change it to.
Here's the relevant fragment shader code:
#version 330 core
in vec2 TexCoord0;
smooth in vec3 vNormal;
smooth in vec3 vWorldPos;
in mat4 ProjectionMatrix;
uniform sampler2D uDepthTex;
layout(location = 0) out vec4 FragColor;
void main()
{
FragColor = texture(uDepthTex, TexCoord0);
}
I'm at a bit of a loss as to how to fix this. I've read a lot of sample code online which seems to use regular texture coordinates to draw the depth.
EDIT:
Here's my framebuffer setup code:
glGenFramebuffers(1, &ssaoFramebufferID);
glBindFramebuffer(GL_FRAMEBUFFER, ssaoFramebufferID);
glGenTextures(1, &ssaoDepthTextureID);
glBindTexture(GL_TEXTURE_2D, ssaoDepthTextureID);
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT24, 1024, 1024, 0, GL_DEPTH_COMPONENT, GL_FLOAT, 0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
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_COMPARE_MODE, GL_NONE);
glFramebufferTexture(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, ssaoDepthTextureID, 0);
glDrawBuffer(GL_NONE);
glReadBuffer(GL_NONE);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
And the depth pass code I call each frame before regular draw:
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glBindTexture(GL_TEXTURE_2D, 0);
glBindFramebuffer(GL_FRAMEBUFFER, ssaoFramebufferID);
glViewport(0, 0, 1024, 1024);
depthShader.Bind();
depthShader.SetUniformMatrixfv("depthMVP", camera.GetViewMatrix() * Matrix4::Perspective(60, aspectRatio, 0.1f, 10.0f));
DrawScene(true);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glViewport(0, 0, width, height);
My depth shaders, vertex:
#version 330 core
layout(location = 0) in vec3 Position;
uniform mat4 depthMVP;
void main() {
gl_Position = depthMVP * vec4(Position, 1.0);
}
fragment:
#version 330 core
layout(location = 0) out float fragmentdepth;
void main() {
fragmentdepth = gl_FragCoord.z;
}
EDIT2:
The glClear call where it currently is gives me a completely black texture. Putting it below the first glViewport call gives the depth image I displayed above though:
glBindTexture(GL_TEXTURE_2D, 0);
glBindFramebuffer(GL_FRAMEBUFFER, ssaoFramebufferID);
glViewport(0, 0, 1024, 1024);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
I managed to get it working thanks to some help in the comments:
My code is now as follows, fragment shader:
#version 330 core
in vec2 TexCoord0;
smooth in vec3 vNormal;
smooth in vec3 vWorldPos;
in mat4 ProjectionMatrix;
uniform sampler2D uDepthTex;
uniform float uWidth;
uniform float uHeight;
layout(location = 0) out vec4 FragColor;
void main()
{
vec2 res = gl_FragCoord.xy / vec2(uWidth, uHeight);
FragColor = texture(uDepthTex, res);
}
Framebuffer creation:
glGenFramebuffers(1, &ssaoFramebufferID);
glBindFramebuffer(GL_FRAMEBUFFER, ssaoFramebufferID);
glGenTextures(1, &ssaoDepthTextureID);
glBindTexture(GL_TEXTURE_2D, ssaoDepthTextureID);
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, 1024, 768, 0, GL_DEPTH_COMPONENT, GL_FLOAT, 0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
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_COMPARE_FUNC, GL_LEQUAL);
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_NONE);
Depth draw code:
glBindFramebuffer(GL_FRAMEBUFFER, ssaoFramebufferID);
glViewport(0, 0, 1024, 768);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
depthShader.Bind();
glDisable(GL_ALPHA_TEST);
depthShader.SetUniformMatrixfv("depthMVP", Matrix4::Perspective(60, aspectRatio, 0.1f, 10.0f) * camera.GetViewMatrix());
DrawScene();
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glViewport(0, 0, width, height);
glEnable(GL_ALPHA_TEST);