RENDERER: Fix animation interpolation at cycle boundaries for alias models#1101
Draft
RENDERER: Fix animation interpolation at cycle boundaries for alias models#1101
Conversation
…dels Previously, animation interpolation was broken at loop boundaries (e.g. frame 7 -> frame 0) for both MDL and MD3 models. This caused visible snapping/popping when an animation cycled back to the beginning. Root causes: 1. `R_AliasModelDeterminePoses` set lerp=1 for non-sequential frame pairs, disabling interpolation at cycle boundaries. 2. `R_AliasModelPrepare` checked that frame2 == expected_next_frame, rejecting legitimate cross-boundary lerp pairs. 3. Classic GL shaders used precomputed direction vectors (nextFrame - currentFrame) baked into VBO at load time. At cycle boundaries these vectors point to the wrong target frame, producing garbage geometry. Classic GL fix (macOS, RENDERER_MODERN_OPENGL=OFF): - Remove the non-sequential frame guard in `R_AliasModelDeterminePoses` so `lerpfrac = r_framelerp` for all frame pairs. - Remove the `expected_frame` check in `R_AliasModelPrepare`. - Change all classic GL alias model vertex shaders from the precomputed- direction formula (`pos + dir * t`) to `mix(pos1, pos2, t)`, where `gl_MultiTexCoord1` is rebound per draw call to carry pose2 positions instead of baked direction vectors. - Add `GLC_BindPose2TextureCoord[_MD3]()` helpers that override the VAO's texcoord1 binding after each state setup call (which resets the VAO), pointing it at the VBO region for the second pose. - When pose2 precedes pose1 in the VBO (cycle boundary where frame2 < frame1), swap the two poses and invert lerpfrac to ensure the VBO offset `(pose2Vert - firstVert)` is always non-negative. Swapping is mathematically equivalent: mix(a, b, t) == mix(b, a, 1-t). - Pass pose2 to `GLC_DrawPowerupShell_Program` and `GLC_DrawAliasModelShadowDrawCall_Program` (previously only received pose1), and apply the same rebind + swap logic there. - Inline `GLC_DrawCachedAliasOutlineFrame` at its call site so that `GLC_BindPose2TextureCoord` can be inserted between the state setup and `GL_DrawArrays`; remove the now-unused function. Modern GL fix (Linux/Windows, RENDERER_MODERN_OPENGL=ON): - Add `pose1Base` / `pose2Base` fields to the per-instance uniform block so the vertex shader can locate the correct second-pose data. - Create a per-model SSBO (r_buffer_aliasmodel_vertex_ssbo) containing the full vertex array as raw floats (same data as the VBO). - In the vertex shader, use `gl_VertexID` to index into the SSBO and read pose2 position directly, replacing the `pos + vboDirection * t` formula with `mix(vboPosition, pose2Position, t)`. - Bind the SSBO in `GLM_PrepareAliasModelBatches` before the draw. Affected files: src/r_aliasmodel.c - lerp guards src/r_aliasmodel_mesh.c - SSBO creation (modern GL) src/glc_aliasmodel.c - pose2 rebind helpers, swap logic (MDL) src/glc_md3.c - pose2 rebind helpers, swap logic (MD3) src/glm_aliasmodel.c - pose1Base/pose2Base uniforms, SSBO bind src/glsl/common.glsl - pose1Base/pose2Base in AliasModel struct src/glsl/constants.glsl - EZQ_GL_BINDINGPOINT_ALIASMODEL_SSBO = 6 src/glsl/draw_aliasmodel.vertex.glsl - SSBO read + mix() (modern GL) src/glsl/glc/glc_aliasmodel_std.vertex.glsl - mix() formula (classic) src/glsl/glc/glc_aliasmodel_shadow.vertex.glsl - mix() formula (classic) src/glsl/glc/glc_aliasmodel_shell.vertex.glsl - mix() formula (classic)
0739ecd to
03da02f
Compare
Collaborator
|
as of now i get a ton of artifacts |
Collaborator
Author
yeah, as I mention in description, you probably using vid_rendrer 1, could not test it. Anyway, PR a draft for a reason. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Previously, animation interpolation was broken at loop boundaries (e.g.
frame 7 -> frame 0) for both MDL and MD3 models. This caused visible
snapping/popping when an animation cycled back to the beginning.
Root causes:
R_AliasModelDeterminePosesset lerp=1 for non-sequential frame pairs,disabling interpolation at cycle boundaries.
R_AliasModelPreparechecked that frame2 == expected_next_frame,rejecting legitimate cross-boundary lerp pairs.
currentFrame) baked into VBO at load time. At cycle boundaries these
vectors point to the wrong target frame, producing garbage geometry.
Classic GL fix (macOS, RENDERER_MODERN_OPENGL=OFF):
R_AliasModelDeterminePosesso
lerpfrac = r_framelerpfor all frame pairs.expected_framecheck inR_AliasModelPrepare.direction formula (
pos + dir * t) tomix(pos1, pos2, t), wheregl_MultiTexCoord1is rebound per draw call to carry pose2 positionsinstead of baked direction vectors.
GLC_BindPose2TextureCoord[_MD3]()helpers that override theVAO's texcoord1 binding after each state setup call (which resets the
VAO), pointing it at the VBO region for the second pose.
frame1), swap the two poses and invert lerpfrac to ensure the VBO
offset
(pose2Vert - firstVert)is always non-negative. Swapping ismathematically equivalent: mix(a, b, t) == mix(b, a, 1-t).
GLC_DrawPowerupShell_ProgramandGLC_DrawAliasModelShadowDrawCall_Program(previously only receivedpose1), and apply the same rebind + swap logic there.
GLC_DrawCachedAliasOutlineFrameat its call site so thatGLC_BindPose2TextureCoordcan be inserted between the state setupand
GL_DrawArrays; remove the now-unused function.Modern GL fix (Linux/Windows, RENDERER_MODERN_OPENGL=ON):
pose1Base/pose2Basefields to the per-instance uniform blockso the vertex shader can locate the correct second-pose data.
the full vertex array as raw floats (same data as the VBO).
gl_VertexIDto index into the SSBO andread pose2 position directly, replacing the
pos + vboDirection * tformula with
mix(vboPosition, pose2Position, t).GLM_PrepareAliasModelBatchesbefore the draw.Affected files:
src/r_aliasmodel.c - lerp guards
src/r_aliasmodel_mesh.c - SSBO creation (modern GL)
src/glc_aliasmodel.c - pose2 rebind helpers, swap logic (MDL)
src/glc_md3.c - pose2 rebind helpers, swap logic (MD3)
src/glm_aliasmodel.c - pose1Base/pose2Base uniforms, SSBO bind
src/glsl/common.glsl - pose1Base/pose2Base in AliasModel struct
src/glsl/constants.glsl - EZQ_GL_BINDINGPOINT_ALIASMODEL_SSBO = 6
src/glsl/draw_aliasmodel.vertex.glsl - SSBO read + mix() (modern GL)
src/glsl/glc/glc_aliasmodel_std.vertex.glsl - mix() formula (classic)
src/glsl/glc/glc_aliasmodel_shadow.vertex.glsl - mix() formula (classic)
src/glsl/glc/glc_aliasmodel_shell.vertex.glsl - mix() formula (classic)