Files
aego/render/shader/abi.go
T
sanspie 5eb1832907
ci-platforms / darwin amd64 smoke (push) Skipped
ci / build (amd64, linux, ubuntu-24.04) (push) Failing after 15m28s
ci / release (push) Skipped
ci-platforms / windows amd64 smoke (push) Skipped
ci-platforms / darwin arm64 smoke (push) Skipped
ci / checks (push) Successful in 7m47s
Complete Stage 12 for v0.12.0
2026-11-05 11:46:53 +03:00

255 lines
4.7 KiB
Go

package shader
import (
"encoding/binary"
"math"
)
const (
ABI = 1
SlotFrame = 0
SlotView = 1
SlotMaterial = 2
SlotDraw = 3
SlotLighting = 4
SlotSurface = 5
TexMain = 0
TexNormal = 1
TexUser = 2
TexShadow = 8
TexCookie = 9
TexEmission = 10
LaneSlot = 1
LaneLocation = 4
LaneStride = 64
TrimSlot = 2
TrimLocation = 8
TrimStride = 16
AuxSlot = 3
AuxStride = 80
AffineLocation = 9
NormalUVLocation = 10
NormalLocalLocation = 11
EmissionUVLocation = 12
EmissionLocalLocation = 13
MaxUserTextures = 6
MaxParams = 32
MaxNameLen = 32
MaxKeywords = 8
MaxVariants = 32
MaxLanes = 4
MaxIncludeDepth = 8
MaxIncludeFiles = 128
MaxExpandedBytes = 1 << 20
MaxInstanceParams = 8
MaxArtifactBytes = 64 << 20
FrameSize = 16
ViewSize = 112
)
type Domain uint8
const (
DomainSprite Domain = iota
DomainMesh2D
DomainPostFX
)
var domainNames = [...]string{"sprite", "mesh2d", "postfx"}
func (d Domain) String() string {
if int(d) < len(domainNames) {
return domainNames[d]
}
return "unknown"
}
func ParseDomain(s string) (Domain, bool) {
for i, n := range domainNames {
if n == s {
return Domain(i), true
}
}
return 0, false
}
type Blend uint8
const (
BlendPremultiplied Blend = iota
BlendOpaque
BlendAdditive
)
var blendNames = [...]string{"premultiplied", "opaque", "additive"}
func (b Blend) String() string {
if int(b) < len(blendNames) {
return blendNames[b]
}
return "unknown"
}
func ParseBlend(s string) (Blend, bool) {
for i, n := range blendNames {
if n == s {
return Blend(i), true
}
}
return 0, false
}
type Kind uint8
const (
KindFloat Kind = iota
KindInt
KindBool
KindVec2
KindVec3
KindVec4
KindTexture
)
var kindNames = [...]string{"float", "int", "bool", "vec2", "vec3", "vec4", "sampler2D"}
func (k Kind) GLSL() string {
if int(k) < len(kindNames) {
return kindNames[k]
}
return "float"
}
func ParseKind(s string) (Kind, bool) {
for i, n := range kindNames {
if n == s {
return Kind(i), true
}
}
return 0, false
}
func (k Kind) Lanes() int {
switch k {
case KindVec2:
return 2
case KindVec3:
return 3
case KindVec4:
return 4
case KindTexture:
return 0
}
return 1
}
func (k Kind) align() int {
switch k {
case KindVec2:
return 8
case KindVec3, KindVec4:
return 16
}
return 4
}
func Std140(kinds []Kind, offsets []int) int {
off := 0
for i, k := range kinds {
a := k.align()
off = (off + a - 1) &^ (a - 1)
offsets[i] = off
off += 4 * k.Lanes()
}
return (off + 15) &^ 15
}
type Param struct {
Name string
Kind Kind
Default [4]float32
// IntDefault is the exact signed 32-bit default; Default is for floating-point values.
IntDefault int32
Former []string
Min float32
Max float32
HasRange bool
Color bool
Hidden bool
Instance bool
// Normal reserves the engine normal binding while preserving all six user samplers.
Normal bool
// Emission reserves the surface emission binding without reducing user textures.
Emission bool
Doc string
Display string
Unit string
Enum []string
Offset int
Lane int
Comp int
Slot int
File int
Line int
}
type Loc struct {
File int32
Line int32
}
const FrameBlock = `layout(std140) uniform ub0 {
vec4 aego_frame_data;
};
#define aego_time aego_frame_data.x
#define aego_delta aego_frame_data.y
#define aego_unscaled aego_frame_data.z
#define aego_frame_index aego_frame_data.w`
const ViewBlock = `layout(std140) uniform ub1 {
mat4 aego_view_proj;
vec4 aego_viewport;
vec4 aego_view_params;
vec4 aego_camera;
};
#define aego_pixel_scale aego_view_params.x
#define aego_pixels_per_unit aego_view_params.y
#define aego_zoom aego_view_params.z
#define aego_clip_to_pixel_y aego_view_params.w
#define aego_camera_pos aego_camera.xyz`
func put(b []byte, v float32) {
binary.LittleEndian.PutUint32(b, math.Float32bits(v))
}
func PutFrame(dst []byte, time, delta, unscaled float32, frame uint64) {
put(dst[0:], time)
put(dst[4:], delta)
put(dst[8:], unscaled)
put(dst[12:], float32(frame))
}
func PutView(dst []byte, viewProj *[16]float32, viewport [4]float32, pixelScale, pixelsPerUnit, zoom float32, camera [3]float32) {
for i, v := range viewProj {
put(dst[4*i:], v)
}
for i, v := range viewport {
put(dst[64+4*i:], v)
}
put(dst[80:], pixelScale)
put(dst[84:], pixelsPerUnit)
put(dst[88:], zoom)
// Direct callers retain the offscreen (+Y) convention. The renderer writes
// -1 for a normal top-left window viewport, +1 for its flipped offscreen view.
put(dst[92:], 1)
for i, v := range camera {
put(dst[96+4*i:], v)
}
put(dst[108:], 0)
}