- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在为 DirectX 11 开发 OBJ 加载器。在 OBJ 格式中,一个正方形(两个三角形)看起来像这样:
v 0 0 0
v 0 1 0
v 1 1 0
v 1 0 0
f 1 2 3
f 1 3 4
所以首先顶点数据由 v
给出,然后面由 f
给出。所以我只是将顶点读入顶点缓冲区,将索引读入索引缓冲区。但现在我需要为像素着色器计算法线。我可以在使用索引渲染时以某种方式存储 FACES 的法线数据,还是必须创建一个没有索引的顶点缓冲区? (因为这样我就可以存储每个顶点的法线数据,因为每个顶点只在 1 个面中使用)
最佳答案
通常的方法是为一个面的所有 3 个顶点存储相同的法向量。像这样:
Vertex
{
Vector3 position;
Vector3 normal;
}
std::vector<Vertex> vertices;
std::vector<uint32_t> indices;
for(each face f)
{
Vector3 faceNormal = CalculateFaceNormalFromPositions(f); // Generate normal for given face number `f`;
for(each vertex v)
{
Vertex vertex;
vertex.position = LoadPosition(f, v); // Load position from OBJ based on face index (f) and vertex index (v);
vertex.normal = faceNormal;
vertices.push_back(vertex);
indices.push_back(GetPosIndex()); // only position index from OBJ file needed
}
}
注意:通常您会希望使用顶点法线而不是面法线,因为顶点法线允许应用更好看的光照算法(逐像素光照):
for(each face f)
{
for(each vertex v)
{
Vertex vertex;
vertex.position = LoadPosition(f, v);
vertex.normal = ...precalculated somewhere...
vertices.push_back(vertex);
}
}
注意 2:通常您会希望从 Assets 文件中读取预先计算的法线,而不是在运行时计算它:
for(each face f)
{
for(each vertex v)
{
Vertex vertex;
vertex.position = LoadPosition(f, v);
vertex.normal = LoadNormal(f, v);
vertices.push_back(vertex);
}
}
.obj 格式允许存储每个顶点的法线)。来自谷歌的示例:
# cube.obj
#
g cube
# positions
v 0.0 0.0 0.0
v 0.0 0.0 1.0
v 0.0 1.0 0.0
v 0.0 1.0 1.0
v 1.0 0.0 0.0
v 1.0 0.0 1.0
v 1.0 1.0 0.0
v 1.0 1.0 1.0
# normals
vn 0.0 0.0 1.0
vn 0.0 0.0 -1.0
vn 0.0 1.0 0.0
vn 0.0 -1.0 0.0
vn 1.0 0.0 0.0
vn -1.0 0.0 0.0
# faces: indices of position / texcoord(empty) / normal
f 1//2 7//2 5//2
f 1//2 3//2 7//2
f 1//6 4//6 3//6
f 1//6 2//6 4//6
f 3//3 8//3 7//3
f 3//3 4//3 8//3
f 5//5 7//5 8//5
f 5//5 8//5 6//5
f 1//4 5//4 6//4
f 1//4 6//4 2//4
f 2//1 6//1 8//1
f 2//1 8//1 4//1
C++ 示例代码(未测试)
struct Vector3{ float x, y, z; };
struct Face
{
uint32_t position_ids[3];
uint32_t normal_ids[3];
};
struct Vertex
{
Vector3 position;
Vector3 normal;
};
std::vector<Vertex> vertices; // Your future vertex buffer
std::vector<uint32_t> indices; // Your future index buffer
void ParseOBJ(std::vector<Vector3>& positions, std::vector <Vector3>& normals, std::vector<Face>& faces) { /*TODO*/ }
void LoadOBJ(const std::wstring& filename, std::vector<Vertex>& vertices, std::vector<uint32_t>& indices)
{
// after parsing obj file
// you will have positions, normals
// and faces (which contains indices for positions and normals)
std::vector<Vector3> positions;
std::vector<Vector3> normals;
std::vector<Face> faces;
ParseOBJ(positions, normals, faces);
for (auto itFace = faces.begin(); itFace != faces.end(); ++itFace) // for each face
{
for (uint32_t i = 0; i < 3; ++i) // for each face vertex
{
uint32_t position_id = itFace->position_ids[i]; // just for short writing later
uint32_t normal_id = itFace->normal_ids[i];
Vertex vertex;
vertex.position = positions[position_id];
vertex.normal = normals[normal_id];
indices.push_back(position_id); // Note: only position's indices
vertices.push_back(vertex);
}
}
}
请注意,在顶点内合并法线数据后,您将不再需要法线索引。因此,法线变得没有索引(两个相等的法线可以存储在不同的顶点,这是一种空间浪费)。但是您仍然可以使用索引渲染,因为位置是索引的。
我必须说,当然,现代 GPU 的可编程流水线允许做更多棘手的事情:
关于带有法线的 DirectX 11 索引绘图,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17548298/
我想用groupshared DirectX 计算着色器中的内存以减少全局内存带宽并有望提高性能。我的输入数据是 Texture2D我可以像这样使用二维索引来访问它: Input[threadID.x
我一直在查看 MSDN 和 Microsoft.com,但只能找到存档论坛。现在还有 Microsoft Run DirectX 论坛吗? 最佳答案 在这里: http://forums.xna.co
我正在尝试将网格切成两半,或者至少能够实时删除其中的面。我想知道如何去做这件事? 锁定顶点缓冲区,将选定的面或顶点 memset 为 0,对我不起作用。有没有人对此有解决方案或教程,我真的希望在我的程
我想这是一个相当深入的主题,因此任何带有洞察信息的网址也很乐意接受。我一直在使用原生 DirectX,但从未管理过。另一方面,大多数情况下,在开发不需要高级 GPU 渲染的其他类型的应用程序时,我通常
微软的开源DirectX Shader Compiler描述了一种用于 HLSL 着色器的新中间语言 (IL) 的格式,称为 DXIL。 文档引用了从以前的 HLSL IL(称为 DXBC)到新 DX
我需要同时在更大的显示器上全屏显示在我的应用程序中播放的视频。在某些显卡上,这称为影院模式,使用显卡制造商提供的工具进行配置。 我只想用软件来做到这一点。我可以用 DirectX 做到这一点吗? 我的
我问 how to take the screen shot in DirectX并回答了“使用 GetFrontBufferData()”。然而,“这个函数在设计上非常慢,并且不应该在任何性能关键路
这让我感到困惑。 DirectX 绕过所有内容并直接与设备驱动程序对话,因此 GDI 和其他常用方法将不起作用 - 除非 Aero 被禁用(或不可用),否则出现的只是屏幕左上角的黑色矩形。我已经尝试了
我们正在开发一个通过 Direct3D 可视化显示信息的应用程序。迟到的客户端请求是能够通过某些远程桌面解决方案查看此应用程序。 有人做过类似的事情吗?哪些选项可用/不可用?我正在考虑 RDC、VNC
由于D3DPOOL_SCRATCH处理速度较慢,所以我编写了桌面捕获程序以引用网上的报告。然而,结果却是一片漆黑的画面。这是控制台程序的结果还是有其他原因? #include #include #
背景 我正在玩东方系列游戏之一的不朽之夜。射击按钮是“z”,移动较慢是“shift”,方向键移动。对我来说不幸的是,使用 shift-z 重影我的右箭头键,所以我在射击时无法向右移动。这种重影发生在所
我已经阅读了关于 DirectX 光栅化规则的在线文档,但我仍然不明白为什么这段代码没有在屏幕上产生任何可见的东西? target->SetAntialiasMode(D2D1_ANTIALIAS_M
如您所知,当我们想要在 DirectX 中绘制三维对象时,我们应该定义相机。现在我们有一个设备对象,它的名称是“device1”。这是我的问题: device1.View = Matrix.Look.
我正在使用桌面复制 API 从一个 GPU 捕获桌面,并且需要将纹理(位于 GPU 内存中)复制到另一个 GPU。为此,我有一个捕获线程,用于获取桌面图像,然后使用 ID3D11DeviceConte
假设 DX12 被挂接到叠加渲染的场景,看起来挂接的最佳函数是 IDXGISwapChain::Present,与 DX11 的方式相同。将此函数 Hook 后,交换链就可用,并且可以从中检索设备以创
当帧开始时,我会进行逻辑更新并在此之后进行渲染。 在我的渲染代码中,我做通常的事情。我设置了一些状态、缓冲区、纹理,并通过调用 Draw 来结束。 m_deviceContext->Draw(
我使用 DirectX 9.0 制作了一个小型 3D 查看器应用程序。现在我想添加一些编辑功能。假设我想编辑一个大多边形。当用户编辑形状时,顶点将被添加、删除和移动。现在每个多边形都存储为顶点缓冲区。
我编写了一个应用程序,它可以在 OpenGL、DirectX 9 和 DirectX 11 之间切换以进行渲染,而无需重新启动或重新创建窗口。在 OpenGL 和 DirectX 9 以及 Direc
如何在 DirectX 中执行此操作? glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glEnable(GL_BLEND); 不知何故,我似乎无
msdn documentation解释了在 directx 11 中,有多种方法可以通过编程方式填充 directx 11 纹理: (1) 使用默认使用纹理创建纹理并使用内存中的数据对其进行初始化
我是一名优秀的程序员,十分优秀!