Loading
Personal Project
Eurekiel: Chess3D

Chess3D is a 3D chess sandbox built in C++ and DirectX 11 on the custom Eurekiel engine. The project features standard chess rule enforcement, TCP multiplayer, Blinn-Phong lighting with normal maps, an OBJ loader with automatic tangent/bitangent generation, and an XML-driven configuration layer for board setups and piece definitions.

Core systems

Gameplay and chess rules

The rule engine enforces movement patterns for standard chess pieces. Each ChessPieceDefinition is parsed from XML with its glyph, movement sliding flags, and attack rules. The ChessMatch controller validates every move against the board state, interpolates piece movement across squares using easing curves, and alternates turn control.

0:00
/0:00
Full chess rule enforcement with piece movement validation, turn alternation, and capture logic

Selecting a piece highlights valid destination squares in real time. The highlight pass evaluates the piece’s move set, discards tiles occupied by friendly pieces, and draws semi-transparent overlays on legal target squares.

Legal move highlighting, where valid destination tiles are computed and displayed on piece selection

3D raycasting and selection

Piece selection casts a 3D ray from the camera through the mouse cursor into world space. The ray checks collision cylinders defined in ChessPieceDefinition.xml (radius and height), selecting the closest hit piece or board tile.

0:00
/0:00
3D raycast-based piece selection where the ray from camera through cursor intersects piece collision volumes

Blinn-Phong rendering pipeline

The renderer uses Blinn-Phong shading with tangent-space normal mapping. Each mesh samples diffuse, normal, and packed specular-gloss-emissive (SGE) maps, computing lighting in world space with per-vertex TBN matrices.

Blinn-Phong Rendering
Blinn-Phong lit scene with normal-mapped chess pieces and board, showing specular highlights and ambient lighting

The material system assigns shaders and textures per object through MeshComponent. Packing specular intensity, gloss, and emissive channels into a single RGB texture reduces descriptor bindings while preserving surface response.

Blinn-Phong Material Maps
Material map breakdown showing diffuse color, normal map, and packed specular/gloss/emissive channels used by the Blinn-Phong shader

Shader debug visualization

The engine exposes 16 shader inspection views through the ShaderDebugType enum, allowing direct visualization of intermediate shader outputs including diffuse color, UV coordinates, model-space normals, TBN tangent vectors, and world-space lighting terms:

enum class ShaderDebugType
{
    Lit = 0,           DiffuseColor,       SurfaceColor,
    UVCoords,          SurfaceTangentModelSpace,  SurfaceBitangentModelSpace,
    SurfaceNormalModelSpace,  NormalColor,  PixelNormalTBNSpace,
    PixelNormalWorldSpace,    Lighting,     SurfaceTangentWorldSpace,
    SurfaceBitangentWorldSpace, SurfaceNormalWorldSpace,
    ModelIBasisWorld,  ModelJBasisWorld,    ModelKBasisWorld
};
0:00
/0:00
Cycling through shader debug modes showing diffuse color, surface normals, TBN vectors, pixel normals in world space, and more

These debug views helped diagnose normal map seam orientation, verify TBN orthogonality, and inspect light response curves during engine development.

OBJ model loader with TBN correction

The OBJ loader converts meshes into the engine’s Vertex_PCUTBN vertex layout. If an imported model lacks tangent or bitangent attributes, the loader reconstructs them from face normals and UV gradients using cross products, ensuring imported models can be used with normal maps without offline preparation.

OBJ Loaded Model
An OBJ model loaded into the engine with automatically computed TBN vectors, ready for Blinn-Phong shading
0:00
/0:00
OBJ model loader demonstrating automatic tangent/bitangent correction where missing TBN data is deduced from normals and UVs

Multiplayer networking

NetworkDispatcher handles TCP-based communication with framing options for null termination, raw byte streams, and length prefixes. Packet fragmentation is reassembled across frame boundaries, with support for up to 20 client connections.

sequenceDiagram
    participant CA as Client A
    participant S as Server
    participant CB as Client B

    CA->>S: Connect
    CB->>S: Connect
    CA->>S: MovePiece A2 A4
    S->>S: ExecuteCommand with remote flag
    S->>CB: Broadcast state update
    CB->>CB: ExecuteCommand with remote flag

Network commands route through the developer console. The dispatcher parses incoming messages, appends remote=true, and forwards them into the command processor, sharing the same execution path between local and networked games.

Data-driven configuration

Game rules, board dimensions, and mesh assignments live in XML files under Run/Data/:

ChessPieceDefinition.xml configures piece properties, slide movements, collision bounds, and component assignments:

<ChessPieceDefinition name="Knight" glyph="N" slide="false">
    <Collision radius="0.05" height="0.6"
               collidesWithWorld="true" collidesWithActors="false"/>
    <Components>
        <Component type="MeshComponent" bakeModel="Knight" renderLit="true"
                   shader="Data/Shaders/Diffuse"
                   texture="Data\Images\FunkyBricks_d.png"
                   normal="Data\Images\FunkyBricks_n.png"
                   specGlossEmit="Data\Images\FunkyBricks_sge.png"/>
    </Components>
</ChessPieceDefinition>

ChessMatchConfig.xml sets board texture paths, faction colors, camera angles, and initial board layout using chess coordinates:

<ChessBoard texture="Data\Images\Bricks_d.png" normal="Data\Images\Bricks_n.png"
            specGlossEmit="Data\Images\Bricks_sge.png" shader="Data/Shaders/Diffuse">
    <Factions>
        <Faction display="Player 0" id="0" color="161,40,35"
                 viewPosition="4,-1.5,4" viewOrientation="90,45,0"/>
        <Faction display="Player 1" id="1" color="85,110,28"
                 viewPosition="4,9.5,4" viewOrientation="-90,45,0"/>
    </Factions>
    <ChessPieces>
        <ChessPiece name="King" position="E1" faction="0"/>
        <!-- ... full board layout ... -->
    </ChessPieces>
</ChessBoard>

GameConfig.xml manages display resolutions, camera controls, and initial debug flags.

System architecture

graph TD
    subgraph Engine["Eurekiel Engine Core"]
        RS[RenderSubsystem]
        NS[NetworkSubsystem]
        WS[WidgetSubsystem]
        LS[LoggerSubsystem]
        IS[InputSystem]
        AS[AudioSystem]
    end

    subgraph Rendering["Rendering Pipeline"]
        BP[BlinnPhong Shader]
        PP[Post-Processing Chain]
        BL[EffectBloom]
        DM[Debug Modes]
        PP --> BL
    end

    subgraph GameLogic["Chess Game Logic"]
        CM[ChessMatch]
        CB[ChessBoard]
        CP[ChessPiece]
        CM --> CB
        CM --> CP
    end

    subgraph DataDriven["Data-Driven Layer"]
        PD[ChessPieceDefinition.xml]
        MC[ChessMatchConfig.xml]
        GC[GameConfig.xml]
    end

    subgraph ActorSystem["Actor-Component System"]
        AC[Actor]
        MC2[MeshComponent]
        CC[CollisionComponent]
        AC --> MC2
        AC --> CC
    end

    RS --> BP
    RS --> PP
    BP --> DM
    DataDriven --> GameLogic
    GameLogic --> ActorSystem
    ActorSystem --> RS
    NS --> CM
    IS --> CM

Design decisions

Data-driven game definitions

Parameters like piece definitions, board layouts, team colors, camera positions, and server network settings are defined in XML. Tuning piece attributes or swapping textures requires editing text files rather than recompiling.

Shared console command pipeline

Local input and remote multiplayer packets both execute through the developer console pipeline via ExecuteCommand(), distinguishing source origin via a remote=true flag. This avoids maintaining separate synchronization paths.

Integrated shader inspection

The 16 debug render modes were implemented alongside the lighting pass, allowing direct visualization of raw normals, tangent vectors, and UVs to verify model imports and lighting calculations.

Tangent and bitangent derivation

The OBJ loader checks for missing tangent space vectors during parsing and computes them from surface normals and UV coordinates, preventing broken shading on models exported without explicit TBN data.

Component composition

The Actor-Component system uses generic methods (AddComponent<T>, GetComponent<T>) to assemble piece behaviors and visual components, avoiding deep inheritance structures.