- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
我已经在此处和其他页面中检查了几种用于计算顶点法线的解决方案。似乎最适合我自己的呈现 3D 地形的实现的常见解决方案是计算面法线,这不是问题。然后遍历每张脸并将其添加到构成它的顶点上,然后在完成后将其归一化。它似乎在大多数情况下都有效,但我有一些奇怪的图形问题,主要是光线从亮到暗的过渡,你可以分辨出脸在哪里。在下图中,您可以在这座山的顶部右下角附近看到它。
所以我想知道是什么导致了这种奇怪的模式。这与我计算法线的方式有关,但我只是看不出问题出在哪里。任何帮助,将不胜感激。
计算法线的代码是...
// Calclulate surface normals
vec3 v1, v2, v3, vec1, vec2;
for(GLuint i = 0; i < terrain->NumFaces; i++) {
v1 = terrain->Vertices[terrain->Faces[i].vert_indices[0]];
v2 = terrain->Vertices[terrain->Faces[i].vert_indices[1]];
vec1 = vector(&v2, &v1);
v3 = terrain->Vertices[terrain->Faces[i].vert_indices[2]];
vec2 = vector(&v3, &v1);
terrain->Faces[i].surface_normal = crossProduct(&vec1, &vec2);
normalize(&terrain->Faces[i].surface_normal);
}
// Calculate vertex normals...
// Add all the surface normals to their attached vertex normals
for(GLuint currentFace = 0; currentFace < terrain->NumFaces; currentFace++) {
vec3 *f = &terrain->Faces[currentFace].surface_normal;
for(GLuint faceVertex = 0; faceVertex < 3; faceVertex++) {
vec3 *n = &terrain->Normals[terrain->Faces[currentFace].vert_indices[faceVertex]];
*n = vec3Add(n, f); // adds vector f to n
}
}
// Go over all vertices and normalize them
for(GLuint currentVertice = 0; currentVertice < terrain->NumVertices; currentVertice++)
normalize(&terrain->Normals[currentVertice]);
我在上面的代码中使用的其他实用函数是...
// Returns the vector between two vertices
vec3 vector(const vec3 *vp1, const vec3 *vp2)
{
vec3 ret;
ret.x = vp1->x - vp2->x;
ret.y = vp1->y - vp2->y;
ret.z = vp1->z - vp2->z;
return ret;
}
// Returns the normal of two vectors
vec3 crossProduct(const vec3 *v1, const vec3 *v2)
{
vec3 normal;
normal.x = v1->y * v2->z - v1->z * v2->y;
normal.y = v1->z * v2->x - v1->x * v2->z;
normal.z = v1->x * v2->y - v1->y * v2->x;
return normal;
}
// Returns the length of a vector
float vec3Length(vec3 *v1) {
return sqrt(v1->x * v1->x + v1->y * v1->y + v1->z * v1->z);
}
// Normalizes a vector
void normalize(vec3 *v1)
{
float len = vec3Length(v1);
if(len < EPSILON) return;
float inv = 1.0f / len;
v1->x *= inv;
v1->y *= inv;
v1->z *= inv;
}
// Adds vector v2 to v1
vec3 vec3Add(vec3 *v1, vec3 *v2)
{
vec3 v;
v.x = v1->x + v2->x;
v.y = v1->y + v2->y;
v.z = v1->z + v2->z;
return v;
}
最佳答案
使用面法线的平均值计算顶点法线的一个问题是计算出的法线可能有偏差。例如,假设有一条南北走向的山脊。山脊顶上的一个顶点在东边有三个多边形,在西边有两个多边形。顶点法线将向东倾斜。当照明来自西方时,这会导致该点的照明变暗。
一个可能的改进是对每个面的法线应用权重,与面角在该顶点处的角度成正比,但这不会消除所有偏差。
关于c - 顶点法线的图形问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54856040/
所以昨天我写了 WaveFront .obj 3D 模型加载器,它现在工作正常(虽然不支持所有内容)所以我写了简单的测试来在屏幕上绘制任何 3D 模型,在我为场景添加照明之前一切正常.光出现了,但法线
我的代码(用 C++ 编码)在处理更新模型法线的 for 循环中存在瓶颈。我用来测试的模型有大约 ~2.2k 个顶点(指示),工作正常并且在 60 fps 限制下工作,但法线与指示器(~12k)一样多
我无法将法线和 u,v 对发送到我的着色器。如果我删除法线,一切都会按预期进行。 编辑看起来 v_normal 正在接收用于 v_coord 的值。我仍然不知道。/编辑 这是我的顶点: struct
我正在寻找一种方法来获取矩形的所有顶点,该矩形的中心、法线、长度和高度我都知道。我的数学有点弱所以请帮助我。编辑:飞机在 3D 空间中。 最佳答案 通过从中心点的 x/y 位置减去/加上宽度/高度的一
是否可以从片段着色器内访问表面法线(与片段平面相关的法线)?或者也许这可以在顶点着色器中完成? 当我们沿着着色器管道走下去时,相关几何体的所有知识是否都会丢失,或者是否有一些巧妙的方法可以在片段着色器
我无法使用 VBO 正确渲染法线。下面是我正在使用的代码,顶点是一个包含顶点的数组,法线是一个包含法线的数组: //Create the buffers and such GLuint VBOID;
我已经有了这个不再那么小的基于图 block 的游戏,这是我的第一个真正的 OpenGL 项目。我想将每个图 block 渲染为 3D 对象。因此,首先我创建了一些对象,例如立方体和球体,为它们提供了
我正在尝试添加一个垂直于我单击的面的框(称为“标记”)。 为此,单击时,我会转换一条射线,如果它击中某些物体,我会获取法线的交点值并将它们传输到“标记”作为其旋转值。在问这个问题之前,我阅读了这个答案
这与另一个问题(那里的图像)中描述的问题有关: Opengl shader problems - weird light reflection artifacts 我有一个 .obj 导入器,它创建一
我正在尝试制作一个在 OpenGL 2.1 和 Qt5 中渲染的简单 map 。但我在非常基本的问题上失败了。我在这里展示的是表面法线。 我有 4 个由单个三角形几何体组成的对象。一个简单的几何图形是
我正在开发一个类似 JavaScript/Canvas 3D FPS 的引擎,迫切需要一个法线向量(如果您愿意,也可以是观察向量)来进行近平面和远平面裁剪。我有 x 轴和 y 轴旋转 Angular
我正在编写用于在我的 DirectX 应用程序中存储、加载和渲染静态网格的类。 我知道 Box 模型可以使用 8 个顶点,但通常它使用 24 或 36 个(因为一个“空间中的顶点”实际上是 3 个具有
我无法使 phong 着色看起来正确。我很确定我的 OpenGL 调用或我加载法线的方式有问题,但我想这可能是其他问题,因为 3D 图形和 Assimp 对我来说都还很陌生。尝试加载 .obj/.mt
我是一名优秀的程序员,十分优秀!