Hello Shader之Hello Trangle
这两天配了一下现代OpenGL的开发环境,同时看了一下基础知识和编程规范
写了一个编译GLSL语言的前端程序和一个Hello trangle的程序
另外,推荐两个资源
1.学习网站Learn Opengl
2.OpenGL编程指南第八版(俗称红宝书)
网站有的地方降得不好可以看书
接下来总结一下知识点:
1.现代GPU内部的管线,其中蓝色部分是可编程的部分,gpu内部有许许多多的微程序,他们可以并行地执行,
可编程的微程序为蓝色部分,称为shader,即着色器程序,其中顶点着色器和片段着色器应用最多。

2.着色器语言GLSL的使用,着色器程序的编译,链接
这个我专门造了一个轮子,封装了一下
#ifndef _SHADER_H_
#define _SHADER_H_ #include <GLEW/glew.h>
#include <iterator> // std::istreambuf_iterator
#include <string>
#include <vector>
#include <iostream>
#include <fstream> struct ShaderFile
{
GLenum shaderType;
const char* filePath;
ShaderFile(GLenum type, const char* path)
:shaderType(type), filePath(path){}
}; class Shader
{
public:
Shader(const char* vertexPath, const char* fragPath) :programId(0)
{
std::vector<ShaderFile> fileVec;
fileVec.push_back(ShaderFile(GL_VERTEX_SHADER, vertexPath));
fileVec.push_back(ShaderFile(GL_FRAGMENT_SHADER, fragPath));
loadFromFile(fileVec);
}
Shader(const char* vertexPath, const char* fragPath, const char* geometryPath) :programId(0)
{
std::vector<ShaderFile> fileVec;
fileVec.push_back(ShaderFile(GL_VERTEX_SHADER, vertexPath));
fileVec.push_back(ShaderFile(GL_FRAGMENT_SHADER, fragPath));
fileVec.push_back(ShaderFile(GL_GEOMETRY_SHADER, geometryPath));
loadFromFile(fileVec);
}
void use()
{
glUseProgram(this->programId);
}
~Shader()
{
if (this->programId)
{
glDeleteProgram(this->programId);
}
}
GLuint GetProgramID()
{
return programId;
}
public:
GLuint programId;
private:
/*
* 从文件加载顶点和片元着色器
* 传递参数为 [(着色器文件类型,着色器文件路径)+]
*/
void loadFromFile(std::vector<ShaderFile>& shaderFileVec)
{
std::vector<GLuint> shaderObjectIdVec;
std::string vertexSource, fragSource;
std::vector<std::string> sourceVec;
size_t shaderCount = shaderFileVec.size();
// 读取文件源代码
for (size_t i = 0; i < shaderCount; ++i)
{
std::string shaderSource;
if (!loadShaderSource(shaderFileVec[i].filePath, shaderSource))
{
std::cout << "Error::Shader could not load file:" << shaderFileVec[i].filePath << std::endl;
return;
}
sourceVec.push_back(shaderSource);
}
bool bSuccess = true;
// 编译shader object
for (size_t i = 0; i < shaderCount; ++i)
{
GLuint shaderId = glCreateShader(shaderFileVec[i].shaderType);
const char *c_str = sourceVec[i].c_str();
glShaderSource(shaderId, 1, &c_str, NULL);
glCompileShader(shaderId);
GLint compileStatus = 0;
glGetShaderiv(shaderId, GL_COMPILE_STATUS, &compileStatus); // 检查编译状态
if (compileStatus == GL_FALSE) // 获取错误报告
{
GLint maxLength = 0;
glGetShaderiv(shaderId, GL_INFO_LOG_LENGTH, &maxLength);
std::vector<GLchar> errLog(maxLength);
glGetShaderInfoLog(shaderId, maxLength, &maxLength, &errLog[0]);
std::cout << "Error::Shader file [" << shaderFileVec[i].filePath << " ] compiled failed,"
<< &errLog[0] << std::endl;
bSuccess = false;
}
shaderObjectIdVec.push_back(shaderId);
}
// 链接shader program
if (bSuccess)
{
this->programId = glCreateProgram();
for (size_t i = 0; i < shaderCount; ++i)
{
glAttachShader(this->programId, shaderObjectIdVec[i]);
}
glLinkProgram(this->programId);
GLint linkStatus;
glGetProgramiv(this->programId, GL_LINK_STATUS, &linkStatus);
if (linkStatus == GL_FALSE)
{
GLint maxLength = 0;
glGetProgramiv(this->programId, GL_INFO_LOG_LENGTH, &maxLength);
std::vector<GLchar> errLog(maxLength);
glGetProgramInfoLog(this->programId, maxLength, &maxLength, &errLog[0]);
std::cout << "Error::shader link failed," << &errLog[0] << std::endl;
}
}
// 链接完成后detach 并释放shader object
for (size_t i = 0; i < shaderCount; ++i)
{
if (this->programId != 0)
{
glDetachShader(this->programId, shaderObjectIdVec[i]);
}
glDeleteShader(shaderObjectIdVec[i]);
}
}
/*
* 读取着色器程序源码
*/
bool loadShaderSource(const char* filePath,std::string& source)
{
source.clear();
std::ifstream in_stream(filePath);
if (!in_stream)
{
return false;
}
source.assign(std::istreambuf_iterator<char>(in_stream),
std::istreambuf_iterator<char>()); // 文件流迭代器构造字符串
return true;
}
};
#endif
3.关于VBO和VAO
这两个的使用函数等等我就不搬上来了,没什么意义
只解释下两者的实质和容易出错的地方
VBO译名顶点缓冲对象,用来从CPU内存读取数据到GPU内存(以后称作显存)中,VBO的内存是独立的,真正存在的,同时一个VBO只能存一段内存
VAO称为顶点数组对象,用来负责组织,解释VBO,记录渲染环境,VAO并不是占有独立内存,仅仅相当于做个索引的作用,可以想象成指针,也就是说VAO是依托于VBO存在的,一旦VBO改变了,VAO也就改变了
最后,鹅厂的面试经历和个人这一段时间和大学生活的总结展望在论坛上开了个坑,最近踪迹应该在论坛上:
传送门:
腾讯实习生面试经历(不打算一次写完,开个坑,慢慢更,同时也算是帮助自己思考些未来)
Hello Shader之Hello Trangle的更多相关文章
- OpenGL shader 中关于顶点坐标值的思考
今天工作中需要做一个事情: 在shader内部做一些空间距离上的计算,而且需要对所有的点进行计算,符合条件的显示,不符合条件的点不显示. 思路很简单,在vertex shader内知道顶点坐标,进行计 ...
- CSharpGL(14)用geometry shader渲染模型的法线(normal)
+BIT祝威+悄悄在此留下版了个权的信息说: CSharpGL(14)用geometry shader渲染模型的法线(normal) +BIT祝威+悄悄在此留下版了个权的信息说: 2016-08-13 ...
- 【译】Unity3D Shader 新手教程(6/6) —— 更好的卡通Shader
本文为翻译,附上原文链接. 转载请注明出处--polobymulberry-博客园. 动机 如果你想了解以下几件事,我建议你阅读以下这篇教程: 想知道如何写一个multipass的toon shade ...
- 【译】Unity3D Shader 新手教程(5/6) —— Bumped Diffuse Shader
本文为翻译,附上原文链接. 转载请注明出处--polobymulberry-博客园. 动机 如果你满足以下条件,我建议你阅读这篇教程: 你想学习片段着色器(Fragment Shader). 你想实现 ...
- 【译】Unity3D Shader 新手教程(4/6) —— 卡通shader(入门版)
本文为翻译,附上原文链接. 转载请注明出处--polobymulberry-博客园. 暗黑系 动机 如果你满足以下条件,我建议你阅读这篇教程: 你想了解更多有关表面着色器的细节知识. 你想实现一个入门 ...
- 【译】Unity3D Shader 新手教程(3/6) —— 更加真实的积雪
本文为翻译,附上原文链接. 转载请注明出处--polobymulberry-博客园. 如果你满足以下条件,我建议你阅读这篇教程: 你想知道如何在表面着色器中进行混色(blend colour) 你想实 ...
- 【译】Unity3D Shader 新手教程(2/6) —— 积雪Shader
本文为翻译,附上原文链接. 转载请注明出处--polobymulberry-博客园. 如果你是一个shader编程的新手,并且你想学到下面这些酷炫的技术,我觉得你可以看看这篇教程: 实现一个积雪效果的 ...
- 【译】Unity3D Shader 新手教程(1/6)
本文为翻译,附上原文链接. 转载请注明出处--polobymulberry-博客园. 刚开始接触Unity3D Shader编程时,你会发现有关shader的文档相当散,这也造成初学者对Unity3D ...
- 多材质(Shader)实现
最近在cocos creator上打算写个U3D中shader功能的插件(能在属性面板调整shader属性). 对其中一个功能有点疑惑,就是U3D中一个渲染物体上可以挂多个材质,后来查询了下,一个物体 ...
随机推荐
- 在Android开发中替换资源图片不起作用的解决方法
现象 在android开发中,经常会需要替换res\drawable中的图片,打开res\layout下的文件预览布局页面发现图片已经被替换,但在模拟器或者真实机器上运行时发现该图片并没有被替换,还是 ...
- ADO.NET 【属性扩展】性别、年龄、编号
1.性别属性扩展 private bool _Sex; //成员变量 public bool Sex // 属性 { get { return _Sex; } set { _Sex = value; ...
- JS forEach()与map() 用法(转载)
JavaScript中的数组遍历forEach()与map()方法以及兼容写法 原理: 高级浏览器支持forEach方法语法:forEach和map都支持2个参数:一个是回调函数(item,ind ...
- [日常] Go语言圣经-指针对象的方法-bit数组习题
练习6.1: 为bit数组实现下面这些方法 func (*IntSet) Len() int // return the number of elements func (*IntSet) Remov ...
- [World Final 2016] Branch Assignment
链接 PDF bzoj 先求出正置边和反置边时b+1到前b个点的最短路dis[0/1][x](x∈[1,b]), 令D[x]=dis[0][x]+dis[1][x] 然后分组后每个x对代价的贡献为D[ ...
- 从零开始学习html(十二)CSS布局模型——上
一.css布局模型 清楚了CSS 盒模型的基本概念. 盒模型类型, 我们就可以深入探讨网页布局的基本模型了. 布局模型与盒模型一样都是 CSS 最基本. 最核心的概念. 但布局模型是建立在盒模型基础之 ...
- 从零开始学习html(十)CSS格式化排版——下
六.文字排版--删除线 <!DOCTYPE HTML> <html> <head> <meta http-equiv="Content-Type&q ...
- JavaScript数组转字符串,字符串转数组
//--------------------数组转字符串--------------------------- //需要将数组元素用某个字符连接成字符串 var a1, b1,c1; a1 = [&q ...
- RecyclerView 下拉刷新和加载更多
一.SwipeRefreshLayout实现下拉刷新 1.方法API: setOnRefreshListener(OnRefreshListener):添加下拉刷新监听器 setRefreshing( ...
- MySQL 命令行操作集合
1.导入数据库 ) 登录 mysql -uroot -p Enter password: 2) 创建数据库create database pluto_0; 3)导入 source /var/www/m ...