PDA

View Full Version : Nothing shows while trying to render a texture



DonPedross
01-11-2018, 02:15 AM
Hi! I am trying to render texture a texture. The quad draws well but texture does not want to attach.

Mesh class


void Mesh::CreateQuad(Rect destRect, Rect uvRect, ColorRGBA color, GLuint texture)
{
this->texture = texture;
//Vertex is a class that contains 3 structs: Position(float x and y), Color (Glubyte r and g, and b, and a), UV (float u and v)
Vertex vertex[6];

vertex[0].color = color;
vertex[0].setPosition(destRect.x, destRect.y + destRect.h);
vertex[0].setUV(uvRect.x, uvRect.y + uvRect.h);

vertex[1].color = color;
vertex[1].setPosition(destRect.x, destRect.y);
vertex[1].setUV(uvRect.x, uvRect.y);

vertex[2].color = color;
vertex[2].setPosition(destRect.x + destRect.w, destRect.y);
vertex[2].setUV(uvRect.x + uvRect.w, uvRect.y);

vertex[3].color = color;
vertex[3].setPosition(destRect.x + destRect.w, destRect.y + destRect.h);
vertex[3].setUV(uvRect.x + uvRect.w, uvRect.y + uvRect.h);

GLuint index[] = {
0, 1, 2,
0, 2, 3
};

glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, 6 * sizeof(Vertex), nullptr, GL_DYNAMIC_DRAW);
glBufferSubData(GL_ARRAY_BUFFER, 0, 6 * sizeof(Vertex), vertex);

glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, 6 * sizeof(GLuint), nullptr, GL_DYNAMIC_DRAW);
glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, 6 * sizeof(GLuint), index);

glBindBuffer(GL_ARRAY_BUFFER, 0);
}

void Mesh::CreateVertexArray()
{
if (vao == 0) {
glGenVertexArrays(1, &vao);
}
glBindVertexArray(vao);

if (vbo == 0) {
glGenBuffers(1, &vbo);
}
glBindBuffer(GL_ARRAY_BUFFER, vbo);

if (ebo == 0) {
glGenBuffers(1, &ebo);
}
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);

glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
glEnableVertexAttribArray(2);

glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)offsetof(Vertex, position));
glVertexAttribPointer(1, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(Vertex), (void*)offsetof(Vertex, color));
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)offsetof(Vertex, uv));

glGenVertexArrays(1, 0);
}

void Mesh::DrawQuad()
{
glBindVertexArray(vao);
glEnable(GL_CULL_FACE);
glCullFace(GL_FRONT);
glFrontFace(GL_CW);

glBindTexture(GL_TEXTURE_2D, texture);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, NULL);

glBindVertexArray(0);
glBindTexture(GL_TEXTURE_2D, 0);

std::cout << "Texture " << texture << std::endl;
}


texture class




void Texture::Init()
{
//Creates vbo vao ebo
mesh.CreateVertexArray();
}

void Texture::LoadFromFile(const std::string & filePath)
{
//attaches texture to the textureID
textureID = texture.getTexture(filePath);
}

void Texture::Draw(Rect destRect, Rect uvRect, ColorRGBA color)
{
//creates and draws a quad with texture ID
mesh.CreateQuad(destRect, uvRect, color, textureID);
mesh.DrawQuad();
}

GLuint TextureCache::loadFromFile(const std::string & filePath)
{
textureMap.clear();

SDL_Surface* surface = IMG_Load(filePath.c_str());

GLuint texture = 0;
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);

int format;
surface->format->BitsPerPixel == 4 ? format = GL_RGBA : format = GL_RGB;

w = surface->w;
h = surface->h;

glTexImage2D(GL_TEXTURE_2D, 0, format, w, h, 0, format, GL_UNSIGNED_BYTE, surface->pixels);

SDL_FreeSurface(surface);
glBindTexture(GL_TEXTURE_2D, 0);

return texture;
}

GLuint TextureCache::getTexture(const std::string & filePath)
{
//finds texture
auto texMap = textureMap.find(filePath);

//if there is no texture create one
if (texMap == textureMap.end()) {
GLuint newTexture = loadFromFile(filePath);

textureMap[filePath] = newTexture;

return newTexture;
}
// else return existing one
return texMap->second;
}



and a bit of main.cpp


Texture texture;
texture.Init();
texture.LoadFromFile("MenuImage.png");

Shader shader;
std::string vertex = shader.LoadFromFile("vertex.shader");
std::string fragment = shader.LoadFromFile("fragment.shader");
shader.CreateShaderProgram(vertex.c_str(), fragment.c_str());

GLint u_textureSampler = shader.GetUniformLocation("u_textureSampler");
glUniform1f(u_textureSampler, 0);

glClearColor(0.0f, 0.0f, 0.0f, 1.0f);

bool quit = false;
SDL_Event event;

while (!quit) {
while (SDL_PollEvent(&event)) {
if (event.type == SDL_QUIT) {
SDL_Quit();
exit(0);
}
}

glClearDepth(1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

Rect destRect = { -0.5, -0.5, 1.0, 1.0 };
Rect uvRect = { 0.0, 0.0, 1.0, 1.0f };
ColorRGBA color = { 255, 0, 255, 255 };

texture.Draw(destRect, uvRect, color);

SDL_GL_SwapWindow(window);
}


and shaders



#version 330 core

layout (location = 0) in vec2 aPosition;
layout (location = 1) in vec4 aColor;
layout (location = 2) in vec2 aUV;

out vec4 v_fragmentColor;
out vec2 v_fragmentUV;

void main()
{
gl_Position = vec4(aPosition, 0.0, 1.0);

v_fragmentColor = aColor;
v_fragmentUV = aUV;
}




#version 330 core

out vec4 outColor;

in vec2 v_fragmentUV;
in vec4 v_fragmentColor;

uniform sampler2D u_textureSampler;

void main()
{
vec4 textureColor = texture(u_textureSampler, v_fragmentUV);
outColor = v_fragmentColor * textureColor;
}

And still there is no texture on the screen. There is only nothing :c
Yes, so I know there is a lot of code and I almost said nothing but there is nothing to say. I think my comments attached to code are enough. If you have more questions ask, though. Maybe there is better way to do it. let me know, please.

GClements
01-11-2018, 06:14 AM
glGenVertexArrays(1, 0);


This call is invalid.





surface->format->BitsPerPixel == 4 ? format = GL_RGBA : format = GL_RGB;



This should be using the BytesPerPixel field, not BitsPerPixel. It won't handle anything other than 888 or 8888 formats; I don't know whether you're likely to encounter those. You can use SDL_ConvertSurfaceFormat() to convert other formats to 888 or 8888. I'd suggest just converting everything to SDL_PIXELFORMAT_RGBA8888 or SDL_PIXELFORMAT_ABGR8888 (depending up byte order) so that you only have to deal with one format. The OpenGL implementation will probably expand GL_RGB8 to 32 bits internally for performance, so you won't save video memory using RGB.





w = surface->w;
h = surface->h;

glTexImage2D(GL_TEXTURE_2D, 0, format, w, h, 0, format, GL_UNSIGNED_BYTE, surface->pixels);


This doesn't account for alignment. You need glPixelStorei(GL_UNPACK_ALIGNMENT,1) if you want to support RGB data with arbitrary widths (RGBA data will always have a multiple of 4 bytes per line).

Also, the minification filter is initially GL_NEAREST_MIPMAP_LINEAR, which requires mipmaps. Either change the filter to something which doesn't require mipmaps with e.g. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,GL_LINEAR) or generate mipmap levels with e.g. glGenerateMipmap(GL_TEXTURE_2D). Otherwise, texturing is disabled (texture() will return zeros).





GLint u_textureSampler = shader.GetUniformLocation("u_textureSampler");
glUniform1f(u_textureSampler, 0);


Sampler uniforms can only be set with glUniform1i() or glUniform1iv().

DonPedross
01-11-2018, 01:27 PM
This call is invalid.



This should be using the BytesPerPixel field, not BitsPerPixel. It won't handle anything other than 888 or 8888 formats; I don't know whether you're likely to encounter those. You can use SDL_ConvertSurfaceFormat() to convert other formats to 888 or 8888. I'd suggest just converting everything to SDL_PIXELFORMAT_RGBA8888 or SDL_PIXELFORMAT_ABGR8888 (depending up byte order) so that you only have to deal with one format. The OpenGL implementation will probably expand GL_RGB8 to 32 bits internally for performance, so you won't save video memory using RGB.


This doesn't account for alignment. You need glPixelStorei(GL_UNPACK_ALIGNMENT,1) if you want to support RGB data with arbitrary widths (RGBA data will always have a multiple of 4 bytes per line).

Also, the minification filter is initially GL_NEAREST_MIPMAP_LINEAR, which requires mipmaps. Either change the filter to something which doesn't require mipmaps with e.g. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,GL_LINEAR) or generate mipmap levels with e.g. glGenerateMipmap(GL_TEXTURE_2D). Otherwise, texturing is disabled (texture() will return zeros).


Sampler uniforms can only be set with glUniform1i() or glUniform1iv().

Do not know why there is bites per pixel. Going to change it.

However you are not exactly right with uniform, because in the other project I am using the same `glUniform1f(u_textureSampler, 0);` it works perfectly fine

GClements
01-11-2018, 07:44 PM
However you are not exactly right with uniform, because in the other project I am using the same `glUniform1f(u_textureSampler, 0);` it works perfectly fine
The call doesn't work; the program just happens to work in spite of that.

Are you checking for errors? Setting a sampler variable with glUniform1f() should report GL_INVALID_OPERATION; if it doesn't, that's a driver bug. The specification is quite clear on this.

However, the value is likely to be 0 initially (recent versions of the GLSL specification require sampler uniforms without a binding qualifier to be initialised to 0, but this is typical behaviour in earlier versions), so the fact that the call fails won't matter in this specific case. If you want to actually change the value, you must use glUniform1i() or glUniform1iv().