Aquacolor

Aquacolor



LearningOpenGL【4】

Gumdrop · 2025-08-26 · 23浏览 · 未分类


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";
unsigned int vertexShader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertexShader, 1, &vertexShaderSource, NULL);//const GLchar*const*类型
glCompileShader(vertexShader);
{
    int  success;
    char infoLog[512];
    glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &success);
    if (!success)
    {
        glGetShaderInfoLog(vertexShader, 512, NULL, infoLog);
        std::cout << "ERROR::SHADER::VERTEX::COMPILATION_FAILED\n" << infoLog << std::endl;
    }
}//这部分是用来判断是否编译成功的。
//GLSL文件是文本文件,所以硬编码在源代码中也可以的。
//用于Shader的是create、source、compile、delete(在use后才能使用它),与前面对象的创建工作流不同。

const char* fragmentShaderSource = R"(#version 330 core
out vec4 FragColor;

void main()
{
FragColor = vec4(1.0f, 0.5f, 0.2f, 1.0f);
} )";
unsigned int fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentShader, 1, &fragmentShaderSource, NULL);//const GLchar*const*类型
glCompileShader(fragmentShader);
{
    int  success;
    char infoLog[512];
    glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &success);
    if (!success)
    {
        glGetShaderInfoLog(fragmentShader, 512, NULL, infoLog);
        std::cout << "ERROR::SHADER::FRAGMENT::COMPILATION_FAILED\n" << infoLog << std::endl;
    }
}

unsigned int shaderProgram = glCreateProgram();
glAttachShader(shaderProgram, vertexShader);
glAttachShader(shaderProgram, fragmentShader);
glLinkProgram(shaderProgram);
{
    int success;
    char infoLog[512];
    glGetProgramiv(shaderProgram, GL_LINK_STATUS, &success);
    if (!success) {
        glGetProgramInfoLog(shaderProgram, 512, NULL, infoLog);
        std::cerr << "ERROR::PROGRAM::LINK_FAILED\n" << infoLog << std::endl;
    }
}
glDeleteShader(vertexShader);
glDeleteShader(fragmentShader);
//管线其实就是其中的Program。
//使用了create、attach、link、use。
//在这之后调用渲染的语句将会使用该管线,即该程序已作为系统状态。
//删除掉Shader并不会使得管线失效,所以可以删掉它。
  1. Shader工作流

    记忆:创建/删除、配置源码、编译

  2. Program工作流

    记忆:创建、连接、链接、使用

    其使用应该在render loop中才符合语义,因为每个循环的绘制方式都可能不同。

    每种mode的shader只能连接一个,且一个有效的程序必须要实现vertex shader和fragment shader。

  3. Render Loop通常写法

    glfwSetFramebufferSizeCallback(window,
     [](GLFWwindow* window, int width, int height) {glViewport(0, 0, width, height); });
    //在之前讲过,要看到窗口才能进行调试,而要看到窗口需要实现创建视口和变化缓冲区大小的回调函数。
    
    //RENDER LOOP
    while (!glfwWindowShouldClose(window))
    {
    //INPUT环节
       processInput(window);
       //大型switch语句,根据当前设备状态执行对应操作
    
    //RENDER环节
       //背景涂色
       glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
       glClear(GL_COLOR_BUFFER_BIT);
       //其他绘制程序
       glUseProgram(shaderProgram);
       glBindVertexArray(VAO);
       //glDrawArrays(GL_TRIANGLES, 0, 3);由于这里使用的是EBO,VBO数据不完全,所以不能用
       glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
       //glBindVertexArray(0);如果有其他VAO时,通常要这么做;但是只有一个VAO时,甚至可以放在循环外
    
    //SWAP&POLL环节
       glfwSwapBuffers(window);
       glfwPollEvents();
       //Swap称为交换,因为进行的操作是将frame buffer拷贝给inner buffer,再通过双缓冲区、与显卡交互更新屏幕。也可以认为就是更新屏幕。
       //Poll可以称作轮询,接收设备触发的事件。同时调用回调函数。
    }
    
    void processInput(GLFWwindow* window) {
    	if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS) {
    		glfwSetWindowShouldClose(window, true);
    	}
    }
    

    目前不能确定glfwPollEvents()是否负责修改glfwGetXX()能获取到的属性。

    记忆:INPUT、RENDER、SWAP、POLL,用英文能保持原义

    对于Program,create、attach、link、use,最后一个环节在render loop。

    对于VAO,绘制步骤前后使用bind、bind(0),绘制步骤使用glDrawArraysglDrawElements,分别对应绘制用VAP定位的VAA的方式,和绘制用EBO定位的VAA的方式

完整代码

#include<glad/glad.h>
#include<GLFW/glfw3.h>
#include<iostream>

void processInput(GLFWwindow*);

int main() {
	/// <summary>
	/// Part 1: Initialize and configure GLFW
	/// </summary>
	glfwInit();
	glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
	glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
	glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
	GLFWwindow* window = glfwCreateWindow(1200, 800, "Learn", NULL, NULL);
	if (window == NULL) {
		std::cerr << "Failed to create GLFW window" << std::endl;
		glfwTerminate();
		return -1;
	}
	glfwMakeContextCurrent(window);
	if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
	{
		std::cerr << "Failed to initialize GLAD" << std::endl;
		return -1;
	}

	/// <summary>
	/// Part 2: Set up vertex data (and buffer(s)) and configure vertex attributes
	/// </summary>
	unsigned int VAO;
	glGenVertexArrays(1, &VAO);
	glBindVertexArray(VAO);

	float vertices[] = {
		-0.5f, -0.5f, 0.0f,
		 0.5f, -0.5f, 0.0f,
		 0.0f,  0.5f, 0.0f,
		 1.0f, 1.0f, 0.0f
	};
	unsigned int VBO;
	glGenBuffers(1, &VBO);
	glBindBuffer(GL_ARRAY_BUFFER, VBO);
	glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
	unsigned int indices[] = {
		0,1,2,
		1,2,3
	};
	unsigned int EBO;
	glGenBuffers(1, &EBO);
	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
	glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
	glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
	glEnableVertexAttribArray(0);

	glBindVertexArray(0);

	/// <summary>
	/// Part 3: Build and compile our shader program
	/// </summary>
	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";
	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, 512, NULL, infoLog);
			std::cout << "ERROR::SHADER::VERTEX::COMPILATION_FAILED\n" << infoLog << std::endl;
		}

		const char* fragmentShaderSource = R"(#version 330 core
out vec4 FragColor;

void main()
{
    FragColor = vec4(1.0f, 0.5f, 0.2f, 1.0f);
} )";
		unsigned int fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
		glShaderSource(fragmentShader, 1, &fragmentShaderSource, NULL);
		glCompileShader(fragmentShader);
		{
			int  success;
			char infoLog[512];
			glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &success);
			if (!success)
			{
				glGetShaderInfoLog(fragmentShader, 512, NULL, infoLog);
				std::cout << "ERROR::SHADER::FRAGMENT::COMPILATION_FAILED\n" << infoLog << std::endl;
			}
		}

		unsigned int shaderProgram = glCreateProgram();
		glAttachShader(shaderProgram, vertexShader);
		glAttachShader(shaderProgram, fragmentShader);
		glLinkProgram(shaderProgram);
		{
			int success;
			char infoLog[512];
			glGetProgramiv(shaderProgram, GL_LINK_STATUS, &success);
			if (!success) {
				glGetProgramInfoLog(shaderProgram, 512, NULL, infoLog);
				std::cerr << "ERROR::PROGRAM::LINK_FAILED\n" << infoLog << std::endl;
			}
		}
		glDeleteShader(vertexShader);
		glDeleteShader(fragmentShader);

		/// <summary>
		/// Part 4: Render loop 
		/// </summary>
		glfwSetFramebufferSizeCallback(window,
			[](GLFWwindow* window, int width, int height) {glViewport(0, 0, width, height); });
		while (!glfwWindowShouldClose(window))
		{
			processInput(window);

			glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
			glClear(GL_COLOR_BUFFER_BIT);
			glUseProgram(shaderProgram);
			glBindVertexArray(VAO);
			glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);

			glfwSwapBuffers(window);
			glfwPollEvents();
		}
	}
}

void processInput(GLFWwindow* window) {
	if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS) {
		glfwSetWindowShouldClose(window, true);
	}
}


©

comment 评论区

添加新评论

face表情



  • ©2026 bilibili.com

textsms
内容不能为空
昵称不能为空
email
邮件地址格式错误
web
beach_access
验证码不能为空
keyboard发表评论


star_outline 咱快来抢个沙发吧!




©2026 Aquacolor

Theme Romanticism2.2 by Akashi
Powered by Typecho