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

Author Topic: [Crash] using shader with rendertextures.  (Read 1129 times)

0 Members and 1 Guest are viewing this topic.

Lolilolight

  • Hero Member
  • *****
  • Posts: 1232
    • View Profile
[Crash] using shader with rendertextures.
« on: March 14, 2014, 02:39:23 pm »
Hi, i'm trying to put a set of 3D or 2D entities using the same texture in a tilemap and I use a shader and two render textures to render them because I've semi-transparent textures.

But I've a problem :
Here's the code of my tilemap class :

#ifndef TILEMAP
#define TILEMAP
#include "renderTexture.h"
#include "tile.h"
#include "shader.h"
namespace odfaeg {
    namespace g3d {
class TileMap : public Drawable, public Transformable
{
public:
    TileMap (View& view, int zOrder = 0) : view(view) ,
        Transformable (Vec3f (view.getPosition().x, view.getPosition().y, zOrder), Vec3f(view.getSize().x, view.getSize().y, 0), Vec3f(view.getSize().x * 0.5f, view.getSize().y * 0.5f, 0)) {
        this->zOrder = zOrder;
        this->view = view;
    }
    static void genBuffers(int screenWidth, int screenHeight) {
        resolution = Vec2f(screenWidth, screenHeight);
        depthBuffer.create(resolution.x, resolution.y);
        frameBuffer.create(resolution.x, resolution.y);
        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) {" \
                "float delta = color.a - finalColor.a;" \
                "gl_FragColor = color + vec4(finalColor.r * delta, finalColor.g * delta, finalColor.b * delta, delta);" \
                "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(const Texture& tileset, std::vector<Tile*> tiles)
    {
        // load the tileset texture
        m_tileset = tileset;

        // resize the vertex array to fit the level size
        m_vertices.setPrimitiveType(sf::Quads);
        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;
                Vec2f size = Vec2f(tiles[i]->getSize().x, tiles[i]->getSize().y);
                sf::IntRect subRect = tiles[i]->getTextureRect();
                // define its 4 corners
                quad[i*4].position = sf::Vector3f(position.x, position.y, zOrder);
                quad[i*4+1].position = sf::Vector3f(position.x + size.x, position.y, zOrder);
                quad[i*4+2].position = sf::Vector3f(position.x + size.x, position.y + size.y, zOrder);
                quad[i*4+3].position = sf::Vector3f(position.x, position.y + size.y, zOrder);

                // define its 4 texture coordinates
                quad[i*4].texCoords = sf::Vector2f(subRect.left, subRect.top);
                quad[i*4+1].texCoords = sf::Vector2f(subRect.left + subRect.width, subRect.top);
                quad[i*4+2].texCoords = sf::Vector2f(subRect.left + subRect.width, subRect.top + subRect.height);
                quad[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(), frameBuffer.getView().getPosition(), frameBuffer.getView().getSize(), subRect, 0);
        return tile;
    }
    static Tile getDepthBufferTile() {
        sf::IntRect subRect(0, 0, depthBuffer.getView().getSize().x, depthBuffer.getView().getSize().y);
        Tile tile (&depthBuffer.getTexture(), depthBuffer.getView().getPosition(), depthBuffer.getView().getSize(), subRect, 0);
        return tile;
    }
private:
    virtual void draw(RenderTarget& target, RenderStates states) const
    {
        // apply the transform
        states.texture = &m_tileset;
        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);

    }
    VertexArray m_vertices;
    Texture m_tileset;
    static RenderTexture depthBuffer;
    static RenderTexture frameBuffer;
    static Shader *depthBufferGenerator;
    static Shader *frameBufferGenerator;
    int zOrder;
    static Vec2f resolution;
    View& view;
};
}
}
#endif // TILEMAP
 

So I want to put a set of 3D tiles here.

It work when I have only one quad per tilemap but when I want to load more than one quad (in other words, when I put more than one tiles un the tilemap), it crashes and the debuguers gives me this error :

Code: [Select]
#0 03060D85 atioglxx!DrvPresentBuffers() (C:\Windows\SysWOW64\atioglxx.dll:??)
#1 0308BED8 atioglxx!DrvPresentBuffers() (C:\Windows\SysWOW64\atioglxx.dll:??)
#2 0308AF84 atioglxx!DrvPresentBuffers() (C:\Windows\SysWOW64\atioglxx.dll:??)
#3 0305C87E atioglxx!DrvPresentBuffers() (C:\Windows\SysWOW64\atioglxx.dll:??)
#4 02E27531 atioglxx!DrvPresentBuffers() (C:\Windows\SysWOW64\atioglxx.dll:??)
#5 02E4A76F atioglxx!DrvPresentBuffers() (C:\Windows\SysWOW64\atioglxx.dll:??)
#6 02E4D218 atioglxx!DrvPresentBuffers() (C:\Windows\SysWOW64\atioglxx.dll:??)
#7 03037EA1 atioglxx!DrvPresentBuffers() (C:\Windows\SysWOW64\atioglxx.dll:??)
#8 0302E009 atioglxx!DrvPresentBuffers() (C:\Windows\SysWOW64\atioglxx.dll:??)
#9 0302F522 atioglxx!DrvPresentBuffers() (C:\Windows\SysWOW64\atioglxx.dll:??)
#10 0302F375 atioglxx!DrvPresentBuffers() (C:\Windows\SysWOW64\atioglxx.dll:??)
#11 0303D67A atioglxx!DrvPresentBuffers() (C:\Windows\SysWOW64\atioglxx.dll:??)
#12 0279907B atioglxx!DrvPresentBuffers() (C:\Windows\SysWOW64\atioglxx.dll:??)
#13 02AAC3E9 atioglxx!DrvPresentBuffers() (C:\Windows\SysWOW64\atioglxx.dll:??)
#14 028AF92E atioglxx!DrvPresentBuffers() (C:\Windows\SysWOW64\atioglxx.dll:??)
#15 004DEF73 main() (D:\Projets\Projets-c++\Test3DODFAEG\main.cpp:64)

It crash when I want to clear the window, here's my code :

#include "ODFAEG/Graphics/3D/renderWindow.h"
#include "ODFAEG/Graphics/3D/tile.h"
#include "ODFAEG/Graphics/3D/tileMap.h"
#include "ODFAEG/Graphics/3D/tile.h"
#include "ODFAEG/Graphics/3D/wall.h"
#include "ODFAEG/Graphics/3D/map.h"
#include "ODFAEG/Graphics/3D/cube.h"
#include "ODFAEG/Core/ResourceManager.h"
#include "ODFAEG/Math/projMatrix.h"
using namespace odfaeg;
using namespace odfaeg::g3d;


int main() {

    RenderWindow window(sf::VideoMode(800, 600), "TestODFAEG", sf::Style::Default, sf::ContextSettings(32));
    View &view = window.getView();
    view.setUpVector(Vec3f(0, -1, 0));
    view.scale(-1, 1, 1);
    view.move(-400, -300, 0);
    AABB viewRect(Vec3f(view.getPosition().x, view.getPosition().y, 0), view.getSize().x, view.getSize().y, 0);
    TileMap::genBuffers(view.getSize().x, view.getSize().y);
    Texture t1;
    Texture t2;
    t1.loadFromFile("tilesets/herbe.png");
    t2.loadFromFile("tilesets/murs.png");
    std::vector<Tile*> tiles;
    tiles.push_back(new Tile(&t1, Vec2f(0, 0), Vec2f(120, 60),sf::IntRect(0, 0, 100, 50), 0));
    tiles.push_back(new Tile(&t1, Vec2f(100, 50), Vec2f(120, 60),sf::IntRect(0, 0, 100, 50), 0));  
    TileMap tm1(view);  
    tm1.load(t1, tiles);
    while(window.isOpen()) {
       

        sf::Event event;
        while(window.pollEvent(event)) {
            if (event.type == sf::Event::Closed)
                window.close();
        }

        window.clear(sf::Color(0, 0, 0));
        TileMap::clearBufferBits(sf::Color(0, 0, 0));
        TileMap::clearDepthBits();
        window.draw(tm1);
        window.display();

    }

    return 0;
}
 

I've an ATI mobility Radeon HD 5470 as graphical card.

I've checked out my driver but it seems it's up to date.








Lolilolight

  • Hero Member
  • *****
  • Posts: 1232
    • View Profile
Re: [Crash] using shader with rendertextures.
« Reply #1 on: March 16, 2014, 03:19:45 pm »
I've simply changed the source code :

 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;
            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);
        }
 

And it works.


 

anything