目录
(一)OpenGL加工流程可分为三部分:Asset区。组件生产线。组件装配。
本文将从OpenGL生产流程角度,整理learn OpenGL的应用纹理程序和摄像机的步骤。也对OpenGL近期所学做了一下整理。
(一)OpenGL加工流程可分为三部分:Asset区。组件生产线。组件装配。
(1) Asset
(2)组件封装
(3)组件装配
(二)组件分析
1.组件:生成模型轮廓。
需将C++数据,通过锚点定位,传入至顶点着色器对应的各个属性数组。
2. 组件装配:组合组件,管理渲染信息。
3.组件:生成纹理。
需将读入的图片数据传入顶点着色器,并再由顶点着色器传入至片段着色器,数据处理由片段着色器完成。
4.组件:摄像机
这里的摄像机没有封装成类。我们可以把摄像机理解成坐标的变换。空间中的一点通过摄像机矩阵,变换成为摄像机视角,再通过投影矩阵变换成为屏幕视角。在顶点着色器中的矩阵处理其实就可以看成一个组件“函数”。
即摄像机可以看作 矩阵作用于顶点位置坐标的结果。下为顶点着色器文件的代码。
观察(1)(2)发现,这更是像写给Shader着色器的注释。我们的目标就是将所有的、C++数据处理成着色器能看懂的 着色器数据。
分析:(1)使之生成一份专属于摄像机和投影矩阵的矩阵数据。 后面的(2)解释了uniform变量的名字,所对应的数据是什么。类似于宏替换的方法传数据。并且注意要在shaderProgram程序激活后,再去传数据才会生效。
有些情况,关于一些绑定和配置的操作 是不能封装进组件内的。要根据组件的特点灵活应用。比如涉及到shader中的变量,就要把绑定操作独立出来,方便后续调用。另外可能涉及到批量应用的组件也不适用(如纹理组件:导入多张纹理后还要指定纹理单元)。
运行结果:
(三)代码:
main.cpp
#define _CRT_SECURE_NO_DEPRECATE
#include"Base.h"
#include"shader.h"
#include"ffImage.h"
//================Asset============
unsigned int VAO,VBO;
unsigned int _texture=0;
unsigned int _texture2 = 1;
Shader _shaderProgram;
ffImage* _pImage = NULL;
glm::mat4 _viewMatrix(1.0f);
glm::mat4 _projMatrix(1.0f);
//================Asset============
//=组件生产线====================
void initModel()
{
float vertices[] =
{
-0.5f, -0.5f, -0.5f, 0.0f, 0.0f,
0.5f, -0.5f, -0.5f, 1.0f, 0.0f,
0.5f, 0.5f, -0.5f, 1.0f, 1.0f,
0.5f, 0.5f, -0.5f, 1.0f, 1.0f,
-0.5f, 0.5f, -0.5f, 0.0f, 1.0f,
-0.5f, -0.5f, -0.5f, 0.0f, 0.0f,
-0.5f, -0.5f, 0.5f, 0.0f, 0.0f,
0.5f, -0.5f, 0.5f, 1.0f, 0.0f,
0.5f, 0.5f, 0.5f, 1.0f, 1.0f,
0.5f, 0.5f, 0.5f, 1.0f, 1.0f,
-0.5f, 0.5f, 0.5f, 0.0f, 1.0f,
-0.5f, -0.5f, 0.5f, 0.0f, 0.0f,
-0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
-0.5f, 0.5f, -0.5f, 1.0f, 1.0f,
-0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
-0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
-0.5f, -0.5f, 0.5f, 0.0f, 0.0f,
-0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
0.5f, 0.5f, -0.5f, 1.0f, 1.0f,
0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
0.5f, -0.5f, 0.5f, 0.0f, 0.0f,
0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
-0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
0.5f, -0.5f, -0.5f, 1.0f, 1.0f,
0.5f, -0.5f, 0.5f, 1.0f, 0.0f,
0.5f, -0.5f, 0.5f, 1.0f, 0.0f,
-0.5f, -0.5f, 0.5f, 0.0f, 0.0f,
-0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
-0.5f, 0.5f, -0.5f, 0.0f, 1.0f,
0.5f, 0.5f, -0.5f, 1.0f, 1.0f,
0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
-0.5f, 0.5f, 0.5f, 0.0f, 0.0f,
-0.5f, 0.5f, -0.5f, 0.0f, 1.0f
};
glGenVertexArrays(1, &VAO);
glBindVertexArray(VAO);
glGenBuffers(1, &VBO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices),vertices ,GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)0);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)(sizeof(float)*3));
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
glBindVertexArray(0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
}
void initShader(const char* _vertexPath, const char* _fragPath)
{
_shaderProgram.initShader(_vertexPath, _fragPath);
}
void initTexture()
{
glGenTextures(1, &_texture);
_pImage = ffImage::readFromFile("res/wall.jpg");
glBindTexture(GL_TEXTURE_2D, _texture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, _pImage->getWidth(), _pImage->getHeight(), 0, GL_RGBA, GL_UNSIGNED_BYTE, _pImage->getData());
glGenTextures(2, &_texture2);
_pImage = ffImage::readFromFile("res/awesomeface.png");
glBindTexture(GL_TEXTURE_2D, _texture2);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, _pImage->getWidth(), _pImage->getHeight(), 0, GL_RGBA, GL_UNSIGNED_BYTE, _pImage->getData());
}
void rend()
{
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
glEnable(GL_DEPTH_TEST);
_viewMatrix = glm::lookAt(glm::vec3(3.0f, 3.0f, 3.0f), glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(0.0f, 1.0f, 0.0f));//定制摄像机矩阵
_projMatrix = glm::perspective(glm::radians(30.0f), 1.0f, 0.1f, 100.0f); //定制投影矩阵
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, _texture);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, _texture2);
_shaderProgram.shader_Begin();
//传入矩阵数据
_shaderProgram.setInt("_texture", 0);
_shaderProgram.setInt("_texture2", 1);
_shaderProgram.setMartrix("_viewMatrix", _viewMatrix);//给对应名字的矩阵传入数据
_shaderProgram.setMartrix("_projMatrix", _projMatrix);
//传入图元顶点对象
glBindVertexArray(VAO);
glDrawArrays(GL_TRIANGLES, 0, 36);
_shaderProgram.shader_End();
}
//=组件调用按====================
int main()
{
GLFWwindow* wWindow;
glfwInit();
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3.0);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3.0);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
wWindow = glfwCreateWindow(800, 800, "wuyutong", NULL, NULL);
if (!wWindow)
{
std::cout << "Fail to Create Window" << std::endl;
glfwTerminate();//释放资源
return -1;
}
glfwMakeContextCurrent(wWindow);
if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
{
std::cout << "Failed to intialize GLAD" << std::endl;
}
//组件装配区================================================
initModel();
initTexture();
_shaderProgram.initShader("vertexShader.glsl", "fragmentShader.glsl");
//组件装配区================================================
while (!glfwWindowShouldClose(wWindow))
{
rend();
glfwSwapBuffers(wWindow);
glfwPollEvents();
}
glDeleteBuffers(1, &VBO);
glfwTerminate();
return 0;
}
Shader代码
fragmentShader.glsl
#version 330 core
out vec4 FragColor;
in vec2 outUV;
uniform sampler2D _texture;
uniform sampler2D _texture2;
void main()
{
vec4 _texture=texture(_texture,outUV).xyzw;
vec4 _texture2=texture(_texture2,outUV).xyzw;
FragColor =mix(_texture,_texture2,0.2);
};
vertexShader.glsl
#version 330 core
layout (location = 0) in vec3 aPos;
layout (location = 1) in vec2 aUV;
out vec2 outUV;
uniform mat4 _viewMatrix;
uniform mat4 _projMatrix;
void main()
{
gl_Position = _projMatrix*_viewMatrix * vec4(aPos.x, aPos.y, aPos.z,1.0);
outUV = aUV;
};
Shader类 Shader.h
#pragma once
#include "Base.h"
class Shader
{
public:
Shader()
{
m_shaderProgram = 0;
}
~Shader(){}
void initShader(const char* _vertexPath, const char* _fragPath);
void shader_Begin()
{
glUseProgram(m_shaderProgram);
}
void shader_End()
{
glUseProgram(0);
}
void setInt(const std::string& name, int value) const
{
glUniform1i(glGetUniformLocation(m_shaderProgram, name.c_str()), value);
}
void setMartrix(const std::string& _name, glm::mat4 matrix)const;
private:
unsigned int m_shaderProgram;
};
Shader.cpp
#include "shader.h"
void Shader::initShader(const char* _vertexPath, const char* _fragPath)
{
std::string _vertexCode("");
std::string _fragCode("");
std::ifstream _vShaderFile;
std::ifstream _fShaderFile;
_vShaderFile.exceptions(std::ifstream::failbit | std::ifstream::badbit);
_fShaderFile.exceptions(std::ifstream::failbit | std::ifstream::badbit);
try
{
_vShaderFile.open(_vertexPath);
_fShaderFile.open(_fragPath);
std::stringstream _vShaderStream, _fShaderStream;
_vShaderStream << _vShaderFile.rdbuf();
_fShaderStream << _fShaderFile.rdbuf();
_vertexCode = _vShaderStream.str();
_fragCode = _fShaderStream.str();
}
catch (std::ifstream::failure e)
{
std::string errStr = "read shader fail";
std::cout << errStr << std::endl;
}
const char* _vShaderStr = _vertexCode.c_str();
const char* _fShaderStr = _fragCode.c_str();
//shader的编译链接
unsigned int _vertexID = 0, _fragID = 0;
char _infoLog[512];
int _successFlag = 0;
//编译
_vertexID = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(_vertexID, 1, &_vShaderStr, NULL);
glCompileShader(_vertexID);
glGetShaderiv(_vertexID, GL_COMPILE_STATUS, &_successFlag);
if (!_successFlag)
{
glGetShaderInfoLog(_vertexID, 512, NULL, _infoLog);
std::string errStr(_infoLog);
std::cout << _infoLog << std::endl;
}
_fragID = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(_fragID, 1, &_fShaderStr, NULL);
glCompileShader(_fragID);
glGetShaderiv(_fragID, GL_COMPILE_STATUS, &_successFlag);
if (!_successFlag)
{
glGetShaderInfoLog(_fragID, 512, NULL, _infoLog);
std::string errStr(_infoLog);
std::cout << _infoLog << std::endl;
}
//链接
m_shaderProgram = glCreateProgram();
glAttachShader(m_shaderProgram, _vertexID);
glAttachShader(m_shaderProgram, _fragID);
glLinkProgram(m_shaderProgram);
glGetProgramiv(m_shaderProgram, GL_LINK_STATUS, &_successFlag);
if (!_successFlag)
{
glGetProgramInfoLog(m_shaderProgram, 512, NULL, _infoLog);
std::string errStr(_infoLog);
std::cout << _infoLog << std::endl;
}
glDeleteShader(_vertexID);
glDeleteShader(_fragID);
}
void Shader::setMartrix(const std::string& _name, glm::mat4 _matrix)const
{
glUniformMatrix4fv(glGetUniformLocation(m_shaderProgram, _name.c_str()), 1, GL_FALSE, glm::value_ptr(_matrix));
//1个,列优先,数据转化数组
}