gpt4 book ai didi

c++ - opengl - 三角形邻接三角形带

转载 作者:搜寻专家 更新时间:2023-10-31 00:54:16 25 4
gpt4 key购买 nike

假设我有自己的几何图形并创建了一个包含三角形邻接信息的索引缓冲区。然后,将绘制模式从 GL_TRIANGLES 更改为 GL_TRIANGLE_ADJACENCY。问题是,我可以使用几何着色器将几何图形从三角形邻接转换为三角形带吗?

像这样:

layout(triangles_adjacency) in;
layout(triangle_strip, max_vertices = 3) out;

in Vertex
{
vec3 normal;
} vertex[];

out FragmentVertexData
{
vec3 normal;
vec3 fragpos;
} VertexOut;


void main()
{
for(int i = 0 ; i < gl_in.length(); i+=2)
{
gl_Position = ProjectionMatrix * ViewMatrix * ModelMatrix * gl_in[i].gl_Position;
VertexOut.normal = vertex[i].normal;
VertexOut.fragpos = vec3(ModelMatrix * gl_in[i].gl_Position);
VertexOut.fragpos = gl_Position;
EmitVertex();
}
EndPrimitive();
}

我已经尝试过,事实上它绘制到几何体上,但法线有问题。我也必须为它们编制索引吗?我错过了一步吗?

enter image description here

这就是我在片段着色器中使用 fragpos 和法线的方式

vec3 normal = normalize(VertexOut.normal);
vec3 lightDir = normalize(light.position - VertexOut.fragpos);

这是我编写三角形邻接索引缓冲区的算法:

void Loader::FindAdjacencies(const aiMesh * paiMesh, vector<int>& indices)
{
// Step 1 - find the two triangles that share every edge
for (uint i = 0; i < paiMesh->mNumFaces; i++)
{
const aiFace& face = paiMesh->mFaces[i];

Face Unique;

// If a position vector is duplicated in the VB we fetch the
// index of the first occurrence.
for (uint j = 0; j < 3; j++)
{
uint Index = face.mIndices[j];
aiVector3D& v = paiMesh->mVertices[Index];

if (m_posMap.find(v) == m_posMap.end())
{
m_posMap[v] = Index;
}
else
{
Index = m_posMap[v];
}

Unique.Indices[j] = Index;
}

m_uniqueFaces.push_back(Unique);

Edge e1(Unique.Indices[0], Unique.Indices[1]);
Edge e2(Unique.Indices[1], Unique.Indices[2]);
Edge e3(Unique.Indices[2], Unique.Indices[0]);

m_indexMap[e1].AddNeigbor(i);
m_indexMap[e2].AddNeigbor(i);
m_indexMap[e3].AddNeigbor(i);

}

// Step 2 - build the index buffer with the adjacency info
for (uint i = 0; i < paiMesh->mNumFaces; i++)
{
const Face& face = m_uniqueFaces[i];

for (uint j = 0; j < 3; j++)
{
Edge e(face.Indices[j], face.Indices[(j + 1) % 3]);
assert(m_indexMap.find(e) != m_indexMap.end());
Neighbors n = m_indexMap[e];
uint OtherTri = n.GetOther(i);
uint minus1 = (uint)-1;
bool comp = (OtherTri != minus1);
assert(comp);

const Face& OtherFace = m_uniqueFaces[OtherTri];
uint OppositeIndex = OtherFace.GetOppositeIndex(e);

indices.push_back(face.Indices[j]);
indices.push_back(OppositeIndex);
}
}

}

不幸的是,仅适用于紧密的几何形状。这就是我用立方体测试它的原因。我尝试使用 bunny.ply,但模型的一部分有漏洞,我将不得不在 blender 中对其进行编辑。

这是 obj 文件:

# Blender v2.76 (sub 0) OBJ File: ''
# www.blender.org
v 1.000000 -1.000000 -1.000000
v 1.000000 -1.000000 1.000000
v -1.000000 -1.000000 1.000000
v -1.000000 -1.000000 -1.000000
v 1.000000 1.000000 -0.999999
v 0.999999 1.000000 1.000001
v -1.000000 1.000000 1.000000
v -1.000000 1.000000 -1.000000
vt 0.333333 0.666667
vt 0.333333 1.000000
vt 0.000000 1.000000
vt 0.000000 0.666667
vt 0.000000 0.333333
vt 0.333333 0.333333
vt 0.333333 0.000000
vt 0.666667 0.000000
vt 0.000000 0.000000
vt 1.000000 0.333333
vt 0.666667 0.333333
vt 0.666667 0.666667
vt 1.000000 0.000000
vn 0.000000 -1.000000 0.000000
vn 0.000000 1.000000 0.000000
vn 1.000000 0.000000 0.000000
vn -0.000000 0.000000 1.000000
vn -1.000000 -0.000000 -0.000000
vn 0.000000 0.000000 -1.000000
f 2/1/1 3/2/1 4/3/1
f 8/1/2 7/4/2 6/5/2
f 5/6/3 6/7/3 2/8/3
f 6/9/4 7/7/4 3/6/4
f 3/10/5 7/11/5 8/8/5
f 1/11/6 4/12/6 8/1/6
f 1/4/1 2/1/1 4/3/1
f 5/6/2 8/1/2 6/5/2
f 1/11/3 5/6/3 2/8/3
f 2/5/4 6/9/4 3/6/4
f 4/13/5 3/10/5 8/8/5
f 5/6/6 1/11/6 8/1/6

非常感谢!

这是我的顶点着色器:

#version 430 core
layout(location = 0) in vec3 vertexPosition;
layout(location = 1) in vec2 texCoord;
layout(location = 2) in vec3 normal;

out VertexData
{
vec3 normal;
vec2 textCoord;
} vertex;

// Values that stay constant for the whole mesh.

void main(){
gl_Position = vec4(vertexPosition,1.0f);
vertex.textCoord = texCoord;
vertex.normal = normal;
}

和我的片段着色器:

#version 430 core

struct Material {
vec3 ambient;
vec3 diffuse;
vec3 specular;
float shininess;
};

struct Light {
vec3 position;
vec3 ambient;
vec3 diffuse;
vec3 specular;
};

uniform Material material;
uniform Light light;

out vec4 color;

uniform float LightIntensity;
uniform vec3 LightPos;
uniform vec3 ViewPos;

in FragmentVertexData
{
vec3 normal;
vec3 fragpos;
vec2 texCoord;
} VertexOut;


void main(){


// color of the object
vec3 objectColor = vec3(1.0f, 0.5f, 0.31f);


// Ambient

vec3 ambient = light.ambient * material.ambient ;

vec3 normal = normalize(VertexOut.normal);
vec3 lightDir = normalize(light.position - VertexOut.fragpos);

float diff = max(dot(lightDir,normal), 0.0);
vec3 diffuse = light.diffuse * diff * material.diffuse ;

vec3 viewDir = normalize(ViewPos - VertexOut.fragpos);
vec3 reflectDir = reflect(-lightDir, normal);

vec3 halfwayDir = normalize(lightDir + viewDir );

float spec = pow(max(dot(normal, halfwayDir), 0.0), material.shininess);


vec3 specular = light.specular * spec * material.specular ;

color = vec4((ambient + diffuse + specular) * objectColor, 1);

}

最佳答案

三角形邻接,包含三角形的邻接数据,以便访问相邻的三角形。 Geometry Shader stage 可以访问 6 个顶点和属性,形成 4 个三角形。 3 个顶点构成当前渲染的三角形。其他 3 个顶点与当前呈现的三角形的 3 个侧边结合形成相邻(相邻)三角形。 (参见 GL_ARB_geometry_shader4Primitive)。

triangle adjacency

如果 Geometry Shader应该将渲染的三角形传递到下一个着色器阶段,然后它只需要处理构成三角形的三个点,而不是它的邻接点。

其他问题:

  • 模型的世界空间位置被VertexOut.fragpos = gl_Position;覆盖
  • 法 vector 必须转换到世界空间:
    VertexOut.normal = mat3(ModelMatrix) * vertex[i].normal;

几何着色器应该看起来像这样:

layout(triangles_adjacency) in;
layout(triangle_strip, max_vertices = 3) out;

in Vertex
{
vec3 normal;
} vertex[];

out FragmentVertexData
{
vec3 normal;
vec3 fragpos;
} VertexOut;

uniform mat4 ModelMatrix;
uniform mat4 ViewMatrix;
uniform mat4 ProjectionMatrix;

void main()
{
for (int i = 0; i < 6; i += 2)
{
vec4 fragPos = ModelMatrix * gl_in[i].gl_Position;
VertexOut.normal = mat3(ModelMatrix) * vertex[i].normal;
VertexOut.fragpos = fragPos.xyz;
gl_Position = ProjectionMatrix * ViewMatrix * fragPos;
EmitVertex();
}
EndPrimitive();
}


如果法 vector 是每个面,您的邻接算法将失败:

生成邻接索引的算法没有考虑到,面的每个点都由一对顶点位置和法 vector 定义。不同的面可能有相同的角点位置,但它们总是有不同的法 vector 。因为你把所有的顶点位置都放在一个 map m_pos Map中,其中位置是关键,法 vector 的区别就丢失了。当你有一个立方体时,每个面都有法 vector ,每个顶点位置必须是顶点缓冲区中的 3 倍,因为它由立方体的 3 个面共享并且有 3 个不同的法 vector 。
如果你有一个网格,其中法 vector 是每个顶点(例如球体),你的算法将正常工作。但是如果法 vector 是每个面的,你的算法就会失败,就像立方体的情况一样。


保留面孔并仅将邻接添加到面孔的算法如下所示:

#include <array>
#include <vector>
#include <map>

using TIndices = std::vector<int>;
using TFace = std::array<int, 3>;
using TFaces = std::vector<TFace>;
using TVertex = std::array<float, 3>;
using TVertices = std::vector<TVertex>;

void GenerateAdjacencies( const TVertices &vertices, const TFaces &faces, TIndices &adj )
{
// associate each geometric vertex position with an unique ID
std::vector<int> uniqueMap;
std::map<TVertex,int> tempUniqueVertices;
int uniqueIndex = 0;
for ( size_t vI = 0; vI < vertices.size(); ++ vI )
{
auto vIt = tempUniqueVertices.find( vertices[vI] );
if ( vIt == tempUniqueVertices.end() )
{
tempUniqueVertices[ vertices[vI] ] = uniqueIndex;
uniqueMap.push_back( uniqueIndex );
uniqueIndex ++;
}
else
uniqueMap.push_back( vIt->second );
}
tempUniqueVertices.clear();

// find all edges and associate the edge with all the points, which form a triangle with it.
std::map< std::tuple<int, int>, std::vector<int> > edges;
for ( auto & f : faces )
{
for ( int pI = 0; pI < 3; ++ pI )
{
int edgeU[2]{ uniqueMap[f[pI]], uniqueMap[f[(pI+1) % 3]] };
int i0 = edgeU[0] < edgeU[1] ? 0 : 1;
edges[{ edgeU[i0], edgeU[1-i0] }].push_back( f[(pI+2) % 3] );
}
}

// create the adjacencies
for ( auto & f : faces )
{
for ( int pI = 0; pI < 3; ++ pI )
{
int edgeU[2]{ uniqueMap[f[pI]], uniqueMap[f[(pI+1) % 3]] };
int i0 = edgeU[0] < edgeU[1] ? 0 : 1;
auto &adjs = edges[{ edgeU[i0], edgeU[1 - i0] }];
int adjI = adjs.size() > 1 && adjs[0] == f[(pI+2) % 3] ? 1 : 0;
adj.push_back( f[pI] );
adj.push_back( adjs[adjI] );
}
}
}

参见 example

关于c++ - opengl - 三角形邻接三角形带,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46018049/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com