Working on the night mode

This commit is contained in:
Vladislav Khorev committed 2026-06-04 13:27:52 +03:00
1 parent e6bfe85e2e
commit 442d3a7945
18 files changed
+1060 -2

No files matched your search

+289
View File
@@ -901,6 +901,295 @@ void Character::drawGpuSkinningWithShadow(Renderer& renderer, const Eigen::Matri
CheckGlError(__FILE__, __LINE__);
}
// ==================== Night pass with point lights ====================
void Character::drawNight(Renderer& renderer, const float* pointLightPosEye, const float* pointLightDirEye, const float* pointLightColors, int pointLightCount) {
if (!enabled) return;
if (hitSparkEmitter.isConfigured() && hitSparkEmitter.getActiveParticleCount() > 0) {
hitSparkEmitter.draw(renderer, 1.0f, Environment::width, Environment::height, false);
}
renderer.RenderUniform1f("uAlpha", 1.0f);
glDisable(GL_BLEND);
if (!isPlayer && hp <= 0) return;
if (useGpuSkinning) {
drawNightGpuSkinning(renderer, pointLightPosEye, pointLightDirEye, pointLightColors, pointLightCount);
} else {
drawNightCpu(renderer, pointLightPosEye, pointLightDirEye, pointLightColors, pointLightCount);
}
}
void Character::drawNightGpuSkinning(Renderer& renderer, const float* plPosEye, const float* plDirEye, const float* plColors, int plCount) {
AnimationState drawState = resolveActiveState();
auto it = animations.find(drawState);
if (it == animations.end()) return;
if (!prepareGpuSkinning()) return;
static const std::string nightSkinningShader = "night_fog_skinning";
static const std::string boneMatricesUniform = "uBoneMatrices[0]";
renderer.shaderManager.PushShader(nightSkinningShader);
renderer.RenderUniform1i(textureUniformName, 0);
const float playerEyePosNight[3] = { 0.0f, 0.0f, -Environment::zoom };
renderer.RenderUniform3fv("uPlayerEyePos", playerEyePosNight);
renderer.RenderUniform1i("uPointLightCount", plCount);
if (plCount > 0) {
renderer.RenderUniform3fvArray("uPointLightPos[0]", plCount, plPosEye);
renderer.RenderUniform3fvArray("uPointLightDir[0]", plCount, plDirEye);
renderer.RenderUniform3fvArray("uPointLightColor[0]", plCount, plColors);
}
renderer.PushPerspectiveProjectionMatrix(1.0 / 1.5,
static_cast<float>(Environment::width) / static_cast<float>(Environment::height),
Environment::CONST_Z_NEAR, Environment::CONST_Z_FAR);
renderer.PushMatrix();
renderer.TranslateMatrix({ position.x(), position.y(), position.z() });
renderer.RotateMatrix(Eigen::Quaternionf(Eigen::AngleAxisf(-facingAngle, Eigen::Vector3f::UnitY())).toRotationMatrix());
renderer.ScaleMatrix(modelScale);
renderer.RotateMatrix(modelCorrectionRotation.toRotationMatrix());
renderer.RenderUniformMatrix4fvArray(boneMatricesUniform,
static_cast<int>(it->second.gpuSkinningShaderData.skinningMatrices.size()), false,
it->second.gpuSkinningShaderData.skinningMatrices[0].data());
for (const auto& name : it->second.model.meshNamesOrdered) {
auto pit = it->second.gpuSkinningShaderData.perMesh.find(name);
if (pit == it->second.gpuSkinningShaderData.perMesh.end()) continue;
auto tit = meshTextures.find(name);
if (tit == meshTextures.end() || !tit->second) continue;
glBindTexture(GL_TEXTURE_2D, tit->second->getTexID());
pit->second.RenderVBO(renderer);
}
renderer.PopMatrix();
renderer.shaderManager.PushShader("night_fog");
renderer.RenderUniform1i(textureUniformName, 0);
renderer.RenderUniform3fv("uPlayerEyePos", playerEyePosNight);
renderer.RenderUniform1i("uPointLightCount", plCount);
if (plCount > 0) {
renderer.RenderUniform3fvArray("uPointLightPos[0]", plCount, plPosEye);
renderer.RenderUniform3fvArray("uPointLightDir[0]", plCount, plDirEye);
renderer.RenderUniform3fvArray("uPointLightColor[0]", plCount, plColors);
}
drawAttachedWeapon(renderer);
renderer.shaderManager.PopShader();
renderer.PopProjectionMatrix();
renderer.shaderManager.PopShader();
}
void Character::drawNightCpu(Renderer& renderer, const float* plPosEye, const float* plDirEye, const float* plColors, int plCount) {
AnimationState drawState = resolveActiveState();
auto it = animations.find(drawState);
if (it == animations.end()) return;
static const std::string nightShader = "night_fog";
renderer.shaderManager.PushShader(nightShader);
renderer.RenderUniform1i(textureUniformName, 0);
const float playerEyePosNight[3] = { 0.0f, 0.0f, -Environment::zoom };
renderer.RenderUniform3fv("uPlayerEyePos", playerEyePosNight);
renderer.RenderUniform1i("uPointLightCount", plCount);
if (plCount > 0) {
renderer.RenderUniform3fvArray("uPointLightPos[0]", plCount, plPosEye);
renderer.RenderUniform3fvArray("uPointLightDir[0]", plCount, plDirEye);
renderer.RenderUniform3fvArray("uPointLightColor[0]", plCount, plColors);
}
renderer.PushPerspectiveProjectionMatrix(1.0 / 1.5,
static_cast<float>(Environment::width) / static_cast<float>(Environment::height),
Environment::CONST_Z_NEAR, Environment::CONST_Z_FAR);
renderer.PushMatrix();
renderer.TranslateMatrix({ position.x(), position.y(), position.z() });
renderer.RotateMatrix(Eigen::Quaternionf(Eigen::AngleAxisf(-facingAngle, Eigen::Vector3f::UnitY())).toRotationMatrix());
renderer.ScaleMatrix(modelScale);
renderer.RotateMatrix(modelCorrectionRotation.toRotationMatrix());
auto& anim = it->second;
for (const auto& name : anim.model.meshNamesOrdered) {
auto mit = anim.model.meshes.find(name);
if (mit == anim.model.meshes.end()) continue;
auto tit = meshTextures.find(name);
if (tit == meshTextures.end() || !tit->second) continue;
glBindTexture(GL_TEXTURE_2D, tit->second->getTexID());
modelMutable.AssignFrom(mit->second.mesh);
modelMutable.RefreshVBO();
renderer.DrawVertexRenderStruct(modelMutable);
}
renderer.PopMatrix();
renderer.RenderUniform3fv("uPlayerEyePos", playerEyePosNight);
drawAttachedWeapon(renderer);
renderer.PopProjectionMatrix();
renderer.shaderManager.PopShader();
}
// ==================== Night pass with spot-light + shadow ====================
void Character::drawNightWithShadow(Renderer& renderer,
const float* plPosEye, const float* plDirEye, const float* plColors, int plCount,
const Eigen::Matrix4f& lightFromCamera, GLuint shadowMapTex)
{
if (!enabled) return;
if (hitSparkEmitter.isConfigured() && hitSparkEmitter.getActiveParticleCount() > 0) {
hitSparkEmitter.draw(renderer, 1.0f, Environment::width, Environment::height, false);
}
renderer.RenderUniform1f("uAlpha", 1.0f);
glDisable(GL_BLEND);
if (!isPlayer && hp <= 0) return;
if (useGpuSkinning) {
drawNightGpuSkinningWithShadow(renderer, plPosEye, plDirEye, plColors, plCount, lightFromCamera, shadowMapTex);
} else {
drawNightCpuWithShadow(renderer, plPosEye, plDirEye, plColors, plCount, lightFromCamera, shadowMapTex);
}
}
void Character::drawNightGpuSkinningWithShadow(Renderer& renderer,
const float* plPosEye, const float* plDirEye, const float* plColors, int plCount,
const Eigen::Matrix4f& lightFromCamera, GLuint shadowMapTex)
{
AnimationState drawState = resolveActiveState();
auto it = animations.find(drawState);
if (it == animations.end()) return;
if (!prepareGpuSkinning()) return;
static const std::string nightShadowSkinningShader = "night_fog_skinning_shadow";
static const std::string boneMatricesUniform = "uBoneMatrices[0]";
renderer.shaderManager.PushShader(nightShadowSkinningShader);
renderer.RenderUniform1i(textureUniformName, 0);
renderer.RenderUniform1i("uShadowMap", 1);
renderer.RenderUniformMatrix4fv("uLightFromCamera", false, lightFromCamera.data());
// First light's eye-space direction used for shadow bias
if (plCount > 0) renderer.RenderUniform3fv("uLightDir", plDirEye);
const float playerEyePosNightShadow[3] = { 0.0f, 0.0f, -Environment::zoom };
renderer.RenderUniform3fv("uPlayerEyePos", playerEyePosNightShadow);
renderer.RenderUniform1i("uPointLightCount", plCount);
if (plCount > 0) {
renderer.RenderUniform3fvArray("uPointLightPos[0]", plCount, plPosEye);
renderer.RenderUniform3fvArray("uPointLightDir[0]", plCount, plDirEye);
renderer.RenderUniform3fvArray("uPointLightColor[0]", plCount, plColors);
}
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, shadowMapTex);
glActiveTexture(GL_TEXTURE0);
renderer.PushPerspectiveProjectionMatrix(1.0 / 1.5,
static_cast<float>(Environment::width) / static_cast<float>(Environment::height),
Environment::CONST_Z_NEAR, Environment::CONST_Z_FAR);
renderer.PushMatrix();
renderer.TranslateMatrix({ position.x(), position.y(), position.z() });
renderer.RotateMatrix(Eigen::Quaternionf(Eigen::AngleAxisf(-facingAngle, Eigen::Vector3f::UnitY())).toRotationMatrix());
renderer.ScaleMatrix(modelScale);
renderer.RotateMatrix(modelCorrectionRotation.toRotationMatrix());
renderer.RenderUniformMatrix4fvArray(boneMatricesUniform,
static_cast<int>(it->second.gpuSkinningShaderData.skinningMatrices.size()), false,
it->second.gpuSkinningShaderData.skinningMatrices[0].data());
for (const auto& name : it->second.model.meshNamesOrdered) {
auto pit = it->second.gpuSkinningShaderData.perMesh.find(name);
if (pit == it->second.gpuSkinningShaderData.perMesh.end()) continue;
auto tit = meshTextures.find(name);
if (tit == meshTextures.end() || !tit->second) continue;
glBindTexture(GL_TEXTURE_2D, tit->second->getTexID());
pit->second.RenderVBO(renderer);
}
renderer.PopMatrix();
// Weapon uses the non-skinning night shadow shader
renderer.shaderManager.PushShader("night_fog_shadow");
renderer.RenderUniform1i(textureUniformName, 0);
renderer.RenderUniform1i("uShadowMap", 1);
renderer.RenderUniformMatrix4fv("uLightFromCamera", false, lightFromCamera.data());
if (plCount > 0) renderer.RenderUniform3fv("uLightDir", plDirEye);
renderer.RenderUniform3fv("uPlayerEyePos", playerEyePosNightShadow);
renderer.RenderUniform1i("uPointLightCount", plCount);
if (plCount > 0) {
renderer.RenderUniform3fvArray("uPointLightPos[0]", plCount, plPosEye);
renderer.RenderUniform3fvArray("uPointLightDir[0]", plCount, plDirEye);
renderer.RenderUniform3fvArray("uPointLightColor[0]", plCount, plColors);
}
drawAttachedWeapon(renderer);
renderer.shaderManager.PopShader();
renderer.PopProjectionMatrix();
renderer.shaderManager.PopShader();
}
void Character::drawNightCpuWithShadow(Renderer& renderer,
const float* plPosEye, const float* plDirEye, const float* plColors, int plCount,
const Eigen::Matrix4f& lightFromCamera, GLuint shadowMapTex)
{
AnimationState drawState = resolveActiveState();
auto it = animations.find(drawState);
if (it == animations.end()) return;
static const std::string nightShadowShader = "night_fog_shadow";
renderer.shaderManager.PushShader(nightShadowShader);
renderer.RenderUniform1i(textureUniformName, 0);
renderer.RenderUniform1i("uShadowMap", 1);
renderer.RenderUniformMatrix4fv("uLightFromCamera", false, lightFromCamera.data());
if (plCount > 0) renderer.RenderUniform3fv("uLightDir", plDirEye);
const float playerEyePosNightShadow[3] = { 0.0f, 0.0f, -Environment::zoom };
renderer.RenderUniform3fv("uPlayerEyePos", playerEyePosNightShadow);
renderer.RenderUniform1i("uPointLightCount", plCount);
if (plCount > 0) {
renderer.RenderUniform3fvArray("uPointLightPos[0]", plCount, plPosEye);
renderer.RenderUniform3fvArray("uPointLightDir[0]", plCount, plDirEye);
renderer.RenderUniform3fvArray("uPointLightColor[0]", plCount, plColors);
}
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, shadowMapTex);
glActiveTexture(GL_TEXTURE0);
renderer.PushPerspectiveProjectionMatrix(1.0 / 1.5,
static_cast<float>(Environment::width) / static_cast<float>(Environment::height),
Environment::CONST_Z_NEAR, Environment::CONST_Z_FAR);
renderer.PushMatrix();
renderer.TranslateMatrix({ position.x(), position.y(), position.z() });
renderer.RotateMatrix(Eigen::Quaternionf(Eigen::AngleAxisf(-facingAngle, Eigen::Vector3f::UnitY())).toRotationMatrix());
renderer.ScaleMatrix(modelScale);
renderer.RotateMatrix(modelCorrectionRotation.toRotationMatrix());
auto& anim = it->second;
for (const auto& name : anim.model.meshNamesOrdered) {
auto mit = anim.model.meshes.find(name);
if (mit == anim.model.meshes.end()) continue;
auto tit = meshTextures.find(name);
if (tit == meshTextures.end() || !tit->second) continue;
glBindTexture(GL_TEXTURE_2D, tit->second->getTexID());
modelMutable.AssignFrom(mit->second.mesh);
modelMutable.RefreshVBO();
renderer.DrawVertexRenderStruct(modelMutable);
}
renderer.PopMatrix();
renderer.RenderUniform3fv("uPlayerEyePos", playerEyePosNightShadow);
drawAttachedWeapon(renderer);
renderer.PopProjectionMatrix();
renderer.shaderManager.PopShader();
}
void Character::setupHitSparks(std::shared_ptr<Texture> sparkTexture)
{
hitSparkEmitter.setTexture(sparkTexture);