@@ -205,11 +205,17 @@ static void setScissor(RenderPass *self, const SDL_Rect *scissor) {
205205 // so w/h never exceed the space remaining from the clamped origin. A fully
206206 // offscreen scissor collapses to zero w/h, scissoring out the draw.
207207 // RenderPass does not yet capture the target dimensions, so the viewport
208- // (which the caller is expected to have set) stands in for them.
209- const int x = SDL_clamp (scissor -> x , 0 , (int ) self -> viewport .w );
210- const int y = SDL_clamp (scissor -> y , 0 , (int ) self -> viewport .h );
211- const int r = SDL_clamp (scissor -> x + scissor -> w , 0 , (int ) self -> viewport .w );
212- const int b = SDL_clamp (scissor -> y + scissor -> h , 0 , (int ) self -> viewport .h );
208+ // (which the caller is expected to have set) stands in for them. The bounds
209+ // are relative to the viewport *origin*, not (0, 0): a viewport offset into
210+ // the target (e.g. shadow atlas tiles) must not collapse the scissor.
211+ const int vx = (int ) self -> viewport .x ;
212+ const int vy = (int ) self -> viewport .y ;
213+ const int vw = (int ) self -> viewport .w ;
214+ const int vh = (int ) self -> viewport .h ;
215+ const int x = SDL_clamp (scissor -> x , vx , vx + vw );
216+ const int y = SDL_clamp (scissor -> y , vy , vy + vh );
217+ const int r = SDL_clamp (scissor -> x + scissor -> w , vx , vx + vw );
218+ const int b = SDL_clamp (scissor -> y + scissor -> h , vy , vy + vh );
213219 self -> scissor = (SDL_Rect ) { .x = x , .y = y , .w = r - x , .h = b - y };
214220 } else {
215221 // Reset to the full render target. RenderPass does not yet capture the
0 commit comments