//go:build gl // 光影包加载:type=shader 内容包替换着色器(渲染.md §9.2–§9.3)。 package render import ( "fmt" "os" "path/filepath" "mc/internal/assets" "github.com/go-gl/gl/v3.3-core/gl" ) // ShaderPack 一个光影包(着色器源码集合)。 type ShaderPack struct { ID string Vert string // chunk.vert 源码 Frag string // chunk.frag 源码 } // LoadShaderPack 扫描内容包管理器,寻找 type=shader 的包并读取着色器。 // 未安装光影包返回 (nil, nil) → 使用系统默认光影(渲染.md §9.1 默认回退)。 func LoadShaderPack(am *assets.Manager) (*ShaderPack, error) { var pack *assets.Pack for _, p := range am.Packs() { if p.Type == assets.PackShader { pack = p break // 优先级已排序,第一个即最高优先级 } } if pack == nil { return nil, nil // 默认光影 } sp := &ShaderPack{ID: pack.ID} for _, ns := range []string{"minecraft", pack.ID} { vertPath := filepath.Join(pack.Root, "assets", ns, "shaders", "chunk.vert") if b, err := os.ReadFile(vertPath); err == nil { sp.Vert = string(b) break } } for _, ns := range []string{"minecraft", pack.ID} { fragPath := filepath.Join(pack.Root, "assets", ns, "shaders", "chunk.frag") if b, err := os.ReadFile(fragPath); err == nil { sp.Frag = string(b) break } } if sp.Vert == "" || sp.Frag == "" { return nil, fmt.Errorf("render.LoadShaderPack: 光影包 %q 缺少 chunk.vert/chunk.frag(拒绝加载,回退默认)", pack.ID) } return sp, nil } // ApplyShaderPack 用光影包重建着色程序(失败回退默认并返回错误,渲染.md §9.3)。 func (r *Renderer) ApplyShaderPack(sp *ShaderPack) error { vertSrc, fragSrc := chunkVertSrc, chunkFragSrc if sp != nil { vertSrc, fragSrc = sp.Vert, sp.Frag } vs, err := compileShader(gl.VERTEX_SHADER, vertSrc) if err != nil { return fmt.Errorf("render.ApplyShaderPack 顶点着色器: %w", err) } defer gl.DeleteShader(vs) fs, err := compileShader(gl.FRAGMENT_SHADER, fragSrc) if err != nil { return fmt.Errorf("render.ApplyShaderPack 片元着色器: %w", err) } defer gl.DeleteShader(fs) prog := gl.CreateProgram() gl.AttachShader(prog, vs) gl.AttachShader(prog, fs) gl.LinkProgram(prog) var ok int32 gl.GetProgramiv(prog, gl.LINK_STATUS, &ok) if ok == 0 { gl.DeleteProgram(prog) return fmt.Errorf("render.ApplyShaderPack: 链接失败(保留默认光影)") } if r.prog != 0 { gl.DeleteProgram(r.prog) } r.prog = prog return nil }