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] 接口使用
侵入式接口 √ 在其他一些编程语言中,接口主要是作为不同组件之间的契约存在,即规定双方交互的规约. √ 对契约的实现是强制的,即必须确保用户的确实现了该接口,而实现一个接口,需要从该接口继承. √ 如 ...
- git相关使用技巧和问题
本地有修改和提交,如何强制用远程的库更新更新.我尝试过用git pull -f,总是提示 You have not concluded your merge. (MERGE_HEAD exists). ...
- 分布式存储之MogileFS基于Nginx实现负载均衡(Nginx+MogileFS)
MogileFS分布式文件系统特点: 1.具有raid的性能 2.不存在单点故障 3.简单的命名空间: 每个文件对应一个key:用于domain定义名称空间 4.不共享任何数据 5.传输中立,无特殊协 ...
- 解决不能在本地使用JQuery load的方法
$.ajaxSetup({ xhr: function () { if ("ActiveXObject" in window) { return new ActiveXObject ...
- Avito Cool Challenge 2018 Solution
A. Definite Game 签. #include <bits/stdc++.h> using namespace std; int main() { int a; while (s ...
- 服务器负载、CPU性能判断
说在前面: 在linux操作系统中,我们一般查看系统的cpu负载情况常用的命令可以是uptime,top,还有vmstat等这些个都是可以有的.每个工具所提供的信息各不相同, 我这里要讨论的仅说cpu ...
- uwsgi手动安装时报错ValueError: invalid literal for int() with base 10: '32_1'
安装uwsgi,安装步骤如下 wget https://projects.unbit.it/downloads/uwsgi-latest.tar.gz tar zxvf uwsgi-latest.ta ...
- Python:导入numpy报错 No module named numpy
Numpy是python的一种开源的数值计算扩展.这种工具可用来存储和处理大型矩阵,比python自身的嵌套列表结构要高效的多.但是在使用numpy时可能会出错(如上图). 解决办法:下载安装对应版本 ...
- python ConfigParser读取配置文件,及解决报错(去掉BOM)ConfigParser.MissingSectionHeaderError: File contains no section headers的方法
先说一下在读取配置文件时报错的问题--ConfigParser.MissingSectionHeaderError: File contains no section headers 问题描述: 在练 ...
- .Ignite是什么
Ignite是什么 Apache Ignite内存数据组织是高性能的.集成化的以及分布式的内存平台,他可以实时地在大数据集中执行事务和计算,和传统的基于磁盘或者闪存的技术相比,性能有数量级的提升. ...