当前位置:首页 > 每日看点 > 正文内容

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

卡卷网12个月前 (12-29)每日看点164

就说个编写 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

分享给朋友:

相关文章

为什么苹果贵没人喷,华为贵一群人喷?

苹果:6:¥5288,6s:¥5288,7:¥5288,8:¥5288,XR:¥6299,11:¥5499,12:¥5999,13:¥5999,14:¥5999,15:¥5999,16:¥5999华为:P8:¥2888,P9:¥2988,P...

用wordpress做这个网站的话,需要用到哪些插件?

一个完整成型的B2C电商独立站,如果用wordpress+woocommerce搭建,最终会用上20来个插件,而且是在经过慎重筛选,剔除不必要的插件的情况下,别问我为什么。wordpress建站,插件安装多了,速度会变慢,这是常识,但需要在...

想入个键盘,想买机械的但是太贵,求知友推荐一款手感比较好的薄膜键盘?

想入个键盘,想买机械的但是太贵,求知友推荐一款手感比较好的薄膜键盘?

相信很多接触过286的90后朋友都和我有一样的体会,以前的机械键盘真的是让人头皮发麻,不仅敲击要非常用力,而且很吵。所以后面随着大家的生活消费水平的上升,家家户户都有电脑了,自然也不想再用打字来宣扬自己有电脑的优越感,基本上大家都换成了又轻...

阿里云服务器续费价格好贵,想换一家云服务厂商,该怎么选择?

阿里云服务器续费价格好贵,想换一家云服务厂商,该怎么选择?

最近一台买了3年时间的腾讯云轻量服务器到期了,还有5天时间。当时买的价格是3年198元。配置是2核CPU、4GB内存,80GB SSD云硬盘,1200GB 流量包,然后中途给免费升级了CPU,从2核变成了4核。平均下来一年的费用70元不到,...

国内AI大模型已近80个,哪个最有前途?

国内AI大模型已近80个,哪个最有前途?

题主说错了,不是80个,是168个!虽然“最有前途”不好说,但是我可以帮题主排除一些错误方向:开源大模型一定比闭源的有前途吗?参数量大的模型一定就比小模型有前途吗?榜单排名高的大模型一定更有前途吗?2024年3月更新,243个大模型中有哪几...

年收入40万的网文作者,是不是可以吊打任何职业了?

哈,我二十岁的时候也这么狂。想当年,我一个大二学生,在宿舍里写出一本大精品,月入两万五,在学校里走路都是横着的,游戏卡池一开,看都不看,氪到出货为止。iPhone12pro一发布直接买,还买了个iPad Pro,都是官网直接买的,Apple...

发表评论

访客

看不清,换一张

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