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

Author Topic: Opengl displays errors messages with FBO.  (Read 1653 times)

0 Members and 1 Guest are viewing this topic.

Lolilolight

  • Hero Member
  • *****
  • Posts: 1232
    • View Profile
Opengl displays errors messages with FBO.
« on: March 21, 2014, 12:31:48 pm »
Hi, I've rewritten the SFML classes for the 3D so I just added a z component in the SFML Graphics module, I had also to copy some SFML classes (Texture, RenderTexture, TextureSaver, RenderTextureImple, etc...) in my own project because the m_cache_id and other texture informations used by SFML are only accessible by SFML classes. (because these informations are internal to SFML)

I didn't changed anything for the textures and rendertextures management classe except the namspace nam of course.

But Opengl give me some error message when I delete the render texture, and, especially when they are static, here is the classe which hold the render textures :

#ifndef ODFAEG_TILEMAP_HPP
#define ODFAEG_TILEMAP_HPP
#include "../renderTexture.h"
#include "tile.h"
#include "../shader.h"
namespace odfaeg {
    namespace g2d {
class TileMap : public Entity
{
public:
    TileMap (View& view, const Texture* tileset) : view(view) ,
        Entity (Vec3f (view.getPosition().x, view.getPosition().y, 0), Vec3f(view.getSize().x, view.getSize().y, 0), Vec3f(view.getSize().x * 0.5f, view.getSize().y * 0.5f, 0), "E_TILEMAP") {
        this->view = view;
        // load the tileset texture
        m_tileset = tileset;
    }
    static void genBuffers(unsigned int screenWidth, unsigned int screenHeight) {
        resolution = Vec2f(screenWidth, screenHeight);
        if (Shader::isAvailable()) {
            depthBuffer.create(screenWidth, screenHeight);
            frameBuffer.create(screenWidth, screenHeight);
            const std::string vertexShader = \
            "void main () {" \
                "gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;" \
                "gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;" \
                "gl_FrontColor = gl_Color;" \
            "}";
            const std::string  depthGenFragShader = \
            "uniform sampler2D depthBuffer;" \
            "uniform vec2 resolution;" \
            "void main () {" \
                  "vec2 position = ( gl_FragCoord.xy / resolution.xy );" \
                  "vec4 pixel = texture2D(depthBuffer, position);" \
                  "if (gl_FragCoord.z > pixel.z) {" \
                    "gl_FragColor = vec4(0, 0,  gl_FragCoord.z, 1);" \
                  "} else {" \
                     "gl_FragColor = gl_Color * pixel;" \
                  "}" \
            "}";
            const std::string frameBufferGenFragShader = \
            "uniform sampler2D depthBuffer;" \
            "uniform sampler2D frameBuffer;" \
            "uniform sampler2D texture;" \
            "uniform vec2 resolution;" \
            "void main () {     " \
                "vec2 position = ( gl_FragCoord.xy / resolution.xy );" \
                "vec4 depth = texture2D(depthBuffer, position);" \
                "vec4 color = texture2D(frameBuffer, position);" \
                "vec4 pixel = texture2D(texture, gl_TexCoord[0].xy);" \
                "vec4 finalColor = pixel;" \
                "if (gl_FragCoord.z >= depth.z) {" \
                    "gl_FragColor = finalColor;" \
                "} else if (color.a < finalColor.a) {" \
                    "float delta = finalColor.a - color.a;" \
                    "gl_FragColor = color + vec4(finalColor.r * delta, finalColor.g * delta, finalColor.b * delta, delta);" \
                "} else {" \
                    "gl_FragColor = color;" \
                "}" \
            "}";
            if (!depthBufferGenerator.loadFromMemory(vertexShader, depthGenFragShader))
                throw Erreur(50, "Failed to load depth buffer generator shader", 0);
            if (!frameBufferGenerator.loadFromMemory(vertexShader, frameBufferGenFragShader))
                throw Erreur(51, "Failed to load frame buffer generator shader", 0);
             depthBufferGenerator.setParameter("resolution",resolution.x, resolution.y);
             frameBufferGenerator.setParameter("resolution",resolution.x, resolution.y);
        }
    }
    static void clearBufferBits(sf::Color color) {
        frameBuffer.clear(sf::Color(color.r, color.g, color.b, 0));
    }
    static void clearDepthBits() {
        depthBuffer.clear(sf::Color(0, 0, 0, 255));
    }

    bool load(std::vector<Tile*> tiles, sf::PrimitiveType pType = sf::Quads)
    {
        // resize the vertex array to fit the level size
        m_vertices.setPrimitiveType(pType);
        m_vertices.resize(tiles.size() * 4);
        // populate the vertex array, with one quad per tile
        for (unsigned int i = 0; i < tiles.size(); i++) {
            // get a pointer to the current tile's quad

            //Vertex* quad = &m_vertices[i * 4];

            Vec2f position (tiles[i]->getPosition().x, tiles[i]->getPosition().y);
            float zOrder = tiles[i]->getPosition().z - view.getSize().z + 1;
            Vec2f size = Vec2f(tiles[i]->getSize().x, tiles[i]->getSize().y);
            sf::IntRect subRect = tiles[i]->getTextureRect();
            // define its 4 corners
            m_vertices[i*4].position = sf::Vector3f(position.x, position.y, zOrder);
            m_vertices[i*4+1].position = sf::Vector3f(position.x + size.x, position.y, zOrder);
            m_vertices[i*4+2].position = sf::Vector3f(position.x + size.x, position.y + size.y, zOrder);
            m_vertices[i*4+3].position = sf::Vector3f(position.x, position.y + size.y, zOrder);

            // define its 4 texture coordinates
            m_vertices[i*4].texCoords = sf::Vector2f(subRect.left, subRect.top);
            m_vertices[i*4+1].texCoords = sf::Vector2f(subRect.left + subRect.width, subRect.top);
            m_vertices[i*4+2].texCoords = sf::Vector2f(subRect.left + subRect.width, subRect.top + subRect.height);
            m_vertices[i*4+3].texCoords = sf::Vector2f(subRect.left, subRect.top + subRect.height);
        }

        return true;
    }
    static Tile getFrameBufferTile () {
        sf::IntRect subRect(0, 0, frameBuffer.getView().getSize().x, frameBuffer.getView().getSize().y);
        Tile tile (&frameBuffer.getTexture(), Vec2f(frameBuffer.getView().getPosition().x, frameBuffer.getView().getPosition().y), Vec2f(frameBuffer.getView().getSize().x, frameBuffer.getView().getSize().y), subRect, 0);
        return tile;
    }
    static Tile getDepthBufferTile() {
        sf::IntRect subRect(0, 0, depthBuffer.getView().getSize().x, depthBuffer.getView().getSize().y);
        Tile tile (&depthBuffer.getTexture(), Vec2f(depthBuffer.getView().getPosition().x, depthBuffer.getView().getPosition().y), Vec2f(depthBuffer.getView().getSize().x, depthBuffer.getView().getSize().y), subRect, 0);
        return tile;
    }
    bool isAnimated() const {
        return false;
    }
    bool selectable() const {
        return false;
    }
    bool isModel() const {
        return false;
    }
    bool isShadow() const {
        return false;
    }
    bool isLight() const {
        return true;
    }
    const Texture* getTileset() {
        return m_tileset;
    }
    bool operator==(Entity& other) {
        if (other.getType() != "E_TILEMAP")
            return false;
        TileMap& tm = static_cast<TileMap&>(other);
        return m_tileset == tm.m_tileset;
    }
    void clear() {
        m_vertices.clear();
    }

    virtual void onDraw(RenderTarget& target, RenderStates states) const
    {
        // apply the transform
        states.texture = m_tileset;
        if (Shader::isAvailable()) {
            states.shader = &frameBufferGenerator;
            //Update the depth buffer and the frame buffer of the current frame.
            frameBufferGenerator.setParameter("depthBuffer", depthBuffer.getTexture());
            frameBufferGenerator.setParameter("frameBuffer", frameBuffer.getTexture());
            frameBufferGenerator.setParameter("texture", Shader::CurrentTexture);
            frameBuffer.setView(view);
            frameBuffer.draw(m_vertices, states);
            frameBuffer.display();
            //Update the depth buffer.
            depthBuffer.setView(view);
            depthBufferGenerator.setParameter("depthBuffer", depthBuffer.getTexture());
            states.shader = &depthBufferGenerator;
            depthBuffer.draw(m_vertices, states);
            depthBuffer.display();
            states.shader = nullptr;
            states.transform = getTransform();
            Tile tile = getFrameBufferTile();
            tile.move(Vec3f(-view.getSize().x * 0.5f, -view.getSize().y * 0.5f, 0));
            target.draw(tile, states);
        } else {
            states.transform = getTransform();
            target.draw(m_vertices, states);
        }
    }
    private:
    static Shader& getShader() {
        static Shader shader;
        return shader;
    }
    static RenderTexture& getRenderTexture() {
        static RenderTexture renderTexture;
        return renderTexture;
    }
    VertexArray m_vertices;
    const Texture* m_tileset;
    static RenderTexture depthBuffer;
    static RenderTexture frameBuffer;
    static Shader& depthBufferGenerator;
    static Shader& frameBufferGenerator;
    static Vec2f resolution;
    View& view;
};
}
}
#endif // TILEMAP

 

When I close the application I have this error message :

An internal OpenGL call failed in renderTextureImplFBO.cpp (65) : GL_INVALID_VALUE, a numeric argument is out of range.

I've printed the frameBuffer id in the console and they are correct (1 for the frameBuffer render texture and 2 for the depthBuffer render texture)

I've a question so, is it a problem if the renderwindow is destroyed before the RenderTextures ?

But even if I don't destroy the window, the problem remains....




Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Re: Opengl displays errors messages with FBO.
« Reply #1 on: March 21, 2014, 01:46:18 pm »
Static variables are destroyed at global exit, at the same time as SFML's internal resources. If your variables are destroyed after, you have a problem.

The solution is to avoid global scope destructions, keep the destruction of your resources under control.
Laurent Gomila - SFML developer

Lolilolight

  • Hero Member
  • *****
  • Posts: 1232
    • View Profile
Re: Opengl displays errors messages with FBO.
« Reply #2 on: March 21, 2014, 05:49:21 pm »
Ha ok, I've used pointers instead and the error message has disappeared.

Nexus

  • SFML Team
  • Hero Member
  • *****
  • Posts: 6287
  • Thor Developer
    • View Profile
    • Bromeon
Re: Opengl displays errors messages with FBO.
« Reply #3 on: March 21, 2014, 07:46:44 pm »
Don't simply use pointers, avoid global/static variables wherever possible. If you want to build your own framework, you should really invest some time into designing it -- not only because nobody will use it with a strange API, but also because it's harder to extend, maintain and debug without well-structured code.
Zloxx II: action platformer
Thor Library: particle systems, animations, dot products, ...
SFML Game Development: