Эффект воды 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);
}

