dedecms手機(jī)網(wǎng)站插件網(wǎng)絡(luò)營銷方案策劃論文
? ? ? ? 在前面的文章當(dāng)中我們已經(jīng)成功播放了動(dòng)畫,讓我們的角色動(dòng)了起來,這一切變得比較有意思了起來。不過我們發(fā)現(xiàn),角色雖然說是動(dòng)了起來,不過只是在不停地原地踏步而已,而且我們也沒有辦法通過鍵盤來控制這個(gè)角色來進(jìn)行移動(dòng),現(xiàn)在整個(gè)項(xiàng)目處在一個(gè)只能看不能玩的處境。那么這篇文章,筆者將為大家介紹如何通過鍵盤輸入來控制我們繪制的角色。
輸入事件
? ? ? ??看過windows編程的朋友們應(yīng)該是知道的,當(dāng)我們的鍵盤上面的某一個(gè)按鍵被按下,鍵盤就會(huì)給系統(tǒng)發(fā)送一個(gè)信號(hào),系統(tǒng)也會(huì)接受到這個(gè)信號(hào),不過到底要怎么處理這個(gè)信號(hào)由具體的程序來決定。在這個(gè)案例中我們只處理鍵盤上的WASD按鍵的信號(hào)(不區(qū)分大小寫),我們整個(gè)案例使用的試glfw框架,該框架給我們提供的一些接口讓我們來處理這些信號(hào)。下面我們就來看一下代碼
void InputProcess(GLFWwindow* window) {//dirX,dirY,sameDirect,moveDirect都是全局變量//當(dāng)鍵盤上的 W 被按下時(shí)如何做出的處理if (glfwGetKey(window, GLFW_KEY_W) == GLFW_PRESS)dirX = 0, dirY = 1;//當(dāng)鍵盤上的 S 被按下時(shí)如何做出的處理else if (glfwGetKey(window, GLFW_KEY_S) == GLFW_PRESS)dirX = 0, dirY = -1;//當(dāng)鍵盤上的 A 被按下時(shí)如何做出的處理else if (glfwGetKey(window, GLFW_KEY_A) == GLFW_PRESS)dirX = -1, dirY = 0;//當(dāng)鍵盤上的 D 被按下時(shí)如何做出的處理else if (glfwGetKey(window, GLFW_KEY_D) == GLFW_PRESS)dirX = 1, dirY = 0;elsedirX = 0, dirY = 0;//當(dāng)輸入的方向和當(dāng)前移動(dòng)的方向不同時(shí)我們需要將整個(gè)圖形進(jìn)行一次翻轉(zhuǎn)sameDirect = dirX * moveDirect < 0 ? false : true;if (dirX != 0)moveDirect = dirX < 0 ? -1 : 1;elsemoveDirect = moveDirect;}
我們可以看到處理輸入特定按鍵輸入的函數(shù)是glfwGetKey(),GLFW_PRESS表示這個(gè)按鍵被按下,這里我們規(guī)定沿著X軸的右邊的方向是正方向,沿Y軸的上邊的方向是正方向,至于整個(gè)函數(shù)的邏輯,相信并不難理解。至于還想了解更多的輸入事件,比如說鼠標(biāo)輸入等,可以在編輯器上選中GLFW_KEY_S,然后按下F12鍵,就可以跳轉(zhuǎn)到對(duì)應(yīng)的程序文件,進(jìn)行翻找查看,找到對(duì)應(yīng)的宏定義之后依然可以使用glfwGetKey()進(jìn)行處理(這里筆者同樣建議讀者學(xué)會(huì)去閱讀源代碼,對(duì)自己的編程能力會(huì)有較大的提升)。鼠標(biāo)輸入宏定義如下
#define GLFW_MOUSE_BUTTON_1 0
#define GLFW_MOUSE_BUTTON_2 1
#define GLFW_MOUSE_BUTTON_3 2
#define GLFW_MOUSE_BUTTON_4 3
#define GLFW_MOUSE_BUTTON_5 4
#define GLFW_MOUSE_BUTTON_6 5
#define GLFW_MOUSE_BUTTON_7 6
#define GLFW_MOUSE_BUTTON_8 7
#define GLFW_MOUSE_BUTTON_LAST GLFW_MOUSE_BUTTON_8
#define GLFW_MOUSE_BUTTON_LEFT GLFW_MOUSE_BUTTON_1
#define GLFW_MOUSE_BUTTON_RIGHT GLFW_MOUSE_BUTTON_2
#define GLFW_MOUSE_BUTTON_MIDDLE GLFW_MOUSE_BUTTON_3
上面就是輸入事件,非常的簡單,有了輸入事件我們會(huì)序就可以控制自己的角色了,下面的矩陣變換才是重頭戲,因?yàn)樗O(shè)計(jì)到了線性代數(shù)的知識(shí)。
變換矩陣
? ? ? ? 按照現(xiàn)代圖形軟件的設(shè)計(jì)思路來講,圖形要經(jīng)過模型矩陣,觀察矩陣,投影矩陣(model_matrix ?view_matrix
?project_matrix)。
模型矩陣
????????可以理解為我們創(chuàng)建一個(gè)圖形時(shí)各個(gè)頂點(diǎn)相對(duì)于世界原點(diǎn)的坐標(biāo),我們?cè)谧铋_始輸入的坐標(biāo)位置都是相對(duì)于世界原點(diǎn)坐標(biāo)而言的,每個(gè)頂點(diǎn)的坐標(biāo)就是一個(gè)就是一個(gè)模型矩陣,可能有些朋友們會(huì)比較疑惑,為什么不把整個(gè)圖形作為一個(gè)模型矩陣了?這里請(qǐng)讀者們記住一個(gè)原則,計(jì)算機(jī)圖形當(dāng)中的所有圖形都是由頂點(diǎn)構(gòu)成,我們通過設(shè)定對(duì)應(yīng)的圖元,以及繪制順序,來告訴計(jì)算機(jī)這些頂點(diǎn)將要繪制什么樣的圖形。無論我們對(duì)模型矩陣進(jìn)行任何平移,旋轉(zhuǎn),縮放的操作都是在對(duì)頂點(diǎn)進(jìn)行操作。
平移矩陣
我們可以看到,右邊的坐標(biāo)與左邊的平移矩陣相乘,各個(gè)分量就加上了平移的分量。可能有的朋友又有疑問了,為什么這個(gè)點(diǎn)的坐標(biāo)有四個(gè)分量,三維的空間坐標(biāo)不是應(yīng)該只有三個(gè)向量嗎?其實(shí)我們?cè)跀?shù)學(xué)上管第四個(gè)分量叫作齊次量,它的存在有更多數(shù)學(xué)意義,這里就不展開講了,要不然就扯得實(shí)在太遠(yuǎn)了,它在這里作用就是就是給每個(gè)分量加上對(duì)應(yīng)平移量,讀者可以將第四個(gè)分量寫作0試一下,兩個(gè)矩陣相乘過后你就會(huì)發(fā)現(xiàn)這個(gè)平移矩陣沒有起到任何得作用。所以我們一般把頂點(diǎn)的第四個(gè)分量寫作1,向量的第四個(gè)分量寫作0,以為向量的平移是沒有數(shù)學(xué)意義的。
旋轉(zhuǎn)矩陣
? ? ? ? 旋轉(zhuǎn)的話,我們一般會(huì)將讓該物體繞著某一個(gè)軸進(jìn)行旋轉(zhuǎn),就比如說繞Z軸旋轉(zhuǎn)angle°得到向量
(頂點(diǎn)的話也沒有問題,因?yàn)榈谒膫€(gè)分量并沒有參與到運(yùn)算當(dāng)中)
?旋轉(zhuǎn)矩陣具體如下
?就是想要旋轉(zhuǎn)的角度我不過歐拉旋轉(zhuǎn)陣,有個(gè)很致命的問題,那就是萬象死鎖問題,有興趣去了解的話,大家可以自己去查閱一些相關(guān)的資料。(如果制作的是一個(gè)2D游戲的話不需要擔(dān)心這個(gè)問題)
縮放矩陣
如果我們把縮放變量表示為(S1,S2,S3)我們可以為任意向量(x,y,z)定義一個(gè)縮放矩陣:
S1,S2,S3各個(gè)分量大于1,就是對(duì)相對(duì)應(yīng)的分量進(jìn)行放大,小于1就是縮小。
對(duì)模型進(jìn)行變換的矩陣就這么三種,只是這三種就可以組合出我們想要的所有的變化,可能有很多讀者并不相信,可這就是事實(shí)。數(shù)學(xué)就是這么神奇!
觀察矩陣
? ? ? ? 觀察矩陣,也可以叫作相機(jī)矩陣。不過這個(gè)案例相機(jī)矩陣的效果不是很明顯,因?yàn)槲覀兊哪P褪瞧矫娴?#xff0c;就算移動(dòng)相機(jī)也看不出什么效果,到時(shí)候筆者單獨(dú)做一個(gè)案例來講這個(gè)東西。所以在這個(gè)案例單中我們將它設(shè)置為一個(gè)單位陣E。
投影矩陣
? ? ? ? 簡言之就是將三位空間當(dāng)中的物體投影到我們屏幕上來。沒錯(cuò)雖然我們做的案例是個(gè)二維平面的圖形,但是他是實(shí)打?qū)嵲?D空間當(dāng)中。投影的方式有兩種,正交投影和透視投影,透視投影就和我們生活中看到的物體同樣的效果,滿足近大遠(yuǎn)小的規(guī)律。正交投影將沒有這種效果,它無論距離屏幕有多遠(yuǎn),投影到屏幕上是一樣的大小。
正交投影
????????正射投影矩陣定義了一個(gè)類似立方體的平截頭箱,它定義了一個(gè)裁剪空間,在這空間之外的頂點(diǎn)都會(huì)被裁剪掉。創(chuàng)建一個(gè)正射投影矩陣需要指定可見平截頭體的寬、高和長度。在使用正射投影矩陣變換至裁剪空間之后處于這個(gè)平截頭體內(nèi)的所有坐標(biāo)將不會(huì)被裁剪掉。它的平截頭體看起來像一個(gè)容器:
?????????上面的平截頭體定義了可見的坐標(biāo),它由寬、高、近(Near)平面和遠(yuǎn)(Far)平面所指定。任何出現(xiàn)在近平面之前或遠(yuǎn)平面之后的坐標(biāo)都會(huì)被裁剪掉。正射平截頭體直接將平截頭體內(nèi)部的所有坐標(biāo)映射為標(biāo)準(zhǔn)化設(shè)備坐標(biāo),因?yàn)槊總€(gè)向量的w分量都沒有進(jìn)行改變;如果w分量等于1.0,透視除法則不會(huì)改變這個(gè)坐標(biāo)。
透視投影
????????如果你曾經(jīng)體驗(yàn)過實(shí)際生活給你帶來的景象,你就會(huì)注意到離你越遠(yuǎn)的東西看起來更小。這個(gè)奇怪的效果稱之為透視(Perspective)。透視的效果在我們看一條無限長的高速公路或鐵路時(shí)尤其明顯,正如下面圖片顯示的那樣:
?????????正如你看到的那樣,由于透視,這兩條線在很遠(yuǎn)的地方看起來會(huì)相交。這正是透視投影想要模仿的效果,它是使用透視投影矩陣來完成的。這個(gè)投影矩陣將給定的平截頭體范圍映射到裁剪空間,除此之外還修改了每個(gè)頂點(diǎn)坐標(biāo)的w值,從而使得離觀察者越遠(yuǎn)的頂點(diǎn)坐標(biāo)w分量越大。被變換到裁剪空間的坐標(biāo)都會(huì)在-w到w的范圍之間(任何大于這個(gè)范圍的坐標(biāo)都會(huì)被裁剪掉)。OpenGL要求所有可見的坐標(biāo)都落在-1.0到1.0范圍內(nèi)。
變換矩陣的實(shí)際應(yīng)用
? ? ? ? 相信很多讀者都看過Games101的課,課上面老師只講了原理,并沒有告訴朋友具體的代碼應(yīng)該怎么寫,要求觀眾自行學(xué)習(xí)。不過我們都知道理論向?qū)嵺`落地那是有一道巨大的鴻溝需要去跨越的,所以筆者將會(huì)用上面的知識(shí)來告訴大家如何讓我們屏幕中的角色在屏幕上進(jìn)行移動(dòng)。
準(zhǔn)備數(shù)學(xué)庫
? ? ? ? OpenGL有一個(gè)專門的數(shù)學(xué)庫glm,讓我們?nèi)ナ謱戇@些矩陣乘法非常的耗費(fèi)時(shí)間,而且代碼的效率不高,所以我們?cè)诎咐?dāng)中glm這個(gè)三方庫。
glm github官方網(wǎng)址https://github.com/g-truc/glm
如果上面這個(gè)網(wǎng)站打不開,可以到這個(gè)網(wǎng)站去找glm庫https://gitee.com/HonyOrange_227/OpenGLProjectInitial
把這個(gè)項(xiàng)目下載或者克隆下來,在下面這個(gè)路徑就可找到glm庫了,該文章當(dāng)中所有需要使用到的代碼都在這個(gè)項(xiàng)目當(dāng)中,甚至美術(shù)素材,那只跑動(dòng)的青蛙也在這個(gè)項(xiàng)目當(dāng)中。
將整個(gè)文件,復(fù)制自己項(xiàng)目下面就可以了,記得配置對(duì)應(yīng)的路勁。
使用投影矩陣
? ? ? ? 因?yàn)檫@個(gè)項(xiàng)目我們創(chuàng)建的都是2D平面元素,所以這里我打算使用正交投影。具體代碼如下:
//原點(diǎn)到底部和頂部的距離依然設(shè)置是-1,1 左右兩邊給去窗口的長寬比
glm::mat4 projection = glm::ortho(-viewPortSize.x/ viewPortSize.y, viewPortSize.x / viewPortSize.y, -1.0f, 1.0f);
//觀察矩陣為單位陣
glm::mat4 view = glm::mat4(1.0f);
glm::mat4 viewprojection = projection * view;
有的朋友注意到最后一行代碼,筆者將兩個(gè)矩陣乘了起來,沒錯(cuò)從模型矩陣從觀察矩陣到投影矩陣的方式就是矩陣相乘,可能讀者還要問,為什么是project*view 不是 view*project 。這是因?yàn)?strong>OpenGL的矩陣都是列主序的矩陣,前面的數(shù)學(xué)公式當(dāng)中我們可以看到,頂點(diǎn)坐標(biāo)陣都是在變換矩陣的右邊,大家要是感覺這很疑惑的話可以這樣記,那個(gè)矩陣在公式上距離頂點(diǎn)陣最近它就最先發(fā)揮作用,這樣是不是感覺好多了。
? ? ? ? 有了這個(gè)矩陣過后,我們需要將它上傳到著色器上,所以我們需要就著色器進(jìn)行一些修改。具體修改內(nèi)容如下:
TextureShader.glsl
layout(location = 1) out vec2 v_TexCoord;
// 增加該用戶變量
uniform mat4 u_ViewProject;void main()
{gl_Position = u_ViewProject * position; v_TexCoord = texCoord;
};
Shader.h
//增加此函數(shù)
void UploadUniformat4(const std::string& name, glm::mat4& transform);
Shader.cpp
void Shader::UploadUniformat4(const std::string& name, glm::mat4& transform) {int location = glGetUniformLocation(m_ShaderID, name.c_str());glUniformMatrix4fv(location, 1, GL_FALSE, glm::value_ptr(transform));
}
使用正交投影陣
ImGui::Begin("ViewPort");
viewPortSize = ImGui::GetContentRegionAvail();
if (viewPortSize.x * viewPortSize.y > 0 && (viewPortSize.x != pFrameBuffer->GetWidth() || viewPortSize.y != pFrameBuffer->GetHeight())) {pFrameBuffer->Resize(viewPortSize.x, viewPortSize.y);glViewport(0, 0, viewPortSize.x, viewPortSize.y);glm::mat4 projection = glm::ortho(-viewPortSize.x/ viewPortSize.y, viewPortSize.x / viewPortSize.y, -1.0f, 1.0f);glm::mat4 view = glm::mat4(1.0f);glm::mat4 viewprojection = projection * view;pShader->UploadUniformat4("u_ViewProject", viewprojection);
}
可能有的朋友就還是不解,沒有投影矩陣,我們不是一樣能看到東西嗎,這個(gè)投影陣存在的意義是什么。如果還沒有使用投影陣的朋友可以去拖動(dòng)一下自己窗口,你的青蛙會(huì)更跟窗口一起變寬變窄。就像下面情況一樣
大家還記不記得,我們創(chuàng)建的青蛙長寬是一樣的,接近一個(gè)正方形才對(duì),我們?cè)谕蟿?dòng)窗口的時(shí)候,世界坐標(biāo)的單位長度發(fā)生了變換(但是坐標(biāo)對(duì)應(yīng)的數(shù)值不會(huì)改變),所以青蛙就會(huì)一會(huì)被拉長,一會(huì)又被壓扁,這種情況是不允許的,使用投影矩陣后就不會(huì)出現(xiàn)這樣的狀況。
使用變換矩陣
? ? ? ? 變換矩陣,就是讓青蛙移動(dòng)起來的關(guān)鍵,這次我們讓青蛙跟著我們的按鍵進(jìn)行左右移動(dòng),使用到的變換矩陣如下
glm::mat4 transform = glm::translate(glm::mat4(1.0f), glm::vec3(xPosition, yPosition, 0.0f))
* glm::rotate(glm::mat4(1.0f), glm::radians(rotateAngle), glm::vec3(0.0f, 1.0f, 0.0f))
* glm::scale(glm::mat4(1.0f), glm::vec3(0.5f, 0.5f, 0.5f));
第一個(gè)就是移動(dòng)矩陣,第二個(gè)圓轉(zhuǎn)矩陣(當(dāng)青蛙向左邊跑的時(shí)候,我們需要把青蛙轉(zhuǎn)個(gè)向),第三個(gè)就是縮放矩陣。這里我們要注意的是平移移動(dòng)要最后進(jìn)行,看前面的公式我們也知道,旋轉(zhuǎn),縮放操作都是相對(duì)于世界中心原點(diǎn)來進(jìn)行操作的,如果我先進(jìn)行平移的話,得到的就不是我們想要的結(jié)果了。至于為什么平移矩陣寫在第一個(gè)位置,我想我前說投影矩陣和觀察矩陣時(shí)應(yīng)該是給大家解釋過了這是為什么了。
具體使用代碼如下
glm::mat4 transform = glm::translate(glm::mat4(1.0f), glm::vec3(xPosition, yPosition, 0.0f))
* glm::rotate(glm::mat4(1.0f), glm::radians(rotateAngle), glm::vec3(0.0f, 1.0f, 0.0f))
* glm::scale(glm::mat4(1.0f), glm::vec3(0.5f, 0.5f, 0.5f));
//原模型各個(gè)頂點(diǎn)的坐標(biāo)
glm::vec4 p1 = glm::vec4(-0.5f, -0.5f, 0.0f,1.0f);
glm::vec4 p2 = glm::vec4(0.5f, -0.5f, 0.0f, 1.0f);
glm::vec4 p3 = glm::vec4(0.5f, 0.5f, 0.0f, 1.0f);
glm::vec4 p4 = glm::vec4(-0.5f, 0.5f, 0.0f,1.0f);p1 = transform * p1;
p2 = transform * p2;
p3 = transform * p3;
p4 = transform * p4;//寫入頂點(diǎn)緩沖區(qū)當(dāng)中,在對(duì)應(yīng)位置進(jìn)行繪制
positions[0] = p1.x, positions[1] = p1.y, positions[2] = p1.z, positions[3] = p1.w;
positions[6] = p2.x, positions[7] = p2.y, positions[8] = p2.z, positions[9] = p2.w;
positions[12] = p3.x, positions[13] = p3.y, positions[14] = p3.z, positions[15] = p3.w;
positions[18] = p4.x, positions[19] = p4.y, positions[20] = p4.z, positions[21] = p4.w;
好了結(jié)合前面的鍵盤輸入我們可以讓這只青蛙跑起來了
?還是老樣子,把主函數(shù)的代碼給大家帖在這里,希望能幫助到大家。這一片和以前都不一樣,非常的難,特別是數(shù)學(xué)這塊。但是想要做出一款好的游戲,數(shù)學(xué)就是避不開的話題,就算是使用成熟的游戲引擎,數(shù)學(xué)這一塊依然不能完全避免,希望大家能克服困難,做出自己心儀的好游戲。
#include<glad/glad.h>
#include<GLFW/glfw3.h>#include "imgui.h"
#include "imgui_impl_glfw.h"
#include "imgui_impl_opengl3.h"#include<iostream>
#include<glm/gtc/matrix_transform.hpp>#include"FrameBuffer.h"
#include"Shader.h"
#include"Texture.h"static int dirX = 0,dirY = 0;
static int moveDirect = 1;
static bool sameDirect = true;void InputProcess(GLFWwindow* window);int main() {glfwInit();GLFWwindow* window = glfwCreateWindow(640, 480, "Triangles", NULL, NULL);glfwMakeContextCurrent(window);glfwSwapInterval(1); // Enable vsync// Setup Dear ImGui contextIMGUI_CHECKVERSION();ImGui::CreateContext();ImGuiIO& io = ImGui::GetIO(); (void)io;io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controlsio.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad; // Enable Gamepad Controlsio.ConfigFlags |= ImGuiConfigFlags_DockingEnable; // Enable Dockingio.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable; // Enable Multi-Viewport / Platform Windows//io.ConfigViewportsNoAutoMerge = true;//io.ConfigViewportsNoTaskBarIcon = true;// Setup Dear ImGui styleImGui::StyleColorsDark();//ImGui::StyleColorsLight();// When viewports are enabled we tweak WindowRounding/WindowBg so platform windows can look identical to regular ones.ImGuiStyle& style = ImGui::GetStyle();if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable){style.WindowRounding = 0.0f;style.Colors[ImGuiCol_WindowBg].w = 1.0f;}// Setup Platform/Renderer backendsImGui_ImplGlfw_InitForOpenGL(window, true);ImGui_ImplOpenGL3_Init("#version 130");//需要初始化GLADif (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)) {std::cout << "Failed to initialize GLAD" << std::endl;return -1;}float positions[] = {-0.5f, -0.5f, 0.0f,1.0f, 0.0f,0.0f,0.5f, -0.5f, 0.0f,1.0f, 1.0f,0.0f,0.5f, 0.5f, 0.0f,1.0f, 1.0f,1.0f,-0.5f, 0.5f, 0.0f,1.0f, 0.0f,1.0f};unsigned int vertexIndex[] = {0,1,2,2,3,0};GLuint buffer = 0;GLuint indexBuffer = 0;glCreateBuffers(1, &buffer);glBindBuffer(GL_ARRAY_BUFFER, buffer);glBufferData(GL_ARRAY_BUFFER, sizeof(positions), positions, GL_STATIC_DRAW);glEnableVertexAttribArray(0);glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 6 * sizeof(float), NULL);glEnableVertexAttribArray(1);glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (const void*)(4*sizeof(float)));glCreateBuffers(1, &indexBuffer);glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer);glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(vertexIndex), vertexIndex, GL_STATIC_DRAW);bool show_demo_window = true;ImVec2 viewPortSize(640,480);float colorEditor[4] = {1.0f, 1.0f, 1.0f, 1.0f};FrameBuffer *pFrameBuffer = new FrameBuffer(640, 480);Texture *pTexture = new Texture("assets/Textures/Run.png");Shader* pShader = new Shader("assets/shaders/TextureShader.glsl");pShader->Bind();pShader->UploadUniform1i("u_Texture", 0);pShader->UBind();float textureWidth = pTexture->GetWidth();float unitActorWidth = 32.0f / textureWidth;int actorIndex = 0;float LastFrameTime = 0.0f;float moveSpeed = 0.015f;float stepTime = 0.0f, detalTime = 0.0f;float xPosition = 0.0f, yPosition = 0.0f;float rotateAngle = 0.0f;while (!glfwWindowShouldClose(window)) {float time = (float)glfwGetTime();detalTime = (time - stepTime) * 100.0f;stepTime = time;if (time - LastFrameTime > 0.05f) {LastFrameTime = time;actorIndex += 1;actorIndex = actorIndex % 11;}InputProcess(window);xPosition += dirX * moveSpeed * detalTime;yPosition += dirY * moveSpeed * detalTime;if (!sameDirect)rotateAngle += 180.0f;rotateAngle = rotateAngle == 360.0f ? 0.0f : rotateAngle;glm::mat4 transform = glm::translate(glm::mat4(1.0f), glm::vec3(xPosition, yPosition, 0.0f))*glm::rotate(glm::mat4(1.0f), glm::radians(rotateAngle), glm::vec3(0.0f, 1.0f, 0.0f)) * glm::scale(glm::mat4(1.0f), glm::vec3(0.5f, 0.5f, 0.5f));glm::vec4 p1 = glm::vec4(-0.5f, -0.5f, 0.0f,1.0f);glm::vec4 p2 = glm::vec4(0.5f, -0.5f, 0.0f, 1.0f);glm::vec4 p3 = glm::vec4(0.5f, 0.5f, 0.0f, 1.0f);glm::vec4 p4 = glm::vec4(-0.5f, 0.5f, 0.0f,1.0f);p1 = transform * p1;p2 = transform * p2;p3 = transform * p3;p4 = transform * p4;positions[0] = p1.x, positions[1] = p1.y, positions[2] = p1.z, positions[3] = p1.w;positions[6] = p2.x, positions[7] = p2.y, positions[8] = p2.z, positions[9] = p2.w;positions[12] = p3.x, positions[13] = p3.y, positions[14] = p3.z, positions[15] = p3.w;positions[18] = p4.x, positions[19] = p4.y, positions[20] = p4.z, positions[21] = p4.w;positions[4] = unitActorWidth * actorIndex;positions[10] = unitActorWidth * (actorIndex + 1);positions[16] = unitActorWidth * (actorIndex + 1);positions[22] = unitActorWidth * actorIndex;glBindBuffer(GL_ARRAY_BUFFER, buffer);glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(positions), positions);pShader->Bind();pFrameBuffer->Bind();pTexture->Bind(0);glClear(GL_COLOR_BUFFER_BIT);glDrawElements(GL_TRIANGLE_STRIP, 6, GL_UNSIGNED_INT, NULL);pFrameBuffer->UBind();// Start the Dear ImGui frameImGui_ImplOpenGL3_NewFrame();ImGui_ImplGlfw_NewFrame();ImGui::NewFrame();ImGui::DockSpaceOverViewport(0, ImGui::GetMainViewport());ImGui::Begin("ViewPort");viewPortSize = ImGui::GetContentRegionAvail();if (viewPortSize.x * viewPortSize.y > 0 && (viewPortSize.x != pFrameBuffer->GetWidth() || viewPortSize.y != pFrameBuffer->GetHeight())) {pFrameBuffer->Resize(viewPortSize.x, viewPortSize.y);glViewport(0, 0, viewPortSize.x, viewPortSize.y);glm::mat4 projection = glm::ortho(-viewPortSize.x/ viewPortSize.y, viewPortSize.x / viewPortSize.y, -1.0f, 1.0f);glm::mat4 view = glm::mat4(1.0f);glm::mat4 viewprojection = projection * view;pShader->UploadUniformat4("u_ViewProject", viewprojection);}uint32_t textureID = pFrameBuffer->GetColorAttachment();ImGui::Image(reinterpret_cast<void*>(textureID), viewPortSize, { 0,1 }, { 1,0 });ImGui::End();ImGui::Begin("ColorEditor");ImGui::ColorEdit4("##colorEditor", colorEditor);ImGui::End();/*if(show_demo_window)ImGui::ShowDemoWindow(&show_demo_window);*/// RenderingImGui::Render();ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable){GLFWwindow* backup_current_context = glfwGetCurrentContext();ImGui::UpdatePlatformWindows();ImGui::RenderPlatformWindowsDefault();glfwMakeContextCurrent(backup_current_context);}glfwSwapBuffers(window);glfwPollEvents();}// CleanupImGui_ImplOpenGL3_Shutdown();ImGui_ImplGlfw_Shutdown();ImGui::DestroyContext();delete pFrameBuffer;delete pShader;delete pTexture;glfwDestroyWindow(window);glfwTerminate();
}void InputProcess(GLFWwindow* window) {if (glfwGetKey(window, GLFW_KEY_W) == GLFW_PRESS)dirX = 0, dirY = 1;else if (glfwGetKey(window, GLFW_KEY_S) == GLFW_PRESS)dirX = 0, dirY = -1;else if (glfwGetKey(window, GLFW_KEY_A) == GLFW_PRESS)dirX = -1, dirY = 0;else if (glfwGetKey(window, GLFW_KEY_D) == GLFW_PRESS)dirX = 1, dirY = 0;elsedirX = 0, dirY = 0;sameDirect = dirX * moveDirect < 0 ? false : true;if (dirX != 0)moveDirect = dirX < 0 ? -1 : 1;elsemoveDirect = moveDirect;}