Skip to content

Commit 477c4ef

Browse files
committed
Add support for emissive + occlusion map
1 parent 8aabadd commit 477c4ef

20 files changed

Lines changed: 301 additions & 116 deletions

README.md

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,11 @@ The code is programmed to support bgfx's OpenGL and DirectX 11/12 backends. I've
2525

2626
### Deferred Shading
2727

28-
- compact G-Buffer with 3 render targets
29-
- stores diffuse RGB, normal, F0 RGB, metallic, roughness
28+
- G-Buffer with 4 render targets
29+
- diffuse RGB, roughness
30+
- normal
31+
- F0 RGB, metallic
32+
- emissive RGB, occlusion
3033
- light culling with light geometry
3134
- axis-aligned bounding box
3235
- backface rendering with reversed depth test

src/Cluster.cpp

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,9 @@ void Cluster::initialize(int _argc, char* _argv[])
9494
if(config->fullscreen)
9595
toggleFullscreen();
9696

97+
if(glfwRawMouseMotionSupported())
98+
glfwSetInputMode(mWindow, GLFW_RAW_MOUSE_MOTION, GLFW_TRUE);
99+
97100
renderer->initialize();
98101
renderer->setTonemappingMode(config->tonemappingMode);
99102
ui->initialize();
@@ -109,10 +112,13 @@ void Cluster::initialize(int _argc, char* _argv[])
109112
return;
110113
}
111114

115+
// Sponza
112116
// debug camera + lights
113117

114-
scene->camera.move({ -7.0f, 2.0f, 0.0f });
115-
scene->camera.rotate({ -45.0f, -90.0f });
118+
//scene->camera.move({ -7.0f, 2.0f, 0.0f });
119+
//scene->camera.rotate({ -45.0f, -90.0f });
120+
121+
//scene->camera.lookAt({ -7.0f, 2.0f, 0.0f }, scene->center, glm::vec3(0.0f, 1.0f, 0.0f));
116122

117123
scene->pointLights.lights = {
118124
// pos, power
@@ -163,8 +169,13 @@ void Cluster::onCursorPos(double xpos, double ypos)
163169
{
164170
if(isMouseButtonDown(GLFW_MOUSE_BUTTON_RIGHT))
165171
{
172+
glfwSetInputMode(mWindow, GLFW_CURSOR, GLFW_CURSOR_HIDDEN);
166173
scene->camera.rotate(-glm::vec2(ypos - mouseY, xpos - mouseX) * angularVelocity);
167174
}
175+
else
176+
{
177+
glfwSetInputMode(mWindow, GLFW_CURSOR, GLFW_CURSOR_NORMAL);
178+
}
168179
}
169180
mouseX = xpos;
170181
mouseY = ypos;
@@ -186,7 +197,9 @@ void Cluster::onScroll(double xoffset, double yoffset)
186197

187198
void Cluster::update(float dt)
188199
{
189-
constexpr float velocity = 3.0f; // m/s
200+
float velocity = scene->diagonal / 5.0f; // m/s
201+
// TODO faster with Shift
202+
// need to cache mods & GLFW_MOD_SHIFT in onKey
190203
if(isKeyDown(GLFW_KEY_W))
191204
scene->camera.move(scene->camera.forward() * velocity * dt);
192205
if(isKeyDown(GLFW_KEY_A))

src/Config.cpp

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,10 @@ Config::Config() :
1111
tonemappingMode(Renderer::TonemappingMode::ACES),
1212
profile(false),
1313
vsync(false),
14-
//sceneFile("assets/models/duck/Duck.gltf"),
15-
sceneFile("assets/models/Sponza/glTF/Sponza.gltf"),
14+
sceneFile("assets/models/BoomBox/glTF/BoomBox.gltf"),
15+
//sceneFile("assets/models/Duck/glTF/Duck.gltf"),
16+
//sceneFile("assets/models/MetalRoughSpheres/glTF/MetalRoughSpheres.gltf"),
17+
//sceneFile("assets/models/Sponza/glTF/Sponza.gltf"),
1618
lights(1),
1719
maxLights(1000),
1820
movingLights(false),
@@ -40,7 +42,7 @@ void Config::readArgv(int argc, char* argv[])
4042
//cmdLine.hasArg("gl");
4143

4244
//renderer = bgfx::RendererType::OpenGL;
43-
//renderer = bgfx::RendererType::Direct3D12;
45+
renderer = bgfx::RendererType::Direct3D12;
4446

4547
profile = true;
4648

src/Renderer/DeferredRenderer.cpp

Lines changed: 27 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -12,22 +12,25 @@ DeferredRenderer::DeferredRenderer(const Scene* scene) :
1212
pointLightVertexBuffer(BGFX_INVALID_HANDLE),
1313
pointLightIndexBuffer(BGFX_INVALID_HANDLE),
1414
gBufferTextures {
15-
{ BGFX_INVALID_HANDLE, "Diffuse + roughness" },
16-
{ BGFX_INVALID_HANDLE, "Normal" },
17-
{ BGFX_INVALID_HANDLE, "F0 + metallic" },
18-
{ BGFX_INVALID_HANDLE, "Depth" },
19-
{ BGFX_INVALID_HANDLE, nullptr }
15+
{ BGFX_INVALID_HANDLE, "Diffuse + roughness" },
16+
{ BGFX_INVALID_HANDLE, "Normal" },
17+
{ BGFX_INVALID_HANDLE, "F0 + metallic" },
18+
{ BGFX_INVALID_HANDLE, "Emissive + occlusion" },
19+
{ BGFX_INVALID_HANDLE, "Depth" },
20+
{ BGFX_INVALID_HANDLE, nullptr }
2021
},
2122
gBufferTextureUnits {
2223
Samplers::DEFERRED_DIFFUSE_A,
2324
Samplers::DEFERRED_NORMAL,
2425
Samplers::DEFERRED_F0_METALLIC,
26+
Samplers::DEFERRED_EMISSIVE_OCCLUSION,
2527
Samplers::DEFERRED_DEPTH
2628
},
2729
gBufferSamplerNames {
2830
"s_texDiffuseA",
2931
"s_texNormal",
3032
"s_texF0Metallic",
33+
"s_texEmissiveOcclusion",
3134
"s_texDepth"
3235
},
3336
gBuffer(BGFX_INVALID_HANDLE),
@@ -187,6 +190,7 @@ void DeferredRenderer::onRender(float dt)
187190
glm::mat4 identity = glm::identity<glm::mat4>();
188191
bgfx::setViewTransform(vFullscreenLight, glm::value_ptr(identity), glm::value_ptr(identity));
189192
setViewProjection(vLight);
193+
//bgfx::setViewTransform(vLight, glm::value_ptr(identity), glm::value_ptr(identity));
190194
setViewProjection(vTransparent);
191195

192196
bgfx::setViewName(vGeometry, "Deferred geometry pass");
@@ -242,12 +246,17 @@ void DeferredRenderer::onRender(float dt)
242246
model = glm::translate(model, glm::vec3(0.0f, 0.0f, 1.0f));
243247
bgfx::setTransform(glm::value_ptr(model));
244248
bgfx::setVertexBuffer(0, blitTriangleBuffer);
245-
uint8_t t = GBufferAttachment::Diffuse_A;
246-
bgfx::setTexture(gBufferTextureUnits[t], gBufferSamplers[t], bgfx::getTexture(gBuffer, t));
249+
bindGBuffer();
247250
lights.bindLights(scene);
248251
bgfx::setState(BGFX_STATE_WRITE_RGB | BGFX_STATE_DEPTH_TEST_GREATER | BGFX_STATE_CULL_CW);
249252
bgfx::submit(vFullscreenLight, ambientLightProgram);
250253

254+
// getting a debug crash here with D3D12 when resizing the window
255+
// "Using ResourceBarrier on Command List (0x000001E06B71DC10:'Unnamed ID3D12GraphicsCommandList Object'):
256+
// Before state (0x400: D3D12_RESOURCE_STATE_COPY_DEST) of resource (0x000001E07E10D6E0:'Unnamed ID3D12Resource Object') (subresource: 0)
257+
// specified by transition barrier does not match with the state (0x10: D3D12_RESOURCE_STATE_DEPTH_WRITE) specified in the previous call
258+
// to ResourceBarrier [ RESOURCE_MANIPULATION ERROR #527: RESOURCE_BARRIER_BEFORE_AFTER_MISMATCH]"
259+
251260
bgfx::setViewName(vLight, "Deferred light pass (point lights)");
252261

253262
// point lights
@@ -265,10 +274,7 @@ void DeferredRenderer::onRender(float dt)
265274
bgfx::setIndexBuffer(pointLightIndexBuffer);
266275
float lightIndexVec[4] = { (float)i };
267276
bgfx::setUniform(lightIndexVecUniform, lightIndexVec);
268-
for(size_t i = 0; i < GBufferAttachment::Count; i++)
269-
{
270-
bgfx::setTexture(gBufferTextureUnits[i], gBufferSamplers[i], bgfx::getTexture(gBuffer, (uint8_t)i));
271-
}
277+
bindGBuffer();
272278
lights.bindLights(scene);
273279
bgfx::setState(BGFX_STATE_WRITE_RGB | BGFX_STATE_DEPTH_TEST_GEQUAL | BGFX_STATE_CULL_CCW | BGFX_STATE_BLEND_ADD);
274280
bgfx::submit(vLight, pointLightProgram);
@@ -330,17 +336,10 @@ bgfx::FrameBufferHandle DeferredRenderer::createGBuffer()
330336
const uint64_t samplerFlags = BGFX_SAMPLER_MIN_POINT | BGFX_SAMPLER_MAG_POINT | BGFX_SAMPLER_MIP_POINT |
331337
BGFX_SAMPLER_U_CLAMP | BGFX_SAMPLER_V_CLAMP;
332338

333-
bgfx::TextureFormat::Enum attachmentFormats[] =
334-
{
335-
bgfx::TextureFormat::BGRA8,
336-
bgfx::TextureFormat::RGB10A2,
337-
bgfx::TextureFormat::BGRA8
338-
};
339-
340339
for(size_t i = 0; i < GBufferAttachment::Depth; i++)
341340
{
342-
assert(bgfx::isTextureValid(0, false, 1, attachmentFormats[i], BGFX_TEXTURE_RT | samplerFlags));
343-
textures[i] = bgfx::createTexture2D(bgfx::BackbufferRatio::Equal, false, 1, attachmentFormats[i], BGFX_TEXTURE_RT | samplerFlags);
341+
assert(bgfx::isTextureValid(0, false, 1, gBufferAttachmentFormats[i], BGFX_TEXTURE_RT | samplerFlags));
342+
textures[i] = bgfx::createTexture2D(bgfx::BackbufferRatio::Equal, false, 1, gBufferAttachmentFormats[i], BGFX_TEXTURE_RT | samplerFlags);
344343
}
345344

346345
// not write only
@@ -357,3 +356,11 @@ bgfx::FrameBufferHandle DeferredRenderer::createGBuffer()
357356

358357
return gb;
359358
}
359+
360+
void DeferredRenderer::bindGBuffer()
361+
{
362+
for(size_t i = 0; i < GBufferAttachment::Count; i++)
363+
{
364+
bgfx::setTexture(gBufferTextureUnits[i], gBufferSamplers[i], bgfx::getTexture(gBuffer, (uint8_t)i));
365+
}
366+
}

src/Renderer/DeferredRenderer.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,11 +38,23 @@ class DeferredRenderer : public Renderer
3838
// TODO? don't use F0, calculate from diffuse and metallic in shader
3939
F0_Metallic,
4040

41+
// RGB = emissive radiance
42+
// A = occlusion multiplier
43+
EmissiveOcclusion,
44+
4145
Depth,
4246

4347
Count
4448
};
4549

50+
static constexpr bgfx::TextureFormat::Enum gBufferAttachmentFormats[] =
51+
{
52+
bgfx::TextureFormat::BGRA8,
53+
bgfx::TextureFormat::RGB10A2,
54+
bgfx::TextureFormat::BGRA8,
55+
bgfx::TextureFormat::BGRA8
56+
};
57+
4658
TextureBuffer gBufferTextures[GBufferAttachment::Count + 1]; // includes depth, + null-terminated
4759
uint8_t gBufferTextureUnits[GBufferAttachment::Count];
4860
const char* gBufferSamplerNames[GBufferAttachment::Count];
@@ -60,4 +72,5 @@ class DeferredRenderer : public Renderer
6072
bgfx::ProgramHandle transparencyProgram;
6173

6274
static bgfx::FrameBufferHandle createGBuffer();
75+
void bindGBuffer();
6376
};

src/Renderer/PBRShader.cpp

Lines changed: 43 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -2,61 +2,87 @@
22

33
#include "Scene/Material.h"
44
#include "Renderer/Samplers.h"
5+
#include <glm/gtc/type_ptr.hpp>
56

67
PBRShader::PBRShader() :
78
baseColorFactorUniform(BGFX_INVALID_HANDLE),
8-
metallicRoughnessFactorUniform(BGFX_INVALID_HANDLE),
9-
hasTexturesUniform(BGFX_INVALID_HANDLE),
9+
metallicRoughnessNormalOcclusionFactorUniform(BGFX_INVALID_HANDLE),
10+
emissiveFactorUniform(BGFX_INVALID_HANDLE),
11+
hasTextures1Uniform(BGFX_INVALID_HANDLE),
12+
hasTextures2Uniform(BGFX_INVALID_HANDLE),
1013
baseColorSampler(BGFX_INVALID_HANDLE),
1114
metallicRoughnessSampler(BGFX_INVALID_HANDLE),
12-
normalSampler(BGFX_INVALID_HANDLE)
15+
normalSampler(BGFX_INVALID_HANDLE),
16+
occlusionSampler(BGFX_INVALID_HANDLE),
17+
emissiveSampler(BGFX_INVALID_HANDLE)
1318
{
1419
}
1520

1621
void PBRShader::initialize()
1722
{
1823
baseColorFactorUniform = bgfx::createUniform("u_baseColorFactor", bgfx::UniformType::Vec4);
19-
metallicRoughnessFactorUniform = bgfx::createUniform("u_metallicRoughnessFactor", bgfx::UniformType::Vec4);
20-
hasTexturesUniform = bgfx::createUniform("u_hasTextures", bgfx::UniformType::Vec4);
24+
metallicRoughnessNormalOcclusionFactorUniform = bgfx::createUniform("u_metallicRoughnessNormalOcclusionFactor", bgfx::UniformType::Vec4);
25+
emissiveFactorUniform = bgfx::createUniform("u_emissiveFactorVec", bgfx::UniformType::Vec4);
26+
hasTextures1Uniform = bgfx::createUniform("u_hasTextures1", bgfx::UniformType::Vec4);
27+
hasTextures2Uniform = bgfx::createUniform("u_hasTextures2", bgfx::UniformType::Vec4);
2128
baseColorSampler = bgfx::createUniform("s_texBaseColor", bgfx::UniformType::Sampler);
2229
metallicRoughnessSampler = bgfx::createUniform("s_texMetallicRoughness", bgfx::UniformType::Sampler);
2330
normalSampler = bgfx::createUniform("s_texNormal", bgfx::UniformType::Sampler);
31+
occlusionSampler = bgfx::createUniform("s_texOcclusion", bgfx::UniformType::Sampler);
32+
emissiveSampler = bgfx::createUniform("s_texEmissive", bgfx::UniformType::Sampler);
2433
}
2534

2635
void PBRShader::shutdown()
2736
{
2837
bgfx::destroy(baseColorFactorUniform);
29-
bgfx::destroy(metallicRoughnessFactorUniform);
30-
bgfx::destroy(hasTexturesUniform);
38+
bgfx::destroy(metallicRoughnessNormalOcclusionFactorUniform);
39+
bgfx::destroy(emissiveFactorUniform);
40+
bgfx::destroy(hasTextures1Uniform);
41+
bgfx::destroy(hasTextures2Uniform);
3142
bgfx::destroy(baseColorSampler);
3243
bgfx::destroy(metallicRoughnessSampler);
3344
bgfx::destroy(normalSampler);
45+
bgfx::destroy(occlusionSampler);
46+
bgfx::destroy(emissiveSampler);
3447

35-
baseColorFactorUniform = metallicRoughnessFactorUniform = hasTexturesUniform = baseColorSampler =
36-
metallicRoughnessSampler = normalSampler = BGFX_INVALID_HANDLE;
48+
baseColorFactorUniform = metallicRoughnessNormalOcclusionFactorUniform = emissiveFactorUniform = hasTextures1Uniform =
49+
hasTextures2Uniform = baseColorSampler = metallicRoughnessSampler = normalSampler = occlusionSampler =
50+
emissiveSampler = BGFX_INVALID_HANDLE;
3751
}
3852

3953
uint64_t PBRShader::bindMaterial(const Material& material)
4054
{
41-
float metallicRoughnessValues[4] = { material.metallicFactor, material.roughnessFactor, 0.0f, 0.0f };
42-
float hasTexturesValues[4] = { 1.0f, 1.0f, 1.0f, 0.0f };
43-
bgfx::setUniform(baseColorFactorUniform, &material.baseColorFactor[0]);
44-
bgfx::setUniform(metallicRoughnessFactorUniform, &metallicRoughnessValues[0]);
55+
float factorValues[4] = { material.metallicFactor, material.roughnessFactor, material.normalScale, material.occlusionStrength };
56+
bgfx::setUniform(baseColorFactorUniform, glm::value_ptr(material.baseColorFactor));
57+
bgfx::setUniform(metallicRoughnessNormalOcclusionFactorUniform, factorValues);
58+
glm::vec4 emissiveFactor = glm::vec4(material.emissiveFactor, 0.0f);
59+
bgfx::setUniform(emissiveFactorUniform, glm::value_ptr(emissiveFactor));
4560

61+
float hasTextures1Values[4] = { 1.0f, 1.0f, 1.0f, 1.0f };
62+
float hasTextures2Values[4] = { 1.0f, 0.0f, 0.0f, 0.0f };
4663
if(bgfx::isValid(material.baseColorTexture))
4764
bgfx::setTexture(Samplers::PBR_BASECOLOR, baseColorSampler, material.baseColorTexture);
4865
else
49-
hasTexturesValues[0] = 0.0f;
66+
hasTextures1Values[0] = 0.0f;
5067
if(bgfx::isValid(material.metallicRoughnessTexture))
5168
bgfx::setTexture(Samplers::PBR_METALROUGHNESS, metallicRoughnessSampler, material.metallicRoughnessTexture);
5269
else
53-
hasTexturesValues[1] = 0.0f;
70+
hasTextures1Values[1] = 0.0f;
5471
if(bgfx::isValid(material.normalTexture))
5572
bgfx::setTexture(Samplers::PBR_NORMAL, normalSampler, material.normalTexture);
5673
else
57-
hasTexturesValues[2] = 0.0f;
74+
hasTextures1Values[2] = 0.0f;
75+
if(bgfx::isValid(material.occlusionTexture))
76+
bgfx::setTexture(Samplers::PBR_OCCLUSION, occlusionSampler, material.occlusionTexture);
77+
else
78+
hasTextures1Values[3] = 0.0f;
79+
if(bgfx::isValid(material.emissiveTexture))
80+
bgfx::setTexture(Samplers::PBR_EMISSIVE, emissiveSampler, material.emissiveTexture);
81+
else
82+
hasTextures2Values[0] = 0.0f;
5883

59-
bgfx::setUniform(hasTexturesUniform, &hasTexturesValues[0]);
84+
bgfx::setUniform(hasTextures1Uniform, hasTextures1Values);
85+
bgfx::setUniform(hasTextures2Uniform, hasTextures2Values);
6086

6187
uint64_t state = 0;
6288
if(material.blend)

src/Renderer/PBRShader.h

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,13 @@ class PBRShader
1616

1717
private:
1818
bgfx::UniformHandle baseColorFactorUniform;
19-
bgfx::UniformHandle metallicRoughnessFactorUniform;
20-
bgfx::UniformHandle hasTexturesUniform;
19+
bgfx::UniformHandle metallicRoughnessNormalOcclusionFactorUniform;
20+
bgfx::UniformHandle emissiveFactorUniform;
21+
bgfx::UniformHandle hasTextures1Uniform;
22+
bgfx::UniformHandle hasTextures2Uniform;
2123
bgfx::UniformHandle baseColorSampler;
2224
bgfx::UniformHandle metallicRoughnessSampler;
2325
bgfx::UniformHandle normalSampler;
26+
bgfx::UniformHandle occlusionSampler;
27+
bgfx::UniformHandle emissiveSampler;
2428
};

src/Renderer/Samplers.h

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -10,16 +10,19 @@ class Samplers
1010
static const uint8_t PBR_BASECOLOR = 0;
1111
static const uint8_t PBR_METALROUGHNESS = 1;
1212
static const uint8_t PBR_NORMAL = 2;
13+
static const uint8_t PBR_OCCLUSION = 3;
14+
static const uint8_t PBR_EMISSIVE = 4;
1315

14-
static const uint8_t LIGHTS_POINTLIGHTS = 3;
16+
static const uint8_t LIGHTS_POINTLIGHTS = 5;
1517

16-
static const uint8_t CLUSTERS_CLUSTERS = 4;
17-
static const uint8_t CLUSTERS_LIGHTINDICES = 5;
18-
static const uint8_t CLUSTERS_LIGHTGRID = 6;
19-
static const uint8_t CLUSTERS_ATOMICINDEX = 7;
18+
static const uint8_t CLUSTERS_CLUSTERS = 6;
19+
static const uint8_t CLUSTERS_LIGHTINDICES = 7;
20+
static const uint8_t CLUSTERS_LIGHTGRID = 8;
21+
static const uint8_t CLUSTERS_ATOMICINDEX = 9;
2022

21-
static const uint8_t DEFERRED_DIFFUSE_A = 4;
22-
static const uint8_t DEFERRED_NORMAL = 5;
23-
static const uint8_t DEFERRED_F0_METALLIC = 6;
24-
static const uint8_t DEFERRED_DEPTH = 7;
23+
static const uint8_t DEFERRED_DIFFUSE_A = 6;
24+
static const uint8_t DEFERRED_NORMAL = 7;
25+
static const uint8_t DEFERRED_F0_METALLIC = 8;
26+
static const uint8_t DEFERRED_EMISSIVE_OCCLUSION = 9;
27+
static const uint8_t DEFERRED_DEPTH = 10;
2528
};

src/Renderer/Shaders/fs_clustered.sc

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -36,19 +36,19 @@ void main()
3636
uint lightIndex = getGridLightIndex(grid.offset, i);
3737
PointLight light = getPointLight(lightIndex);
3838
float dist = distance(light.position, fragPos);
39-
if(dist < light.radius)
39+
float attenuation = smoothAttenuation(dist, light.radius);
40+
if(attenuation > 0.0)
4041
{
41-
float attenuation = smoothAttenuation(dist, light.radius);
4242
vec3 L = normalize(light.position - fragPos);
4343
vec3 radianceIn = light.intensity * attenuation;
4444
float NoL = saturate(dot(N, L));
4545
radianceOut += BRDF(V, L, N, mat) * radianceIn * NoL;
4646
}
4747
}
4848

49-
vec3 ambient = getAmbientLight().irradiance * mat.diffuseColor;
50-
vec3 color = radianceOut + ambient;
49+
radianceOut += getAmbientLight().irradiance * mat.diffuseColor * mat.occlusion;
50+
radianceOut += mat.emissive;
5151

52-
gl_FragColor.rgb = color;
52+
gl_FragColor.rgb = radianceOut;
5353
gl_FragColor.a = mat.albedo.a;
5454
}

0 commit comments

Comments
 (0)