AgentSkillsCN

Engine Rendering

引擎渲染

SKILL.md

Rendering and Materials

This skill guides rendering setup, RenderMesh usage, materials, and shaders for the engine.

Rendering Architecture

The engine uses a rendering pipeline with phases:

  • Shadow casting
  • Geometry rendering
  • Gizmos (debug visualization)
  • Overlay/UI

RenderMesh Component

go
type RenderMeshData struct {
    MeshId         string // ID of mesh to render
    MaterialId     string // ID of material to use
    ShaderId       string // Optional shader override
    IsTransparent  bool   // Render in transparent pass
}

Scene JSON Format

json
{
  "id": 1001,
  "components": {
    "Name": { "Value": "My Object" },
    "RenderMesh": {
      "MeshId": "cube",
      "MaterialId": "red",
      "ShaderId": "",
      "IsTransparent": false
    },
    "Transform": { ... }
  }
}

Available Meshes

Built-in meshes:

  • "cube" - 1x1x1 cube
  • "sphere" - 1 unit diameter sphere
  • "plane" - 10x10 plane (scales with transform)
  • "cylinder" - 1x2 cylinder

Model files (from assets):

  • "model_name.obj:0" - First mesh from OBJ file
  • "model_name.obj:1" - Second mesh from OBJ file

Material System

Built-in Materials

Place materials in assets/materials/ as .mat files or configure in code:

go
// In main.go InitFunc
eng.MaterialRegistry().Add("red", &material.Material{
    Albedo: rl.NewColor(255, 0, 0, 255),
    // ... other properties
})

Material Properties

go
type Material struct {
    Albedo       rl.Color
    Emissive     rl.Color
    Metalness    float32
    Roughness    float32
    Opacity      float32
}

Shader System

Register Shaders

go
eng.InitFunc = func() {
    shader, err := eng.LoadShaderFromFiles("", "shaders/example.fs")
    if err != nil {
        log.Fatal(err)
    }
    eng.ShaderRegistry().Add("my_shader", shader)
}

Use Shader in RenderMesh

json
{
  "RenderMesh": {
    "MeshId": "cube",
    "MaterialId": "default",
    "ShaderId": "my_shader"
  }
}

Transparency

Set IsTransparent: true for transparent materials:

json
{
  "RenderMesh": {
    "MeshId": "sphere",
    "MaterialId": "transparent_green",
    "IsTransparent": true
  }
}

Transparent objects render after opaque objects.

Debug Rendering

Enable debug mode on Transform to see wireframes:

json
{
  "Transform": {
    "Position": { "X": 0, "Y": 0, "Z": 0 },
    "Debug": true,
    "Parent": 0
  }
}

Custom Render in Systems

Implement SystemWithRender for custom rendering:

go
type GizmoSystem struct{}

func (s *GizmoSystem) Render(phase sys.RenderPhase, world donburi.World, scene *engineScene.Scene) {
    if phase != sys.RenderPhaseGizmos {
        return
    }
    
    query := donburi.NewQuery(filter.Contains(
        engineComponent.Transform,
        gameComponent.Waypoint,
    ))
    
    for entry := range query.Iter(world) {
        transform := engineComponent.Transform.Get(entry)
        pos := transform.WorldMatrix.ExtractPosition()
        
        rl.DrawSphereWires(pos.ToRaylib(), 0.5, 8, 8, rl.Green)
    }
}

Render Phases

PhaseUse Case
RenderPhaseShadowCustom shadow casters
RenderPhaseGeometryMain 3D rendering
RenderPhaseGizmosDebug visualization
RenderPhaseOverlay2D text/HUD
RenderPhaseEditorUIImGui (editor only)

Common Patterns

Rendering Multiple Meshes

go
meshIds := []string{"cube", "sphere", "cylinder"}
for i, meshId := range meshIds {
    entity := scene.CreateEntity(fmt.Sprintf("Object %d", i))
    scene.SetRenderMesh(entity, component.RenderMeshData{
        MeshId:     meshId,
        MaterialId: "default",
    })
    // ... set transform
}

Toggle Visibility

go
func (s *VisibilitySystem) Update(world donburi.World, scene *engineScene.Scene, dt float32) {
    query := donburi.NewQuery(filter.Contains(
        engineComponent.Transform,
        gameComponent.Hidden,
    ))
    
    for entry := range query.Iter(world) {
        renderMesh := engineComponent.RenderMesh.Get(entry)
        hidden := gameComponent.Hidden.Get(entry)
        
        // Remove or add RenderMesh component based on hidden state
        if hidden.IsHidden {
            entry.RemoveComponent(engineComponent.RenderMesh)
        } else if !entry.HasComponent(engineComponent.RenderMesh) {
            entry.AddComponent(engineComponent.RenderMesh)
            engineComponent.RenderMesh.SetValue(entry, renderMesh)
        }
    }
}

Assets Organization

code
assets/
├── meshes/           # .obj files
│   └── player.obj
├── materials/        # .mat files
│   └── red.mat
├── shaders/          # .fs / .vs files
│   └── toon.fs
└── textures/         # .png files
    └── diffuse.png

See Also

  • engine-scene: Creating scene files with entities
  • engine-component: Custom components with rendering data
  • engine-system: Systems that modify rendering