openGL之着色器程序的使用
#define GLEW_STATIC
#include <GL\glew.h>
#include <GLFW\glfw3.h>
#include<iostream>
using namespace std; //函数原型
void key_callback(GLFWwindow* window, int key, int scancode,
int action, int mode); //窗口大小
const GLuint WIDTH = , HEIGHT = ; const GLchar* vertexShaderSource = "#version 330 core\n"
"layout (location = 0) in vec3 position;\n"
"void main()\n"
"{\n"
"gl_Position = vec4(position.x,position.y,position.z,1.0);\n"
"}\0"; const GLchar* fragmentShaderSource = "#version 330 core\n"
"out vec4 color;\n"
"void main()\n"
"{\n"
"color = vec4(1.0f,0.5f,0.2f,1.0f);\n"
"}\n\0"; int main(){
//初始化 GLFW
glfwInit(); //设置GLFW需要的选项
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, );
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, );
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
glfwWindowHint(GLFW_RESIZABLE, GL_FALSE); //创建一个窗口对象
GLFWwindow* window = glfwCreateWindow(WIDTH, HEIGHT, "test2", nullptr, nullptr);
glfwMakeContextCurrent(window); //设置徐亚的回调函数
glfwSetKeyCallback(window, key_callback); glewExperimental = GL_TRUE; glewInit(); int width, height;
glfwGetFramebufferSize(window, &width, &height);
glViewport(, , width, height); //定点着色器
GLuint vertextShader;
vertextShader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertextShader, , &vertexShaderSource, NULL);
glCompileShader(vertextShader); //用于判断一个着色器是否编译成功
GLint success;
GLchar infoLog[];
glGetShaderiv(vertextShader, GL_COMPILE_STATUS, &success);
if (!success){
glGetShaderInfoLog(vertextShader, , NULL, infoLog);
cout << "vertextShader COMPILE FAILED" << endl;
} //像素着色器
GLuint fragmentShader;
fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentShader, , &fragmentShaderSource, NULL);
glCompileShader(fragmentShader); //用于判断一个着色器是否编译成功
glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &success);
if (!success){
glGetShaderInfoLog(fragmentShader, , NULL, infoLog);
cout << "fragmentShader COMPILE FAILED" << endl;
} //创建一个着色器程序对象:多个着色器最后链接的版本
GLuint shaderProgram;
shaderProgram = glCreateProgram();
glAttachShader(shaderProgram, vertextShader);
glAttachShader(shaderProgram, fragmentShader);
glLinkProgram(shaderProgram); glGetProgramiv(shaderProgram, GL_LINK_STATUS, &success); if (!success){
glGetProgramInfoLog(shaderProgram, , NULL, infoLog);
}
glDeleteShader(vertextShader);
glDeleteShader(fragmentShader); //创建定点数据
GLfloat vertices[] = {
-0.5f, -0.5f, 0.0f,
0.5f, -0.5f, 0.0f,
0.0f, 0.5f, 0.0f
};
//创建 VBO 顶点缓冲数据,并把数据赋值到内存中
GLuint VBO;
glGenBuffers(, &VBO);
//VAO顶点数组对象
GLuint VAO;
glGenVertexArrays(, &VAO); //绑定VAO
glBindVertexArray(VAO); //复制顶点数据到缓冲中提供给OpenGL使用
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); //设置顶点属性指针
glVertexAttribPointer(, , GL_FLOAT, GL_FALSE, * sizeof(GLfloat), (GLvoid *));
glEnableVertexAttribArray(); //解绑VBO
glBindBuffer(GL_ARRAY_BUFFER, ); //解绑VAO
glBindVertexArray(); while (!glfwWindowShouldClose(window)){
glfwPollEvents(); //释放颜色缓存
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT); //绘制物体
//当打算渲染一个物体使用使用着色器程序
glUseProgram(shaderProgram);
glBindVertexArray(VAO); //绘制函数
glDrawArrays(GL_TRIANGLES, , );
glBindVertexArray(); glfwSwapBuffers(window);
} glDeleteVertexArrays(, &VAO);
glDeleteBuffers(, &VBO); glfwTerminate();
return ;
}
void key_callback(GLFWwindow* window, int key, int scancode,
int action, int mode){
if (key == GLFW_KEY_L && action == GLFW_PRESS){
glfwSetWindowShouldClose(window, GL_TRUE);
}
}
首先,在发该贴的时候,这个程序依旧没有跑起来,因为GLFW、GLEW等库的原因,鉴于GLUT是上个时代的产物,所以学到后面看到的一些案例都是用的GLEW、GLFW、GLAD等库,一时半会儿没有配置成功,但是,这并不能影响我们根据其中的代码来理解着色器程序(shader)。
下面,我们主要来看一下其中的着色器代码部分:
一、两个着色器程序
const GLchar* vertexShaderSource = "#version 330 core\n"
"layout (location = 0) in vec3 position;\n"
"void main()\n"
"{\n"
"gl_Position = vec4(position.x,position.y,position.z,1.0);\n"
"}\0"; const GLchar* fragmentShaderSource = "#version 330 core\n"
"out vec4 color;\n"
"void main()\n"
"{\n"
"color = vec4(1.0f,0.5f,0.2f,1.0f);\n"
"}\n\0";
首先第一个是顶点着色器(vertexShader):
顶点着色器用于读取顶点(坐标)数据,所以这个position参数是从外部数据源读取的,在main方法中将外部读取的顶点数据转化为四维坐标(x,y,z,w),并且赋值给全局变量:gl_Position。
第二个是片元着色器(fragmentShader):
这里注意了,片元着色器隐式地对所有的gl_Position中的坐标点进行着色并且将颜色输出。所以这个color参数是输出的,可能你也看到了,输出的颜色是个vec4,分别代表RGBA,最后一个1.0f表示alpha通道值为1.0f(浮点型)
二、着色器程序的编译
//定点着色器
GLuint vertextShader;
vertextShader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertextShader, , &vertexShaderSource, NULL);
glCompileShader(vertextShader); //用于判断一个着色器是否编译成功
GLint success;
GLchar infoLog[];
glGetShaderiv(vertextShader, GL_COMPILE_STATUS, &success);
if (!success){
glGetShaderInfoLog(vertextShader, , NULL, infoLog);
cout << "vertextShader COMPILE FAILED" << endl;
} //片元着色器
GLuint fragmentShader;
fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentShader, , &fragmentShaderSource, NULL);
glCompileShader(fragmentShader); //用于判断一个着色器是否编译成功
glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &success);
if (!success){
glGetShaderInfoLog(fragmentShader, , NULL, infoLog);
cout << "fragmentShader COMPILE FAILED" << endl;
}
这一块也不难理解:
1st,定义一个着色器(顶点着色器或者片元着色器);
2nd,为这个着色器对象加载着色器程序片段;
3rd,编译这个着色器;
当然,案例程序还加了一段编译成功与否的判断,这是有必要的,方便调试。
三、多个着色器连接
//创建一个着色器程序对象:多个着色器最后链接的版本
GLuint shaderProgram;
shaderProgram = glCreateProgram();
glAttachShader(shaderProgram, vertextShader);
glAttachShader(shaderProgram, fragmentShader);
glLinkProgram(shaderProgram); glGetProgramiv(shaderProgram, GL_LINK_STATUS, &success); if (!success){
glGetProgramInfoLog(shaderProgram, , NULL, infoLog);
}
glDeleteShader(vertextShader);
glDeleteShader(fragmentShader);
这块也不难理解,新建一个shaderProgram,并且通过glAttachShader() API将之前的两个着色器进行连接,这样顶点着色器输出的四维坐标就能供片元着色器使用了。
两个着色器进行连接之后,对之前的着色器进行删除。
四、将外部顶点数据进行绑定(用户自定义数据)
//创建定点数据
GLfloat vertices[] = {
-0.5f, -0.5f, 0.0f,
0.5f, -0.5f, 0.0f,
0.0f, 0.5f, 0.0f
};
//创建 VBO 顶点缓冲数据,并把数据赋值到内存中
GLuint VBO;
glGenBuffers(, &VBO);
//VAO顶点数组对象
GLuint VAO;
glGenVertexArrays(, &VAO); //绑定VAO
glBindVertexArray(VAO); //复制顶点数据到缓冲中提供给OpenGL使用
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); //设置顶点属性指针
glVertexAttribPointer(, , GL_FLOAT, GL_FALSE, * sizeof(GLfloat), (GLvoid *));
glEnableVertexAttribArray(); //解绑VBO
glBindBuffer(GL_ARRAY_BUFFER, ); //解绑VAO
glBindVertexArray();
不难看出,用户自定义顶点数据为三个顶点(-0.5,-0.5,0)(0.5,-0.5,0)和(0,0.5,0);

新建VAO、VBO对象并将其放到内存中;
将用户自定义数据赋值到VBO中;
后面的VAO相关操作没有看懂,这一块不是直接用VBO(顶点缓存对象)么,并没有用到VAO啊???
glVertexAttribPointer()我的理解就是为这些顶点(坐标)设置相应的指针好让程序知道如何操作。
五、渲染
//释放颜色缓存
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT); //绘制物体
//当打算渲染一个物体使用使用着色器程序
glUseProgram(shaderProgram);
glBindVertexArray(VAO); //绘制函数
glDrawArrays(GL_TRIANGLES, , );
glBindVertexArray(); glfwSwapBuffers(window);
首先,清空屏幕;
然后调用之前的shaderProgram,并为其绑定数据(??不是已经绑定数据了么)
openGL之着色器程序的使用的更多相关文章
- OpenGL ES着色器语言之语句和结构体(官方文档第六章)内建变量(官方文档第七、八章)
OpenGL ES着色器语言之语句和结构体(官方文档第六章) OpenGL ES着色器语言的程序块基本构成如下: 语句和声明 函数定义 选择(if-else) 迭代(for, while, do-wh ...
- OpenGL ES着色器语言之变量和数据类型(一)(官方文档第四章)和varying,uniform,attribute修饰范围
OpenGL ES着色器语言之变量和数据类型(一)(官方文档第四章) 所有变量和函数在使用前必须声明.变量和函数名是标识符. 没有默认类型,所有变量和函数声明必须包含一个声明类型以及可选的修饰符. ...
- OpenGL ES着色器语言之着色概览(官方文档)
OpenGL ES着色器语言之着色概览(官方文档第二章) 事实上,OpenGL ES着色语言是两种紧密关联的语言.这些语言用来在OpenGL ES处理管线的可编程处理器创建着色器. 在本文档中,除非另 ...
- GLSL 着色器程序
除了使用Cg/HSL 着色器程序以外, OpenGL 着色器语言(GLSL)着色器可以直接书写shader. 然而,使用原生的GLSL只推荐作为测试使用,或者你清晰的知道你的目标平台是 Mac OS ...
- OpenGL ES着色器语言之操作数(官方文档第五章)
OpenGL ES着色器语言之操作数(官方文档第五章) 5.1操作数 OpenGL ES着色器语言包含如下操作符. 5.2数组下标 数组元素通过数组下标操作符([ ])进行访问.这是操作数组的唯一操作 ...
- OpenGL ES着色器语言之变量和数据类型(二)(官方文档第四章)
OpenGL ES着色器语言之变量和数据类型(二)(官方文档第四章) 4.5精度和精度修饰符 4.5.1范围和精度 用于存储和展示浮点数.整数变量的范围和精度依赖于数值的源(varying,unifo ...
- OpenGL ES着色器语言之静态使用(static use)和预处理
OpenGL ES着色器语言之静态使用(static use) 在OpenGL ES中有一个术语叫静态使用(static use),什么叫静态使用呢? 在写代码中,对于一个变量可能具有以下三种情况: ...
- Android OpenGL ES 开发(八): OpenGL ES 着色器语言GLSL
前面的文章主要是整理的Android 官方文档对OpenGL ES支持的介绍.通过之前的文章,我们基本上可以完成的基本的形状的绘制. 这是本人做的整理笔记: https://github.com/re ...
- OpenGL中着色器,渲染管线,光栅化
https://www.zhihu.com/question/29163054 光栅(shan一声)化(Rasterize/rasteriztion).这个词儿Adobe官方翻译成栅格化或者像素化 ...
随机推荐
- [golang note] 接口使用
侵入式接口 √ 在其他一些编程语言中,接口主要是作为不同组件之间的契约存在,即规定双方交互的规约. √ 对契约的实现是强制的,即必须确保用户的确实现了该接口,而实现一个接口,需要从该接口继承. √ 如 ...
- 手游精品时代,iClap参会TFC高效解决手游问题
随着“互联网+”概念的广泛应用,文娱类产品跨界融合的现象日益明显,不再以孤立的形态出现在市场中.移动游戏作为泛娱乐产业链的变现末端和关键环节,在传统游戏和VR/AR.HTML5.机器人.智能设备等新业 ...
- zw版【转发·台湾nvp系列Delphi例程】HALCON TestSubsetRegio
zw版[转发·台湾nvp系列Delphi例程]HALCON TestSubsetRegio procedure TForm1.Button1Click(Sender: TObject);var rg0 ...
- LA 4287 有相图的强连通分量
大白书P322 , 一个有向图在添加至少的边使得整个图变成强连通图, 是计算整个图有a个点没有 入度, b 个点没有出度, 答案为 max(a,b) ; 至今不知所云.(求教) #include &l ...
- Spring MVC 复习笔记04
复习 springmvc框架: DispatcherServlet前端控制器:接收request,进行response HandlerMapping处理器映射器:根据url查找Handler.(可以通 ...
- 微信JS支付代码_前端调用微信支付接口
转自:http://dditblog.com/itshare_553.html 跟大家分享一段微信支付的js代码片段.V3版的微信支付没有paySignKey参数.基本上是直接复制就可以使用了.改一改 ...
- Python3.x:os.mkdir与 os.makedirs(创建目录方法)区别
Python3.x:os.mkdir与 os.makedirs区别 1,os.mkdir mkdir( path [,mode] ) 说明: 创建一个目录,可以是相对或者绝对路径,mode的默认模式是 ...
- 20145315 《Java程序设计》第四周学习总结
20145315 <Java程序设计>第四周学习总结 教材学习内容总结 第六章 继承与多态 6.1何谓继承 6.1.1继承共同行为 把相同的程序代码提升为父类 private String ...
- 安装Git【转】
本文转载自:http://www.liaoxuefeng.com/wiki/0013739516305929606dd18361248578c67b8067c8c017b000 最早Git是在Linu ...
- Python学习札记(二十九) 模块2
参考:使用模块 NOTE 1.内建sys模块: #!/usr/bin/env python3 import sys 'a test module' __author__ = 'wasdns' def ...