Add texture class and texture test
This commit is contained in:
Binary file not shown.
|
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);
|
||||||
|
}
|
||||||
@@ -12,6 +12,7 @@
|
|||||||
#include "inferno/render/context.h"
|
#include "inferno/render/context.h"
|
||||||
#include "inferno/render/renderer.h"
|
#include "inferno/render/renderer.h"
|
||||||
#include "inferno/render/shader.h"
|
#include "inferno/render/shader.h"
|
||||||
|
#include "inferno/render/texture.h"
|
||||||
#include "inferno/window.h"
|
#include "inferno/window.h"
|
||||||
|
|
||||||
namespace Inferno {
|
namespace Inferno {
|
||||||
@@ -29,32 +30,68 @@ namespace Inferno {
|
|||||||
m_window = std::make_unique<Window>();
|
m_window = std::make_unique<Window>();
|
||||||
m_window->setEventCallback(NF_BIND_EVENT(Application::onEvent));
|
m_window->setEventCallback(NF_BIND_EVENT(Application::onEvent));
|
||||||
|
|
||||||
float vertices[] = {
|
TextureManager textureManager;
|
||||||
|
m_texture = textureManager.load("assets/gfx/test.png");
|
||||||
|
|
||||||
|
// -----------------------------------------
|
||||||
|
|
||||||
|
float verticesColor[] = {
|
||||||
-0.5f, -0.5f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f,
|
-0.5f, -0.5f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f,
|
||||||
0.5f, -0.5f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f,
|
0.5f, -0.5f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f,
|
||||||
0.5f, 0.5f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f,
|
0.5f, 0.5f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f,
|
||||||
-0.5f, 0.5f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f,
|
-0.5f, 0.5f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f,
|
||||||
};
|
};
|
||||||
|
|
||||||
uint32_t indices[] = {
|
uint32_t indicesColor[] = {
|
||||||
0, 1, 2, 2, 3, 0
|
0, 1, 2, 2, 3, 0
|
||||||
};
|
};
|
||||||
|
|
||||||
m_vertexArray = std::make_shared<VertexArray>();
|
m_vertexArrayColor = std::make_shared<VertexArray>();
|
||||||
|
|
||||||
std::shared_ptr<VertexBuffer> vertexBuffer = std::make_shared<VertexBuffer>(vertices, sizeof(vertices));
|
std::shared_ptr<VertexBuffer> vertexBufferColor = std::make_shared<VertexBuffer>(verticesColor, sizeof(verticesColor));
|
||||||
vertexBuffer->setLayout({
|
vertexBufferColor->setLayout({
|
||||||
{ BufferElementType::Vec3, "a_position" },
|
{ BufferElementType::Vec3, "a_position" },
|
||||||
{ BufferElementType::Vec4, "a_color" },
|
{ BufferElementType::Vec4, "a_color" },
|
||||||
});
|
});
|
||||||
|
|
||||||
m_vertexArray->addVertexBuffer(vertexBuffer);
|
m_vertexArrayColor->addVertexBuffer(vertexBufferColor);
|
||||||
|
|
||||||
std::shared_ptr<IndexBuffer> indexBuffer = std::make_shared<IndexBuffer>(indices, sizeof(indices));
|
std::shared_ptr<IndexBuffer> indexBufferColor = std::make_shared<IndexBuffer>(indicesColor, sizeof(indicesColor));
|
||||||
|
|
||||||
m_vertexArray->setIndexBuffer(indexBuffer);
|
m_vertexArrayColor->setIndexBuffer(indexBufferColor);
|
||||||
|
|
||||||
m_shader = std::make_unique<Shader>("assets/glsl/simple.vert", "assets/glsl/simple.frag");
|
// -----------------------------------------
|
||||||
|
|
||||||
|
m_vertexArrayTexture = std::make_shared<VertexArray>();
|
||||||
|
|
||||||
|
float verticesTexture[] = {
|
||||||
|
-0.5f, -0.5f, 0.0f, 0.0f, 0.0f,
|
||||||
|
0.5f, -0.5f, 0.0f, 1.0f, 0.0f,
|
||||||
|
0.5f, 0.5f, 0.0f, 1.0f, 1.0f,
|
||||||
|
-0.5f, 0.5f, 0.0f, 0.0f, 1.0f,
|
||||||
|
};
|
||||||
|
|
||||||
|
uint32_t indicesTexture[] = {
|
||||||
|
0, 1, 2, 2, 3, 0
|
||||||
|
};
|
||||||
|
|
||||||
|
std::shared_ptr<VertexBuffer> vertexBufferTexture = std::make_shared<VertexBuffer>(verticesTexture, sizeof(verticesTexture));
|
||||||
|
vertexBufferTexture->setLayout({
|
||||||
|
{ BufferElementType::Vec3, "a_position" },
|
||||||
|
{ BufferElementType::Vec2, "a_texCoord" },
|
||||||
|
});
|
||||||
|
|
||||||
|
m_vertexArrayTexture->addVertexBuffer(vertexBufferTexture);
|
||||||
|
|
||||||
|
std::shared_ptr<IndexBuffer> indexBufferTexture = std::make_shared<IndexBuffer>(indicesTexture, sizeof(indicesTexture));
|
||||||
|
|
||||||
|
m_vertexArrayTexture->setIndexBuffer(indexBufferTexture);
|
||||||
|
|
||||||
|
// -----------------------------------------
|
||||||
|
|
||||||
|
m_shaderSimple = std::make_shared<Shader>("assets/glsl/simple.vert", "assets/glsl/simple.frag");
|
||||||
|
m_shaderTexture = std::make_shared<Shader>("assets/glsl/texture.vert", "assets/glsl/texture.frag");
|
||||||
|
m_shaderTexture->setInt("u_texture", m_texture->id());
|
||||||
}
|
}
|
||||||
|
|
||||||
Application::~Application()
|
Application::~Application()
|
||||||
@@ -74,10 +111,19 @@ namespace Inferno {
|
|||||||
Command::clearColor({ 0.2f, 0.3f, 0.3f, 1.0f });
|
Command::clearColor({ 0.2f, 0.3f, 0.3f, 1.0f });
|
||||||
Command::clear();
|
Command::clear();
|
||||||
|
|
||||||
Renderer::beginScene(); // camera, lights, environment
|
// Renderer::beginScene(); // camera, lights, environment
|
||||||
m_shader->bind();
|
|
||||||
Renderer::submit(m_vertexArray);
|
// m_shaderSimple->bind();
|
||||||
Renderer::endScene();
|
// Renderer::submit(m_vertexArrayColor);
|
||||||
|
// m_shaderSimple->unbind();
|
||||||
|
|
||||||
|
m_shaderTexture->bind();
|
||||||
|
m_texture->bind();
|
||||||
|
Renderer::submit(m_vertexArrayTexture);
|
||||||
|
m_texture->unbind();
|
||||||
|
m_shaderTexture->unbind();
|
||||||
|
|
||||||
|
// Renderer::endScene();
|
||||||
|
|
||||||
m_window->update();
|
m_window->update();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,9 +6,11 @@
|
|||||||
namespace Inferno {
|
namespace Inferno {
|
||||||
|
|
||||||
class Event;
|
class Event;
|
||||||
|
class Texture;
|
||||||
|
class TextureManager;
|
||||||
|
class Window;
|
||||||
class WindowCloseEvent;
|
class WindowCloseEvent;
|
||||||
class WindowResizeEvent;
|
class WindowResizeEvent;
|
||||||
class Window;
|
|
||||||
|
|
||||||
class VertexArray;
|
class VertexArray;
|
||||||
class Shader;
|
class Shader;
|
||||||
@@ -26,7 +28,7 @@ namespace Inferno {
|
|||||||
|
|
||||||
// -----------------------------------------
|
// -----------------------------------------
|
||||||
|
|
||||||
inline Window &getWindow() { return *m_window; }
|
inline Window& getWindow() const { return *m_window; }
|
||||||
|
|
||||||
static inline Application& get() { return *s_instance; }
|
static inline Application& get() { return *s_instance; }
|
||||||
|
|
||||||
@@ -34,8 +36,11 @@ namespace Inferno {
|
|||||||
std::unique_ptr<Window> m_window;
|
std::unique_ptr<Window> m_window;
|
||||||
|
|
||||||
//
|
//
|
||||||
std::shared_ptr<VertexArray> m_vertexArray;
|
std::shared_ptr<VertexArray> m_vertexArrayColor;
|
||||||
std::unique_ptr<Shader> m_shader;
|
std::shared_ptr<VertexArray> m_vertexArrayTexture;
|
||||||
|
std::shared_ptr<Shader> m_shaderSimple;
|
||||||
|
std::shared_ptr<Shader> m_shaderTexture;
|
||||||
|
std::shared_ptr<Texture> m_texture;
|
||||||
//
|
//
|
||||||
|
|
||||||
static Application* s_instance;
|
static Application* s_instance;
|
||||||
|
|||||||
@@ -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
|
||||||
Reference in New Issue
Block a user