#include "PGLFW.h"
#include <iostream>
#include <fstream>
#include <sstream>
using namespace std;
//--------------------------------------------------------------------------------------------- 回调
void framebuffer_size_callback(GLFWwindow* window, int width, int height)
{
PGLFW::Instance()->setWidth(width);
PGLFW::Instance()->setHeight(height);
glViewport(0, 0, width, height);
}
void processInput(GLFWwindow* window)
{
if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
{
glfwSetWindowShouldClose(window, true);
}
}
//---------------------------------------------------------------------------------------------
PGLFW* PGLFW::Instance()
{
static PGLFW ins;
return &ins;
}
PGLFW::PGLFW()
: m_Width(1024)
, m_Height(768)
{
}
PGLFW::~PGLFW()
{
//释放资源
glfwTerminate();
}
bool PGLFW::initWindow()
{
//[01] 初始化OpenGL上下文环境
glfwInit();
//[02] 选择版本 3.3
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
//[03] 选择OpenGL为核心模式
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
//[04] 创建窗体
m_Window = glfwCreateWindow(m_Width, m_Height, "My First OpenGL Window", nullptr, nullptr);
if (m_Window == nullptr) {
cout << "failed to create glfw window" << endl;
//释放资源
glfwTerminate();
return false;
}
//[05] 创建完窗体后通知GLFW将我们的上下文设置为当前线程的主上下文
glfwMakeContextCurrent(m_Window);
cout << "success to create glfw window" << endl;
return true;
}
bool PGLFW::initGLAD()
{
if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
{
std::cout << "Failed to initialize GLAD" << std::endl;
return false;
}
/*
* 在我们开始渲染之前还有一件重要的事情要做,
* 我们必须告诉OpenGL渲染窗口的尺寸大小,即视口(Viewport),这样OpenGL才只能知道怎样根据窗口大小显示数据和坐标。
* 我们可以通过调用glViewport函数来设置窗口的维度
*
* 函数前两个参数控制窗口左下角的位置。第三个和第四个参数控制渲染窗口的宽度和高度(像素)
*
* 我们实际上也可以将视口的维度设置为比GLFW的维度小,这样子之后所有的OpenGL渲染将会在一个更小的窗口中显示,
* 这样子的话我们也可以将一些其它元素显示在OpenGL视口之外。
*
* OpenGL幕后使用glViewport中定义的位置和宽高进行2D坐标的转换,将OpenGL中的位置坐标转换为你的屏幕坐标。
* 例如,OpenGL中的坐标(-0.5, 0.5)有可能(最终)被映射为屏幕中的坐标(200,450)。
* 注意,处理过的OpenGL坐标范围只为-1到1,因此我们事实上将(-1到1)范围内的坐标映射到(0, 800)和(0, 600)。
*
*/
glViewport(0, 0, m_Width, m_Height);
/*
* 然而,当用户改变窗口的大小的时候,视口也应该被调整。我们可以对窗口注册一个回调函数(Callback Function),它会在每次窗口大小被调整的时候被调用。
* 当窗口被第一次显示的时候framebuffer_size_callback也会被调用。对于视网膜(Retina)显示屏,width和height都会明显比原输入值更高一点。
*
* 我们还可以将我们的函数注册到其它很多的回调函数中。
* 比如说,我们可以创建一个回调函数来处理手柄输入变化,处理错误消息等。我们会在创建窗口之后,渲染循环初始化之前注册这些回调函数。
*/
glfwSetFramebufferSizeCallback(m_Window, framebuffer_size_callback);
return true;
}
void PGLFW::initShader()
{
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("Shader/vertex.glsl");
_fShaderFile.open("Shader/fragment.glsl");
std::stringstream _vShaderStream;
std::stringstream _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;
unsigned int _fragID = 0;
char _infoLog[512];
int _successFlag = 0;
/*
* [01] 编译
*/
//vertexShader
_vertexID = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(_vertexID, 1, &_vShaderStr, nullptr);
glCompileShader(_vertexID);
glGetShaderiv(_vertexID, GL_COMPILE_STATUS, &_successFlag);
if (!_successFlag)
{
glGetShaderInfoLog(_vertexID, 512, nullptr, _infoLog);
std::cout << _infoLog;
}
//fragmentShader
_fragID = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(_fragID, 1, &_fShaderStr, nullptr);
glCompileShader(_fragID);
glGetShaderiv(_fragID, GL_COMPILE_STATUS, &_successFlag);
if (!_successFlag)
{
glGetShaderInfoLog(_fragID, 512, nullptr, _infoLog);
std::cout << _infoLog;
}
/*
* [02] 链接
*/
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, nullptr, _infoLog);
std::cout << _infoLog;
}
glDeleteShader(_vertexID);
glDeleteShader(_fragID);
}
void PGLFW::setMatrix(const std::string& _name, glm::mat4 _matrix) const
{
glUniformMatrix4fv(glGetUniformLocation(m_shaderProgram, _name.c_str()), 1, GL_FALSE, glm::value_ptr(_matrix));
}
void PGLFW::rend()
{
/*
* 在每个新的渲染迭代开始的时候我们总是希望清屏,否则我们仍能看见上一次迭代的渲染结果(这可能是你想要的效果,但通常这不是)。
* 我们可以通过调用glClear函数来清空屏幕的颜色缓冲,它接受一个缓冲位(Buffer Bit)来指定要清空的缓冲,
* 可能的缓冲位有GL_COLOR_BUFFER_BIT,GL_DEPTH_BUFFER_BIT和GL_STENCIL_BUFFER_BIT。由于现在我们只关心颜色值,所以我们只清空颜色缓冲。
*/
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glEnable(GL_DEPTH_TEST);
//------------------------------------
//使用m_shaderProgram进行渲染
glUseProgram(m_shaderProgram);
#if 0
//使用m_VAO管理的VBO进行绘图
glBindVertexArray(m_VAO_Triangle);
glDrawArrays(GL_TRIANGLES, 0, 3);
glBindVertexArray(m_VAO_Rectangle);
glDrawArrays(GL_TRIANGLES, 0, 6);
#endif
glm::mat4 _modelMatrix(1.0f);
_modelMatrix = glm::rotate(_modelMatrix, glm::radians((float)glfwGetTime() * (0 + 1) * 10), glm::vec3(0.0f, 1.0f, 0.0f));
setMatrix("_modelMatrix", _modelMatrix);
setMatrix("_viewMatrix", m_Camera.getMatrix());
setMatrix("_projMatrix", glm::perspective(glm::radians(45.0f), (float)m_Width / (float)m_Height, 0.1f, 100.0f));
glBindVertexArray(m_VAO_Cube);
glDrawArrays(GL_TRIANGLES, 0, 36);
glUseProgram(0);
//------------------------------------
}
void PGLFW::run()
{
while (!glfwWindowShouldClose(m_Window))
{
processInput(m_Window);
//----------------------- 这个中间可以做一些渲染 ---------------------------------------------||||||
rend();
//---------------------------------------------------------------------------------------------------
/*
* 双缓冲(Double Buffer)
* 应用程序使用单缓冲绘图时可能会存在图像闪烁的问题。 这是因为生成的图像不是一下子被绘制出来的,
* 而是按照从左到右,由上而下逐像素地绘制而成的。最终图像不是在瞬间显示给用户,而是通过一步一步生成的,
* 这会导致渲染的结果很不真实。为了规避这些问题,我们应用双缓冲渲染窗口应用程序。前缓冲保存着最终输出的图像,
* 它会在屏幕上显示;
* 而所有的的渲染指令都会在后缓冲上绘制。当所有的渲染指令执行完毕后,我们交换(Swap)前缓冲和后缓冲,
* 这样图像就立即呈显出来,之前提到的不真实感就消除了。
*/
glfwSwapBuffers(m_Window);
//处理一下相关的事件(鼠标键盘等)
glfwPollEvents();
}
}
void PGLFW::initRendData()
{
m_Camera.lookAt(glm::vec3(0.0f, 0.0f, 3.0f), glm::vec3(0.0f, 0.0f, -1.0f), glm::vec3(0.0f, 1.0f, 0.0f));
m_Camera.setSpeed(0.005f);
initModle();
}
void PGLFW::initModle()
{
//------------------------------------------------------------------------------------------------- triangle
//三角形
float vertices_triangle[] =
{
0.0f, 0.5f, 0.0f, 1.0f, 0.0f, 0.0f,
-0.5f, -0.5f, 0.0f, 0.0f, 1.0f, 0.0f,
0.5f, -0.5f, 0.0f, 0.0f, 0.0f, 1.0f,
};
//VAO是管理数据的,它里面没有具体数据,所以需要创建VBO,向VBO中添加数据
glGenVertexArrays(1, &m_VAO_Triangle);
glBindVertexArray(m_VAO_Triangle);
glGenBuffers(1, &m_VBO_Triangle);
glBindBuffer(GL_ARRAY_BUFFER, m_VBO_Triangle);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices_triangle), vertices_triangle, GL_STATIC_DRAW);
//告诉OpenGL怎样解析它的数据
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)0);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)(sizeof(float) * 3));
//启用锚点
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
//解除绑定
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
//------------------------------------------------------------------------------------------------- rectangle
//矩形
float vertices_rectangle[] =
{
-0.5f, 0.5f, 0.0f, 1.0f, 0.2f, 0.5f,
0.5f, 0.5f, 0.0f, 1.0f, 0.2f, 0.5f,
-0.5f, -0.5f, 0.0f, 1.0f, 0.2f, 0.5f,
0.5f, 0.5f, 0.0f, 1.0f, 0.2f, 0.5f,
-0.5f, -0.5f, 0.0f, 1.0f, 0.2f, 0.5f,
0.5f, -0.5f, 0.0f, 1.0f, 0.2f, 0.5f,
};
glGenVertexArrays(1, &m_VAO_Rectangle);
glBindVertexArray(m_VAO_Rectangle);
glGenBuffers(1, &m_VBO_Rectangle);
glBindBuffer(GL_ARRAY_BUFFER, m_VBO_Rectangle);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices_rectangle), vertices_rectangle, GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)0);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)(sizeof(float) * 3));
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
//------------------------------------------------------------------------------------------------- cube
//立方体
float vertices_cube[] =
{
-0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f,
0.5f, -0.5f, -0.5f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f,
0.5f, 0.5f, -0.5f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f,
0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f,
-0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f,
-0.5f, -0.5f, -0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f,
-0.5f, -0.5f, 0.5f, 1.0f, 0.5f, 0.0f, 0.0f, 0.0f,
0.5f, -0.5f, 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f,
0.5f, 0.5f, 0.5f, 1.0f, 0.5f, 0.5f, 1.0f, 1.0f,
0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 1.0f,
-0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f,
-0.5f, -0.5f, 0.5f, 1.0f, 0.5f, 0.5f, 0.0f, 0.0f,
-0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f,
-0.5f, 0.5f, -0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 1.0f,
-0.5f, -0.5f, -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f,
-0.5f, -0.5f, -0.5f, 1.0f, 0.5f, 0.5f, 0.0f, 1.0f,
-0.5f, -0.5f, 0.5f, 1.0f, 0.5f, 0.5f, 0.0f, 0.0f,
-0.5f, 0.5f, 0.5f, 1.0f, 0.5f, 0.5f, 1.0f, 0.0f,
0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f,
0.5f, 0.5f, -0.5f, 1.0f, 0.5f, 0.5f, 1.0f, 1.0f,
0.5f, -0.5f, -0.5f, 1.0f, 0.5f, 0.5f, 0.0f, 1.0f,
0.5f, -0.5f, -0.5f, 1.0f, 0.5f, 0.5f, 0.0f, 1.0f,
0.5f, -0.5f, 0.5f, 1.0f, 0.5f, 0.5f, 0.0f, 0.0f,
0.5f, 0.5f, 0.5f, 1.0f, 0.5f, 0.5f, 1.0f, 0.0f,
-0.5f, -0.5f, -0.5f, 0.5f, 0.5f, 0.5f, 0.0f, 1.0f,
0.5f, -0.5f, -0.5f, 0.5f, 0.5f, 0.5f, 1.0f, 1.0f,
0.5f, -0.5f, 0.5f, 1.0f, 0.5f, 0.0f, 1.0f, 0.0f,
0.5f, -0.5f, 0.5f, 0.0f, 0.5f, 0.5f, 1.0f, 0.0f,
-0.5f, -0.5f, 0.5f, 0.0f, 0.5f, 0.5f, 0.0f, 0.0f,
-0.5f, -0.5f, -0.5f, 0.0f, 0.5f, 0.5f, 0.0f, 1.0f,
-0.5f, 0.5f, -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f,
0.5f, 0.5f, -0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 1.0f,
0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f,
0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f,
-0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 0.0f,
-0.5f, 0.5f, -0.5f, 0.5f, 1.0f, 0.5f, 0.0f, 1.0f
};
glGenVertexArrays(1, &m_VAO_Cube);
glBindVertexArray(m_VAO_Cube);
glGenBuffers(1, &m_VBO_Cube);
glBindBuffer(GL_ARRAY_BUFFER, m_VBO_Cube);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices_cube), vertices_cube, GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)0);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(sizeof(float) * 3));
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
//----------------------------------------------------------------------------------------------------------------------------------------
}
源码:Hello_OpenGL.zip-图像处理文档类资源-CSDN下载
|