[MESA Driver] Render on the window works but render to a texture fails. :/

Hi!

I need to render to a texture, but it doesn’t display anything, only the clear color of the render texture is displayed, here is my source code.

I try to keep a compatibility with old opengl versions, so, I’ve modified the SFML class like this. (because the name of the function change in modern opengl)

[code=cpp]
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
// Copyright (C) 2007-2013 Laurent Gomila (laurent.gom@gmail.com)
//
// This software is provided ‘as-is’, without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it freely,
// subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented;
// you must not claim that you wrote the original software.
// If you use this software in a product, an acknowledgment
// in the product documentation would be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such,
// and must not be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source distribution.
//
////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include “renderTextureImplFBO.h”
#include “…/…/…/include/odfaeg/Graphics/renderTarget.h”
#include “…/…/…/include/odfaeg/Graphics/texture.h”
#include “glCheck.h”
#include <SFML/System/Err.hpp>
#include <iostream>
using namespace sf;
namespace odfaeg {
namespace graphic {
namespace priv
{
////////////////////////////////////////////////////////////
RenderTextureImplFBO::RenderTextureImplFBO() :
m_frameBuffer(0),
m_depthBuffer(0)
{

        }


        ////////////////////////////////////////////////////////////
        RenderTextureImplFBO::~RenderTextureImplFBO()
        {
            ensureGlContext();

            // Destroy the depth buffer
            if (m_depthBuffer)
            {
                GLuint depthBuffer = static_cast&lt;GLuint&gt;(m_depthBuffer);
                if (RenderTarget::getMajorVersion() &gt;= 3 && RenderTarget::getMinorVersion() &gt;= 3)
                    glCheck(glDeleteRenderbuffers(1, &depthBuffer));
                else
                    glCheck(glDeleteRenderbuffersEXT(1, &depthBuffer));
            }

            // Destroy the frame buffer
            if (m_frameBuffer)
            {
                GLuint frameBuffer = static_cast&lt;GLuint&gt;(m_frameBuffer);
                if (RenderTarget::getMajorVersion() &gt;= 3 && RenderTarget::getMinorVersion() &gt;= 3)
                    glCheck(glDeleteFramebuffers(1, &frameBuffer));
                else
                    glCheck(glDeleteFramebuffersEXT(1, &frameBuffer));
            }

            // Delete the context
            delete m_context;
        }


        ////////////////////////////////////////////////////////////
        bool RenderTextureImplFBO::isAvailable()
        {
            ensureGlContext();

            // Make sure that GLEW is initialized
            priv::ensureGlewInit();

            if (RenderTarget::getMajorVersion() &gt;= 3 && RenderTarget::getMinorVersion() &gt;= 3)
                return true;
            return GLEW_EXT_framebuffer_object != 0;
        }


        ////////////////////////////////////////////////////////////
        bool RenderTextureImplFBO::create(unsigned int width, unsigned int height, ContextSettings settings, unsigned int textureId)
        {
            // Create the context
            m_context = new Context(settings, width, height);
            // Create the framebuffer object
            GLuint frameBuffer = 0;
            if (RenderTarget::getMajorVersion() &gt;= 3 && RenderTarget::getMinorVersion() &gt;= 3)
                glCheck(glGenFramebuffers(1, &frameBuffer));
            else
                glCheck(glGenFramebuffersEXT(1, &frameBuffer));
            m_frameBuffer = static_cast&lt;unsigned int&gt;(frameBuffer);
            if (!m_frameBuffer)
            {
                err() &lt;&lt; "Impossible to create render texture (failed to create the frame buffer object)" &lt;&lt; std::endl;
                return false;
            }
            if (RenderTarget::getMajorVersion() &gt;= 3 && RenderTarget::getMinorVersion() &gt;= 3)
                glCheck(glBindFramebuffer(GL_FRAMEBUFFER, m_frameBuffer));
            else
                glCheck(glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_frameBuffer));

            // Create the depth buffer if requested
            if (settings.depthBits &gt; 0)
            {
                GLuint depth = 0;
                if (RenderTarget::getMajorVersion() &gt;= 3 && RenderTarget::getMinorVersion() &gt;= 3)
                    glCheck(glGenRenderbuffers(1, &depth));
                else
                    glCheck(glGenRenderbuffersEXT(1, &depth));
                m_depthBuffer = static_cast&lt;unsigned int&gt;(depth);
                if (!m_depthBuffer)
                {
                    err() &lt;&lt; "Impossible to create render texture (failed to create the attached depth buffer)" &lt;&lt; std::endl;
                    return false;
                }
                if (RenderTarget::getMajorVersion() &gt;= 3 && RenderTarget::getMinorVersion() &gt;= 3) {
                    glCheck(glBindRenderbuffer(GL_RENDERBUFFER, m_depthBuffer));
                    glCheck(glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, width, height));
                    glCheck(glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, m_depthBuffer));
                } else {
                    glCheck(glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, m_depthBuffer));
                    glCheck(glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT, width, height));
                    glCheck(glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, m_depthBuffer));
                }
            }
            if (RenderTarget::getMajorVersion() &gt;= 3 && RenderTarget::getMinorVersion() &gt;= 3) {
                glCheck(glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, textureId, 0));
                GLenum DrawBuffers[1] = {GL_COLOR_ATTACHMENT0};
                glCheck(glDrawBuffers(1, DrawBuffers));
            } else {
                // Link the texture to the frame buffer
                glCheck(glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, textureId, 0));
            }
            if (RenderTarget::getMajorVersion() &gt;= 3 && RenderTarget::getMinorVersion() &gt;= 3) {
                // A final check, just to be sure.
                if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
                {
                    glCheck(glBindFramebuffer(GL_FRAMEBUFFER, 0));
                    err() &lt;&lt; "Impossible to create render texture (failed to link the target texture to the frame buffer)" &lt;&lt; std::endl;
                    return false;
                }
            } else {
                // A final check, just to be sure...
                if (glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT) != GL_FRAMEBUFFER_COMPLETE_EXT)
                {
                    glCheck(glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0));
                    err() &lt;&lt; "Impossible to create render texture (failed to link the target texture to the frame buffer)" &lt;&lt; std::endl;
                    return false;
                }
            }

            return true;
        }


        ////////////////////////////////////////////////////////////
        bool RenderTextureImplFBO::activate(bool active)
        {
            return m_context-&gt;setActive(active);
        }


        ////////////////////////////////////////////////////////////
        void RenderTextureImplFBO::updateTexture(unsigned int)
        {
            glFlush();
        }
    }

} // namespace priv

} // namespace sf



I'm trying to draw a tile on a render texture, and then, drawing the whole texture on the window, so, the code is like this :


int main(int argc, char* argv[])
{
RenderWindow window (sf::VideoMode (800, 600), “Test”, sf::Style::Default, sf::ContextSettings(0, 0, 4, 3, 3));
const std::string vertexShader =
#version 330 core
"
“layout (location = 0) in vec4 position;”
“layout (location = 1) in vec4 color;”
“layout (location = 2) in vec2 uv;”
“layout (location = 3) in vec3 normals;”
“uniform mat4 projMatrix;”
“uniform mat4 viewMatrix;”
“uniform mat4 modelMatrix;”
“uniform mat4 texMatrix;”
“out vec4 f_color;”
“out vec2 f_uv;”
“void main() {”
" gl_Position = projMatrix * viewMatrix * modelMatrix * position;”
" f_uv = (texMatrix * vec4(uv.xy, 0, 0)).xy;"
" f_color = color;"
“}”;
const std::string fragmentShader =
#version 330 core
"
“layout (location = 0) out vec4 color;”
“uniform sampler2D texSampler;”
“in vec2 f_uv;”
“in vec4 f_color;”
“void main() {”
" vec4 texel = texture (texSampler, f_uv);”
" color = f_color * texel;"
“}”;
Texture tex;
tex.loadFromFile(“tilesets/herbe.png”);
Tile tile (&tex, Vec3f(0, 0, 0), Vec3f(100, 50, 0), sf::IntRect(0, 0, 100, 50));
tile.move(Vec3f(100, 100, 0));
Shader simpleShader;
simpleShader.loadFromMemory(vertexShader, fragmentShader);
Matrix4f projMatrix = window.getView().getProjMatrix().getMatrix().transpose();
Matrix4f viewMatrix = window.getView().getViewMatrix().getMatrix().transpose();
Matrix4f modelMatrix = tile.getTransform().getMatrix().transpose();
Matrix4f texMatrix = tex.getTextureMatrix().transpose();
simpleShader.setParameter(“projMatrix”, projMatrix);
simpleShader.setParameter(“viewMatrix”, viewMatrix);
simpleShader.setParameter(“modelMatrix”, modelMatrix);
simpleShader.setParameter(“texMatrix”, texMatrix);
simpleShader.setParameter(“texSampler”, Shader::CurrentTexture);
RenderStates states;
states.shader = &simpleShader;
RenderTexture rt;
rt.create(window.getSize().x, window.getSize().y, window.getSettings());
rt.setView(window.getView());
rt.clear(sf::Color::White);
rt.draw(tile, states);
rt.display();
const Texture& rtex = rt.getTexture();
Tile tile2 (&rtex, Vec3f(0, 0, 0), Vec3f(rt.getView().getSize().x, rt.getView().getSize().y, 0), sf::IntRect(0, 0, rt.getView().getSize().x, rt.getView().getSize().y));
tile2.setCenter(window.getView().getPosition());
simpleShader.setParameter(“projMatrix”, rt.getView().getProjMatrix().getMatrix().transpose());
simpleShader.setParameter(“viewMatrix”, rt.getView().getViewMatrix().getMatrix().transpose());
simpleShader.setParameter(“modelMatrix”, tile2.getTransform().getMatrix().transpose());
simpleShader.setParameter(“texMatrix”, rtex.getTextureMatrix().transpose());
while (window.isOpen()) {
window.clear();
window.draw(tile2, states);
window.display();
sf::Event event;
while (window.pollEvent(event)) {
if (event.type == sf::Event::Closed) {
window.close();
}
}
}
return 0;
}



But only the clear color of the render texture (white) is displayed all over the screen, but if I display the tile directly on the window it works so it means that all my other classes are correct. 
  
Have I made something wrong when creating the render texture or in my shader code ?

I've never used FBO with modern opengl. :/

So I've followed this tuorial [http://www.opengl-tutorial.org/intermediate-tutorials/tutorial-14-render-to-texture/](http://www.opengl-tutorial.org/intermediate-tutorials/tutorial-14-render-to-texture/) but everything seems to be correct. :/

PS : The source code of the tutorial works so I've doing something wrong but I can't find what...

Surprising, I’ve just changed the stencil buffer size and now it works.


RenderWindow window (sf::VideoMode (800, 600), "Test", sf::Style::Default, sf::ContextSettings(0, 32, 4, 3, 3));

I really don’t understand…

PS : he just failed to create an higher context with a larger buffer size, but with a lower opengl version it works…

Sometimes I’m so stupid, I just needed to recreate a VAO after creating the render texture’s context, but I need to flip the texture in y because it’s inverted.

Now, my code is ready for image load/store, so I just have to wait that this functionnality is implemented by mesa. ^^

I’ll try to emulate a window system with virtual box to get priority driver working, as a developper this is the way that I prefer, it avoids me to have to reboot the pc each time I want to switch.

I hope it’ll work fine.

Or having a remote access to another PC by ssh is nice too but I have only one PC.

This topic was automatically closed 183 days after the last reply. New replies are no longer allowed.