这两天配了一下现代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的更多相关文章

  1. OpenGL shader 中关于顶点坐标值的思考

    今天工作中需要做一个事情: 在shader内部做一些空间距离上的计算,而且需要对所有的点进行计算,符合条件的显示,不符合条件的点不显示. 思路很简单,在vertex shader内知道顶点坐标,进行计 ...

  2. CSharpGL(14)用geometry shader渲染模型的法线(normal)

    +BIT祝威+悄悄在此留下版了个权的信息说: CSharpGL(14)用geometry shader渲染模型的法线(normal) +BIT祝威+悄悄在此留下版了个权的信息说: 2016-08-13 ...

  3. 【译】Unity3D Shader 新手教程(6/6) —— 更好的卡通Shader

    本文为翻译,附上原文链接. 转载请注明出处--polobymulberry-博客园. 动机 如果你想了解以下几件事,我建议你阅读以下这篇教程: 想知道如何写一个multipass的toon shade ...

  4. 【译】Unity3D Shader 新手教程(5/6) —— Bumped Diffuse Shader

    本文为翻译,附上原文链接. 转载请注明出处--polobymulberry-博客园. 动机 如果你满足以下条件,我建议你阅读这篇教程: 你想学习片段着色器(Fragment Shader). 你想实现 ...

  5. 【译】Unity3D Shader 新手教程(4/6) —— 卡通shader(入门版)

    本文为翻译,附上原文链接. 转载请注明出处--polobymulberry-博客园. 暗黑系 动机 如果你满足以下条件,我建议你阅读这篇教程: 你想了解更多有关表面着色器的细节知识. 你想实现一个入门 ...

  6. 【译】Unity3D Shader 新手教程(3/6) —— 更加真实的积雪

    本文为翻译,附上原文链接. 转载请注明出处--polobymulberry-博客园. 如果你满足以下条件,我建议你阅读这篇教程: 你想知道如何在表面着色器中进行混色(blend colour) 你想实 ...

  7. 【译】Unity3D Shader 新手教程(2/6) —— 积雪Shader

    本文为翻译,附上原文链接. 转载请注明出处--polobymulberry-博客园. 如果你是一个shader编程的新手,并且你想学到下面这些酷炫的技术,我觉得你可以看看这篇教程: 实现一个积雪效果的 ...

  8. 【译】Unity3D Shader 新手教程(1/6)

    本文为翻译,附上原文链接. 转载请注明出处--polobymulberry-博客园. 刚开始接触Unity3D Shader编程时,你会发现有关shader的文档相当散,这也造成初学者对Unity3D ...

  9. 多材质(Shader)实现

    最近在cocos creator上打算写个U3D中shader功能的插件(能在属性面板调整shader属性). 对其中一个功能有点疑惑,就是U3D中一个渲染物体上可以挂多个材质,后来查询了下,一个物体 ...

随机推荐

  1. jQuery获取子元素的个数

    一.获取div下的子元素的个数 $("div").children().length; 二.获取div下的span子元素的个数 $("div").childre ...

  2. 设计模式(10)--Facade(外观模式)--结构型

    作者QQ:1095737364    QQ群:123300273     欢迎加入! 1.模式定义: 外观模式提供了一个统一的接口,用来访问子系统中的一群接口.外观定义了一个高层接口,让子系统更容易使 ...

  3. js 回调函数理解与应用

    定义:在JavaScript中,回调函数具体的定义为:函数A作为参数(函数引用)传递到另一个函数B中,并且这个函数B执行函数A.我们就说函数A叫做回调函数.如果没有名称(函数表达式),就叫做匿名回调函 ...

  4. 排错-Ad Hoc Distributed Queries组件被禁用的解决办法

    Ad Hoc Distributed Queries组件被禁用的解决办法 by:授客 QQ:1033553122 SQL Server 阻止了对组件 'Ad Hoc Distributed Queri ...

  5. 测试sql server服务是否配置正确

    最简单的方法: 新建一个testdb.udl文件,双击可出现测试界面

  6. vue-router 手势滑动触发返回

    vue-router的路由变换只存在“变换前”和“变换后”,不存在“切换中”的状态,所以做不到大多数app(微信那样的)在滑动过程中让界面跟随手指移动.但滑动事件还是可以监听的,我们可以在滑动之后再触 ...

  7. Java学习笔记之异常处理

    一.异常的分类 1.由Java虚拟机抛出的异常(Error):程序无法处理的问题,用户不用去进行处理(虚拟机错误丶内存溢出错误丶线程死锁) 2.Exception异常:程序本身可以进行处理的异常 1. ...

  8. 如何扩展 Azure 资源组中虚拟机的 OS 驱动器

    概述 在资源组中通过从 Azure 应用商店部署映像来创建新的虚拟机 (VM) 时,默认的 OS 驱动器空间为 127 GB. 尽管可以将数据磁盘添加到 VM(数量取决于所选择的 SKU),并且我们建 ...

  9. 注意Sqlserver中使用with(nolock)后实际上还是会加架构锁,只是不对要查询的数据加S锁而已(转载)

    开发人员喜欢在SQL脚本中使用WITH(NOLOCK), WITH(NOLOCK)其实是表提示(table_hint)中的一种.它等同于 READUNCOMMITTED . 具体的功能作用如下所示(摘 ...

  10. fab提供远程IP和账号密码

    #!/usr/bin/python #-*- coding: UTF-8 -*- from fabric.api import * from fabric.context_managers impor ...