
#include "Tsea3d_low_1.h"

// shader et plan en fin

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

Tsea3d_low_1::Tsea3d_low_1()
{
	//
}

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

Tsea3d_low_1::~Tsea3d_low_1()
{
    //
}


void Tsea3d_low_1::create(int size, float scale_uv)
{
    s_texParam texParam;

	OTextureList::P_setPath(PATH_IMAGE);
	OTextureList::P_setMipmap(true);

    textureList.add("colorMap1.png");
    //textureList.add("colorMap2.png");

    OTextureList::P_setMipmap(false);

    texParam = textureList.getParam("colorMap1.png");
    //texParam = textureList.getID("colorMap2.png");

    m_reflectionMap = texParam.id;

    // ---

    plan.create(size, scale_uv);

    // ---

    shSea3d_low.create();
    shSea3d_low.enable();
        shSea3d_low.setSizeTexture(texParam.w);

    shSea3d_low_w.create();
    m_time = 0.0f;

}





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

    glDisable(GL_CULL_FACE);

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

            shSea3d_low.setTime(m_time);
            shSea3d_low.setEyePos(eyePos);
            shSea3d_low.setTextures(refractionMap, m_reflectionMap);

            plan.draw();

        shSea3d_low.disable();
        return;
    }

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

        shSea3d_low.setTime(m_time);
        shSea3d_low.setEyePos(eyePos);
        shSea3d_low.setTextures(refractionMap, m_reflectionMap);

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

    shSea3d_low.disable();
}

void Tsea3d_low_1::draw_water_reflection(OMat4& vp)
{
    glDisable(GL_CULL_FACE);

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

            plan.draw();

        shSea3d_low_w.disable();
        return;
    }

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

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

    shSea3d_low_w.disable();
}




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



// --- grille map plan carte


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

Tsea3d_low_1_plan::Tsea3d_low_1_plan()
{
    //
}

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

Tsea3d_low_1_plan::~Tsea3d_low_1_plan()
{
    //
}

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

// px py pz
void Tsea3d_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]);

	m_pos[idx] *= 2; // scale_col
    _setModel(idx);
}

// px py pz
void Tsea3d_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);
    m_pos[idx] *= 2;    // scale_col
    _setModel(idx);
}





void Tsea3d_low_1_plan::create(uint32_t size, float scale_uv)
{
    float scale_col = 2.0f; // 2 mètres entre sommets
    //float scale_uv = (1.0f / (float)size) * 50.0f; // 0.5 pour une image 1024*124 et grille 100 > vue de loin

    // ---

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

    _setModel(0);

    // ---

    m_vertex.reserve(size*size);
    m_normal.reserve(size*size);
    m_uv.reserve(size*size);
	m_indice.reserve(size*size*6);
    int idx = 0;

	for (uint32_t j = 0; j <= size; ++j)
	{
		for (uint32_t i = 0; i <= size; ++i)
		{
            // z verticale
			m_vertex.push_back(OVec3_f());
			//m_vertex[idx].x = (((float)i / (float)size) - 0.5f) * size * scale_col;
			//m_vertex[idx].y = (((float)j / (float)size) - 0.5f) * size * scale_col;
			m_vertex[idx].x = ((((float)i / (float)size) - 0.5f) * size * scale_col) + (ECO_rnd_f(0.5f)-0.25f);
			m_vertex[idx].y = ((((float)j / (float)size) - 0.5f) * size * scale_col) + (ECO_rnd_f(0.5f)-0.25f);
			m_vertex[idx].z = 0.0f;

            m_normal.push_back(OVec3_f());
			m_normal[idx].set(0.5f, 0.5f, 1.0f);

			m_uv.push_back(OVec2_f());
			m_uv[idx].set(static_cast<float>(i) / static_cast<float>(size*scale_uv), static_cast<float>(j) / static_cast<float>(size*scale_uv));

            idx++;
		}
	}

	for (uint32_t j = 0; j < size; ++j)
	{
		for (uint32_t i = 0; i < size; ++i)
		{
			uint32_t row1 = j * (size + 1);
			uint32_t row2 = (j + 1) * (size + 1);

			// triangle 1
			m_indice.push_back(row1 + i);
			m_indice.push_back(row1 + i + 1);
			m_indice.push_back(row2 + i + 1);

			// triangle 2
			m_indice.push_back(row1 + i);
			m_indice.push_back(row2 + i + 1);
			m_indice.push_back(row2 + i);
		}
	}

	_make_vao();
}




void Tsea3d_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 Tsea3d_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& Tsea3d_low_1_plan::getModel()
{
    return m_model[0];
}

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






void Tsea3d_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 Tsea3d_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].scale(1.1f, 1.1, 1.0f); // emboite les bords > il faut ajuster avec la hauteur des vagues 1.1 pour uWave_hight = 2.0
    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 Tsea3d_low_1_plan::setPos(OVec3_f& pos, size_t idx)
{
    m_pos[idx] = pos;
    _setModel(idx);
}

void Tsea3d_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 core   \n\
// thebaud philippe \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 float uTime; \n\
uniform bool uMulti = false; \n\
 \n\
uniform float uWindStrength = 10.0; \n\
uniform float uAgitation = 0.005; \n\
uniform float uWave_hight = 0.4; // 0.1 > 2.0; \n\
uniform float uWave_frequency = 15.0; \n\
 \n\
out vec4 var_clipSpace; \n\
out vec2 var_uv; \n\
out vec3 var_model; \n\
out vec3 var_normal; \n\
out float var_high; \n\
 \n\
void main()  \n\
{ \n\
    vec3 newPosition = in_vertex; \n\
    float time = uTime * uAgitation; \n\
    float wave1 = sin((newPosition.x*uWave_frequency * 0.005) + (time * uWindStrength)) * 0.1; \n\
    float wave2 = cos((newPosition.y*uWave_frequency * 0.01) + (time * uWindStrength)) * 0.15; \n\
    float noise = (sin(newPosition.x + time*20) * cos(newPosition.y - time*20)) * 0.25; \n\
    newPosition.z += ((wave1+wave2)*(uWave_hight*10) + noise); \n\
    \n\
    if (uMulti) \n\
    { \n\
        var_clipSpace = uVP * in_model * vec4(newPosition, 1.0); \n\
        var_model = (in_model * vec4(newPosition, 1.0)).xyz; \n\
        var_normal = (in_model * vec4(in_normal, 1.0)).xyz; \n\
        var_normal = normalize(var_normal); \n\
    } \n\
    else \n\
    { \n\
        var_clipSpace = uVP * uModel * vec4(newPosition, 1.0); \n\
        var_model = (uModel * vec4(newPosition, 1.0)).xyz; \n\
        var_normal = (uModel * vec4(in_normal, 1.0)).xyz; \n\
        var_normal = normalize(var_normal); \n\
    } \n\
 \n\
    var_uv = in_uv + (time*0.01); \n\
    float noise2 = fract(sin(dot(in_uv ,vec2(12.9898,78.233))) * 43758.5453); \n\
    var_high = smoothstep(0.0, 0.4, noise*noise2); \n\
    gl_Position = var_clipSpace; \n\
}";


static const char* pFS = " \n\
#version 330 core \n\
 \n\
in vec4 var_clipSpace; \n\
in vec2 var_uv; \n\
in vec3 var_model; \n\
in vec3 var_normal; \n\
in float var_high; \n\
 \n\
out vec4 out_color; \n\
 \n\
uniform sampler2D uReflectionMap; //water \n\
uniform sampler2D uRefractionMap; //sky \n\
uniform float uTime; \n\
uniform vec3 uEyePos; \n\
uniform float uLight_ambient = 0.75; \n\
uniform vec3 uLight_dir = vec3(-0.5,0.5,-0.5); // z verticale \n\
uniform vec3 uLight_color = vec3(1.0,1.0,0.9); \n\
uniform float uRefractiveFactor = 0.5; \n\
uniform vec4 uReflecColor = vec4(0.5,0.55,0.45,1.0); \n\
uniform float uTurbidity = 0.1;  // 0.01 limpide > 0.1 opaque \n\
uniform int uSizeTexture = 1024; \n\
// quand la reflection n'est pas correctement possitionnée \n\
uniform vec2 uCorrectif_reflection = vec2(1, 0.98); \n\
 \n\
const float shineDamper = 2.5; \n\
const float reflectivity = 1.75; \n\
 \n\
void main() { \n\
    float move = uTime * 0.00015; \n\
    vec3 normal = var_normal; \n\
 \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\
 \n\
    vec4 surfaceColor = texture(uReflectionMap, var_uv); \n\
 \n\
    // === fwidth-based LOD === \n\
    float pixelSize = length(fwidth(var_uv)); \n\
    float lod = clamp(log2(pixelSize * uSizeTexture), 0.0, 6.0); // 1024 = size texture \n\
    vec2 dudv = textureLod(uReflectionMap, vec2(var_uv.x + move, var_uv.y), lod).rg * 0.2; \n\
    vec2 distortedTexCoords = var_uv + vec2(dudv.x, dudv.y + move); \n\
    vec2 totalDistortion = (textureLod(uReflectionMap, distortedTexCoords, lod).rg * 2.0 - 0.95) * 0.2; \n\
    uv_reflection.y += totalDistortion.y; \n\
    vec4 refractColor = texture(uRefractionMap, uv_reflection) * uReflecColor; \n\
 \n\
    // faux eclat de lumiere sur les pointes des vagues \n\
    float fspec = smoothstep(0.25, 0.65, var_high) * 0.25; \n\
 \n\
    vec3 viewVector = normalize(uEyePos - var_model); \n\
    vec3 reflectedLight = reflect(uLight_dir, normal) * var_high; \n\
    float specular = max(dot(reflectedLight, viewVector), 0.0); \n\
    specular = pow(specular, shineDamper); \n\
    vec3 specularHighlights = (uLight_color * specular * reflectivity) + fspec;  \n\
 \n\
    float alpha = length(uEyePos - var_model) * uTurbidity; \n\
    out_color = mix(surfaceColor, refractColor, uRefractiveFactor); \n\
    out_color.a = alpha; \n\
    out_color = (out_color + vec4(specularHighlights,0.0)) * (uLight_ambient + 0.25); // ambient est généralement limité à 0.8 \n\
}";




Tsea3d_low_1_sh::Tsea3d_low_1_sh()
{
	//
}

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

	m_vp = getUniformLocation("uVP");
    m_model = getUniformLocation("uModel");
    m_time = getUniformLocation("uTime");
    m_eyePos = getUniformLocation("uEyePos");
    m_multi = getUniformLocation("uMulti");
    m_sizeTexture = getUniformLocation("uSizeTexture");

    m_refractionMap = getUniformLocation("uRefractionMap");
    m_reflectionMap = getUniformLocation("uReflectionMap");

    m_light_ambient = getUniformLocation("uLight_ambient");
    m_light_dir = getUniformLocation("uLight_dir");
    m_light_color = getUniformLocation("uLight_color");

    m_wave_hight = getUniformLocation("uWave_hight");
    m_wave_frequency = getUniformLocation("uWave_frequency");
    m_turbidity = getUniformLocation("uTurbidity");


/*
    if (m_vp == INVALID_UNIFORM_LOCATION
    || m_model == INVALID_UNIFORM_LOCATION
    || m_time == INVALID_UNIFORM_LOCATION
    || m_eyePos == INVALID_UNIFORM_LOCATION
    || m_refractionMap == INVALID_UNIFORM_LOCATION
    || m_reflectionMap == INVALID_UNIFORM_LOCATION
    || m_normalMap == INVALID_UNIFORM_LOCATION
    || m_waterMap == INVALID_UNIFORM_LOCATION
    || m_light_ambient == INVALID_UNIFORM_LOCATION
    || m_light_dir == INVALID_UNIFORM_LOCATION
    || m_light_color == INVALID_UNIFORM_LOCATION
    || m_turbidity == INVALID_UNIFORM_LOCATION
    || m_waveStrength == INVALID_UNIFORM_LOCATION
    || m_windSpeed == INVALID_UNIFORM_LOCATION
    )
    {
        ECO_error_set("Echec Tsea3d_low_1_sh 0");
        return false;
    }
*/

    return true;
}

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

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




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

void Tsea3d_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 Tsea3d_low_1_sh::setMulti(bool mode)
{
    glUniform1i(m_multi, mode);
}

// texture de la mer
void Tsea3d_low_1_sh::setSizeTexture(int size)
{
    glUniform1i(m_sizeTexture, size);
}

// sky > water
void Tsea3d_low_1_sh::setTextures(uint32_t refraction, uint32_t reflection)
{
    glActiveTexture(GL_TEXTURE1);
	glBindTexture(GL_TEXTURE_2D, reflection);
    glUniform1i(m_reflectionMap, 1);

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

    //glActiveTexture(GL_TEXTURE0);
}

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

// 0.005 > 0.05
void Tsea3d_low_1_sh::setTurbidity(float value)
{
    glUniform1f(m_turbidity, value);
}

void Tsea3d_low_1_sh::setWave(float hight, float frequency)
{
    glUniform1f(m_wave_hight, hight);
    glUniform1f(m_wave_frequency, frequency);
}


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

static const char* pVS_w = " \n\
#version 330 core \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\
uniform float uTime; \n\
uniform float uWindStrength = 10.0; \n\
uniform float uAgitation = 0.005; \n\
uniform float uWave_hight = 0.4; // 0.1 > 2.0; \n\
uniform float uWave_frequency = 15.0; \n\
 \n\
void main() \n\
{ \n\
    vec3 newPosition = in_vertex; \n\
    float time = uTime * uAgitation; \n\
    float wave1 = sin((newPosition.x*uWave_frequency * 0.005) + (time * uWindStrength)) * 0.1; \n\
    float wave2 = cos((newPosition.y*uWave_frequency * 0.01) + (time * uWindStrength)) * 0.15; \n\
    float noise = (sin(newPosition.x + time*20) * cos(newPosition.y - time*20)) * 0.25; \n\
    newPosition.z += ((wave1+wave2)*(uWave_hight*10) + noise); \n\
    \n\
    if (uMulti) \n\
    { \n\
        gl_Position = uVP * in_model * vec4(newPosition, 1.0); \n\
    } \n\
    else \n\
    { \n\
        gl_Position = uVP * uModel * vec4(newPosition, 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\
}";



Tsea3d_low_1_shw::Tsea3d_low_1_shw()
{
	//
}

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

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

/*
	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 Tsea3d_low_1_shw");
        return false;
    }
*/
    return true;
}

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

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

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

void Tsea3d_low_1_shw::setTime(float value)
{
    glUniform1f(m_time, value);
}





