skybox.cpp 3.61 KB
Newer Older
1
#include "skybox.h" 
unknown's avatar
unknown committed
2
3
4
5

#include <util/log.h>
#include <util/files.h>
#include <util/images.h>
's avatar
committed
6

7
#include <core/state.h>
Johannes Braun's avatar
Johannes Braun committed
8
#include <core/rendering/batch_render_list.h>
9

10
namespace glare::core
's avatar
committed
11
{
12

Johannes Braun's avatar
Johannes Braun committed
13
	Skybox::Skybox() : SceneComponent("Skybox")
14
	{
's avatar
committed
15

16
	}
17

Johannes Braun's avatar
Johannes Braun committed
18
	Skybox::Skybox(const std::vector<fs::path>& faces) : Skybox()
19
20
21
	{
		reset(faces);
	}
Johannes Braun's avatar
Johannes Braun committed
22
23
24
25
26

	Skybox::Skybox(const fs::path& directory) : Skybox()
	{
		reset(directory);
	}
27

28
29
30
31
	bool Skybox::isInitialized() const
	{
		return m_initialized;
	}
32

Johannes Braun's avatar
Johannes Braun committed
33
34
35
36
37
38
39
40
41
42
	void Skybox::reset(const fs::path& directory)
	{
		reset({ directory / "/posx.jpg",
			directory / "/negx.jpg",
			directory / "/posy.jpg",
			directory / "/negy.jpg",
			directory / "/posz.jpg",
			directory / "/negz.jpg" });
	}

43
44
45
	void Skybox::reset(const std::vector<fs::path>& faces)
	{
		m_initialized = true;
's avatar
committed
46

Johannes Braun's avatar
Johannes Braun committed
47
		// L oad images and create a cube map texture
's avatar
committed
48
		{
Johannes Braun's avatar
Johannes Braun committed
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
			m_texture = std::make_shared<Texture>(Texture::Target::eCubeMap, Texture::StoreFormat::eRGB8);
			Texture::Parameters parameters;
			parameters.base_level = 0;
			parameters.max_level = 8;
			parameters.filter_mag = gl::TextureFilterMag::eLinear;
			parameters.filter_min = gl::TextureFilterMin::eLinearMipmapLinear;
			parameters.wrap_r = gl::TextureWrapMode::eClampToEdge;
			parameters.wrap_s = gl::TextureWrapMode::eClampToEdge;
			parameters.wrap_t = gl::TextureWrapMode::eClampToEdge;
			for (int face = 0; face < faces.size(); face++)
			{
				Log_Debug << "Face No " << face;
				Image<uint8_t> image(faces[face]);
				image.flip();
				m_texture->set(gl::ImageTarget(static_cast<int>(gl::ImageTarget::eCubeMapPosX) + face), image, true);
			}
			m_texture->apply(parameters);
's avatar
committed
66
67
		}

Johannes Braun's avatar
Johannes Braun committed
68
		// Create a screen filling triangle
's avatar
committed
69
		{
Johannes Braun's avatar
Johannes Braun committed
70
71
72
73
74
75
76
77
78
			std::vector<math::Vertex> triangle_vertices
			{
				math::Vertex{ glm::vec4(-1, -1, 0, 1), glm::vec4(0, 0, -1, 0), glm::vec2(0, 0) },
				math::Vertex{ glm::vec4(3, -1, 0, 1), glm::vec4(0, 0, -1, 0), glm::vec2(3, 0) },
				math::Vertex{ glm::vec4(-1, 3, 0, 1), glm::vec4(0, 0, -1, 0), glm::vec2(0, 3) },
			};
			std::vector<unsigned> indices{ 0, 2, 1 };
			m_triangle_mesh = std::make_shared<Mesh>(triangle_vertices, indices);
		}
79

Johannes Braun's avatar
Johannes Braun committed
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
		// Create shader program and drawable.
		{
			const auto vert = std::make_shared<Shader>(gl::ShaderType::eVertex, files::shader("/cubemap/triangle_skybox.vert"));
			const auto frag = std::make_shared<Shader>(gl::ShaderType::eFragment, files::shader("/cubemap/triangle_skybox.frag"));
			m_cubemap_shader = std::make_shared<Program>(std::vector<std::shared_ptr<Shader>>{ frag, vert });
			m_cubemap_shader->uniform("u_cube_map", m_texture->textureAddress());
			m_drawable = std::make_shared<core::BatchDrawable>([this](std::shared_ptr<Program> program) {
				// The cube map shader will output a fragment depth of 1. 
				gl::depthMask(false);
				gl::cullFace(gl::Face::eFront);
				gl::depthFunc(gl::CompareFunc::eEqual);
				m_triangle_mesh->draw();
				gl::depthFunc(gl::CompareFunc::eLessEqual);
				gl::cullFace(gl::Face::eBack);
				gl::depthMask(true);
			});
		}
97
	}
's avatar
committed
98

Johannes Braun's avatar
Johannes Braun committed
99
	void Skybox::uniformUpdate(const Program& program, const std::string& name) const
100
	{
Johannes Braun's avatar
Johannes Braun committed
101
102
103
104
105
106
107
108
109
110
		if (m_initialized)
		{
			program.uniform(name + ".cubemap", m_texture->textureAddress());
			program.uniform(name + ".has_cubemap", 1);
		}
		else
		{
			program.uniform(name + ".color", m_background);
			program.uniform(name + ".has_cubemap", 0);
		}
111
	}
's avatar
committed
112

Johannes Braun's avatar
Johannes Braun committed
113
	void Skybox::onDraw(DrawMode mode)
114
115
	{
		if (mode == DrawMode::eShaded)
's avatar
committed
116
		{
117
			Context::current().renderList().submit(m_cubemap_shader, m_drawable, glm::mat4(1.f));
's avatar
committed
118
		}
119
	}
's avatar
committed
120

Johannes Braun's avatar
Johannes Braun committed
121
	const Texture& Skybox::texture() const
122
	{
Johannes Braun's avatar
Johannes Braun committed
123
		return *m_texture;
's avatar
committed
124
125
	}
}