ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

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

2021-08-02 01:31:06  阅读:270  来源: 互联网

标签:GLSL 片段 对象 void window 顶点 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。

标签:GLSL,片段,对象,void,window,顶点,GL,着色器
来源: https://www.cnblogs.com/haosk/p/15088284.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有