当前位置:首页 > 每日看点

为什么c#能做大型游戏,而java不适合,c#跟java不是很相似吗?

卡卷网2年前 (2024-12-29)每日看点262

就说个编写 3D 游戏里最常见的场景吧。

现在我想要渲染一个 3D 模型,需要将组成模型的面传递给游戏引擎,然后引擎会去调用 DirectX/Vulkan/OpenGL 等等的 API 将我们模型数据提供给 GPU 渲染出来。

我们都知道 3D 模型的面由三角形组成,而每个三角形都有 3 个顶点,最后一大堆三角形组成了整个模型的表面。

那这件事情要怎么做呢?最简单的方法:整一个缓冲区把三角形的各顶点的位置存起来,然后调用图形 API 把数据上传到 GPU 就行了。

那这件事情在 C# 里面怎么做呢?

首先定义顶点类型:

[StructLayout(LayoutKind.Sequential)] record struct Vertex(float X, float Y, float Z);

然后我们整个顶点数组:

var vertices = new Vertex[12345];

然后把我们的三角形扔进去之后直接扔给引擎就完事了。

填充的时候简单 for 循环里往 vertices 里塞 Vertex 就行了。

假设引擎用的 OpenGL,那此时引擎接收到我们的数组后需要调用 glBufferData 来给 VAO 提供顶点数据:

const uint GL_ARRAY_BUFFER = 0x8892; const uint GL_STATIC_DRAW = 0x88E4; fixed (Vertex* p = vertices) glBufferData(GL_ARRAY_BUFFER, sizeof(Vertex) * vertices.Length, p, GL_STATIC_DRAW);

glBufferData 这个函数要怎么在 C# 里定义呢?

[DllImport("glew32.dll", EntryPoint = "__glewBufferData"), SuppressGCTransition] static extern void glBufferData(uint target, nint size, void* data, uint usage);

搞定。

至此为止我没有用到任何的(除了 OpenGL 本身之外的)库,也没有编写任何的 C# 以外的代码。

那写法这么简单,性能怎么样呢?我们看看最终调用 glBufferData 的部分 JIT 给我们生成了什么代码:

add rax, 16 ; address of vertices + method table (8) + array length (8) mov r8, rax ; = data of vertices mov edx, 0x242AC ; sizeof(Vertex) * vertices.Length mov ecx, 0x8892 ; GL_ARRAY_BUFFER mov r9d, 0x88E4 ; GL_STATIC_DRAW mov eax, 0x5B589850 ; function pointer of glBufferData call rax ; call glBufferData

可以看到,没有任何额外的内存分配和开销,数据直接从指针传出去,压根不需要拷贝,从头到尾的零成本抽象。

甚至可以说 C# 就是一个可以用 GC 的现代版 C++,这对于需要频繁与 native 进行交互的场景而言最适合不过。更不要提 C# 的 P/Invoke 在 NativeAOT 之下支持静态链接,连额外的 dll 都省了。


以上东西你用 Java 做一个试试,看看能有多复杂,再看看填充 buffer 的时候能否直接利用定义好的数据结构和类型,再看看能不能做到零拷贝。


更新:

鉴于 Java 22 之后有了 FFM API,以上东西虽然做起来很麻烦,但是好歹能写出来了,虽然我不知道他们现在的 FFM API 打算如何支持静态链接,毕竟 Java FFM API 这种运行时定义布局和查找入口点跟静态链接就是天生不兼容的。


那我们现在进一步加大难度。

我们都知道给 GPU 送的数据不一定非得是 float ,还可以是 intdouble 等等。那此时在 C# 里面我们只需要把顶点类型改成:

[StructLayout(LayoutKind.Sequential)] record struct Vertex<T>(T X, T Y, T Z) where T : unmanaged;

然后调用 glBufferData 那句改成:

fixed (Vertex<T>* p = vertices) glBufferData(GL_ARRAY_BUFFER, sizeof(Vertex<T>) * vertices.Length, p, GL_STATIC_DRAW);

就搞定了。

由于 .NET 会针对泛型参数给代码进行特化,因此 T 无论是 intfloat 还是 double,甚至是更复杂的类型例如 record struct Foo<U>(Bar A, float B, U C) 都能获得独一无二的代码生成,并且其内存布局也是编译时就确定的,效率也有保证。

扫描二维码推送至手机访问。

版权声明:本文由卡卷网发布,如需转载请注明出处。

本文链接:https://www.kajuan.net/ttnews/2024/12/5894.html

分享给朋友:

相关文章

需要做一个微信小程序项目,大公司价格太高怎么办?

需要做一个微信小程序项目,大公司价格太高怎么办?

一个小程序制作开发多少钱 构建一个微信小程序大概需要花费多少资金? 一、自主开发如果选择自主开发,这里面门道可不少。 微信小程序认证费用: 300 /年 域名费用: 30 - 80 /年 服务器费用: 600 - 3000 /年 这么一…

电视参数哪个最重要?

电视参数哪个最重要?

在选择智能电视时,面板类型是一个关键因素。 IPS面板以其宽广的视角和出色的色彩还原能力受到青睐,尤其适合日常观看和游戏。 尽管可能会有轻微的漏光,但在大多数情况下,这并不影响使用体验。 相比之下,VA面板提供更高的对比度和更深的黑色,增强…

你手机里有哪些堪称神器的 App?

你手机里有哪些堪称神器的 App?

嗨嗨,我是赢酱~ 首先我认为对于我们有用的提升自我的都是手机里的神器 App。 一个人应该什么样子呢?在我从女孩子的角度看来,自律,上进,会打扮,情商高,会挣钱,独立,落落大方,这才是应该有的样子,我们可以借助手机不断学习改变 今天给大家准…

是什么让你抛弃了 Windows 而转向 Mac?

是什么让你抛弃了 Windows 而转向 Mac?

别的不说,这玩意儿是真抗造啊,我这2012年买的MacBook Pro,依然在用…… 这台电脑我博士最后两年用来写代码(只写不运行,运行要上集群)和写论文,工作之后就变成生活和娱乐了,因为我一直用架子和外接键盘(颈椎不好)所以电脑看…

我觉得华为Mate60Pro明明配置不高,为什么还是有那么多人买呢?

我也好奇啊,所以闲聊时,我问了我们公司的副总,我说Mate60pro配置这么拉胯你怎么还买啊? 他一脸疑惑的看着我,配置?什么配置?我这手机信号挺好的啊? 我们总经理用的是去年华为出的折叠手机,花了一万多,我也想问问他同样的问题,但奈何一直…

2024,java开发,已经炸了吗?

炸的透透的了,坐标南京。 一月底,一个好哥们,双休朝九晚六不加班18K,被裁。 入职不到两年,算是工资和年终奖才赔了6.5W左右。 上周五新公司入职,周六开始加班。现在每周134加班到晚上八点,好像薪资还不如以前高。三月上旬,另一个好哥们,…

发表评论

访客

看不清,换一张

◎欢迎参与讨论,请在这里发表您的看法和观点。