對我們來說,座標系統大致分爲5個不同的座標系統:
局部空間(Local Space,或者稱爲物體空間(Object Space))
世界空間(World Space)
觀察空間(View Space,或者稱爲視覺空間(Eye Space))
裁剪空間(Clip Space)
屏幕空間(Screen Space)
上圖有點類似於shader的流水線操作:
1,局部座標是對象相對於局部原點的座標,也是物體起始的座標。
2,下一步是將局部座標變換爲世界空間座標,世界空間座標是處於一個更大的空間範圍的。這些座標相對於世界的全局原點,它們會和其它物體一起相對於世界的原點進行擺放。
3,接下來我們將世界座標變換爲觀察空間座標,使得每個座標都是從攝像機或者說觀察者的角度進行觀察的。
4,座標到達觀察空間之後,我們需要將其投影到裁剪座標。裁剪座標會被處理至-1.0到1.0的範圍內,並判斷哪些頂點將會出現在屏幕上。
5,最後,我們將裁剪座標變換爲屏幕座標,我們將使用一個叫做視口變換(Viewport Transform)的過程。視口變換將位於-1.0到1.0範圍的座標變換到由glViewport函數所定義的座標範圍內。最後變換出來的座標將會送到光柵器,將其轉化爲片段。
以前我們都是畫的二維圖像,現在這次就要開始畫3維的了。
老樣子先開始shader的修改:
這次的fragmentSource沒有什麼改變,改變的只有vertexSource:
#version 330 core
out vec4 vertexColor;
out vec2 TextureCoord;
layout(location = 3) in vec3 aPos;
layout(location = 4) in vec3 aColor;
layout(location = 5) in vec2 aTextureCoord;
uniform mat4 transform;
uniform mat4 modelMat;
uniform mat4 viewMat;
uniform mat4 projMat;
void main(){
//這個乘以的順序一定不能錯,否則就會失敗還沒有提示
gl_Position = projMat*viewMat*modelMat*vec4(aPos.x, aPos.y, aPos.z, 1.0);
vertexColor=vec4(aColor,1.0f);
TextureCoord=aTextureCoord;
}
接下來是main.cpp
先是變一下頂點數組,以及添加一個位置數組
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)
};
我們可以發現頂點數組中,沒有顏色數值,所以我們的
glVertexAttribPointer(3, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (GLvoid*)0);//從vao裏面在0號索引位上拿取三個值
glVertexAttribPointer(4, 3, GL_FLOAT, GL_FALSE, 8* sizeof(GLfloat), (GLvoid*)(3 * sizeof(GLfloat)));//從vao裏面在0號索引位上拿取三個值
glVertexAttribPointer(5, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (GLvoid*)(6 * sizeof(GLfloat)));//從vao裏面在0號索引位上拿取三個值
glEnableVertexAttribArray(3);//啓用屬性0,因爲默認是禁用的
glEnableVertexAttribArray(4);//啓用屬性0,因爲默認是禁用的
glEnableVertexAttribArray(5);//啓用屬性0,因爲默認是禁用的
需要改爲
glVertexAttribPointer(3, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), (GLvoid*)0);//從vao裏面在0號索引位上拿取三個值
glVertexAttribPointer(5, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), (GLvoid*)(3 * sizeof(GLfloat)));//從vao裏面在0號索引位上拿取三個值
glEnableVertexAttribArray(3);//啓用屬性0,因爲默認是禁用的
glEnableVertexAttribArray(5);//啓用屬性0,因爲默認是禁用的
再者就是
//模型舉證在後面,主要負責位移,旋轉,縮放
glm::mat4 viewMat;//視圖矩陣,其實就是攝像機視角位置
viewMat = glm::translate(viewMat, glm::vec3(0, 0, -5.0f));
glm::mat4 projMat;//投影矩陣,通過這個來剪切畫面到標準化座標系
projMat = glm::perspective(glm::radians(45.0f), (float)WIDTH / (float)HEIGHT, 0.01f, 100.0f);//這個是攝像機
glEnable(GL_DEPTH_TEST);
Shader* myShader = new Shader("vertexSource.txt", "fragmentSource.txt");
// Game loop
while (!glfwWindowShouldClose(window))
{ // 檢查事件,調用相應的回調函數,如下文的glfwInput函數
glfwInput(window);
//trans = glm::translate(trans, glm::vec3(0.01f, 0, 0));
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, texbufferA);//綁定
glActiveTexture(GL_TEXTURE2);
glBindTexture(GL_TEXTURE_2D, texbufferB);//綁定
glBindVertexArray(VAO);//每次循環都調用,綁定函數綁定VAO
//glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
for (size_t i = 1; i <= 10; i++)
{
glm::mat4 modelMat;//模型矩陣
modelMat = glm::translate(modelMat, cubePositions[i]);//根據cubPosition定義位置
if(i==1||i%3==0)//1和能整除3的旋轉
modelMat = glm::rotate(modelMat, (float)glfwGetTime(), glm::vec3(0, 1.0f, 0));
else
modelMat = glm::rotate(modelMat, glm::radians(i*10.0f), glm::vec3(0, 1.0f, 0));
myShader->Use();
glUniform1i(glGetUniformLocation(myShader->ID, "ourTexture"), 0);
glUniform1i(glGetUniformLocation(myShader->ID, "ourFace"), 2);
//glUniformMatrix4fv(glGetUniformLocation(myShader->ID,"transform"),1,GL_FALSE,glm::value_ptr(trans));
glUniformMatrix4fv(glGetUniformLocation(myShader->ID, "modelMat"), 1, GL_FALSE, glm::value_ptr(modelMat));
glUniformMatrix4fv(glGetUniformLocation(myShader->ID, "viewMat"), 1, GL_FALSE, glm::value_ptr(viewMat));
glUniformMatrix4fv(glGetUniformLocation(myShader->ID, "projMat"), 1, GL_FALSE, glm::value_ptr(projMat));
glDrawArrays(GL_TRIANGLES, 0, 36);
}
//glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);//繪製三角形,根據索引數組繪製6個頂點,索引數組類型爲GL_UNSIGNED_INT,偏移值爲0
//glDrawArrays(GL_TRIANGLES, 0, 3);//開始繪製三角形從0起始,畫三組數值
//glBindVertexArray(0);//解綁
// Swap the screen buffers
glfwSwapBuffers(window);
glfwPollEvents();
}
輸出效果如下: