OpenGL 入门 2:渲染管线与着色器

一、渲染管线

1.顶点着色器(Vertex Shader):它把一个单独的顶点作为输入。顶点着色器主要的目的是把3D坐标转为另一种3D坐标,同时顶点着色器允许我们对顶点属性进行一些基本处理。

2. 图元装配(Primitive Assembly):将顶点着色器输出的所有顶点作为输入(如果是GL_POINTS,那么就是一个顶点),并所有的点装配成指定图元的形状;本节例子中是一个三角形。

3. 几何着色器(Geometry Shader):几何着色器把图元形式的一系列顶点的集合作为输入,它可以通过产生新顶点构造出新的(或是其它的)图元来生成其他形状。例子中,它生成了另一个三角形。

4. 光栅化阶段(Rasterization Stage):这里它会把图元映射为最终屏幕上相应的像素,生成供片段着色器使用的片段(Fragment)。在片段着色器运行之前会执行裁切(Clipping)。裁切会丢弃超出你的视图以外的所有像素,用来提升执行效率。

5. 片段着色器(Fragment Shader):其主要目的是计算一个像素的最终颜色,这也是所有OpenGL高级效果产生的地方。通常,片段着色器包含3D场景的数据(比如光照、阴影、光的颜色等等),这些数据可以被用来计算最终像素的颜色。

6. Alpha测试和混合(Blending):这个阶段检测片段的对应的深度(和模板(Stencil))值(后面会讲),用它们来判断这个像素是其它物体的前面还是后面,决定是否应该丢弃。这个阶段也会检查alpha值(alpha值定义了一个物体的透明度)并对物体进行混合(Blend)。所以,即使在片段着色器中计算出来了一个像素输出的颜色,在渲染多个三角形的时候最后的像素颜色也可能完全不同。

二、顶点着色器

#version 330 core
layout (location = 0) in vec3 aPos;

void main()
{
    gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0);
}
  • 版本声明,OpenGL 3.3以及和更高版本中,GLSL版本号和OpenGL的版本是匹配的(比如说GLSL 420版本对应于OpenGL 4.2),同样明确表示我们会使用核心模式。

  • 使用in关键字声明所有的输入顶点属性(Input Vertex Attribute),通过layout (location = 0)设定了输入变量的位置值(Location),在进入顶点着色器前,会加载所有顶点进入GPU中,并会解释内存中的顶点数据,此时会设置相应顶点属性的location,因此与顶点着色器中输入属性的location需相对应。

  • gl_Position变量为预定义的位置数据,其是vec4类型。

三、片元着色器

#version 330 core
out vec4 FragColor;

void main()
{
    FragColor = vec4(1.0f, 0.5f, 0.2f, 1.0f);
} 
  • 使用out关键字定义输出属性。

  • FrageColor代表最终输出的颜色。

四、编译着色器

const char *vertexShaderSource = "#version 330 core\n"
    "layout (location = 0) in vec3 aPos;\n"
    "void main()\n"
    "{\n"
    "   gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0);\n"
    "}\0";

将顶点着色器(片元着色器)的源代码硬编码在代码文件顶部的C风格字符串中。

unsigned int vertexShader;
vertexShader = glCreateShader(GL_VERTEX_SHADER); //GL_FRAGMENT_SHADER
glShaderSource(vertexShader, 1, &vertexShaderSource, NULL);
glCompileShader(vertexShader);
  • 用unsigned int类型的ID来引用着色器对象。

  • glCreateShader创建指定类型的着色器对象。GL_VERTEX_SHADER 或者 GL_FRAGMENT_SHADER

  • glShaderSource把着色器源码附加到着色器对象上。着色器对象作为第一个参数。第二参数指定了传递的源码字符串数量,这里只有一个。第三个参数是顶点着色器真正的源码,第四个参数我们先设置为NULL

  • glCompileShader编译着色器。

int  success;
char infoLog[512];
glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &success);
if(!success)
{
    glGetShaderInfoLog(vertexShader, 512, NULL, infoLog);
    std::cout << "ERROR::SHADER::VERTEX::COMPILATION_FAILED\n" << infoLog << std::endl;
}

检测在调用glCompileShader后编译是否成功了,如果没成功,输出报错信息。

五、着色器程序

着色器程序对象(Shader Program Object)是多个着色器合并之后并最终链接完成的版本。如果要使用刚才编译的着色器我们必须把它们链接(Link)为一个着色器程序对象,然后在渲染对象的时候激活这个着色器程序。已激活着色器程序的着色器将在我们发送渲染调用的时候被使用。

unsigned int shaderProgram;
shaderProgram = glCreateProgram();
glAttachShader(shaderProgram, vertexShader);
glAttachShader(shaderProgram, fragmentShader);
glLinkProgram(shaderProgram);
  • glCreateProgram创建一个程序,并返回新创建程序对象的ID引用。

  • glAttachShader把编译好的着色器附加到程序对象上。

  • glLinkProgram进行链接。

glUseProgram(shaderProgram);

我们可以调用glUseProgram函数,用刚创建的程序对象作为它的参数,以激活这个程序对象。

glDeleteShader(vertexShader);
glDeleteShader(fragmentShader);

把着色器对象链接到程序对象以后,由于不再需要,即可删除着色器对象。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值