我刚开始使用OpenGL曲面细分并遇到了麻烦。我正在细分由一个顶点形成的一系列补丁。这些顶点/补丁以网格状结构构造,以后形成由Perlin Noise生成的地形。
我遇到的问题是从第二个补丁开始,之后每5个 th 补丁,有时会有很多细分(不是我配置的方式)但是大部分时间它根本没有被细分。
两个白色圆圈标记高度/过度镶嵌的色块。另请注意未分页补丁的模式。
奇怪的是它可以在我的Surface Pro 2(英特尔HD4400显卡)上运行,但在我的主台式电脑(AMD HD6950显卡)上有问题。硬件有可能坏吗?
vec4* patches = new vec4[m_patchesWidth * m_patchesDepth];
int c = 0;
for (unsigned int z = 0; z < m_patchesDepth; ++z) {
for (unsigned int x = 0; x < m_patchesWidth; ++x) {
patches[c] = vec4(x * 1.5f, 0, z * 1.5f, 1.0f);
c++;
}
}
m_fxTerrain->Apply();
glGenBuffers(1, &m_planePatches);
glBindBuffer(GL_ARRAY_BUFFER, m_planePatches);
glBufferData(GL_ARRAY_BUFFER, m_patchesWidth * m_patchesDepth * sizeof(vec4), patches, GL_STATIC_DRAW);
GLuint loc = m_fxTerrain->GetAttrib("posIn");
glEnableVertexAttribArray(loc);
glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, sizeof(vec4), nullptr);
delete(patches);
glPatchParameteri(GL_PATCH_VERTICES, 1);
glBindVertexArray(patches);
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
glDrawArrays(GL_PATCHES, 0, nrOfPatches);
#version 430 core
in vec4 posIn;
out gl_PerVertex {
vec4 gl_Position;
};
void main() {
gl_Position = posIn;
}
#version 430
#extension GL_ARB_tessellation_shader : enable
layout (vertices = 1) out;
uniform float OuterTessFactor;
uniform float InnerTessFactor;
out gl_PerVertex {
vec4 gl_Position;
} gl_out[];
void main() {
if (gl_InvocationID == 0) {
gl_TessLevelOuter[0] = OuterTessFactor;
gl_TessLevelOuter[1] = OuterTessFactor;
gl_TessLevelOuter[2] = OuterTessFactor;
gl_TessLevelOuter[3] = OuterTessFactor;
gl_TessLevelInner[0] = InnerTessFactor;
gl_TessLevelInner[1] = InnerTessFactor;
}
gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;
}
#version 430
#extension GL_ARB_tessellation_shader : enable
layout (quads, equal_spacing, ccw) in;
uniform mat4 ProjView;
uniform sampler2D PerlinNoise;
out vec3 PosW;
out vec3 Normal;
out vec4 ColorFrag;
out gl_PerVertex {
vec4 gl_Position;
};
void main() {
vec4 pos = gl_in[0].gl_Position;
pos.xz += gl_TessCoord.xy;
pos.y = texture2D(PerlinNoise, pos.xz / vec2(8, 8)).x * 10.0f - 10.0f;
Normal = vec3(0, 1, 0);
gl_Position = ProjView * pos;
PosW = pos.xyz;
ColorFrag = vec4(pos.x / 64.0f, 0.0f, pos.z / 64.0f, 1.0f);
}
#version 430 core
in vec3 PosW;
in vec3 Normal;
in vec4 ColorFrag;
in vec4 PosH;
out vec3 FragColor;
out vec3 FragNormal;
void main() {
FragNormal = Normal;
FragColor = ColorFrag.xyz;
}
我尝试对不同的曲面细分级别进行硬编码,但这没有帮助。我最近开始使用OpenGL,所以如果我做了一些愚蠢的事情,请告诉我。
那么有没有人知道可能导致某些补丁“闪烁”的原因是什么?
更新:我有一个朋友运行该项目,他得到了相同的闪烁曲面细分模式,但除了过度镶嵌细分外,根本没有绘制失败的补丁。他和我一样拥有相同的显卡(AMD HD6950)。
答案 0 :(得分:10)
您应该使用三角形/四边形曲面细分,其中每个贴片具有3或4个顶点。我可以看到,你使用四边形(我也使用它们)。在这种情况下,您可以这样设置:
glPatchParameteri(GL_PATCH_VERTICES,4);
glBindVertexArray(VertexArray);
(提示:对于您的地形使用drawelements,对于基于2D位移的网格使用更好的性能。)
在控件着色器中,使用
layout (vertices = 4) out;
因为你的补丁有4个控制点。订购仍然很重要(CCW / CW) 我个人不喜欢使用内置变量,因此对于顶点着色器,您可以将顶点数据发送到tesscontrol,如下所示:
layout (location = 0) out vec3 outPos;
....
outPos.xz = grid.xy;
outPos.y = noise(outPos.xz);
苔丝控制:
layout (location = 0) in vec3 inPos[]; //outPos (location = 0) from vertex shader
//'collects' the 4 control points to an array in the order they're sended
layout (location = 0) out vec3 outPos[]; //send the c.points to the ev. shader
...
gl_TessLevelOuter[0] = outt[0];
gl_TessLevelOuter[1] = outt[1];
gl_TessLevelOuter[2] = outt[2];
gl_TessLevelOuter[3] = outt[3];
gl_TessLevelInner[0] = inn[0];
gl_TessLevelInner[1] = inn[1];
outPos[ID] = inPos[ID];//gl_invocationID = ID
请注意,顶点和顶点数据都是一个数组。
tessev很简单:
layout (location = 0) in vec3 inPos[]; //the 4 control points
layout (location = 0) out vec3 outPos; //this is no longer array, next is the fragment shader
...
//edit: do not forgot to add the next line
layout (quads) in;
vec3 interpolate3D(vec3 v0, vec3 v1, vec3 v2, vec3 v3) //linear interpolation for x,y,z coords on the quad
{
return mix(mix(v0,v1,gl_TessCoord.x),mix(v3,v2,gl_TessCoord.x),gl_TessCoord.y);
};
...main{...
outPos = interpolate3D(inPos[0],inPos[1],inPos[2],inPos[3]); //the four control points of the quad. Every other point is linearly interpolated between them according to the TessCoord.
gl_Position = mvp * vec4(outPos,1.0f);
四元域的良好表示:http://ogldev.atspace.co.uk/www/tutorial30/tutorial30.html。
我认为问题在于你的单顶点补丁。我无法想象一个顶点路径如何被分成三角形,我不知道它是如何在另一个硬件上工作的。曲面细分用于将基元划分为其他简单基元,在OGL情况下为三角形,因为它可以由GPU轻松处理(3个点始终位于平面中)。因此,对于三角形,最小补丁顶点数应为3。我喜欢四边形,因为索引更简单,内存成本更低。在镶嵌过程中它也将被分成三角形。 http://www.informit.com/articles/article.aspx?p=2120983 此外,还有另一种类型,即等值线镶嵌。 (查看链接,第二个非常好。)
总而言之,尝试使用四边形或三角形,并将控制顶点设置为4(或3)。我的(相当复杂的)地形着色器在此处使用视锥体剔除,曲面细分着色器剔除基于geoclipmap的地形。此外,没有细分,它适用于顶点着色器中的顶点变形。也许这段代码的某些部分会很有用。 http://speedy.sh/TAvPR/gshader.txt
具有大约4像素/三角形的曲面细分的场景以75 FPS(具有fraps)运行,具有运行时正常计算和双三次平滑等。我正在使用AMD HD 5750.通过更好的代码和预先烘焙的法线,它仍然可以更快:D。 (运行最大120 w / o正常计算。)
哦,如果你在着色器中移动顶点,你只能发送x和z坐标。它也会更快。
很多顶点。