- Java 双重比较
- java - 比较器与 Apache BeanComparator
- Objective-C 完成 block 导致额外的方法调用?
- database - RESTful URI 是否应该公开数据库主键?
假设我有自己的几何图形并创建了一个包含三角形邻接信息的索引缓冲区。然后,将绘制模式从 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();
}
我已经尝试过,事实上它绘制到几何体上,但法线有问题。我也必须为它们编制索引吗?我错过了一步吗?
这就是我在片段着色器中使用 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_shader4 和 Primitive)。
如果 Geometry Shader应该将渲染的三角形传递到下一个着色器阶段,然后它只需要处理构成三角形的三个点,而不是它的邻接点。
其他问题:
VertexOut.fragpos = gl_Position;
覆盖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/
在 OpenGL/ES 中,在实现渲染到纹理功能时,您必须小心,不要引起反馈循环(从正在写入的同一纹理中读取像素)。由于显而易见的原因,当您读取和写入纹理的相同像素时,行为是未定义的。但是,如果您正在
正如我们最终都知道的那样,规范是一回事,实现是另一回事。大多数错误是我们自己造成的,但有时情况并非如此。 我相信列出以下内容会很有用: GPU 驱动程序中当前已知的与最新版本的 OpenGL 和 GL
很难说出这里问的是什么。这个问题是模棱两可的、模糊的、不完整的、过于宽泛的或修辞的,无法以目前的形式得到合理的回答。为了帮助澄清这个问题以便可以重新打开它,visit the help center
我正在学习 OpenGL,非常想知道与显卡的交互如何。 我觉得了解它是如何在图形驱动程序中实现的,会让我了解 opengl 的完整内部结构(通过这个我可以知道哪些阶段/因素影响我对 opengl 性能
我正在尝试绘制到大于屏幕尺寸(即 320x480)的渲染缓冲区 (512x512)。 执行 glReadPixels 后,图像看起来是正确的,除非图像的尺寸超过屏幕尺寸——在本例中,超过 320 水平
我正在 Windows 中制作一个 3D 小行星游戏(使用 OpenGL 和 GLUT),您可以在其中穿过一堆障碍物在太空中移动并生存下来。我正在寻找一种方法来针对无聊的 bg 颜色选项设置图像背景。
如果我想要一个包含 100 个 10*10 像素 Sprite 的 Sprite 表,是否可以将它们全部排成一排来制作 1,000*10 像素纹理?还是 GPU 对不那么窄的纹理表现更好?这对性能有什
这个问题在这里已经有了答案: Rendering 2D sprites in a 3D world? (7 个答案) 关闭 6 年前。 我如何概念化让图像始终面对相机。我尝试将三角函数与 arcta
是否可以在 OpenGL 中增加缓冲区? 假设我想使用实例化渲染。每次在世界上生成一个新对象时,我都必须用实例化数据更新缓冲区。 在这种情况下,我有一个 3 个 float 的缓冲区 std::v
有人可以向我解释为什么下面的代码没有绘制任何东西,但如果我使用 GL_LINE_LOOP 它确实形成了一个闭环吗? glBegin(GL_POLYGON); for(int i = 0; i <= N
正如标题所说,OpenGL 中的渲染目标是什么?我对 OpenGL 很陌生,我看到的所有网站都让我很困惑。 它只是一个缓冲区,我在其中放置稍后将用于渲染的东西吗? 如果您能提供一个很好的引用来阅读它,
当使用 OpenGL 1.4 固定功能多纹理时,每个纹理阶段的输出在传递到下一个阶段之前是否都固定在 [0, 1]? spec说(第 153 页): If the value of TEXTURE_E
我比较了 2 个函数 openGL ES 和 openGL gvec4 texelFetchOffset(gsampler2DArray sampler, ivec3 P, int lod, ivec
关闭。这个问题是off-topic .它目前不接受答案。 想改进这个问题吗? Update the question所以它是on-topic用于堆栈溢出。 关闭 10 年前。 Improve thi
关闭。这个问题不符合Stack Overflow guidelines .它目前不接受答案。 想改进这个问题?将问题更新为 on-topic对于堆栈溢出。 6年前关闭。 Improve this qu
那么当你调用opengl函数时,比如glDraw或者gLBufferData,是否会导致程序线程停止等待GL完成调用呢? 如果不是,那么 GL 如何处理调用像 glDraw 这样的重要函数,然后立即更
我正在尝试实现级联阴影贴图,当我想访问我的视锥体的每个分区的相应深度纹理时,我遇到了一个错误。 更具体地说,当我想选择正确的阴影纹理时会出现我的问题,如果我尝试下面的代码,我会得到一个像 this 中
我想为OpenGL ES和OpenGL(Windows)使用相同的着色器源。为此,我想定义自定义数据类型并仅使用OpenGL ES函数。 一种方法是定义: #define highp #define
我尝试用 6 个位图映射立方体以实现天空盒效果。我的问题是一个纹理映射到立方体的每个面。我已经检查了 gDEBugger,在立方体纹理内存中我只有一个 图像(因为我尝试加载六个图像)。 代码准备纹理:
在 OpenGL 中偏移深度的最佳方法是什么?我目前每个多边形都有索引顶点属性,我将其传递给 OpenGL 中的顶点着色器。我的目标是在深度上偏移多边形,其中最高索引始终位于较低索引的前面。我目前有这
我是一名优秀的程序员,十分优秀!