@@ -136,13 +136,23 @@ void Shader::RecalculateDerivedMatrices() {
136136
137137void Shader::UpdateFragmentCache (const std::string& name,
138138 const Light& value) {
139- if (name != " light" ) {
140- return ;
139+ if (name != " light" ) { return ; }
140+ fragment_uniform_cache_.lights .clear ();
141+ fragment_uniform_cache_.lights .push_back (value);
142+ fragment_uniform_cache_.has_lights = true ;
143+ fragment_uniform_cache_.derived_valid = false ;
144+ if (fragment_uniform_cache_.has_lights && fragment_uniform_cache_.has_camera ) {
145+ RecalculateFragmentDerived ();
141146 }
142- fragment_uniform_cache_.light = value;
143- fragment_uniform_cache_.has_light = true ;
147+ }
148+
149+ void Shader::UpdateFragmentCache (const std::string& name,
150+ const std::vector<Light>& value) {
151+ if (name != " lights" ) { return ; }
152+ fragment_uniform_cache_.lights = value;
153+ fragment_uniform_cache_.has_lights = true ;
144154 fragment_uniform_cache_.derived_valid = false ;
145- if (fragment_uniform_cache_.has_light && fragment_uniform_cache_.has_camera ) {
155+ if (fragment_uniform_cache_.has_lights && fragment_uniform_cache_.has_camera ) {
146156 RecalculateFragmentDerived ();
147157 }
148158}
@@ -155,14 +165,18 @@ void Shader::UpdateFragmentCache(const std::string& name,
155165 fragment_uniform_cache_.camera_pos = value;
156166 fragment_uniform_cache_.has_camera = true ;
157167 fragment_uniform_cache_.derived_valid = false ;
158- if (fragment_uniform_cache_.has_light && fragment_uniform_cache_.has_camera ) {
168+ if (fragment_uniform_cache_.has_lights && fragment_uniform_cache_.has_camera ) {
159169 RecalculateFragmentDerived ();
160170 }
161171}
162172
163173void Shader::RecalculateFragmentDerived () {
164- fragment_uniform_cache_.light_dir_normalized =
165- glm::normalize (fragment_uniform_cache_.light .dir );
174+ fragment_uniform_cache_.light_dirs_normalized .clear ();
175+ fragment_uniform_cache_.light_dirs_normalized .reserve (
176+ fragment_uniform_cache_.lights .size ());
177+ for (const auto & l : fragment_uniform_cache_.lights ) {
178+ fragment_uniform_cache_.light_dirs_normalized .push_back (glm::normalize (l.dir ));
179+ }
166180 fragment_uniform_cache_.derived_valid = true ;
167181}
168182
@@ -196,13 +210,27 @@ void Shader::PrepareFragmentUniformCache() {
196210 if (fragment_uniform_cache_.derived_valid ) {
197211 return ;
198212 }
213+ // 优先多光源
214+ if (uniformbuffer_.HasUniform <std::vector<Light>>(" lights" ) &&
215+ uniformbuffer_.HasUniform <Vector3f>(" cameraPos" )) {
216+ fragment_uniform_cache_.lights =
217+ uniformbuffer_.GetUniform <std::vector<Light>>(" lights" );
218+ fragment_uniform_cache_.has_lights = true ;
219+ fragment_uniform_cache_.camera_pos =
220+ uniformbuffer_.GetUniform <Vector3f>(" cameraPos" );
221+ fragment_uniform_cache_.has_camera = true ;
222+ RecalculateFragmentDerived ();
223+ return ;
224+ }
225+ // 兼容单光源
199226 if (uniformbuffer_.HasUniform <Light>(" light" ) &&
200227 uniformbuffer_.HasUniform <Vector3f>(" cameraPos" )) {
201- fragment_uniform_cache_.light =
202- uniformbuffer_.GetUniform <Light>(" light" );
228+ fragment_uniform_cache_.lights .clear ();
229+ fragment_uniform_cache_.lights .push_back (
230+ uniformbuffer_.GetUniform <Light>(" light" ));
203231 fragment_uniform_cache_.camera_pos =
204232 uniformbuffer_.GetUniform <Vector3f>(" cameraPos" );
205- fragment_uniform_cache_.has_light = true ;
233+ fragment_uniform_cache_.has_lights = true ;
206234 fragment_uniform_cache_.has_camera = true ;
207235 RecalculateFragmentDerived ();
208236 }
@@ -259,59 +287,81 @@ auto Shader::EvaluateSpecular(float cos_theta, float shininess) const -> float {
259287}
260288
261289Color Shader::FragmentShader (const Fragment& fragment) const {
262- // interpolate Normal, Color and UV
263- Color interpolateColor = fragment.color ;
290+ // Helper: 将 Color 转为 [0,1] 归一化向量
291+ auto color_to_vec = [](const Color& c) -> Vector3f {
292+ constexpr float inv255 = 1 .0f / 255 .0f ;
293+ return Vector3f (static_cast <float >(c[Color::kColorIndexRed ]) * inv255,
294+ static_cast <float >(c[Color::kColorIndexGreen ]) * inv255,
295+ static_cast <float >(c[Color::kColorIndexBlue ]) * inv255);
296+ };
297+
298+ // 输入插值属性
299+ Vector3f base_color = color_to_vec (fragment.color );
264300 Vector3f normal = glm::normalize (fragment.normal );
265301 Vector2f uv = fragment.uv ;
266302
267- // uniform
268- Light light ;
269- Vector3f light_dir ;
303+ // uniform(优先缓存)
304+ std::vector< Light> lights ;
305+ std::vector< Vector3f> light_dirs ;
270306 Vector3f camera_pos;
271307 if (fragment_uniform_cache_.derived_valid ) {
272- light = fragment_uniform_cache_.light ;
273- light_dir = fragment_uniform_cache_.light_dir_normalized ;
308+ lights = fragment_uniform_cache_.lights ;
309+ light_dirs = fragment_uniform_cache_.light_dirs_normalized ;
274310 camera_pos = fragment_uniform_cache_.camera_pos ;
275311 } else {
276- light = uniformbuffer_.GetUniform <Light>(" light" );
312+ if (uniformbuffer_.HasUniform <std::vector<Light>>(" lights" )) {
313+ lights = uniformbuffer_.GetUniform <std::vector<Light>>(" lights" );
314+ light_dirs.reserve (lights.size ());
315+ for (const auto & l : lights) light_dirs.push_back (glm::normalize (l.dir ));
316+ } else if (uniformbuffer_.HasUniform <Light>(" light" )) {
317+ lights = {uniformbuffer_.GetUniform <Light>(" light" )};
318+ light_dirs = {glm::normalize (lights[0 ].dir )};
319+ }
277320 camera_pos = uniformbuffer_.GetUniform <Vector3f>(" cameraPos" );
278- light_dir = glm::normalize (light.dir );
279321 }
322+
280323 Material material = *fragment.material ;
281324
282- // view direction
283- Vector3f view_dir =
284- glm::normalize (sharedDataInShader_.fragPos_varying - camera_pos);
325+ // 视线方向
326+ Vector3f view_dir = glm::normalize (sharedDataInShader_.fragPos_varying - camera_pos);
285327
286- auto intensity = std::max (glm::dot (normal, light_dir), 0 .0f );
287- // texture color
288- Color ambient_color, diffuse_color, specular_color;
328+ // ambient(只计算一次,使用纹理或顶点颜色)
329+ Vector3f ambient_rgb;
289330 if (material.has_ambient_texture ) {
290- Color texture_color = SampleTexture (material.ambient_texture , uv);
291- ambient_color = texture_color;
331+ ambient_rgb = color_to_vec (SampleTexture (material.ambient_texture , uv));
292332 } else {
293- ambient_color = interpolateColor ;
333+ ambient_rgb = base_color ;
294334 }
295335
296- if (material.has_diffuse_texture ) {
297- Color texture_color = SampleTexture (material.diffuse_texture , uv);
298- diffuse_color = texture_color * intensity;
299- } else {
300- diffuse_color = interpolateColor * intensity;
301- }
302-
303- Vector3f halfVector = glm::normalize (light_dir + view_dir);
304- float cos_theta = std::max (glm::dot (normal, halfVector), 0 .0f );
305- float spec = EvaluateSpecular (cos_theta, material.shininess );
306- if (material.has_specular_texture ) {
307- Color texture_color = SampleTexture (material.specular_texture , uv);
308- specular_color = texture_color * spec;
309- } else {
310- specular_color = Color (1 .0f , 1 .0f , 1 .0f ) * spec;
336+ // diffuse/specular 累加(float 归一化空间,避免 8bit 溢出与截断)
337+ Vector3f diffuse_accum (0 .0f );
338+ Vector3f specular_accum (0 .0f );
339+ for (size_t i = 0 ; i < light_dirs.size (); ++i) {
340+ const Vector3f& ldir = light_dirs[i];
341+ float intensity = std::max (glm::dot (normal, ldir), 0 .0f );
342+
343+ // diffuse
344+ Vector3f kd = material.has_diffuse_texture
345+ ? color_to_vec (SampleTexture (material.diffuse_texture , uv))
346+ : base_color;
347+ diffuse_accum += kd * intensity;
348+
349+ // specular
350+ Vector3f halfVector = glm::normalize (ldir + view_dir);
351+ float cos_theta = std::max (glm::dot (normal, halfVector), 0 .0f );
352+ float spec = EvaluateSpecular (cos_theta, material.shininess );
353+ Vector3f ks = material.has_specular_texture
354+ ? color_to_vec (SampleTexture (material.specular_texture , uv))
355+ : Vector3f (1 .0f );
356+ specular_accum += ks * spec;
311357 }
312358
313- return ClampColor (ambient_color * 0 .1f + diffuse_color +
314- specular_color * 0 .2f );
359+ Vector3f out_rgb = ambient_rgb * 0 .1f + diffuse_accum + specular_accum * 0 .2f ;
360+ // clamp 到 [0,1]
361+ out_rgb.x = std::clamp (out_rgb.x , 0 .0f , 1 .0f );
362+ out_rgb.y = std::clamp (out_rgb.y , 0 .0f , 1 .0f );
363+ out_rgb.z = std::clamp (out_rgb.z , 0 .0f , 1 .0f );
364+ return Color (out_rgb.x , out_rgb.y , out_rgb.z , 1 .0f );
315365}
316366
317367// 将浮点数转换为 uint8_t
0 commit comments