OGLES顶点着色器

顶点着色器在模型变换到裁剪空间阶段,主要进行几何变换和光照的计算,逐顶点颜色,法线和纹理坐标计算。

顶点着色器的输入包括

1)属性
2)统一变量和统一变量缓冲区
3)采样器
4)着色器程序

顶点着色器内建变量

1)内建特殊变量

gl_VertexID
gl_Position
gl_InstanceID
gl_PointSize
gl_FrontFacing是否是正面

2)内建统一状态

顶点着色器唯一可用的内建统一状态是窗口坐标中的深度范围。由内建统一变量:
gl_DepthRange给出,该声明内建定义为:
struct gl_DepthRangeParameters
{
highp float near;
highp float far;
highp float diff;// far - near
}
uniform gl_DepthRangeParameters gl_DepthRange;

3)内建常量

const mediump int gl_MaxVertexAttribs = 16;//16个vec4输入
const mediump int gl_MaxVertexUniformVectors = 256;
const mediump int gl_MaxVertexOutputVectors = 16; // 16个vec4
const mediump int gl_MaxVertexTextureImageUnits = 16; // 顶点着色器中用的纹理最大数
const mediump int gl_MaxCombinedTextureImageUnits = 32;// 顶点和片段中用的纹理最大数

顶点着色器的应用

1)光照的计算

分为平行光,点光源,聚光灯计算。
光源位置,方向,顶点位置方向,转换到统一的相对位置中,例如统一转换到世界坐标系或视图坐标系。
光源和材质的镜面反射,漫反射,环境光,还有材质高光光泽度,材质自发光。
在多光源光照下的计算,还要考虑点光源和聚光灯的衰减,阴影的作用,雾的作用。

2)纹理坐标生成

GL_SPHERE_MAP
GL_REFLECTION_MAP
GL_SPHERE_MAP计算方法为:
vec2 sphere_map(vec3 position, vec3 normal)
{
reflection = reflect(position, normal);
m = 2.0 * sqrt(reflection.x * reflection.x + reflection.y*reflection.y +
(reflection.z + 1) *(reflection.z + 1));
return vec2((reflection.x / m + 0.5), (reflection.y / m + 0.5));
}
GL_REFLECTION_MAP计算方法为:
vec3 cube_map(vec3 position, vec3 normal)
{
return reflect(position, normal);
}

3)骨骼蒙皮动画

顶点着色器骨骼动画,一般需要计算顶点位置和法向量位置,法向量一般用顶点变换矩阵即可(因为骨骼动画一般不包含非等比缩放),所以(M^-1)^T = M。

4 ) 变换反馈

使用变换反馈,可以将顶点着色器的输出到缓冲区对象中,缓冲区可作为后续绘图调用中顶点数据的来源,这种方法对于在GPU上执行动画而无需任何CPU干预的许多技术很有用,例如顶点动画或渲染到顶点缓冲区的物理学模拟。
// 1.设置顶点着色器相关顶点信息输出到指定的变换反馈缓冲区
glTransformFeedbackVaryings (GLuint program, GLsizei count, const GLchar *const*varyings, GLenum bufferMode);
例如:
const char *feedbackVaryings[5] =
{
"v_position",
"v_velocity",
"v_size",
"v_curtime",
"v_lifetime"
};
// Set the vertex shader outputs as transform feedback varyings
glTransformFeedbackVaryings ( userData->emitProgramObject, 5, feedbackVaryings, GL_INTERLEAVED_ATTRIBS );
// Link program must occur after calling glTransformFeedbackVaryings
glLinkProgram ( userData->emitProgramObject );
// 2.开始变换反馈绘制
glBeginTransformFeedback ( GL_POINTS );
glDrawArrays ( GL_POINTS, 0, NUM_PARTICLES );
glEndTransformFeedback();

// Create a sync object to ensure transform feedback results are completed before the draw that uses them.
userData->emitSync = glFenceSync ( GL_SYNC_GPU_COMMANDS_COMPLETE, 0 );
// 3.绑定自己的输出缓冲区到反馈缓冲区
// Set transform feedback buffer
glBindBuffer ( GL_TRANSFORM_FEEDBACK_BUFFER, dstVBO );
glBindBufferBase ( GL_TRANSFORM_FEEDBACK_BUFFER, 0, dstVBO );
// Restore state
// 4.禁止光栅化,避免片段着色器执行
glDisable ( GL_RASTERIZER_DISCARD );
glUseProgram ( 0 );
// 5.解绑定反馈缓冲区
glBindBufferBase ( GL_TRANSFORM_FEEDBACK_BUFFER, 0, 0 );
glBindBuffer ( GL_ARRAY_BUFFER, 0 );
glBindTexture ( GL_TEXTURE_3D, 0 );

// Block the GL server until transform feedback results are completed
glWaitSync ( userData->emitSync, 0, GL_TIMEOUT_IGNORED );
glDeleteSync ( userData->emitSync );
// 6.后续绘制设置使用输出数据
SetupVertexAttributes ( esContext, userData->particleVBOs[ userData->curSrcIndex ] );

5)顶点纹理

OES3.0顶点着色器中可以应用纹理,在用纹理数据处理顶点位置偏移的应用中很有用,类似地形和水面。
顶点着色器中执行纹理查找有一些限制:
细节层次不是隐含的计算。
不接受texture查找函数中的偏差参数。
基本纹理用于mip贴图纹理。
地形根据法线贴图进行凹凸设置:
void main()
{
v_color = a_color;
float displacement = texture(displacementMap, a_texcoord).a;
vec4 displaced_position = a_position + vec4(a_normal*displacement, 0.0);
gl_Position = u_mvpMatrix * displaced_position;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值