Engine²
Open-source game engine written in C++.
Loading...
Searching...
No Matches
GBuffer.hpp
Go to the documentation of this file.
1#pragma once
2
3#include "Logger.hpp"
8#include "core/Core.hpp"
9#include "entity/Entity.hpp"
17#include <entt/core/hashed_string.hpp>
18#include <string_view>
19
21static inline constexpr std::string_view GBUFFER_PASS_OUTPUT_NORMAL = "GBUFFER_PASS_OUTPUT_NORMAL";
22static inline const entt::hashed_string GBUFFER_PASS_OUTPUT_NORMAL_ID{GBUFFER_PASS_OUTPUT_NORMAL.data(),
24static inline constexpr std::string_view GBUFFER_PASS_OUTPUT_ALBEDO = "GBUFFER_PASS_OUTPUT_ALBEDO";
25static inline const entt::hashed_string GBUFFER_PASS_OUTPUT_ALBEDO_ID{GBUFFER_PASS_OUTPUT_ALBEDO.data(),
27static inline constexpr std::string_view GBUFFER_PASS_OUTPUT_DEPTH = "GBUFFER_PASS_OUTPUT_DEPTH";
28static inline const entt::hashed_string GBUFFER_PASS_OUTPUT_DEPTH_ID{GBUFFER_PASS_OUTPUT_DEPTH.data(),
30static inline constexpr std::string_view GBUFFER_PASS_NAME = "GBUFFER_PASS_NAME";
31static inline const entt::hashed_string GBUFFER_PASS_ID{GBUFFER_PASS_NAME.data(), GBUFFER_PASS_NAME.size()};
32static inline constexpr std::string_view GBUFFER_SHADER_NAME = "GBUFFER_SHADER_NAME";
33static inline const entt::hashed_string GBUFFER_SHADER_ID =
34 entt::hashed_string{GBUFFER_SHADER_NAME.data(), GBUFFER_SHADER_NAME.size()};
35static inline constexpr std::string_view GBUFFER_SHADE_CONTENT = R"(
36struct Camera {
37 viewProjectionMatrix : mat4x4<f32>,
38 invViewProjectionMatrix : mat4x4<f32>,
39 position : vec3f,
40}
41
42struct Object {
43 model : mat4x4<f32>,
44 normal : mat4x4<f32>,
45}
46
47struct Material {
48 ambient : vec4f,
49 diffuse : vec4f,
50 specular : vec4f,
51 transmittance : vec4f,
52 emission : vec4f,
53 _padding : vec3f,
54 shininess : f32
55};
56
57struct VertexToFragment {
58 @builtin(position) Position : vec4f,
59 @location(0) fragNormal: vec3f,
60 @location(1) fragUV: vec2f,
61}
62
63struct GBufferOutput {
64 @location(0) normal : vec4f,
65 @location(1) albedo : vec4f,
66}
67
68@group(0) @binding(0) var<uniform> camera: Camera;
69
70@group(1) @binding(0) var<uniform> object: Object;
71
72@group(2) @binding(0) var<uniform> material : Material;
73@group(2) @binding(1) var texture : texture_2d<f32>;
74@group(2) @binding(2) var textureSampler : sampler;
75
76@vertex
77fn vs_main(
78 @location(0) position: vec3f,
79 @location(1) normal: vec3f,
80 @location(2) uv: vec2f,
81) -> VertexToFragment {
82 var output : VertexToFragment;
83 let worldPosition = (object.model * vec4(position, 1.0)).xyz;
84 output.Position = camera.viewProjectionMatrix * vec4(worldPosition, 1.0);
85 output.fragNormal = normalize((object.normal * vec4(normal, 0.0)).xyz);
86 output.fragUV = uv;
87 return output;
88}
89
90@fragment
91fn fs_main(
92 @location(0) fragNormal: vec3f,
93 @location(1) fragUV : vec2f
94) -> GBufferOutput {
95 var output : GBufferOutput;
96 var uv = vec2f(1.0 - fragUV.x, 1.0 - fragUV.y);
97 output.normal = vec4(normalize(fragNormal), 1.0);
98 var textureColor = textureSample(texture, textureSampler, uv);
99 if (textureColor.a < 0.05) {
100 discard;
101 }
102 output.albedo = vec4(textureColor.rgb * material.diffuse.rgb, 1.0);
103 return output;
104}
105
106)";
107
109 public:
115 explicit GBuffer(std::string_view name = GBUFFER_PASS_NAME) : ASingleExecutionRenderPass<GBuffer>(name) {}
116
129 void UniqueRenderCallback(wgpu::RenderPassEncoder &renderPass, Engine::Core &core) override
130 {
131 const auto &bindGroupManager = core.GetResource<Graphic::Resource::BindGroupManager>();
132 const auto &bufferContainer = core.GetResource<Graphic::Resource::GPUBufferContainer>();
133
134 auto cameraView = core.GetRegistry().view<Component::GPUCamera>();
135 if (cameraView.empty())
136 {
137 Log::Error("GBuffer::UniqueRenderCallback: No camera with GPUCamera component found.");
138 return;
139 }
140 Engine::Entity camera{core, cameraView.front()};
141 const auto &cameraGPUComponent = camera.GetComponents<Component::GPUCamera>();
142
143 const auto &cameraBindGroup = bindGroupManager.Get(cameraGPUComponent.bindGroup);
144 renderPass.setBindGroup(0, cameraBindGroup.GetBindGroup(), 0, nullptr);
145
146 auto view = core.GetRegistry().view<Component::GPUTransform, Component::GPUMesh>();
147
148 for (auto &&[e, transform, gpuMesh] : view.each())
149 {
150 Engine::Entity entity{core, e};
151
152 const auto &transformBindGroup = bindGroupManager.Get(transform.bindGroup);
153 renderPass.setBindGroup(transformBindGroup.GetLayoutIndex(), transformBindGroup.GetBindGroup(), 0, nullptr);
154
155 entt::hashed_string gpuMaterialId{};
157 {
158 const auto &materialComponent = entity.GetComponents<Component::GPUMaterial>();
159 gpuMaterialId = materialComponent.bindGroup;
160 }
161 else
162 {
164 }
165 const auto &materialBindGroup = bindGroupManager.Get(gpuMaterialId);
166 renderPass.setBindGroup(materialBindGroup.GetLayoutIndex(), materialBindGroup.GetBindGroup(), 0, nullptr);
167
168 const auto &pointBuffer = bufferContainer.Get(gpuMesh.pointBufferId);
169 const auto &pointBufferSize = pointBuffer->GetBuffer().getSize();
170 renderPass.setVertexBuffer(0, pointBuffer->GetBuffer(), 0, pointBufferSize);
171 const auto &indexBuffer = bufferContainer.Get(gpuMesh.indexBufferId);
172 const auto &indexBufferSize = indexBuffer->GetBuffer().getSize();
173 renderPass.setIndexBuffer(indexBuffer->GetBuffer(), wgpu::IndexFormat::Uint32, 0, indexBufferSize);
174
175 renderPass.drawIndexed(indexBufferSize / sizeof(uint32_t), 1, 0, 0, 0);
176 }
177 }
178
191 {
193
194 auto cameraLayout = Graphic::Utils::BindGroupLayout("Camera").addEntry(
196 .setType(wgpu::BufferBindingType::Uniform)
198 .setVisibility(wgpu::ShaderStage::Vertex | wgpu::ShaderStage::Fragment)
199 .setBinding(0));
200 // Model buffer contains: mat4 modelMatrix (64 bytes) + mat4 normalMatrix (64 bytes) = 128 bytes
201 auto modelLayout = Graphic::Utils::BindGroupLayout("Model").addEntry(
203 .setType(wgpu::BufferBindingType::Uniform)
204 .setMinBindingSize(sizeof(glm::mat4) + sizeof(glm::mat4))
205 .setVisibility(wgpu::ShaderStage::Vertex)
206 .setBinding(0));
207 auto materialLayout =
210 .setType(wgpu::BufferBindingType::Uniform)
212 .setVisibility(wgpu::ShaderStage::Fragment)
213 .setBinding(0))
215 .setSampleType(wgpu::TextureSampleType::Float)
216 .setViewDimension(wgpu::TextureViewDimension::_2D)
217 .setVisibility(wgpu::ShaderStage::Fragment)
218 .setBinding(1))
220 .setType(wgpu::SamplerBindingType::Filtering)
221 .setVisibility(wgpu::ShaderStage::Fragment)
222 .setBinding(2));
223
224 auto vertexLayout = Graphic::Utils::VertexBufferLayout()
225 .addVertexAttribute(wgpu::VertexFormat::Float32x3, 0, 0)
226 .addVertexAttribute(wgpu::VertexFormat::Float32x3, 3 * sizeof(float), 1)
227 .addVertexAttribute(wgpu::VertexFormat::Float32x2, 6 * sizeof(float), 2)
228 .setArrayStride(8 * sizeof(float))
229 .setStepMode(wgpu::VertexStepMode::Vertex);
230
231 auto normalOutput =
232 Graphic::Utils::ColorTargetState("GBUFFER_NORMAL").setFormat(wgpu::TextureFormat::RGBA16Float);
233
234 auto albedoOutput =
235 Graphic::Utils::ColorTargetState("GBUFFER_ALBEDO").setFormat(wgpu::TextureFormat::BGRA8Unorm);
236
237 auto depthOutput = Graphic::Utils::DepthStencilState("GBUFFER_DEPTH")
238 .setFormat(wgpu::TextureFormat::Depth32Float)
239 .setCompareFunction(wgpu::CompareFunction::Less)
240 .setDepthWriteEnabled(wgpu::OptionalBool::True);
241
242 shaderDescriptor.setShader(GBUFFER_SHADE_CONTENT)
244 .setVertexEntryPoint("vs_main")
245 .setFragmentEntryPoint("fs_main")
246 .addBindGroupLayout(cameraLayout)
247 .addBindGroupLayout(modelLayout)
248 .addBindGroupLayout(materialLayout)
249 .addVertexBufferLayout(vertexLayout)
250 .addOutputColorFormat(normalOutput)
251 .addOutputColorFormat(albedoOutput)
252 .setCullMode(wgpu::CullMode::None)
253 .setOutputDepthFormat(depthOutput);
254 const auto validations = shaderDescriptor.validate();
255 if (!validations.empty())
256 {
257 for (const auto &validation : validations)
258 {
259 if (validation.severity == Graphic::Utils::ValidationError::Severity::Error)
260 {
261 Log::Error(fmt::format("Shader Descriptor Validation Error: {} at {}", validation.message,
262 validation.location));
263 }
264 else if (validation.severity == Graphic::Utils::ValidationError::Severity::Warning)
265 {
266 Log::Warning(fmt::format("Shader Descriptor Validation Warning: {} at {}", validation.message,
267 validation.location));
268 }
269 }
270 }
271 return Graphic::Resource::Shader::Create(shaderDescriptor, graphicContext);
272 }
273};
274
275} // namespace DefaultPipeline::Resource
GBuffer(std::string_view name=GBUFFER_PASS_NAME)
Constructs a GBuffer render pass with an optional name.
Definition GBuffer.hpp:115
void UniqueRenderCallback(wgpu::RenderPassEncoder &renderPass, Engine::Core &core) override
Render all entities with GPUTransform and GPUMesh into the G-buffer using the active camera.
Definition GBuffer.hpp:129
static Graphic::Resource::Shader CreateShader(Graphic::Resource::Context &graphicContext)
Constructs and returns a shader configured for the G-buffer pass.
Definition GBuffer.hpp:190
The core is the place where all the data of the engine is stored. It contains the registry (entities)...
Definition Core.hpp:33
TResource & GetResource()
Get a reference of a resource.
Definition Core.inl:14
Registry & GetRegistry()
Get the entt::registry that contains all components. It should be used to update component through sy...
Definition Core.hpp:50
Wrapper class providing a convenient interface for entity manipulation with the Core....
Definition Entity.hpp:20
bool HasComponents() const
Check if entity have one or multiple component's type.
Definition Entity.hpp:109
decltype(auto) GetComponents()
Get components of type TComponent from the entity.
Definition Entity.hpp:118
Definition ASingleExecutionRenderPass.hpp:9
ASingleExecutionRenderPass(std::string_view name)
Definition ASingleExecutionRenderPass.hpp:11
Definition Context.hpp:8
Definition ShaderDescriptor.hpp:21
ShaderDescriptor & setVertexEntryPoint(std::string_view entryPoint)
Definition ShaderDescriptor.hpp:50
ShaderDescriptor & setName(std::string_view name)
Definition ShaderDescriptor.hpp:108
ShaderDescriptor & setCullMode(wgpu::CullMode mode)
Definition ShaderDescriptor.hpp:96
ShaderDescriptor & setFragmentEntryPoint(std::string_view entryPoint)
Definition ShaderDescriptor.hpp:56
ShaderDescriptor & addBindGroupLayout(const Utils::BindGroupLayout &layout)
Definition ShaderDescriptor.hpp:73
ShaderDescriptor & addOutputColorFormat(const Utils::ColorTargetState &state)
Definition ShaderDescriptor.hpp:84
std::vector< Utils::ValidationError > validate(void) const override
Validate the ShaderDescriptor and all contained layouts/states.
Definition ShaderDescriptor.hpp:127
ShaderDescriptor & addVertexBufferLayout(const Utils::VertexBufferLayout &layout)
Definition ShaderDescriptor.hpp:62
ShaderDescriptor & setShader(std::string_view source)
Definition ShaderDescriptor.hpp:26
ShaderDescriptor & setOutputDepthFormat(const Utils::DepthStencilState &state)
Definition ShaderDescriptor.hpp:90
Definition Shader.hpp:14
static Shader Create(const ShaderDescriptor &descriptor, Context &context)
Definition Shader.hpp:45
Definition BindGroupLayout.hpp:13
BindGroupLayout & addEntry(const TEntry &entry)
Definition BindGroupLayout.hpp:18
Definition BufferBindGroupLayoutEntry.hpp:7
Definition ColorTargetState.hpp:8
ColorTargetState & setFormat(wgpu::TextureFormat format)
Definition ColorTargetState.hpp:13
Definition DepthStencilState.hpp:8
DepthStencilState & setDepthWriteEnabled(wgpu::OptionalBool enabled)
Definition DepthStencilState.hpp:35
DepthStencilState & setCompareFunction(wgpu::CompareFunction func)
Definition DepthStencilState.hpp:29
DepthStencilState & setFormat(wgpu::TextureFormat format)
Definition DepthStencilState.hpp:41
Definition SamplerBindGroupLayoutEntry.hpp:7
Definition TextureBindGroupLayoutEntry.hpp:7
Definition VertexBufferLayout.hpp:11
VertexBufferLayout & setArrayStride(uint32_t stride)
Definition VertexBufferLayout.hpp:26
VertexBufferLayout & addVertexAttribute(wgpu::VertexFormat format, uint32_t offset, uint32_t shaderLocation)
Definition VertexBufferLayout.hpp:16
VertexBufferLayout & setStepMode(wgpu::VertexStepMode mode)
Definition VertexBufferLayout.hpp:32
ResourceType & Get(const entt::hashed_string &id)
Get the reference to a stored resource.
Definition ResourceManager.hpp:73
Definition AmbientLight.cpp:6
static const entt::hashed_string GBUFFER_SHADER_ID
Definition GBuffer.hpp:33
static const entt::hashed_string GBUFFER_PASS_OUTPUT_DEPTH_ID
Definition GBuffer.hpp:28
static constexpr std::string_view GBUFFER_PASS_NAME
Definition GBuffer.hpp:30
static constexpr std::string_view GBUFFER_PASS_OUTPUT_ALBEDO
Definition GBuffer.hpp:24
static const entt::hashed_string GBUFFER_PASS_OUTPUT_ALBEDO_ID
Definition GBuffer.hpp:25
static constexpr std::string_view GBUFFER_PASS_OUTPUT_DEPTH
Definition GBuffer.hpp:27
static constexpr std::string_view GBUFFER_SHADE_CONTENT
Definition GBuffer.hpp:35
static constexpr std::string_view GBUFFER_SHADER_NAME
Definition GBuffer.hpp:32
static constexpr std::string_view GBUFFER_PASS_OUTPUT_NORMAL
Definition GBuffer.hpp:21
static const entt::hashed_string GBUFFER_PASS_ID
Definition GBuffer.hpp:31
static const entt::hashed_string GBUFFER_PASS_OUTPUT_NORMAL_ID
Definition GBuffer.hpp:22
static const entt::hashed_string DEFAULT_MATERIAL_BIND_GROUP_ID
Definition DefaultMaterial.hpp:10
Object::Resource::ResourceManager< std::unique_ptr< AGPUBuffer > > GPUBufferContainer
GPUBufferContainer is a resource that stores GPUBuffer resources.
Definition GPUBufferContainer.hpp:17
Object::Resource::ResourceManager< BindGroup > BindGroupManager
BindGroupManager is a resource that stores BindGroup resources.
Definition BindGroupManager.hpp:17
void Warning(const T &msg) noexcept
Definition Logger.hpp:49
void Error(const T &msg) noexcept
Definition Logger.hpp:51
Definition GPUCamera.hpp:10
Definition GPUMaterial.hpp:6
Id bindGroup
Definition GPUMaterial.hpp:12
Definition GPUMesh.hpp:6
Definition GPUTransform.hpp:6
static uint32_t GPUSize()
Definition CameraGPUBuffer.hpp:28
static uint32_t GPUSize()
Definition MaterialGPUBuffer.hpp:30
@ Warning
Definition IValidable.hpp:13
@ Error
Definition IValidable.hpp:14