{"id":461,"date":"2022-01-28T23:03:55","date_gmt":"2022-01-28T15:03:55","guid":{"rendered":"http:\/\/liyanliang.net\/?p=461"},"modified":"2022-01-29T09:34:32","modified_gmt":"2022-01-29T01:34:32","slug":"geometryshaderbezier-curves","status":"publish","type":"post","link":"http:\/\/liyanliang.net\/index.php\/2022\/01\/28\/geometryshaderbezier-curves\/","title":{"rendered":"OpenGL\u51e0\u4f55\u7740\u8272\u5668\u5b9e\u73b0\u8d1d\u585e\u5c14\u66f2\u7ebf"},"content":{"rendered":"\n<p>\u51e0\u4f55\u7740\u8272\u5668 (GS) \u662f\u7528 GLSL \u7f16\u5199\u7684\u7740\u8272\u5668\u7a0b\u5e8f\uff0c\u7528\u4e8e\u63a7\u5236\u57fa\u5143\u7684\u5904\u7406\u3002\u51e0\u4f55\u7740\u8272\u5668\u4f4d\u4e8e\u9876\u70b9\u7740\u8272\u5668\uff08\u6216<a href=\"https:\/\/www.khronos.org\/opengl\/wiki\/Tessellation\">Tessellation<\/a> \u9636\u6bb5\uff09\u548c<a href=\"https:\/\/www.khronos.org\/opengl\/wiki\/Vertex_Post-Processing\">Vertex Post-Processing<\/a>\u9636\u6bb5\u4e4b\u95f4\u3002<\/p>\n\n\n\n<div class=\"wp-block-image is-style-default\"><figure class=\"aligncenter\"><img decoding=\"async\" src=\"https:\/\/liyanliangpublic.oss-cn-hongkong.aliyuncs.com\/img\/20220129093140.png\" alt=\"\"\/><figcaption>GLSL rendering pipeline<\/figcaption><\/figure><\/div>\n\n\n\n<p>\u672c\u6587\u5b9e\u73b0\u7684\u662f\u4e09\u6b21\u65b9\u8d1d\u585e\u5c14\u66f2\u7ebf\u3002<\/p>\n\n\n\n<p>P0\u3001P1\u3001P2\u3001P3\u56db\u4e2a\u70b9\u5728\u5e73\u9762\u6216\u5728\u4e09\u7ef4\u7a7a\u95f4\u4e2d\u5b9a\u4e49\u4e86\u4e09\u6b21\u65b9\u8d1d\u585e\u5c14\u66f2\u7ebf\u3002\u66f2\u7ebf\u8d77\u59cb\u4e8eP0\u8d70\u5411P1\uff0c\u5e76\u4eceP2\u7684\u65b9\u5411\u6765\u5230P3\u3002\u4e00\u822c\u4e0d\u4f1a\u7ecf\u8fc7P1\u6216P2\uff1b\u8fd9\u4e24\u4e2a\u70b9\u53ea\u662f\u5728\u90a3\u91cc\u63d0\u4f9b\u65b9\u5411\u8d44\u8baf\u3002P0\u548cP1\u4e4b\u95f4\u7684\u95f4\u8ddd\uff0c\u51b3\u5b9a\u4e86\u66f2\u7ebf\u5728\u8f6c\u800c\u8d8b\u8fdbP3\u4e4b\u524d\uff0c\u8d70\u5411P2\u65b9\u5411\u7684\u201c\u957f\u5ea6\u6709\u591a\u957f\u201d\u3002<\/p>\n\n\n\n<p>\u66f2\u7ebf\u7684\u53c2\u6570\u5f62\u5f0f\u4e3a\uff1a<\/p>\n\n\n\n<figure class=\"wp-block-image is-style-default\"><img decoding=\"async\" src=\"https:\/\/liyanliangpublic.oss-cn-hongkong.aliyuncs.com\/img\/20220128215114.png\" alt=\"\"\/><\/figure>\n\n\n\n<figure class=\"wp-block-image is-style-default\"><img decoding=\"async\" src=\"https:\/\/liyanliangpublic.oss-cn-hongkong.aliyuncs.com\/img\/20220128224640.png\" alt=\"\"\/><\/figure>\n\n\n\n<p>\u9700\u8981\u6ce8\u610f\u7684\u662f\uff0c\u663e\u5361\u4f1a\u5f71\u54cd\u66f2\u7ebf\u7684\u7ed8\u5236\u6548\u679c\uff0c\u5982\u679c\u4f7f\u7528\u7684\u662f\u96c6\u4e2d\u663e\u5361\uff0c\u5efa\u8bae\u5207\u6362\u4e3a\u72ec\u7acb\u663e\u5361\u3002<\/p>\n\n\n\n<p><strong>lines_adjacency:<\/strong><\/p>\n\n\n\n<figure class=\"wp-block-image is-style-default\"><img decoding=\"async\" src=\"https:\/\/liyanliangpublic.oss-cn-hongkong.aliyuncs.com\/img\/20220128224850.png\" alt=\"\"\/><\/figure>\n\n\n\n<p><strong>line_strip:<\/strong><\/p>\n\n\n\n<figure class=\"wp-block-image is-style-default\"><img decoding=\"async\" src=\"https:\/\/liyanliangpublic.oss-cn-hongkong.aliyuncs.com\/img\/20220128225006.png\" alt=\"\"\/><\/figure>\n\n\n\n<p><strong>geometry_shader_bezier.vs<\/strong><\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"cpp\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">  #version 330 core\n  layout (location = 0) in vec3 aPos;\n  \u200b\n  uniform mat4 model;\n  uniform mat4 view;\n  uniform mat4 projection;\n  \u200b\n  void main()\n  {\n      gl_Position = vec4(aPos, 1.0); \n  }<\/pre>\n\n\n\n<p><strong>geometry_shader_bezier.gs<\/strong><\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"cpp\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">  #version 330 core\n   \n  layout (lines_adjacency) in; \/\/\u57fa\u5143\u7c7b\u578b\u6a21\u5f0flines_adjacency,\u8f93\u5165\u56fe\u5143\u90bb\u63a5\u7ebf\uff0c\u8f93\u5165\u6570\u7ec4gl_in[]\u5927\u5c0f\u4e3a4\uff0c\u521a\u597d\u7ed8\u5236\u4e09\u6b21bezier\u66f2\u7ebf\u9700\u8981\u56db\u4e2a\u63a7\u5236\u70b9\n  layout (line_strip, max_vertices = 200) out; \/\/\u5c06\u4e00\u4e2a\u70b9\u53d8\u4e3a\u6700\u591a32\u4e2a\u53ef\u8fde\u6210\u7ebf\u6761\u7684\u70b9 \u4ea4\u7ed9FragShader\n  \u200b\n  uniform mat4 model;\n  uniform mat4 view;\n  uniform mat4 projection;\n  \u200b\n  void creatBezier(){\n     int segments = 1000;\n     float delta = 1.0 \/ float(segments);\n     vec4 v;\n     for ( int i=0; i&lt;=segments; ++i )\n     {\n          float   t   =   delta * float(i);\/\/\u63d2\u503c\u8ba1\u7b97\u53c2\u6570t\u4e0esegment\u5173\u8054\u8d77\u6765\n          vec3    p0  =   gl_in[0].gl_Position.xyz;   \n          vec3    p1  =   gl_in[1].gl_Position.xyz;   \n          vec3    p2  =   gl_in[2].gl_Position.xyz;   \n          vec3    p3  =   gl_in[3].gl_Position.xyz;   \n          float   len =   length(p1 - p0)\/2.0;   \n          \/\/ Linear interpolation \n          vec3    p;  \n          p.x = (1 - t) * (1 - t) * (1 - t) * p0.x + 3 * t * (1 - t) * (1 - t)* p1.x + 3 * t*t* (1 - t)* p2.x + t * t * t * p3.x;\n          p.y = (1 - t) * (1 - t) * (1 - t) * p0.y + 3 * t * (1 - t) * (1 - t)* p1.y + 3 * t*t* (1 - t)* p2.y + t * t * t * p3.y;\n          p.z =   0;\n          gl_Position = projection * view * model * vec4(p, 1); \n         EmitVertex();\n    }\n  }\n   \n  void main(){\n      creatBezier();\n  }\n  \u200b<\/pre>\n\n\n\n<p><strong>geometry_shader_bezier.fs<\/strong><\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"cpp\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">  #version 330 core\n  out vec4 FragColor;\n  \u200b\n  void main()\n  {\n      FragColor = vec4(1.0, 0.0, 0.0, 1.0);   \n  }<\/pre>\n\n\n\n<p><strong>main.cpp<\/strong><\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"cpp\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">  #include &lt;glad\/glad.h>\n  #include &lt;GLFW\/glfw3.h>\n  #include &lt;glm\/glm.hpp>\n  #include &lt;learnopengl\/camera.h>\n  \u200b\n  #include &lt;learnopengl\/shader.h>\n  \u200b\n  #include &lt;iostream>\n  \u200b\n  void framebuffer_size_callback(GLFWwindow* window, int width, int height);\n  \u200b\n  \/\/ settings\n  const unsigned int SCR_WIDTH = 800;\n  const unsigned int SCR_HEIGHT = 600;\n  \u200b\n  Camera camera(glm::vec3(0.0f, 0.0f, 3.0f));\n  \u200b\n  int main()\n  {\n      \/\/ glfw: initialize and configure\n      \/\/ ------------------------------\n      glfwInit();\n      glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);\n      glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);\n      glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);\n  \u200b\n  #ifdef __APPLE__\n      glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);\n  #endif\n  \u200b\n      \/\/ glfw window creation\n      \/\/ --------------------\n      GLFWwindow* window = glfwCreateWindow(SCR_WIDTH, SCR_HEIGHT, \"LearnOpenGL\", NULL, NULL);\n      if (window == NULL)\n      {\n          std::cout &lt;&lt; \"Failed to create GLFW window\" &lt;&lt; std::endl;\n          glfwTerminate();\n          return -1;\n      }\n      glfwMakeContextCurrent(window);\n  \u200b\n      \/\/ glad: load all OpenGL function pointers\n      \/\/ ---------------------------------------\n      if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))\n      {\n          std::cout &lt;&lt; \"Failed to initialize GLAD\" &lt;&lt; std::endl;\n          return -1;\n      }\n  \u200b\n      \/\/ configure global opengl state\n      \/\/ -----------------------------\n      glEnable(GL_DEPTH_TEST);\n  \u200b\n      \/\/ build and compile shaders\n      \/\/ -------------------------\n      Shader shader(\"geometry_shader_bezier.vs\", \"geometry_shader_bezier.fs\", \"geometry_shader_bezier.gs\");\n  \u200b\n      \/\/ set up vertex data (and buffer(s)) and configure vertex attributes\n      \/\/ ------------------------------------------------------------------\n      float points[] = {\n          0.1f, 0.1f, 0.0f,\n          1.0f, 1.0f, 0.0f,\n          2.0f, 0.1f, 0.0f,\n          3.0f, 1.5f, 0.0f,\n      };\n      unsigned int VBO, VAO;\n      glGenBuffers(1, &amp;VBO);\n      glGenVertexArrays(1, &amp;VAO);\n      glBindVertexArray(VAO);\n      glBindBuffer(GL_ARRAY_BUFFER, VBO);\n      glBufferData(GL_ARRAY_BUFFER, sizeof(points), &amp;points, GL_STATIC_DRAW);\n      glEnableVertexAttribArray(0);\n      glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), 0);\n      glBindVertexArray(0);\n  \u200b\n      \/\/ render loop\n      \/\/ -----------\n      while (!glfwWindowShouldClose(window))\n      {\n          \/\/ render\n          \/\/ ------\n          glClearColor(0.1f, 0.1f, 0.1f, 1.0f);\n          glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);\n  \u200b\n          \/\/ draw points\n          shader.use();\n          glm::mat4 projection = glm::perspective(glm::radians(camera.Zoom), (float)SCR_WIDTH \/ (float)SCR_HEIGHT, 0.1f, 100.0f);\n          glm::mat4 view = camera.GetViewMatrix();\n          glm::mat4 model = glm::mat4(1.0f);\n          shader.setMat4(\"projection\", projection);\n          shader.setMat4(\"view\", view);\n          shader.setMat4(\"model\", model);\n  \u200b\n          glBindVertexArray(VAO);\n          glDrawArrays(GL_LINES_ADJACENCY, 0, 4);\n  \u200b\n          \/\/ glfw: swap buffers and poll IO events (keys pressed\/released, mouse moved etc.)\n          \/\/ -------------------------------------------------------------------------------\n          glfwSwapBuffers(window);\n          glfwPollEvents();\n      }\n  \u200b\n      \/\/ optional: de-allocate all resources once they've outlived their purpose:\n      \/\/ ------------------------------------------------------------------------\n      glDeleteVertexArrays(1, &amp;VAO);\n      glDeleteBuffers(1, &amp;VBO);\n  \u200b\n      glfwTerminate();\n      return 0;\n  }\n  \u200b\n  \/\/ glfw: whenever the window size changed (by OS or user resize) this callback function executes\n  \/\/ ---------------------------------------------------------------------------------------------\n  void framebuffer_size_callback(GLFWwindow* window, int width, int height)\n  {\n      \/\/ make sure the viewport matches the new window dimensions; note that width and \n      \/\/ height will be significantly larger than specified on retina displays.\n      glViewport(0, 0, width, height);\n  }\n  \u200b<\/pre>\n\n\n\n<p><strong>\u6548\u679c\uff1a<\/strong><\/p>\n\n\n\n<figure class=\"wp-block-image is-style-default\"><img decoding=\"async\" src=\"https:\/\/liyanliangpublic.oss-cn-hongkong.aliyuncs.com\/img\/20220128223606.png\" alt=\"\"\/><\/figure>\n\n\n\n<p>\u5b8c\u6574\u9879\u76ee\u4ee3\u7801\uff1a<\/p>\n\n\n\n<p><a href=\"https:\/\/github.com\/mc-liyanliang\/OpenGL-Shader\/tree\/master\">https:\/\/github.com\/mc-liyanliang\/OpenGL-Shader\/tree\/master<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>\u51e0\u4f55\u7740\u8272\u5668 (GS) \u662f\u7528 GLSL \u7f16\u5199\u7684\u7740\u8272\u5668\u7a0b\u5e8f\uff0c\u7528\u4e8e\u63a7\u5236\u57fa\u5143\u7684\u5904\u7406\u3002\u51e0\u4f55\u7740\u8272\u5668\u4f4d\u4e8e\u9876\u70b9\u7740\u8272\u5668\uff08\u6216Tessellation \u9636\u6bb5\uff09\u548cVertex Post-Processing\u9636\u6bb5\u4e4b\u95f4\u3002 \u672c\u6587\u5b9e\u73b0\u7684\u662f\u4e09\u6b21\u65b9\u8d1d\u585e\u5c14\u66f2\u7ebf\u3002 P0\u3001P1\u3001P2\u3001P3\u56db\u4e2a\u70b9\u5728\u5e73\u9762\u6216\u5728\u4e09\u7ef4\u7a7a\u95f4\u4e2d\u5b9a\u4e49\u4e86\u4e09\u6b21\u65b9\u8d1d\u585e\u5c14\u66f2\u7ebf\u3002\u66f2\u7ebf\u8d77\u59cb\u4e8eP0\u8d70\u5411P1\uff0c\u5e76\u4eceP2\u7684\u65b9\u5411\u6765\u5230P3\u3002\u4e00\u822c\u4e0d\u4f1a\u7ecf\u8fc7P1\u6216P2\uff1b\u8fd9\u4e24\u4e2a\u70b9\u53ea\u662f\u5728\u90a3\u91cc\u63d0\u4f9b\u65b9\u5411\u8d44\u8baf\u3002P0\u548cP1\u4e4b\u95f4\u7684\u95f4\u8ddd\uff0c\u51b3\u5b9a\u4e86\u66f2\u7ebf\u5728\u8f6c\u800c\u8d8b\u8fdbP3\u4e4b\u524d\uff0c\u8d70\u5411P2\u65b9\u5411\u7684\u201c\u957f\u5ea6\u6709\u591a\u957f\u201d\u3002 \u66f2\u7ebf\u7684\u53c2\u6570\u5f62\u5f0f\u4e3a\uff1a \u9700\u8981\u6ce8\u610f\u7684\u662f\uff0c\u663e\u5361\u4f1a\u5f71\u54cd\u66f2\u7ebf\u7684\u7ed8\u5236\u6548\u679c\uff0c\u5982\u679c\u4f7f\u7528\u7684\u662f\u96c6\u4e2d\u663e\u5361\uff0c\u5efa\u8bae\u5207\u6362\u4e3a\u72ec\u7acb\u663e\u5361\u3002 lines_adjacency: line_strip: geometry_shader_bezier.vs geometry_shader_bezier.gs geometry_shader_bezier.fs main.cpp \u6548\u679c\uff1a \u5b8c\u6574\u9879\u76ee\u4ee3\u7801\uff1a https:\/\/github.com\/mc-liyanliang\/OpenGL-Shader\/tree\/master<\/p>\n","protected":false},"author":1,"featured_media":459,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1,14],"tags":[50],"class_list":["post-461","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-c","category-opengl","tag-bezier-curves"],"_links":{"self":[{"href":"http:\/\/liyanliang.net\/index.php\/wp-json\/wp\/v2\/posts\/461","targetHints":{"allow":["GET"]}}],"collection":[{"href":"http:\/\/liyanliang.net\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/liyanliang.net\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/liyanliang.net\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/liyanliang.net\/index.php\/wp-json\/wp\/v2\/comments?post=461"}],"version-history":[{"count":2,"href":"http:\/\/liyanliang.net\/index.php\/wp-json\/wp\/v2\/posts\/461\/revisions"}],"predecessor-version":[{"id":464,"href":"http:\/\/liyanliang.net\/index.php\/wp-json\/wp\/v2\/posts\/461\/revisions\/464"}],"wp:featuredmedia":[{"embeddable":true,"href":"http:\/\/liyanliang.net\/index.php\/wp-json\/wp\/v2\/media\/459"}],"wp:attachment":[{"href":"http:\/\/liyanliang.net\/index.php\/wp-json\/wp\/v2\/media?parent=461"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/liyanliang.net\/index.php\/wp-json\/wp\/v2\/categories?post=461"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/liyanliang.net\/index.php\/wp-json\/wp\/v2\/tags?post=461"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}