Compare commits

..

9 Commits
v0.1 ... master

10 changed files with 201 additions and 50 deletions

View File

@ -12,8 +12,7 @@
], ],
"compilerPath": "C:/MinGW/bin/g++.exe", "compilerPath": "C:/MinGW/bin/g++.exe",
"cStandard": "c11", "cStandard": "c11",
"cppStandard": "c++11", "cppStandard": "c++11"
"intelliSenseMode": "gcc-x86"
} }
], ],
"version": 4 "version": 4

View File

@ -63,8 +63,11 @@ struct Material
alignas(16) glm::vec3 kd; // коэф. диффузного отражения (цвет объекта) alignas(16) glm::vec3 kd; // коэф. диффузного отражения (цвет объекта)
alignas(16) glm::vec3 ks; // коэф. зеркального блика alignas(16) glm::vec3 ks; // коэф. зеркального блика
float p; // показатель глянцевости float p; // показатель глянцевости
int normalmapped; // Использование карт нормалей
int parallaxmapped; // Использование параллакса
int displacementmapped; // Использование карт высот для сдвига вершин
// Значения по умолчанию // Значения по умолчанию
Material() : ka(0.2f), kd(0.2f), ks(0.2f), p(1) { }; Material() : ka(0.2f), kd(0.2f), ks(0.2f), p(1), normalmapped(false), parallaxmapped(false), displacementmapped(false) { };
}; };
// Класс модели // Класс модели
@ -99,6 +102,8 @@ class Model : public Node
Texture texture_diffuse; // Диффузная текстура Texture texture_diffuse; // Диффузная текстура
Texture texture_ambient; // Текстура фонового освщения Texture texture_ambient; // Текстура фонового освщения
Texture texture_specular; // Текстура зеркального отражения Texture texture_specular; // Текстура зеркального отражения
Texture texture_heights; // Текстура высот
Texture texture_normals; // Текстура нормалей
}; };
#endif // MODEL_H #endif // MODEL_H

View File

@ -10,6 +10,8 @@ enum TexType {
TEX_DIFFUSE, TEX_DIFFUSE,
TEX_AMBIENT, TEX_AMBIENT,
TEX_SPECULAR, TEX_SPECULAR,
TEX_HEIGHTS,
TEX_NORMAL,
TEX_AVAILABLE_COUNT TEX_AVAILABLE_COUNT
}; };

View File

@ -6,6 +6,9 @@ layout(std140, binding = 1) uniform Material
vec3 kd; vec3 kd;
vec3 ks; vec3 ks;
float p; float p;
bool normalmapped;
bool parallaxmapped;
bool displacementmapped;
}; };
in vec3 pos_local; in vec3 pos_local;

View File

@ -6,6 +6,9 @@ layout(std140, binding = 1) uniform Material
vec3 kd; vec3 kd;
vec3 ks; vec3 ks;
float p; float p;
bool normalmapped;
bool parallaxmapped;
bool displacementmapped;
}; };
layout (location = 0) out vec3 gPosition; layout (location = 0) out vec3 gPosition;
@ -16,23 +19,88 @@ layout (location = 3) out vec4 gAmbientSpecular;
in vec3 vertex; // Позиция вершины в пространстве in vec3 vertex; // Позиция вершины в пространстве
in vec3 N; // Нормаль трансформированноая in vec3 N; // Нормаль трансформированноая
in vec2 texCoord; // Текстурные координаты in vec2 texCoord; // Текстурные координаты
in vec3 T; // Касательный вектор
in vec3 B; // Бикасательный вектор
in vec3 view; // Вектор от поверхности к камере
uniform sampler2D tex_diffuse; uniform sampler2D tex_diffuse;
uniform sampler2D tex_ambient; uniform sampler2D tex_ambient;
uniform sampler2D tex_specular; uniform sampler2D tex_specular;
uniform sampler2D tex_heights;
uniform sampler2D tex_normal;
uniform float parallax_heightScale = 0.1;
void main() void main()
{ {
// Сформируем TBN матрицу
mat3 TBN = mat3(T, B, N);
// Перевод вектора в касательное пространство
vec3 viewTBN = normalize(transpose(TBN) * view);
// Измененные текстурные координаты
vec2 new_texCoord = texCoord;
// Сохранение позиции фрагмента в G-буфере // Сохранение позиции фрагмента в G-буфере
gPosition = vertex; 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-буфере // Сохранение нормали в G-буфере
gNormal = N; 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, texCoord).rgb * kd; gDiffuseP.rgb = texture(tex_diffuse, new_texCoord).rgb * kd;
// Сохранение глянцевости // Сохранение глянцевости
gDiffuseP.a = p; gDiffuseP.a = p;
// Сохранение фоновой составляющей // Сохранение фоновой составляющей
gAmbientSpecular.rgb = texture(tex_ambient, texCoord).rgb * ka; gAmbientSpecular.rgb = texture(tex_ambient, new_texCoord).rgb * ka;
// Сохранение зеркальной составляющей // Сохранение зеркальной составляющей
gAmbientSpecular.a = texture(tex_specular, texCoord).r * ks.r; gAmbientSpecular.a = texture(tex_specular, new_texCoord).r * ks.r;
} }

View File

@ -3,6 +3,8 @@
layout(location = 0) in vec3 pos; layout(location = 0) in vec3 pos;
layout(location = 1) in vec2 inTexCoord; layout(location = 1) in vec2 inTexCoord;
layout(location = 2) in vec3 normals; layout(location = 2) in vec3 normals;
layout(location = 3) in vec3 tangent;
layout(location = 4) in vec3 bitangent;
layout(std140, binding = 0) uniform Camera layout(std140, binding = 0) uniform Camera
{ {
@ -11,11 +13,28 @@ layout(std140, binding = 0) uniform Camera
vec3 position; vec3 position;
} camera; } camera;
layout(std140, binding = 1) uniform Material
{
vec3 ka;
vec3 kd;
vec3 ks;
float p;
bool normalmapped;
bool parallaxmapped;
bool displacementmapped;
};
uniform sampler2D tex_heights;
uniform float displacement_heightScale = 0.1;
uniform mat4 model; uniform mat4 model;
out vec3 vertex; // Позиция вершины в пространстве out vec3 vertex; // Позиция вершины в пространстве
out vec3 N; // Нормаль трансформированноая out vec3 N; // Нормаль трансформированноая
out vec2 texCoord; // Текстурные координаты out vec2 texCoord; // Текстурные координаты
out vec3 T; // Касательный вектор
out vec3 B; // Бикасательный вектор
out vec3 view; // Вектор от поверхности к камере
void main() void main()
{ {
@ -26,5 +45,16 @@ void main()
texCoord = inTexCoord; // Текстурные координаты texCoord = inTexCoord; // Текстурные координаты
T = normalize(mat3(model) * tangent);
B = normalize(mat3(model) * bitangent);
view = camera.position - vertex;
if (displacementmapped)
{
float height = texture(tex_heights, texCoord).r * displacement_heightScale;
P.xyz += mat3(T, B, N) * vec3(0, 0, height);
}
gl_Position = camera.projection * camera.view * P; gl_Position = camera.projection * camera.view * P;
} }

View File

@ -215,6 +215,7 @@ verteces_count(copy.verteces_count), first_index_byteOffset(copy.first_index_byt
vertex_vbo(copy.vertex_vbo), index_vbo(copy.index_vbo), normals_vbo(copy.normals_vbo), texCoords_vbo(copy.texCoords_vbo), vertex_vbo(copy.vertex_vbo), index_vbo(copy.index_vbo), normals_vbo(copy.normals_vbo), texCoords_vbo(copy.texCoords_vbo),
tangent_vbo(copy.tangent_vbo), bitangent_vbo(copy.bitangent_vbo), tangent_vbo(copy.tangent_vbo), bitangent_vbo(copy.bitangent_vbo),
texture_diffuse(copy.texture_diffuse), texture_ambient(copy.texture_ambient), texture_specular(copy.texture_specular), texture_diffuse(copy.texture_diffuse), texture_ambient(copy.texture_ambient), texture_specular(copy.texture_specular),
texture_heights(copy.texture_heights), texture_normals(copy.texture_normals),
material(copy.material) material(copy.material)
{ {
@ -241,6 +242,9 @@ Model& Model::operator=(const Model& other)
texture_ambient = other.texture_ambient; texture_ambient = other.texture_ambient;
texture_specular = other.texture_specular; texture_specular = other.texture_specular;
texture_heights = other.texture_heights;
texture_normals = other.texture_normals;
material = other.material; material = other.material;
return *this; return *this;
@ -277,7 +281,8 @@ void Model::render(ShaderProgram &shaderProgram, UBO &material_buffer)
texture_diffuse.use(); texture_diffuse.use();
texture_ambient.use(); texture_ambient.use();
texture_specular.use(); texture_specular.use();
texture_heights.use();
texture_normals.use();
// Загружаем данные о материале // Загружаем данные о материале
material_buffer.load(&material, sizeof(material)); material_buffer.load(&material, sizeof(material));
@ -405,6 +410,12 @@ void Model::set_texture(Texture& texture)
case TEX_SPECULAR: case TEX_SPECULAR:
texture_specular = texture; texture_specular = texture;
break; break;
case TEX_HEIGHTS:
texture_heights = texture;
break;
case TEX_NORMAL:
texture_normals = texture;
break;
}; };
} }

View File

@ -222,6 +222,10 @@ Scene loadOBJtoScene(const char* filename, const char* mtl_directory, const char
s->set_texture(ambient); s->set_texture(ambient);
Texture specular(TEX_SPECULAR, texture_directory + materials[materials_ids[i]].specular_texname); Texture specular(TEX_SPECULAR, texture_directory + materials[materials_ids[i]].specular_texname);
s->set_texture(specular); s->set_texture(specular);
Texture normal(TEX_NORMAL, texture_directory + materials[materials_ids[i]].normal_texname);
s->set_texture(normal);
Texture heights(TEX_HEIGHTS, texture_directory + materials[materials_ids[i]].bump_texname);
s->set_texture(heights);
// Материал // Материал
s->material.ka = pow(glm::vec3(materials[materials_ids[i]].ambient[0], materials[materials_ids[i]].ambient[1], materials[materials_ids[i]].ambient[2]), glm::vec3(1/inv_gamma)); s->material.ka = pow(glm::vec3(materials[materials_ids[i]].ambient[0], materials[materials_ids[i]].ambient[1], materials[materials_ids[i]].ambient[2]), glm::vec3(1/inv_gamma));

View File

@ -28,11 +28,34 @@ Texture::Texture(GLuint t, const std::string& filename)
// Если изображение успешно считано // Если изображение успешно считано
if (image) if (image)
{ {
// Загрузка данных с учетом прозрачности // Выбор формата с учетом типа текстуры (нормали не sRGB) и числа каналов
if (channels == 3) // RGB GLuint internalformat = GL_RGB, format = GL_RGB;
glTexImage2D(GL_TEXTURE_2D, 0, GL_SRGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, image); switch (channels)
else if (channels == 4) // RGBA {
glTexImage2D(GL_TEXTURE_2D, 0, GL_SRGB_ALPHA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, image); case 1:
internalformat = format = GL_RED;
break;
case 2:
internalformat = format = GL_RG;
break;
case 3:
format = GL_RGB;
if (type == TEX_NORMAL || type == TEX_HEIGHTS)
internalformat = GL_RGB;
else
internalformat = GL_SRGB;
break;
case 4:
format = GL_RGBA;
if (type == TEX_NORMAL || type == TEX_HEIGHTS)
internalformat = GL_RGBA;
else
internalformat = GL_SRGB_ALPHA;
break;
}
// Загрузка данных с учетом формата
glTexImage2D(GL_TEXTURE_2D, 0, internalformat, width, height, 0, format, GL_UNSIGNED_BYTE, image);
glGenerateMipmap(GL_TEXTURE_2D); // Генерация мипмапа для активной текстуры glGenerateMipmap(GL_TEXTURE_2D); // Генерация мипмапа для активной текстуры
glBindTexture(GL_TEXTURE_2D, 0); // Отвязка активной текстуры glBindTexture(GL_TEXTURE_2D, 0); // Отвязка активной текстуры
@ -253,11 +276,34 @@ TextureCube::TextureCube(GLuint t, const std::string (&filename)[6])
// Если изображение успешно считано // Если изображение успешно считано
if (image) if (image)
{ {
// Загрузка данных с учетом прозрачности // Выбор формата с учетом типа текстуры (нормали не sRGB) и числа каналов
if (channels == 3) // RGB GLuint internalformat = GL_RGB, format = GL_RGB;
glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_SRGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, image); switch (channels)
else if (channels == 4) // RGBA {
glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_SRGB_ALPHA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, image); case 1:
internalformat = format = GL_RED;
break;
case 2:
internalformat = format = GL_RG;
break;
case 3:
format = GL_RGB;
if (type == TEX_NORMAL || type == TEX_HEIGHTS)
internalformat = GL_RGB;
else
internalformat = GL_SRGB;
break;
case 4:
format = GL_RGBA;
if (type == TEX_NORMAL || type == TEX_HEIGHTS)
internalformat = GL_RGBA;
else
internalformat = GL_SRGB_ALPHA;
break;
}
// Загрузка данных с учетом формата
glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, internalformat, width, height, 0, format, GL_UNSIGNED_BYTE, image);
stbi_image_free(image); // Освобождение оперативной памяти stbi_image_free(image); // Освобождение оперативной памяти
} }

View File

@ -130,7 +130,7 @@ int main(void)
gShader.load(GL_FRAGMENT_SHADER, "shaders/gshader.frag"); gShader.load(GL_FRAGMENT_SHADER, "shaders/gshader.frag");
gShader.link(); gShader.link();
// Установим значения текстур // Установим значения текстур
const char* textures_base_shader_names[] = {"tex_diffuse", "tex_ambient", "tex_specular"}; const char* textures_base_shader_names[] = {"tex_diffuse", "tex_ambient", "tex_specular", "tex_heights", "tex_normal"};
gShader.bindTextures(textures_base_shader_names, sizeof(textures_base_shader_names)/sizeof(const char*)); gShader.bindTextures(textures_base_shader_names, sizeof(textures_base_shader_names)/sizeof(const char*));
// Загрузка сцены из obj файла // Загрузка сцены из obj файла
@ -322,39 +322,21 @@ int main(void)
ssaoBlurShader.link(); ssaoBlurShader.link();
// Модель прямоугольника // Модель прямоугольника
Model rectangle; Scene rectangle = loadOBJtoScene("../resources/models/plane2.obj", "../resources/models/", "../resources/textures/");
// Вершины прямоугольника
glm::vec3 rectangle_verticies[] = { {-0.5f, 0.0f, -0.5f}
, { 0.5f, 0.0f, -0.5f}
, { 0.5f, 0.0f, 0.5f}
, {-0.5f, 0.0f, 0.5f}
};
// Загрузка вершин модели
rectangle.load_verteces(rectangle_verticies, sizeof(rectangle_verticies)/sizeof(glm::vec3));
// индексы вершин
GLuint rectangle_indices[] = {0, 1, 2, 2, 3, 0};
// Загрузка индексов модели
rectangle.load_indices(rectangle_indices, sizeof(rectangle_indices)/sizeof(GLuint));
// Нормали
glm::vec3 rectangle_normals[] = { {0.0f, 1.0f, 0.0f}
, {0.0f, 1.0f, 0.0f}
, {0.0f, 1.0f, 0.0f}
, {0.0f, 1.0f, 0.0f}
};
// Загрузка нормалей модели
rectangle.load_normals(rectangle_normals, sizeof(rectangle_normals)/sizeof(glm::vec3));
// Зададим горизонтальное положение перед камерой // Зададим горизонтальное положение перед камерой
rectangle.e_position().y = -1; rectangle.root.e_position().y = -1;
rectangle.e_position().z = 2; rectangle.root.e_position().z = 2;
rectangle.e_scale() = glm::vec3(4); rectangle.root.e_rotation() = glm::quat(0.707f, 0.707f, 0.0f, 0.0f);
rectangle.root.e_scale() = glm::vec3(4);
// Параметры материала // Текстуры для прямоугольника
rectangle.material.ka = {0.05, 0.05, 0.05}; Texture rectangle_diffuse(TEX_DIFFUSE, "../resources/textures/rekovalev_diffusemap.png");
rectangle.material.kd = {1, 1, 1}; rectangle.models.begin()->set_texture(rectangle_diffuse);
Texture rectangle_normal(TEX_NORMAL, "../resources/textures/rekovalev_normalmap.png");
rectangle.models.begin()->set_texture(rectangle_normal);
Texture rectangle_heights(TEX_HEIGHTS, "../resources/textures/rekovalev_bumpmap.png");
rectangle.models.begin()->set_texture(rectangle_heights);
// Шейдер для рисования отладочных лампочек // Шейдер для рисования отладочных лампочек
ShaderProgram bulbShader; ShaderProgram bulbShader;
@ -362,7 +344,7 @@ int main(void)
bulbShader.load(GL_VERTEX_SHADER, "shaders/bulb.vert"); bulbShader.load(GL_VERTEX_SHADER, "shaders/bulb.vert");
bulbShader.load(GL_FRAGMENT_SHADER, "shaders/bulb.frag"); bulbShader.load(GL_FRAGMENT_SHADER, "shaders/bulb.frag");
bulbShader.link(); bulbShader.link();
// Вершины для скайбокса // Вершины для скайбокса
glm::vec3 skybox_verticies[] = { glm::vec3 skybox_verticies[] = {
{-1.0f, 1.0f, -1.0f}, {-1.0f, 1.0f, -1.0f},
@ -407,6 +389,7 @@ int main(void)
{-1.0f, -1.0f, 1.0f}, {-1.0f, -1.0f, 1.0f},
{ 1.0f, -1.0f, 1.0f} { 1.0f, -1.0f, 1.0f}
}; };
// Модель скайбокса // Модель скайбокса
Model skybox; Model skybox;
skybox.load_verteces(skybox_verticies, sizeof(skybox_verticies)/sizeof(glm::vec3)); skybox.load_verteces(skybox_verticies, sizeof(skybox_verticies)/sizeof(glm::vec3));