图元装配(Primitive Assembly)
Primitive
也就是对顶点坐标,进行装配,形成形状
裁剪
原文:片段着色器运行之前会执行裁切(Clipping)。裁切会丢弃超出你的视图以外的所有像素,用来提升执行效率
裁剪默认在片段着色前
最后一个阶段
在着色后,是Alpha测试和混合。会进行深度测试、会检测透明度进行混合
必须定义的着色器
现代openGl有必须定义的着色器,因为GPU没有默认的。他们是:顶点shader、片段shader
顶点缓冲对象(Vertex Buffer Objects, VBO)
用于一次性CPU给GPU发送顶点,多次发送慢,所以缓存后一次发送
生成buffer->设置当前绑定buffer->设置buffer内容
genBuffer->bind->bufferData
glBufferData函数里有一个选项,可以选择buffer的性能。分为几乎不会变的、常变的、每帧变的
好的,至此,显存里有数据了
继续根据https://learnopengl-cn.github.io/01%20Getting%20started/04%20Hello%20Triangle/
有点不同的是,我分解成了class,为后续更方便添加代码
运行后出现了一个问题,窗口上画了一个橙色的方块,有时也不会画出方块而是完全黑屏,而且方块的位置不固定,有时在右上角,有时在左下角
分析一下:首先,没有报错,说明shader编译之类的都是对的,也就是整个流程是跑通的。那么大概率是数据的问题。读入数据的时候有一个地方我和教程不一样,我用了vector。将vector改为float v2[] = {
-0.5f, -0.5f, 0.0f,
0.5f, -0.5f, 0.0f,
0.0f, 0.5f, 0.0f
};后,正常了
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), &vertices, GL_STATIC_DRAW);//异常
glBufferData(GL_ARRAY_BUFFER, sizeof(v2), v2, GL_STATIC_DRAW);//正常
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), &vertices[0], GL_STATIC_DRAW);//三角形高度减半,也就是一个点变成了0,0,0
glBufferData(GL_ARRAY_BUFFER, sizeof(float)*vertices.size(), &vertices[0], GL_STATIC_DRAW);//正常
由此,有2件之前没注意的事,vector是一个obj,里面封装了一些指针,sizeof(vec)=32,有的资料说里面只有3个指针,不过是32的话,显然是4个,可能因为我在debug模式下MSVC会加一个debugSize,不过这不重要,重要的是传读取长度得用size算。其次是传入的指针,bufferData需要传入的是连续地址0位的指针,传&vec的话,是obj的指针
异常分析:用renderDoc
因为传成了地址。所以点取成了一些 接近0 or 接近无穷的点,当恰好能形成三角形的时候,渲染就会这样。虽然看到的是四边形,但实际上是三角形,只是因为y太大或太小,导致视角内看起来是四边形。
EBO (IBO)
教程里本章用的术语是EBO,个人认为从特性层面看,IBO更符合。简单来说,重复的点不重复传入,加传点的索引,从而获得更高的效率
EBO在active vao 中的时候,不能解绑,会运行错误
练习
玩玩
2个点相同,然后注意第三个点不要在第一个三角形内就行
以为之前封装好了操作,所以第二个只要复制一下就行
int main()
{
auto myWindow = MyWindow();
if (myWindow.IsSuccess() == false) {
return -1;
}
auto v = VertexShader();
auto f = FragmentShader();
auto shaderProgram = Tool::LinkShader(v, f);
unsigned int VAO;
glGenVertexArrays(1, &VAO);
glBindVertexArray(VAO);auto vbo = VBObject(triangleVertices);
auto ebo = EBObject(indces);glBindBuffer(GL_ARRAY_BUFFER, 0);//解绑
glBindVertexArray(0);//解绑unsigned int VAO2;
glGenVertexArrays(1, &VAO2);
glBindVertexArray(VAO2);auto vbo2 = VBObject(triangleVertices2);
auto ebo2 = EBObject(indces);glBindBuffer(GL_ARRAY_BUFFER, 0);//解绑
glBindVertexArray(0);//解绑std::vector<unsigned int>vaos={VAO, VAO2};
Tool::BindAutoAdaptSize(myWindow.GetWindow());
Tool::RenderLoop(myWindow.GetWindow(), shaderProgram, vaos);return 0;
}
不同色也差不多
#include<glad/glad.h>
#include"Tool.h"
#include"VBObject.h"
#include"MyWindow.h"
#include"EBObject.h"
#include <vector>std::vector<float> triangleVertices = {0.0f, 0.0f, 0.0f, // 右上角0.0f, -0.5f, 0.0f, // 右下角-0.5f, -0.5f, 0.0f, // 左下角0.5f, 0.5f, 0.0f, // 左上角0.5f, 0.0f, 0.0f , // 左上角};std::vector<int> indces = {0, 1, 2, // 第一个三角形};
std::vector<int> indces2 = {0, 4, 3 // 第二个三角形};int main()
{auto myWindow = MyWindow();if (myWindow.IsSuccess() == false) {return -1;}auto v = VertexShader();auto f = FragmentShader("#version 330 core\n""out vec4 FragColor;\n""void main()\n""{\n"" FragColor = vec4(1.0f, 0.5f, 0.2f, 1.0f);\n""}\0");auto f2 = FragmentShader("#version 330 core\n""out vec4 FragColor;\n""void main()\n""{\n"" FragColor = vec4(0.2f, 0.5f, 0.2f, 1.0f);\n""}\0");auto shaderProgram = Tool::LinkShader(v, f);auto shaderProgram2 = Tool::LinkShader(v, f2);unsigned int VAO;glGenVertexArrays(1, &VAO);glBindVertexArray(VAO);auto vbo = VBObject(triangleVertices);auto ebo = EBObject(indces);glBindBuffer(GL_ARRAY_BUFFER, 0);//解绑glBindVertexArray(0);//解绑unsigned int VAO2;glGenVertexArrays(1, &VAO2);glBindVertexArray(VAO2);auto vbo2 = VBObject(triangleVertices);auto ebo2 = EBObject(indces2);glBindBuffer(GL_ARRAY_BUFFER, 0);//解绑glBindVertexArray(0);//解绑std::vector<unsigned int>vaos = { VAO, VAO2 };std::vector<unsigned int>shaderPrograms ={ shaderProgram,shaderProgram2};Tool::BindAutoAdaptSize(myWindow.GetWindow());Tool::RenderLoop(myWindow.GetWindow(), shaderPrograms, vaos);return 0;
}