您的位置:首页 > 其它

Tessellation Shader的GLSL入门实现: 曲线

2013-04-12 20:41 393 查看
本文不作Tessellation Shader的基本介绍。直接给出细分曲线的”Hellow World“代码。

下面代码将使用Tessellation Shader,传入2个控制点的情况下绘制一条正弦曲线连接这2个控制点。

效果如下图:(细分数目分别为1,8,32)







Vertex Shader:

#version 400
layout (location = 0) in vec3 in_Vertex;
uniform mat4  ModelViewProjectionMatrix;

void main()
{
gl_Position    = vec4(in_Vertex, 1);
}
就这么简单。Vertex Shader原封不动的把传入的点传给下一道渲染工序:Tessellation Control Shader。

Tessellation Control Shader(TCS):

#version 400
layout( vertices=4 ) out;
void main()
{
// Pass along the vertex position unmodified
gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;

gl_TessLevelOuter[0] = float(1);
gl_TessLevelOuter[1] = float(32);
}
Tessellation Control Shader干了两件事情。

第一:把输入的控制点的坐标信息(gl_in[gl_InvocationID].gl_Position)原封不动的输出。

第二:设置了细分控制参数。对于不同的细分类型(这里是曲线细分,会在下一个shader中看到细分类型的选择),这2个参数意义不一样。

gl_TessLevelOuter[0]表示要生成几条曲线。这里我们选择1条。

gl_TessLevelOuter[1] 表示将曲线细分成几段。这个很是决定细分程度的关键参数。我们分别使用1、8、32测试。

【注意】gl_TessLevelOuter[0]与gl_TessLevelOuter[1]的意义,在ATI显卡和NV显卡中是相反的!我这里以NV的卡为例。

Tessellation Evaluation Shader(TES):

#version 400
layout( isolines ) in;
uniform mat4 ModelViewProjectionMatrix;
void main()
{
float u    = gl_TessCoord.x;
vec3  p0   = gl_in[0].gl_Position.xyz;
vec3  p1   = gl_in[1].gl_Position.xyz;
float leng = length(p1 - p0)/2.0;
// Linear interpolation
vec3 p;
p.x	= p0.x*u + p1.x*(1-u);
p.y	= p0.y + leng*sin(u*2*3.1415);
// Transform to clip coordinates
gl_Position = ModelViewProjectionMatrix * vec4(p, 1);
}


这里就是最关键的细分曲线算法了。

首先看到layout( isolines ) 的申明。这就告诉了TES我们使用的细分类型为曲线。这样,这里的gl_TessCoord.x,对于曲线来说我们只用到x分量就够了,他的取值范围在[0, 1]之间自动插值(根据Tessellation Control Shader中设置的分段数)

对于传入的2个控制点p0和p1,我们计算两点之间的长度,然后使用[0, 2*pi]区间,绘制一条正弦曲线。最后进行MVP坐标转换输出。

Fragment Shader

#version 400

void main()
{
gl_FragColor = vec4(1, 0, 0, 1.0);
}
这个不是关键,能多简单我就多简单了。

OpenGL代码:

pShader->sendUniform(string("ModelViewProjectionMatrix"), value_ptr(matMVP2));
gl::BindVertexArray(_vertexArrayBlock);
gl::EnableVertexAttribArray(0);

gl::PatchParameteri(GL_PATCH_VERTICES, 2);
gl::DrawArrays(GL_PATCHES, 0, 2);

gl::BindVertexArray(0);
gl::DisableVertexAttribArray(0);


这里看到绘制类型一定只能为GL_PATCHES,另外注意设置Patch参数为GL_PATCH_VERTICES。由于只有2个控制点,DrawArrays传递参数2.

【注】2个控制点的VBO或者VAO的设置,以及4个Shader的编译、链接等步骤,这里就省略不写了。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: