主要内容:
画一个立方体,然后设计一个camera类。本文涉及的内容有点多,请读者耐心的看下去,这里不仅有软件的配置,还有shader的应用,以及摄像机类的编写,还包括一些矩阵变换之类的,闲话少说,具体内容一步一步展开。

按照我们的思路,首先需要的是数据,顶点的数据,画一个立方体,需要八个顶点的数据。一个正方体如何画出来,需要一个面一个面的哈,那么正方体有6个面,而每个面呢?是一个正方形,我们把正方形划分为两个三角形,这个三角形是opengl中最小的片元了。如下图所示:
这里写图片描述

讲到这里,可能有点过早了,所以还是要从基本的三角形开始。
三角形的顶点数据准备:
这里写图片描述
数据如下:
float vertices[]={
-0.5f,-0.5f,0.0f,
0.5f,-0.5f,0.0f,
0.0f,0.5f,0.0f
};
我们为什么画一个逆时针的指示图呢?这个只是代表,上面的数组的是从左下角开始到右下角再到上顶点结束。这个数据是逆时针的,与是否是正方向无关。
然后我们定义一个顶点着色器,负责接收这些数据。
vertexShader内容如下:

#version 330 core
layout (location=0) in vec3 aPos;
void main()
{gl_Position = vec4(aPos.x,aPos.y,aPos.z,1.0);
}

layout=0,因为这里只有一个顶点位置属性,所以location=0。
shader用于接收数据,那么如何将数据传输到shader呢?是通过显卡内部的一块缓存区域,暂时这么理解。对应到程序,那就是vbo啦。
首先,我们创建一个vbo对象:
unsigned int VBO;
glGenBuffers(1,&VBO);
定义一个无符号数字,用于保存创建的VBO的唯一标识。
然后绑定这个对象:
glBindBuffer(GL_ARRAY_BUFFER,VBO);
然后拷贝数据到这个对象:
glBufferData(GL_ARRAY_BUFFER,sizeof(vertices),vertices,GL_STATIC_DRAW);
然后数据是拷贝进去了,那么如何解析这些数据呢?
glVertexAttribPointer(0,3,GL_FLOAT,GL_FALSE,3*sizeof(float),(void*)0);
第1个参数:0,因为这里只有一个属性,所以从0开始。
第2个参数:3,表示某个属性包含的分量的个数。这里有3个顶点,但是每个顶点包含3个分量,也就是x、y、z。
第3个参数:顶点属性中每个分量的数据类型是什么,这里是float类型。
第4个参数:表示是否将数据标准化,这里不需要,为啥不需要,我也不知道。
第5个参数:是每个属性的长度,也就是步长,什么是步长,也就是第一个属性从多少道多少,第2个属性从多少到多少,每当我们要新的属性的时候,一步要走多少,这里每个属性包含3个float长度的数据,所以步长为3。
第6个参数:表示属性的偏移,因为我们这里的属性只有一个也就是顶点位置属性,没有其他的属性,所以这里的偏移为0。
接下来就是将这个属性的状态变为使能状态,也就是可用的状态。
glEnableVertexAttribArray(0);
下面是创建shader,并做连接处理,以渲染这个三角形。
int vertexShader = glCreateShader(GL_VERTEX_SHADER);
然后将上面的shader字符串与这个shader相互关联起来。
glShaderSource(vertexShader,1,&vertexShaderSource,NULL);
编译这个shader。
glCompileShader(vertexShader);
然后我们在创建片段着色器。顶点着色器,负责接收我们的顶点数据,对顶点处理之后,就要传递给片段着色器进行上色了,说到这里,我们就要回顾下渲染管线的几个阶段了。
最初的阶段,我们只有各个顶点的数据,顶点数据这里说明一下,它不仅仅可以包含位置信息,还可以有颜色信息、纹理坐标信息。这些都是以单独的数据存在的比如上面我们的三角形的三个顶点数据。
有了各自独立的顶点数据,我们并没有给出任何的指令要求将这些数据呈现出来,到底是一条线、还是一个三角形、还是就是一个顶点,于是接下来的渲染管线做得就是组装顶点。这个阶段之后,我们就知道,到底得到了什么样的图形了。
下一个阶段,就是几何渲染阶段,这个阶段主要是产生新的顶点,然后呢将新生成的顶点连接起来,得到新的形状。
几何阶段之后,就是离散化的过程,也就是所谓的光栅化阶段,啥意思呢?我们上面得到的就是一整块的面片,一个面,那么在电脑中如何染出这一个面呢?我们知道屏幕上只有一个一个点,由这些点组合而成,所以在几何阶段之后就是将一个面,分成多个点的过程。也就是说,我们有最初的少量的点,最终变换处理多个点,由这多个点,展示一个面。再接下来就是上色的过程,我们要对这些离散出来的点进行染色。
再接下来就是,颜色的最后处理,比如透明测试、混合处理等,最终把满足条件的、混合处理之后的颜色输出。
经过这些阶段之后,由最初的顶点数据变为了有颜色的图形。
具体的图示如下:
这里写图片描述
所以经过上面的回顾之后,我们要自定义的,自己实现的,就是顶点处理阶段和像素处理阶段。
那么接下来我们就看看像素着色器的处理方式:

#version 330 core
out vec4 FragColor;
void main()
{FragColor = vec4(1.0f,0.5f,0.2f,1.0f);
}

功能只有一个就是简单的着色。
下面是创建一个片段着色器的代码:

unsigned int fragmentShader;
fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentShader, 1, &fragmentShaderSource, NULL);
glCompileShader(fragmentShader);

下面是将两个shader连接起来,并且使用shader program程序进行编译。

int shaderProgram = glCreateProgram();
glAttachShader(shaderProgram, vertexShader);
glAttachShader(shaderProgram, fragmentShader);
glLinkProgram(shaderProgram);

到这里,似乎可以画出一个三角形了,但是还是少了主循环。

while (!glfwWindowShouldClose(window))
{processInput(window);glClearColor(0.2f, 0.3f, 0.3f, 1.0f);glClear(GL_COLOR_BUFFER_BIT);glUseProgram(shaderProgram);glBindVertexArray(VAO);glDrawArrays(GL_TRIANGLES, 0, 3);glfwSwapBuffers(window);glfwPollEvents();
}

解释上面的代码:
1、processInput(window);
处理所有的输入,比如下面的输入实现。

void processInput(GLFWwindow *window)
{if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS){glfwSetWindowShouldClose(window, true);}
}

这个函数的主要目的是处理键盘的输入,比如上面的函数,当我们输入Esc键之后,就会关闭窗口。
2、
glClearColor(0.2f,0.3f,0.3f,1.0f);
glClear(GL_COLOR_BUFFER_BIT);
这两句代码的意思是使用glClearColor指定的颜色来设置缓冲区。

3、glUseProgram(shaderProgram);
使用shader的应用程序。

4、glBindVertexArray(VAO);
绑定一个VAO对象,那么接下来的VBO、EBO、其他的解析属性的操作都将储存在VAO对象中,简化绑定操作。

5、glDrawArrays(GL_TRIANGLES,0,3);
指定opengl画三角形,0表示从数据的那个位置开始,3表示画3个顶点的数据。

6、glfwSwapBuffers(window);

下面的我们来看看如何把窗口显示出来,我们使用的glfw的方式显示窗口。

#include <glad/glad.h>
#include <GLFW/glfw3.h>
#include <iostream>const unsigned int SCR_WIDTH = 800;
const unsigned int SCR_HEIGHT = 600;int main()
{glfwInit();GLFWwindow* window = glfwCreateWindow(SCR_WIDTH, SCR_HEIGHT, "LearnOpenGL", NULL, NULL);while (!glfwWindowShouldClose(window)){glfwSwapBuffers(window);glfwPollEvents();}return 0;
}

上面的这段代码,是最简单的将窗口显示出来的方式。我们试图将上面的代码再次精简,发现已经不能再精简了,比如我们把glfwInit();改为如下的代码:

#include <glad/glad.h>
#include <GLFW/glfw3.h>
#include <iostream>
using namespace std;const unsigned int SCR_WIDTH = 800;
const unsigned int SCR_HEIGHT = 600;int main()
{//glfwInit();GLFWwindow* window = glfwCreateWindow(SCR_WIDTH, SCR_HEIGHT, "LearnOpenGL", NULL, NULL);return 0;
}

发现没有任何窗口,只有一个控制台。而如果将glfwInit()打开,运行之后会发现白色窗口一闪而过。原因是我们少了一个主循环,所以经过上面的测试,我们将while循环加到上面去,最终运行之后得到一个窗口了。

那么下面是不是就要将shader使用上去了呢?再次整合代码如下:

#include <glad/glad.h>
#include <GLFW/glfw3.h>
#include <iostream>
using namespace std;const unsigned int SCR_WIDTH = 800;
const unsigned int SCR_HEIGHT = 600;const char *vertexShaderSource = "#version 330 core\n"
"layout (location = 0) in vec3 aPos;\n"
"void main()\n"
"{\n"
"   gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0);\n"
"}\0";
const char *fragmentShaderSource = "#version 330 core\n"
"out vec4 FragColor;\n"
"void main()\n"
"{\n"
"   FragColor = vec4(1.0f, 0.5f, 0.2f, 1.0f);\n"
"}\n\0";int main()
{//初始化和创建窗口glfwInit();GLFWwindow* window = glfwCreateWindow(SCR_WIDTH, SCR_HEIGHT, "LearnOpenGL", NULL, NULL);//设置glfwMakeContextCurrent(window);gladLoadGLLoader((GLADloadproc)glfwGetProcAddress);//三角形的三个顶点数据float vertices[] = {-0.5f, -0.5f, 0.0f, // left  0.5f, -0.5f, 0.0f, // right 0.0f, 0.5f, 0.0f  // top   };unsigned int VBO, VAO;glGenVertexArrays(1, &VAO);glGenBuffers(1, &VBO);glBindVertexArray(VAO);glBindBuffer(GL_ARRAY_BUFFER, VBO);glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);glEnableVertexAttribArray(0);int vertexShader = glCreateShader(GL_VERTEX_SHADER);glShaderSource(vertexShader, 1, &vertexShaderSource, NULL);glCompileShader(vertexShader);int fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);glShaderSource(fragmentShader, 1, &fragmentShaderSource, NULL);glCompileShader(fragmentShader);int shaderProgram = glCreateProgram();glAttachShader(shaderProgram, vertexShader);glAttachShader(shaderProgram, fragmentShader);glLinkProgram(shaderProgram);while (!glfwWindowShouldClose(window)){glClearColor(0.2f, 0.3f, 0.3f, 1.0f);glClear(GL_COLOR_BUFFER_BIT);glUseProgram(shaderProgram);glBindVertexArray(VAO); glDrawArrays(GL_TRIANGLES, 0, 3);glfwSwapBuffers(window);glfwPollEvents();}return 0;
}

至此我们完成了一个三角形的绘制了。上面的代码只考虑的正确的情况,对于编译shader的失败等等其他报错信息我们一概不问,只关心起无意外的情况。

接下来我们应该画一个矩形,接着上面问题,一个矩形包含两个三角形,我们可以再增加一个顶点数据,如下所示:
这里写图片描述
数据如下:

    //三角形的三个顶点数据float vertices[] = {-0.5f,-0.5f,0.0f,0.5f,-0.5f,0.0f,0.5f,0.5f,0.0f,-0.5f, -0.5f, 0.0f,0.5f, 0.5f, 0.0f,-0.5f, 0.5f, 0.0f,};

然后只要改动while循环中的一句代码即可:

    glDrawArrays(GL_TRIANGLES, 0, 6);

意思是从0索引开始画6个点组成三角形。这里你也可以把0改为其他的值,比如3看看画的形状是什么,答案是上半个三角形。完整的代码如下:

#include <glad/glad.h>
#include <GLFW/glfw3.h>
#include <iostream>
using namespace std;const unsigned int SCR_WIDTH = 800;
const unsigned int SCR_HEIGHT = 600;const char *vertexShaderSource = "#version 330 core\n"
"layout (location = 0) in vec3 aPos;\n"
"void main()\n"
"{\n"
"   gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0);\n"
"}\0";
const char *fragmentShaderSource = "#version 330 core\n"
"out vec4 FragColor;\n"
"void main()\n"
"{\n"
"   FragColor = vec4(1.0f, 0.5f, 0.2f, 1.0f);\n"
"}\n\0";int main()
{//初始化和创建窗口glfwInit();GLFWwindow* window = glfwCreateWindow(SCR_WIDTH, SCR_HEIGHT, "LearnOpenGL", NULL, NULL);//设置glfwMakeContextCurrent(window);gladLoadGLLoader((GLADloadproc)glfwGetProcAddress);//三角形的三个顶点数据float vertices[] = {-0.5f,-0.5f,0.0f,0.5f,-0.5f,0.0f,0.5f,0.5f,0.0f,-0.5f, -0.5f, 0.0f,0.5f, 0.5f, 0.0f,-0.5f, 0.5f, 0.0f,};unsigned int VBO, VAO;glGenVertexArrays(1, &VAO);glGenBuffers(1, &VBO);glBindVertexArray(VAO);glBindBuffer(GL_ARRAY_BUFFER, VBO);glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);glEnableVertexAttribArray(0);int vertexShader = glCreateShader(GL_VERTEX_SHADER);glShaderSource(vertexShader, 1, &vertexShaderSource, NULL);glCompileShader(vertexShader);int fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);glShaderSource(fragmentShader, 1, &fragmentShaderSource, NULL);glCompileShader(fragmentShader);int shaderProgram = glCreateProgram();glAttachShader(shaderProgram, vertexShader);glAttachShader(shaderProgram, fragmentShader);glLinkProgram(shaderProgram);while (!glfwWindowShouldClose(window)){glClearColor(0.2f, 0.3f, 0.3f, 1.0f);glClear(GL_COLOR_BUFFER_BIT);glUseProgram(shaderProgram);glBindVertexArray(VAO); glDrawArrays(GL_TRIANGLES, 3, 6);glfwSwapBuffers(window);glfwPollEvents();}return 0;
}

那么下面我们就来介绍一下如何使用ebo的方式来减少重复数据的存储问题,例如上面的矩形四个顶点,而使用画三角形的方式画矩形的时候,有两个顶点重复存储了,分别是B和D两点。此时我们用EBO的方式记录顶点的索引来解决这个问题。

#include <glad/glad.h>
#include <GLFW/glfw3.h>
#include <iostream>
using namespace std;const unsigned int SCR_WIDTH = 800;
const unsigned int SCR_HEIGHT = 600;const char *vertexShaderSource = "#version 330 core\n"
"layout (location = 0) in vec3 aPos;\n"
"void main()\n"
"{\n"
"   gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0);\n"
"}\0";
const char *fragmentShaderSource = "#version 330 core\n"
"out vec4 FragColor;\n"
"void main()\n"
"{\n"
"   FragColor = vec4(1.0f, 0.5f, 0.2f, 1.0f);\n"
"}\n\0";int main()
{//初始化和创建窗口glfwInit();GLFWwindow* window = glfwCreateWindow(SCR_WIDTH, SCR_HEIGHT, "LearnOpenGL", NULL, NULL);//设置glfwMakeContextCurrent(window);gladLoadGLLoader((GLADloadproc)glfwGetProcAddress);//三角形的三个顶点数据float vertices[] = {-0.5f,-0.5f,0.0f,0.5f,-0.5f,0.0f,0.5f,0.5f,0.0f,-0.5f,0.5f,0.0f,};unsigned int indices[] = {  0, 1, 2,  //第一个三角形0, 2, 3   //第二个三角形};unsigned int VBO, VAO, 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, 3 * sizeof(float), (void*)0);glEnableVertexAttribArray(0);int vertexShader = glCreateShader(GL_VERTEX_SHADER);glShaderSource(vertexShader, 1, &vertexShaderSource, NULL);glCompileShader(vertexShader);int fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);glShaderSource(fragmentShader, 1, &fragmentShaderSource, NULL);glCompileShader(fragmentShader);int shaderProgram = glCreateProgram();glAttachShader(shaderProgram, vertexShader);glAttachShader(shaderProgram, fragmentShader);glLinkProgram(shaderProgram);while (!glfwWindowShouldClose(window)){glClearColor(0.2f, 0.3f, 0.3f, 1.0f);glClear(GL_COLOR_BUFFER_BIT);glUseProgram(shaderProgram);glBindVertexArray(VAO); glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0); //改为glDrawElements即可。6为索引个数,0表示偏移。glfwSwapBuffers(window);glfwPollEvents();}return 0;
}

看看结果:
这里写图片描述

下面,我们再来看看,能否画一个立方体呢?在画一个立方体之前,我们要思考几个问题。
一个是数据问题,数据是怎样的,前面分析过,立方体,六个面,每个面两个三角形,也就是12个三角形,每个三角形3个顶点,于是要定义36个顶点。
这里写图片描述
如上图所示,我们对每个面再分割为两个三角形,于是有了下面的数组:

//三角形的三个顶点数据float vertices[] = {-0.5f, -0.5f, -0.5f,0.5f, -0.5f, -0.5f, 0.5f, 0.5f, -0.5f, 0.5f, 0.5f, -0.5f, -0.5f, 0.5f, -0.5f, -0.5f, -0.5f, -0.5f,-0.5f, -0.5f, 0.5f,0.5f, -0.5f, 0.5f, 0.5f, 0.5f, 0.5f,0.5f, 0.5f, 0.5f, -0.5f, 0.5f, 0.5f, -0.5f, -0.5f, 0.5f, -0.5f, 0.5f, 0.5f,-0.5f, 0.5f, -0.5f, -0.5f, -0.5f, -0.5f, -0.5f, -0.5f, -0.5f, -0.5f, -0.5f, 0.5f, -0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f,0.5f, 0.5f, -0.5f, 0.5f, -0.5f, -0.5f, 0.5f, -0.5f, -0.5f,0.5f, -0.5f, 0.5f, 0.5f, 0.5f, 0.5f, -0.5f, -0.5f, -0.5f, 0.5f, -0.5f, -0.5f, 0.5f, -0.5f, 0.5f, 0.5f, -0.5f, 0.5f, -0.5f, -0.5f, 0.5f,-0.5f, -0.5f, -0.5f, -0.5f, 0.5f, -0.5f, 0.5f, 0.5f, -0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, -0.5f, 0.5f, 0.5f, -0.5f, 0.5f, -0.5f, };

于是我们将上面的画三角形的程序稍微改动一下,有如下的代码:

#include <glad/glad.h>
#include <GLFW/glfw3.h>
#include <iostream>
using namespace std;const unsigned int SCR_WIDTH = 800;
const unsigned int SCR_HEIGHT = 600;const char *vertexShaderSource = "#version 330 core\n"
"layout (location = 0) in vec3 aPos;\n"
"void main()\n"
"{\n"
"   gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0);\n"
"}\0";
const char *fragmentShaderSource = "#version 330 core\n"
"out vec4 FragColor;\n"
"void main()\n"
"{\n"
"   FragColor = vec4(1.0f, 0.5f, 0.2f, 1.0f);\n"
"}\n\0";int main()
{//初始化和创建窗口glfwInit();GLFWwindow* window = glfwCreateWindow(SCR_WIDTH, SCR_HEIGHT, "LearnOpenGL", NULL, NULL);//设置glfwMakeContextCurrent(window);gladLoadGLLoader((GLADloadproc)glfwGetProcAddress);//三角形的三个顶点数据float vertices[] = {-0.5f, -0.5f, -0.5f,0.5f, -0.5f, -0.5f, 0.5f, 0.5f, -0.5f, 0.5f, 0.5f, -0.5f, -0.5f, 0.5f, -0.5f, -0.5f, -0.5f, -0.5f,-0.5f, -0.5f, 0.5f,0.5f, -0.5f, 0.5f, 0.5f, 0.5f, 0.5f,0.5f, 0.5f, 0.5f, -0.5f, 0.5f, 0.5f, -0.5f, -0.5f, 0.5f, -0.5f, 0.5f, 0.5f,-0.5f, 0.5f, -0.5f, -0.5f, -0.5f, -0.5f, -0.5f, -0.5f, -0.5f, -0.5f, -0.5f, 0.5f, -0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f,0.5f, 0.5f, -0.5f, 0.5f, -0.5f, -0.5f, 0.5f, -0.5f, -0.5f,0.5f, -0.5f, 0.5f, 0.5f, 0.5f, 0.5f, -0.5f, -0.5f, -0.5f, 0.5f, -0.5f, -0.5f, 0.5f, -0.5f, 0.5f, 0.5f, -0.5f, 0.5f, -0.5f, -0.5f, 0.5f,-0.5f, -0.5f, -0.5f, -0.5f, 0.5f, -0.5f, 0.5f, 0.5f, -0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, -0.5f, 0.5f, 0.5f, -0.5f, 0.5f, -0.5f, };unsigned int VBO, VAO;glGenVertexArrays(1, &VAO);glGenBuffers(1, &VBO);glBindVertexArray(VAO);glBindBuffer(GL_ARRAY_BUFFER, VBO);glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);glEnableVertexAttribArray(0);int vertexShader = glCreateShader(GL_VERTEX_SHADER);glShaderSource(vertexShader, 1, &vertexShaderSource, NULL);glCompileShader(vertexShader);int fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);glShaderSource(fragmentShader, 1, &fragmentShaderSource, NULL);glCompileShader(fragmentShader);int shaderProgram = glCreateProgram();glAttachShader(shaderProgram, vertexShader);glAttachShader(shaderProgram, fragmentShader);glLinkProgram(shaderProgram);while (!glfwWindowShouldClose(window)){glClearColor(0.2f, 0.3f, 0.3f, 1.0f);glClear(GL_COLOR_BUFFER_BIT);glUseProgram(shaderProgram);glBindVertexArray(VAO); glDrawArrays(GL_TRIANGLES, 0, 36);glfwSwapBuffers(window);glfwPollEvents();}return 0;
}

其中唯一改动的是glDrawArrays(GL_TRIANGLES, 0, 36);变为了画36个顶点。
那么运行的结果为:
这里写图片描述
并没有出现立方体,而只是一个平面,为什么呢?因为我们是正对着物体的,后面的、侧面的、左右两的两个面都看不到,所以只看到一个面,于是我们想把这个立方体自动旋转一下看看有没有立方体的效果。这就涉及到旋转的操作了,那么旋转怎么做呢?
在前面http://blog.csdn.net/wodownload2/article/details/72637897
章节中我们已经推到了,如果是左手坐标系,绕y轴旋转的旋转矩阵的推导过程,那么这个矩阵最终为:
这里写图片描述
写成四维矩阵的即为:
这里写图片描述
那么在opengl中如何构建这个矩阵,又如何将这个矩阵和shader中的顶点着色器进行交互呢?这将是我们下面讨论的内容。
首先来看opengl中单位矩阵的产生方法,就是使用一句代码:glm::mat4 trans;即可,如下所示:
这里写图片描述
下面就是这个单位矩阵进行旋转一定的角度比如30度,代码如下:

#include <glad/glad.h>
#include <GLFW/glfw3.h>
#include <iostream>
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
using namespace std;int main()
{glm::mat4 trans;for (int i = 0; i < 4; ++i){cout << trans[i].x << " " << trans[i].y << " " << trans[i].z << " " << trans[i].w << endl;}trans = glm::rotate(trans, 30.0f, glm::vec3(0.0f, 1.0f, 0.0f));cout << endl;for (int i = 0; i < 4; ++i){cout << trans[i].x << " " << trans[i].y << " " << trans[i].z << " " << trans[i].w << endl;}return 0;
}

经过验证,代入上面的旋转矩阵,验证正确:
这里写图片描述

然后下面是将这个矩阵怎么传递给shader的顶点着色器。
在顶点着色器中我们定义一个类型为uniform类型的变量,这个变量的可以在C++程序中进行赋值,也就是说shader程序的和c++程序的交互可以通过uniform类型的变量建立起桥梁。比如下面的顶点着色器程序:

#version 330 core
layout (location=0) in vec3 aPos;
uniform mat4 transform;
void main()
{gl_Position = transform * vec4(aPos,1.0);
}

而片段着色器仍然使用上面的代码,如下:

#version 330 core
out vec4 FragColor;
void main()
{FragColor = vec4(1.0f, 0.5f, 0.2f, 1.0f);
}

上面的片段着色器仅仅是赋了一个颜色而已。
下面紧接着,顶点着色器中有了uniform类型mat4变量,那么c++程序中如何把这个矩阵传递给shader呢?

glm::mat4 transform;transform = glm::rotate(transform, 10*(float)glfwGetTime(), glm::vec3(0.0f, 1.0f, 0.0f)); //绕y轴旋转unsigned int transformLoc = glGetUniformLocation(shaderProgram, "transform");glUniformMatrix4fv(transformLoc, 1, GL_FALSE, glm::value_ptr(transform));

这个c++程序中,创建单位矩阵,然后绕y轴旋转指定角度,然后通过glGetUniformLocation找到shader中的transform变量,然后将矩阵与此变量关联即可。总的代码如下:

#include <glad/glad.h>
#include <GLFW/glfw3.h>
#include <iostream>
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
using namespace std;const unsigned int SCR_WIDTH = 800;
const unsigned int SCR_HEIGHT = 600;const char *vertexShaderSource = "#version 330 core\n"
"layout (location = 0) in vec3 aPos;\n"
"uniform mat4 transform;\n"
"void main()\n"
"{\n"
"   gl_Position = transform * vec4(aPos,1.0);\n"
"}\0";const char *fragmentShaderSource = "#version 330 core\n"
"out vec4 FragColor;\n"
"void main()\n"
"{\n"
"   FragColor = vec4(1.0f, 0.5f, 0.2f, 1.0f);\n"
"}\n\0";int main()
{//初始化和创建窗口glfwInit();GLFWwindow* window = glfwCreateWindow(SCR_WIDTH, SCR_HEIGHT, "LearnOpenGL", NULL, NULL);//设置glfwMakeContextCurrent(window);gladLoadGLLoader((GLADloadproc)glfwGetProcAddress);//三角形的三个顶点数据//三角形的三个顶点数据float vertices[] = {-0.5f, -0.5f, -0.5f,0.5f, -0.5f, -0.5f,0.5f, 0.5f, -0.5f,0.5f, 0.5f, -0.5f,-0.5f, 0.5f, -0.5f,-0.5f, -0.5f, -0.5f,-0.5f, -0.5f, 0.5f,0.5f, -0.5f, 0.5f,0.5f, 0.5f, 0.5f,0.5f, 0.5f, 0.5f,-0.5f, 0.5f, 0.5f,-0.5f, -0.5f, 0.5f,-0.5f, 0.5f, 0.5f,-0.5f, 0.5f, -0.5f,-0.5f, -0.5f, -0.5f,-0.5f, -0.5f, -0.5f,-0.5f, -0.5f, 0.5f,-0.5f, 0.5f, 0.5f,0.5f, 0.5f, 0.5f,0.5f, 0.5f, -0.5f,0.5f, -0.5f, -0.5f,0.5f, -0.5f, -0.5f,0.5f, -0.5f, 0.5f,0.5f, 0.5f, 0.5f,-0.5f, -0.5f, -0.5f,0.5f, -0.5f, -0.5f,0.5f, -0.5f, 0.5f,0.5f, -0.5f, 0.5f,-0.5f, -0.5f, 0.5f,-0.5f, -0.5f, -0.5f,-0.5f, 0.5f, -0.5f,0.5f, 0.5f, -0.5f,0.5f, 0.5f, 0.5f,0.5f, 0.5f, 0.5f,-0.5f, 0.5f, 0.5f,-0.5f, 0.5f, -0.5f,};unsigned int VBO, VAO;glGenVertexArrays(1, &VAO);glGenBuffers(1, &VBO);glBindVertexArray(VAO);glBindBuffer(GL_ARRAY_BUFFER, VBO);glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);glEnableVertexAttribArray(0);int vertexShader = glCreateShader(GL_VERTEX_SHADER);glShaderSource(vertexShader, 1, &vertexShaderSource, NULL);glCompileShader(vertexShader);int fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);glShaderSource(fragmentShader, 1, &fragmentShaderSource, NULL);glCompileShader(fragmentShader);int shaderProgram = glCreateProgram();glAttachShader(shaderProgram, vertexShader);glAttachShader(shaderProgram, fragmentShader);glLinkProgram(shaderProgram);while (!glfwWindowShouldClose(window)){glClearColor(0.2f, 0.3f, 0.3f, 1.0f);glClear(GL_COLOR_BUFFER_BIT);glUseProgram(shaderProgram);glm::mat4 transform;transform = glm::rotate(transform, 10*(float)glfwGetTime(), glm::vec3(0.0f, 1.0f, 0.0f)); //绕y轴旋转unsigned int transformLoc = glGetUniformLocation(shaderProgram, "transform");glUniformMatrix4fv(transformLoc, 1, GL_FALSE, glm::value_ptr(transform));glBindVertexArray(VAO);glDrawArrays(GL_TRIANGLES, 0, 36);glfwSwapBuffers(window);glfwPollEvents();}return 0;
}

运行的结果是,你会看到矩形由宽变窄,又由窄变宽。你就会感到很奇怪,所以我们稍微改下旋转的轴,让立方体绕着(1.0,1.0,0.0)这个轴旋转即可。

glm::mat4 transform;transform = glm::rotate(transform, 10*(float)glfwGetTime(), glm::vec3(1.0f, 1.0f, 0.0f)); 

结果你可以自己将这段代码贴上去即可,这里贴上一个图:
这里写图片描述
ok,到此,我们已经将一个立方体完整的画出来了,并且实现了旋转操作。
那么下面我们就要对这个立方体进行贴一张图片了,也就是使用纹理,让其变得好看一点,而不是单一的一个颜色。

查看全文
如若内容造成侵权/违法违规/事实不符,请联系编程学习网邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!

相关文章

  1. windows将tomcat配置成系统服务开机自启动

    在windows上有部署一个tomcat服务,需要在每次开机的时候自动启动,于是研究了下。并将步骤记录下来:1. 首先在【环境变量】--> 【系统变量】中增加CATALINA_HOME | JAVA_HOME | JRE_HOME2. 打开【命令提示符】将service.bat拖进命令提示符,然后回车,出现如下画面说明…...

    2024/4/12 14:56:12
  2. 许单单奋斗记:没有人比我更曲折

    进入职场4年半,许单单已经跳了3次槽,从年薪10万的互联网公司员工成为一个年薪近几百万的美国基金公司分析师,许单单的成功是几乎不可复制的。像他这样一个曾经一无所有的人,或许有更强的能力获得一切。许单单奋斗记许单单的故事非常适合被写成奋斗传奇。1982年出生的安徽农…...

    2024/4/11 20:08:22
  3. .net core 生成二维码

    其实生成二维码的组件有很多种,如:QrcodeNet,ZKWeb.Fork.QRCoder,QRCoder等我选QRCoder,是因为小而易用、支持大并发生成请求、不依赖任何库和网络服务。既然是.net core 那当然要用依赖注入,通过构造函数注入到控制器。 软件版本Asp.net Core:2.0(开发时最新) 项目结构S…...

    2024/4/17 18:35:27
  4. 许单单奋斗记

    进入职场4年半,许单单(微博)已经跳了3次槽,从年薪10万的互联网公司员工成为一个年薪近几百万的美国基金公司分析师,许单单的成功是几乎不可复制的。像他这样一个曾经一无所有的人,或许有更强的能力获得一切。许单单奋斗记  许单单的故事非常适合被写成奋斗传奇。1982年出…...

    2024/4/17 18:37:40
  5. Ubuntu tomcat配置https的方法

    参考文献: http://www.cnblogs.com/xwdreamer/p/3466661.html(后半部分需要做修正) http://tomcat.apache.org/tomcat-7.0-doc/ssl-howto.html http://blog.sina.com.cn/s/blog_682b5aa1010113uu.html(中文,比较实用) https://help.ubuntu.com/community/TomcatSSL http://…...

    2024/4/17 18:36:40
  6. SQL防注入大全——史上最全的 SQL 注入资料

    什么是 SQL 注入速查表?SQL注入速查表是可以为你提供关于不同种类 SQL注入漏洞 的详细信息的一个资源。这份速查表对于经验丰富的渗透测试人员,或者刚开始接触 Web应用安全 的初学者,都是一份很好的参考资料。关于这份 SQL 注入速查表这份 SQL 速查表最初是 2007 年时 Ferru…...

    2024/4/18 19:19:35
  7. IDEA - Tomcat 配置虚拟目录用来存放图片和访问图片

    目的配置tomcat虚拟目录用来存放图片和图片的访问;操作步骤1.点击工具栏的运行配置Edit ConfigurationsEdit Configurations2.在弹出的Run/debug Configurations中选中tomcat容器,选择deployment3.添加物理目录和并设置虚拟目录路径这里我选择了D盘下面的tmp文件夹作为物理目录…...

    2024/4/17 18:37:39
  8. 密码战争,区块链技术之路

    本文为区块链行业的知名创业者和投资者——“暴走恭亲王”龚鸣,在万向区块链蜂巢学院第五课上的演讲内容。龚鸣以现代计算机、密码学&区块链历史上十几位重要传奇人物为线索,从他们的故事,为大家介绍了区块链技术的演进之路。或许我们如今已经习惯了互联网带给我们生活的…...

    2024/4/17 18:37:27
  9. Java破解图片防盗链

    前言 今天想下载几张好看的壁纸,然后发现了一张是自己比较喜欢的额。然后点进去看看,WOW!好多好看的壁纸呀,于是我就起了贪念。哈哈!想把他们这一组图片打包下载,小白的方法就是一张一张下载,那样对于我们程序员来说是很low的办法。于是我考虑使用万能的java来下载他们的…...

    2024/4/17 18:37:39
  10. 从零搭建前端开发环境(零)——基础篇:1.npm、git及项目初始化

    从零搭建前端开发环境(零)——基础篇:1.npm、git及项目初始化从零搭建前端开发环境(零)——基础篇:2.webpack生产与开发环境配置从零搭建前端开发环境(零)——扩展篇:3.jest单测从零搭建前端开发环境(零)——扩展篇:4.eslint统一代码规范从零搭建前端开发环境(零)…...

    2024/4/11 20:08:58
  11. 如何预防SQL注入,XSS漏洞(spring,java)

    SQL注入简介SQL注入是由于程序员对用户输入的参数没有做好校验,让不法分子钻了SQL的空子, 比如:我们一个登录界面,要求用户输入用户名和密码: 用户名: ’ or 1=1– 密码: 点击登录之后,如果后台只有一条简单的待条件的sql语句,没有做特殊处理的话: 如: String …...

    2024/4/17 18:37:21
  12. Android 直播礼物动画实现之SVGA动画

    在最近做的直播项目中,产品要求发送礼物时,需要显示对应的礼物动画,其中几个礼物动画效果如下:看了这几个动画效果,是挺炫酷的,妥妥的能够增加用户体验,但是实现起来可就没那么容易了。Android中动画实现方案,主要有以下几种:(1)Frame Animation(逐帧动画)(2)Twe…...

    2024/4/17 18:37:09
  13. Dedecms 搜索模块sql注入

    Dedecms 搜索模块sql注入描述: Search模块对外部输入参数过滤不严谨,导致产生了sql注入漏洞。 - 收起 Dedecms plus/search.php 文件存在变量覆盖漏洞,导致$typeid能被二次覆盖,产生sql注入漏洞。 Dedecms 搜索模块sql注入危害: 被SQL注入后可能导致以下后果: 1.网页被篡改…...

    2024/4/17 18:38:40
  14. 阿里云https证书tomcat配置

    阅读本文前,请先参看前文http://blog.csdn.net/baidu_19473529/article/details/70037696 当我们使用Java生成的证书使用https访问时会出现未认证的问题,证书风险现在我们就申请一个阿里云云盾的免费证书 一、登录阿里云-->安全(云盾)-->证书服务->购买证书在配置单…...

    2024/4/17 18:36:22
  15. 2012前端技术回顾

    尽管Web前端技术诞生至今时日并不长,但随着Web技术的逐渐深入,今后将会在以下几方面发力。1. Web移动终端开发。2. JavaScript的兄弟们。3. 百花齐放的类库和框架。4. 工程化的Web前端开发规范。Web移动终端开发PhoneGap:一个开源的开发框架,使用HTML、CSS和JavaScript来构…...

    2024/4/11 20:09:22
  16. 关于在MyEclipse 2017 CI 10中遇到Tomcat配置的问题

    经过了一晚上的折腾,终于成功把MyEclipse成功破解。然后兴奋的去睡觉了,结果第二天配置Tomcat的时候却按网上的方法遇到了很多问题,在经过了自己不懈努力下(不好意思),终于成功配置了Tomcat。下面写一下自己出现的问题。在自己成功的打开MyEclipse之后,在按照window->…...

    2024/4/17 18:38:21
  17. 那个16岁盗走马化腾QQ 震惊央视的农村男孩去哪了

    十几年前,还没有微博、微信、知乎。 但在网络上却有这样一个无人不知,无人不晓的江湖——“天涯社区”,和它的名字一样,这里鱼龙混杂,又有情有义,有无数大神。 当年的天涯孕育了一个又一个爆点:慕容雪村和他的《成都,今夜请将我遗忘》、芙蓉姐姐、奇葩小月月、天下霸…...

    2024/4/17 18:38:40
  18. SQL注入攻击与防御

    什么是SQL注入 程序员在编写代码的时候,没有对用户输入数据的合法性进行判断,使应用程序存在安全隐患。攻击者可以提交一段精心构造的数据库查询代码,根据返回的结果,获得某些他想得知的数据,这就是所谓的SQL Injection,即SQL注入。受影响的系统:对输入的参数不进行检查…...

    2024/4/17 18:37:27
  19. JAVA获取视频播第一帧

    java获取视频播第一帧FFMPEG 功能很强大,做视频必备的软件。大家可通过 http://ffmpeg.org/ 了解。Windows版本的软件,可通过 http://ffmpeg.zeranoe.com/builds/ 下载。 因为有这个需求,通过 ffmpeg 获取视频第一帧图片 Google一把,就有了结果。 参考: 1、http://www.cod…...

    2024/4/11 20:10:34
  20. Web开发就业方向有哪些?前端自学能找到工作?

    Web前端自学好学吗?Web前端开发就业方向有哪些呢?很多朋友都想拥有一门IT技术,很多人首先是会选择自学的方式。但是没有基础的同学自学起来就比较费劲一些,因为自学Web前端的路上,会出现各种问题,遇到各种障碍,如果无法有效的解决,是很难自学成才的。所以,在学习之前,…...

    2024/4/17 18:37:33

最新文章

  1. VulnHub靶机 DC-5 打靶 渗透测试详情过程

    VulnHub靶机 DC-5 打靶 详细渗透测试过程 目录 VulnHub靶机 DC-5 打靶 详细渗透测试过程一、将靶机导入到虚拟机当中二、渗透流程主机发现端口扫描目录爆破文件包含getshell反弹shell提权 一、将靶机导入到虚拟机当中 靶机地址&#xff1a; https://download.vulnhub.com/dc/…...

    2024/4/19 7:41:49
  2. 梯度消失和梯度爆炸的一些处理方法

    在这里是记录一下梯度消失或梯度爆炸的一些处理技巧。全当学习总结了如有错误还请留言&#xff0c;在此感激不尽。 权重和梯度的更新公式如下&#xff1a; w w − η ⋅ ∇ w w w - \eta \cdot \nabla w ww−η⋅∇w 个人通俗的理解梯度消失就是网络模型在反向求导的时候出…...

    2024/3/20 10:50:27
  3. Docker - Nginx

    博文目录 文章目录 说明命令 说明 Docker Hub Nginx 数据卷数据卷印射在容器内的路径nginx.conf/etc/nginxnginx.html/usr/share/nginx/htmlnginx.log/var/log/nginx 容器内的路径说明/etc/nginx/nginx.conf配置文件/etc/nginx/conf.d配置目录/usr/share/nginx/html静态目录/…...

    2024/4/19 0:58:44
  4. 触想四代ARM架构工业一体机助力手功能康复机器人应用

    一、行业发展背景 手功能康复机器人是医疗机器人的一个分支&#xff0c;设计用于帮助肢体障碍患者进行手部运动和力量训练&#xff0c;在医疗健康领域有着巨大的成长空间。 手功能康复机器人融合了传感、控制、计算、AI视觉等智能科技与医学技术&#xff0c;能够帮助患者改善康…...

    2024/4/18 5:08:58
  5. Web CSS笔记3

    一、边框弧度 使用它你就可以制作盒子边框圆角 border-radius&#xff1a;1个值四个圆角值相同2个值 第一个值为左上角与右下角&#xff0c;第二个值为右上角与左下角3个值第一个值为左上角, 第二个值为右上角和左下角&#xff0c;第三个值为右下角4个值 左上角&#xff0c;右…...

    2024/4/14 11:40:28
  6. 【外汇早评】美通胀数据走低,美元调整

    原标题:【外汇早评】美通胀数据走低,美元调整昨日美国方面公布了新一期的核心PCE物价指数数据,同比增长1.6%,低于前值和预期值的1.7%,距离美联储的通胀目标2%继续走低,通胀压力较低,且此前美国一季度GDP初值中的消费部分下滑明显,因此市场对美联储后续更可能降息的政策…...

    2024/4/18 0:33:31
  7. 【原油贵金属周评】原油多头拥挤,价格调整

    原标题:【原油贵金属周评】原油多头拥挤,价格调整本周国际劳动节,我们喜迎四天假期,但是整个金融市场确实流动性充沛,大事频发,各个商品波动剧烈。美国方面,在本周四凌晨公布5月份的利率决议和新闻发布会,维持联邦基金利率在2.25%-2.50%不变,符合市场预期。同时美联储…...

    2024/4/18 22:36:36
  8. 【外汇周评】靓丽非农不及疲软通胀影响

    原标题:【外汇周评】靓丽非农不及疲软通胀影响在刚结束的周五,美国方面公布了新一期的非农就业数据,大幅好于前值和预期,新增就业重新回到20万以上。具体数据: 美国4月非农就业人口变动 26.3万人,预期 19万人,前值 19.6万人。 美国4月失业率 3.6%,预期 3.8%,前值 3…...

    2024/4/18 9:45:31
  9. 【原油贵金属早评】库存继续增加,油价收跌

    原标题:【原油贵金属早评】库存继续增加,油价收跌周三清晨公布美国当周API原油库存数据,上周原油库存增加281万桶至4.692亿桶,增幅超过预期的74.4万桶。且有消息人士称,沙特阿美据悉将于6月向亚洲炼油厂额外出售更多原油,印度炼油商预计将每日获得至多20万桶的额外原油供…...

    2024/4/17 2:33:17
  10. 【外汇早评】日本央行会议纪要不改日元强势

    原标题:【外汇早评】日本央行会议纪要不改日元强势近两日日元大幅走强与近期市场风险情绪上升,避险资金回流日元有关,也与前一段时间的美日贸易谈判给日本缓冲期,日本方面对汇率问题也避免继续贬值有关。虽然今日早间日本央行公布的利率会议纪要仍然是支持宽松政策,但这符…...

    2024/4/17 7:50:46
  11. 【原油贵金属早评】欧佩克稳定市场,填补伊朗问题的影响

    原标题:【原油贵金属早评】欧佩克稳定市场,填补伊朗问题的影响近日伊朗局势升温,导致市场担忧影响原油供给,油价试图反弹。此时OPEC表态稳定市场。据消息人士透露,沙特6月石油出口料将低于700万桶/日,沙特已经收到石油消费国提出的6月份扩大出口的“适度要求”,沙特将满…...

    2024/4/18 3:56:01
  12. 【外汇早评】美欲与伊朗重谈协议

    原标题:【外汇早评】美欲与伊朗重谈协议美国对伊朗的制裁遭到伊朗的抗议,昨日伊朗方面提出将部分退出伊核协议。而此行为又遭到欧洲方面对伊朗的谴责和警告,伊朗外长昨日回应称,欧洲国家履行它们的义务,伊核协议就能保证存续。据传闻伊朗的导弹已经对准了以色列和美国的航…...

    2024/4/18 3:56:04
  13. 【原油贵金属早评】波动率飙升,市场情绪动荡

    原标题:【原油贵金属早评】波动率飙升,市场情绪动荡因中美贸易谈判不安情绪影响,金融市场各资产品种出现明显的波动。随着美国与中方开启第十一轮谈判之际,美国按照既定计划向中国2000亿商品征收25%的关税,市场情绪有所平复,已经开始接受这一事实。虽然波动率-恐慌指数VI…...

    2024/4/18 3:55:30
  14. 【原油贵金属周评】伊朗局势升温,黄金多头跃跃欲试

    原标题:【原油贵金属周评】伊朗局势升温,黄金多头跃跃欲试美国和伊朗的局势继续升温,市场风险情绪上升,避险黄金有向上突破阻力的迹象。原油方面稍显平稳,近期美国和OPEC加大供给及市场需求回落的影响,伊朗局势并未推升油价走强。近期中美贸易谈判摩擦再度升级,美国对中…...

    2024/4/18 3:55:54
  15. 【原油贵金属早评】市场情绪继续恶化,黄金上破

    原标题:【原油贵金属早评】市场情绪继续恶化,黄金上破周初中国针对于美国加征关税的进行的反制措施引发市场情绪的大幅波动,人民币汇率出现大幅的贬值动能,金融市场受到非常明显的冲击。尤其是波动率起来之后,对于股市的表现尤其不安。隔夜美国股市出现明显的下行走势,这…...

    2024/4/18 3:55:45
  16. 【外汇早评】美伊僵持,风险情绪继续升温

    原标题:【外汇早评】美伊僵持,风险情绪继续升温昨日沙特两艘油轮再次发生爆炸事件,导致波斯湾局势进一步恶化,市场担忧美伊可能会出现摩擦生火,避险品种获得支撑,黄金和日元大幅走强。美指受中美贸易问题影响而在低位震荡。继5月12日,四艘商船在阿联酋领海附近的阿曼湾、…...

    2024/4/17 21:50:30
  17. 【原油贵金属早评】贸易冲突导致需求低迷,油价弱势

    原标题:【原油贵金属早评】贸易冲突导致需求低迷,油价弱势近日虽然伊朗局势升温,中东地区几起油船被袭击事件影响,但油价并未走高,而是出于调整结构中。由于市场预期局势失控的可能性较低,而中美贸易问题导致的全球经济衰退风险更大,需求会持续低迷,因此油价调整压力较…...

    2024/4/15 13:53:08
  18. 氧生福地 玩美北湖(上)——为时光守候两千年

    原标题:氧生福地 玩美北湖(上)——为时光守候两千年一次说走就走的旅行,只有一张高铁票的距离~ 所以,湖南郴州,我来了~ 从广州南站出发,一个半小时就到达郴州西站了。在动车上,同时改票的南风兄和我居然被分到了一个车厢,所以一路非常愉快地聊了过来。 挺好,最起…...

    2024/4/15 9:16:52
  19. 氧生福地 玩美北湖(中)——永春梯田里的美与鲜

    原标题:氧生福地 玩美北湖(中)——永春梯田里的美与鲜一觉醒来,因为大家太爱“美”照,在柳毅山庄去寻找龙女而错过了早餐时间。近十点,向导坏坏还是带着饥肠辘辘的我们去吃郴州最富有盛名的“鱼头粉”。说这是“十二分推荐”,到郴州必吃的美食之一。 哇塞!那个味美香甜…...

    2024/4/18 9:24:29
  20. 氧生福地 玩美北湖(下)——奔跑吧骚年!

    原标题:氧生福地 玩美北湖(下)——奔跑吧骚年!让我们红尘做伴 活得潇潇洒洒 策马奔腾共享人世繁华 对酒当歌唱出心中喜悦 轰轰烈烈把握青春年华 让我们红尘做伴 活得潇潇洒洒 策马奔腾共享人世繁华 对酒当歌唱出心中喜悦 轰轰烈烈把握青春年华 啊……啊……啊 两…...

    2024/4/18 3:56:18
  21. 扒开伪装医用面膜,翻六倍价格宰客,小姐姐注意了!

    原标题:扒开伪装医用面膜,翻六倍价格宰客,小姐姐注意了!扒开伪装医用面膜,翻六倍价格宰客!当行业里的某一品项火爆了,就会有很多商家蹭热度,装逼忽悠,最近火爆朋友圈的医用面膜,被沾上了污点,到底怎么回事呢? “比普通面膜安全、效果好!痘痘、痘印、敏感肌都能用…...

    2024/4/18 3:55:57
  22. 「发现」铁皮石斛仙草之神奇功效用于医用面膜

    原标题:「发现」铁皮石斛仙草之神奇功效用于医用面膜丽彦妆铁皮石斛医用面膜|石斛多糖无菌修护补水贴19大优势: 1、铁皮石斛:自唐宋以来,一直被列为皇室贡品,铁皮石斛生于海拔1600米的悬崖峭壁之上,繁殖力差,产量极低,所以古代仅供皇室、贵族享用 2、铁皮石斛自古民间…...

    2024/4/18 3:55:50
  23. 丽彦妆\医用面膜\冷敷贴轻奢医学护肤引导者

    原标题:丽彦妆\医用面膜\冷敷贴轻奢医学护肤引导者【公司简介】 广州华彬企业隶属香港华彬集团有限公司,专注美业21年,其旗下品牌: 「圣茵美」私密荷尔蒙抗衰,产后修复 「圣仪轩」私密荷尔蒙抗衰,产后修复 「花茵莳」私密荷尔蒙抗衰,产后修复 「丽彦妆」专注医学护…...

    2024/4/15 23:28:22
  24. 广州械字号面膜生产厂家OEM/ODM4项须知!

    原标题:广州械字号面膜生产厂家OEM/ODM4项须知!广州械字号面膜生产厂家OEM/ODM流程及注意事项解读: 械字号医用面膜,其实在我国并没有严格的定义,通常我们说的医美面膜指的应该是一种「医用敷料」,也就是说,医用面膜其实算作「医疗器械」的一种,又称「医用冷敷贴」。 …...

    2024/4/18 3:56:20
  25. 械字号医用眼膜缓解用眼过度到底有无作用?

    原标题:械字号医用眼膜缓解用眼过度到底有无作用?医用眼膜/械字号眼膜/医用冷敷眼贴 凝胶层为亲水高分子材料,含70%以上的水分。体表皮肤温度传导到本产品的凝胶层,热量被凝胶内水分子吸收,通过水分的蒸发带走大量的热量,可迅速地降低体表皮肤局部温度,减轻局部皮肤的灼…...

    2024/4/18 3:56:11
  26. 配置失败还原请勿关闭计算机,电脑开机屏幕上面显示,配置失败还原更改 请勿关闭计算机 开不了机 这个问题怎么办...

    解析如下&#xff1a;1、长按电脑电源键直至关机&#xff0c;然后再按一次电源健重启电脑&#xff0c;按F8健进入安全模式2、安全模式下进入Windows系统桌面后&#xff0c;按住“winR”打开运行窗口&#xff0c;输入“services.msc”打开服务设置3、在服务界面&#xff0c;选中…...

    2022/11/19 21:17:18
  27. 错误使用 reshape要执行 RESHAPE,请勿更改元素数目。

    %读入6幅图像&#xff08;每一幅图像的大小是564*564&#xff09; f1 imread(WashingtonDC_Band1_564.tif); subplot(3,2,1),imshow(f1); f2 imread(WashingtonDC_Band2_564.tif); subplot(3,2,2),imshow(f2); f3 imread(WashingtonDC_Band3_564.tif); subplot(3,2,3),imsho…...

    2022/11/19 21:17:16
  28. 配置 已完成 请勿关闭计算机,win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机...

    win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机”问题的解决方法在win7系统关机时如果有升级系统的或者其他需要会直接进入一个 等待界面&#xff0c;在等待界面中我们需要等待操作结束才能关机&#xff0c;虽然这比较麻烦&#xff0c;但是对系统进行配置和升级…...

    2022/11/19 21:17:15
  29. 台式电脑显示配置100%请勿关闭计算机,“准备配置windows 请勿关闭计算机”的解决方法...

    有不少用户在重装Win7系统或更新系统后会遇到“准备配置windows&#xff0c;请勿关闭计算机”的提示&#xff0c;要过很久才能进入系统&#xff0c;有的用户甚至几个小时也无法进入&#xff0c;下面就教大家这个问题的解决方法。第一种方法&#xff1a;我们首先在左下角的“开始…...

    2022/11/19 21:17:14
  30. win7 正在配置 请勿关闭计算机,怎么办Win7开机显示正在配置Windows Update请勿关机...

    置信有很多用户都跟小编一样遇到过这样的问题&#xff0c;电脑时发现开机屏幕显现“正在配置Windows Update&#xff0c;请勿关机”(如下图所示)&#xff0c;而且还需求等大约5分钟才干进入系统。这是怎样回事呢&#xff1f;一切都是正常操作的&#xff0c;为什么开时机呈现“正…...

    2022/11/19 21:17:13
  31. 准备配置windows 请勿关闭计算机 蓝屏,Win7开机总是出现提示“配置Windows请勿关机”...

    Win7系统开机启动时总是出现“配置Windows请勿关机”的提示&#xff0c;没过几秒后电脑自动重启&#xff0c;每次开机都这样无法进入系统&#xff0c;此时碰到这种现象的用户就可以使用以下5种方法解决问题。方法一&#xff1a;开机按下F8&#xff0c;在出现的Windows高级启动选…...

    2022/11/19 21:17:12
  32. 准备windows请勿关闭计算机要多久,windows10系统提示正在准备windows请勿关闭计算机怎么办...

    有不少windows10系统用户反映说碰到这样一个情况&#xff0c;就是电脑提示正在准备windows请勿关闭计算机&#xff0c;碰到这样的问题该怎么解决呢&#xff0c;现在小编就给大家分享一下windows10系统提示正在准备windows请勿关闭计算机的具体第一种方法&#xff1a;1、2、依次…...

    2022/11/19 21:17:11
  33. 配置 已完成 请勿关闭计算机,win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机”的解决方法...

    今天和大家分享一下win7系统重装了Win7旗舰版系统后&#xff0c;每次关机的时候桌面上都会显示一个“配置Windows Update的界面&#xff0c;提示请勿关闭计算机”&#xff0c;每次停留好几分钟才能正常关机&#xff0c;导致什么情况引起的呢&#xff1f;出现配置Windows Update…...

    2022/11/19 21:17:10
  34. 电脑桌面一直是清理请关闭计算机,windows7一直卡在清理 请勿关闭计算机-win7清理请勿关机,win7配置更新35%不动...

    只能是等着&#xff0c;别无他法。说是卡着如果你看硬盘灯应该在读写。如果从 Win 10 无法正常回滚&#xff0c;只能是考虑备份数据后重装系统了。解决来方案一&#xff1a;管理员运行cmd&#xff1a;net stop WuAuServcd %windir%ren SoftwareDistribution SDoldnet start WuA…...

    2022/11/19 21:17:09
  35. 计算机配置更新不起,电脑提示“配置Windows Update请勿关闭计算机”怎么办?

    原标题&#xff1a;电脑提示“配置Windows Update请勿关闭计算机”怎么办&#xff1f;win7系统中在开机与关闭的时候总是显示“配置windows update请勿关闭计算机”相信有不少朋友都曾遇到过一次两次还能忍但经常遇到就叫人感到心烦了遇到这种问题怎么办呢&#xff1f;一般的方…...

    2022/11/19 21:17:08
  36. 计算机正在配置无法关机,关机提示 windows7 正在配置windows 请勿关闭计算机 ,然后等了一晚上也没有关掉。现在电脑无法正常关机...

    关机提示 windows7 正在配置windows 请勿关闭计算机 &#xff0c;然后等了一晚上也没有关掉。现在电脑无法正常关机以下文字资料是由(历史新知网www.lishixinzhi.com)小编为大家搜集整理后发布的内容&#xff0c;让我们赶快一起来看一下吧&#xff01;关机提示 windows7 正在配…...

    2022/11/19 21:17:05
  37. 钉钉提示请勿通过开发者调试模式_钉钉请勿通过开发者调试模式是真的吗好不好用...

    钉钉请勿通过开发者调试模式是真的吗好不好用 更新时间:2020-04-20 22:24:19 浏览次数:729次 区域: 南阳 > 卧龙 列举网提醒您:为保障您的权益,请不要提前支付任何费用! 虚拟位置外设器!!轨迹模拟&虚拟位置外设神器 专业用于:钉钉,外勤365,红圈通,企业微信和…...

    2022/11/19 21:17:05
  38. 配置失败还原请勿关闭计算机怎么办,win7系统出现“配置windows update失败 还原更改 请勿关闭计算机”,长时间没反应,无法进入系统的解决方案...

    前几天班里有位学生电脑(windows 7系统)出问题了&#xff0c;具体表现是开机时一直停留在“配置windows update失败 还原更改 请勿关闭计算机”这个界面&#xff0c;长时间没反应&#xff0c;无法进入系统。这个问题原来帮其他同学也解决过&#xff0c;网上搜了不少资料&#x…...

    2022/11/19 21:17:04
  39. 一个电脑无法关闭计算机你应该怎么办,电脑显示“清理请勿关闭计算机”怎么办?...

    本文为你提供了3个有效解决电脑显示“清理请勿关闭计算机”问题的方法&#xff0c;并在最后教给你1种保护系统安全的好方法&#xff0c;一起来看看&#xff01;电脑出现“清理请勿关闭计算机”在Windows 7(SP1)和Windows Server 2008 R2 SP1中&#xff0c;添加了1个新功能在“磁…...

    2022/11/19 21:17:03
  40. 请勿关闭计算机还原更改要多久,电脑显示:配置windows更新失败,正在还原更改,请勿关闭计算机怎么办...

    许多用户在长期不使用电脑的时候&#xff0c;开启电脑发现电脑显示&#xff1a;配置windows更新失败&#xff0c;正在还原更改&#xff0c;请勿关闭计算机。。.这要怎么办呢&#xff1f;下面小编就带着大家一起看看吧&#xff01;如果能够正常进入系统&#xff0c;建议您暂时移…...

    2022/11/19 21:17:02
  41. 还原更改请勿关闭计算机 要多久,配置windows update失败 还原更改 请勿关闭计算机,电脑开机后一直显示以...

    配置windows update失败 还原更改 请勿关闭计算机&#xff0c;电脑开机后一直显示以以下文字资料是由(历史新知网www.lishixinzhi.com)小编为大家搜集整理后发布的内容&#xff0c;让我们赶快一起来看一下吧&#xff01;配置windows update失败 还原更改 请勿关闭计算机&#x…...

    2022/11/19 21:17:01
  42. 电脑配置中请勿关闭计算机怎么办,准备配置windows请勿关闭计算机一直显示怎么办【图解】...

    不知道大家有没有遇到过这样的一个问题&#xff0c;就是我们的win7系统在关机的时候&#xff0c;总是喜欢显示“准备配置windows&#xff0c;请勿关机”这样的一个页面&#xff0c;没有什么大碍&#xff0c;但是如果一直等着的话就要两个小时甚至更久都关不了机&#xff0c;非常…...

    2022/11/19 21:17:00
  43. 正在准备配置请勿关闭计算机,正在准备配置windows请勿关闭计算机时间长了解决教程...

    当电脑出现正在准备配置windows请勿关闭计算机时&#xff0c;一般是您正对windows进行升级&#xff0c;但是这个要是长时间没有反应&#xff0c;我们不能再傻等下去了。可能是电脑出了别的问题了&#xff0c;来看看教程的说法。正在准备配置windows请勿关闭计算机时间长了方法一…...

    2022/11/19 21:16:59
  44. 配置失败还原请勿关闭计算机,配置Windows Update失败,还原更改请勿关闭计算机...

    我们使用电脑的过程中有时会遇到这种情况&#xff0c;当我们打开电脑之后&#xff0c;发现一直停留在一个界面&#xff1a;“配置Windows Update失败&#xff0c;还原更改请勿关闭计算机”&#xff0c;等了许久还是无法进入系统。如果我们遇到此类问题应该如何解决呢&#xff0…...

    2022/11/19 21:16:58
  45. 如何在iPhone上关闭“请勿打扰”

    Apple’s “Do Not Disturb While Driving” is a potentially lifesaving iPhone feature, but it doesn’t always turn on automatically at the appropriate time. For example, you might be a passenger in a moving car, but your iPhone may think you’re the one dri…...

    2022/11/19 21:16:57