我们来逐行解析这两个着色器,并深入了解它们背后的语法和核心概念。这是你与 GPU 直接对话的语言——GLSL (OpenGL Shading Language)。
什么是着色器 (Shader)?首先,要理解着色器是一个在 GPU 上运行的小程序。它不像你的 C++ 代码在 CPU 上按顺序执行,而是被 GPU 以大规模并行的方式执行。例如,片段着色器会为屏幕上的每一个像素(或者说,每一个“片段”)都运行一次。
你提供的这两个着色器是构成最基本渲染管线的两个核心部分:顶点着色器和片段着色器
1. 顶点着色器 (Vertex Shader)123456789101112// (1) 版本声明#version 330 core// (2) 输入变量layout(location = 0) in vec4 position;// (3) 主函数void main(){ // (4) 输出变量 gl_Position = position;}
作用: 它的核心任务是处理每一个顶点。对于你发送给 GPU 的每一个顶点,这个着色器都会执行一次。它的主要工作是计算出该顶 ...
现在我们把比喻翻译成实际的技术流程:
你的应用 -> GLFW 你调用 glfwCreateWindow()。这就像在说:“嘿,GLFW,我需要一个 800x600 的窗口,并且我准备用 OpenGL 3.3 版本来画图。”
GLFW -> 操作系统 (OS) GLFW 并不自己画窗口。它会把你的请求翻译成特定操作系统的原生调用。
在 Windows 上,它会调用 CreateWindowExW() 等 Win32 API 函数来创建窗口。
在 macOS 上,它会调用 Cocoa 框架的函数。
最关键的一步是请求 OpenGL 上下文。GLFW 会使用操作系统的特定函数(如 Windows 上的 wglCreateContext)来告诉操作系统:“请为这个窗口创建一个 OpenGL 的运行环境。”
操作系统 (OS) -> GPU 驱动程序 操作系统本身不知道如何渲染 OpenGL。当它收到创建上下文的请求时,它会去查找为你的 GPU 安装的驱动程序(例如 NVIDIA 的 nvoglv64.dll)。操作系统加载这个驱动程序,并让它来创建和管理这个 ...
学习笔记:GLFW 简介1. 核心概念:GLFW 是什么?GLFW (Graphics Library Framework) 是一个轻量级的、开源的、跨平台的 C 语言库。它的核心使命是为你创建和管理窗口、处理用户输入,并管理 OpenGL 上下文(Context)。
一个重要的比喻:
OpenGL 就像一个高性能的汽车引擎。它只负责一件事:根据指令进行强大的图形计算和渲染。但引擎本身不能在路上跑。
GLFW 就像是汽车的底盘、车身、方向盘和踏板。它为引擎提供了一个可以运行的载体(窗口),并让你能够通过方向盘(鼠标)和踏板(键盘)来控制它。
一句话总结:OpenGL 负责画,GLFW 负责提供一个“画板”(窗口)并处理与用户的交互。
2. 为什么需要 GLFW?你可能会问:“为什么 OpenGL 自己不处理窗口和输入呢?”
OpenGL 的专注性:OpenGL 是一个纯粹的图形 API(应用程序编程接口)规范。它的设计目标是独立于任何操作系统和窗口系统,从而实现最大的可移植性。它根本不知道“窗口”、“鼠标点击”或“键盘按键”是什么。
跨平台的复杂性:创建窗口和处理输入在不同的操作 ...
官方 glVertexAttribPointer 函数文档
glVertexAttribPointer 是将 VBO 中的原始数据与顶点着色器(Vertex Shader)中的属性(layout(location = ...))关联起来的关键桥梁。当你的顶点数据变得复杂时(比如同时包含位置、颜色、纹理坐标),理解它的每个参数就变得至关重要。
我们先用一个包含位置(Position)和纹理坐标(Texture Coordinate)的顶点数组作为例子,然后为你整理一份清晰的笔记。
示例场景:渲染一个带纹理的正方形我们要画一个由两个三角形组成的正方形。每个顶点都需要两个信息:
它在屏幕上的位置 (x, y)。
它对应纹理图片的哪个坐标 (s, t)。
1. 准备顶点数据 (在 CPU 端)我们把位置和纹理坐标交错(Interleaved)存放在一个数组里。这样做通常性能更好,因为 GPU 在读取一个顶点的数据时,所有相关属性都在内存中相邻的位置。
1234567float vertices[] = {// ---- 位置 ---- --- 纹理坐标 --- ...
什么是屏幕撕裂?想象一下你的显示器是如何工作的:它以固定的频率(比如每秒 60 次,即 60Hz 刷新率)从显存中读取图像数据,并逐行绘制到屏幕上。这个过程被称为**垂直同步空白期 (Vertical Blanking Interval, VBI)**。
而你的显卡则以尽可能快的速度渲染新的图像帧。如果显卡渲染帧的速度超过了显示器的刷新率,并且在显示器正在绘制一帧的过程中,显卡完成了新的一帧并将其写入显存,那么显示器可能会同时从两个不同的帧中读取数据。
结果就是,屏幕上会出现水平的断裂线,画面上半部分显示的是旧帧,下半部分显示的是新帧,这就是屏幕撕裂。在快速移动的场景中,这种现象尤为明显,会严重影响视觉观感。
VSync 的工作原理VSync 的核心思想就是同步显卡渲染和显示器刷新。
为了实现这一点,OpenGL (以及其他图形 API) 通常会使用双缓冲(Double Buffering) 技术。这意味着有至少两个帧缓冲区:
**前置缓冲区 (Front Buffer)**:当前显示器正在读取并显示给用户的帧。
**后置缓冲区 (Back Buffer)**:显卡正在渲染新帧的缓 ...
How to debug OpenGL
Two Method to check error without using external tools1. GL get errorEdge: 在1.1版本中便引入了这个方法,几乎适用于所有版本的OpenGLDoc: glGetError - OpenGL 4 - docs.glDetails:每次造成错误的时候,OpenGl会在内存中以错误代码的形式暂存错误信息。如果你不小心造成了多个错误,那么它会随机返回一个错误代码,你需要==多次调用以获得全部错误信息==。
Code Example
12345678910111213static void GLClearError(){ while (glGetError() != GL_NO_ERROR);}static void GLCheckError(){ GLenum error; while ((error = glGetError()) != GL_NO_ERROR) { std::cout <&l ...
1. Initialize1. GLFW-try to make a window123456GLFWwindow* window;if(!glfwInit()) return -1;window = glfwCreateWindow(640,480,"Hello,World",NULL,NULL);
The params of glfwCreateWindow![[image-1851-5.5 A workflow of generating a graphics.png]]
2. GLFW-make context12/* Make the window's context current */glfwMakeContextCurrent(window);
3. GLEW-Init123/* Use glew to get the function pointers in the local driver,so that we can use them*/if (glewInit() != GLEW_OK) std::cerr << ...
[!notes] Default shaderIf you have followed the first five videos , then run the program you will see a triangle is generated.This is because if you don’t set a shader of yourself , the driver will use the default shader.
1. ShaderKind 1 : vertex shaderprimary purpose:
Provide the positions of the vertexes , so that we can have and use these positions to make some transformations
[!Example]As we all know, there is a camera in the world of the game world. If we just set the vertex’s screen pos ...
1. Definition 一个图形相关项目,需要调用到手机/电脑中的显卡时。我们需要在应用层面对GPU行为作出调用,基本就是一个显卡的API。 其本身只是一个规范,其本身并不是一个库,它只是规定了哪些函数应该拥有,以及我们该用什么参数去调用它。
Who to achieve this specifit/OpenGL ?你的GPU生成厂商会负责实现,也就是GPU驱动。而这些驱动很大概率上,是不会开源的。
2. Features
跨平台
原生的API(Direct 3D X11;Matal)对自家的GPU支持肯定更好,但是OpenGL的广泛性肯定更好
[!Note] Shader-着色器Some scripts that transform code from CPU into GPU , in order to make it perform better
3. How to know the version of the OpenGL in you machine1std::cout << glGetString(GL_VERSION) < ...
1. What is vertex buffer![[Vertex Buffers]]
2. Draw a triangle
The easiest way12345glBegin(GL_TRIANGLES);glVertex2f(-0.5f, -0.5f);glVertex2f(0.0f, 0.0f);glVertex2f(0.5f, -0.5f);glEnd();
In this script,we tell the shader that we want to draw a traingle and give it three points,then it draw the traingle for us.
Bind-glBindBuffer12glBindBuffer(GL_ARRAY_BUFFER, buffer);//This code means that the current time you bind with sth,so you don't need to cite which buffer you will draw.Just bind it.
I ...