
#include "Tlake3d_low_1.h"

// shader et plan en fin

// -----------------------
// --- le constructeur ---
// -----------------------

Tlake3d_low_1::Tlake3d_low_1()
{
	//
}

// ----------------------
// --- le destructeur ---
// ----------------------

Tlake3d_low_1::~Tlake3d_low_1()
{
    //
}


void Tlake3d_low_1::create(int size, float scale_uv)
{
	OTextureList::P_setPath(PATH_IMAGE);
	OTextureList::P_setMipmap(true);

    textureList.add("lac_00.png");
    textureList.add("lac_00_n.png");

    OTextureList::P_setMipmap(false);

    m_colorMap = textureList.getID("lac_00.png");
    m_normalMap = textureList.getID("lac_00_n.png");

    // ---

    plan.create(size, scale_uv);

    // ---

    shLake_low.create();
    shLake_low_w.create();

    m_time = 0.0f;
}

void Tlake3d_low_1::draw(OMat4& vp, OVec3_f& eyePos, uint32_t reflectionMap)
{
    m_time++;

    glDisable(GL_CULL_FACE);
    //glEnable(GL_CULL_FACE);

    // on pourrait passer en multi
    if (plan.getSize() == 1)
    {
        shLake_low.enable();
            shLake_low.setVP(vp);
            shLake_low.setModel( plan.getModel() );

            shLake_low.setTime(m_time);
            shLake_low.setEyePos(eyePos);
            shLake_low.setTextures(m_colorMap, m_normalMap, reflectionMap);

            plan.draw();

        shLake_low.disable();
        return;
    }

    shLake_low.enable();
        shLake_low.setVP(vp);
        shLake_low.setMulti(true);

        shLake_low.setTime(m_time);
        shLake_low.setEyePos(eyePos);
        shLake_low.setTextures(m_colorMap, m_normalMap, reflectionMap);

        plan.draw_multi();
        shLake_low.setMulti(false);

    shLake_low.disable();
}


void Tlake3d_low_1::draw_water_reflection(OMat4& vp)
{
    glDisable(GL_CULL_FACE);
    //glEnable(GL_CULL_FACE);

    // on pourrait passer en multi
    if (plan.getSize() == 1)
    {
        shLake_low_w.enable();
            shLake_low_w.setVP(vp);
            shLake_low_w.setModel( plan.getModel() );

            plan.draw();

        shLake_low_w.disable();
        return;
    }

    shLake_low_w.enable();
        shLake_low_w.setVP(vp);
        shLake_low_w.setMulti(true);

        plan.draw_multi();
        shLake_low_w.setMulti(false);

    shLake_low_w.disable();
}

void Tlake3d_low_1::setLight(float ambient, OVec3_f& dir, OVec3_f& color)
{
    shLake_low.enable();
        shLake_low.setLight(ambient, dir, color);
    shLake_low.disable();
}



// --- grille map plan carte


// -----------------------
// --- le constructeur ---
// -----------------------

Tlake3d_low_1_plan::Tlake3d_low_1_plan()
{
    //
}

// ----------------------
// --- le destructeur ---
// ----------------------

Tlake3d_low_1_plan::~Tlake3d_low_1_plan()
{
    //
}

// --------------------
// --- les méthodes ---
// --------------------

// px py pz
void Tlake3d_low_1_plan::addModel(std::string flux)
{
    std::vector<std::string> strList;
    size_t idx = m_pos.size();

    ECO_strCut(strList, flux, ' ');

    m_pos.push_back(OVec3_f());
    m_model.push_back(OMat4());
    m_model_multi.push_back(OMat4());

	m_pos[idx].x = ECO_strToFloat(strList[0]);
	m_pos[idx].y = ECO_strToFloat(strList[1]);
	m_pos[idx].z = ECO_strToFloat(strList[2]);

    _setModel(idx);
}

// px py pz
void Tlake3d_low_1_plan::addModel(float px, float py, float pz)
{
    size_t idx = m_pos.size();

    m_pos.push_back(OVec3_f());
    m_model.push_back(OMat4());
    m_model_multi.push_back(OMat4());

	m_pos[idx].set(px,py,pz);

    _setModel(idx);
}





void Tlake3d_low_1_plan::create(uint32_t size, float scale_uv)
{
    m_pos.push_back(OVec3_f());
    m_model.push_back(OMat4());
    m_model_multi.push_back(OMat4());

    _setModel(0);

    // ---

    OVec3_f vertex[] = {
    {-1,-1,0}, {1,-1,0}, {1,1,0}, {-1,1,0}
    };
    OVec3_f normal[] = {
        {0.0f, 0.5f, 1.0f}
    };
    OVec2_f uv[] = {
        {0,0}, {1,0}, {1,1}, {0,1}
    };

    // 2 faces de 3 points
    int ivertex[] = {0,1,2, 2,3,0};
    int inormal[] = {0,0,0, 0,0,0};
    int iuv[]     = {0,1,2, 2,3,0};

    float radius = size * 0.5f;

    for (size_t pt = 0; pt < ECO_sizeOf(ivertex); pt++)
    {
        m_vertex.push_back(vertex[ivertex[pt]] * radius);
        m_normal.push_back(normal[inormal[pt]]);
        m_uv.push_back(uv[iuv[pt]] * scale_uv);
        m_indice.push_back(pt);
    }

	_make_vao();
}




void Tlake3d_low_1_plan::draw()
{
    glBindVertexArray(m_vao);

    //if (mode == 0) {
        glDrawElements(GL_TRIANGLES, m_indice.size(), GL_UNSIGNED_INT, 0);
    //}
    //else if (mode == 1) {
    //	glDrawElements(GL_POINTS, m_indice.size(), GL_UNSIGNED_INT, 0);
    //}
    glBindVertexArray(0);

    glBindTexture(GL_TEXTURE_2D, 0);
    glActiveTexture(GL_TEXTURE0);
}

void Tlake3d_low_1_plan::draw_multi()
{
    glBindVertexArray(m_vao);

        glDrawElementsInstanced(GL_TRIANGLES, m_indice.size(), GL_UNSIGNED_INT, 0, m_model_multi.size());

    glBindBuffer(GL_ARRAY_BUFFER, 0);
    glBindVertexArray(0);

    glBindTexture(GL_TEXTURE_2D, 0);
    glActiveTexture(GL_TEXTURE0);
}


// grille unique
OMat4& Tlake3d_low_1_plan::getModel()
{
    return m_model[0];
}

size_t Tlake3d_low_1_plan::getSize()
{
    return m_pos.size();
}







void Tlake3d_low_1_plan::_make_vao()
{
    //génération de l'identifiant du VAO
    glGenVertexArrays(1, &m_vao);
    //activation du VAO
    glBindVertexArray(m_vao);

    // créations des buffers
    //obj_nbr_vao_buffer = 10;
    glGenBuffers(10, m_vao_buffer);

    glBindBuffer(GL_ARRAY_BUFFER, m_vao_buffer[0]);
    glBufferData(GL_ARRAY_BUFFER, sizeof(OVec3_f) * m_vertex.size(), &m_vertex[0], GL_STATIC_DRAW);
    glEnableVertexAttribArray(LOCATION_POSITION);
    glVertexAttribPointer(LOCATION_POSITION, 3, GL_FLOAT, GL_FALSE, 0, 0);

    glBindBuffer(GL_ARRAY_BUFFER, m_vao_buffer[1]);
    glBufferData(GL_ARRAY_BUFFER, sizeof(OVec3_f) * m_normal.size(), &m_normal[0], GL_STATIC_DRAW);
    glEnableVertexAttribArray(LOCATION_NORMAL);
    glVertexAttribPointer(LOCATION_NORMAL, 3, GL_FLOAT, GL_FALSE, 0, 0);

    glBindBuffer(GL_ARRAY_BUFFER, m_vao_buffer[2]);
    glBufferData(GL_ARRAY_BUFFER, sizeof(OVec2_f) * m_uv.size(), &m_uv[0], GL_STATIC_DRAW);
    glEnableVertexAttribArray(LOCATION_TEXCOORD);
    glVertexAttribPointer(LOCATION_TEXCOORD, 2, GL_FLOAT, GL_FALSE, 0, 0);

    // 3 4 5 6
    glBindBuffer(GL_ARRAY_BUFFER, m_vao_buffer[LOCATION_MODEL]);
        for (int i = 0; i < 4 ; i++)
        {
            glEnableVertexAttribArray(LOCATION_MODEL + i);
            glVertexAttribPointer(LOCATION_MODEL + i, 4, GL_FLOAT, GL_FALSE, sizeof(OMat4), (const void*)(sizeof(float) * i * 4));
            glVertexAttribDivisor(LOCATION_MODEL + i, 1);
        }

    // >>> il faut définir les buffers pour nos shaders avec bones
    glBindBuffer(GL_ARRAY_BUFFER, m_vao_buffer[7]);
    //glBufferData(GL_ARRAY_BUFFER, sizeof(uint16_t) * meshPart[i_part].boneWeight.size(), &meshPart[i_part].boneWeight[0], GL_STATIC_DRAW);
    glBufferData(GL_ARRAY_BUFFER, sizeof(uint16_t), 0, GL_STATIC_DRAW);
    // !!! notez glVertex(AttribI)Pointer
    glEnableVertexAttribArray(LOCATION_BONE);
    glVertexAttribIPointer(LOCATION_BONE, 4, GL_UNSIGNED_SHORT, 0, BUFFER_OFFSET(0));

    glBindBuffer(GL_ARRAY_BUFFER, m_vao_buffer[8]);
    //glBufferData(GL_ARRAY_BUFFER, sizeof(float) * meshPart[i_part].weight.size(), &meshPart[i_part].weight[0], GL_STATIC_DRAW);
    glBufferData(GL_ARRAY_BUFFER, sizeof(float), 0, GL_STATIC_DRAW);
    glEnableVertexAttribArray(LOCATION_WEIGHT);
    glVertexAttribPointer(LOCATION_WEIGHT, 4, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(0));

    //---

    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_vao_buffer[9]);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(unsigned int) * m_indice.size(), &m_indice[0], GL_STATIC_DRAW);

    //glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
    glBindBuffer(GL_ARRAY_BUFFER, 0);
    glBindVertexArray(0);
}





void Tlake3d_low_1_plan::_setModel(size_t idx)
{
    m_model[idx].loadIdentity();
    m_model[idx].translate(m_pos[idx]);

    m_model_multi[idx] = m_model[idx];
    m_model_multi[idx].transpose(); // avec mat4 'horizontale'

    //_setModelMulti(m_model_multi);
    glBindVertexArray(m_vao);
    glBindBuffer(GL_ARRAY_BUFFER, m_vao_buffer[LOCATION_MODEL]);
    glBufferData(GL_ARRAY_BUFFER, sizeof(OMat4) * m_model_multi.size(), &m_model_multi[0], GL_DYNAMIC_DRAW);

    //désactivation du VAO
    glBindBuffer(GL_ARRAY_BUFFER, 0);
    glBindVertexArray(0);
}

void Tlake3d_low_1_plan::setPos(OVec3_f& pos, size_t idx)
{
    m_pos[idx] = pos;
    _setModel(idx);
}

void Tlake3d_low_1_plan::setPos(float px, float py, float pz, size_t idx)
{
    m_pos[idx].set(px, py, pz);
    _setModel(idx);
}


// --- shader


static const char* pVS = " \n\
#version 330 \n\
 \n\
layout (location = 0) in vec3 in_vertex; \n\
layout (location = 1) in vec3 in_normal; \n\
layout (location = 2) in vec2 in_uv; \n\
layout (location = 3) in mat4 in_model; \n\
 \n\
uniform mat4 uVP; \n\
uniform mat4 uModel; \n\
uniform bool uMulti = false; \n\
 \n\
out vec3 var_model; \n\
out vec3 var_normal; \n\
out vec2 var_uv; \n\
out vec4 var_clipSpace; \n\
 \n\
void main(){ \n\
    if (uMulti) \n\
    { \n\
        gl_Position = uVP * in_model * vec4(in_vertex, 1.0); \n\
        \n\
        mat3 normalMat = mat3(in_model); \n\
        normalMat = transpose(inverse(normalMat)); \n\
        \n\
        vec3 normal_transformed = vec3(0.0); \n\
        normal_transformed = normalize(normalMat*in_normal); \n\
        var_normal = normal_transformed; \n\
        var_model = vec3(in_model*vec4(in_vertex, 1.0)); \n\
        vec3 world_pos = (in_model * vec4(in_vertex, 1.0)).xyz; \n\
        var_clipSpace = uVP * vec4(world_pos, 1.0); \n\
        var_uv = in_uv; \n\
    } \n\
    else \n\
    { \n\
        gl_Position = uVP * uModel * vec4(in_vertex, 1.0); \n\
        \n\
        mat3 normalMat = mat3(uModel); \n\
        normalMat = transpose(inverse(normalMat)); \n\
        \n\
        vec3 normal_transformed = vec3(0.0); \n\
        normal_transformed = normalize(normalMat*in_normal); \n\
        var_normal = normal_transformed; \n\
        var_model = vec3(uModel*vec4(in_vertex, 1.0)); \n\
        vec3 world_pos = (uModel * vec4(in_vertex, 1.0)).xyz; \n\
        var_clipSpace = uVP * vec4(world_pos, 1.0); \n\
        var_uv = in_uv; \n\
    } \n\
}";


static const char* pFS = " \n\
#version 330 core   \n\
 \n\
in vec3 var_model; \n\
in vec2 var_uv; \n\
in vec3 var_normal; \n\
in vec4 var_clipSpace; \n\
 \n\
uniform sampler2D uRefractionMap; \n\
uniform sampler2D uNormalMap; \n\
uniform sampler2D uReflectionMap; \n\
uniform vec3  uEyePos; \n\
uniform float uTime; \n\
uniform vec3  uLight_dir; \n\
uniform vec3  uLight_color; \n\
uniform float uLight_ambient; \n\
uniform float uSpecularIntensity = 1.5; // 0->1 \n\
uniform float uSpecularPower = 4.5; // 0->10 etendue \n\
uniform float uTurbidity = 0.15; \n\
uniform float uRepeatNormal = 8; \n\
uniform vec2  uWind_dir = vec2(20.5,-5.0); \n\
uniform float uRefractiveFactor = 0.25; \n\
// si la reflection est décalée > modifiez \n\
uniform vec2 uCorrectif_reflection = vec2(0.99, 1.02); \n\
 \n\
out vec4 out_color; \n\
 \n\
float get_wave(float x, float y, float time){ \n\
    float wave = 0.02*sin( dot(normalize(vec2(1,0)), vec2(x, y)) *512+time); \n\
    wave += 0.02*sin( dot(normalize(vec2(15,1)), vec2(x, y)) *1024+time); \n\
    wave += 0.02*sin( dot(normalize(vec2(10,-1)), vec2(x, y)) *1024+time*1.5); \n\
    wave += 0.02*sin( dot(normalize(vec2(3,1)), vec2(x, y)) *2048+time*2); \n\
    return wave * 0.05; //petite deformation \n\
} \n\
 \n\
void main(){ \n\
    // --- reflexion \n\
    vec2 ndc = ((var_clipSpace.xy/var_clipSpace.w) / 2.0) + 0.5; \n\
    vec2 uv_reflection = vec2(ndc.x*uCorrectif_reflection.x, -ndc.y*uCorrectif_reflection.y); \n\
    vec2 uv_refraction = vec2(ndc.x*uCorrectif_reflection.x,  ndc.y*uCorrectif_reflection.y); \n\
\n\
    // agitation \n\
    float timer = uTime * 0.1; \n\
    float shears = get_wave(var_uv.x*5, var_uv.y*5, timer); \n\
    uv_reflection += vec2(shears, shears); \n\
 \n\
    vec3 colour_refraction = texture(uRefractionMap, var_uv).rgb; \n\
    vec3 colour_reflection = texture(uReflectionMap, uv_reflection).rgb; \n\
 \n\
    // --- vaguelettes \n\
    vec2 coord = var_uv; \n\
    timer = uTime *0.00001; \n\
    coord.x += uWind_dir.x * timer; \n\
    coord.y += uWind_dir.y * timer; \n\
    vec3 normal = var_normal + texture2D(uNormalMap, coord * uRepeatNormal).xyz; \n\
    coord.x -= uWind_dir.x * timer; \n\
    coord.y -= uWind_dir.y * timer; \n\
    normal = normal + (var_normal + texture2D(uNormalMap, coord * uRepeatNormal).xyz); \n\
    normal = normalize(normal); \n\
 \n\
    // --- lumiere \n\
    vec3 ambientColor = uLight_color * uLight_ambient; \n\
    float diffuseFactor = dot(normal, vec3(1,-1,1)); \n\
    vec3 diffuseColor  = vec3(0,0,0); \n\
    vec3 specularColor = vec3(0,0,0); \n\
    if (diffuseFactor > 0) { \n\
        diffuseColor = uLight_color * diffuseFactor; \n\
        vec3 lightReflect = normalize(reflect(uLight_dir, vec3(0,0,0))); \n\
        vec3 vertexToEye = normalize(uEyePos - var_model); \n\
        float specularFactor = dot(vertexToEye, lightReflect); \n\
        if (specularFactor > 0) { \n\
            specularFactor = pow(specularFactor, uSpecularPower); \n\
            specularColor = uLight_color * uSpecularIntensity * specularFactor; \n\
        } \n\
    } \n\
    // --- couleur \n\
    out_color.rgb = mix(colour_refraction, colour_reflection, uRefractiveFactor); \n\
    out_color.rgb *= (ambientColor + diffuseColor + specularColor) * uLight_ambient; \n\
    float alpha = length(uEyePos - var_model) * uTurbidity; \n\
    out_color.a = clamp(alpha, 1.0-uLight_ambient, 1.0); \n\
}";



Tlake3d_low_1_sh::Tlake3d_low_1_sh()
{
	//
}

bool Tlake3d_low_1_sh::create()
{
	if (!OShader::init())
	{
		ECO_error_set("erreur Tlake3d_low_1_sh.init");
		return false;
	}
	if (!addShader(GL_VERTEX_SHADER, pVS))
	{
		ECO_error_set("erreur Tlake3d_low_1_sh.addShader vs");
		return false;
	}
	if (!addShader(GL_FRAGMENT_SHADER, pFS))
	{
		ECO_error_set("erreur Tlake3d_low_1_sh.addShader fs");
		return false;
	}
	if (!finalize())
	{
		ECO_error_set("erreur Tlake3d_low_1_sh.finalize");
		return false;
	}

    m_vp = getUniformLocation("uVP");
    m_model = getUniformLocation("uModel");
    m_refractionMap = getUniformLocation("uRefractionMap");
    m_normalMap = getUniformLocation("uNormalMap");
    m_reflectionMap = getUniformLocation("uReflectionMap");
    //
    m_multi = getUniformLocation("uMulti");
    m_eyePos = getUniformLocation("uEyePos");
    m_light_color = getUniformLocation("uLight_color");
    m_light_ambient = getUniformLocation("uLight_ambient");
    m_light_dir = getUniformLocation("uLight_dir");
    m_specularIntensity = getUniformLocation("uSpecularIntensity");
    m_specularPower = getUniformLocation("uSpecularPower");
    m_turbidity = getUniformLocation("uTurbidity");
    m_repeatNormal = getUniformLocation("uRepeatNormal");
    m_time = getUniformLocation("uTime");
    m_wind_dir = getUniformLocation("uWind_dir");

/*
    if (m_vp == INVALID_UNIFORM_LOCATION
    || m_model == INVALID_UNIFORM_LOCATION
    ||m_refractionMap == INVALID_UNIFORM_LOCATION
    || m_normalMap == INVALID_UNIFORM_LOCATION
    || m_reflectionMap == INVALID_UNIFORM_LOCATION
    || m_eyePos == INVALID_UNIFORM_LOCATION
    || m_light_color == INVALID_UNIFORM_LOCATION
    || m_light_ambient = == INVALID_UNIFORM_LOCATION
    || m_light_dir === INVALID_UNIFORM_LOCATION
    || m_specularIntensity == INVALID_UNIFORM_LOCATION
    || m_specularPower == INVALID_UNIFORM_LOCATION
    || m_turbidity == INVALID_UNIFORM_LOCATION
    || m_repeatNormal == INVALID_UNIFORM_LOCATION
    || m_time == INVALID_UNIFORM_LOCATION
    || m_wind_dir == INVALID_UNIFORM_LOCATION
    )
    {
        ECO_error_set("Echec Tlake3d_low_1_sh 0");
        return false;
    }
*/
    return true;
}

void Tlake3d_low_1_sh::setVP(const OMat4& vp)
{
    glUniformMatrix4fv(m_vp, 1, GL_TRUE, vp.getFv());
}

void Tlake3d_low_1_sh::setModel(const OMat4& model)
{
    glUniformMatrix4fv(m_model, 1, GL_TRUE, model.getFv());
}

void Tlake3d_low_1_sh::setMulti(bool mode)
{
    glUniform1i(m_multi, mode);
}

void Tlake3d_low_1_sh::setLight(float ambient, const OVec3_f& direction, const OVec3_f& color)
{
    glUniform1f(m_light_ambient, ambient);
    glUniform3f(m_light_color, color.r, color.g, color.b);

    OVec3_f dir = direction;
    dir.normalize();
    glUniform3f(m_light_dir, dir.x, dir.y, dir.z);
}

void Tlake3d_low_1_sh::setEyePos(const OVec3_f& eyePos)
{
    glUniform3f(m_eyePos, eyePos.x, eyePos.y, eyePos.z);
}

void Tlake3d_low_1_sh::setTextures(uint32_t refraction, uint32_t normal, uint32_t reflection)
{
    glActiveTexture(GL_TEXTURE2);
	glBindTexture(GL_TEXTURE_2D, reflection);
    glUniform1i(m_reflectionMap, 2);

    glActiveTexture(GL_TEXTURE1);
    glBindTexture(GL_TEXTURE_2D, normal);
   	glUniform1i(m_normalMap, 1);

    glActiveTexture(GL_TEXTURE0);
    glBindTexture(GL_TEXTURE_2D, refraction);
   	glUniform1i(m_refractionMap, 0);

    //glActiveTexture(GL_TEXTURE0);
}

//0.0->1.0
void Tlake3d_low_1_sh::setSpecularIntensity(float intensity)
{
    glUniform1f(m_specularIntensity, intensity);
}

//0->100 etendue/petit point
void Tlake3d_low_1_sh::setSpecularPower(float power)
{
    glUniform1f(m_specularPower, power);
}

void Tlake3d_low_1_sh::setTurbidity(float value)
{
    glUniform1f(m_turbidity, value);
}

void Tlake3d_low_1_sh::setRepeatNormal(float value)
{
    glUniform1f(m_repeatNormal, value);
}

// m_time +1.0f
void Tlake3d_low_1_sh::setTime(float value)
{
    glUniform1f(m_time, value);
}

void Tlake3d_low_1_sh::setWind(float dx, float dy)
{
    glUniform2f(m_wind_dir, dx, dy);
}


// --- shader pour l'affichage eau dans le stencil ---

static const char* pVS_w = " \n\
#version 330 core \n\
 \n\
layout (location = 0) in vec3 in_vertex; \n\
layout (location = 1) in vec3 in_normal; \n\
layout (location = 2) in vec2 in_uv; \n\
layout (location = 3) in mat4 in_model; \n\
 \n\
uniform mat4 uVP; \n\
uniform mat4 uModel; \n\
uniform bool uMulti = false; \n\
 \n\
void main() \n\
{ \n\
    if (uMulti) \n\
    { \n\
        gl_Position = uVP * in_model * vec4(in_vertex, 1.0); \n\
    } \n\
    else \n\
    { \n\
        gl_Position = uVP * uModel * vec4(in_vertex, 1.0); \n\
    } \n\
}";


static const char* pFS_w = " \n\
#version 330 core \n\
 \n\
out vec4 out_color; \n\
 \n\
void main(){ \n\
    out_color = vec4(1,1,1,1); \n\
}";



Tlake3d_low_1_shw::Tlake3d_low_1_shw()
{
	//
}

bool Tlake3d_low_1_shw::create()
{
    if (!OShader::init())
    {
        ECO_error_set("echec init Tlake3d_low_1_shw");
        return false;
    }
    if (!addShader(GL_VERTEX_SHADER, pVS_w))
    {
        ECO_error_set("echec add vertex Tlake3d_low_1_shw");
        return false;
    }
    if (!addShader(GL_FRAGMENT_SHADER, pFS_w))
    {
        ECO_error_set("echec add fragment Tlake3d_low_1_shw");
        return false;
    }
    if (!finalize())
    {
        ECO_error_set("echec finalize Tlake3d_low_1_shw");
        return false;
    }

    m_vp = getUniformLocation("uVP");
    m_model = getUniformLocation("uModel");
    m_multi = getUniformLocation("uMulti");

/*
	if (m_vp == INVALID_UNIFORM_LOCATION
    || m_model == INVALID_UNIFORM_LOCATION
    || m_multi == INVALID_UNIFORM_LOCATION
    || m_colorGray == INVALID_UNIFORM_LOCATION
    || m_colorMul == INVALID_UNIFORM_LOCATION
    || m_colorMap == INVALID_UNIFORM_LOCATION
    || m_normalMap == INVALID_UNIFORM_LOCATION
    || m_specularMap == INVALID_UNIFORM_LOCATION
    )
    {
        ECO_error_set("Echec Tlake3d_low_1_shw");
        return false;
    }
*/
    return true;
}

void Tlake3d_low_1_shw::setVP(const OMat4& vp)
{
    glUniformMatrix4fv(m_vp, 1, GL_TRUE, vp.getFv());
}

void Tlake3d_low_1_shw::setModel(const OMat4& model)
{
    glUniformMatrix4fv(m_model, 1, GL_TRUE, model.getFv());
}

void Tlake3d_low_1_shw::setMulti(bool mode)
{
    glUniform1i(m_multi, mode);
}

