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/renderer.h"
|
||||
#include "inferno/render/shader.h"
|
||||
#include "inferno/render/texture.h"
|
||||
#include "inferno/window.h"
|
||||
|
||||
namespace Inferno {
|
||||
@@ -29,32 +30,68 @@ namespace Inferno {
|
||||
m_window = std::make_unique<Window>();
|
||||
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, 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, 1.0f, 1.0f, 1.0f, 1.0f,
|
||||
};
|
||||
|
||||
uint32_t indices[] = {
|
||||
uint32_t indicesColor[] = {
|
||||
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));
|
||||
vertexBuffer->setLayout({
|
||||
std::shared_ptr<VertexBuffer> vertexBufferColor = std::make_shared<VertexBuffer>(verticesColor, sizeof(verticesColor));
|
||||
vertexBufferColor->setLayout({
|
||||
{ BufferElementType::Vec3, "a_position" },
|
||||
{ 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()
|
||||
@@ -74,10 +111,19 @@ namespace Inferno {
|
||||
Command::clearColor({ 0.2f, 0.3f, 0.3f, 1.0f });
|
||||
Command::clear();
|
||||
|
||||
Renderer::beginScene(); // camera, lights, environment
|
||||
m_shader->bind();
|
||||
Renderer::submit(m_vertexArray);
|
||||
Renderer::endScene();
|
||||
// Renderer::beginScene(); // camera, lights, environment
|
||||
|
||||
// m_shaderSimple->bind();
|
||||
// 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();
|
||||
}
|
||||
|
||||
@@ -6,9 +6,11 @@
|
||||
namespace Inferno {
|
||||
|
||||
class Event;
|
||||
class Texture;
|
||||
class TextureManager;
|
||||
class Window;
|
||||
class WindowCloseEvent;
|
||||
class WindowResizeEvent;
|
||||
class Window;
|
||||
|
||||
class VertexArray;
|
||||
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; }
|
||||
|
||||
@@ -34,8 +36,11 @@ namespace Inferno {
|
||||
std::unique_ptr<Window> m_window;
|
||||
|
||||
//
|
||||
std::shared_ptr<VertexArray> m_vertexArray;
|
||||
std::unique_ptr<Shader> m_shader;
|
||||
std::shared_ptr<VertexArray> m_vertexArrayColor;
|
||||
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;
|
||||
|
||||
@@ -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