和前面使用不同的VBO和VAO缓存顶点数据一样,不同的片元Shader我们需要创建多个片元ShaderID,shader进程,并且对进程进行连接。代码如下:
/*引入OpneGL方法库头文件*/
#include <glad/glad.h>
#include <GLFW/glfw3.h>
/*引入文件里头文件,方便我们调用方法进行问题检查*/
#include <iostream>
/*视口变换回调函数*/
void framebuffer_size_callback(GLFWwindow *window, int width, int height)
{
glViewport(0, 0, width, height);
}
/*输入设置,比如按下Esc键关闭窗口*/
void player_input(GLFWwindow *window)
{
if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
glfwSetWindowShouldClose(window, true);
}
/*顶点Shader源码*/
const char *vertexShaderSource = "#version 330 core\n"
"layout (location=0) in vec3 aPos;\n"
"void main()\n"
"{\n"
"gl_Position = vec4(aPos.x,aPos.y,aPos.z,1.0);\n"
"}\0";
/*片元Shader源码*/
const char *fragmentShaderSource = "#version 330 core\n"
"out vec4 finalColor;\n"
"void main()\n"
"{\n"
"finalColor = vec4(1.0);\n"
"}\0";
const char *fragmentShaderSource_Second = "#version 330 core\n"
"out vec4 finalColor;\n"
"void main()\n"
"{\n"
"finalColor = vec4(1.0,1.0,0.0,1.0);\n"
"}\0";
/*声明屏幕的宽度和高度,分别为800和600*/
const unsigned int Screen_Width = 800;
const unsigned int Screen_Height = 600;
/*主函数*/
int main()
{
/*初始化GLFW*/
glfwInit();
/*此函数基于OpenGL 3.3版本展开,需要告诉GLFW我们要使用的OpenGL版本是3.3,这样GLFW会在创建OpenGL上下文时做出适当的调整。
这也可以确保用户在没有适当的OpenGL版本支持的情况下无法运行。将主版本号(Major)和次版本号(Minor)都设为3。同样你可以修改它们的版本*/
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
/*我们明确告诉GLFW我们使用的是核心模式(Core-profile)
明确告诉GLFW我们需要使用核心模式意味着我们只能使用OpenGL功能的一个子集(没有我们已不再需要的向后兼容特性)。*/
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
/* 如果使用的是Mac OS X系统,还需要加下面这行代码到你的初始化代码中这些配置才能起作用*/
#ifdef __APPLE__
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GLFW_TRUE);
#endif
/*设置窗口对象 */
GLFWwindow *window = glfwCreateWindow(Screen_Width, Screen_Height, "LearOpenGLWidnow", NULL, NULL);
/*如果窗口对象创建失败,在终端输出日志,并且释放内存*/
if (window == NULL)
{
std::cout << "Fail to create window !" << std::endl;
glfwTerminate();
return -1;
}
/*窗口对象创建成功,使用这个窗口 */
glfwMakeContextCurrent(window);
/*窗口大小变换回调*/
glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);
/*检测是否加载所有glad方法库的函数 */
if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
{
std::cout << "Fail to initialize glad !" << std::endl;
return -1;
}
/*构建编译顶点Shader*/
unsigned int vertexShader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertexShader, 1, &vertexShaderSource, NULL);
glCompileShader(vertexShader);
/*检查是否构建编译成功*/
int success;
char infoLog[512];
glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &success);
if (!success)
{
glGetShaderInfoLog(vertexShader, sizeof(infoLog), NULL, infoLog);
std::cout << "Error:Shader:VertexShader:Compile_Status_Failure" << infoLog << std::endl;
return -1;
}
/*构建编译片元Shader*/
unsigned int fragmentShader[2];
fragmentShader[0] = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentShader[0], 1, &fragmentShaderSource, NULL);
glCompileShader(fragmentShader[0]);
fragmentShader[1] = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentShader[1], 1, &fragmentShaderSource_Second, NULL);
glCompileShader(fragmentShader[1]);
/*链接顶点Shader和片元Shader组成Shader进程 */
unsigned int shaderProgram[2];
shaderProgram[0] = glCreateProgram();
glAttachShader(shaderProgram[0], vertexShader);
glAttachShader(shaderProgram[0], fragmentShader[0]);
glLinkProgram(shaderProgram[0]);
shaderProgram[1] = glCreateProgram();
glAttachShader(shaderProgram[1], vertexShader);
glAttachShader(shaderProgram[1], fragmentShader[1]);
glLinkProgram(shaderProgram[1]);
/*删除顶点Shader与片元Shader内存*/
glDeleteShader(vertexShader);
glDeleteShader(fragmentShader[0]);
glDeleteShader(fragmentShader[1]);
/*设置三角形顶点数据 */
float first_vertexts[]{
-0.9, -0.5, 0.0,
-0.4, -0.5, 0.0,
-0.65, 0.5, 0.0};
float second_vertexts[]{
-0.4, -0.5, 0.0,
0.1, -0.5, 0.0,
-0.15, 0.5, 0.0};
/*声明顶点缓冲物体(Vertex Buffer Object)id,顶点数组物体(Vertex Array Objet)id与元素缓冲物体(Element Buffer Object)id*/
unsigned int VBO[2], VAO[2];
/*生成顶点数组 */
glGenVertexArrays(2, VAO);
/*生成顶点缓冲区*/
glGenBuffers(2, VBO);
/*先绑定顶点数组,在绑定和设置缓冲区,然后绑定顶点属性*/
/*绑定顶点数组*/
glBindVertexArray(VAO[0]);
/*绑定顶点缓冲区数据*/
glBindBuffer(GL_ARRAY_BUFFER, VBO[0]);
glBufferData(GL_ARRAY_BUFFER, sizeof(first_vertexts), first_vertexts, GL_STATIC_DRAW);
/*绑定顶点属性*/
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(float) * 3, (void *)0);
/*以顶点属性位置值作为参数,启用顶点属性;顶点属性默认是禁用的*/
glEnableVertexAttribArray(0);
/*先绑定顶点数组,在绑定和设置缓冲区,然后绑定顶点属性*/
/*绑定顶点数组*/
glBindVertexArray(VAO[1]);
/*绑定顶点缓冲区数据*/
glBindBuffer(GL_ARRAY_BUFFER, VBO[1]);
glBufferData(GL_ARRAY_BUFFER, sizeof(second_vertexts), second_vertexts, GL_STATIC_DRAW);
/*绑定顶点属性*/
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(float) * 3, (void *)0);
/*以顶点属性位置值作为参数,启用顶点属性;顶点属性默认是禁用的*/
glEnableVertexAttribArray(0);
/*当窗口没有被关闭时,执行渲染循环 */
while (!glfwWindowShouldClose(window))
{
/* code */
/*按键输入以及对应操作事件*/
player_input(window);
/*渲染*/
/*清除颜色缓冲区*/
glClear(GL_COLOR_BUFFER_BIT);
/*使用Shader进程*/
glUseProgram(shaderProgram[0]);
glBindVertexArray(VBO[0]);
/*绘制顶点数据*/
glDrawArrays(GL_TRIANGLES, 0, 3);
glUseProgram(shaderProgram[1]);
glBindVertexArray(VBO[1]);
/*绘制顶点数据*/
glDrawArrays(GL_TRIANGLES, 0, 3);
/*交换缓存区 */
glfwSwapBuffers(window);
/*执行事件 */
glfwPollEvents();
}
/*删除对象,缓存,进程*/
glDeleteVertexArrays(2, VAO);
glDeleteBuffers(2, VBO);
glDeleteProgram(shaderProgram[0]);
glDeleteProgram(shaderProgram[1]);
/*退出循环后释放内存*/
glfwTerminate();
return 0;
}