Added shadow maps

This commit is contained in:
Vladislav Khorev committed 2026-04-15 19:54:21 +03:00
1 parent a47306533e
commit d8795ec076
15 files changed
+880 -6

No files matched your search

+226 -4
View File
@@ -249,7 +249,11 @@ void Character::draw(Renderer& renderer) {
}
void Character::prepareGpuSkinningVBOs(AnimationData& anim) {
if (anim.gpuSkinningPrepared) return;
if (anim.gpuSkinningPrepared)
{
return;
}
anim.model.PrepareGpuSkinningData();
@@ -284,13 +288,18 @@ void Character::prepareGpuSkinningVBOs(AnimationData& anim) {
void Character::drawGpuSkinning(Renderer& renderer) {
AnimationState drawState = resolveActiveState();
auto it = animations.find(drawState);
if (it == animations.end() || !texture) return;
if (it == animations.end() || !texture)
{
return;
}
auto& anim = it->second;
prepareGpuSkinningVBOs(anim);
if (anim.skinningMatrices.empty()) return;
if (anim.skinningMatrices.empty())
{
return;
}
static const std::string skinningShaderName = "skinning";
static const std::string boneMatricesUniform = "uBoneMatrices[0]";
@@ -354,4 +363,217 @@ void Character::drawGpuSkinning(Renderer& renderer) {
renderer.shaderManager.PopShader();
}
// ==================== Shadow depth pass ====================
void Character::drawShadowDepth(Renderer& renderer) {
if (useGpuSkinning) {
drawShadowDepthGpuSkinning(renderer);
} else {
drawShadowDepthCpu(renderer);
}
}
void Character::drawShadowDepthCpu(Renderer& renderer) {
AnimationState drawState = resolveActiveState();
auto it = animations.find(drawState);
if (it == animations.end()) return;
// The caller has already pushed the shadow_depth shader and the
// light's projection + view onto the renderer stacks.
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;
anim.modelMutable.AssignFrom(anim.model.mesh);
anim.modelMutable.RefreshVBO();
renderer.DrawVertexRenderStruct(anim.modelMutable);
renderer.PopMatrix();
}
void Character::drawShadowDepthGpuSkinning(Renderer& renderer) {
AnimationState drawState = resolveActiveState();
auto it = animations.find(drawState);
if (it == animations.end()) return;
auto& anim = it->second;
prepareGpuSkinningVBOs(anim);
if (anim.skinningMatrices.empty()) return;
static const std::string shadowSkinningShader = "shadow_depth_skinning";
static const std::string boneMatricesUniform = "uBoneMatrices[0]";
// Switch to the skinning depth shader (caller has the static depth shader active).
renderer.shaderManager.PushShader(shadowSkinningShader);
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>(anim.skinningMatrices.size()), false,
anim.skinningMatrices[0].data());
#ifndef EMSCRIPTEN
#ifndef __ANDROID__
if (anim.bindPoseMutable.vao) {
glBindVertexArray(anim.bindPoseMutable.vao->getBuffer());
renderer.shaderManager.EnableVertexAttribArrays();
}
#endif
#endif
glBindBuffer(GL_ARRAY_BUFFER, anim.bindPoseMutable.positionVBO->getBuffer());
renderer.VertexAttribPointer3fv("vPosition", 0, NULL);
if (anim.bindPoseMutable.texCoordVBO) {
glBindBuffer(GL_ARRAY_BUFFER, anim.bindPoseMutable.texCoordVBO->getBuffer());
renderer.VertexAttribPointer2fv("vTexCoord", 0, NULL);
}
glBindBuffer(GL_ARRAY_BUFFER, anim.boneIndices0VBO->getBuffer());
renderer.VertexAttribPointer4fv("aBoneIndices0", 0, NULL);
glBindBuffer(GL_ARRAY_BUFFER, anim.boneIndices1VBO->getBuffer());
renderer.VertexAttribPointer2fv("aBoneIndices1", 0, NULL);
glBindBuffer(GL_ARRAY_BUFFER, anim.boneWeights0VBO->getBuffer());
renderer.VertexAttribPointer4fv("aBoneWeights0", 0, NULL);
glBindBuffer(GL_ARRAY_BUFFER, anim.boneWeights1VBO->getBuffer());
renderer.VertexAttribPointer2fv("aBoneWeights1", 0, NULL);
glDrawArrays(GL_TRIANGLES, 0, static_cast<GLsizei>(anim.bindPoseMutable.data.PositionData.size()));
renderer.PopMatrix();
renderer.shaderManager.PopShader();
}
// ==================== Main pass with shadows ====================
void Character::drawWithShadow(Renderer& renderer, const Eigen::Matrix4f& lightFromCamera, GLuint shadowMapTex, const Eigen::Vector3f& lightDirCamera) {
if (useGpuSkinning) {
drawGpuSkinningWithShadow(renderer, lightFromCamera, shadowMapTex, lightDirCamera);
} else {
drawCpuWithShadow(renderer, lightFromCamera, shadowMapTex, lightDirCamera);
}
}
void Character::drawCpuWithShadow(Renderer& renderer, const Eigen::Matrix4f& lightFromCamera, GLuint shadowMapTex, const Eigen::Vector3f& lightDirCamera) {
AnimationState drawState = resolveActiveState();
auto it = animations.find(drawState);
if (it == animations.end() || !texture) return;
static const std::string shadowShader = "default_shadow";
renderer.shaderManager.PushShader(shadowShader);
renderer.RenderUniform1i(textureUniformName, 0);
renderer.RenderUniform1i("uShadowMap", 1);
renderer.RenderUniformMatrix4fv("uLightFromCamera", false, lightFromCamera.data());
renderer.RenderUniform3fv("uLightDir", lightDirCamera.data());
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;
anim.modelMutable.AssignFrom(anim.model.mesh);
anim.modelMutable.RefreshVBO();
glBindTexture(GL_TEXTURE_2D, texture->getTexID());
renderer.DrawVertexRenderStruct(anim.modelMutable);
renderer.PopMatrix();
renderer.PopProjectionMatrix();
renderer.shaderManager.PopShader();
}
void Character::drawGpuSkinningWithShadow(Renderer& renderer, const Eigen::Matrix4f& lightFromCamera, GLuint shadowMapTex, const Eigen::Vector3f& lightDirCamera) {
AnimationState drawState = resolveActiveState();
auto it = animations.find(drawState);
if (it == animations.end() || !texture) return;
auto& anim = it->second;
prepareGpuSkinningVBOs(anim);
if (anim.skinningMatrices.empty()) return;
static const std::string skinningShadowShader = "skinning_shadow";
static const std::string boneMatricesUniform = "uBoneMatrices[0]";
renderer.shaderManager.PushShader(skinningShadowShader);
renderer.RenderUniform1i(textureUniformName, 0);
renderer.RenderUniform1i("uShadowMap", 1);
renderer.RenderUniformMatrix4fv("uLightFromCamera", false, lightFromCamera.data());
renderer.RenderUniform3fv("uLightDir", lightDirCamera.data());
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>(anim.skinningMatrices.size()), false,
anim.skinningMatrices[0].data());
glBindTexture(GL_TEXTURE_2D, texture->getTexID());
#ifndef EMSCRIPTEN
#ifndef __ANDROID__
if (anim.bindPoseMutable.vao) {
glBindVertexArray(anim.bindPoseMutable.vao->getBuffer());
renderer.shaderManager.EnableVertexAttribArrays();
}
#endif
#endif
glBindBuffer(GL_ARRAY_BUFFER, anim.bindPoseMutable.positionVBO->getBuffer());
renderer.VertexAttribPointer3fv("vPosition", 0, NULL);
if (anim.bindPoseMutable.texCoordVBO) {
glBindBuffer(GL_ARRAY_BUFFER, anim.bindPoseMutable.texCoordVBO->getBuffer());
renderer.VertexAttribPointer2fv("vTexCoord", 0, NULL);
}
// Bind normals for diffuse lighting (skinning_shadow shader skins them)
if (anim.bindPoseMutable.normalVBO) {
glBindBuffer(GL_ARRAY_BUFFER, anim.bindPoseMutable.normalVBO->getBuffer());
renderer.VertexAttribPointer3fv("vNormal", 0, NULL);
}
glBindBuffer(GL_ARRAY_BUFFER, anim.boneIndices0VBO->getBuffer());
renderer.VertexAttribPointer4fv("aBoneIndices0", 0, NULL);
glBindBuffer(GL_ARRAY_BUFFER, anim.boneIndices1VBO->getBuffer());
renderer.VertexAttribPointer2fv("aBoneIndices1", 0, NULL);
glBindBuffer(GL_ARRAY_BUFFER, anim.boneWeights0VBO->getBuffer());
renderer.VertexAttribPointer4fv("aBoneWeights0", 0, NULL);
glBindBuffer(GL_ARRAY_BUFFER, anim.boneWeights1VBO->getBuffer());
renderer.VertexAttribPointer2fv("aBoneWeights1", 0, NULL);
glDrawArrays(GL_TRIANGLES, 0, static_cast<GLsizei>(anim.bindPoseMutable.data.PositionData.size()));
renderer.PopMatrix();
renderer.PopProjectionMatrix();
renderer.shaderManager.PopShader();
}
} // namespace ZL