参考官方文档https://learnopengl-cn.github.io/
将坐标变换为标准化设备坐标,然后转换为屏幕坐标的过程是分布进行的。有5个比较重要的坐标系统:
坐标变换的过程中会用到几个变换矩阵:模型、观察、投影矩阵。
现在我们可以进行3D绘图了。
顶点着色器shader.vs
#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 transform;
uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;
void main(){
gl_Position=projection*view*model*vec4(aPos.x,aPos.y,aPos.z,1.0);
ourColor=aColor;
TexCoord=vec2(aTexCoord.x,1.0-aTexCoord.y);
}
main.cpp
...;
const unsigned int screenWidth = 800, screenHeight = 600;
...;
while(...){
...;
ourShader.use();
//
glm::mat4 model = glm::mat4(1.0f);
model = glm::rotate(model, glm::radians(-55.0f), glm::vec3(1.0f, 0.0f, 0.0f));
glm::mat4 view = glm::mat4(1.0f);
view = glm::translate(view, glm::vec3(0.0f, 0.0f, -3.0f));
glm::mat4 projection = glm::mat4(1.0f);
projection = glm::perspective(glm::radians(45.0f), (float)screenWidth / (float)screenHeight, 0.1f, 100.0f);
int modelLoc = glGetUniformLocation(ourShader.ID, "model");
glUniformMatrix4fv(modelLoc, 1, GL_FALSE, glm::value_ptr(model));
int viewLoc = glGetUniformLocation(ourShader.ID, "view");
glUniformMatri![opentk_40](C:\Users\xhh\Pictures\QQ浏览器截图\opentk_40.png)x4fv(viewLoc, 1, GL_FALSE, &view[0][0]);
int projectionLoc = glGetUniformLocation(ourShader.ID, "projection");
glUniformMatrix4fv(projectionLoc, 1, GL_FALSE, glm::value_ptr(projection));
...;
}
...;
然后我们来渲染一个立方体:
main.cpp
...;
float vertices[] = {
// ---- 位置 ---- - 纹理坐标 -
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, 0.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, 0.0f, 0.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, 0.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, 0.0f, 0.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, 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, 1.0f, 0.0f, // 左上
-0.5f, -0.5f, 0.5f, 1.0f, 1.0f, // 右上
0.5f, -0.5f,0.5f, 0.0f, 1.0f, // 左下
};
...;
while(...){
...;
//每次迭代之前清楚深度缓冲和颜色缓冲
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
//开启深度测试
glEnable(GL_DEPTH_TEST);
...;
model = glm::rotate(model,(float)glfwGetTime()* glm::radians(55.0f), glm::vec3(0.5f, 1.0f, 0.0f));
...;
glDrawArrays(GL_TRIANGLES, 0, 36);
...;
}
...;
另外,我们还可以在屏幕上显示更多的立方体:
...;
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)
};
...;
while(...){
...;
glBindVertexArray(VAO);
for (unsigned int i = 0; i < 10; i++)
{
glm::mat4 model=glm::mat4(1.0f);
model = glm::translate(model, cubePositions[i]);
float angle = 20.0f * i;
model = glm::rotate(model,(float)glfwGetTime()* glm::radians(angle), glm::vec3(1.0f, 0.3f, 0.5f));
ourShader.setMat4("model", model);
glDrawArrays(GL_TRIANGLES, 0, 36);
}
...;
}