gbuffer.cpp 7.05 KB
Newer Older
unknown's avatar
unknown committed
1
2
3
4
5
#include "GBuffer.h" 
#include <core/state.h>
#include <core/numeric/flags.h>
#include <util/log.h>
#include <util/files.h>
6
#include <core/objects/light.h>
7
#include <core/message_tags.h>
unknown's avatar
unknown committed
8
9
10
11
12

namespace glare
{
	namespace core
	{
13
14
		GBuffer::GBuffer(unsigned int width, unsigned int height, unsigned samples) 
			: m_width(width), m_height(height), m_skybox(std::make_shared<core::Skybox>())
unknown's avatar
unknown committed
15
		{
16
			m_texture_renderer = DefaultTextureRenderers::makeRenderer(files::shader("screenshader/gbuffer/gbuffer.frag"));
17
18
19
20

			const GLFWvidmode * mode = glfwGetVideoMode(glfwGetPrimaryMonitor());

			m_gbuffer_framebuffer = std::make_shared<Framebuffer<TextureMultisampled>>(unsigned(mode->width), unsigned(mode->height), samples);
unknown's avatar
unknown committed
21
22
23
24
25
26
27
			m_gbuffer_framebuffer->attach(gl::Attachment::eColor0);
			m_gbuffer_framebuffer->attach(gl::Attachment::eColor1);
			m_gbuffer_framebuffer->attach(gl::Attachment::eColor2);
			m_gbuffer_framebuffer->attach(gl::Attachment::eColor3);
			m_gbuffer_framebuffer->attach(gl::Attachment::eColor4);
			m_gbuffer_framebuffer->attach(gl::Attachment::eColor5);
			m_gbuffer_framebuffer->attach(gl::Attachment::eColor6);
28
			m_gbuffer_framebuffer->attach(gl::Attachment::eDepth);
29

unknown's avatar
unknown committed
30
			m_lights_buffer = std::make_unique<Buffer<gl::BufferType::eShaderStorage>>();
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45

			//Update all uniforms that won't change anymore...
			m_texture_renderer->shader().uniform("u_gbuffer.depth", m_gbuffer_framebuffer->depthAttachment().makeTextureResident());
			m_texture_renderer->shader().uniform("u_gbuffer.diffuse", m_gbuffer_framebuffer->colorAttachment(gl::Attachment::eColor0).makeTextureResident());
			m_texture_renderer->shader().uniform("u_gbuffer.normals", m_gbuffer_framebuffer->colorAttachment(gl::Attachment::eColor1).makeTextureResident());
			m_texture_renderer->shader().uniform("u_gbuffer.specular", m_gbuffer_framebuffer->colorAttachment(gl::Attachment::eColor2).makeTextureResident());
			m_texture_renderer->shader().uniform("u_gbuffer.id", m_gbuffer_framebuffer->colorAttachment(gl::Attachment::eColor3).makeTextureResident());
			m_texture_renderer->shader().uniform("u_gbuffer.position", m_gbuffer_framebuffer->colorAttachment(gl::Attachment::eColor4).makeTextureResident());
			m_texture_renderer->shader().uniform("u_gbuffer.position_raw", m_gbuffer_framebuffer->colorAttachment(gl::Attachment::eColor5).makeTextureResident());
			m_texture_renderer->shader().uniform("u_gbuffer.lighting", m_gbuffer_framebuffer->colorAttachment(gl::Attachment::eColor6).makeTextureResident());

			// Those will only be later updated at will when resizing.
			m_texture_renderer->shader().uniform("screen.width", m_width);
			m_texture_renderer->shader().uniform("screen.height", m_height);
			m_texture_renderer->shader().uniform("u_samples", m_gbuffer_framebuffer->samples());
46
47
48
49
50

			m_texture_renderer->shader().bindSubroutine(gl::ShaderType::eFragment, "u_light_sample[0]", "samplePoint");
			m_texture_renderer->shader().bindSubroutine(gl::ShaderType::eFragment, "u_light_sample[1]", "sampleSpot");
			m_texture_renderer->shader().bindSubroutine(gl::ShaderType::eFragment, "u_light_sample[2]", "sampleDirectional");
			m_texture_renderer->shader().bindSubroutine(gl::ShaderType::eFragment, "u_light_sample[3]", "sampleAmbient");
51
52

			registerForMessage(tags::light);
unknown's avatar
unknown committed
53
54
55
56
		}

		GBuffer::~GBuffer()
		{
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
			unregisterForMessage(tags::light);
		}

		void GBuffer::handle(messaging::message_t &message)
		{
			switch (message.name)
			{
			case tags::light:
			{
				auto light_update = message.as<LightUpdate>();
				if (m_light_to_index.count(light_update.light_id) == 0)
				{
					//Light has just been created.
					m_lights.push_back(light_update.ptr->makeFullData());
					m_light_to_index[light_update.light_id] = m_lights.size() - 1;
					m_lights_buffer->upload<LightWithShadowmap>(m_lights, gl::BufferUsage::eDynamicCopy);

					//Check if successfully added.
					assert(m_light_to_index.count(light_update.light_id) != 0);
					assert(m_lights.size() > m_light_to_index.at(light_update.light_id));
				}
				else if (light_update.ptr == nullptr)
				{
					//Light has just been removed.
					if (m_light_to_index.count(light_update.light_id) != 0)
					{
						size_t position = m_light_to_index[light_update.light_id];
						m_lights.erase(m_lights.begin() + position);

						m_light_to_index.erase(light_update.light_id);

						for (auto it = m_light_to_index.begin(); it != m_light_to_index.end(); ++it)
						{
							// decrement vector index as one element has been removed before
							if (it->second >= position)
								it->second = it->second - 1;
						}

						m_lights_buffer->upload<LightWithShadowmap>(m_lights, gl::BufferUsage::eDynamicCopy);
					}

					//Check if successfully added.
					assert(m_light_to_index.count(light_update.light_id) == 0);
				}
				else
				{
					assert(m_light_to_index.count(light_update.light_id) != 0);

					// Light has changed.
					// don't change any indices, just update the buffer
					auto data = light_update.ptr->makeFullData();
					auto index = m_light_to_index[light_update.light_id];
					m_lights[index] = data;
					m_lights_buffer->map<LightWithShadowmap>(m_lights.size(), gl::BufferMapBit::eWrite)[index] = data;
					m_lights_buffer->unmap();
				}
			} break;
			}
unknown's avatar
unknown committed
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
		}

		void GBuffer::record(std::function<void()> render_function) const
		{
			activate();
			render_function();
			deactivate();
		}

		void GBuffer::activate() const
		{
			m_gbuffer_framebuffer->activate();
			gl::clear(gl::ClearBufferBits::eColor | gl::ClearBufferBits::eDepth);
		}

		void GBuffer::deactivate() const
		{
			m_gbuffer_framebuffer->deactivate();
		}

		void GBuffer::draw() const
		{
			gl::setEnabled(gl::EnableParameter::eDepthTest, false);
			m_texture_renderer->shader().use();

Johannes Braun's avatar
Johannes Braun committed
140
			m_texture_renderer->shader().storageBuffer("lightsBuffer", *m_lights_buffer);
unknown's avatar
unknown committed
141

142
143
144
			if(m_skybox->isInitialized())
				m_texture_renderer->shader().uniform("environment", m_skybox->makeResident());

145
146
147
			m_texture_renderer->shader().uniform("u_view", state::camera->getView());
			m_texture_renderer->shader().uniform("u_projection", state::camera->getProjection());
			m_texture_renderer->shader().uniform("camera_position", glm::vec3(state::camera->getOwner()->absoluteTransform() * glm::vec4(0,0,0,1)));
unknown's avatar
unknown committed
148
149
150
			m_texture_renderer->draw();
			gl::setEnabled(gl::EnableParameter::eDepthTest, true);
		}
151
152
153
154
155

		std::shared_ptr<Skybox> GBuffer::getSkybox() const
		{
			return m_skybox;
		}
unknown's avatar
unknown committed
156
157
158
159
160
161
162
163
164
165
166
167

		void GBuffer::setSkybox(std::shared_ptr<Skybox> skybox)
		{
			m_skybox = skybox;
		}

		const Framebuffer<TextureMultisampled>& GBuffer::framebuffer() const
		{
			return *m_gbuffer_framebuffer;
		}

		void GBuffer::updateSize(unsigned width, unsigned height)
168
169
170
171
172
		{
			updateSize(width, height, m_gbuffer_framebuffer->samples());
		}

		void GBuffer::updateSize(unsigned width, unsigned height, unsigned samples)
unknown's avatar
unknown committed
173
		{
174
175
			m_width = width;// width;
			m_height = height;// height;
176
177
178
179
			m_gbuffer_framebuffer->resize(width, height, samples);
			m_texture_renderer->shader().uniform("screen.width", m_width);
			m_texture_renderer->shader().uniform("screen.height", m_height);
			m_texture_renderer->shader().uniform("u_samples", samples);
unknown's avatar
unknown committed
180
181
182
		}
	}
}