hachem.wtf
aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--assets/textured.glsl41
-rw-r--r--src/core/application.cpp95
-rw-r--r--src/core/application.h4
-rw-r--r--src/platform/opengl/opengl_renderer_api.cpp17
-rw-r--r--src/platform/opengl/opengl_renderer_api.h1
-rw-r--r--src/platform/opengl/opengl_texture.cpp65
-rw-r--r--src/platform/opengl/opengl_texture.h33
-rw-r--r--src/rendering/renderer.h6
-rw-r--r--src/rendering/texture.cpp32
-rw-r--r--src/rendering/texture.h30
10 files changed, 312 insertions, 12 deletions
diff --git a/assets/textured.glsl b/assets/textured.glsl
new file mode 100644
index 0000000..ad135fe
--- /dev/null
+++ b/assets/textured.glsl
@@ -0,0 +1,41 @@
+#type vertex
+#version 330 core
+
+layout(location = 0) in vec3 a_Position;
+layout(location = 1) in vec4 a_Color;
+layout(location = 2) in vec2 a_TexCoord;
+
+uniform mat4 u_ViewProjection;
+uniform mat4 u_Transform;
+
+out vec3 v_Position;
+out vec4 v_Color;
+out vec2 v_TexCoord;
+
+void main()
+{
+ v_Position = a_Position;
+ v_Color = a_Color;
+ v_TexCoord = a_TexCoord;
+ gl_Position = u_ViewProjection * u_Transform * vec4(a_Position, 1.0);
+}
+
+#type fragment
+#version 330 core
+
+layout(location = 0) out vec4 color;
+
+in vec3 v_Position;
+in vec4 v_Color;
+in vec2 v_TexCoord;
+
+uniform sampler2D u_Texture;
+
+void main()
+{
+ vec4 texColor = texture(u_Texture, v_TexCoord);
+ if (texColor.rgb == vec3(0.0))
+ color = v_Color;
+ else
+ color = v_Color * texColor;
+}
diff --git a/src/core/application.cpp b/src/core/application.cpp
index b80ad84..0acd232 100644
--- a/src/core/application.cpp
+++ b/src/core/application.cpp
@@ -5,6 +5,7 @@
#include "rendering/vertex_buffer.h"
#include "rendering/index_buffer.h"
#include "rendering/shader.h"
+#include "rendering/texture.h"
#include <iostream>
#include <glm/glm.hpp>
@@ -71,6 +72,8 @@ namespace Donut
else
m_minimized = false;
+ Renderer::on_window_resize(e.get_width(), e.get_height());
+
if (m_camera)
m_camera->set_projection(45.0f, (float)e.get_width() / (float)e.get_height(), 0.1f, 100.0f);
@@ -150,6 +153,8 @@ namespace Donut
void Application::on_init()
{
Renderer::init();
+ Renderer::on_window_resize(1280, 720);
+ RenderCommand::set_face_culling(false);
m_camera = std::make_unique<Camera>(45.0f, 1280.0f / 720.0f, 0.1f, 100.0f);
m_camera->set_position({ 0.0f, 0.0f, 3.0f });
@@ -158,14 +163,14 @@ namespace Donut
float vertices[] =
{
- -0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f, 1.0f,
- 0.5f, -0.5f, -0.5f, 0.0f, 1.0f, 0.0f, 1.0f,
- 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, 1.0f, 1.0f,
- -0.5f, 0.5f, -0.5f, 1.0f, 1.0f, 0.0f, 1.0f,
- -0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 1.0f, 1.0f,
- 0.5f, -0.5f, 0.5f, 0.0f, 1.0f, 1.0f, 1.0f,
- 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 1.0f,
- -0.5f, 0.5f, 0.5f, 1.0f, 1.0f, 1.0f, 1.0f
+ -0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f,
+ 0.5f, -0.5f, -0.5f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f,
+ 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f,
+ -0.5f, 0.5f, -0.5f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f,
+ -0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f,
+ 0.5f, -0.5f, 0.5f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f,
+ 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 1.0f, 1.0f, 1.0f,
+ -0.5f, 0.5f, 0.5f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f
};
uint32_t indices[] =
@@ -175,7 +180,7 @@ namespace Donut
5, 4, 7, 7, 6, 5,
4, 0, 3, 3, 7, 4,
3, 2, 6, 6, 7, 3,
- 4, 5, 1, 1, 0, 4
+ 4, 5, 1, 1, 0, 4
};
m_vertex_array = std::shared_ptr<VertexArray>(VertexArray::create());
@@ -184,6 +189,7 @@ namespace Donut
VertexBufferLayout layout;
layout.push<float>(3);
layout.push<float>(4);
+ layout.push<float>(2);
m_vertex_buffer->set_layout(layout);
m_vertex_array->add_vertex_buffer(m_vertex_buffer);
@@ -191,7 +197,32 @@ namespace Donut
m_index_buffer = std::shared_ptr<IndexBuffer>(IndexBuffer::create(indices, 36));
m_vertex_array->set_index_buffer(m_index_buffer);
- m_shader = std::shared_ptr<Shader>(Shader::create("assets/basic.glsl"));
+ m_shader = std::shared_ptr<Shader>(Shader::create("assets/textured.glsl"));
+
+ m_texture = Texture2D::create(256, 256);
+
+ uint32_t* pixel_data = new uint32_t[256 * 256];
+ for (int y = 0; y < 256; y++)
+ {
+ for (int x = 0; x < 256; x++)
+ {
+ float u = (float)x / 256.0f;
+ float v = (float)y / 256.0f;
+
+ float wave = sin(u * 10.0f) * cos(v * 10.0f);
+ wave = (wave + 1.0f) * 0.5f;
+
+ uint8_t r = (uint8_t)(wave * 255);
+ uint8_t g = (uint8_t)((1.0f - wave) * 255);
+ uint8_t b = (uint8_t)((u + v) * 0.5f * 255);
+ uint8_t a = 255;
+
+ pixel_data[y * 256 + x] = (a << 24) | (b << 16) | (g << 8) | r;
+ }
+ }
+
+ m_texture->set_data(pixel_data, 256 * 256 * 4);
+ delete[] pixel_data;
}
void Application::on_shutdown()
@@ -215,11 +246,13 @@ namespace Donut
m_camera->move_left(m_delta_time);
if (m_keys[GLFW_KEY_D])
m_camera->move_right(m_delta_time);
- if (m_keys[GLFW_KEY_SPACE])
+ if (m_keys[GLFW_KEY_SPACE])
m_camera->move_up(m_delta_time);
if (m_keys[GLFW_KEY_LEFT_SHIFT])
- m_camera->move_down(m_delta_time);
+ m_camera->move_down(m_delta_time);
}
+
+ update_texture();
}
void Application::on_render()
@@ -227,6 +260,12 @@ namespace Donut
Renderer::set_clear_color({ 0.0f, 0.0f, 0.0f, 1.0f });
Renderer::clear();
+ if (m_texture)
+ {
+ m_texture->bind(0);
+ m_shader->set_int("u_Texture", 0);
+ }
+
glm::mat4 view_projection = m_camera ? m_camera->get_view_projection_matrix() : glm::mat4(1.0f);
glm::vec3 center_pos(0.0f, 0.0f, 0.0f);
@@ -252,4 +291,36 @@ namespace Donut
transform = glm::translate(glm::mat4(1.0f), back_pos);
Renderer::submit(m_shader, m_vertex_array, transform, view_projection);
}
+
+ void Application::update_texture()
+ {
+ if (!m_texture)
+ return;
+
+ m_texture_time += m_delta_time;
+
+ uint32_t* pixel_data = new uint32_t[256 * 256];
+ for (int y = 0; y < 256; y++)
+ {
+ for (int x = 0; x < 256; x++)
+ {
+ float time = m_texture_time * 2.0f;
+ float u = (float)x / 256.0f;
+ float v = (float)y / 256.0f;
+
+ float wave = sin(u * 10.0f + time) * cos(v * 10.0f + time * 0.5f);
+ wave = (wave + 1.0f) * 0.5f;
+
+ uint8_t r = (uint8_t)(wave * 255);
+ uint8_t g = (uint8_t)((1.0f - wave) * 255);
+ uint8_t b = (uint8_t)((u + v) * 0.5f * 255);
+ uint8_t a = 255;
+
+ pixel_data[y * 256 + x] = (a << 24) | (b << 16) | (g << 8) | r;
+ }
+ }
+
+ m_texture->set_data(pixel_data, 256 * 256 * 4);
+ delete[] pixel_data;
+ }
}
diff --git a/src/core/application.h b/src/core/application.h
index f78f107..2d8c55a 100644
--- a/src/core/application.h
+++ b/src/core/application.h
@@ -12,6 +12,7 @@ namespace Donut
class VertexBuffer;
class IndexBuffer;
class Shader;
+ class Texture2D;
};
namespace Donut
@@ -34,6 +35,7 @@ namespace Donut
void on_update();
void on_render();
void on_event(Event& event);
+ void update_texture();
private:
std::unique_ptr<Window> m_window;
bool m_running;
@@ -43,6 +45,7 @@ namespace Donut
std::shared_ptr<VertexBuffer> m_vertex_buffer;
std::shared_ptr<IndexBuffer> m_index_buffer;
std::shared_ptr<Shader> m_shader;
+ std::shared_ptr<Texture2D> m_texture;
std::unique_ptr<Camera> m_camera;
@@ -53,6 +56,7 @@ namespace Donut
float m_delta_time = 0.0f;
float m_last_frame = 0.0f;
bool m_mouse_dragging = false;
+ float m_texture_time = 0.0f;
static Application* s_instance;
};
diff --git a/src/platform/opengl/opengl_renderer_api.cpp b/src/platform/opengl/opengl_renderer_api.cpp
index 49b4e53..3a147b9 100644
--- a/src/platform/opengl/opengl_renderer_api.cpp
+++ b/src/platform/opengl/opengl_renderer_api.cpp
@@ -8,6 +8,11 @@ namespace Donut
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_DEPTH_TEST);
+ glDepthFunc(GL_LESS);
+
+ glEnable(GL_CULL_FACE);
+ glCullFace(GL_BACK);
+ glFrontFace(GL_CCW);
}
void OpenGLRendererAPI::set_viewport(uint32_t x, uint32_t y, uint32_t width, uint32_t height)
@@ -30,6 +35,18 @@ namespace Donut
glEnable(GL_DEPTH_TEST);
}
+ void OpenGLRendererAPI::set_face_culling(bool enabled)
+ {
+ if (enabled)
+ {
+ glEnable(GL_CULL_FACE);
+ glCullFace(GL_BACK);
+ glFrontFace(GL_CCW);
+ }
+ else
+ glDisable(GL_CULL_FACE);
+ }
+
void OpenGLRendererAPI::draw_indexed(const std::shared_ptr<VertexArray>& vertex_array, uint32_t index_count)
{
uint32_t count = index_count ? index_count : vertex_array->get_index_buffer()->get_count();
diff --git a/src/platform/opengl/opengl_renderer_api.h b/src/platform/opengl/opengl_renderer_api.h
index 30be426..f28567c 100644
--- a/src/platform/opengl/opengl_renderer_api.h
+++ b/src/platform/opengl/opengl_renderer_api.h
@@ -14,6 +14,7 @@ namespace Donut
virtual void set_clear_color(const glm::vec4& color) override;
virtual void clear() override;
virtual void enable_depth_test() override;
+ virtual void set_face_culling(bool enabled) override;
virtual void draw_indexed(const std::shared_ptr<VertexArray>& vertex_array, uint32_t index_count = 0) override;
};
diff --git a/src/platform/opengl/opengl_texture.cpp b/src/platform/opengl/opengl_texture.cpp
new file mode 100644
index 0000000..87e9345
--- /dev/null
+++ b/src/platform/opengl/opengl_texture.cpp
@@ -0,0 +1,65 @@
+#include "opengl_texture.h"
+#include <iostream>
+
+namespace Donut
+{
+ OpenGLTexture2D::OpenGLTexture2D(uint32_t width, uint32_t height)
+ : m_width(width), m_height(height)
+ {
+ m_internal_format = GL_RGBA8;
+ m_data_format = GL_RGBA;
+
+ glCreateTextures(GL_TEXTURE_2D, 1, &m_renderer_id);
+ glTextureStorage2D(m_renderer_id, 1, m_internal_format, m_width, m_height);
+
+ glTextureParameteri(m_renderer_id, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glTextureParameteri(m_renderer_id, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+
+ glTextureParameteri(m_renderer_id, GL_TEXTURE_WRAP_S, GL_REPEAT);
+ glTextureParameteri(m_renderer_id, GL_TEXTURE_WRAP_T, GL_REPEAT);
+ }
+
+ OpenGLTexture2D::OpenGLTexture2D(const std::string& path)
+ : m_path(path)
+ {
+ m_width = 1;
+ m_height = 1;
+ m_internal_format = GL_RGBA8;
+ m_data_format = GL_RGBA;
+
+ glCreateTextures(GL_TEXTURE_2D, 1, &m_renderer_id);
+ glTextureStorage2D(m_renderer_id, 1, m_internal_format, m_width, m_height);
+
+ glTextureParameteri(m_renderer_id, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glTextureParameteri(m_renderer_id, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+
+ glTextureParameteri(m_renderer_id, GL_TEXTURE_WRAP_S, GL_REPEAT);
+ glTextureParameteri(m_renderer_id, GL_TEXTURE_WRAP_T, GL_REPEAT);
+
+ uint32_t white_pixel = 0xFFFFFFFF;
+ glTextureSubImage2D(m_renderer_id, 0, 0, 0, m_width, m_height, m_data_format, GL_UNSIGNED_BYTE, &white_pixel);
+
+ std::cout << "Created default texture (stb_image not available for loading: " << path << ")" << std::endl;
+ }
+
+ OpenGLTexture2D::~OpenGLTexture2D()
+ {
+ glDeleteTextures(1, &m_renderer_id);
+ }
+
+ void OpenGLTexture2D::set_data(void* data, uint32_t size)
+ {
+ uint32_t bpp = m_data_format == GL_RGBA ? 4 : 3;
+ if (size != m_width * m_height * bpp)
+ {
+ std::cout << "Data must be entire texture!" << std::endl;
+ return;
+ }
+ glTextureSubImage2D(m_renderer_id, 0, 0, 0, m_width, m_height, m_data_format, GL_UNSIGNED_BYTE, data);
+ }
+
+ void OpenGLTexture2D::bind(uint32_t slot) const
+ {
+ glBindTextureUnit(slot, m_renderer_id);
+ }
+};
diff --git a/src/platform/opengl/opengl_texture.h b/src/platform/opengl/opengl_texture.h
new file mode 100644
index 0000000..0782e8b
--- /dev/null
+++ b/src/platform/opengl/opengl_texture.h
@@ -0,0 +1,33 @@
+#pragma once
+
+#include "rendering/texture.h"
+#include <glad/glad.h>
+
+namespace Donut
+{
+ class OpenGLTexture2D : public Texture2D
+ {
+ public:
+ OpenGLTexture2D(uint32_t width, uint32_t height);
+ OpenGLTexture2D(const std::string& path);
+ virtual ~OpenGLTexture2D();
+
+ virtual uint32_t get_width() const override { return m_width; }
+ virtual uint32_t get_height() const override { return m_height; }
+ virtual uint32_t get_renderer_id() const override { return m_renderer_id; }
+
+ virtual void set_data(void* data, uint32_t size) override;
+ virtual void bind(uint32_t slot = 0) const override;
+
+ virtual bool operator==(const Texture& other) const override
+ {
+ return m_renderer_id == other.get_renderer_id();
+ }
+
+ private:
+ std::string m_path;
+ uint32_t m_width, m_height;
+ uint32_t m_renderer_id;
+ GLenum m_internal_format, m_data_format;
+ };
+}
diff --git a/src/rendering/renderer.h b/src/rendering/renderer.h
index 09e9521..7bbdd4b 100644
--- a/src/rendering/renderer.h
+++ b/src/rendering/renderer.h
@@ -34,6 +34,7 @@ namespace Donut
virtual void set_clear_color(const glm::vec4& color) = 0;
virtual void clear() = 0;
virtual void enable_depth_test() = 0;
+ virtual void set_face_culling(bool enabled) = 0;
virtual void draw_indexed(const std::shared_ptr<VertexArray>& vertex_array, uint32_t index_count = 0) = 0;
@@ -72,6 +73,11 @@ namespace Donut
s_renderer_api->enable_depth_test();
}
+ inline static void set_face_culling(bool enabled)
+ {
+ s_renderer_api->set_face_culling(enabled);
+ }
+
inline static void draw_indexed(const std::shared_ptr<VertexArray>& vertex_array, uint32_t index_count = 0)
{
s_renderer_api->draw_indexed(vertex_array, index_count);
diff --git a/src/rendering/texture.cpp b/src/rendering/texture.cpp
new file mode 100644
index 0000000..9603034
--- /dev/null
+++ b/src/rendering/texture.cpp
@@ -0,0 +1,32 @@
+#include "texture.h"
+#include "renderer.h"
+#include "../platform/opengl/opengl_texture.h"
+
+namespace Donut
+{
+ std::shared_ptr<Texture2D> Texture2D::create(uint32_t width, uint32_t height)
+ {
+ switch (Renderer::get_api())
+ {
+ case RendererAPI::API::OpenGL:
+ return std::make_shared<OpenGLTexture2D>(width, height);
+ case RendererAPI::API::None:
+ return nullptr;
+ default:
+ return nullptr;
+ }
+ }
+
+ std::shared_ptr<Texture2D> Texture2D::create(const std::string& path)
+ {
+ switch (Renderer::get_api())
+ {
+ case RendererAPI::API::OpenGL:
+ return std::make_shared<OpenGLTexture2D>(path);
+ case RendererAPI::API::None:
+ return nullptr;
+ default:
+ return nullptr;
+ }
+ }
+};
diff --git a/src/rendering/texture.h b/src/rendering/texture.h
new file mode 100644
index 0000000..e3c53f8
--- /dev/null
+++ b/src/rendering/texture.h
@@ -0,0 +1,30 @@
+#pragma once
+
+#include <memory>
+#include <string>
+#include <glm/glm.hpp>
+
+namespace Donut
+{
+ class Texture
+ {
+ public:
+ virtual ~Texture() = default;
+
+ virtual uint32_t get_width() const = 0;
+ virtual uint32_t get_height() const = 0;
+ virtual uint32_t get_renderer_id() const = 0;
+
+ virtual void set_data(void* data, uint32_t size) = 0;
+ virtual void bind(uint32_t slot = 0) const = 0;
+
+ virtual bool operator==(const Texture& other) const = 0;
+ };
+
+ class Texture2D : public Texture
+ {
+ public:
+ static std::shared_ptr<Texture2D> create(uint32_t width, uint32_t height);
+ static std::shared_ptr<Texture2D> create(const std::string& path);
+ };
+};