主题
渲染管线
Behemiron 提供统一的客户端渲染管线,支持渲染命令、渲染通道和并行渲染。
概念导图
渲染命令
RenderCommand 接口
所有渲染操作通过命令模式封装:
kotlin
interface RenderCommand {
/** 渲染类型(用于分组和批处理) */
val renderType: RenderType?
/** 排序键(透明物体排序,值越大越远) */
val sortKey: Float
/** 是否透明 */
val isTransparent: Boolean
/** 执行渲染 */
fun execute(context: RenderContext)
}RenderContext
渲染上下文包含当前帧的渲染信息:
kotlin
data class RenderContext(
val poseStack: PoseStack, // 变换矩阵栈
val bufferSource: MultiBufferSource, // 缓冲区源
val partialTick: Float, // 插值因子(0-1)
val cameraX: Double, // 相机位置
val cameraY: Double,
val cameraZ: Double,
val frameTimeMs: Long, // 帧时间(毫秒)
val gameTime: Long, // 游戏时间(ticks)
val graphics: GuiGraphics?, // GUI 渲染上下文
val camera: Camera? // 相机实例
)使用示例
kotlin
class MyRenderCommand(
private val x: Double,
private val y: Double,
private val z: Double
) : RenderCommand {
override val renderType: RenderType? = null
override val sortKey: Float = 0f
override val isTransparent: Boolean = false
override fun execute(context: RenderContext) {
val pose = context.poseStack
pose.pushPose()
// 相对相机位置
pose.translate(
x - context.cameraX,
y - context.cameraY,
z - context.cameraZ
)
// 渲染逻辑...
pose.popPose()
}
}渲染通道
RenderPass
渲染通道表示管线中的一个阶段:
kotlin
val opaquePass = RenderPass(
name = "opaque",
priority = 0, // 优先级(越小越先执行)
enabled = true
) { context, commands ->
// 自定义执行逻辑
for (command in commands) {
command.execute(context)
}
}
// 收集命令
opaquePass.collect(myCommand)
// 准备(排序等)
opaquePass.prepare()
// 执行
opaquePass.execute(renderContext)
// 清空
opaquePass.clear()TransparentRenderPass
专门处理透明物体的通道,自动按距离排序:
kotlin
val transparentPass = TransparentRenderPass(
name = "transparent",
priority = 100
)
// 透明命令会自动从远到近排序
transparentPass.collect(transparentCommand)
transparentPass.prepare() // 执行排序
transparentPass.execute(context)TypedRenderPass
类型化通道接口,用于只处理特定类型命令:
kotlin
class MyTypedPass : RenderPass("my_pass"), TypedRenderPass {
override fun canHandle(command: RenderCommand): Boolean {
return command is MySpecialCommand
}
}通道统计
kotlin
val stats = pass.getStats()
println("通道: ${stats.name}")
println("总命令数: ${stats.totalCommands}")
println("分组命令: ${stats.groupedCommands}")
println("RenderType 数: ${stats.renderTypeCount}")并行渲染
IRenderable 接口
支持并行顶点生成的渲染对象:
kotlin
interface IRenderable {
/**
* 渲染到顶点缓冲区
*
* 注意:此方法可能在工作线程调用
* - 不要修改 OpenGL 状态
* - 不要访问非线程安全的共享资源
*/
fun renderToBuffer(buffer: VertexConsumer, camera: Camera, partialTick: Float)
/** 是否已移除 */
val isRemoved: Boolean
/** 到相机的距离平方(用于排序) */
fun getDistanceSq(camX: Double, camY: Double, camZ: Double): Double
}ParallelRenderType
并行渲染类型,定义渲染生命周期:
kotlin
abstract class ParallelRenderType {
/** 是否启用并行渲染 */
open fun isParallel(): Boolean = false
/** 排序模式 */
open fun getSortMode(): SortMode = SortMode.NONE
/** 准备渲染状态(主线程) */
open fun prepareState() {}
/** 开始缓冲区(可能在工作线程) */
open fun beginBuffer(buffer: BufferBuilder) {
buffer.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.PARTICLE)
}
/** 结束缓冲区并上传(主线程) */
open fun endBuffer(buffer: BufferBuilder) {
BufferUploader.drawWithShader(buffer.end())
}
/** 释放渲染状态(主线程) */
open fun releaseState() {}
}SortMode
kotlin
enum class SortMode {
NONE, // 不排序
BACK_TO_FRONT // 从远到近(透明物体)
}ParallelExecutor
并行渲染执行器,使用 ForkJoinPool 并行生成顶点:
kotlin
val executor = ParallelExecutor.getInstance()
// 执行并行渲染
executor.execute(
renderables = particles, // IRenderable 列表
config = myRenderConfig, // IRenderConfig 实现
camera = camera,
partialTick = partialTick,
defaultBuilder = bufferBuilder
)
// 批量执行多个渲染配置
executor.executeBatch(
batches = listOf(
particles to particleConfig,
trails to trailConfig
),
camera = camera,
partialTick = partialTick,
defaultBuilder = bufferBuilder
)
// 获取并行度
val threads = executor.getParallelism()并行阈值
当 IRenderable 数量 >= 64 且 IRenderConfig.isParallel() 返回 true 时,才会启用并行渲染。否则使用串行渲染。
着色器注册表
ShaderRegistry
统一的着色器管理:
kotlin
// 获取着色器
val shader = ShaderRegistry.get("particle", "my_plugin")
// 获取失败时返回默认着色器
val shader = ShaderRegistry.getOrDefault("round_box", "my_plugin")内置着色器
UI:particle、fastBlit、spriteBlit、roundBox、progressRoundBox、frameRoundBox、roundLine、sdfRect、round、panelBg
视频:videoNV12、videoYUV420P
特效:hdrParticle、spriteHdrParticle、brightPass、downSampling、upSampling、bloomFinalScatterPass
外部着色器
从 Behemiron/photon/shader/ 目录加载:
Behemiron/
└── photon/
└── shader/
└── my_shader.jsonJSON 格式(Minecraft 标准):
json
{
"blend": {
"func": "add",
"srcrgb": "srcalpha",
"dstrgb": "1-srcalpha"
},
"vertex": "my_shader",
"fragment": "my_shader",
"attributes": ["Position", "UV0", "Color"],
"samplers": [
{ "name": "Sampler0" }
],
"uniforms": [
{ "name": "ModelViewMat", "type": "matrix4x4", "count": 16 },
{ "name": "ProjMat", "type": "matrix4x4", "count": 16 }
]
}缓存管理
kotlin
// 清理指定所有者的缓存
ShaderRegistry.clearExternalCache("my_plugin")
// 清理所有缓存
ShaderRegistry.clearExternalCache(null)
// 获取缓存数量
val count = ShaderRegistry.getExternalCachedCount("my_plugin")状态检查
kotlin
// 检查 UI 着色器是否就绪
if (ShaderRegistry.isUILoaded()) {
// UI 渲染可用
}
// 检查 Bloom 着色器是否就绪
if (ShaderRegistry.isBloomShadersReady()) {
// Bloom 特效可用
}