feat(渲染压缩): 完善字体三维动作导航及压缩
build.yaml / build (push) Successful in 46s

This commit is contained in:
xiaoqidun committed 2026-10-08 01:06:43 +08:00
1 parent be5901100e
commit c8a163a077
35 files changed
+3045 -373

No files matched your search

+93 -34
View File
@@ -30,13 +30,42 @@ type u3dVertex struct {
// 入参: instance 场景实例, node 模型节点, mesh 网格, pass 绘制轮次, passIndex 轮次索引
// 返回: error 几何、资源或取消错误
func (r *u3dRender) drawMesh(instance u3dInstance, node *U3DNode, mesh *U3DMesh, pass U3DViewPass, passIndex int) error {
count := uint64(len(mesh.Positions)) + uint64(len(mesh.Normals))
if r.mode >= U3DRenderBoundingBox && r.mode <= U3DRenderBoundingBoxOutline {
return r.drawBounds(instance, node, mesh, pass, passIndex)
}
if r.opacity == 0 && len(r.sections) == 0 && r.mode == U3DRenderSolid {
return r.ctx.Err()
}
shaded := r.mode.shaded() && !r.depthOnly
var outline *u3dOutline
if r.mode.silhouette() {
if err := r.reserve(1, 1024); err != nil {
return err
}
outline = &u3dOutline{index: make(map[[2]u3dVector]int)}
defer func() { r.remaining += 1024 + uint64(len(outline.edges))*1024 }()
}
if r.mode == U3DRenderShadedWireframe || r.mode == U3DRenderShadedVertices {
if err := r.reserve(1, 1024); err != nil {
return err
}
r.primitives = make(map[u3dPrimitiveKey]struct{})
defer func() {
r.remaining += 1024 + uint64(len(r.primitives))*512
r.primitives = nil
}()
}
normalCount := 0
if shaded {
normalCount = len(mesh.Normals)
}
count := uint64(len(mesh.Positions)) + uint64(normalCount)
if err := r.reserve(count, 24); err != nil {
return err
}
defer func() { r.remaining += count * 24 }()
positions := make([]u3dVector, len(mesh.Positions))
normals := make([]u3dVector, len(mesh.Normals))
normals := make([]u3dVector, normalCount)
inverse, invertible := instance.world.inverse()
for i, p := range mesh.Positions {
if i%1024 == 0 {
@@ -51,7 +80,7 @@ func (r *u3dRender) drawMesh(instance u3dInstance, node *U3DNode, mesh *U3DMesh,
}
}
}
for i, n := range mesh.Normals {
for i, n := range mesh.Normals[:normalCount] {
if i%1024 == 0 {
if err := r.ctx.Err(); err != nil {
return err
@@ -66,6 +95,9 @@ func (r *u3dRender) drawMesh(instance u3dInstance, node *U3DNode, mesh *U3DMesh,
normals[i] = inverse.normal(u3dVector{float64(n[0]), float64(n[1]), float64(n[2])})
}
}
if err := r.drawLines(instance, node, mesh, positions, normals, pass, passIndex); err != nil {
return err
}
for index, face := range mesh.Faces {
if index%128 == 0 {
if err := r.ctx.Err(); err != nil {
@@ -82,7 +114,7 @@ func (r *u3dRender) drawMesh(instance u3dInstance, node *U3DNode, mesh *U3DMesh,
var world [3]u3dVector
var vertices [3]u3dVertex
for i, corner := range face.Corners {
if uint64(corner.Position) >= uint64(len(positions)) || !mesh.ExcludeNormals && uint64(corner.Normal) >= uint64(len(normals)) || shading.Attributes&1 != 0 && uint64(corner.Diffuse) >= uint64(len(mesh.Diffuse)) || shading.Attributes&2 != 0 && uint64(corner.Specular) >= uint64(len(mesh.Specular)) {
if uint64(corner.Position) >= uint64(len(positions)) || shaded && (!mesh.ExcludeNormals && uint64(corner.Normal) >= uint64(len(normals)) || shading.Attributes&1 != 0 && uint64(corner.Diffuse) >= uint64(len(mesh.Diffuse)) || shading.Attributes&2 != 0 && uint64(corner.Specular) >= uint64(len(mesh.Specular))) {
return fmt.Errorf("invalid U3D render corner index")
}
world[i] = positions[corner.Position]
@@ -94,7 +126,7 @@ func (r *u3dRender) drawMesh(instance u3dInstance, node *U3DNode, mesh *U3DMesh,
}
}
var faceNormal u3dVector
if mesh.ExcludeNormals || !invertible {
if shaded && (mesh.ExcludeNormals || !invertible) {
faceNormal = u3dTriangleNormal(world)
}
p0, p1, p2 := vertices[0].point, vertices[1].point, vertices[2].point
@@ -107,30 +139,59 @@ func (r *u3dRender) drawMesh(instance u3dInstance, node *U3DNode, mesh *U3DMesh,
}
front := facing < 0
visibility := instance.modelVisibility(node)
if facing == 0 || front && visibility&1 == 0 || !front && visibility&2 == 0 {
surfaceVisible := facing != 0 && (front && visibility&1 != 0 || !front && visibility&2 != 0)
if r.mode == U3DRenderHiddenWireframe && !front || (r.mode == U3DRenderSolid || r.mode == U3DRenderSolidWireframe || r.depthOnly) && (facing == 0 || front && visibility&1 == 0 || !front && visibility&2 == 0) {
continue
}
shaderNames := []string{""}
if uint64(face.Shading) < uint64(len(node.Shaders)) {
shaderNames = node.Shaders[face.Shading]
}
if outline != nil {
if err := r.outlineFace(outline, world, vertices, front, surfaceVisible, shaderNames, passIndex); err != nil {
return err
}
if !surfaceVisible {
continue
}
}
for shaderIndex, name := range shaderNames {
if shaderIndex%128 == 0 {
if err := r.ctx.Err(); err != nil {
return err
}
}
style, err := r.style(name)
if err != nil {
return err
style := u3dRenderStyle{shader: U3DShader{Blend: 0x606, RenderPass: math.MaxUint32}}
var err error
if shaded {
style, err = r.style(name)
if err != nil {
return err
}
} else if index, ok := r.shaders[name]; ok {
style.shader.RenderPass = r.model.Shaders[index].RenderPass
}
if style.shader.RenderPass&(1<<passIndex) == 0 {
continue
}
if instance.opacity >= 0 {
if instance.opacity >= 0 || r.opacity >= 0 {
style.shader.Blend = 0x606
}
for i, corner := range face.Corners {
if !shaded {
vertices[i].color = [4]float64{r.auxiliaryColor[0], r.auxiliaryColor[1], r.auxiliaryColor[2], 1}
if r.mode == U3DRenderIllustration {
alpha := 1.0
if instance.opacity >= 0 {
alpha = instance.opacity
}
if r.opacity >= 0 {
alpha *= r.opacity
}
vertices[i].color = [4]float64{r.faceColor[0], r.faceColor[1], r.faceColor[2], alpha}
}
continue
}
normal := faceNormal
if !mesh.ExcludeNormals && invertible {
normal = normals[corner.Normal]
@@ -154,13 +215,19 @@ func (r *u3dRender) drawMesh(instance u3dInstance, node *U3DNode, mesh *U3DMesh,
if instance.opacity >= 0 {
vertices[i].color[3] = instance.opacity
}
if r.opacity >= 0 {
vertices[i].color[3] *= r.opacity
}
}
r.order++
if err := r.sectionTriangle(vertices, style.shader, pass); err != nil {
if err := r.modeTriangle(vertices, style.shader, pass); err != nil {
return err
}
}
}
if outline != nil {
return r.drawOutline(outline, pass)
}
return nil
}
@@ -168,6 +235,9 @@ func (r *u3dRender) drawMesh(instance u3dInstance, node *U3DNode, mesh *U3DMesh,
// 入参: triangle 三角面, shader 着色器, pass 绘制轮次
// 返回: error 数值、资源或取消错误
func (r *u3dRender) clipTriangle(triangle [3]u3dVertex, shader U3DShader, pass U3DViewPass) error {
if shader.Blend == 0x606 && triangle[0].color[3] == 0 && triangle[1].color[3] == 0 && triangle[2].color[3] == 0 {
return r.ctx.Err()
}
var storage [2][12]u3dVertex
copy(storage[0][:], triangle[:])
size, current := 3, 0
@@ -306,39 +376,28 @@ func (r *u3dRender) rasterTriangle(triangle [3]u3dVertex, shader U3DShader, pass
if depth > r.frame[pixel].depth {
continue
}
if r.depthOnly {
r.frame[pixel].depth = depth
continue
}
var color [4]float64
for c := range color {
color[c] = triangle[0].color[c] + w1*(triangle[1].color[c]-triangle[0].color[c]) + w2*(triangle[2].color[c]-triangle[0].color[c])
if !finite(color[c]) {
return fmt.Errorf("invalid U3D interpolated color")
}
}
color[3] = min(1, max(0, color[3]))
if shader.Attributes&2 != 0 && !u3dAlphaTest(shader.AlphaFunction, color[3], float64(shader.AlphaReference)) {
continue
}
position := u3dVector{}
if pass.Attributes&1 != 0 {
position := u3dVector{(px - r.viewport[0] - r.viewport[2]/2 - r.camera.ShiftX) / r.camera.ScaleX, (r.viewport[1] + r.viewport[3]/2 + r.camera.ShiftY - py) / r.camera.ScaleY, depth}
position = u3dVector{(px - r.viewport[0] - r.viewport[2]/2 - r.camera.ShiftX) / r.camera.ScaleX, (r.viewport[1] + r.viewport[3]/2 + r.camera.ShiftY - py) / r.camera.ScaleY, depth}
if r.camera.Perspective {
position[0] *= depth
position[1] *= depth
}
distance := math.Hypot(math.Hypot(position[0], position[1]), position[2])
factor := (float64(pass.FogFar) - distance) / (float64(pass.FogFar) - float64(pass.FogNear))
if pass.FogMode != 0 {
amount := distance * math.Log(100) / float64(pass.FogFar)
if pass.FogMode == 2 {
amount *= amount
}
factor = math.Exp(-amount)
}
factor = min(1, max(0, factor))
for c := range 3 {
color[c] = color[c]*factor + float64(pass.FogColor[c])*(1-factor)
}
}
for c := range 3 {
color[c] = min(1, max(0, color[c]))
visible, err := u3dFragmentColor(&color, position, &shader, &pass)
if err != nil {
return err
}
if !visible {
continue
}
if err := r.fragment(pixel, depth, color, shader.Blend); err != nil {
return err