Эффект воды GLSL С++ OpenGL

Программа

Если кто-то решит помочь кодом

  • Обновить шейдер - F6

Управление

  • ESC Скрыть/Показать интерфейс
  • Стрелки - движение
  • Мышь - вращение
  • f5 Обновить шейдеры и простые текстуры и меш, шейдеры .
  • f6 Перезагрузить только шейдеры

  • Загрузить нормальные текстуры кнопка в окне Height S.. Load big...

Пытаюсь сделать воду без кучи непонятных мне формул. Делаю все через шейдеры, Прошу помощи понятной идеей на русском. Английский не знаю.

Сейчас суть такова, Я в вершинном шейдере в зависимости от позиции вершины и времени применил эффект синуса и косинуса наварист, для имитации псевдо преломления.

В вершинном крашу все что ниже линии океана в цвет океана с коэффициентом поверх картинки конечно. Эффект не очень ели честно. Возможно есть что-то лучше синуса?

У меня меша океана нет вообще если честно, только иллюзия, так можно делать?

Возможно что-то простое как синус и косинус лучше имитирует волны?


Над водой

введите сюда описание изображения


И под водой

введите сюда описание изображения

Вершинный

    #version 330 core
    layout (location = 0) in vec3 aPos;
    layout (location = 1) in vec3 aNormal;
    layout (location = 2) in vec2 aTexCoords;
    
    layout (location = 3) in vec3 aTangent;
    layout (location = 4) in vec3 aBitangent;  
    
    out vec3 fragPos;
    out vec3 Normal;
    out vec2 TexCoords;
    out mat3 TBN;
    
    uniform mat4 model;
    uniform mat4 view;
    uniform mat4 projection;
    
    uniform float Time;
    
    uniform float HeightOcean;
    uniform float IntrvalOcean;
    uniform bool EnableOcean;
    uniform vec3 ColorOcean;
    //пОЗИЦИЯ КАМЕРЫ
    uniform vec3 CamPos;
    
    
    void main()
    {
    
        //Вершина для модефикаций
        vec3 NaPos = aPos ;
        
        
        //Даные для отправки в фрагментный
        fragPos = vec3(model * vec4(NaPos, 1.0));
        Normal = mat3(transpose(inverse(model))) * aNormal;  
        TexCoords = aTexCoords;
        
        vec3 T = normalize(vec3(model * vec4(aTangent,   0.0)));
        vec3 B = normalize(vec3(model * vec4(aBitangent, 0.0)));
        vec3 N = normalize(vec3(model * vec4(aNormal,    0.0)));
        TBN = mat3(T, B, N);;    
          
        if(EnableOcean)
        {
            //float NIntrvalOcean = IntrvalOcean;
            
            
            
            float NIntrvalOcean = (1 - (NaPos.y / HeightOcean ))*IntrvalOcean;
            
            if(NaPos.y < HeightOcean-0.1)
            {
                float MOD = sin(Time*2+NaPos.x)*NIntrvalOcean + cos(Time*1+NaPos.z)*NIntrvalOcean;
            NaPos.y = NaPos.y;
        

        float DistVN = HeightOcean - NaPos.y;
        
        //Если персонаж ниже уровня моря
        if(CamPos.y>HeightOcean)
        NaPos.y = (NaPos.y + DistVN / 3) + MOD; //Немного убераем глубину и делаем преломления
        else
        NaPos.y = NaPos.y + MOD/5; //Камера под водой, ефект преломления меньше ПСЕВДО ПРЕЛОМЛЕНИЕ ДАЖЕ ПАРОДИЯ НА ЕТО
        }
        else
        {
            if(CamPos.y<=HeightOcean) //Преломления уже на поверхности ясли камера под водой
            {
                float MOD = sin(Time*2+NaPos.x)*NIntrvalOcean + cos(Time*1+NaPos.z)*NIntrvalOcean;
                NaPos.y  = NaPos.y  +MOD;
            }
        }
    }
        
        
    //Применить трашсформации и отправить по конвееру
    gl_Position = projection * view * model * vec4(NaPos, 1.0);
}

Фрагментный

#version 330 core
out vec4 FragColor;


//Сколько каких источников
#define NR_POINT_LIGHTS 50
#define NR_SPOT_LIGHTS 10
#define NR_DIR_LIGHTS 2


//Матеріал 
struct Material {
    sampler2D diffuse;
    sampler2D specular;
    sampler2D normalMap;
    float shininess;
}; 

struct DirLight {
    bool enable;
    vec3 direction;
    vec3 ambient;
    vec3 diffuse;
    vec3 specular;
};

struct PointLight {
    bool enable;
    vec3 position;
    
    float constant;
    float linear;
    float quadratic;
    
    vec3 ambient;
    vec3 diffuse;
    vec3 specular;
};

struct SpotLight {
    bool enable;
    vec3 position;
    vec3 direction;
    float cutOff;
    float outerCutOff;
  
    float constant;
    float linear;
    float quadratic;
  
    vec3 ambient;
    vec3 diffuse;
    vec3 specular;       
};

struct FogST
{
    bool enable;
    vec3 fogColor;
    float heightMax;
    float heightMin; 
    float startFog;
    float endFog;
};

vec3 FonLight;

in vec3 fragPos;
in vec3 Normal;
in vec2 TexCoords;
in mat3 TBN;

//Модефикатор текстур
vec2 texCoords;

//Позиция камеры
uniform vec3 CamPos;

uniform DirLight dirLight[NR_DIR_LIGHTS];
uniform PointLight pointLights[NR_POINT_LIGHTS];
uniform SpotLight spotLight[NR_SPOT_LIGHTS];
uniform vec3 fonLight  = vec3(0.1,0.1,0.1);
uniform Material material;
//Использовать текстуру нормалей ?
uniform bool NormalMapEnable = true;

//Смещение текстур
uniform vec2 ModTextCords = vec2(0,0);

//Туман
uniform FogST Fog;

//Свет
uniform bool lightEnable = true;

// function prototypes
vec3 CalcDirLight(DirLight light, vec3 normal, vec3 viewDir);
vec3 CalcPointLight(PointLight light, vec3 normal, vec3 fragPos, vec3 viewDir);
vec3 CalcSpotLight(SpotLight light, vec3 normal, vec3 fragPos, vec3 viewDir);

//Experemental
uniform float HeightOcean;
uniform float IntrvalOcean;
uniform bool EnableOcean;
uniform vec3 ColorOcean;

void main()
{    
vec3 result; //Результат цвета 

vec3 viewPos = CamPos;
//vec3 viewPos = ViewPos;
vec3 FragPos = fragPos;

//Камера под водой?
bool OceanCam = viewPos.y<= HeightOcean;

//Растояние между точкой и камирой
float DisF = distance(viewPos,FragPos);
//Коефициент тумана
  if(Fog.enable)
  {

        if(DisF > Fog.startFog) //Толька после начала
        {
            DisF = (DisF-Fog.startFog) /(Fog.endFog-Fog.startFog);
        }
        else
        if(DisF > Fog.endFog) //если конец тумана 
        {
            DisF = 1; //100%
        }
        else //Тут нет тумана
        {
            DisF = 0;
        }
        
        //Высота тумана
        //float Heigh = distance(viewPos.y,FragPos.y);
        //Потом удалить зависимость от камеры возможно
        
        float Max = Fog.heightMax + viewPos.y;
        float Min = Fog.heightMin + viewPos.y;
        float Point = FragPos.y;
        
         if(Point<HeightOcean) //На воде уменньшыть туман
             DisF = DisF*0.7;
        
        if(Point > Max) DisF = 0;
        else
        if(DisF>1)
            DisF = 1; //Нормализация
        //if(Point < Min) DisF = 0;
        float MixC = 1;
        
        //Здвиг в 0
        float Nmax = Max - Min;
        float Npoint = Point - Min;
        
        
        MixC = 1-(Npoint / Nmax) ;//  (Point-Min)-((Max - Min ) / Max);
        
        DisF = DisF*MixC;
        
        //if(FragPos.y<Fog.heightMax && FragPos.y>Fog.heightMin)
        // DisF = DisF * (1/(Fog.heightMax-Fog.heightMin));
        
        
        //(DisF-Fog.startFog) /(Fog.endFog-Fog.startFog);
        
        

        if(DisF>=1) { //Не делать расчеты света бесполезно там уже 100 тумана
           FragColor = vec4(Fog.fogColor, 1.0);
           return;
        }
  }
  
//Здвиг
texCoords = TexCoords + ModTextCords;

if(lightEnable)
{

    vec3 viewDir = normalize(viewPos - FragPos);
    vec3 norm;
    if(NormalMapEnable)
    {
    // преобразование из диапазона [-1,1] в диапазон [0,1]  
    vec3 normRGB = texture(material.normalMap, texCoords).rgb * 2 -1;
    norm =  normalize(TBN * normRGB); 
    }
    else
    {
        norm = Normal;
    }


        //фон
        result = vec3(texture(material.diffuse, texCoords)) * fonLight;

        // phase 1: direct 
        for(int i = 0; i < NR_DIR_LIGHTS; i++)
        if(dirLight[i].enable)
        result += CalcDirLight(dirLight[i], norm, viewDir);
        

        // phase 2: point lights
        for(int i = 0; i < NR_POINT_LIGHTS; i++)
        if(pointLights[i].enable)
            result += CalcPointLight(pointLights[i], norm, FragPos, viewDir); 
        // phase 3: spot light
        for(int i = 0; i < NR_SPOT_LIGHTS; i++)
        if(spotLight[i].enable)
        result += CalcSpotLight(spotLight[i], norm, FragPos, viewDir);    
      
}
else //Отключен свет значит только текстура
{
    result = vec3(texture(material.diffuse, texCoords));
}


{
    float Point = FragPos.y;
    
    bool PointOcean = Point<HeightOcean; //Точка под водой
    
    if(OceanCam && !PointOcean) //Камера под водой
    {
        result = mix(result,ColorOcean,  0.7 );
    }
        
    if(PointOcean)
    {
        
        //float DisF = distance(viewPos,FragPos);
        float Cof =  1-Point/HeightOcean+0.4; //Закрасить дно
        if(Cof>1) Cof = 1;
        
        float DisVF = distance(viewPos,FragPos); //Растояние между камерой и точкой
         Cof = Cof * (DisVF/50);
         if(Cof>1)Cof = 1;
        
        result = mix(result, ColorOcean , Cof  );
    }
}

//if(OceanCam)
//result = mix(result,ColorOcean,  0.5 );

  
  //if(distance(viewPos,FragPos)>50)
      
  if(Fog.enable) //Применить туман
  {
    result = mix(result,Fog.fogColor,  DisF  ); //
    }  
  
  
    //Альфа с цветной текстуры
   FragColor = vec4(result, texture(material.diffuse, texCoords)[3]);

    
    //FragColor = texture(material.diffuse, texCoords);
}

// 00000 calculates the color when using a directional light.
vec3 CalcDirLight(DirLight light, vec3 normal, vec3 viewDir)
{
   vec3 lightDir = normalize(-light.direction);
   

   float diff = 1;
  
    diff   = max(dot(normal, lightDir), 0.0);
    //diff   = max(dot(Normal, lightDir), 0.0);
   
   
    vec3 reflectDir = reflect(-lightDir, normal);  
    float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess);
    vec3 specular = light.specular * spec * texture(material.specular, texCoords).rgb;  
    

    vec3 diffuse = light.diffuse * vec3(texture(material.diffuse, texCoords)) * diff;
    //vec3 specular = light.specular  * vec3(texture(material.specular, texCoords));
    return diffuse + specular + light.ambient * vec3(texture(material.diffuse, texCoords))  ;
}

// calculates the color when using a point light.
vec3 CalcPointLight(PointLight light, vec3 normal, vec3 fragPos, vec3 viewDir)
{
    vec3 lightDir = normalize(light.position - fragPos);
    // diffuse shading
    float diff = max(dot(normal, lightDir), 0.0);
    // specular shading
    vec3 reflectDir = reflect(-lightDir, normal);
    float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess);
    // attenuation
    float distance = length(light.position - fragPos);
    float attenuation = 1.0 / (light.constant + light.linear * distance + light.quadratic * (distance * distance));    
    // combine results
  //  vec3 ambient = light.ambient * vec3(texture(material.diffuse, texCoords));
    vec3 diffuse = light.diffuse * diff * vec3(texture(material.diffuse, texCoords));
    vec3 specular = light.specular * spec * vec3(texture(material.specular, texCoords));
    
    diffuse *= attenuation;
    specular *= attenuation;
    return (diffuse + specular);
}

// calculates the color when using a spot light.
vec3 CalcSpotLight(SpotLight light, vec3 normal, vec3 fragPos, vec3 viewDir)
{
    vec3 lightDir = normalize(light.position - fragPos);
    // diffuse shading
    float diff = max(dot(normal, lightDir), 0.0);
    // specular shading
    vec3 reflectDir = reflect(-lightDir, normal);
    float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess);
    // attenuation
    float distance = length(light.position - fragPos);
    float attenuation = 1.0 / (light.constant + light.linear * distance + light.quadratic * (distance * distance));    
    // spotlight intensity
    float theta = dot(lightDir, normalize(-light.direction)); 
    float epsilon = light.cutOff - light.outerCutOff;
    float intensity = clamp((theta - light.outerCutOff) / epsilon, 0.0, 1.0);
    // combine results
    vec3 ambient = light.ambient * vec3(texture(material.diffuse, texCoords));
    vec3 diffuse = light.diffuse * diff * vec3(texture(material.diffuse, texCoords));
    vec3 specular = light.specular * spec * vec3(texture(material.specular, texCoords));
    
    ambient *= attenuation * intensity;
    diffuse *= attenuation * intensity;
    specular *= attenuation * intensity;
    return (ambient + diffuse + specular);
}

Ответы (0 шт):