曲面细分着色器 - OpenGL

时间:2014-06-06 13:59:05

标签: opengl tessellation

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被列出两次?

2 个答案:

答案 0 :(得分:13)

  

我如何理解gl_TessLevelInnergl_TessLevelOuter

请参阅: gl_TessLevelInnergl_TessLevelOuterOpenGL Tessellation - Levels

正如其名称所暗示的那样,它们控制正在处理的图元的内部和外部曲面细分因子级别。下面的图片说明了各种内/外水平设置的结果。

enter image description here 资料来源:http://antongerdelan.net/opengl/tessellation.html


  

为什么索引0使用了两次?

它被使用了两次,因为它正在访问两个不同的对象。索引0的第一次使用是

gl_TessLevelInner[0]

,第二个是

gl_TessLevelOuter[0]

答案 1 :(得分:1)

对于三角形,前三个“外部” gl_TessLevelOuter []细分值均控制三角形的三个边之一的细分,而第四个值未使用。

仅使用第一个“内部” gl_TessLevelInner [0]值来确定内部三角形的细分。内部层次比外部层次更令人困惑,因此,看一幅图片比解释它更好。

这是与已接受答案相似的图像,但是内部值行标签已更正,并且您可以使用该程序尝试自己的值。

接受的答案上的图像源链接当前已断开(2019年5月)。加上标记为“内部镶嵌因子”的行被一减。第一行的内部镶嵌值实际上为零。

Triangle tessellation matrix

用于创建以上图像的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()