mirror of
https://github.com/LearnOpenGL-CN/LearnOpenGL-CN.git
synced 2025-08-23 04:35:28 +08:00
-第一版翻译完成
This commit is contained in:
@@ -162,3 +162,139 @@ GLSL跟一般的编程语言一样,定义了一些常用的数据类型,基
|
||||
|
||||
如果运行正常的话我们能看到一个绿色到黑色,黑色到绿色变化的三角形,
|
||||
可以查看完整的代码[实例](http://learnopengl.com/code_viewer.php?code=getting-started/shaders-interpolated)
|
||||
|
||||
|
||||
**着色器程序管理程序**
|
||||
|
||||
编写、编译和管理着色器程序是非常繁重的工作,为了减轻这个工作量我们自己定义一个着色器程序管理器,负责读取着色器程序文件,然后编译他们,链接并检查着色器程序有无错误发生。这也可以让我们把已经学到的知识封装到抽象的对象里。
|
||||
|
||||
我们首先顶一个着色器程序的头文件,如下:
|
||||
|
||||
#ifndef SHADER_H
|
||||
#define SHADER_H
|
||||
#include <string>
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
#include <iostream>
|
||||
using namespace std;
|
||||
#include <GL/glew.h>; // Include glew to get all the required
|
||||
OpenGL headers
|
||||
class Shader
|
||||
{
|
||||
public:
|
||||
// The program ID
|
||||
GLuint Program;
|
||||
// Constructor reads and builds the shader
|
||||
Shader(const GLchar* vertexSourcePath, const GLchar*fragmentSourcePath);
|
||||
// Use the program
|
||||
void Use();
|
||||
};
|
||||
#endif
|
||||
|
||||
着色器程序类包含一个着色器程序ID,有一个接受顶点和片段程序的接口,这个两个路径就是普通的文本文件就可以了。
|
||||
Use函数是一个工具属性的函数,主要是控制当前着色器程序是否激活。
|
||||
|
||||
读取着色器程序文件
|
||||
|
||||
Shader(const GLchar* vertexPath, const GLchar* fragmentPath)
|
||||
{
|
||||
// 1. Retrieve the vertex/fragment source code from
|
||||
filePath
|
||||
std::string vertexCode;
|
||||
std::string fragmentCode;
|
||||
try
|
||||
{
|
||||
// Open files
|
||||
std::ifstream vShaderFile(vertexPath);
|
||||
std::ifstream fShaderFile(fragmentPath);
|
||||
std::stringstream vShaderStream, fShaderStream;
|
||||
// Read file’s buffer contents into streams
|
||||
vShaderStream << vShaderFile.rdbuf();
|
||||
fShaderStream << fShaderFile.rdbuf();
|
||||
// close file handlers
|
||||
vShaderFile.close();
|
||||
fShaderFile.close();
|
||||
// Convert stream into GLchar array
|
||||
vertexCode = vShaderStream.str();
|
||||
fragmentCode = fShaderStream.str();
|
||||
}
|
||||
catch(std::exception e)
|
||||
{
|
||||
std::cout << "ERROR::SHADER::FILE_NOT_SUCCESFULLY_READ" <<
|
||||
std::endl;
|
||||
}
|
||||
|
||||
|
||||
接下来编译和链接这些程序,同时收集一些编译和链接的错误,来帮助我们调试。
|
||||
|
||||
// 2. Compile shaders
|
||||
GLuint vertex, fragment;
|
||||
GLint success;
|
||||
GLchar infoLog[512];
|
||||
// Vertex Shader
|
||||
vertex = glCreateShader(GL_VERTEX_SHADER);
|
||||
glShaderSource(vertex, 1, &vShaderCode, NULL);
|
||||
glCompileShader(vertex);
|
||||
// Print compile errors if any
|
||||
glGetShaderiv(vertex, GL_COMPILE_STATUS, &success);
|
||||
if(!success)
|
||||
{
|
||||
glGetShaderInfoLog(vertex, 512, NULL, infoLog);
|
||||
std::cout << "ERROR::SHADER::VERTEX::COMPILATION_FAILED\n"
|
||||
<< infoLog << std::endl;
|
||||
};
|
||||
// Similiar for Fragment Shader
|
||||
[...]
|
||||
// Shader Program
|
||||
this->Program = glCreateProgram();
|
||||
glAttachShader(this->Program, vertex);
|
||||
glAttachShader(this->Program, fragment);
|
||||
glLinkProgram(this->Program);
|
||||
// Print linking errors if any
|
||||
glGetProgramiv(this->Program, GL_LINK_STATUS, &success);
|
||||
if(!success)
|
||||
{
|
||||
glGetProgramInfoLog(this->Program, 512, NULL, infoLog);
|
||||
std::cout << "ERROR::SHADER::PROGRAM::LINKING_FAILED\n" <<
|
||||
infoLog << std::endl;
|
||||
}
|
||||
// Delete the shaders as they’re linked into our program now
|
||||
and no longer necessery
|
||||
glDeleteShader(vertex);
|
||||
glDeleteShader(fragment);
|
||||
|
||||
最后来实现一个use函数
|
||||
|
||||
void Use() { glUseProgram(this->Program); }
|
||||
接下来是一个使用这个简单实例:
|
||||
|
||||
Shader ourShader("path/to/shaders/shader.vs", "path/to/shaders/shader.frag");
|
||||
...
|
||||
while(...)
|
||||
{
|
||||
ourShader.Use();
|
||||
glUniform1f(glGetUniformLocation(ourShader.Program, "
|
||||
someUniform"), 1.0f);
|
||||
DrawStuff();
|
||||
}
|
||||
上面我们已经把顶点着色器和片段着色器代码分别放在shader.vs和shader.frag里面了,这些文件的名字和后缀名都可以随意命名的,只要符合文件名规范就好。
|
||||
完整的代码实例:
|
||||
|
||||
[使用的实例](http://learnopengl.com/code_viewer.php?code=getting-started/shaders-using-object)
|
||||
|
||||
[着色器类](http://learnopengl.com/code_viewer.php?type=header&code=shader)
|
||||
|
||||
[顶点着色器代码](http://learnopengl.com/code_viewer.php?type=vertex&code=getting-started/basic)
|
||||
|
||||
[片段着色器代码](http://learnopengl.com/code_viewer.php?type=fragment&code=getting-started/basic)
|
||||
|
||||
|
||||
**练习题**
|
||||
|
||||
1.通过调整的顶点着色器,以使三角形是倒置 [答案](http://learnopengl.com/code_viewer.php?code=getting-started/shaders-exercise1)
|
||||
|
||||
2.通过一个常量,使得三角在x方向偏移 [答案](http://learnopengl.com/code_viewer.php?code=getting-started/shaders-exercise2)
|
||||
|
||||
3.使用in 和out 关键字,把顶点着色器的位置数据作为片段着色器的颜色,然后看看得出的三角形颜色,进一步理解差值的问题,同时可以尝试回答下面的问题:为什么我们三角形左下侧有黑边?:[答案](http://learnopengl.com/code_viewer.php?code=getting-started/shaders-exercise3)
|
||||
|
||||
|
||||
|
Reference in New Issue
Block a user