OpenGL(六)——坐标系统

目录

一、前言

二、空间系

2.1 局部空间

2.2 世界空间

2.3 观察空间

2.4裁剪空间

2.5 正射投影

2.6 透视投影

2.7 屏幕空间

 三、透视箱子

3.1 创建模型矩阵

3.2 创建观察矩阵

3.3 创建透视投影矩阵

3.4 修改顶点着色器

3.5 传递变换矩阵

四、旋转的箱子 

 五、好多箱子


一、前言

OpenGL显示的顶点在(-1,1)之间,这个坐标叫做标准化设别坐标(Normalized Device Coordinate, NDC)。将物体坐标变化到最终的NDC坐标需要几个过度坐标,在这些坐标系下计算非常容易和方便。过渡坐标分别在局部空间(物体空间)、世界空间、观察空间、裁剪空间、屏幕空间。

OpenGL(六)——坐标系统_第1张图片

 物体坐标从一个坐标系变换到另一个坐标系需要用到几个变换矩阵,最重要的几个分别是模型(Model)观察(View)投影(Projection)三个矩阵。我们的顶点坐标起始于局部坐标(Local Coordinate),之后会变为世界坐标(World Coordinate),观察坐标(View Coordinate),裁剪坐标(Clip Coordinate),并以屏幕坐标(Screen Coordinate)的形式结束。

局部坐标:相对局部原点坐标,物体起始坐标,便于对物体本身进行修改

世界坐标:相对于世界全局原点,和其他物体一起相对于世界原点摆放,便于对一个物体的相对其它物体位置进行操作

观察空间坐标:相对于摄像机或者观察者的角度进行的

裁剪坐标:投影到裁剪空间,被处理至-1到1的范围,并判断哪些顶点出现在屏幕上

屏幕坐标:使用视口变换,将-1到1的坐标转换到glViewPort函数定义的坐标范围内,送给光栅器,转化为片段

二、空间系

2.1 局部空间

局部空间是指物体所在的坐标空间,模型都以(0,0,0)为初始位置,但是它们出现在世界的不同位置。模型的所有顶点都是在局部坐标系中,它们相对于你的物体来说都是局部的。

2.2 世界空间

将所有模型导入到程序中,每个模型物体都有自己的位置,需要定义世界空间原点,模型矩阵用来完成物体坐标从局部变换到世界空间。

模型矩阵:可以对物体进行位移、缩放、旋转它本应该在位置和朝向。

2.3 观察空间

观察空间也叫OpenGL摄像机,也称为摄像机空间、视觉空间。观察空间将世界空间坐标转化为用户视野前方坐标。

观察矩阵:世界空间变换到观察空间使用一系列位移、旋转等组合来完成。

2.4裁剪空间

在顶点着色器运行的最后,OpenGL期望所有坐标落在一个特定范围内(-1,1),范围外的点应该被剪掉(Clip)。屏幕上可见的片段叫做裁剪空间。

投影矩阵(projection Matrix):将指定的坐标集(coordinate set)并将它变化为标准化设备坐标系。投影矩阵可以将3D坐标投影到2D标准化设备坐标中。

由投影矩阵创建的观察箱viewing box被称为平截头体,每个出现在平截头体范围内的坐标最终出现在屏幕上。

一旦所有顶点被变换到裁剪空间,将会执行透视除法,将位置向量的x,y,z分量除以向量齐次w分量。透视除法是将4D裁剪空间坐标变换为3D标准化设备坐标的过程。

观察坐标转换为裁剪坐标投影矩阵有两种形式:正射投影矩阵、透视投影矩阵

2.5 正射投影

正射投影定义一个裁剪空间,空间之外的顶点都会被裁剪掉。创建正射投影需要指定空间的长宽高。下图定义了可见坐标,由宽、高、远近平面指定。该空间内部所有坐标映射为标准设备坐标NDC。

创建正射投影矩阵:

glm::ortho(0.0f, 800.0f, 0.0f, 600.0f, 0.1f, 100.0f);
参数1:裁剪空间左坐标
参数2:裁剪空间右坐标
参数3:裁剪空间底部坐标
参数4:裁剪空间顶部坐标
参数5:近平面距离
参数6:远平面距离

OpenGL(六)——坐标系统_第2张图片

 正射投影矩阵直接将坐标映射到2D平面(屏幕上),实际上一个直接投影矩阵会产生不真实结果,因为没有将透视(perspective)考虑进去。因此正射投影主要用于二维渲染以及一些建筑或者工程的程序,这些场景顶点不会被透视干扰。

2.6 透视投影

透视:立体空间中,近大远小的效果。透视使得两条平行线在远距离会相交,这是透视投影矩阵要完成的效果。

OpenGL(六)——坐标系统_第3张图片

 透视投影矩阵将给定的平截头体映射到裁剪空间,还会修改每个顶点坐标w值,从而使离观察者越远的顶点坐标w分量越大。被变换到裁剪空间的坐标都会在(-w,w)范围内(超出范围坐标被剪掉)。

OpenGL要求所有可见坐标落在(-1,1)范围内,作为顶点着色器输出,当坐标在裁剪空间后,进行透视除法操作,近大远小:

OpenGL(六)——坐标系统_第4张图片

 

OpenGL(六)——坐标系统_第5张图片

 

glm::mat4 proj = glm::perspective(glm::radians(45.0f), (float)width/(float)height, 0.1f, 100.0f);
参数1:fov值,视野,设置观察空间大小
参数2:设置高宽比,视口宽除以高所得
参数3:平截头体近平面距离,0.1
参数4:平截头体远平面距离,100

2.7 屏幕空间

裁剪空间后的坐标映射到屏幕空间(glViewPort设定),并变换为片段。

一个顶点坐标将会经过下面变化,到裁剪坐标,注意矩阵运算顺序是相反的,最后顶点被赋值到gl_Position,OpenGL会自动对其进行透视除法变换到标准化设备坐标。OpenGL使用glViewPort内部的参数将NDC映射到屏幕坐标,每个坐标关联一个屏幕点,该过程称为视口变换。

 三、透视箱子

3.1 创建模型矩阵

位移、缩放、旋转操作。该模型矩阵将应用到所有物体顶点上,来映射到全局世界坐标。变换平面,让其绕x轴旋转。(当前位于原点(0,0,0)

OpenGL(六)——坐标系统_第6张图片

 顶点乘以该模型矩阵,将顶点坐标变换到世界坐标,看起来在地板上,表示全局世界的平面。

glm::mat4 model;
model = glm::rotate(model,glm::radians(-55.0f),glm::vec3(1.0,0.0,0.0));

3.2 创建观察矩阵

想要在场景里移动,可以将摄像机向后移动,或者将整个场景向前移动。以相反与摄像机移动的方向移动整个场景。OpenGL是右手坐标系,当我们要沿z轴正方向移动时,我们将场景沿z轴负方向平移来实现。

OpenGL(六)——坐标系统_第7张图片

右手坐标系 大拇指指向正x轴方向,食指指向正y轴方向,中指指向正z轴方向(DirectX使用左手坐标系)注意在标准化设备坐标系中OpenGL实际上使用的是左手坐标系(投影矩阵交换了左右手)。

glm:mat4 view;
// 注意,我们将矩阵向我们要进行移动场景的反方向移动
view = glm::translate(view,glm::vec3(0.0,0.0,-3.0));

3.3 创建透视投影矩阵

glm::mat4 projection;
projection = glm::perspective(glm::radians(45.0f), screenWidth/screenHight,0.1,100.0);

3.4 修改顶点着色器

使用uniform声明变换矩阵,然后乘以顶点坐标:

#version 330 core
layout (location = 0) in vec3 aPos;
layout (location = 1) in vec3 aColor;
layout (location = 2) in vec2 aTexCoord;

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 = vec2(aTexCoord.x, aTexCoord.y);
}

3.5 传递变换矩阵

        //model matrix
        glm::mat4 modelMat = glm::mat4(1.0f);
        modelMat = glm::rotate(modelMat, glm::radians(-55.0f), glm::vec3(1.0, 0.0, 0.0));
        //view matrix
        glm::mat4 viewMat = glm::mat4(1.0f);
        viewMat = glm::translate(viewMat, glm::vec3(0.0f, 0.0f, -3.0f));
        //projection matrix
        glm::mat4 projectionMat = glm::mat4(1.0f);
        projectionMat = glm::perspective(glm::radians(45.0f), (float)(SCR_WIDTH / SCR_HEIGHT), 0.1f, 100.0f);
        //着色器引用
        ourShader.use();
        unsigned int modelLoc = glGetUniformLocation(ourShader.ID, "model");
        glUniformMatrix4fv(modelLoc, 1, GL_FALSE, glm::value_ptr(modelMat));
        unsigned int viewlLoc = glGetUniformLocation(ourShader.ID, "view");
        glUniformMatrix4fv(viewlLoc, 1, GL_FALSE, glm::value_ptr(viewMat));
        unsigned int projectionlLoc = glGetUniformLocation(ourShader.ID, "projection");
        glUniformMatrix4fv(projectionlLoc, 1, GL_FALSE, glm::value_ptr(projectionMat));

OpenGL(六)——坐标系统_第8张图片

四、旋转的箱子 

3D箱子顶点:

    float vertices[] = {
    -0.5f, -0.5f, -0.5f,  0.0f, 0.0f,
     0.5f, -0.5f, -0.5f,  1.0f, 0.0f,
     0.5f,  0.5f, -0.5f,  1.0f, 1.0f,
     0.5f,  0.5f, -0.5f,  1.0f, 1.0f,
    -0.5f,  0.5f, -0.5f,  0.0f, 1.0f,
    -0.5f, -0.5f, -0.5f,  0.0f, 0.0f,

    -0.5f, -0.5f,  0.5f,  0.0f, 0.0f,
     0.5f, -0.5f,  0.5f,  1.0f, 0.0f,
     0.5f,  0.5f,  0.5f,  1.0f, 1.0f,
     0.5f,  0.5f,  0.5f,  1.0f, 1.0f,
    -0.5f,  0.5f,  0.5f,  0.0f, 1.0f,
    -0.5f, -0.5f,  0.5f,  0.0f, 0.0f,

    -0.5f,  0.5f,  0.5f,  1.0f, 0.0f,
    -0.5f,  0.5f, -0.5f,  1.0f, 1.0f,
    -0.5f, -0.5f, -0.5f,  0.0f, 1.0f,
    -0.5f, -0.5f, -0.5f,  0.0f, 1.0f,
    -0.5f, -0.5f,  0.5f,  0.0f, 0.0f,
    -0.5f,  0.5f,  0.5f,  1.0f, 0.0f,

     0.5f,  0.5f,  0.5f,  1.0f, 0.0f,
     0.5f,  0.5f, -0.5f,  1.0f, 1.0f,
     0.5f, -0.5f, -0.5f,  0.0f, 1.0f,
     0.5f, -0.5f, -0.5f,  0.0f, 1.0f,
     0.5f, -0.5f,  0.5f,  0.0f, 0.0f,
     0.5f,  0.5f,  0.5f,  1.0f, 0.0f,

    -0.5f, -0.5f, -0.5f,  0.0f, 1.0f,
     0.5f, -0.5f, -0.5f,  1.0f, 1.0f,
     0.5f, -0.5f,  0.5f,  1.0f, 0.0f,
     0.5f, -0.5f,  0.5f,  1.0f, 0.0f,
    -0.5f, -0.5f,  0.5f,  0.0f, 0.0f,
    -0.5f, -0.5f, -0.5f,  0.0f, 1.0f,

    -0.5f,  0.5f, -0.5f,  0.0f, 1.0f,
     0.5f,  0.5f, -0.5f,  1.0f, 1.0f,
     0.5f,  0.5f,  0.5f,  1.0f, 0.0f,
     0.5f,  0.5f,  0.5f,  1.0f, 0.0f,
    -0.5f,  0.5f,  0.5f,  0.0f, 0.0f,
    -0.5f,  0.5f, -0.5f,  0.0f, 1.0f
    };

修改模型矩阵:

        glm::mat4 modelMat = glm::mat4(1.0f);
        //modelMat = glm::rotate(modelMat, glm::radians(-55.0f), glm::vec3(1.0, 0.0, 0.0));//model matrix
        modelMat = glm::rotate(modelMat, (float)glfwGetTime(), glm::vec3(0.5f, 1.0f, 0.0f));

解释VAO数据:

    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)0);//位置
    glEnableVertexAttribArray(0);
    glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)(3 * sizeof(float)));//纹理
    glEnableVertexAttribArray(1);

OpenGL(六)——坐标系统_第9张图片

 立方体某些本应遮挡住的面被绘制在立方体其他面上。OpenGL是一个三角形一个三角形绘制立方体,即便有东西也会覆盖之前的像素。OpenGL存储深度信息在Z缓冲中,允许OpenGL是否去执行覆盖像素。通过Z缓冲来配置OpenGL深度测试

GLFW会自动生成一个深度缓冲,深度值存储在每个片段里面,当片段要输出它的颜色时,OpenGL将它的深度值与Z缓冲进行比较,如果当前片段在其他片段之后会被丢失,否则会被覆盖。

glEnable(GL_DEPTH_TEST);//glDisable关闭

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);//清除深度缓冲

OpenGL(六)——坐标系统_第10张图片

 五、好多箱子

要在屏幕上显示10个立方体,每个立方体看起来是一样的,区别是世界位置和旋转角度不同。立方体图形布局已经定义好了,只需改变每个对象的模型矩阵来将立方体变换到世界坐标中。

定义每个立方体的位置:

glm::vec3 cubePositions[] = {
  glm::vec3( 0.0f,  0.0f,  0.0f), 
  glm::vec3( 2.0f,  5.0f, -15.0f), 
  glm::vec3(-1.5f, -2.2f, -2.5f),  
  glm::vec3(-3.8f, -2.0f, -12.3f),  
  glm::vec3( 2.4f, -0.4f, -3.5f),  
  glm::vec3(-1.7f,  3.0f, -7.5f),  
  glm::vec3( 1.3f, -2.0f, -2.5f),  
  glm::vec3( 1.5f,  2.0f, -2.5f), 
  glm::vec3( 1.5f,  0.2f, -1.5f), 
  glm::vec3(-1.3f,  1.0f, -1.5f)  
};

渲染主循环中循环绘制cubePositions

glBindVertexArray(VAO);
for(unsigned int i = 0; i < 10; i++)
{
  glm::mat4 model;
  model = glm::translate(model, cubePositions[i]);
  float angle = 20.0f * i; 
  model = glm::rotate(model, glm::radians(angle), glm::vec3(1.0f, 0.3f, 0.5f));
  ourShader.setMat4("model", model);

  glDrawArrays(GL_TRIANGLES, 0, 36);
}

OpenGL(六)——坐标系统_第11张图片

 

#include 
#include 

#include "glad.h"
#include "GL/glfw3.h"
#define STB_IMAGE_IMPLEMENTATION
#include "stb_image.h"
#include 
#include 
#include 
#include "Shader.h"
// settings
const unsigned int SCR_WIDTH = 800;
const unsigned int SCR_HEIGHT = 600;

// process all input: query GLFW whether relevant keys are pressed/released this frame and react accordingly
// ---------------------------------------------------------------------------------------------------------
void processInput(GLFWwindow* window)
{
    if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
        glfwSetWindowShouldClose(window, true);
}

// glfw: whenever the window size changed (by OS or user resize) this callback function executes
// ---------------------------------------------------------------------------------------------
void framebuffer_size_callback(GLFWwindow* window, int width, int height)
{
    // make sure the viewport matches the new window dimensions; note that width and 
    // height will be significantly larger than specified on retina displays.
    glViewport(0, 0, width, height);
}

int main()
{
    // glfw: 初始化、配置
    // ------------------------------
    glfwInit();
    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);

#ifdef __APPLE__
    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);
    glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);
    // glad: 加载OpenGL相关函数指针
    // ---------------------------------------
    if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
    {
        std::cout << "Failed to initialize GLAD" << std::endl;
        return -1;
    }
    // 构建、编译着色器
    // ------------------------------------
    Shader ourShader("vertexTexture.vs", "fragmentTexture.fms");
    // 顶点数据
    // ------------------------------------------------------------------
    /*float vertices[] = {
        // 位置                 // 纹理坐标
         0.5f,  0.5f, 0.0f,     1.0f, 1.0f, // top right
         0.5f, -0.5f, 0.0f,     1.0f, 0.0f, // bottom right
        -0.5f, -0.5f, 0.0f,     0.0f, 0.0f, // bottom left
        -0.5f,  0.5f, 0.0f,     0.0f, 1.0f  // top left 
    };
    unsigned int indices[] = {
        0, 1, 3, // 第一个三角形
        1, 2, 3  // 第二个三角形
    };*/
    float vertices[] = {
    -0.5f, -0.5f, -0.5f,  0.0f, 0.0f,
     0.5f, -0.5f, -0.5f,  1.0f, 0.0f,
     0.5f,  0.5f, -0.5f,  1.0f, 1.0f,
     0.5f,  0.5f, -0.5f,  1.0f, 1.0f,
    -0.5f,  0.5f, -0.5f,  0.0f, 1.0f,
    -0.5f, -0.5f, -0.5f,  0.0f, 0.0f,

    -0.5f, -0.5f,  0.5f,  0.0f, 0.0f,
     0.5f, -0.5f,  0.5f,  1.0f, 0.0f,
     0.5f,  0.5f,  0.5f,  1.0f, 1.0f,
     0.5f,  0.5f,  0.5f,  1.0f, 1.0f,
    -0.5f,  0.5f,  0.5f,  0.0f, 1.0f,
    -0.5f, -0.5f,  0.5f,  0.0f, 0.0f,

    -0.5f,  0.5f,  0.5f,  1.0f, 0.0f,
    -0.5f,  0.5f, -0.5f,  1.0f, 1.0f,
    -0.5f, -0.5f, -0.5f,  0.0f, 1.0f,
    -0.5f, -0.5f, -0.5f,  0.0f, 1.0f,
    -0.5f, -0.5f,  0.5f,  0.0f, 0.0f,
    -0.5f,  0.5f,  0.5f,  1.0f, 0.0f,

     0.5f,  0.5f,  0.5f,  1.0f, 0.0f,
     0.5f,  0.5f, -0.5f,  1.0f, 1.0f,
     0.5f, -0.5f, -0.5f,  0.0f, 1.0f,
     0.5f, -0.5f, -0.5f,  0.0f, 1.0f,
     0.5f, -0.5f,  0.5f,  0.0f, 0.0f,
     0.5f,  0.5f,  0.5f,  1.0f, 0.0f,

    -0.5f, -0.5f, -0.5f,  0.0f, 1.0f,
     0.5f, -0.5f, -0.5f,  1.0f, 1.0f,
     0.5f, -0.5f,  0.5f,  1.0f, 0.0f,
     0.5f, -0.5f,  0.5f,  1.0f, 0.0f,
    -0.5f, -0.5f,  0.5f,  0.0f, 0.0f,
    -0.5f, -0.5f, -0.5f,  0.0f, 1.0f,

    -0.5f,  0.5f, -0.5f,  0.0f, 1.0f,
     0.5f,  0.5f, -0.5f,  1.0f, 1.0f,
     0.5f,  0.5f,  0.5f,  1.0f, 0.0f,
     0.5f,  0.5f,  0.5f,  1.0f, 0.0f,
    -0.5f,  0.5f,  0.5f,  0.0f, 0.0f,
    -0.5f,  0.5f, -0.5f,  0.0f, 1.0f
    };
    glm::vec3 cubePositions[] = {
  glm::vec3(0.0f,  0.0f,  0.0f),
  glm::vec3(2.0f,  5.0f, -15.0f),
  glm::vec3(-1.5f, -2.2f, -2.5f),
  glm::vec3(-3.8f, -2.0f, -12.3f),
  glm::vec3(2.4f, -0.4f, -3.5f),
  glm::vec3(-1.7f,  3.0f, -7.5f),
  glm::vec3(1.3f, -2.0f, -2.5f),
  glm::vec3(1.5f,  2.0f, -2.5f),
  glm::vec3(1.5f,  0.2f, -1.5f),
  glm::vec3(-1.3f,  1.0f, -1.5f)
    };
    //创建顶点对象
    unsigned int VAO, VBO, EBO;
    glGenVertexArrays(1, &VAO);//顶点数组
    glGenBuffers(1, &VBO);//数据缓存
    //glGenBuffers(1, &EBO);//数据缓存
    //绑定数据
    glBindVertexArray(VAO);
    glBindBuffer(GL_ARRAY_BUFFER, VBO);
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
    //glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
    //glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
    //解释数据
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)0);//位置
    glEnableVertexAttribArray(0);
    glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)(3 * sizeof(float)));//纹理
    glEnableVertexAttribArray(1);
    //创建纹理对象1
    unsigned int texture1;
    glGenTextures(1, &texture1);
    glBindTexture(GL_TEXTURE_2D, texture1);
    //设置纹理环绕方式
    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);
    //加载图片1到纹理数据
    int width, height, nrChannels;
    unsigned char* data = stbi_load(std::string("container.jpg").c_str(), &width, &height, &nrChannels, 0);
    if (data)
    {
        //加载数据,生成OpenGL纹理图
        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
    unsigned int texture2;
    // texture 2
// ---------
    glGenTextures(1, &texture2);
    glBindTexture(GL_TEXTURE_2D, texture2);
    // set the texture wrapping parameters
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);	// set texture wrapping to GL_REPEAT (default wrapping method)
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
    // set texture filtering parameters
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    // load image, create texture and generate mipmaps
    stbi_set_flip_vertically_on_load(true);
    data = stbi_load(std::string("awesomeface.png").c_str(), &width, &height, &nrChannels, 0);
    if (data)
    {
        // note that the awesomeface.png has transparency and thus an alpha channel, so make sure to tell OpenGL the data type is of GL_RGBA
        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);

    //OpenGL解释纹理单元的编号
    ourShader.use(); 
    ourShader.setInt("textur1", 0);
    ourShader.setInt("textur2", 1);
    glEnable(GL_DEPTH_TEST);
    //旋转90度,缩放0.5倍
    //glm::mat4 trans = glm::mat4(1.0f);
   // trans = glm::rotate(trans, glm::radians(90.0f), glm::vec3(0, 0, 1.0));
    //trans = glm::scale(trans, glm::vec3(0.5, 0.5, 0.5));

    //渲染
    while (!glfwWindowShouldClose(window))
    {
        processInput(window);

        //背景颜色
        glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
        glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
        //绑定对应的纹理
        glActiveTexture(GL_TEXTURE0);
        glBindTexture(GL_TEXTURE_2D, texture1);
        glActiveTexture(GL_TEXTURE1);
        glBindTexture(GL_TEXTURE_2D, texture2);
        //glm::mat4 modelMat = glm::mat4(1.0f);
        glm::mat4 viewMat = glm::mat4(1.0f);
        glm::mat4 projectionMat = glm::mat4(1.0f);
        //modelMat = glm::rotate(modelMat, glm::radians(-55.0f), glm::vec3(1.0, 0.0, 0.0));//model matrix
        //modelMat = glm::rotate(modelMat, (float)glfwGetTime(), glm::vec3(0.5f, 1.0f, 0.0f));
        viewMat = glm::translate(viewMat, glm::vec3(0.0f, 0.0f, -3.0f));//view matrix 
        projectionMat = glm::perspective(glm::radians(45.0f), (float)(SCR_WIDTH / SCR_HEIGHT), 0.1f, 100.0f);//projection matrix
        //着色器引用
        ourShader.use();
        //unsigned int modelLoc = glGetUniformLocation(ourShader.ID, "model");
        //glUniformMatrix4fv(modelLoc, 1, GL_FALSE, glm::value_ptr(modelMat));
        unsigned int viewlLoc = glGetUniformLocation(ourShader.ID, "view");
        glUniformMatrix4fv(viewlLoc, 1, GL_FALSE, glm::value_ptr(viewMat));
        unsigned int projectionlLoc = glGetUniformLocation(ourShader.ID, "projection");
        glUniformMatrix4fv(projectionlLoc, 1, GL_FALSE, glm::value_ptr(projectionMat));
        //绘图
        glBindVertexArray(VAO);
        //glDrawArrays(GL_TRIANGLES, 0, 36);
        for (unsigned int i = 0; i < 10; i++)
        {
            glm::mat4 modelMat = glm::mat4(1.0f);
            modelMat = glm::translate(modelMat, cubePositions[i]);
            modelMat = glm::rotate(modelMat, (float)glfwGetTime(), glm::vec3(1.0f, 0.3f, 0.5f));
            ourShader.setMat4("model", modelMat);
            glDrawArrays(GL_TRIANGLES, 0, 36);
        }

        //glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
        /*
        * 
        void glDrawElements(	GLenum mode,
 	    GLsizei count,
 	    GLenum type,
 	    const GLvoid * indices);
        */
        //刷新
        glfwSwapBuffers(window);
        glfwPollEvents();
    }
    //释放缓存资源
    glDeleteVertexArrays(1, &VAO);
    glDeleteBuffers(1, &VBO);
    glDeleteBuffers(1, &EBO);
    //释放glfw资源
    glfwTerminate();

    return 0;
}

参考:

坐标系统 - LearnOpenGL CN (learnopengl-cn.github.io)

你可能感兴趣的:(OpenGL,算法,计算机视觉,人工智能)