最简单的曲面细分着色器(Tesselation Shader)【OpenGL】【GLSL】


效果如图:


最简单的曲面细分着色器(Tesselation Shader)【OpenGL】【GLSL】_第1张图片


按 ‘m’ 键后

最简单的曲面细分着色器(Tesselation Shader)【OpenGL】【GLSL】_第2张图片


代码及详细注释如下

GLuint program;
GLuint vao;

void startup()
{
	static const char * vs_source[] =
	{
		"#version 410 core                                                 \n"
		"                                                                  \n"
		"void main(void)                                                   \n"
		"{                                                                 \n"
		"    const vec4 vertices[] = vec4[](vec4( 0.25, -0.25, 0.5, 1.0),  \n"
		"                                   vec4(-0.25, -0.25, 0.5, 1.0),  \n"
		"                                   vec4( 0.25,  0.25, 0.5, 1.0)); \n"
		"                                                                  \n"
		"    gl_Position = vertices[gl_VertexID];                          \n"	// 根据当前处理的顶点 ID 为顶点位置赋值
		"}                                                                 \n"
	};

	// http://www.cnblogs.com/zenny-chen/p/4280100.html
	static const char * tcs_source[] =
	{
		"#version 410 core                                                                 \n"
		"                                                                                  \n"
		"layout (vertices = 3) out;                                                        \n"	// out-patch 的顶点个数,细分控制着色器将会被执行3次
		"                                                                                  \n"
		"void main(void)                                                                   \n"
		"{                                                                                 \n"	// 仅在第一次执行(第一个顶点)时赋值(控制细分程度)
		"    if (gl_InvocationID == 0)                                                     \n"
		"    {                                                                             \n"	
		"        gl_TessLevelInner[0] = 5.0;                                               \n"	// 内部划分5个区域(新增4排顶点,见下图)
		"        gl_TessLevelOuter[0] = 5.0;                                               \n"	// 左边划分5段
		"        gl_TessLevelOuter[1] = 5.0;                                               \n"	// 右边划分5段
		"        gl_TessLevelOuter[2] = 5.0;                                               \n"	// 下边划分5段
		"    }                                                                             \n"
		"    gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;     \n"	// 通常直接将 in-patch 顶点赋给 out-patch 顶点(也可以新建或移除)
		"}                                                                                 \n"
	};

	static const char * tes_source[] =
	{
		"#version 410 core                                                                 \n"
		"                                                                                  \n"
		"layout (triangles, equal_spacing, cw) in;                                         \n"	 // 指定图元生成域、细分坐标空间、图元的面朝向 
		//"layout (triangles, equal_spacing, cw, point_mode) in;                             \n" // 输出点模式
		"                                                                                  \n"
		"void main(void)                                                                   \n"
		"{                                                                                 \n"  
		"    gl_Position = (gl_TessCoord.x * gl_in[0].gl_Position) +                       \n"	// gl_TessCoord:细分后的新增坐标(插值比例)
		"                  (gl_TessCoord.y * gl_in[1].gl_Position) +                       \n"	// 根据 input-patch 生成输出顶点的位置
		"                  (gl_TessCoord.z * gl_in[2].gl_Position);                        \n"  // 每个细分坐标都会让 TES 的执行一次
		"}                                                                                 \n"
	};

	static const char * fs_source[] =
	{
		"#version 410 core                                                 \n"
		"                                                                  \n"
		"out vec4 color;                                                   \n"
		"                                                                  \n"
		"void main(void)                                                   \n"
		"{                                                                 \n"
		"    color = vec4(0.0, 0.8, 1.0, 1.0);                             \n"
		"}                                                                 \n"
	};

	program = glCreateProgram();
	GLuint vs = glCreateShader(GL_VERTEX_SHADER);
	glShaderSource(vs, 1, vs_source, NULL);
	glCompileShader(vs);

	// Tesselation Control Shader
	GLuint tcs = glCreateShader(GL_TESS_CONTROL_SHADER);
	glShaderSource(tcs, 1, tcs_source, NULL);
	glCompileShader(tcs);

	// Tesselation Evaluation Shader
	GLuint tes = glCreateShader(GL_TESS_EVALUATION_SHADER);
	glShaderSource(tes, 1, tes_source, NULL);
	glCompileShader(tes);

	GLuint fs = glCreateShader(GL_FRAGMENT_SHADER);
	glShaderSource(fs, 1, fs_source, NULL);
	glCompileShader(fs);

	glAttachShader(program, vs);
	glAttachShader(program, tcs);
	glAttachShader(program, tes);
	glAttachShader(program, fs);

	glLinkProgram(program);

	glGenVertexArrays(1, &vao);
	glBindVertexArray(vao);

	glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
}

void render()
{
	static const GLfloat green[] = { 0.0f, 0.25f, 0.0f, 1.0f };
	glClearBufferfv(GL_COLOR, 0, green);

	glUseProgram(program);
	glDrawArrays(GL_PATCHES, 0, 3);

	glutSwapBuffers();
}

void shutdown()
{
	glDeleteVertexArrays(1, &vao);
	glDeleteProgram(program);
}

void reshape(int width, int height)
{
	glViewport(0, 0, width, height);
	GLfloat  aspect = GLfloat(width) / height;

	//glutPostRedisplay();
}

void keyboard(unsigned char key, int x, int y)
{
	switch (key)
	{
		case 'q': case 'Q': case 033 /* Escape key */:
			exit(EXIT_SUCCESS);
			break;

		case 'm':	// 切换填充模式或镂空模式
		{
			static GLenum mode = GL_FILL;
			mode = (mode == GL_FILL ? GL_LINE : GL_FILL);
			glPolygonMode(GL_FRONT_AND_BACK, mode);
			break;
		}
		
	}

	glutPostRedisplay();
}


int _tmain(int argc, char* argv[])
{
	glutInit(&argc, argv);
	glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA /*| GLUT_STENCIL | GLUT_DEPTH*/);
	glutInitWindowPosition(100, 100);
	glutInitWindowSize(512, 512);
	glutCreateWindow("TesselateTri"); // get an openGL context

	GLenum err = glewInit(); // init glew
	if (err != GLEW_OK)
	{
		fprintf(stderr, "Error: %s\n", glewGetErrorString(err));
		exit(-2);
	}

	startup();

	glutDisplayFunc(render);
	glutReshapeFunc(reshape);
	glutKeyboardFunc(keyboard);

	glutMainLoop();

	return 0;
}


内部新增的4排顶点示意图

最简单的曲面细分着色器(Tesselation Shader)【OpenGL】【GLSL】_第3张图片




你可能感兴趣的:(OpenGL,Shader)