/
LightingModeRenderer.cpp
118 lines (91 loc) · 3.5 KB
/
LightingModeRenderer.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
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
115
116
117
118
#include "LightingModeRenderer.h"
#include "LightingModeRenderResult.h"
#include "LightInteractions.h"
#include "OpenGLShaderPass.h"
#include "OpenGLShader.h"
#include "ObjectRenderer.h"
namespace render
{
IRenderResult::Ptr LightingModeRenderer::render(RenderStateFlags globalFlagsMask,
const IRenderView& view, std::size_t time)
{
auto result = std::make_shared<LightingModeRenderResult>();
// Construct default OpenGL state
OpenGLState current;
setupState(current);
setupViewMatrices(view);
std::size_t visibleLights = 0;
std::vector<LightInteractions> interactionLists;
interactionLists.reserve(_lights.size());
// Gather all visible lights and render the surfaces touched by them
for (const auto& light : _lights)
{
LightInteractions interaction(*light, _geometryStore);
if (!interaction.isInView(view))
{
result->skippedLights++;
continue;
}
result->visibleLights++;
// Check all the surfaces that are touching this light
interaction.collectSurfaces(_entities);
result->objects += interaction.getObjectCount();
result->entities += interaction.getEntityCount();
interactionLists.emplace_back(std::move(interaction));
}
// Run the depth fill pass
for (auto& interactionList : interactionLists)
{
interactionList.fillDepthBuffer(current, globalFlagsMask, view, time);
}
// Draw the surfaces per light and material
for (auto& interactionList : interactionLists)
{
interactionList.render(current, globalFlagsMask, view, time);
result->drawCalls += interactionList.getDrawCalls();
}
glUseProgram(0);
glActiveTexture(GL_TEXTURE0);
glClientActiveTexture(GL_TEXTURE0);
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_COLOR_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glEnableClientState(GL_NORMAL_ARRAY);
// Draw non-interaction passes (like skyboxes or blend stages)
for (const auto& entity : _entities)
{
entity->foreachRenderable([&](const render::IRenderableObject::Ptr& object, Shader* shader)
{
// Skip empty objects
if (!object->isVisible()) return;
// Don't collect invisible shaders
if (!shader->isVisible()) return;
auto glShader = static_cast<OpenGLShader*>(shader);
// We only consider materials designated for camera rendering
if (!glShader->isApplicableTo(RenderViewType::Camera))
{
return;
}
// For each pass except for the depth fill and interaction passes, draw the geometry
glShader->foreachNonInteractionPass([&](OpenGLShaderPass& pass)
{
if (!pass.stateIsActive())
{
return;
}
// Apply our state to the current state object
pass.applyState(current, globalFlagsMask, view.getViewer(), time, entity.get());
RenderInfo info(current.getRenderFlags(), view.getViewer(), current.cubeMapMode);
if (current.glProgram)
{
OpenGLShaderPass::SetUpNonInteractionProgram(current, view.getViewer(), object->getObjectTransform());
}
ObjectRenderer::SubmitObject(*object, _geometryStore);
result->drawCalls++;
});
});
}
cleanupState();
return result;
}
}