Welcome, Guest. Please login or register. Did you miss your activation email?

Author Topic: [ANSWERED] Texture loading causes segfault at glDrawElements  (Read 6433 times)

0 Members and 1 Guest are viewing this topic.

thecheeselover

  • Newbie
  • *
  • Posts: 24
    • View Profile
[ANSWERED] Texture loading causes segfault at glDrawElements
« on: April 04, 2015, 12:22:47 am »
I'm currently making a little modern OpenGL engine just learn new stuff. I use VBOs, IBOs and VAOs to render primitives on the screen using glDrawElements. When I draw simple cubes with only colors as shader attributes, everything works fine. I tried to draw those same cube with texture and then BAM! The program crashes at glDrawElements only if I call texture->loadFromFile(). I searched a lot and found that OpenGL's client states might be the cause, so I disabled them all before drawing, but nothing changed:

glDisableClientState(GL_COLOR_ARRAY);
glDisableClientState(GL_EDGE_FLAG_ARRAY);
glDisableClientState(GL_FOG_COORD_ARRAY);
glDisableClientState(GL_INDEX_ARRAY);
glDisableClientState(GL_NORMAL_ARRAY);
glDisableClientState(GL_SECONDARY_COLOR_ARRAY);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glDisableClientState(GL_VERTEX_ARRAY);

Then I found the pushGLStates() and popGLStates() functions and used them between the loadFromFile(). If I draw my cubes with the equate ''texel + color" (+ instead of *) then I can see my cubes but with no texture, only color. If I just use texture coordinates and positions, everything is black. How can make texture loading and rendering work with OpenGL and SFML 2.2?

//window->pushGLStates();
if (texture->loadFromFile("Resources/Test/cage.png"))
    std::cout << "Texture loaded" << std::endl;

sf::Texture::bind(texture);
//window->popGLStates();

glBindVertexArray(vao);
glDrawElements(GL_TRIANGLES, indicesCount, GL_UNSIGNED_INT, nullptr);

Thanks!  :)
« Last Edit: April 05, 2015, 02:30:38 am by thecheeselover »

binary1248

  • SFML Team
  • Hero Member
  • *****
  • Posts: 1405
  • I am awesome.
    • View Profile
    • The server that really shouldn't be running
Re: Texture loading causes segfault at glDrawElements
« Reply #1 on: April 04, 2015, 04:20:15 am »
  • You probably misunderstood what pushGLStates() and popGLStates() is for. Read the documentation and look at the example again.
  • You haven't provided enough useful information for us to help you. Half of what you said might even be unrelated to the actual problem. Showing us more code would help and not be as ambiguous as trying to explain what you are trying to do.
  • If you are already using buffer objects, shaders and generic vertex attributes, why are you still messing around with enabling/disabling client state? Client state no longer exists in modern OpenGL. It is highly probable that whatever you searched for and found is not even related to the actual problem. If you use modern OpenGL (like you seem to be doing), you shouldn't even have to use pushGLStates() and popGLStates() since all the required state is contained in the OpenGL objects you use for drawing (shaders, textures, VAOs, etc.).
For the cleanest environment in which to learn modern OpenGL, don't use sfml-graphics for drawing. You can still use sf::Image for loading images and manually load the pixel data into an OpenGL texture you create yourself (do not use sf::Texture). Also, don't touch sf::Shader, manage it yourself. This way, you will learn OpenGL the "pure way" and not have to worry about SFML messing around with things that shouldn't matter in the first place. For added practice, you can draw the text yourself as well, if that is what you use sfml-graphics for.
SFGUI # SFNUL # GLS # Wyrm <- Why do I waste my time on such a useless project? Because I am awesome (first meaning).

thecheeselover

  • Newbie
  • *
  • Posts: 24
    • View Profile
Re: Texture loading causes segfault at glDrawElements
« Reply #2 on: April 04, 2015, 09:09:21 pm »
Okay that was useful, thanks. :) I played a lot with texture and was able to render the textures. Somehow, I was too confident of myself and didn't save my progress to continue toying with texture. Now I'm back with the black texture... At least, now it's not giving a segfault.

Mostly take from: https://www.opengl.org/wiki/Common_Mistakes#Creating_a_complete_texture
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, img.getSize().x, img.getSize().y, 0, GL_RGBA, GL_UNSIGNED_BYTE, img.getPixelsPtr());
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_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);

I also tried this with no success.

glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);
    // gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGBA, img.getSize().x, img.getSize().y, GL_RGBA, GL_UNSIGNED_BYTE, img.getPixelsPtr());
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); // Avant sampler object
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); // Avant sampler object
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); // Avant sampler object
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); // Avant sampler object
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, img.getSize().x, img.getSize().y, 0, GL_RGBA, GL_UNSIGNED_BYTE, img.getPixelsPtr());

Do you have any idea what's cause the black texture?

binary1248

  • SFML Team
  • Hero Member
  • *****
  • Posts: 1405
  • I am awesome.
    • View Profile
    • The server that really shouldn't be running
Re: Texture loading causes segfault at glDrawElements
« Reply #3 on: April 04, 2015, 09:36:47 pm »
Like I already said, you will have to show more code.
SFGUI # SFNUL # GLS # Wyrm <- Why do I waste my time on such a useless project? Because I am awesome (first meaning).

thecheeselover

  • Newbie
  • *
  • Posts: 24
    • View Profile
Re: Texture loading causes segfault at glDrawElements
« Reply #4 on: April 04, 2015, 09:47:48 pm »
Just ask if you don't have enough code. I took the main parts of the engine.

#include <SFML/Graphics.hpp>
#include "Engine/Core/Core.h"

int main()
{
    { // Juste pour que le destructeur soit appelé avant la fin du main pour le cleanup.
        Core core;

        core.Init();
        core.Load();

        while (!core.requestCloseWindow)
        {
            core.HandleInput();

            core.Update();
            core.Draw();
        }

        core.Unload();
        core.window->close();
    }

    return 0;
}
 

#include <GL/glew.h>

#include "Core.h"
#include <SFML/OpenGL.hpp>
#include <glm/fwd.hpp>

void Core::Init()
{
    window = new sf::RenderWindow(sf::VideoMode(800, 600), "SFML works!");
    window->setVerticalSyncEnabled(true);
    window->setMouseCursorVisible(false);
    glewInit(); // Doit être appelé quand il y a un contexte OpenGL, donc après l'instanciation de la fenêtre.

    clock = new sf::Clock();
    camera = new CameraFreeRoaming (window, glm::vec3(0.0f, 5.0f, 5.0f), VecConst::ZERO_VEC3);

    glEnable(GL_TEXTURE_2D);

    glEnable(GL_DEPTH_TEST);
    glDepthMask(GL_TRUE);
    glDepthFunc(GL_LEQUAL);
    glDepthRange(0.0f, 1.0f);
    glClearDepth(1.0f);
}
 

#include "Core.h"
#include <string>
#include <vector>
#include "../Graphics/DrawBuffers.h"
#include "../Graphics/BufferUsage.h"
#include "../Graphics/CubeDataGenerator.h"
#include "../Graphics/Shader/ShaderType.h"
#include <iostream>

void Core::Load()
{
    std::vector<ShaderSource> shaderSources =
        {ShaderSource("Resources/Test/Test_Tex_Shader.frag", ShaderType::FRAGMENT),
         ShaderSource("Resources/Test/Test_Tex_Shader.vert", ShaderType::VERTEX)};
    colorShader = new Shader(shaderSources);

    sf::Image img;

    //window->pushGLStates();
    if (img.loadFromFile("Resources/Test/Google_Chrome_logo.png"))
        std::cout << "Texture loaded" << std::endl;
       
    glGenTextures(1, &texture);
    glBindTexture(GL_TEXTURE_2D, texture);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, img.getSize().x, img.getSize().y, 0, GL_BGRA, GL_UNSIGNED_BYTE, img.getPixelsPtr());
    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_MAG_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
    glGenerateMipmap(GL_TEXTURE_2D);

    std::cout << gluErrorString(glGetError()) << std::endl;

    //window->popGLStates();

    /*glDisableClientState(GL_COLOR_ARRAY);
    glDisableClientState(GL_EDGE_FLAG_ARRAY);
    glDisableClientState(GL_FOG_COORD_ARRAY);
    glDisableClientState(GL_INDEX_ARRAY);
    glDisableClientState(GL_NORMAL_ARRAY);
    glDisableClientState(GL_SECONDARY_COLOR_ARRAY);
    glDisableClientState(GL_TEXTURE_COORD_ARRAY);
    glDisableClientState(GL_VERTEX_ARRAY);*/


    colorShader->useProgram();

    projectionMat = glm::perspective(glm::radians(60.0f), (float)window->getSize().x / (float)window->getSize().y, 0.001f, 1000.0f);

    glUniformMatrix4fv(glGetUniformLocation(colorShader->program, "ProjectionMatrix"), 1, GL_FALSE, &projectionMat[0][0]);
    glUniformMatrix4fv(glGetUniformLocation(colorShader->program, "ModelMatrix"), 1, GL_FALSE, &worldMatrix[0][0]); // Si location = -1 = aucune erreur; autre que -1, mais n'existe pas = erreur

    cube1 = new DrawBuffers(CubeDataGenerator::GenCube(DataGeneratorUsage::Position3 | DataGeneratorUsage::ColorRGBA | DataGeneratorUsage::TexCoord), BufferUsage::STATIC_DRAW, true);
    cube2 = new DrawBuffers(CubeDataGenerator::GenCube(DataGeneratorUsage::Position3 | DataGeneratorUsage::ColorRGBA | DataGeneratorUsage::TexCoord, 2.0f), BufferUsage::STATIC_DRAW, true);
    cube3 = new DrawBuffers(CubeDataGenerator::GenCube(DataGeneratorUsage::Position3 | DataGeneratorUsage::ColorRGBA | DataGeneratorUsage::TexCoord, 1.0f, 3.0f, 0.1f), BufferUsage::STATIC_DRAW, true);

    clock->restart();
}
 

#include "Core.h"
#include <SFML/OpenGL.hpp>

// Header file
#include <glm/fwd.hpp>
#include <glm/gtc/matrix_transform.hpp>

void Core::Draw()
{
    window->clear();
    glClear(GL_DEPTH_BUFFER_BIT);

    colorShader->useProgram();
    glUniformMatrix4fv(glGetUniformLocation(colorShader->program, "ViewMatrix"), 1, GL_FALSE, &camera->getView()[0][0]);

    glm::vec3 v1 (0.0f, 0.0f, 0.0f);
    glm::vec3 v2 (3.0f, 0.0f, 0.0f);
    glm::vec3 v3 (6.0f, 0.0f, 0.0f);

    glUniformMatrix4fv(glGetUniformLocation(colorShader->program, "ModelMatrix"), 1, GL_FALSE, &glm::translate(worldMatrix, v1)[0][0]);
    cube1->draw();

    glUniformMatrix4fv(glGetUniformLocation(colorShader->program, "ModelMatrix"), 1, GL_FALSE, &glm::translate(worldMatrix, v2)[0][0]);
    cube2->draw();

    glUniformMatrix4fv(glGetUniformLocation(colorShader->program, "ModelMatrix"), 1, GL_FALSE, &glm::translate(worldMatrix, v3)[0][0]);
    cube3->draw();

    window->display();
}
 

binary1248

  • SFML Team
  • Hero Member
  • *****
  • Posts: 1405
  • I am awesome.
    • View Profile
    • The server that really shouldn't be running
Re: Texture loading causes segfault at glDrawElements
« Reply #5 on: April 04, 2015, 10:09:34 pm »
Where do you bind your texture to the sampler inside your shader program?
SFGUI # SFNUL # GLS # Wyrm <- Why do I waste my time on such a useless project? Because I am awesome (first meaning).

thecheeselover

  • Newbie
  • *
  • Posts: 24
    • View Profile
Re: Texture loading causes segfault at glDrawElements
« Reply #6 on: April 04, 2015, 11:04:58 pm »
I thought sampler objects were optional.  :o Are they mandatory since 4.x?

 glGenTextures(1, &texture);
    glActiveTexture(GL_TEXTURE0);
    glBindTexture(GL_TEXTURE_2D, texture);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, img.getSize().x, img.getSize().y, 0, GL_BGRA, GL_UNSIGNED_BYTE, img.getPixelsPtr());
    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_MAG_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
    glGenerateMipmap(GL_TEXTURE_2D);

    std::cout << gluErrorString(glGetError()) << std::endl;

    colorShader->useProgram();

    glUniform1i(glGetUniformLocation(colorShader->program, "textureSampler"), 0); // 0 pour GL_TEXTURE0
« Last Edit: April 04, 2015, 11:13:48 pm by thecheeselover »

binary1248

  • SFML Team
  • Hero Member
  • *****
  • Posts: 1405
  • I am awesome.
    • View Profile
    • The server that really shouldn't be running
Re: Texture loading causes segfault at glDrawElements
« Reply #7 on: April 04, 2015, 11:28:16 pm »
I thought sampler objects were optional.  :o Are they mandatory since 4.x?
They were mandatory since forever if you are using your own fragment shader.
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, img.getSize().x, img.getSize().y, 0, GL_BGRA, GL_UNSIGNED_BYTE, img.getPixelsPtr());
You know that sf::Image uses RGBA pixel storage right?

Also, do you check for OpenGL errors anywhere? This is the first thing anybody who uses OpenGL should do. You probably have well over 100 OpenGL calls in your code and don't know if they all succeeded. I'm pretty sure one or more of them might have failed and you are just not realizing it.
SFGUI # SFNUL # GLS # Wyrm <- Why do I waste my time on such a useless project? Because I am awesome (first meaning).

thecheeselover

  • Newbie
  • *
  • Posts: 24
    • View Profile
Re: Texture loading causes segfault at glDrawElements
« Reply #8 on: April 04, 2015, 11:39:12 pm »
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, img.getSize().x, img.getSize().y, 0, GL_RGBA, GL_UNSIGNED_BYTE, img.getPixelsPtr());

You mean when I used GL_BGRA? That was just for testing but thanks. (I tested many combinations ahah)

I have put
std::cout << gluErrorString(glGetError()) << std::endl;
in my draw loop and get no errors. What's really frustating is that I once had a texture rendered on my cubes.

Is my texture to sampler binding ok?

glGenTextures(1, &texture);
    glActiveTexture(GL_TEXTURE0);
    glBindTexture(GL_TEXTURE_2D, texture);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, img.getSize().x, img.getSize().y, 0, GL_RGBA, GL_UNSIGNED_BYTE, img.getPixelsPtr());
    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_MAG_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
    glGenerateMipmap(GL_TEXTURE_2D);

    colorShader->useProgram();

    glUniform1i(glGetUniformLocation(colorShader->program, "textureSampler"), 0); // 0 pour GL_TEXTURE0

vertex shader
#version 330

uniform mat4 ProjectionMatrix;
uniform mat4 ViewMatrix;
uniform mat4 ModelMatrix;

uniform vec3 testVec3;

layout(location = 0) in vec4 inPosition;
layout(location = 1) in vec4 inColor;
layout(location = 2) in vec2 inTexturePos;

// Smooth
out vec4 vColor;
out vec2 vTexturePos;

void main()
{
        gl_Position = ProjectionMatrix * ViewMatrix * ModelMatrix * inPosition;
        vColor = inColor;
        vTexturePos = inTexturePos;
}
 

fragment shader
#version 330

uniform sampler2D textureSampler;

// Smooth
in vec4 vColor;
in vec2 vTexturePos;

out vec4 pixel;

void main()
{
    pixel = texture(textureSampler, vTexturePos) * vColor;
}
 

binary1248

  • SFML Team
  • Hero Member
  • *****
  • Posts: 1405
  • I am awesome.
    • View Profile
    • The server that really shouldn't be running
Re: Texture loading causes segfault at glDrawElements
« Reply #9 on: April 04, 2015, 11:57:47 pm »
Are you sure all of your attribute data is arriving in your shaders? If any of them don't, the attribute will return a constant value (0) when the program is run.
SFGUI # SFNUL # GLS # Wyrm <- Why do I waste my time on such a useless project? Because I am awesome (first meaning).

thecheeselover

  • Newbie
  • *
  • Posts: 24
    • View Profile
Re: Texture loading causes segfault at glDrawElements
« Reply #10 on: April 05, 2015, 12:10:13 am »
Interesting question you ask.
I used this neat little trick to test my texture coordinates and it does what I expected: it cuts 1/4 of the surface of each cube's face. If texture coordinates weren't properly sent to the shaders (i.e. always == (0,0)), then all faces would be invisible. To be able to see the cubes, I added to each texel vColor.

#version 330

uniform sampler2D textureSampler;

// Smooth
in vec4 vColor;
in vec2 vTexturePos;

out vec4 pixel;

void main()
{
    if (vTexturePos.x < 0.5f && vTexturePos.y < 0.5f)
        discard;

    pixel = texture(textureSampler, vTexturePos) + vColor;
}
 


EDIT: For some unknown reasons, my texture seems to be unbinded before my draw function. I juste did glBindTexture(GL_TEXTURE_2D, 1) and my Nicolas Cage image appeared. :P What's weird is that I never used glBindTexture in my engine... Anyway, a big thanks to you!
« Last Edit: April 05, 2015, 02:29:46 am by thecheeselover »