//  SuperTuxKart - a fun racing game with go-kart
//  Copyright (C) 2014-2015 SuperTuxKart-Team
//
//  This program is free software; you can redistribute it and/or
//  modify it under the terms of the GNU General Public License
//  as published by the Free Software Foundation; either version 3
//  of the License, or (at your option) any later version.
//
//  This program is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//  GNU General Public License for more details.
//
//  You should have received a copy of the GNU General Public License
//  along with this program; if not, write to the Free Software
//  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.

#ifndef SERVER_ONLY

#include "graphics/stk_billboard.hpp"

#include "graphics/irr_driver.hpp"
#include "graphics/material.hpp"
#include "graphics/material_manager.hpp"
#include "graphics/shared_gpu_objects.hpp"
#include "graphics/texture_shader.hpp"

#include <ISceneManager.h>

using namespace irr;


static GLuint billboardvao = 0;


class BillboardShader : public TextureShader<BillboardShader, 1, core::matrix4,
                                      core::matrix4, core::vector3df,
                                      core::dimension2df>
{
public:
    BillboardShader()
    {
        loadProgram(OBJECT, GL_VERTEX_SHADER, "billboard.vert",
                            GL_FRAGMENT_SHADER, "billboard.frag");

        assignUniforms("ModelViewMatrix", "ProjectionMatrix", "Position",
                       "Size");
        assignSamplerNames(0, "tex", ST_TRILINEAR_ANISOTROPIC_FILTERED);
    }   // BillboardShader
};   // BillboardShader

// ============================================================================

static void createBillboardVAO()
{
    glGenVertexArrays(1, &billboardvao);
    glBindVertexArray(billboardvao);
    glBindBuffer(GL_ARRAY_BUFFER, SharedGPUObjects::getBillboardVBO());
    glEnableVertexAttribArray(0);
    glEnableVertexAttribArray(3);
    glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), 0);
    glVertexAttribPointer(3, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), 
                          (GLvoid*) (2 * sizeof(float)));
    glBindVertexArray(0);
}   // createBillboardVAO

// ----------------------------------------------------------------------------
STKBillboard::STKBillboard(irr::scene::ISceneNode* parent,
                           irr::scene::ISceneManager* mgr, irr::s32 id,
                           const irr::core::vector3df& position,
                           const irr::core::dimension2d<irr::f32>& size,
                           irr::video::SColor colorTop, 
                           irr::video::SColor colorBottom)
            : IBillboardSceneNode(parent, mgr, id, position),
              CBillboardSceneNode(parent, mgr, id, position, size, 
                                  colorTop, colorBottom)
{
    if (!billboardvao)
        createBillboardVAO();
}   // STKBillboard

// ----------------------------------------------------------------------------
void STKBillboard::OnRegisterSceneNode()
{
    if (IsVisible)
    {
        SceneManager->registerNodeForRendering(this, scene::ESNRP_TRANSPARENT);
    }

    ISceneNode::OnRegisterSceneNode();
}   // OnRegisterSceneNode

// ----------------------------------------------------------------------------
void STKBillboard::render()
{
    if (irr_driver->getPhase() != TRANSPARENT_PASS)
        return;

    core::vector3df pos = getAbsolutePosition();
    glBindVertexArray(billboardvao);
    video::ITexture *tex = Material.getTexture(0);
    if (!tex )
        return;

    ::Material* material = material_manager->getMaterialFor(tex, 
        video::E_MATERIAL_TYPE::EMT_ONETEXTURE_BLEND);
    if (material->getShaderType() == Material::SHADERTYPE_ADDITIVE)
        glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
    else
        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

    BillboardShader::getInstance()->use();
    BillboardShader::getInstance()->setTextureUnits(tex->getOpenGLTextureName());
    BillboardShader::getInstance()->setUniforms(irr_driver->getViewMatrix(), 
                                                irr_driver->getProjMatrix(),
                                                pos, Size);
    glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
    glBindVertexArray(0);
}   // render

#endif   // !SERVER_ONLY

