Skip to content

Commit e81bcff

Browse files
committed
FS: Cache vectors and matrices to avoid redundant computations.
Signed-off-by: ZhouFANG <indevn@outlook.com>
1 parent b659f57 commit e81bcff

5 files changed

Lines changed: 111 additions & 30 deletions

File tree

src/include/shader.hpp

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,15 @@ struct VertexUniformCache {
7676
bool derived_valid = false;
7777
};
7878

79+
struct FragmentUniformCache {
80+
Light light{};
81+
Vector3f camera_pos = Vector3f(0.0f);
82+
Vector3f light_dir_normalized = Vector3f(0.0f);
83+
bool has_light = false;
84+
bool has_camera = false;
85+
bool derived_valid = false;
86+
};
87+
7988
/**
8089
* @brief Shader Class 着色器类
8190
*
@@ -100,10 +109,14 @@ class Shader {
100109
uniformbuffer_.SetUniform(name, value);
101110
if constexpr (std::is_same_v<T, Matrix4f>) {
102111
UpdateMatrixCache(name, value);
112+
} else if constexpr (std::is_same_v<T, Light>) {
113+
UpdateFragmentCache(name, value);
114+
} else if constexpr (std::is_same_v<T, Vector3f>) {
115+
UpdateFragmentCache(name, value);
103116
}
104117
}
105118

106-
void PrepareVertexUniforms();
119+
void PrepareUniformCaches();
107120

108121
private:
109122
// UniformBuffer
@@ -113,9 +126,15 @@ class Shader {
113126
// 共享变量
114127
SharedDataInShader sharedDataInShader_;
115128
VertexUniformCache vertex_uniform_cache_;
129+
FragmentUniformCache fragment_uniform_cache_;
116130

117131
void UpdateMatrixCache(const std::string &name, const Matrix4f &value);
132+
void UpdateFragmentCache(const std::string &name, const Light &value);
133+
void UpdateFragmentCache(const std::string &name, const Vector3f &value);
118134
void RecalculateDerivedMatrices();
135+
void RecalculateFragmentDerived();
136+
void PrepareVertexUniformCache();
137+
void PrepareFragmentUniformCache();
119138

120139
Color SampleTexture(const Texture &texture, const Vector2f &uv) const;
121140
Color ClampColor(const Color color) const;

src/renderers/deferred_renderer.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ namespace simple_renderer {
1414
bool DeferredRenderer::Render(const Model& model, const Shader& shader_in, uint32_t* buffer) {
1515
auto total_start_time = std::chrono::high_resolution_clock::now();
1616
auto shader = std::make_shared<Shader>(shader_in);
17-
shader->PrepareVertexUniforms();
17+
shader->PrepareUniformCaches();
1818

1919
// 顶点变换(AoS)
2020
auto vertex_start = std::chrono::high_resolution_clock::now();

src/renderers/per_triangle_renderer.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ bool PerTriangleRenderer::Render(const Model &model, const Shader &shader_in,
1919

2020
// 复制 shader 以便在多线程中共享
2121
auto shader = std::make_shared<Shader>(shader_in);
22-
shader->PrepareVertexUniforms();
22+
shader->PrepareUniformCaches();
2323

2424
// 顶点变换(AoS)
2525
auto vertex_start = std::chrono::high_resolution_clock::now();

src/renderers/tile_based_renderer.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ bool TileBasedRenderer::Render(const Model &model, const Shader &shader_in,
1717
uint32_t *buffer) {
1818
auto total_start_time = std::chrono::high_resolution_clock::now();
1919
auto shader = std::make_shared<Shader>(shader_in);
20-
shader->PrepareVertexUniforms();
20+
shader->PrepareUniformCaches();
2121

2222
// 顶点变换(SoA)
2323
auto vertex_start = std::chrono::high_resolution_clock::now();

src/shader.cpp

Lines changed: 88 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -51,27 +51,6 @@ Vertex Shader::VertexShader(const Vertex& vertex) {
5151
clip_position); // 同时保存裁剪空间坐标用于后续裁剪
5252
}
5353

54-
void Shader::PrepareVertexUniforms() {
55-
if (vertex_uniform_cache_.derived_valid) {
56-
return;
57-
}
58-
// 在进入顶点阶段前一次性取出常用矩阵并填充缓存
59-
if (uniformbuffer_.HasUniform<Matrix4f>("modelMatrix") &&
60-
uniformbuffer_.HasUniform<Matrix4f>("viewMatrix") &&
61-
uniformbuffer_.HasUniform<Matrix4f>("projectionMatrix")) {
62-
vertex_uniform_cache_.model =
63-
uniformbuffer_.GetUniform<Matrix4f>("modelMatrix");
64-
vertex_uniform_cache_.view =
65-
uniformbuffer_.GetUniform<Matrix4f>("viewMatrix");
66-
vertex_uniform_cache_.projection =
67-
uniformbuffer_.GetUniform<Matrix4f>("projectionMatrix");
68-
vertex_uniform_cache_.has_model = true;
69-
vertex_uniform_cache_.has_view = true;
70-
vertex_uniform_cache_.has_projection = true;
71-
RecalculateDerivedMatrices();
72-
}
73-
}
74-
7554
void Shader::UpdateMatrixCache(const std::string& name,
7655
const Matrix4f& value) {
7756
if (name == "modelMatrix") {
@@ -106,21 +85,104 @@ void Shader::RecalculateDerivedMatrices() {
10685
vertex_uniform_cache_.derived_valid = true;
10786
}
10887

88+
void Shader::UpdateFragmentCache(const std::string& name,
89+
const Light& value) {
90+
if (name != "light") {
91+
return;
92+
}
93+
fragment_uniform_cache_.light = value;
94+
fragment_uniform_cache_.has_light = true;
95+
fragment_uniform_cache_.derived_valid = false;
96+
if (fragment_uniform_cache_.has_light && fragment_uniform_cache_.has_camera) {
97+
RecalculateFragmentDerived();
98+
}
99+
}
100+
101+
void Shader::UpdateFragmentCache(const std::string& name,
102+
const Vector3f& value) {
103+
if (name != "cameraPos") {
104+
return;
105+
}
106+
fragment_uniform_cache_.camera_pos = value;
107+
fragment_uniform_cache_.has_camera = true;
108+
fragment_uniform_cache_.derived_valid = false;
109+
if (fragment_uniform_cache_.has_light && fragment_uniform_cache_.has_camera) {
110+
RecalculateFragmentDerived();
111+
}
112+
}
113+
114+
void Shader::RecalculateFragmentDerived() {
115+
fragment_uniform_cache_.light_dir_normalized =
116+
glm::normalize(fragment_uniform_cache_.light.dir);
117+
fragment_uniform_cache_.derived_valid = true;
118+
}
119+
120+
void Shader::PrepareUniformCaches() {
121+
PrepareVertexUniformCache();
122+
PrepareFragmentUniformCache();
123+
}
124+
125+
void Shader::PrepareVertexUniformCache() {
126+
if (vertex_uniform_cache_.derived_valid) {
127+
return;
128+
}
129+
// 在进入渲染阶段前一次性取出常用矩阵并填充缓存
130+
if (uniformbuffer_.HasUniform<Matrix4f>("modelMatrix") &&
131+
uniformbuffer_.HasUniform<Matrix4f>("viewMatrix") &&
132+
uniformbuffer_.HasUniform<Matrix4f>("projectionMatrix")) {
133+
vertex_uniform_cache_.model =
134+
uniformbuffer_.GetUniform<Matrix4f>("modelMatrix");
135+
vertex_uniform_cache_.view =
136+
uniformbuffer_.GetUniform<Matrix4f>("viewMatrix");
137+
vertex_uniform_cache_.projection =
138+
uniformbuffer_.GetUniform<Matrix4f>("projectionMatrix");
139+
vertex_uniform_cache_.has_model = true;
140+
vertex_uniform_cache_.has_view = true;
141+
vertex_uniform_cache_.has_projection = true;
142+
RecalculateDerivedMatrices();
143+
}
144+
}
145+
146+
void Shader::PrepareFragmentUniformCache() {
147+
if (fragment_uniform_cache_.derived_valid) {
148+
return;
149+
}
150+
if (uniformbuffer_.HasUniform<Light>("light") &&
151+
uniformbuffer_.HasUniform<Vector3f>("cameraPos")) {
152+
fragment_uniform_cache_.light =
153+
uniformbuffer_.GetUniform<Light>("light");
154+
fragment_uniform_cache_.camera_pos =
155+
uniformbuffer_.GetUniform<Vector3f>("cameraPos");
156+
fragment_uniform_cache_.has_light = true;
157+
fragment_uniform_cache_.has_camera = true;
158+
RecalculateFragmentDerived();
159+
}
160+
}
161+
109162
Color Shader::FragmentShader(const Fragment& fragment) const {
110163
// interpolate Normal, Color and UV
111164
Color interpolateColor = fragment.color;
112165
Vector3f normal = glm::normalize(fragment.normal);
113166
Vector2f uv = fragment.uv;
114167

115168
// uniform
116-
Light light = uniformbuffer_.GetUniform<Light>("light");
169+
Light light;
170+
Vector3f light_dir;
171+
Vector3f camera_pos;
172+
if (fragment_uniform_cache_.derived_valid) {
173+
light = fragment_uniform_cache_.light;
174+
light_dir = fragment_uniform_cache_.light_dir_normalized;
175+
camera_pos = fragment_uniform_cache_.camera_pos;
176+
} else {
177+
light = uniformbuffer_.GetUniform<Light>("light");
178+
camera_pos = uniformbuffer_.GetUniform<Vector3f>("cameraPos");
179+
light_dir = glm::normalize(light.dir);
180+
}
117181
Material material = *fragment.material;
118182

119183
// view direction
120184
Vector3f view_dir =
121-
glm::normalize(sharedDataInShader_.fragPos_varying -
122-
uniformbuffer_.GetUniform<Vector3f>("cameraPos"));
123-
Vector3f light_dir = glm::normalize(light.dir);
185+
glm::normalize(sharedDataInShader_.fragPos_varying - camera_pos);
124186

125187
auto intensity = std::max(glm::dot(normal, light_dir), 0.0f);
126188
// texture color
@@ -197,4 +259,4 @@ Color Shader::ClampColor(const Color color) const {
197259
return Color(red, green, blue, alpha);
198260
}
199261

200-
} // namespace simple_renderer
262+
} // namespace simple_renderer

0 commit comments

Comments
 (0)