引擎开发者/研究员知识体系技术介绍
1. 物理引擎实现 - 从零构建
约束求解器(Constraint Solver)
// 基于位置的动力学(Position Based Dynamics)
public class PBDSolver {
public struct Particle {
public Vector3 position;
public Vector3 prevPosition;
public Vector3 velocity;
public float invMass; // 1/质量,0表示固定
public void Integrate(float dt, Vector3 gravity) {
if (invMass == 0) return;
velocity += gravity * dt;
prevPosition = position;
position += velocity * dt;
}
}
public struct DistanceConstraint {
public int particleA;
public int particleB;
public float restLength;
public float stiffness;
// Gauss-Seidel求解器
public void Solve(Particle[] particles) {
Vector3 pa = particles[particleA].position;
Vector3 pb = particles[particleB].position;
Vector3 delta = pb - pa;
float currentLength = delta.magnitude;
if (currentLength < 0.0001f) return;
// 计算修正量
float diff = (currentLength - restLength) / currentLength;
Vector3 correction = delta * diff * stiffness;
float wa = particles[particleA].invMass;
float wb = particles[particleB].invMass;
float totalInvMass = wa + wb;
if (totalInvMass < 0.0001f) return;
// 应用修正
particles[particleA].position += correction * (wa / totalInvMass);
particles[particleB].position -= correction * (wb / totalInvMass);
}
}
private Particle[] particles;
private DistanceConstraint[] constraints;
private const int SOLVER_ITERATIONS = 10;
public void Step(float dt, Vector3 gravity) {
// 1. 预测位置(显式欧拉)
for (int i = 0; i < particles.Length; i++) {
particles[i].Integrate(dt, gravity);
}
// 2. 生成碰撞约束
GenerateCollisionConstraints();
// 3. 迭代求解约束
for (int iter = 0; iter < SOLVER_ITERATIONS; iter++) {
foreach (var constraint in constraints) {
constraint.Solve(particles);
}
}
// 4. 更新速度
for (int i = 0; i < particles.Length; i++) {
if (particles[i].invMass > 0) {
particles[i].velocity = (particles[i].position - particles[i].prevPosition) / dt;
}
}
// 5. 速度阻尼
for (int i = 0; i < particles.Length; i++) {
particles[i].velocity *= 0.99f;
}
}
void GenerateCollisionConstraints() {
// 宽相检测 + 窄相检测
// BVH/Octree等空间划分
}
}
// 刚体动力学 - 冲量求解
public class RigidBodySolver {
public struct RigidBody {
public Vector3 position;
public Quaternion rotation;
public Vector3 velocity;
public Vector3 angularVelocity;
public float mass;
public Matrix4x4 inertiaTensor; // 惯性张量
public Matrix4x4 inverseInertiaTensor;
// 世界空间的逆惯性张量
public Matrix4x4 GetWorldInverseInertiaTensor() {
Matrix4x4 R = Matrix4x4.Rotate(rotation);
return R * inverseInertiaTensor * R.transpose;
}
}
public struct Contact {
public int bodyA;
public int bodyB;
public Vector3 point;
public Vector3 normal;
public float penetration;
}
// 序列冲量求解器(Sequential Impulse)
public void SolveContact(RigidBody[] bodies, Contact contact, float dt) {
RigidBody a = bodies[contact.bodyA];
RigidBody b = bodies[contact.bodyB];
Vector3 ra = contact.point - a.position;
Vector3 rb = contact.point - b.position;
// 相对速度
Vector3 va = a.velocity + Vector3.Cross(a.angularVelocity, ra);
Vector3 vb = b.velocity + Vector3.Cross(b.angularVelocity, rb);
Vector3 relativeVel = va - vb;
float normalVel = Vector3.Dot(relativeVel, contact.normal);
// 如果物体在分离,不处理
if (normalVel > 0) return;
// 计算冲量
float e = 0.5f; // 恢复系数(弹性)
Matrix4x4 invInertiaA = a.GetWorldInverseInertiaTensor();
Matrix4x4 invInertiaB = b.GetWorldInverseInertiaTensor();
Vector3 raXn = Vector3.Cross(ra, contact.normal);
Vector3 rbXn = Vector3.Cross(rb, contact.normal);
float invMassSum =
(1f / a.mass) + (1f / b.mass) +
Vector3.Dot(invInertiaA.MultiplyVector(raXn), raXn) +
Vector3.Dot(invInertiaB.MultiplyVector(rbXn), rbXn);
float j = -(1 + e) * normalVel / invMassSum;
Vector3 impulse = contact.normal * j;
// 应用冲量
a.velocity += impulse / a.mass;
a.angularVelocity += invInertiaA.MultiplyVector(Vector3.Cross(ra, impulse));
b.velocity -= impulse / b.mass;
b.angularVelocity -= invInertiaB.MultiplyVector(Vector3.Cross(rb, impulse));
// 位置修正(Baumgarte stabilization)
const float baumgarte = 0.2f;
const float slop = 0.01f;
float correction = Mathf.Max(contact.penetration - slop, 0f) * baumgarte / dt;
Vector3 correctionImpulse = contact.normal * correction / invMassSum;
a.position += correctionImpulse / a.mass;
b.position -= correctionImpulse / b.mass;
bodies[contact.bodyA] = a;
bodies[contact.bodyB] = b;
}
}
宽相碰撞检测 - BVH
// 层次包围盒(Bounding Volume Hierarchy)
public class BVHTree {
public class Node {
public Bounds bounds;
public Node left;
public Node right;
public int objectIndex; // -1表示内部节点
public bool IsLeaf => left == null && right == null;
}
private Node root;
// SAH(Surface Area Heuristic)构建
public Node Build(Bounds[] bounds, int[] indices, int start, int end) {
Node node = new Node();
// 计算包围盒
node.bounds = bounds[indices[start]];
for (int i = start + 1; i < end; i++) {
node.bounds.Encapsulate(bounds[indices[i]]);
}
int count = end - start;
// 叶子节点
if (count == 1) {
node.objectIndex = indices[start];
return node;
}
// 找最佳分割
int bestAxis = -1;
int bestIndex = -1;
float bestCost = float.MaxValue;
for (int axis = 0; axis < 3; axis++) {
// 按轴排序
System.Array.Sort(indices, start, count, new AxisComparer(bounds, axis));
// 尝试每个分割点
for (int i = start + 1; i < end; i++) {
Bounds leftBox = bounds[indices[start]];
for (int j = start + 1; j < i; j++) {
leftBox.Encapsulate(bounds[indices[j]]);
}
Bounds rightBox = bounds[indices[i]];
for (int j = i + 1; j < end; j++) {
rightBox.Encapsulate(bounds[indices[j]]);
}
// SAH代价函数
int leftCount = i - start;
int rightCount = end - i;
float cost = leftBox.size.magnitude * leftCount +
rightBox.size.magnitude * rightCount;
if (cost < bestCost) {
bestCost = cost;
bestAxis = axis;
bestIndex = i;
}
}
}
// 无法分割,创建叶子
if (bestAxis == -1) {
node.objectIndex = indices[start];
return node;
}
// 按最佳轴重新排序
System.Array.Sort(indices, start, count, new AxisComparer(bounds, bestAxis));
// 递归构建子树
node.left = Build(bounds, indices, start, bestIndex);
node.right = Build(bounds, indices, bestIndex, end);
return node;
}
// 查询相交
public void Query(Bounds queryBounds, List<int> results) {
QueryRecursive(root, queryBounds, results);
}
void QueryRecursive(Node node, Bounds queryBounds, List<int> results) {
if (node == null) return;
if (!node.bounds.Intersects(queryBounds)) return;
if (node.IsLeaf) {
results.Add(node.objectIndex);
return;
}
QueryRecursive(node.left, queryBounds, results);
QueryRecursive(node.right, queryBounds, results);
}
class AxisComparer : IComparer<int> {
private Bounds[] bounds;
private int axis;
public AxisComparer(Bounds[] bounds, int axis) {
this.bounds = bounds;
this.axis = axis;
}
public int Compare(int a, int b) {
float centerA = bounds[a].center[axis];
float centerB = bounds[b].center[axis];
return centerA.CompareTo(centerB);
}
}
}
2. 渲染器架构 - 延迟渲染
// 完整的延迟渲染管线
public class DeferredRenderer {
// G-Buffer布局
// RT0: Albedo (RGB) + Metallic (A)
// RT1: Normal (RGB) + Roughness (A)
// RT2: Emission (RGB) + AO (A)
// RT3: World Position (RGB) + Depth (A)
private RenderTexture[] gBuffer = new RenderTexture[4];
private RenderTexture lightingBuffer;
private CommandBuffer commandBuffer;
public void Setup(int width, int height) {
// 创建G-Buffer
gBuffer[0] = CreateRT(width, height, RenderTextureFormat.ARGB32); // Albedo
gBuffer[1] = CreateRT(width, height, RenderTextureFormat.ARGB2101010); // Normal
gBuffer[2] = CreateRT(width, height, RenderTextureFormat.ARGBHalf); // Emission
gBuffer[3] = CreateRT(width, height, RenderTextureFormat.ARGBFloat); // Position
lightingBuffer = CreateRT(width, height, RenderTextureFormat.ARGBHalf);
commandBuffer = new CommandBuffer { name = "Deferred Rendering" };
}
public void Render(Camera camera, ScriptableRenderContext context) {
commandBuffer.Clear();
// === Pass 1: Geometry Pass ===
// 渲染到G-Buffer
commandBuffer.SetRenderTarget(gBuffer, gBuffer[3].depthBuffer);
commandBuffer.ClearRenderTarget(true, true, Color.black);
// 绘制所有几何体
var cullingResults = context.Cull(ref camera.cullingParameters);
var drawSettings = new DrawingSettings(
new ShaderTagId("Deferred"),
new SortingSettings(camera)
);
var filterSettings = new FilteringSettings(RenderQueueRange.opaque);
context.DrawRenderers(cullingResults, ref drawSettings, ref filterSettings);
// === Pass 2: Lighting Pass ===
// 使用G-Buffer计算光照
commandBuffer.SetRenderTarget(lightingBuffer);
commandBuffer.ClearRenderTarget(false, true, Color.black);
// 设置G-Buffer纹理
commandBuffer.SetGlobalTexture("_GBufferAlbedo", gBuffer[0]);
commandBuffer.SetGlobalTexture("_GBufferNormal", gBuffer[1]);
commandBuffer.SetGlobalTexture("_GBufferEmission", gBuffer[2]);
commandBuffer.SetGlobalTexture("_GBufferPosition", gBuffer[3]);
// 渲染每个光源
foreach (var light in cullingResults.visibleLights) {
RenderLight(commandBuffer, camera, light);
}
// === Pass 3: Forward Pass (透明物体) ===
commandBuffer.SetRenderTarget(BuiltinRenderTextureType.CameraTarget);
commandBuffer.Blit(lightingBuffer, BuiltinRenderTextureType.CameraTarget);
filterSettings.renderQueueRange = RenderQueueRange.transparent;
context.DrawRenderers(cullingResults, ref drawSettings, ref filterSettings);
context.ExecuteCommandBuffer(commandBuffer);
context.Submit();
}
void RenderLight(CommandBuffer cmd, Camera camera, VisibleLight light) {
if (light.lightType == LightType.Directional) {
// 全屏四边形
cmd.DrawMesh(fullscreenQuad, Matrix4x4.identity, deferredLightingMat, 0, 0);
} else {
// 光源体积(球体/锥体)
Mesh volumeMesh = GetLightVolume(light.lightType);
Matrix4x4 matrix = GetLightMatrix(light);
// 背面剔除,避免摄像机在光源内部时的问题
cmd.DrawMesh(volumeMesh, matrix, deferredLightingMat, 0, 1);
}
}
RenderTexture CreateRT(int width, int height, RenderTextureFormat format) {
return new RenderTexture(width, height, 0, format) {
enableRandomWrite = true
};
}
private Mesh fullscreenQuad;
private Material deferredLightingMat;
Mesh GetLightVolume(LightType type) { return null; }
Matrix4x4 GetLightMatrix(VisibleLight light) { return Matrix4x4.identity; }
}
// 对应的Shader
/*
Shader "Custom/DeferredLighting" {
Properties {
_LightColor ("Light Color", Color) = (1,1,1,1)
_LightPosition ("Light Position", Vector) = (0,0,0,0)
_LightRange ("Light Range", Float) = 10
}
SubShader {
Pass {
Name "Directional Light"
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
sampler2D _GBufferAlbedo;
sampler2D _GBufferNormal;
sampler2D _GBufferPosition;
float3 _LightDirection;
float4 _LightColor;
struct v2f {
float4 pos : SV_POSITION;
float2 uv : TEXCOORD0;
};
v2f vert(appdata_full v) {
v2f o;
o.pos = UnityObjectToClipPos(v.vertex);
o.uv = v.texcoord;
return o;
}
float4 frag(v2f i) : SV_Target {
// 从G-Buffer读取
float3 albedo = tex2D(_GBufferAlbedo, i.uv).rgb;
float3 normal = tex2D(_GBufferNormal, i.uv).rgb * 2 - 1;
float3 worldPos = tex2D(_GBufferPosition, i.uv).rgb;
// PBR光照计算
float3 V = normalize(_WorldSpaceCameraPos - worldPos);
float3 L = -_LightDirection;
float3 H = normalize(V + L);
float NdotL = max(dot(normal, L), 0);
float NdotH = max(dot(normal, H), 0);
// Cook-Torrance BRDF
float roughness = tex2D(_GBufferNormal, i.uv).a;
float metallic = tex2D(_GBufferAlbedo, i.uv).a;
// ... 完整的PBR计算
return float4(albedo * _LightColor.rgb * NdotL, 1);
}
ENDCG
}
}
}
*/
3. AI系统 - 行为树与GOAP
// Goal-Oriented Action Planning
public class GOAPPlanner {
public class WorldState {
private Dictionary<string, bool> state = new Dictionary<string, bool>();
public bool Get(string key) => state.TryGetValue(key, out bool value) && value;
public void Set(string key, bool value) => state[key] = value;
public int Difference(WorldState other) {
int diff = 0;
foreach (var kvp in state) {
if (!other.state.TryGetValue(kvp.Key, out bool otherValue) || otherValue != kvp.Value) {
diff++;
}
}
return diff;
}
public WorldState Clone() {
var clone = new WorldState();
foreach (var kvp in state) {
clone.state[kvp.Key] = kvp.Value;
}
return clone;
}
}
public abstract class Action {
public string name;
public float cost;
public abstract bool CheckPreconditions(WorldState state);
public abstract void ApplyEffects(WorldState state);
public abstract void Execute();
}
// A*规划算法
public List<Action> Plan(WorldState current, WorldState goal, List<Action> actions) {
var openSet = new PriorityQueue<Node>();
var closedSet = new HashSet<WorldState>();
var startNode = new Node {
state = current,
gCost = 0,
hCost = current.Difference(goal),
parent = null,
action = null
};
openSet.Enqueue(startNode, startNode.fCost);
while (openSet.Count > 0) {
Node currentNode = openSet.Dequeue();
// 找到目标
if (currentNode.state.Difference(goal) == 0) {
return ReconstructPath(currentNode);
}
closedSet.Add(currentNode.state);
// 尝试所有可行的行动
foreach (var action in actions) {
if (!action.CheckPreconditions(currentNode.state)) continue;
WorldState newState = currentNode.state.Clone();
action.ApplyEffects(newState);
if (closedSet.Contains(newState)) continue;
float newGCost = currentNode.gCost + action.cost;
float newHCost = newState.Difference(goal);
Node neighbor = new Node {
state = newState,
gCost = newGCost,
hCost = newHCost,
parent = currentNode,
action = action
};
openSet.Enqueue(neighbor, neighbor.fCost);
}
}
return null; // 无法找到计划
}
List<Action> ReconstructPath(Node node) {
var path = new List<Action>();
while (node.parent != null) {
path.Add(node.action);
node = node.parent;
}
path.Reverse();
return path;
}
class Node {
public WorldState state;
public float gCost; // 从起点到当前的代价
public float hCost; // 启发式:当前到目标的估计
public float fCost => gCost + hCost;
public Node parent;
public Action action;
}
}
// 使用示例
public class EnemyAI : MonoBehaviour {
GOAPPlanner planner = new GOAPPlanner();
List<GOAPPlanner.Action> plan;
void Start() {
// 定义行动
var actions = new List<GOAPPlanner.Action> {
new GrabWeaponAction(),
new MoveToPlayerAction(),
new AttackAction(),
new FindCoverAction()
};
// 当前状态
var current = new GOAPPlanner.WorldState();
current.Set("hasWeapon", false);
current.Set("nearPlayer", false);
current.Set("playerDead", false);
// 目标状态
var goal = new GOAPPlanner.WorldState();
goal.Set("playerDead", true);
// 规划
plan = planner.Plan(current, goal, actions);
if (plan != null) {
Debug.Log($"计划: {string.Join(" -> ", plan.Select(a => a.name))}");
// 输出可能是: "GrabWeapon -> MoveToPlayer -> Attack"
}
}
void Update() {
if (plan != null && plan.Count > 0) {
plan[0].Execute();
// 完成后移除
}
}
class GrabWeaponAction : GOAPPlanner.Action {
public GrabWeaponAction() { name = "GrabWeapon"; cost = 1; }
public override bool CheckPreconditions(GOAPPlanner.WorldState state) => !state.Get("hasWeapon");
public override void ApplyEffects(GOAPPlanner.WorldState state) => state.Set("hasWeapon", true);
public override void Execute() { /* 实际执行 */ }
}
class MoveToPlayerAction : GOAPPlanner.Action {
public MoveToPlayerAction() { name = "MoveToPlayer"; cost = 2; }
public override bool CheckPreconditions(GOAPPlanner.WorldState state) => !state.Get("nearPlayer");
public override void ApplyEffects(GOAPPlanner.WorldState state) => state.Set("nearPlayer", true);
public override void Execute() { /* 实际执行 */ }
}
class AttackAction : GOAPPlanner.Action {
public AttackAction() { name = "Attack"; cost = 1; }
public override bool CheckPreconditions(GOAPPlanner.WorldState state) =>
state.Get("hasWeapon") && state.Get("nearPlayer");
public override void ApplyEffects(GOAPPlanner.WorldState state) => state.Set("playerDead", true);
public override void Execute() { /* 实际执行 */ }
}
class FindCoverAction : GOAPPlanner.Action {
public FindCoverAction() { name = "FindCover"; cost = 1; }
public override bool CheckPreconditions(GOAPPlanner.WorldState state) => true;
public override void ApplyEffects(GOAPPlanner.WorldState state) { }
public override void Execute() { /* 实际执行 */ }
}
}
// 优先队列(简化实现)
class PriorityQueue<T> {
private List<(T item, float priority)> elements = new List<(T, float)>();
public int Count => elements.Count;
public void Enqueue(T item, float priority) {
elements.Add((item, priority));
elements.Sort((a, b) => a.priority.CompareTo(b.priority));
}
public T Dequeue() {
T item = elements[0].item;
elements.RemoveAt(0);
return item;
}
}
4. 程序化生成 - Wave Function Collapse
// 波函数坍缩算法(程序化生成关卡)
public class WaveFunctionCollapse {
public class Tile {
public int id;
public Sprite sprite;
public bool[] validNeighbors; // 上下左右4个方向
}
class Cell {
public HashSet<int> possibleTiles; // 可能的tile
public int collapsed = -1; // 坍缩后的tile ID
public float Entropy => collapsed >= 0 ? 0 : possibleTiles.Count;
}
private Cell[,] grid;
private Tile[] tiles;
private int width, height;
public void Generate(int width, int height, Tile[] tiles) {
this.width = width;
this.height = height;
this.tiles = tiles;
// 初始化网格
grid = new Cell[width, height];
for (int x = 0; x < width; x++) {
for (int y = 0; y < height; y++) {
grid[x, y] = new Cell {
possibleTiles = new HashSet<int>(Enumerable.Range(0, tiles.Length))
};
}
}
// 主循环
while (true) {
// 1. 找熵最小的单元格
(int x, int y) = FindLowestEntropy();
if (x == -1) break; // 全部坍缩完成
// 2. 坍缩(随机选择一个可能的tile)
Collapse(x, y);
// 3. 传播约束
Propagate(x, y);
}
}
(int, int) FindLowestEntropy() {
float minEntropy = float.MaxValue;
var candidates = new List<(int, int)>();
for (int x = 0; x < width; x++) {
for (int y = 0; y < height; y++) {
Cell cell = grid[x, y];
if (cell.collapsed >= 0) continue;
float entropy = cell.Entropy;
if (entropy < minEntropy) {
minEntropy = entropy;
candidates.Clear();
candidates.Add((x, y));
} else if (Mathf.Approximately(entropy, minEntropy)) {
candidates.Add((x, y));
}
}
}
if (candidates.Count == 0) return (-1, -1);
// 随机选择一个
return candidates[UnityEngine.Random.Range(0, candidates.Count)];
}
void Collapse(int x, int y) {
Cell cell = grid[x, y];
// 加权随机选择
int[] possible = cell.possibleTiles.ToArray();
int chosen = possible[UnityEngine.Random.Range(0, possible.Length)];
cell.collapsed = chosen;
cell.possibleTiles.Clear();
cell.possibleTiles.Add(chosen);
}
void Propagate(int x, int y) {
var stack = new Stack<(int, int)>();
stack.Push((x, y));
while (stack.Count > 0) {
(int cx, int cy) = stack.Pop();
// 检查4个邻居
var neighbors = new[] {
(cx - 1, cy, 3), // 左 (右邻居的视角)
(cx + 1, cy, 2), // 右 (左邻居的视角)
(cx, cy - 1, 1), // 下 (上邻居的视角)
(cx, cy + 1, 0) // 上 (下邻居的视角)
};
foreach (var (nx, ny, direction) in neighbors) {
if (nx < 0 || nx >= width || ny < 0 || ny >= height) continue;
Cell neighbor = grid[nx, ny];
if (neighbor.collapsed >= 0) continue;
// 计算邻居可能的tiles
var validTiles = new HashSet<int>();
foreach (int currentTile in grid[cx, cy].possibleTiles) {
foreach (int neighborTile in neighbor.possibleTiles) {
if (tiles[currentTile].validNeighbors[direction] &&
IsCompatible(currentTile, neighborTile, direction)) {
validTiles.Add(neighborTile);
}
}
}
// 如果约束改变了,继续传播
if (validTiles.Count < neighbor.possibleTiles.Count) {
neighbor.possibleTiles = validTiles;
stack.Push((nx, ny));
}
}
}
}
bool IsCompatible(int tileA, int tileB, int direction) {
// 检查两个tile在特定方向上是否兼容
return tiles[tileA].validNeighbors[direction];
}
}
5. 汇编级优化
using System.Runtime.CompilerServices;
using System.Runtime.Intrinsics;
using System.Runtime.Intrinsics.X86;
// SIMD优化(AVX2)
public static class SIMDMath {
// 向量点积(同时计算8个)
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static unsafe void DotProduct8(
float* aX, float* aY, float* aZ,
float* bX, float* bY, float* bZ,
float* results, int count)
{
if (!Avx.IsSupported) {
// 降级实现
for (int i = 0; i < count; i++) {
results[i] = aX[i] * bX[i] + aY[i] * bY[i] + aZ[i] * bZ[i];
}
return;
}
int vectorCount = count / 8;
for (int i = 0; i < vectorCount; i++) {
int offset = i * 8;
// 加载8个向量
Vector256<float> ax = Avx.LoadVector256(aX + offset);
Vector256<float> ay = Avx.LoadVector256(aY + offset);
Vector256<float> az = Avx.LoadVector256(aZ + offset);
Vector256<float> bx = Avx.LoadVector256(bX + offset);
Vector256<float> by = Avx.LoadVector256(bY + offset);
Vector256<float> bz = Avx.LoadVector256(bZ + offset);
// 计算 ax*bx + ay*by + az*bz
Vector256<float> mulX = Avx.Multiply(ax, bx);
Vector256<float> mulY = Avx.Multiply(ay, by);
Vector256<float> mulZ = Avx.Multiply(az, bz);
Vector256<float> result = Avx.Add(Avx.Add(mulX, mulY), mulZ);
// 存储结果
Avx.Store(results + offset, result);
}
// 处理剩余元素
for (int i = vectorCount * 8; i < count; i++) {
results[i] = aX[i] * bX[i] + aY[i] * bY[i] + aZ[i] * bZ[i];
}
}
// 矩阵乘法(4x4)- 使用SSE
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static unsafe void MultiplyMatrix4x4SSE(float* a, float* b, float* result) {
if (!Sse.IsSupported) {
// 标准实现
return;
}
// 加载矩阵B的列
Vector128<float> b0 = Sse.LoadVector128(b + 0);
Vector128<float> b1 = Sse.LoadVector128(b + 4);
Vector128<float> b2 = Sse.LoadVector128(b + 8);
Vector128<float> b3 = Sse.LoadVector128(b + 12);
for (int i = 0; i < 4; i++) {
// 加载矩阵A的一行
Vector128<float> a0 = Sse.LoadVector128Scalar(a + i * 4 + 0);
Vector128<float> a1 = Sse.LoadVector128Scalar(a + i * 4 + 1);
Vector128<float> a2 = Sse.LoadVector128Scalar(a + i * 4 + 2);
Vector128<float> a3 = Sse.LoadVector128Scalar(a + i * 4 + 3);
// 广播每个元素
a0 = Sse.Shuffle(a0, a0, 0x00);
a1 = Sse.Shuffle(a1, a1, 0x00);
a2 = Sse.Shuffle(a2, a2, 0x00);
a3 = Sse.Shuffle(a3, a3, 0x00);
// 计算结果行
Vector128<float> row = Sse.Multiply(a0, b0);
row = Sse.Add(row, Sse.Multiply(a1, b1));
row = Sse.Add(row, Sse.Multiply(a2, b2));
row = Sse.Add(row, Sse.Multiply(a3, b3));
Sse.Store(result + i * 4, row);
}
}
}
终极知识图谱
🌟 引擎开发者/研究员级别
│
├─ ⚛️ 物理引擎
│ ├─ 约束求解器(PBD/PGS/LCP)
│ ├─ 连续碰撞检测(CCD)
│ ├─ 刚体动力学(冲量/约束)
│ ├─ 软体模拟(FEM/Mass-Spring)
│ ├─ 流体力学(SPH/PIC/FLIP)
│ └─ 布料模拟(Position Based)
│
├─ 🎨 高级渲染
│ ├─ 延迟渲染管线
│ ├─ 聚类延迟渲染
│ ├─ 体积光照
│ ├─ 全局光照(Path Tracing/Photon Mapping)
│ ├─ 实时光线追踪
│ └─ 虚幻渲染器架构
│
├─ 🧠 游戏AI
│ ├─ GOAP规划系统
│ ├─ HTN分层任务网络
│ ├─ 行为树高级模式
│ ├─ 机器学习(ML-Agents)
│ ├─ 导航网格生成
│ └─ 群体行为(Boids/Flow Field)
│
├─ 🌍 程序化生成
│ ├─ Wave Function Collapse
│ ├─ Perlin/Simplex噪声
│ ├─ L-System(植物生成)
│ ├─ Voronoi图(地形分割)
│ ├─ Delaunay三角化
│ └─ Marching Cubes(体素)
│
├─ 📐 高级数学
│ ├─ 四元数代数
│ ├─ 李群与李代数
│ ├─ 微分几何
│ ├─ 数值分析
│ ├─ 线性代数优化
│ └─ 计算几何
│
├─ ⚡ 极限优化
│ ├─ SIMD向量化(SSE/AVX/NEON)
│ ├─ 缓存友好数据结构
│ ├─ 无锁并发算法
│ ├─ 分支预测优化
│ ├─ 内存对齐与Prefetch
│ └─ 汇编级调优
│
├─ 🔬 空间结构
│ ├─ BVH层次包围盒
│ ├─ Octree/Quadtree
│ ├─ KD-Tree/BSP树
│ ├─ R-Tree空间索引
│ ├─ 空间哈希
│ └─ Loose Octree
│
├─ 🎮 引擎架构
│ ├─ ECS深度实现
│ ├─ 插件系统设计
│ ├─ 资源热重载
│ ├─ 脚本虚拟机
│ ├─ 渲染图(Frame Graph)
│ └─ 任务系统(Job System)
│
└─ 📚 理论基础
├─ 图形学论文(SIGGRAPH)
├─ 游戏编程模式
├─ 实时渲染(RTR4)
├─ 物理引擎设计
├─ 游戏AI编程精粹
└─ GPU Gems系列
📖 推荐学习资源
顶级书籍:
《Real-Time Rendering 4th》 - 图形学圣经
《Game Physics Engine Development》 - 物理引擎
《Game Engine Architecture》 - 引擎架构
《Game Programming Patterns》 - 设计模式
《Physically Based Rendering》 - PBR渲染
顶级论文/会议:
SIGGRAPH(图形学)
GDC(游戏开发)
I3D(交互式3D图形)
Eurographics
AIIDE(AI)
到这个层次,就是引擎开发、3A游戏核心技术、计算机图形学研究的领域了。需要:
- 🎓 扎实的数学基础(线性代数、微积分、数值分析)
- 💻 深入的计算机体系结构知识
- 🧮 算法与数据结构专家级理解
- 📐图形学/物理学理论基础
- 🔬 阅读论文的能力

被折叠的 条评论
为什么被折叠?



