此问题不依赖于基于3D的代码,也不依赖于逻辑;它只是着重于消除一个对象与另一个对象之间的依赖关系,因此,我在描述问题时会尽量做到透彻。虽然具有3D背景知识可能会有助于理解代码的作用,但不需要将A类与B类分开。我相信可以通过一些逻辑但横向的思考来解决此任务。
我正在重构一些旧代码(在90年代初的某个时候编写),并且有一些类依赖于其他类。这个问题将集中在依赖于另一个单独类的单个类上(在这种情况下,没有其他依赖项)。该项目是DirectX项目,它只是将一些对象渲染到屏幕上以用于工作目的。不幸的是,我无法给出详尽的描述。但是,我可以用代码解释问题。
我需要重点关注两个类,由于我们现在对渲染存在第二需求,因此我目前正在重写其中一个类,以使其具有通用性和可重用性。
我将在下面更详细地说明,但是情况的要点是Engine3D
在Camera3D
方法中依赖于Render
。
Engine3D
的当前流量 Engine3D
的当前流程主要集中在实现一个目标上。呈现项目所需的东西,就是这样。
public void Render() {
// Clear render target.
// Render camera.
// Set constant buffers.
// Render objects.
// Present back buffer.
}
更新代码和渲染代码都混杂在一起,并且渲染到屏幕上的每个对象都位于Render
方法中。这对可重用性不利,因为它会强制每次渲染完全相同的场景。因此,我将其分解,创建一个通用的Engine3D
,然后在我的代码(我们称之为Form1
)中使用它。
通过将Draw
调用到Engine3D
并传入要渲染的对象,使渲染对象到屏幕成为一个简单的任务。与XNA Framework
的过去很像。 Engine3D
的新流程的基本表示是:
// I may move this to the constructor; if you believe this is a good idea, please let me know.
public new virtual void Initialize() {
base.Initialize();
OnInitialize(this, new EventArgs());
RenderLoop.Run(Window, () => {
if (!Paused) {
OnUpdate(this, new EventArgs());
Render();
}
});
}
protected override void Render() {
// Clear Render Target. context.ClearRenderTargetView(...);
// Set constant buffers.
OnRender(this, new EventArgs());
// Present back buffer.
}
将OnUpdate
用于更新屏幕上的任何对象,而OnRender
将处理新的Draw
调用。
问题是旧的流程(在渲染循环内)清除了渲染目标,然后渲染了摄影机,然后开始设置常量缓冲区。我已经很轻松地完成了该列表中的第一个,该列表中的第二个是使用新流程的简单Draw
调用(可以在设置缓冲区之后进行);但是问题在于设置了常量缓冲区。以下代码行需要Camera3D
对象,而在移动该对象时遇到了问题。
ConstantBuffers.PerFrame perFrame = new ConstantBuffers.PerFrame();
perFrame.Light.Direction = (camera.TargetPosition - camera.Position);
perFrame.CameraPosition = camera.Position;
perFrame.CameraUp = camera.Up;
context.AddResource(perFrame);
然后将此变量添加到渲染目标的资源列表中,该资源必须保留在Engine3D
中,以防止绘制代码过于复杂。
代码中稍后还有其他对象依赖于Camera3D
的{{1}}属性,但是一旦我解决了如何将World
与Engine3D
分离开来,我确保我可以轻松地照顾其余的人。
如何将这种依赖性与Camera3D
类分开?
我想到的一些事情是:
Engine3D
上设为静态,因为总有一个摄像头,再也没有。Camera3D
和Engine3D
类。如果对我要达到的目标感到困惑,请告诉我,我将尽力而为。
答案 0 :(得分:1)
您要进行的重构称为 Pure Fabrication 。
您建议的解决方案是:
在Camera3D上将这些属性设为静态,因为总是有一个摄像机,再也没有。
我建议:
StudioSetup
),该类包含Engine3D
中需要的字段(并且您希望在Camera3D
中使其成为静态对象) ); Engine3D->Render()
; Camera3D
的依赖已替换为对StudioSetup
对象的依赖。这类似于您的“创建一个中间人类来处理所有这些”。解。但是,中间人除了做单向快递员以外,不会做任何事情。