## ADDED Requirements

### Requirement: Viewport renders USD stage geometry into an FBO-backed ImGui panel

The system SHALL render USD stage geometry into an OpenGL Framebuffer Object (FBO) and display the attached color texture via `ImGui::Image()` within the "Viewport" dockable panel.

#### Scenario: Viewport displays scene geometry when a stage is loaded
- **WHEN** a USD stage is opened and the Viewport panel is visible
- **THEN** the system traverses the stage's prim tree, extracts `UsdGeomMesh` data, and renders mesh geometry into the FBO
- **AND** the FBO color texture is displayed as an ImGui image in the Viewport panel

#### Scenario: Viewport shows empty background when no stage is loaded
- **WHEN** no USD stage is open
- **THEN** the Viewport panel displays a dark background with no geometry

### Requirement: FBO resizes to match viewport panel dimensions

The system SHALL resize the FBO color and depth attachments whenever the Viewport panel's content region dimensions change.

#### Scenario: FBO resized on dock layout change
- **WHEN** the user docks, undocks, or resizes the Viewport panel
- **THEN** the FBO is recreated with the new width and height from `ImGui::GetContentRegionAvail()`
- **AND** the previous FBO textures are deleted

#### Scenario: No unnecessary FBO reallocation
- **WHEN** the Viewport panel dimensions remain unchanged between frames
- **THEN** the FBO is not recreated

### Requirement: USD mesh geometry is extracted and uploaded to GPU buffers

The system SHALL traverse the UsdStage, extract `UsdGeomMesh` points, face vertex counts, face vertex indices, and normals, and upload them to OpenGL VBOs/VAOs.

#### Scenario: Mesh data loaded from UsdGeomMesh prims
- **WHEN** the stage is loaded or refreshed
- **THEN** for each `UsdGeomMesh` prim, the system reads `points`, `faceVertexCounts`, `faceVertexIndices`, and `normals` attributes
- **AND** uploads the data to OpenGL vertex buffer objects

#### Scenario: Missing normals handled gracefully
- **WHEN** a `UsdGeomMesh` prim has no authored normals
- **THEN** the system computes flat face normals from the triangle winding
- **AND** renders the mesh with the computed normals

### Requirement: Meshes are rendered with diffuse color from UsdShade or primvar

The system SHALL apply a diffuse color to each mesh obtained from `UsdShadeMaterial` binding or a `displayColor` primvar, falling back to a default color.

#### Scenario: Mesh with UsdShade material
- **WHEN** a mesh prim has a bound `UsdShadeMaterial` with a diffuse color output
- **THEN** the mesh is rendered with that diffuse color

#### Scenario: Mesh with displayColor primvar
- **WHEN** a mesh prim has a `primvars:displayColor` attribute and no bound material
- **THEN** the mesh is rendered with the displayColor value

#### Scenario: Mesh with no color information
- **WHEN** a mesh prim has neither a bound material nor a displayColor primvar
- **THEN** the mesh is rendered with a default gray color (0.7, 0.7, 0.7)

### Requirement: OpenGL shaders are GLSL #version 130 compatible

All viewport shaders SHALL be written in GLSL #version 130 and use the compatibility profile built-in variables (`gl_Vertex`, attribute bindings, etc.) to match the existing OpenGL context.

#### Scenario: Shaders compile on legacy OpenGL context
- **WHEN** the application initializes the viewport renderer
- **THEN** the vertex and fragment shaders compile successfully on the existing WGL OpenGL context initialized with `#version 130`

### Requirement: Scene rendering is refreshed when the stage changes

The system SHALL rebuild GPU geometry buffers when the USD stage is opened, closed, or when the stage content is modified.

#### Scenario: Stage opened triggers rebuild
- **WHEN** a new USD stage is opened
- **THEN** the renderer clears existing GPU buffers and re-traverses the new stage

#### Scenario: Stage closed clears geometry
- **WHEN** the current stage is closed
- **THEN** the renderer clears all GPU buffers and the viewport shows an empty scene
