Tessellation Shader的GLSL入门实现: 曲线

本文不作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的编译、链接等步骤,这里就省略不写了。




  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值