Riyyi
4 years ago
7 changed files with 291 additions and 21 deletions
After Width: | Height: | Size: 5.7 KiB |
@ -0,0 +1,12 @@ |
|||||||
|
#version 450 core |
||||||
|
|
||||||
|
layout(location = 0) out vec4 color; |
||||||
|
|
||||||
|
in vec2 v_texCoord; |
||||||
|
|
||||||
|
uniform sampler2D u_texture; |
||||||
|
|
||||||
|
void main() |
||||||
|
{ |
||||||
|
color = texture(u_texture, v_texCoord); |
||||||
|
} |
@ -0,0 +1,12 @@ |
|||||||
|
#version 450 core |
||||||
|
|
||||||
|
layout(location = 0) in vec3 a_position; |
||||||
|
layout(location = 1) in vec2 a_texCoord; |
||||||
|
|
||||||
|
out vec2 v_texCoord; |
||||||
|
|
||||||
|
void main() |
||||||
|
{ |
||||||
|
v_texCoord = a_texCoord; |
||||||
|
gl_Position = vec4(a_position, 1.0f); |
||||||
|
} |
@ -0,0 +1,139 @@ |
|||||||
|
#include <climits> // UINT_MAX |
||||||
|
#include <memory> |
||||||
|
|
||||||
|
#include <glad/glad.h> |
||||||
|
#define STB_IMAGE_IMPLEMENTATION |
||||||
|
#include <stb_image.h> |
||||||
|
|
||||||
|
#include "inferno/assertions.h" |
||||||
|
#include "inferno/render/texture.h" |
||||||
|
|
||||||
|
namespace Inferno { |
||||||
|
|
||||||
|
Texture::Texture(const std::string& path) |
||||||
|
{ |
||||||
|
int width; |
||||||
|
int height; |
||||||
|
int channels; |
||||||
|
|
||||||
|
// Load image data
|
||||||
|
stbi_set_flip_vertically_on_load(1); |
||||||
|
unsigned char* data = stbi_load(path.c_str(), &width, &height, &channels, STBI_default); |
||||||
|
|
||||||
|
ASSERT(data, "Failed to load image: '{}'", path); |
||||||
|
|
||||||
|
m_width = width; |
||||||
|
m_height = height; |
||||||
|
|
||||||
|
if (channels == 4) { |
||||||
|
m_internalFormat = GL_RGBA8; |
||||||
|
m_dataFormat = GL_RGBA; |
||||||
|
} |
||||||
|
else if (channels == 3) { |
||||||
|
m_internalFormat = GL_RGB8; |
||||||
|
m_dataFormat = GL_RGB; |
||||||
|
} |
||||||
|
|
||||||
|
create(data); |
||||||
|
|
||||||
|
// Clean resources
|
||||||
|
stbi_image_free(data); |
||||||
|
} |
||||||
|
|
||||||
|
Texture::~Texture() |
||||||
|
{ |
||||||
|
glDeleteTextures(1, &m_id); |
||||||
|
} |
||||||
|
|
||||||
|
void Texture::bind() const |
||||||
|
{ |
||||||
|
glBindTexture(GL_TEXTURE_2D, m_id); |
||||||
|
} |
||||||
|
|
||||||
|
void Texture::unbind() const |
||||||
|
{ |
||||||
|
glBindTexture(GL_TEXTURE_2D, 0); |
||||||
|
} |
||||||
|
|
||||||
|
void Texture::create(unsigned char* data) |
||||||
|
{ |
||||||
|
m_id = UINT_MAX; |
||||||
|
|
||||||
|
// Create texture object
|
||||||
|
glGenTextures(1, &m_id); |
||||||
|
|
||||||
|
// Bind texture object
|
||||||
|
glBindTexture(GL_TEXTURE_2D, m_id); |
||||||
|
|
||||||
|
// Set unpacking of pixel data to byte-alignment,
|
||||||
|
// this prevents alignment issues when using a single byte for color
|
||||||
|
glPixelStorei(GL_UNPACK_ALIGNMENT, 1); |
||||||
|
|
||||||
|
// Generate texture
|
||||||
|
glTexImage2D( |
||||||
|
GL_TEXTURE_2D, // Texture target
|
||||||
|
0, // Midmap level, base starts at level 0
|
||||||
|
m_internalFormat, // Texture format
|
||||||
|
m_width, m_height, // Image width/height
|
||||||
|
0, // Always 0 (legacy)
|
||||||
|
m_dataFormat, // Texture source format
|
||||||
|
GL_UNSIGNED_BYTE, // Texture source datatype
|
||||||
|
data); // Image data
|
||||||
|
|
||||||
|
// Set the texture wrapping / filtering options
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); // X
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); // Y
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); // Minify
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); // Magnify
|
||||||
|
|
||||||
|
// Automatically generate all mipmap levels
|
||||||
|
glGenerateMipmap(GL_TEXTURE_2D); |
||||||
|
|
||||||
|
// Unbind texture object
|
||||||
|
glBindTexture(GL_TEXTURE_2D, 0); |
||||||
|
} |
||||||
|
|
||||||
|
// -----------------------------------------
|
||||||
|
|
||||||
|
void TextureManager::add(const std::string& path, const std::shared_ptr<Texture>& texture) |
||||||
|
{ |
||||||
|
// Construct (key, value) pair and insert it into the unordered_map
|
||||||
|
m_textureList.emplace(path, texture); |
||||||
|
} |
||||||
|
|
||||||
|
std::shared_ptr<Texture> TextureManager::load(const std::string& path) |
||||||
|
{ |
||||||
|
if (exists(path)) { |
||||||
|
return get(path); |
||||||
|
} |
||||||
|
|
||||||
|
std::shared_ptr<Texture> texture = std::make_shared<Texture>(path); |
||||||
|
add(path, texture); |
||||||
|
return get(path); |
||||||
|
} |
||||||
|
|
||||||
|
std::shared_ptr<Texture> TextureManager::get(const std::string& path) |
||||||
|
{ |
||||||
|
return exists(path) ? m_textureList.at(path) : nullptr; |
||||||
|
} |
||||||
|
|
||||||
|
bool TextureManager::exists(const std::string& path) |
||||||
|
{ |
||||||
|
return m_textureList.find(path) != m_textureList.end(); |
||||||
|
} |
||||||
|
|
||||||
|
void TextureManager::remove(const std::string& path) |
||||||
|
{ |
||||||
|
if (exists(path)) { |
||||||
|
m_textureList.erase(path); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
void TextureManager::remove(const std::shared_ptr<Texture>& texture) |
||||||
|
{ |
||||||
|
if (exists(texture->path())) { |
||||||
|
m_textureList.erase(texture->path()); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,56 @@ |
|||||||
|
#ifndef TEXTURE_H |
||||||
|
#define TEXTURE_H |
||||||
|
|
||||||
|
#include <cstdint> // std::uint32_t |
||||||
|
#include <memory> // std::shared_ptr |
||||||
|
#include <string> // std::string |
||||||
|
#include <unordered_map> // std::unordered_map |
||||||
|
|
||||||
|
namespace Inferno { |
||||||
|
|
||||||
|
class Texture { |
||||||
|
public: |
||||||
|
Texture(const std::string& path); |
||||||
|
virtual ~Texture(); |
||||||
|
|
||||||
|
void bind() const; |
||||||
|
void unbind() const; |
||||||
|
|
||||||
|
inline std::string path() const { return m_path; } |
||||||
|
inline uint32_t width() const { return m_width; } |
||||||
|
inline uint32_t height() const { return m_height; } |
||||||
|
inline uint32_t id() const { return m_id; } |
||||||
|
inline uint32_t internalFormat() const { return m_internalFormat; } |
||||||
|
inline uint32_t dataFormat() const { return m_dataFormat; } |
||||||
|
|
||||||
|
protected: |
||||||
|
void create(unsigned char* data); |
||||||
|
|
||||||
|
private: |
||||||
|
std::string m_path; |
||||||
|
uint32_t m_width; |
||||||
|
uint32_t m_height; |
||||||
|
uint32_t m_id; |
||||||
|
uint32_t m_internalFormat; |
||||||
|
uint32_t m_dataFormat; |
||||||
|
}; |
||||||
|
|
||||||
|
// -----------------------------------------
|
||||||
|
|
||||||
|
class TextureManager { |
||||||
|
public: |
||||||
|
void add(const std::string& path, const std::shared_ptr<Texture>& texture); |
||||||
|
std::shared_ptr<Texture> load(const std::string& path); |
||||||
|
std::shared_ptr<Texture> get(const std::string& path); |
||||||
|
bool exists(const std::string& path); |
||||||
|
|
||||||
|
void remove(const std::string& path); |
||||||
|
void remove(const std::shared_ptr<Texture>& texture); |
||||||
|
|
||||||
|
private: |
||||||
|
std::unordered_map<std::string, std::shared_ptr<Texture>> m_textureList; |
||||||
|
}; |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
#endif // TEXTURE_H
|
Loading…
Reference in new issue