¶OpenGL(三) 分离并使用着色器
注:本文仅供自己以及OPENGL初学者共同学习进步,并无实际教学意义,不过会对自己学习中遇到的关键点加上个人解释。应该会对初学者有所帮助,如有错误请指正!
继续沿用上章的代码,我们发现着色器代码写在主代码文件中看上去非常冗余,并且难以分析,所以我们可以建立一个专属处理Shader的类,封装处理Shader的操作,这样我们在使用Shader的时候就只需要短短一两行代码就可以实现。
依旧是在VS2017下完成以下操作。
先不管我们的main.cpp(主执行代码),右键我们的项目名称->添加->类,把类名设置成Shader,其他设置一律用默认,点击确定即可,VS2017就会帮我们建立好一个Shader.h 以及 Shader.cpp,来分析一下我们需要的东西,我们的目的是用从txt文档中取得着色器代码,并且能够编译使用它,那么Shader的构建函数就应该传入txt文档的路径,由于我们只使用了顶点着色器与片段着色器,所以只需要传入两个文件的路径即可,用const char * 接收(注意:这里必须是const类型):
1 | Shader(const char * vertexPath, const char * fragmentPath); |
然后看向Shader.cpp,既然是从文件读取内容,当然就要用到C++的文件流了:
1 |
我们要从txt文档中读取内容要经过以下几个步骤:
shader文件从硬盘被读取到内存里,放在文件缓冲区,然后转换到string缓冲,再由string字符接收内容,然后由于CPU只认得char,所以最后再将string转为char *,内容接收就完成了。
所以我们是不是需要文件缓冲,字符缓冲与string还有char *,看下面的代码:
1 | //Shader.h |
1 | //shader.cpp |
然后接下来我们就可以把主代码那些关于着色器的代码全部去掉了:
1 |
|
既然着色器代码已经删除了,那么我们就需要两个txt文档来写着色器代码.
可以直接到VS2017右键项目->添加->新建项->实用工具->文档,创建两个文档,一个写vertexShader,一个写fragmentShader,然后你会发现你的资源文件多了两个txt文档,把之前的着色器代码复制粘贴进去,去掉双引号和"\n"(不去干净就会出错),就OK了。
然后我们到主执行代码程序里面去,创建Shader对象,初始化路径,使用use方法就行啦。
还有一点要注意,创建Shader对象时,必须是在初始化glad或glew之后才能创建。
附上ShaderSource代码:
vertexSource.txt
1 |
|
fragmentSource.txt
1 |
|
最后再补充一下代码,可以看到我们的顶点数组多了些内容,也就是每个顶点的RGB值,还记得我们如何告诉OpenGL处理这些数据吗
![](https://learnopengl-cn.github.io/img/01/05/vertex_attribute_pointer_interleaved.png)
1 | glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)0); |
我们将RGB值放在了我们绑定的VAO的1号位置,然后由于现在每一个顶点数据变成了6个,所以第四个参数改成了6*sizeof(float);
可以看到我们的vertexShader里面也多了个aColor属性,然后将它传入了fragmentShader.
输出效果如下:
我们要记得一个地方,就是如果颜色不对,一般就是fragmentShader出问题了,如果连图形都没有,一般就是vertexShader出问题了,然后检查两个着色器的代码。
那我们希望知道着色器代码编译出错的点该怎么办,我们只需要使用OpenGL的函数来获取Shader的编译信息就行了。
1 | void Shader::checkCompileErrors(unsigned int ID, std::string type) |
只要我们着色器编译出错,它就会在窗口打印出错误信息。这样我们就能知道错误的详细情况了。