C++ 如何在directx/c中进行平移/缩放操作++
为了便于学习,我正在尝试创建简单的绘图程序。现在我正在尝试添加平移和缩放功能。 这就是我如何更新我的相机m_向右和m_向上是1和0,基于是否单击wasdC++ 如何在directx/c中进行平移/缩放操作++,c++,directx,directx-11,C++,Directx,Directx 11,为了便于学习,我正在尝试创建简单的绘图程序。现在我正在尝试添加平移和缩放功能。 这就是我如何更新我的相机m_向右和m_向上是1和0,基于是否单击wasd void Camera::updateCamera(int width, int height) { this->height = height; this->width = width; cc.client_height = this->height; cc.client_width = t
void Camera::updateCamera(int width, int height)
{
this->height = height;
this->width = width;
cc.client_height = this->height;
cc.client_width = this->width;
cc.m_time = ::GetTickCount();
//panning and zooming in here
new_pos = world_cam.getTranslation() + world_cam.getZDirection()*(m_forward*0.1f);
new_pos = new_pos + world_cam.getXDirection()*(m_rightward * 20);
new_pos = new_pos + world_cam.getYDirection()*(m_upward * 20);
world_cam.setTranslation(new_pos);
temp = world_cam;
temp.inverse();
cc.m_view = temp;
cc.m_proj.setOrthoLH
(
width,
height,
-1.0f,
1.0f
);
}
这是我如何填充线条条来绘制的
void AppWindow::onLeftMouseDown(const Point & mouse_pos)
{
Point pos = screenToClient(mouse_pos);
clickedPoint = Vector3D(pos.m_x, pos.m_y, 0.0f);
if (isLPressed)
{
if (counter == 0)
{
LineStrip.push_back(Line(clickedPoint));
counter++;
}
else
{
LineStrip.back().addPoint(clickedPoint);
counter++;
}
}
}
这是顶点着色器
VS_OUTPUT vsmain(VS_INPUT input)
{
VS_OUTPUT output = (VS_OUTPUT) 0;
float4 new_pos = mul(input.position, m_world);
float clip_x = (new_pos.x / client_width) * 2.0 - 1.0;
float clip_y = 1.0 - (new_pos.y / client_height) * 2.0;
output.position = float4(clip_x, clip_y, 0, 1);
output.color = input.color;
return output;
}
现在我可以画我想要的线。问题是我不能使平移和缩放工作。它根本不会移动屏幕。我猜我如何填充线条带和顶点着色器输出是错误的。如果你们中的任何人帮助我,我将非常高兴。
谢谢您在这里的主要问题源于对3D空间工作原理的误解 三维渲染管道中使用了五个主要空间:局部空间、世界空间、视图空间、投影空间/同质剪辑空间和屏幕空间。用于在它们之间转换的矩阵以它们转换到的空间命名: 世界矩阵从局部空间转换为世界空间 视图矩阵将从世界空间转换为视图空间 投影矩阵从视图空间转换为投影空间 光栅化器根据在ID3D11DeviceContext::RSSetViewports调用中指定的D3D11_视口结构中的设置执行最终转换 您的系统非常简单,不需要世界矩阵。由于您可能正在使用3D API制作2D绘图程序,因此可以直接在世界空间中为每条线指定点 但是,为了支持摄影机操作,您需要一个视图矩阵,并且为了正确进行渲染,您需要一个投影矩阵和一个填充了客户区域大小的D3D11_视口结构 在代码中创建正交投影矩阵,尽管近平面和远平面规格应为支持的最小和最大缩放,但这是完美的。但是,您没有正确创建视图矩阵。视图矩阵是相机世界矩阵的逆转置,可以直接使用XMMatrixLookAtLH或XMMatrixLookToLH创建视图矩阵。对于您的系统来说,LookTo可能是一个更好的选择 最后,使用新矩阵更新着色器的常量缓冲区时,将视图和投影矩阵相乘,然后再将新的组合矩阵写入缓冲区 由于这种新的复杂性,您不再需要顶点着色器中的大部分代码-您可以直接执行乘法:
VS_OUTPUT vsmain(VS_INPUT input)
{
VS_OUTPUT output = (VS_OUTPUT) 0;
output.position = mul(input.position, m_viewprojection);
output.color = input.color;
return output;
}
最后一个阶段是添加新的点。由于添加了视图和投影矩阵,从鼠标按下事件获得的坐标不是世界空间坐标。您需要将它们转换为剪辑空间,然后将它们乘以组合视图/投影矩阵的倒数,以将它们转换为世界空间中的真实坐标。然后可以将新线段添加到条带中,与代码中的方式相同
到剪辑空间的转换是基本代数-光栅化器进行的转换是:
[ScreenX, ScreenY] = [(ProjX + 1)*(ScreenWidth/2), (ProjY + 1)*(ScreenHeight/2)]
要转换回投影空间,请执行以下操作:
[ProjX, ProjY] = [(ScreenX * (2 / ScreenWidth)) - 1, (ScreenY * (2 / ScreenHeight)) - 1]
从那里,你可以做一个矩阵向量乘法,得到世界空间中的X和Y坐标。因为这个应用程序大概是2D的,所以你可以忽略丢失的Z分量,只取X和Y。但是,如果你转换为3D,你需要从X和Y坐标向世界投射光线,以找到要选择的对象,或者用不同的算法修复Z坐标。看起来您不太了解3D应用程序如何使用不同的向量空间来表示事物。根据我所看到的,很可能你的相机、线条画和顶点着色器代码都错了。如何更新传递给顶点着色器的世界矩阵?updateCamera方法中的世界矩阵是我的世界矩阵,它在每一帧中都会更新我知道LineStrip的输入是错误的,这就是为什么我在这里无法得到它背后的公式。我在帖子中提到,它是错误的,但现在仍然有效