//====================================================================
// deferred_renderer.v - 延迟渲染器
// 第23课：G-Buffer生成与光照pass
//====================================================================
module deferred_renderer #(
    parameter COORD_WIDTH = 16,
    parameter COLOR_WIDTH = 24,
    parameter GBUF_WIDTH  = 80,  // G-Buffer总位宽
    parameter ADDR_WIDTH  = 20,
    parameter FRAC_BITS   = 12
)(
    input  wire                          clk, rst_n,
    // Geometry Pass输入
    input  wire                          geom_valid,
    input  wire [ADDR_WIDTH-1:0]         geom_addr,
    input  wire [COLOR_WIDTH-1:0]        geom_albedo,
    input  wire signed [COORD_WIDTH-1:0] geom_nx, geom_ny, geom_nz,
    input  wire signed [COORD_WIDTH-1:0] geom_depth,
    output reg                           geom_ready,
    // Lighting Pass输入
    input  wire                          light_valid,
    input  wire [ADDR_WIDTH-1:0]         light_addr,
    input  wire signed [COORD_WIDTH-1:0] light_dir_x, light_dir_y, light_dir_z,
    input  wire [COLOR_WIDTH-1:0]        light_color,
    output reg                           light_ready,
    // 最终输出
    output reg                           result_valid,
    output reg  [ADDR_WIDTH-1:0]         result_addr,
    output reg  [COLOR_WIDTH-1:0]        result_color
);
/* verilator lint_off WIDTHEXPAND */
/* verilator lint_off WIDTHTRUNC */
/* verilator lint_off CASEOVERLAP */
/* verilator lint_off CMPCONST */
/* verilator lint_off UNSIGNED */
/* verilator lint_off WIDTHCONCAT */

    // G-Buffer存储(简化版: albedo + normal + depth)
    reg [COLOR_WIDTH-1:0]   gbuf_albedo [0:255];
    reg [COORD_WIDTH-1:0]   gbuf_nx [0:255], gbuf_ny [0:255], gbuf_nz [0:255];
    reg [COORD_WIDTH-1:0]   gbuf_depth [0:255];
    // 光照计算
    reg signed [2*COORD_WIDTH-1:0] dot_nl;
    reg [7:0] diff_factor;
    reg [7:0] alb_r, alb_g, alb_b;
    reg [7:0] lit_r, lit_g, lit_b;
    localparam S_GEOM=3'd0, S_LIGHT_READ=3'd1, S_LIGHT_CALC=3'd2, S_LIGHT_OUT=3'd3;
    reg [2:0] state;
    always @(posedge clk or negedge rst_n) begin
        if (!rst_n) begin state<=S_GEOM; geom_ready<=1; light_ready<=0; result_valid<=0; end
        else begin
            result_valid <= 0;
            case (state)
                S_GEOM: begin
                    geom_ready <= 1; light_ready <= 0;
                    if (geom_valid) begin
                        geom_ready <= 0;
                        gbuf_albedo[geom_addr[7:0]] <= geom_albedo;
                        gbuf_nx[geom_addr[7:0]] <= geom_nx;
                        gbuf_ny[geom_addr[7:0]] <= geom_ny;
                        gbuf_nz[geom_addr[7:0]] <= geom_nz;
                        gbuf_depth[geom_addr[7:0]] <= geom_depth;
                    end
                    light_ready <= 1; // 两个pass并行
                end
                S_LIGHT_READ: begin
                    light_ready <= 1;
                    if (light_valid) begin
                        light_ready <= 0;
                        alb_r <= gbuf_albedo[light_addr[7:0]][23:16];
                        alb_g <= gbuf_albedo[light_addr[7:0]][15:8];
                        alb_b <= gbuf_albedo[light_addr[7:0]][7:0];
                        dot_nl = gbuf_nx[light_addr[7:0]] * light_dir_x +
                                 gbuf_ny[light_addr[7:0]] * light_dir_y +
                                 gbuf_nz[light_addr[7:0]] * light_dir_z;
                        state <= S_LIGHT_CALC;
                    end
                end
                S_LIGHT_CALC: begin
                    diff_factor = (dot_nl > 0) ? ((dot_nl[19:12]>8'd255)?8'd255:dot_nl[19:12]) : 8'd0;
                    lit_r <= (alb_r * diff_factor) >> 8;
                    lit_g <= (alb_g * diff_factor) >> 8;
                    lit_b <= (alb_b * diff_factor) >> 8;
                    result_addr <= light_addr;
                    state <= S_LIGHT_OUT;
                end
                S_LIGHT_OUT: begin
                    result_color <= {lit_r, lit_g, lit_b};
                    result_valid <= 1; state <= S_GEOM;
                end
                default: state <= S_GEOM;
            endcase
        end
    end
endmodule