实现流程
1.创建一个基本的窗口.
2.利用用C++封装的Program和Shader
3.简单创建自己需要的顶点数据和索引数据
4.调用对应的绘制方法. glDrawArrays 或者 glDrawElements
#include "MyOpenglWindow.hpp"
#include <iostream>
#include <glad/glad.h>
#include <GLFW/glfw3.h>
#include "MyShader.hpp"
#include "MyProgram.hpp"
#define STRINGIZE(x) #x
#define SHADER(shader) STRINGIZE(shader)
// 模拟顶点数据
//三角形
GLfloat triangleVertices[] = {
-0.5f, -0.5f, 0.0f, //左下
0.5f, -0.5f, 0.0f, //右下
0.0f, 0.5f, 0.0f, //中上
};
//正方形
GLfloat squareVertices[] = {
-0.5f, -0.5f, 0.0f, //左下
0.5f, -0.5f, 0.0f, //右下
0.5f, 0.5f, 0.0f, //右上
-0.5f, 0.5f, 0.0f, //左上
};
unsigned int squareIndices[] = { // 注意索引从0开始!
0, 1, 2, // 第一个三角形
0, 3, 2 // 第二个三角形
};
//顶点着色器程序
char *vertexShaderStr = SHADER(
\#version 330 core\n
layout (location = 0) in vec3 position;
void main()
{
gl_Position = vec4(position.x, position.y, position.z, 1.0);
}
);
//片元着色器程序
char *fragmentShaderSrc = SHADER(
\#version 330 core\n
out vec4 color;
void main()
{
color = vec4(1.0f, 0.5f, 0.2f, 1.0f);
}
);
bool showTriangle = false;
int runMyOpenGlWindow() {
int result = glfwInit();
if (result == GL_FALSE) {
printf("glfwInit 初始化失败");
return -1;
}
//这里的宏不好提示出来, 根据LearnOpenGL的文档提示, 用这三个
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
//Mac平台需要加入
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GLFW_TRUE);
//创建一个Window
GLFWwindow *window = glfwCreateWindow(600, 400, "My Opengl Window", NULL, NULL);
if(!window) {
printf("window 创建失败");
}
//opengl运行模式 -- 单线程, 理解为跟当前的Window做一次绑定操作.
glfwMakeContextCurrent(window);
//任何的OpenGL接口调用都必须在初始化GLAD库后才可以正常访问。如果成功的话,该接口将返回GL_TRUE,否则就会返回GL_FALSE。
gladLoadGLLoader((GLADloadproc)glfwGetProcAddress);
//----------------------------------------------------------------------
//先创建我们的Program对象, 加载顶点着色器程序和片元着色器程序
MyProgram myProgram = MyProgram(vertexShaderStr, fragmentShaderSrc);
GLuint VBO , VAO , EBO;
unsigned int squareIndicesCount = 0;
showTriangle = false;
if (showTriangle) {
//创建VBO
glGenBuffers(1, &VBO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(triangleVertices), triangleVertices, GL_STATIC_DRAW);
//创建VAO
glGenVertexArrays(1, &VAO);
glBindVertexArray(VAO);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), (GLvoid*)0);
glEnableVertexAttribArray(0);
//解绑VAO
glBindVertexArray(0);
} else {
//创建VBO
glGenBuffers(1, &VBO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(squareVertices), squareVertices, GL_STATIC_DRAW);
//创建VAO
glGenVertexArrays(1, &VAO);
glBindVertexArray(VAO);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), (GLvoid*)0);
glEnableVertexAttribArray(0);
//创建EBO, 这里的EBO相当于索引的作用
glGenBuffers(1, &EBO);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(squareIndices), squareIndices, GL_STATIC_DRAW);
//解绑VAO
glBindVertexArray(0);
//计算索引个数
squareIndicesCount = sizeof(squareIndices)/sizeof(squareIndices[0]);
}
//在glUseProgram函数调用之后,每个着色器调用和渲染调用都会使用这个程序对象(也就是之前写的着色器)了。
glUseProgram(myProgram.program);
//线框模式
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
//----------------------------------------------------------------------
//进行绘制
while(!glfwWindowShouldClose(window)){
//检查事件
glfwPollEvents();
//渲染指令
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
//这里VAO也行, VBO也行
glBindVertexArray(VAO);
if (showTriangle) {
glDrawArrays(GL_TRIANGLES, 0, 3);
} else {
//使用EBO
glDrawElements(GL_TRIANGLES, squareIndicesCount, GL_UNSIGNED_INT, 0);
//不使用EBO
// glDrawArrays(GL_TRIANGLE_FAN, 0, 6);
/*
v参数1:有三种取值
1.GL_TRIANGLES:每三个顶之间绘制三角形,之间不连接
2.GL_TRIANGLE_FAN:以V0V1V2,V0V2V3,V0V3V4,……的形式绘制三角形
3.GL_TRIANGLE_STRIP:顺序在每三个顶点之间均绘制三角形。
这个方法可以保证从相同的方向上所有三角形均被绘制。以V0V1V2,V1V2V3,V2V3V4……的形式绘制三角形
*/
}
//解绑VAO
glBindVertexArray(0);
//交换缓冲
glfwSwapBuffers(window);
}
//程序销毁
glfwTerminate();
return 1;
}
在main.cpp中执行
int main(int argc, const char * argv[]) {
return runMyOpenGlWindow();
}
注意点 :
1.创建了一个SHADER宏 , 里面写的内容直接会转为字符串.
- 顶点着色器程序vertexShaderStr 和片元着色器程序fragmentShaderSrc暂时不用管它是什么一回事, 假装默认就是这样. 还需要研究Shader编程.
3.理解绘制的流程, 绘制的方法.
4.理解VAO,VBO,EBO的buffer绑定方式,怎么(调用什么函数)把数据拷贝到缓冲区中
5.整个流程理解了, 开始研究Shader, 着色器语言.
6.后续实现 : 通过研究Shader,实现一个渐变的正方形
效果图 :
正方形
网友评论