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 :
#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.