diff --git a/include/Texture.h b/include/Texture.h index 9d78434..5e5367d 100644 --- a/include/Texture.h +++ b/include/Texture.h @@ -58,4 +58,19 @@ class TextureArray : public BaseTexture virtual void use(); // Привязка текстуры }; +// Класс кубической текстуры +class TextureCube : public BaseTexture +{ + public: + TextureCube(GLuint type = TEX_AVAILABLE_COUNT, const std::string (&filename)[6] = {""}); // Загрузка текстуры с диска или использование "пустой" + TextureCube(GLuint width, GLuint height, GLuint attachment, GLuint texType = TEX_DIFFUSE, GLint internalformat = GL_RGBA, GLint format = GL_RGBA, GLenum dataType = GL_FLOAT); // Конструктор текстуры заданного размера для использования в буфере + TextureCube(const TextureCube& other); // Конструктор копирования + + TextureCube& operator=(const TextureCube& other); // Оператор присваивания + + void reallocate(GLuint width, GLuint height, GLuint texType = TEX_DIFFUSE, GLint internalformat = GL_RGBA, GLint format = GL_RGBA, GLenum dataType = GL_FLOAT); // Пересоздает текстуру для имеющегося дескриптора + + virtual void use(); // Привязка текстуры +}; + #endif // TEXTURE_H diff --git a/src/Texture.cpp b/src/Texture.cpp index 5d8f5fe..2d4dd20 100644 --- a/src/Texture.cpp +++ b/src/Texture.cpp @@ -210,3 +210,120 @@ void TextureArray::use() glActiveTexture(type + GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D_ARRAY, handler); // Привязка текстуры как активной } + +// Загрузка текстуры с диска или использование "пустой" +TextureCube::TextureCube(GLuint t, const std::string (&filename)[6]) +{ + type = t; + std::string complex_name; + for (int i = 0; i < 6; i++) + complex_name += filename[i]; + if (!filename_handler.count(complex_name)) + { + std::string empty = ""; + int width, height, channels; // Ширина, высота и цветовые каналы текстуры + unsigned char* image; + + glActiveTexture(type + GL_TEXTURE0); + glGenTextures(1, &handler); // Генерация одной текстуры + glBindTexture(GL_TEXTURE_CUBE_MAP, handler); // Привязка текстуры как активной + + filename_handler[complex_name] = handler; // Запомним её дескриптор для этого имени файла + handler_count[handler] = 0; // Создадим счетчик использований дескриптора, который будет изменен в конце + + for (int i = 0; i < 6; i++) + { + image = stbi_load(filename[i].c_str(), &width, &height, &channels, STBI_default); // Загрузка в оперативную память изображения + + // Если изображение успешно считано + if (image) + { + // Загрузка данных с учетом прозрачности + if (channels == 3) // RGB + glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, image); + else if (channels == 4) // RGBA + glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, image); + + stbi_image_free(image); // Освобождение оперативной памяти + } + // Иначе изображение не считано и надо создать пустую текстуру + else + { + image = new unsigned char[3] {255,255,255}; // RGB по 1 байту на + glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_RGB, 1, 1, 0, GL_RGB, GL_UNSIGNED_BYTE, image); // Загрузка данных на видеокарту + delete[] image; // Освобождение оперативной памяти + } + } + } + // Иначе используем уже существующую по имени файла + else + handler = filename_handler[complex_name]; + + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE); + + handler_count[handler]++; +} + +// Конструктор текстуры заданного размера для использования в буфере +TextureCube::TextureCube(GLuint width, GLuint height, GLuint attachment, GLuint texType, GLint internalformat, GLint format, GLenum dataType) +{ + type = texType; + // Генерация текстуры заданного размера + glGenTextures(1, &handler); + glBindTexture(GL_TEXTURE_CUBE_MAP, handler); + for (int i = 0; i < 6; ++i) + glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, internalformat, width, height, 0, format, dataType, 0); + + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + + // Привязка к буферу кадра + glFramebufferTexture(GL_FRAMEBUFFER, attachment, handler, 0); + + // Создаем счетчик использований дескриптора + handler_count[handler] = 1; +} + +// Конструктор копирования +TextureCube::TextureCube(const TextureCube& other) +{ + handler = other.handler; + type = other.type; + // Делаем копию и увеличиваем счетчик + handler_count[handler]++; +} + +// Оператор присваивания +TextureCube& TextureCube::operator=(const TextureCube& other) +{ + // Если это разные текстуры + if (handler != other.handler) + { + this->~TextureCube(); // Уничтожаем имеющуюся + // Заменяем новой + handler = other.handler; + handler_count[handler]++; + } + type = other.type; + + return *this; +} + +// Пересоздает текстуру для имеющегося дескриптора +void TextureCube::reallocate(GLuint width, GLuint height, GLuint texType, GLint internalformat, GLint format, GLenum dataType) +{ + use(); + for (int i = 0; i < 6; ++i) + glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, internalformat, width, height, 0, format, dataType, 0); +} + +// Привязка текстуры +void TextureCube::use() +{ + glActiveTexture(type + GL_TEXTURE0); + glBindTexture(GL_TEXTURE_CUBE_MAP, handler); // Привязка текстуры как активной +}