layout (vertices = 3) out;
void main(void)
{
if (gl_InvocationID == 0)
{
gl_TessLevelInner[0] = 5.0;
gl_TessLevelOuter[0] = 5.0;
gl_TessLevelOuter[1] = 5.0;
gl_TessLevelOuter[2] = 5.0;
}
gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;
}
摘自:Haemel,Nicholas。 “OpenGL SuperBible:
我如何理解TessLevelInner和Outer以及为什么id 0被列出两次?
答案 0 :(得分:13)
我如何理解
gl_TessLevelInner
和gl_TessLevelOuter
?
请参阅:
gl_TessLevelInner
,gl_TessLevelOuter
,OpenGL Tessellation - Levels
正如其名称所暗示的那样,它们控制正在处理的图元的内部和外部曲面细分因子级别。下面的图片说明了各种内/外水平设置的结果。
资料来源:http://antongerdelan.net/opengl/tessellation.html
为什么索引
0
使用了两次?
它被使用了两次,因为它正在访问两个不同的对象。索引0
的第一次使用是
gl_TessLevelInner[0]
,第二个是
gl_TessLevelOuter[0]
答案 1 :(得分:1)
对于三角形,前三个“外部” gl_TessLevelOuter []细分值均控制三角形的三个边之一的细分,而第四个值未使用。
仅使用第一个“内部” gl_TessLevelInner [0]值来确定内部三角形的细分。内部层次比外部层次更令人困惑,因此,看一幅图片比解释它更好。
这是与已接受答案相似的图像,但是内部值行标签已更正,并且您可以使用该程序尝试自己的值。
接受的答案上的图像源链接当前已断开(2019年5月)。加上标记为“内部镶嵌因子”的行被一减。第一行的内部镶嵌值实际上为零。
用于创建以上图像的Python程序:
import inspect, glfw, numpy
from OpenGL.GL import *
from OpenGL.GL import shaders
glfw.init()
tile_size, tile_count = 80, 8
width = tile_size * tile_count
glfw.window_hint(glfw.SAMPLES, 16)
window = glfw.create_window(width, width, 'tessellation demo', None, None)
glfw.make_context_current(window)
glBindVertexArray(glGenVertexArrays(1))
triangle = numpy.array([
[-0.9, -0.9, 0.5], # lower left
[ 0.9, -0.9, 0.5], # lower right
[ 0.0, 0.9, 0.5], # top
], dtype=numpy.float32)
glBindBuffer(GL_ARRAY_BUFFER, glGenBuffers(1))
glBufferData(GL_ARRAY_BUFFER, triangle, GL_STATIC_DRAW)
glEnableVertexAttribArray(0)
glVertexAttribPointer(index=0, size=3, type=GL_FLOAT, normalized=False, stride=0, pointer=None)
program = shaders.compileProgram(
shaders.compileShader(source=inspect.cleandoc('''
#version 460 core
in vec3 aPos;
void main() {
gl_Position = vec4(aPos, 1);
}
'''), shaderType=GL_VERTEX_SHADER),
# Tessellation control shader not defined here because default is OK.
shaders.compileShader(source=inspect.cleandoc('''
#version 460 core
layout(triangles) in;
void main() {
gl_Position = (gl_TessCoord.x * gl_in[0].gl_Position) +
(gl_TessCoord.y * gl_in[1].gl_Position) +
(gl_TessCoord.z * gl_in[2].gl_Position);
}
'''), shaderType=GL_TESS_EVALUATION_SHADER),
shaders.compileShader(source=inspect.cleandoc('''
#version 460 core
out vec4 fragColor;
void main() {
fragColor = vec4(vec3(0.1), 1); // dark gray
}
'''), shaderType=GL_FRAGMENT_SHADER),)
glUseProgram(program)
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE)
glPatchParameteri(GL_PATCH_VERTICES, 3)
glClearColor(0.95, 0.95, 0.95, 1) # pale gray
outer_levels = numpy.array([1, 1, 1, 1], dtype=numpy.float32)
inner_levels = numpy.array([1, 1], dtype=numpy.float32)
while not glfw.window_should_close(window):
glClear(GL_COLOR_BUFFER_BIT)
for outer in range(tile_count + 1): # increase outer tessellation factors left to right
for inner in range(tile_count + 1): # inner tesselation factors top to bottom
glViewport(outer * tile_size, width - inner * tile_size, tile_size, tile_size)
outer_levels[:] = [outer + 1] * 4 # range 1 to 9; zero means no triangles at all
inner_levels[:] = [inner] * 2 # range 0 to 8
glPatchParameterfv(GL_PATCH_DEFAULT_OUTER_LEVEL, outer_levels)
glPatchParameterfv(GL_PATCH_DEFAULT_INNER_LEVEL, inner_levels)
glDrawArrays(GL_PATCHES, 0, 3)
glfw.swap_buffers(window)
glfw.poll_events()
glfw.terminate()