18/shaders/gshader.frag

111 lines
4.6 KiB
GLSL
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#version 420 core
layout(std140, binding = 1) uniform Material
{
vec3 ka;
vec3 kd;
vec3 ks;
float p;
bool normalmapped;
bool parallaxmapped;
bool displacementmapped;
};
layout (location = 0) out vec3 gPosition;
layout (location = 1) out vec3 gNormal;
layout (location = 2) out vec4 gDiffuseP;
layout (location = 3) out vec4 gAmbientSpecular;
layout (location = 4) out uvec3 gID;
in vec3 vertex; // Позиция вершины в пространстве
in vec3 N; // Нормаль трансформированноая
in vec2 texCoord; // Текстурные координаты
in vec3 T; // Касательный вектор
in vec3 B; // Бикасательный вектор
in vec3 view; // Вектор от поверхности к камере
uniform sampler2D tex_diffuse;
uniform sampler2D tex_ambient;
uniform sampler2D tex_specular;
uniform sampler2D tex_heights;
uniform sampler2D tex_normal;
uniform float parallax_heightScale = 0.1;
uniform uvec3 ID = uvec3(0);
void main()
{
// Сформируем TBN матрицу
mat3 TBN = mat3(T, B, N);
// Перевод вектора в касательное пространство
vec3 viewTBN = normalize(transpose(TBN) * view);
// Измененные текстурные координаты
vec2 new_texCoord = texCoord;
// Сохранение позиции фрагмента в G-буфере
gPosition = vertex;
if (parallaxmapped)
{
// Число слоев
float layersCount = 32;
// Вычислим размер каждого слоя
float layerDepth = 1.0 / layersCount;
// Глубина текущего слоя
float currentLayerDepth = 0.0;
// Величина сдвига между слоями
vec2 deltaTexCoords = (parallax_heightScale * viewTBN.xy / viewTBN.z) / layersCount;
// Переменные для вычислений
vec2 currentTexCoords = texCoord;
float currentDepthMapValue = 1.0 - texture(tex_heights, currentTexCoords).r;
// Пока глубина текущего слоя меньше текущего значения глубины из текстуры
while(currentLayerDepth < currentDepthMapValue)
{
// Сдвигаем координаты
currentTexCoords -= deltaTexCoords;
// Обновляем значение глубины из текстуры
currentDepthMapValue = 1.0 - texture(tex_heights, currentTexCoords).r;
// Сдвигаем глубину на следующий слой
currentLayerDepth += layerDepth;
}
// Получим значение текстурных координат с предыдущего шага
vec2 prevTexCoords = currentTexCoords + deltaTexCoords;
// Значения глубины до и после пересечения
float afterDepth = currentDepthMapValue - currentLayerDepth;
float beforeDepth = 1.0 - texture(tex_heights, prevTexCoords).r - currentLayerDepth + layerDepth;
// Интерполяция текстурных координат
float weight = afterDepth / (afterDepth - beforeDepth);
new_texCoord = prevTexCoords * weight + currentTexCoords * (1.0 - weight);
// Проверка диапазона [0;1]
if(new_texCoord.x > 1.0 || new_texCoord.y > 1.0 || new_texCoord.x < 0.0 || new_texCoord.y < 0.0)
discard;
}
// Сохранение нормали в G-буфере
gNormal = N;
// Если используется карта нормалей
if (normalmapped)
{
// Получим значение из карты нормалей и приведем их к диапазону [-1;1]
gNormal = texture(tex_normal, new_texCoord).rgb * 2 - 1.0f;
gNormal = normalize(TBN * gNormal); // Из касательного пространства в мировые координаты
}
// Сохранение диффузного цвета
gDiffuseP.rgb = texture(tex_diffuse, new_texCoord).rgb * kd;
// Сохранение глянцевости
gDiffuseP.a = p;
// Сохранение фоновой составляющей
gAmbientSpecular.rgb = texture(tex_ambient, new_texCoord).rgb * ka;
// Сохранение зеркальной составляющей
gAmbientSpecular.a = texture(tex_specular, new_texCoord).r * ks.r;
// Сохранение идентификатора объекта
gID = ID;
}