openGL系列文章目录
文章目录
- 效果
前言
术语Tessellation(镶嵌)是指一大类设计活动,通常是指在平坦的表面上,用各种几何
形状的瓷砖相邻排列以形成图案。它的目的可以是艺术性的或实用性的,很多例子可以追
溯到几千年前[TS16]。
在3D 图形学中,Tessellation 指的是有点不同的东西(曲面细分),但显然是由它的经典
对应物(镶嵌)启发而成的。在这里,曲面细分指的是生成并且操控大量三角形以渲染复
杂的形状和表面,尤其是使用硬件进行渲染。曲面细分是OpenGL 核心近期才增加的新功
能,在2010 年的4.0 版本中出现。①
一、OpenGL 中的曲面细分
OpenGL 对硬件曲面细分的支持,通过3 个管线阶段提供:
(1)曲面细分控制着色器;
(2)曲面细分器;
(3)曲面细分评估着色器。
第(1)和第(3)阶段是可编程的;而中间的第(2)阶段不是。为了使用曲面细分,
程序员通常会提供控制着色器和评估着色器。
曲面细分器(其全名是曲面细分图元生成器,或TPG)是硬件支持的引擎,可以生成固
定的三角形网格。②控制着色器允许我们配置曲面细分器要构建什么样的三角形网格。然后,
评估着色器允许我们以各种方式操控网格。然后,被操控过的三角形网格,会作为通过管
线前进的顶点的源数据。回想一下,在管线上,曲面细分着色器位于顶点着色器和几
何着色器阶段之间。
让我们从一个简单的应用程序开始,该应用程序只使用曲面细分器创建顶点的三角形网
格,然后在不进行任何操作的情况下显示它。为此,我们需要以下模块。
(1)C++/OpenGL 应用程序:
创建一个摄像机和相关的MVP 矩阵,视图(v)和投影(p)矩阵确定摄像机朝向,模
型(m)矩阵可用于修改网格的位置和方向。
(2)顶点着色器:
在这个例子中基本上什么都不做,顶点将在曲面细分器中生成。
(3)曲面细分控制着色器:
指定曲面细分器要构建的网格。
(4)曲面细分评估着色器:
将MVP 矩阵应用于网格中的顶点。
(5)片段着色器:
只需为每个像素输出固定颜色。
程序12.1 显示了整个应用程序的代码。即使像这样的简单示例也相当复杂,因此许多代
码元素都需要解释。请注意,这是我们第一次使用除顶点和片段着色器之外的组件构建
GLSL 渲染程序。因此,我们实现了createShaderProgram()的4 参数重载版本。
二、代码
1.主程序c++
// glm::value_ptr
// glm::translate, glm::rotate, glm::scale, glm::perspective
using namespace std;
float toRadians(float degrees) { return (degrees * 2.0f * 3.14159f) / 360.0f; }
//-------------------------------------------Utils util = Utils();
float cameraX, cameraY, cameraZ;
float terLocX, terLocY, terLocZ;
GLuint renderingProgram;
GLuint vao[numVAOs];
// variable allocation for display
GLuint mvpLoc;
int width, height;
float aspect;
glm::mat4 pMat, vMat, mMat, mvpMat;
float tessInner = 30.0f;
float tessOuter = 20.0f;
void init(GLFWwindow* window) {
renderingProgram = Utils::createShaderProgram("vertShader.glsl", "tessCShader.glsl", "tessEShader.glsl", "fragShader.glsl");
cameraX = 0.5f; cameraY = -0.5f; cameraZ = 2.0f;
terLocX = 0.0f; terLocY = 0.0f; terLocZ = 0.0f;
glfwGetFramebufferSize(window, &width, &height);
aspect = (float)width / (float)height;
pMat = glm::perspective(1.0472f, aspect, 0.1f, 1000.0f);
glGenVertexArrays(numVAOs, vao);
glBindVertexArray(vao[0]);
}
void display(GLFWwindow* window, double currentTime) {
glClear(GL_DEPTH_BUFFER_BIT);
glClear(GL_COLOR_BUFFER_BIT);
glUseProgram(renderingProgram);
vMat = glm::translate(glm::mat4(1.0f), glm::vec3(-cameraX, -cameraY, -cameraZ));
mMat = glm::translate(glm::mat4(1.0f), glm::vec3(terLocX, terLocY, terLocZ));
mMat = glm::rotate(mMat, toRadians(35.0f), glm::vec3(1.0f, 0.0f, 0.0f));
mvpMat = pMat * vMat * mMat;
mvpLoc = glGetUniformLocation(renderingProgram, "mvp_matrix");
glUniformMatrix4fv(mvpLoc, 1, GL_FALSE, glm::value_ptr(mvpMat));
glFrontFace(GL_CCW);
glPatchParameteri(GL_PATCH_VERTICES, 1);
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); // FILL or LINE
glDrawArrays(GL_PATCHES, 0, 1);
}
void window_size_callback(GLFWwindow* win, int newWidth, int newHeight) {
aspect = (float)newWidth / (float)newHeight;
glViewport(0, 0, newWidth, newHeight);
pMat = glm::perspective(1.0472f, aspect, 0.1f, 1000.0f);
}
int main(void) {
if (!glfwInit()) { exit(EXIT_FAILURE); }
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
GLFWwindow* window = glfwCreateWindow(800, 800, "Chapter12 - program1", NULL, NULL);
glfwMakeContextCurrent(window);
if (glewInit() != GLEW_OK) { exit(EXIT_FAILURE); }
glfwSwapInterval(1);
glfwSetWindowSizeCallback(window, window_size_callback);
init(window);
while (!glfwWindowShouldClose(window)) {
display(window, glfwGetTime());
glfwSwapBuffers(window);
glfwPollEvents();
}
glfwDestroyWindow(window);
glfwTerminate();
exit(EXIT_SUCCESS);
}
## 2.着色器
1.顶点着色器
```cpp
#version 430
uniform mat4 mvp_matrix;
void main(void)
{
}
2.片元着色器
out vec4 color;
uniform mat4 mvp_matrix;
void main(void)
{
color = vec4(1.0, 1.0, 0.0, 1.0);
}
3.曲面细分着色器
uniform mat4 mvp_matrix;
layout (vertices = 1) out;
void main(void)
{ gl_TessLevelOuter[0] = 6;
gl_TessLevelOuter[2] = 6;
gl_TessLevelOuter[1] = 6;
gl_TessLevelOuter[3] = 6;
gl_TessLevelInner[0] = 12;
gl_TessLevelInner[1] = 12;
}
layout (quads, equal_spacing, ccw) in;
uniform mat4 mvp_matrix;
void main (void)
{
float u = gl_TessCoord.x;
float v = gl_TessCoord.y;
gl_Position = mvp_matrix * vec4(u,0,v,1);
}
效果