I've found the bugs with my render components and now I use a framebuffer and a depthbuffer texture by component (and not for all components anymore) I've adapted the gridMap class to store 3D entities for the final version of ODFAEG!!!
Now, 2D and 3D entities can be drawn on components correctly, the advantage of odfaeg's render components is that they have a dephtest which manage semi-tranparent pixels. (if your pc support the GLSL)
You can so cross semi-transparent textures on the z axis and create special effects. (pixel water which overlap the ground by exemple)
(But it only work for PC which support shader, otherwise rendercomponent'll use the default opengl depth test or the zsorting for flat textures)
The world class can so directly draw entities on component, and components'll be drawn directly on the window by the application, so in the onRender function you have just to specify which entity you want to draw on which component, here I draw the ground on a first render component and the other entities in a second render component, so, event if the z of the ground textures is greater than the z of the texture's caracter, the ground texture doesn't overlap the caracter because the ground is drawn on another component.
void onRender() {
World::drawOnComponents("E_TILE", 0);// draw the ground on the background component.
World::drawOnComponents("E_WALL+E_DECOR+E_ANIMATION+E_CARACTER+E_PONCTUAL_LIGHT", 1);
//Draw all other entities to the foreground component.
}
Component'll also be used to generate light map and shadow easy in 3D in the last version of ODFAEG.
The node of the framework is nearby finished so I'll wait to have a better source code before updating the git-hub with a source code example!
But maybe I'll need some help fore optimisation so I'll browse some other forums before, because drawing everything on rendertextures and passing params to shader is a bit slow. :/ (even with vbos)
#include "../../../../include/odfaeg/Graphics/2D/fastRenderComponent.h"
namespace odfaeg {
namespace g2d {
FastRenderComponent::FastRenderComponent (RenderWindow& window, int layer) :
Transformable(Vec3f(window.getView().getPosition().x, window.getView().getPosition().y, layer),
Vec3f(window.getView().getSize().x, window.getView().getSize().y, 0),
Vec3f(window.getView().getSize().x + window.getView().getSize().x * 0.5f, window.getView().getPosition().y + window.getView().getSize().y * 0.5f, layer)),
view(window.getView()) {
sf::Vector3i resolution ((int) window.getSize().x, (int) window.getSize().y, window.getView().getSize().z);
depthBuffer = new RenderTexture();
frameBuffer = new RenderTexture();
depthBuffer->create(resolution.x, resolution.y);
frameBuffer->create(resolution.x, resolution.y);
frameBuffer->setView(window.getView());
depthBuffer->setView(window.getView());
if (Shader::isAvailable()) {
frameBufferGenerator = new Shader();
depthBufferGenerator = new Shader();
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 sampler2D texture;"
"uniform vec3 resolution;"
"void main () {"
"vec2 position = ( gl_FragCoord.xy / resolution.xy );"
"vec4 color = texture2D(depthBuffer, position);"
"vec4 pixel = texture2D(texture, gl_TexCoord[0].xy);"
"if (gl_FragCoord.z >= color.z && pixel.a >= color.a) {"
"gl_FragColor = vec4(0, 0,gl_FragCoord.z, pixel.a);"
"} else {"
"gl_FragColor = color;"
"}"
"}";
const std::string frameBufferGenFragShader =
"uniform sampler2D depthBuffer;"
"uniform sampler2D frameBuffer;"
"uniform sampler2D texture;"
"uniform vec3 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);"
"if (gl_FragCoord.z >= depth.z) {"
"gl_FragColor = pixel;"
"} else if (color.a < pixel.a) {"
"gl_FragColor = pixel;"
"} 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, resolution.z);
frameBufferGenerator->setParameter("resolution",resolution.x, resolution.y, resolution.z);
backgroundColor = sf::Color::Transparent;
}
}
void FastRenderComponent::setBackgroundColor(sf::Color color) {
this->backgroundColor = color;
}
void FastRenderComponent::clearBufferBits() {
frameBuffer->clear(backgroundColor);
}
void FastRenderComponent::clearDepthBits() {
depthBuffer->clear(sf::Color::Transparent);
}
g2d::Tile FastRenderComponent::getFrameBufferTile () const {
sf::IntRect subRect(0, 0, frameBuffer->getView().getSize().x, frameBuffer->getView().getSize().y);
g2d::Tile tile (&frameBuffer->getTexture(), Vec2f(0, 0), Vec2f(frameBuffer->getView().getSize().x, frameBuffer->getView().getSize().y), subRect);
return tile;
}
g2d::Tile FastRenderComponent::getDepthBufferTile() const {
sf::IntRect subRect(0, 0, depthBuffer->getView().getSize().x, depthBuffer->getView().getSize().y);
g2d::Tile tile (&depthBuffer->getTexture(), Vec2f(0, 0), Vec2f(depthBuffer->getView().getSize().x, depthBuffer->getView().getSize().y), subRect);
return tile;
}
bool FastRenderComponent::load(std::vector<Entity*> visibleEntities)
{
if (Shader::isAvailable()) {
fg.clear();
for (unsigned int i = 0; i < visibleEntities.size(); i++) {
if (visibleEntities[i]->isLeaf()) {
for (unsigned int j = 0; j < visibleEntities[i]->getFaces().size(); j++) {
visibleEntities[i]->getFaces()[j]->transform(visibleEntities[i]->getTransform());
fg.addFace(visibleEntities[i]->getFaces()[j]);
}
}
}
m_vertices = fg.getFaces();
}
this->visibleEntities = visibleEntities;
}
void FastRenderComponent::draw(RenderTarget& target, RenderStates states) const {
const Shader* devShader = states.shader;
states.transform = getTransform();
if (Shader::isAvailable()) {
frameBuffer->setView(target.getView());
depthBuffer->setView(target.getView());
for (unsigned int i = 0; i < m_vertices.size(); i++) {
states.texture = const_cast<FastRenderComponent*>(this)->m_vertices[i].first.getMaterial().getTexture();
for (unsigned int j = 0; j < m_vertices[i].second.size(); j++) {
states.shader = frameBufferGenerator;
frameBufferGenerator->setParameter("depthBuffer", depthBuffer->getTexture());
frameBufferGenerator->setParameter("frameBuffer", frameBuffer->getTexture());
frameBufferGenerator->setParameter("texture", Shader::CurrentTexture);
frameBuffer->draw(*m_vertices[i].second[j], states);
frameBuffer->display();
depthBufferGenerator->setParameter("depthBuffer", depthBuffer->getTexture());
depthBufferGenerator->setParameter("texture", Shader::CurrentTexture);
states.shader = depthBufferGenerator;
depthBuffer->draw(*m_vertices[i].second[j], states);
depthBuffer->display();
}
}
g2d::Tile tile = getFrameBufferTile();
tile.setCenter(frameBuffer->getView().getPosition());
states.shader = devShader;
target.draw(tile, states);
} else {
for (unsigned int i = 0; i < visibleEntities.size(); i++) {
for (unsigned int j = 0; j < visibleEntities[i]->getFaces().size(); j++) {
states.texture = visibleEntities[i]->getFaces()[j]->getMaterial().getTexture();
states.transform = visibleEntities[i]->getTransform();
target.draw(visibleEntities[i]->getFaces()[j]->getVertexArray(), states);
}
}
}
}
void FastRenderComponent::init() {
}
FastRenderComponent::~FastRenderComponent() {
}
View& FastRenderComponent::getView() {
return view;
}
int FastRenderComponent::getLayer() {
return getPosition().z;
}
}
}
I don't thing that's it's necessary to pass the transformation matrix if I update vertices in the vbo, in any case I'll have to browse other forums to get some optimisation advices, the source code of SFML is not sufficient anymore.