Java教程

理解GL管线(二)着色器(认识顶点着色器和片段着色器)

本文主要是介绍理解GL管线(二)着色器(认识顶点着色器和片段着色器),对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

1.GLSL语言

GLSL是着色器语言的一种,其他的着色器语言如HLSL,微软的3D框架DirectX等。着色器语言程序主要运行在GPU上。

GLSL是与OpenGL兼容的专用着色器语言,因此我们需要用GLSL编写着色器使用的程序代码。并将编写完的代码载入各个着色器阶段。其过程如下:

(1)编写GLSL程序代码(可以写进文件中,也可以硬编码在C++程序的字符串中。)

(2)使用C++获取GLSL程序代码。

(3)创建OpenGL着色器对象,并将GLSL程序代码加载进着色器对象。

(4)用OpenGL命令编译并链接着色器对象,并将其安装进GPU。

实践中,至少要顶点着色器和片段着色器阶段的GLSL代码,而曲面细分着色器和几何着色器阶段是可选的。

2.图元

  OpenGL只允许绘制三类图形:点、线、三角形。它们叫做图元。即便是复杂的3D模型通常也是由许多三角形构成的。

  图元由顶点组成。例如三角形有三个顶点。

  顶点的来源可以是任意的,从文件中读取、硬编码在C++程序中或者直接在GLSL代码中。加载的顶点会被载入管线,经由着色器处理,最终变成屏幕上的各种形状。

  Gl通过【glDrawArrays(GLenum mode,Glint first,Glsizei count)】方法绘制图元,其中mode是图元类型,first是从那个顶点开始绘制(通常是顶点0)。当调用该方法时,管线中的着色器(顶点着色器开始)开始执行。

3.着色器

  顶点着色器:即处理顶点的着色器,所有顶点被载入管线后都会经由顶点着色器(即会对每个顶点执行一次(通常时并行的)),处理后载入管线的下一步。通过顶点着色器可以改变绘制内容的形状,包括形状大小、位置、角度、投影等等。

  片段着色器:片段着色器负责处理绘制内容的颜色,所有顶点光栅化后经由片段着色器都会被赋值颜色,并且也会被插值处理。

代码示例:

 

 1 #include <GL\glew.h>
 2 #include <GLFW\glFW3.h>
 3 
 4 #define numVAOs 1    
 5 
 6 GLuint renderingProgram;      
 7 GLuint vao[numVAOs]; //定义voa
 8 //创建着色器程序
 9 GLuint createShaderProgram() { 
  //GLSL程序代码
10   const char *vshaderSource = 
11     "#version 430 \n" 
12     "void main(void) \n" 
13     "{ gl_Position = vec4(0.0, 0.0, 0.0, 1.0); }"; 
14 //GLSL程序代码
15   const char *fshaderSource = 
16     "#version 430 \n" 
17     "out vec4 color; \n"
18     "void main(void) \n" 
19     "{ color = vec4(0.0, 0.0, 1.0, 1.0); }"; 
20 
21   GLuint vShader = glCreateShader(GL_VERTEX_SHADER); //创建顶点着色器对象,返回对象ID
22   GLuint fShader = glCreateShader(GL_FRAGMENT_SHADER); //创建片段着色器对象,返回对象ID
23 
24   glShaderSource(vShader, 1, &vshaderSource, NULL); //将GLSL代码载入空着色器对象
25   glShaderSource(fShader, 1, &fshaderSource, NULL); //同上
26   glCompileShader(vShader); //编译着色器
27   glCompileShader(fShader); //同上
28 
29   GLuint vfProgram = glCreateProgram(); //创建OpenGL程序对象,它包含一系列编译过的着色器对象。
30   glAttachShader(vfProgram, vShader); //将着色器对象加入程序对象
31   glAttachShader(vfProgram, fShader); //同上
32   glLinkProgram(vfProgram); //请求GLSL编译器确保新加入着色器对象的兼容性
33   //返回程序对象ID
34   return vfProgram;
35 }
36 
37 int main(void) {
38     //初始化glfw库
39     if (!glfwInit())
40     {
41         exit(EXIT_FAILURE);
42      }
43     //设置gl主版本号
44     glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
45      //设置gl次版本号,与主版本号一起指定了机器必须与opengl4.3版本兼容
46     glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
47     //创建glfw窗口,大小1280x640像素,窗口标题(window1)
48     GLFWwindow* window = glfwCreateWindow(1280,640,"window1", NULL, NULL);
49     //通知GLFW将我们窗口的上下文设置为当前opengl线程的主上下文
50     glfwMakeContextCurrent(window);
51      //初始化glew库
52     if (glewInit() != GLEW_OK)
53     {
54          exit(EXIT_FAILURE);
55      }
56     //设置缓冲区交换间隔(帧)。 默认情况下,交换间隔为0,但因缓冲区
57     //有可能在屏幕更新的中间交换,出现屏幕撕裂的情况。
58     //所以,可以将该间隔设为1,即每帧更新一次。 它可以设置为更高的
59     //值,但这可能导致输入延迟。
60     glfwSwapInterval(1);
61 
62     init(window);
63     //检查GLFW是否被要求退出
64     while (!glfwWindowShouldClose(window)) {
65         display(window, glfwGetTime()); //glfwGetTime:获取glfw初始化后经过的时间
66         //交换缓冲区
67         glfwSwapBuffers(window);
68         //glfwPollEvents函数检查有没有触发什么事件(比如键盘输入、鼠标移动等)、更新窗口状态,并调用对应的回调函数(可以通过回调方法手动设置)。
69         glfwPollEvents();
70     }
71     //glfw销毁窗口
72     glfwDestroyWindow(window);
73      //glfw终止运行
74     glfwTerminate();
75     exit(EXIT_SUCCESS);
76 }
77 
78 void init(GLFWwindow* window) {
79   renderingProgram = createShaderProgram(); //创建OpenGL程序对象,它包含一系列编译过的着色器对象
80   glGenVertexArrays(numVAOs, vao); //创建Vao
81   glBindVertexArray(vao[0]);//激活VAO
82 
83  }
84 
85 void display(GLFWwindow* window, double currentTime) {
86   glUseProgram(renderingProgram); //将OpenGL程序(包含我们编译进去的两个着色器对象)载入管线阶段(在GPU上);这一步并没有运行着色器,只是将着色器加载进硬件
87   glDrawArrays(GL_POINTS, 0, 1);//启动管线,描绘内容,图元是点。即描画一个点。
88 }

 

4.着色器代码解析:

顶点着色器:

  #version 430 //指明GL版本:4.3

  void main(void) //着色器是一个程序,与C++类似,也是从main函数开始

  gl_Position//这是一个预定义的输出变量。用来设置顶点。并发送至下一个管线。

  vec4//四元组,这里用来存储x,y,z,和齐次坐标值。

片段着色器:

  out vec4 color; //指定一个输出变量,类型为四元组,名称是color。输出变量会自动输出到管线的下一阶段。

VAO:

  vao是用来管理缓冲区的,所有的缓冲区都会被存入VAO。即便不使用任何缓冲区,OpenGl仍然需要创建至少一个VAO。

这篇关于理解GL管线(二)着色器(认识顶点着色器和片段着色器)的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!