既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上C C++开发知识点,真正体系化!
由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新
if (window == NULL)
{
std::cout << "Failed to create GLFW window" << std::endl;
glfwTerminate();
return -1;
}
glfwMakeContextCurrent(window);//GLFW将我们窗口的上下文设置为当前线程的主上下文
glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);
//GLAD加载所有的opengl函数指针
if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
{
std::cout << "Failed to initialize GLAD" << std::endl;
return -1;
}
/******************************2、 着色器编译编译链接 *********************************************/
Shader ourShader("shader.vs", "shader.fs");
/******************************3、 顶点属性缓存这些 *********************************************/
//绘制两个相连的三角形
float vertices[] = {
// ---- 位置 ---- ---- 颜色 ---- - 纹理坐标 -
0.5f, 0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, // 右上
0.5f, -0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, // 右下
-0.5f, -0.5f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, // 左下
-0.5f, 0.5f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f // 左上
};
//索引数组
unsigned int indices[] = {
0, 1, 3, // first triangle
1, 2, 3 // second triangle
};
unsigned int VBO, VAO, EBO;
glGenVertexArrays(1, &VAO);//创建一个顶点数组 与顶点属性相绑定
glGenBuffers(1, &VBO);//创建顶点缓冲对象
glGenBuffers(1, &EBO);
glBindVertexArray(VAO);//绑定顶点数组 配置顶点属性
glBindBuffer(GL_ARRAY_BUFFER, VBO);//将GL_ARRAY_BUFFER类型的缓存与VBO绑定
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);//之前定义的顶点数据复制到缓冲的内存
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);//将GL_ELEMENT_ARRAY_BUFFER类型的缓冲与EBO绑定
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);//把索引复制到缓冲里
/*
0;指定我们要配置的顶点位置属性 就是顶点着色器里面location那个
*/
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 *sizeof(float), (void *)0);//步长为8了
glEnableVertexAttribArray(0);//以顶点属性位置值0作为参数,启用顶点属性
/*
1;指定我们要配置的顶点颜色属性 就是顶点着色器里面location那个 glVertexAttribPointer函数更新顶点格式
*/
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(3 * sizeof(float)));
glEnableVertexAttribArray(1);
/*
2;指定我们要配置的顶点纹理属性 就是顶点着色器里面location那个 glVertexAttribPointer函数更新顶点格式
*/
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(6 * sizeof(float)));
glEnableVertexAttribArray(2);
glBindBuffer(GL_ARRAY_BUFFER, 0);//VBO 已经与顶点属性数组VAO进行绑定了 那么GL_ARRAY_BUFFER就可以解除绑定
//glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); //记住:不要在VAO激活时解除绑定EBO,因为绑定的元素缓冲区对象存储在VAO中;保持EBO绑定。
glBindVertexArray(0);//您可以在之后解除绑定VAO,这样其他VAO调用就不会意外地修改这个VAO
// 加载创建纹理
unsigned int texture, texture2;
glGenTextures(1, &texture);//生成纹理对象,同样也可以创建一个数组的纹理
glBindTexture(GL_TEXTURE_2D, texture); //绑定它,让之后任何的纹理指令都可以配置当前绑定的纹理:
//为当前绑定的纹理对象设置环绕、过滤方式
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); //重复纹理的填充方式
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
// 多级渐远纹理的设置
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);//缩小时采用在两个邻近的多级渐远纹理之间使用线性插值,并使用线性插值进行采样
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);//线性
// 加载图像
int width, height, nrChannels;
unsigned char* data = stbi_load("container.jpg", &width, &height, &nrChannels, 0);
if (data)
{
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, data);
glGenerateMipmap(GL_TEXTURE_2D);//为当前绑定的纹理自动生成所有需要的多级渐远纹理
}
else
{
std::cout << "Failed to load texture" << std::endl;
}
stbi_image_free(data);//释放图像的内存
//纹理2
glGenTextures(1, &texture2);
glBindTexture(GL_TEXTURE_2D, texture2);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
stbi_set_flip_vertically_on_load(true);
data = stbi_load("awesomeface.png", &width, &height, &nrChannels, 0);
if (data)
{
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
glGenerateMipmap(GL_TEXTURE_2D);
}
else
{
std::cout << "Failed to load texture" << std::endl;
}
stbi_image_free(data);
ourShader.use();
glUniform1i(glGetUniformLocation(ourShader.ID, "texture1"), 0);//绑定这个着色器的第0个纹理
ourShader.setInt("texture2", 1);//绑定这个着色器的第0个纹理
//位移
//glm::vec4 vec(1.0f, 0.0f, 0.0f, 1.0f);
译注:下面就是矩阵初始化的一个例子,如果使用的是0.9.9及以上版本
下面这行代码就需要改为:
glm::mat4 trans = glm::mat4(1.0f)
之后将不再进行提示
//glm::mat4 trans;
//trans = glm::translate(trans, glm::vec3(1.0f, 1.0f, 0.0f));
//vec = trans * vec;
//std::cout << vec.x << vec.y << vec.z << std::endl;
/* //旋转
glm::mat4 trans = glm::mat4(1.0f);
trans = glm::rotate(trans, glm::radians(90.0f), glm::vec3(0.0, 0.0, 1.0));
trans = glm::scale(trans, glm::vec3(0.5, 0.5, 0.5));*/
//渲染循环
//程序在我们主动关闭它之前不断绘制图像并能够接受用户输入 GLFW退出前一直保持运行
while (!glfwWindowShouldClose(window))//检查一次GLFW是否被要求退出
{
//可接收键盘输入esc从而退出
processInput(window);
glClearColor(0.2f, 0.3f, 0.3f, 1.0f); //设置状态函数
glClear(GL_COLOR_BUFFER_BIT);//使用状态函数
//位移+随时间旋转
glm::mat4 trans = glm::mat4(1.0f);
trans = glm::translate(trans, glm::vec3(0.5f, -0.5f, 0.0f));//位移
trans = glm::rotate(trans, (float)glfwGetTime(), glm::vec3(0.0f, 0.0f, 1.0f));//旋转
//传到顶点着色器进行设置
unsigned int transformLoc = glGetUniformLocation(ourShader.ID, "transform");
glUniformMatrix4fv(transformLoc, 1, GL_FALSE, glm::value_ptr(trans));
//激活纹理进行绑定
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texture);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, texture2);
ourShader.use();
// glUseProgram(shaderProgram);//使用着色器程序
glBindVertexArray(VAO);//绑定顶点数组 就是使用顶点属性
//glDrawArrays(GL_TRIANGLES, 0, 3);
//配置OpenGL如何绘制图元。第一个参数表示我们打算将其应用到所有的三角形的正面和背面,第二个参数告诉我们用线来绘制
//注意如果进行设置glPolygonMode(GL_FRONT_AND_BACK, GL_FILL) 那么就会一直是线框模式
//glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
//在调用glDrawElements之前绑定纹理了,它会自动把纹理赋值给片段着色器的采样器:
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);//使用当前绑定的索引缓冲对象中的索引进行绘制:
glfwSwapBuffers(window);//交换颜色缓冲(它是一个储存着GLFW窗口每一个像素颜色值的大缓冲),它在这一迭代中被用来绘制,并且将会作为输出显示在屏幕上。
glfwPollEvents();//检查有没有触发什么事件(比如键盘输入、鼠标移动等)、更新窗口状态,并调用对应的回调函数
}
glDeleteVertexArrays(1, &VAO);
glDeleteBuffers(1, &VBO);
ourShader.dele();
//释放/删除之前的分配的所有资源
glfwTerminate();
return 0;
}
void processInput(GLFWwindow* window)
{
if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)//会返回这个按键是否正在被按下
glfwSetWindowShouldClose(window, true);//把WindowShouldClose属性设置为 true的方法关闭GLFW
}
void framebuffer_size_callback(GLFWwindow* window, int width, int height)
{
//左上角坐标xy和宽高
glViewport(0, 0, width, height);//OpenGL的显示试图
}
顶点着色器
#version 330 core
layout (location = 0) in vec3 aPos;
layout (location = 1) in vec3 aColor;
layout (location = 2) in vec2 aTexCoord;
uniform mat4 transform;
out vec3 ourColor;
out vec2 TexCoord;
void main()
{
gl_Position = transform * vec4(aPos, 1.0);
ourColor = aColor;
TexCoord = aTexCoord;
}
片段着色器
#version 330 core
out vec4 FragColor;
in vec3 ourColor;
in vec2 TexCoord;
//在调用glDrawElements之前绑定纹理了,它会自动把纹理赋值给片段着色器的采样器:
uniform sampler2D ourTexture;
//sampler2D就是表示纹理单元类型的 是uniform卡类型
uniform sampler2D texture1;
uniform sampler2D texture2;
void main()
{
//ourTexture 采样器
//TexCoord 由顶点坐标那边传来的纹理坐标
//最后输出还可以把颜色也叠加上去
//FragColor = texture(ourTexture, TexCoord) * vec4(ourColor, 1.0);;
FragColor = mix(texture(texture1, TexCoord), texture(texture2, TexCoord), 0.2) * vec4(ourColor, 1.0);
}
### 2.2.6、绘制第二个箱子进行放缩
![在这里插入图片描述](https://img-blog.csdnimg.cn/cffe703e2aff475aa9d4f5bc6e0d02ef.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBAencxOTk2,size_20,color_FFFFFF,t_70,g_se,x_16)
//第二个
trans = glm::mat4(1.0f); // reset it to identity matrix
trans = glm::translate(trans, glm::vec3(-0.5f, 0.5f, 0.0f));//移动
float scaleAmount = sin(glfwGetTime());
trans = glm::scale(trans, glm::vec3(scaleAmount, scaleAmount, scaleAmount));//放缩
// glUniformMatrix4fv(transformLoc, 1, GL_FALSE, glm::value_ptr(trans));
glUniformMatrix4fv(transformLoc, 1, GL_FALSE, &trans[0][0]);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
### 二、坐标系统
### 1、坐标的转换
OpenGL希望在每次顶点着色器运行后,我们可见的所有顶点都为**标准化设备坐标**(Normalized Device Coordinate, NDC)。也就是说,每个顶点的x,y,z坐标都应该在\*\*-1.0到1.0之间\*\*,超出这个坐标范围的顶点都将不可见。
坐标变换为标准化设备坐标,接着再转化为屏幕坐标的过程通常是分步进行的,也就是类似于流水线那样子。
![在这里插入图片描述](https://img-blog.csdnimg.cn/3fe7549ab018421f8f6c97171ec11d07.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBAencxOTk2,size_20,color_FFFFFF,t_70,g_se,x_16#pic_center)
正射投影:
就是相当于平行投影
实现
glm::ortho(0.0f, 800.0f, 0.0f, 600.0f, 0.1f, 100.0f);
透视投影:
就是相当于越远越小的视觉投影
实现
glm::mat4 proj = glm::perspective(glm::radians(45.0f), (float)width/(float)height, 0.1f, 100.0f);
它的第一个参数定义了fov的值,它表示的是视野(Field of View),并且设置了观察空间的大小。
如果想要一个真实的观察效果,它的值通常设置为45.0f,但想要一个末日风格的结果你可以将其设置一个更大的值。
第二个参数设置了宽高比,由视口的宽除以高所得。
第三和第四个参数设置了平截头体的近和远平面。
我们通常设置近距离为0.1f,而远距离设为100.0f。所有在近平面和远平面内且处于平截头体内的顶点都会被渲染。
当你把透视矩阵的 near 值设置太大时(如10.0f),OpenGL会将靠近摄像机的坐标(在0.0f和10.0f之间)都裁剪掉、
这会导致一个你在游戏中很熟悉的视觉效果:
在太过靠近一个物体的时候你的视线会直接穿过去。
详情可以查看学习链接
https://learnopengl-cn.github.io/01%20Getting%20started/08%20Coordinate%20Systems/
最后坐标实现的过程就是把这些操作整合到一起
![在这里插入图片描述](https://img-blog.csdnimg.cn/d556d1e19c5b4e478ffef839a0e2bab9.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBAencxOTk2,size_20,color_FFFFFF,t_70,g_se,x_16)
### 2、实践流程
### 2.1、api步骤流程
### **2.1.1、创建模型矩阵:顶点坐标->世界坐标**
![在这里插入图片描述](https://img-blog.csdnimg.cn/c08643cf7a8142208b7512cb32f02e82.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBAencxOTk2,size_20,color_FFFFFF,t_70,g_se,x_16#pic_center)
### **2.1.2、创建观察矩阵:世界坐标->观察坐标**
![在这里插入图片描述](https://img-blog.csdnimg.cn/0b071a3c6a6a431da07be4c2af9ba389.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBAencxOTk2,size_20,color_FFFFFF,t_70,g_se,x_16#pic_center)
### **2.1.3、创建投影矩阵:观察坐标->裁剪坐标**
![在这里插入图片描述](https://img-blog.csdnimg.cn/4412e77ba92e4449a3d1ae322e7c0505.png)
### **2.1.4、将变换矩阵设置到顶点着色器当中**
![在这里插入图片描述](https://img-blog.csdnimg.cn/15f72594f2254ef6bb133762bf207420.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBAencxOTk2,size_20,color_FFFFFF,t_70,g_se,x_16)
**2.1.5、效果图**
![在这里插入图片描述](https://img-blog.csdnimg.cn/38035405eddd46c7ac927f3c57459744.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBAencxOTk2,size_20,color_FFFFFF,t_70,g_se,x_16)
### 2.2、绘制3D立体并旋转\_36个顶点
![在这里插入图片描述](https://img-blog.csdnimg.cn/6f05a2954a124d9c8a9c0445931b3266.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBAencxOTk2,size_20,color_FFFFFF,t_70,g_se,x_16)
顶点着色器
#version 330 core
layout (location = 0) in vec3 aPos;
layout (location = 1) in vec3 aColor;
layout (location = 2) in vec2 aTexCoord;
uniform mat4 transform;
out vec3 ourColor;
out vec2 TexCoord;
uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;
void main()
{
gl_Position = projection * view * model * vec4(aPos, 1.0);
ourColor = aColor;
TexCoord = aTexCoord;
}
片段着色器
#version 330 core
out vec4 FragColor;
in vec3 ourColor;
in vec2 TexCoord;
//在调用glDrawElements之前绑定纹理了,它会自动把纹理赋值给片段着色器的采样器:
uniform sampler2D ourTexture;
//sampler2D就是表示纹理单元类型的 是uniform卡类型
uniform sampler2D texture1;
uniform sampler2D texture2;
void main()
{
//ourTexture 采样器
//TexCoord 由顶点坐标那边传来的纹理坐标
//最后输出还可以把颜色也叠加上去
//FragColor = texture(ourTexture, TexCoord) * vec4(ourColor, 1.0);;
FragColor = mix(texture(texture1, TexCoord), texture(texture2, TexCoord), 0.2) * vec4(ourColor, 1.0);
}
主代码
#include
#include <glad/glad.h>
#include <GLFW/glfw3.h>
#include “glm/glm/glm.hpp”
#include “glm/glm/gtc/matrix_transform.hpp”
#include “glm/glm/gtc/type_ptr.hpp”
#include “ShaderClass.h”
#include “stb_image.h”
using namespace std;
void framebuffer_size_callback(GLFWwindow* window, int width, int height);
void processInput(GLFWwindow* window);
const unsigned int SCR_WIDTH = 800;
const unsigned int SCR_HEIGHT = 600;
int main()
{
/1、 初始化opengl窗口***************/
//glfw 初始化和配置
glfwInit();//初始化GLFW
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);//主版本号
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);//子版本号
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);//指定哪个配置文件配置上下文:GLFW我们使用的是核心模式
#ifdef APPLE//如果时mac os xp等系统则要进行配置一下才能生效
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
#endif
//glfw创建窗口
GLFWwindow* window = glfwCreateWindow(SCR_WIDTH, SCR_HEIGHT, "LearnOpenGL", NULL, NULL);
if (window == NULL)
{
std::cout << "Failed to create GLFW window" << std::endl;
glfwTerminate();
return -1;
}
glfwMakeContextCurrent(window);//GLFW将我们窗口的上下文设置为当前线程的主上下文
glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);
//GLAD加载所有的opengl函数指针
if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
{
std::cout << "Failed to initialize GLAD" << std::endl;
return -1;
}
/******************************2、 着色器编译编译链接 *********************************************/
Shader ourShader("shader.vs", "shader.fs");
/******************************3、 顶点属性缓存这些 *********************************************/
//绘制两个相连的三角形
//float vertices[] = {
// // ---- 位置 ---- ---- 颜色 ---- - 纹理坐标 -
// 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, // 右上
// 0.5f, -0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, // 右下
// -0.5f, -0.5f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, // 左下
// -0.5f, 0.5f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f // 左上
//};
float vertices[] = {
//-- 位置 ---- ---- 颜色 ---- - 纹理坐标 -
-0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f,
0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f,
0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f,
0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f,
-0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f,
-0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f,
-0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f,
0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f,
0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f,
0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f,
-0.5f, 0.5f, 0.5f,1.0f, 0.0f, 0.0f, 0.0f, 1.0f,
-0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f,
-0.5f, 0.5f, 0.5f,1.0f, 0.0f, 0.0f, 1.0f, 0.0f,
-0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f,
-0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f,
-0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f,
-0.5f, -0.5f, 0.5f,1.0f, 0.0f, 0.0f, 0.0f, 0.0f,
-0.5f, 0.5f, 0.5f,1.0f, 0.0f, 0.0f, 1.0f, 0.0f,
0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f,
0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f,
0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f,
0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f,
0.5f, -0.5f, 0.5f,1.0f, 0.0f, 0.0f, 0.0f, 0.0f,
0.5f, 0.5f, 0.5f,1.0f, 0.0f, 0.0f, 1.0f, 0.0f,
-0.5f, -0.5f, -0.5f,1.0f, 0.0f, 0.0f, 0.0f, 1.0f,
0.5f, -0.5f, -0.5f,1.0f, 0.0f, 0.0f, 1.0f, 1.0f,
0.5f, -0.5f, 0.5f,1.0f, 0.0f, 0.0f, 1.0f, 0.0f,
0.5f, -0.5f, 0.5f,1.0f, 0.0f, 0.0f, 1.0f, 0.0f,
-0.5f, -0.5f, 0.5f,1.0f, 0.0f, 0.0f, 0.0f, 0.0f,
-0.5f, -0.5f, -0.5f,1.0f, 0.0f, 0.0f, 0.0f, 1.0f,
-0.5f, 0.5f, -0.5f,1.0f, 0.0f, 0.0f, 0.0f, 1.0f,
0.5f, 0.5f, -0.5f,1.0f, 0.0f, 0.0f, 1.0f, 1.0f,
0.5f, 0.5f, 0.5f,1.0f, 0.0f, 0.0f, 1.0f, 0.0f,
0.5f, 0.5f, 0.5f,1.0f, 0.0f, 0.0f, 1.0f, 0.0f,
-0.5f, 0.5f, 0.5f,1.0f, 0.0f, 0.0f, 0.0f, 0.0f,
-0.5f, 0.5f, -0.5f,1.0f, 0.0f, 0.0f, 0.0f, 1.0f
};
//索引数组
unsigned int indices[] = {
0, 1, 3, // first triangle
1, 2, 3 // second triangle
};
unsigned int VBO, VAO, EBO;
glGenVertexArrays(1, &VAO);//创建一个顶点数组 与顶点属性相绑定
glGenBuffers(1, &VBO);//创建顶点缓冲对象
glGenBuffers(1, &EBO);
glBindVertexArray(VAO);//绑定顶点数组 配置顶点属性
glBindBuffer(GL_ARRAY_BUFFER, VBO);//将GL_ARRAY_BUFFER类型的缓存与VBO绑定
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);//之前定义的顶点数据复制到缓冲的内存
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);//将GL_ELEMENT_ARRAY_BUFFER类型的缓冲与EBO绑定
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);//把索引复制到缓冲里
/*
0;指定我们要配置的顶点位置属性 就是顶点着色器里面location那个
*/
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 *sizeof(float), (void *)0);//步长为8了
glEnableVertexAttribArray(0);//以顶点属性位置值0作为参数,启用顶点属性
/*
1;指定我们要配置的顶点颜色属性 就是顶点着色器里面location那个 glVertexAttribPointer函数更新顶点格式
*/
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(3 * sizeof(float)));
glEnableVertexAttribArray(1);
/*
2;指定我们要配置的顶点纹理属性 就是顶点着色器里面location那个 glVertexAttribPointer函数更新顶点格式
*/
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(6 * sizeof(float)));
glEnableVertexAttribArray(2);
glBindBuffer(GL_ARRAY_BUFFER, 0);//VBO 已经与顶点属性数组VAO进行绑定了 那么GL_ARRAY_BUFFER就可以解除绑定
//glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); //记住:不要在VAO激活时解除绑定EBO,因为绑定的元素缓冲区对象存储在VAO中;保持EBO绑定。
glBindVertexArray(0);//您可以在之后解除绑定VAO,这样其他VAO调用就不会意外地修改这个VAO
// 加载创建纹理
unsigned int texture, texture2;
glGenTextures(1, &texture);//生成纹理对象,同样也可以创建一个数组的纹理
glBindTexture(GL_TEXTURE_2D, texture); //绑定它,让之后任何的纹理指令都可以配置当前绑定的纹理:
//为当前绑定的纹理对象设置环绕、过滤方式
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); //重复纹理的填充方式
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
// 多级渐远纹理的设置
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上C C++开发知识点,真正体系化!
由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新
glBindTexture(GL_TEXTURE_2D, texture); //绑定它,让之后任何的纹理指令都可以配置当前绑定的纹理:
//为当前绑定的纹理对象设置环绕、过滤方式
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); //重复纹理的填充方式
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
// 多级渐远纹理的设置
[外链图片转存中…(img-iPy1T5Ju-1715839319746)]
[外链图片转存中…(img-Vl8rE2ga-1715839319746)]
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上C C++开发知识点,真正体系化!
由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新