openGL入门3、变换矩阵2D变换&坐标系统3D效果_glm radians(1)

img
img

既有适合小白学习的零基础资料,也有适合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);
// 多级渐远纹理的设置

img
img

既有适合小白学习的零基础资料,也有适合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++开发知识点,真正体系化!

由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新

如果你需要这些资料,可以戳这里获取

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值