//====================================================================
// shadow_mapper.v - 阴影映射器
// 第19课：深度图生成与阴影测试
//====================================================================
module shadow_mapper #(
    parameter COORD_WIDTH = 16,
    parameter COLOR_WIDTH = 24,
    parameter SHADOW_WIDTH = 10,
    parameter FRAC_BITS  = 12
)(
    input  wire                          clk, rst_n,
    // 光源空间坐标
    input  wire                          frag_valid,
    input  wire signed [COORD_WIDTH-1:0] frag_light_x, frag_light_y, frag_light_z,
    input  wire [COLOR_WIDTH-1:0]        frag_color,
    input  wire signed [COORD_WIDTH-1:0] bias,
    output reg                           frag_ready,
    // 阴影图读取接口
    output reg  [SHADOW_WIDTH-1:0]       smap_addr,
    output reg                           smap_read,
    input  wire signed [COORD_WIDTH-1:0] smap_depth,
    input  wire                          smap_valid,
    output reg                           result_valid,
    output reg  [COLOR_WIDTH-1:0]        result_color,
    output reg                           in_shadow
);
/* verilator lint_off WIDTHEXPAND */
/* verilator lint_off WIDTHTRUNC */
/* verilator lint_off CASEOVERLAP */
/* verilator lint_off CMPCONST */
/* verilator lint_off UNSIGNED */
/* verilator lint_off WIDTHCONCAT */

    localparam S_IDLE=3'd0, S_ADDR=3'd1, S_READ=3'd2, S_TEST=3'd3, S_OUT=3'd4;
    reg [2:0] state;
    reg [COLOR_WIDTH-1:0] stored_color;
    always @(posedge clk or negedge rst_n) begin
        if (!rst_n) begin state<=S_IDLE; frag_ready<=1; result_valid<=0; in_shadow<=0; smap_read<=0; end
        else begin
            result_valid <= 0; smap_read <= 0;
            case (state)
                S_IDLE: begin
                    frag_ready <= 1;
                    if (frag_valid) begin
                        frag_ready <= 0;
                        stored_color <= frag_color;
                        // 将光源空间坐标转换为阴影图地址
                        smap_addr <= frag_light_x[COORD_WIDTH-1:COORD_WIDTH-SHADOW_WIDTH];
                        state <= S_ADDR;
                    end
                end
                S_ADDR: begin
                    smap_read <= 1; state <= S_READ;
                end
                S_READ: begin
                    if (smap_valid) state <= S_TEST;
                end
                S_TEST: begin
                    // 阴影测试: 当前深度 > 阴影图深度 + 偏移 → 在阴影中
                    if (frag_light_z > smap_depth + bias)
                        in_shadow <= 1;
                    else
                        in_shadow <= 0;
                    state <= S_OUT;
                end
                S_OUT: begin
                    // 在阴影中时降低亮度
                    if (in_shadow)
                        result_color <= {1'b0, stored_color[23:17], 1'b0, stored_color[15:9], 1'b0, stored_color[7:1]}; // 1/2亮度
                    else
                        result_color <= stored_color;
                    result_valid <= 1; state <= S_IDLE;
                end
                default: state <= S_IDLE;
            endcase
        end
    end
endmodule