[英]OpenGL GLM rotate 2D shape around Z-axis
這類似於這個問題,但我有一個 2D 三角形,我試圖僅圍繞 z 軸旋轉,所以我認為我不必做任何負旋轉。 我故意選擇了一個以屏幕中心為中心的三角形(我用這個網頁計算了質心)。 本質上,我希望它看起來像三角形圍繞 window 的中心順時針或逆時針旋轉,但是通過改變我定義頂點的順序,我發現它似乎圍繞着最后一個頂點旋轉定義。
這是我的 C++ 代碼; 為簡潔起見,我刪除了評論。 我目前沒有任何輸入處理——我在 vscode 中運行,所以我一直通過 IDE 終止它。
// Third-party library
#include <SDL2/SDL.h>
// Include GLAD
#include <glad/glad.h>
#include <glm/vec3.hpp>
#include <glm/mat3x3.hpp>
#include <glm/mat4x4.hpp>
#include <glm/ext/matrix_transform.hpp>
#include <glm/gtx/string_cast.hpp>
// C++ Standard Libraries
#include <iostream>
#include <fstream>
#include <vector>
#include <string>
// Screen dimensions
int gScreenHeight = 480;
int gScreenWidth = 640;
SDL_Window* gGraphicsApplicationWindow = nullptr;
SDL_GLContext gOpenGLContext = nullptr;
// Main loop flag
bool gQuit = false; // if true, we quit
GLuint gGraphicsPipelineShaderProgram = 0;
GLuint gVertexArrayObject = 0;
GLuint gVertexBufferObject = 0;
GLuint gVertexBufferObject2 = 0;
glm::mat4 gVertexData(
-0.4f, -0.4f, 0.0f, 0.0f, // point 1 - bottom left
0.4f, -0.4f, 0.0f, 0.0f, // point 2 - bottom right
0.0f, 0.8f, 0.0f, 0.0f, // point 3 - top
0.0f, 0.0f, 0.0f, 1.0f // 4th dimension
);
const auto gVertexBytes = gVertexData.length() * gVertexData[0].length()
* sizeof(gVertexData[0][0]);
std::string loadShaderAsString(const std::string& filename) {
std::string result = "";
std::string line = "";
std::ifstream myFile(filename);
if (myFile.is_open()) {
while (std::getline(myFile, line)) {
result += line + '\n';
}
myFile.close();
}
return result;
}
GLuint compileShader(GLuint type, const std::string& source) {
GLuint shaderObject;
if (type == GL_VERTEX_SHADER) {
shaderObject = glCreateShader(GL_VERTEX_SHADER);
} else if (type == GL_FRAGMENT_SHADER) {
shaderObject = glCreateShader(GL_FRAGMENT_SHADER);
}
const char* src = source.c_str();
glShaderSource(shaderObject, 1, &src, nullptr);
glCompileShader(shaderObject);
int result;
glGetShaderiv(shaderObject, GL_COMPILE_STATUS, &result);
if (result == GL_FALSE) {
int length;
glGetShaderiv(shaderObject, GL_INFO_LOG_LENGTH, &length);
char* errorMessages = new char[length]; // Could also use alloca here.
glGetShaderInfoLog(shaderObject, length, &length, errorMessages);
if (type == GL_VERTEX_SHADER) {
std::cout << "ERROR: GL_VERTEX_SHADER compilation failed!\n"
<< errorMessages << "\n";
} else if (type == GL_FRAGMENT_SHADER) {
std::cout << "ERROR: GL_FRAGMENT_SHADER compilation failed!\n"
<< errorMessages << "\n";
}
delete[] errorMessages;
glDeleteShader(shaderObject);
return 0;
}
return shaderObject;
}
GLuint createShaderProgram(const std::string& vertexShaderSource,
const std::string& fragmentShaderSource) {
GLuint programObject = glCreateProgram();
GLuint myVertexShader = compileShader(GL_VERTEX_SHADER, vertexShaderSource);
GLuint myFragmentShader = compileShader(GL_FRAGMENT_SHADER, fragmentShaderSource);
glAttachShader(programObject, myVertexShader);
glAttachShader(programObject, myFragmentShader);
glLinkProgram(programObject);
glValidateProgram(programObject);
glDetachShader(programObject, myVertexShader);
glDetachShader(programObject, myFragmentShader);
glDeleteShader(myVertexShader);
glDeleteShader(myFragmentShader);
return programObject;
}
void createGraphicsPipeline() {
std::string vertexShaderSource = loadShaderAsString("../shaders/vert.glsl");
std::string fragmentShaderSource = loadShaderAsString("../shaders/frag.glsl");
gGraphicsPipelineShaderProgram = createShaderProgram(vertexShaderSource,
fragmentShaderSource);
}
void getOpenGLVersionInfo() {
std::cout << "Vendor: " << glGetString(GL_VENDOR) << std::endl;
std::cout << "Renderer: " << glGetString(GL_RENDERER) << std::endl;
std::cout << "Version: " << glGetString(GL_VERSION) << std::endl;
std::cout << "Shading Language: " << glGetString(GL_SHADING_LANGUAGE_VERSION) << std::endl;
}
void vertexSpecification() {
const std::vector<GLfloat> vertexColors {
1.0f, 0.0f, 0.0f, // vertex 1 - Left
0.0f, 1.0f, 0.0f, // vertex 2 - Right
0.0f, 0.0f, 1.0f // vertex 3 - Top
};
glGenVertexArrays(1, &gVertexArrayObject);
glBindVertexArray(gVertexArrayObject);
glGenBuffers(1, &gVertexBufferObject);
glBindBuffer(GL_ARRAY_BUFFER, gVertexBufferObject);
glBufferData(GL_ARRAY_BUFFER,
gVertexBytes,
&gVertexData[0][0],
GL_DYNAMIC_DRAW);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0,
gVertexData[0].length(),
GL_FLOAT,
GL_FALSE,
0,
nullptr);
glGenBuffers(1, &gVertexBufferObject2);
glBindBuffer(GL_ARRAY_BUFFER, gVertexBufferObject2);
glBufferData(GL_ARRAY_BUFFER,
vertexColors.size() * sizeof(GL_FLOAT),
vertexColors.data(),
GL_STATIC_DRAW);
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 3, GL_FLOAT,
GL_FALSE, 0, nullptr);
glBindVertexArray(0);
glDisableVertexAttribArray(0);
glDisableVertexAttribArray(1);
}
void initializeProgram() {
if (SDL_Init(SDL_INIT_VIDEO) < 0) {
std::cout << "SDL could not be initialized: " <<
SDL_GetError();
exit(1);
}
std::cout << "SDL video system is ready to go\n";
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 4);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 1);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);
gGraphicsApplicationWindow = SDL_CreateWindow("C++ SDL2 Window",
SDL_WINDOWPOS_UNDEFINED,
SDL_WINDOWPOS_UNDEFINED,
gScreenWidth,
gScreenHeight,
SDL_WINDOW_OPENGL);
if (gGraphicsApplicationWindow == nullptr) {
std::cout << "SDL WIndow was not able to be created" << std::endl;
exit(1);
}
gOpenGLContext = SDL_GL_CreateContext(gGraphicsApplicationWindow);
if (gOpenGLContext == nullptr) {
std::cout << "OpenGL context not available" << std::endl;
exit(1);
}
if (!gladLoadGLLoader(SDL_GL_GetProcAddress)) {
std::cout << "Glad was not initialized" << std::endl;
exit(1);
}
getOpenGLVersionInfo();
}
void predraw() {
static glm::vec3 zNorm(0.0f, 0.0f, 1.0f);
gVertexData = glm::rotate(gVertexData, glm::radians(0.10f), zNorm);
glBindBuffer(GL_ARRAY_BUFFER, gVertexBufferObject);
glBufferData(GL_ARRAY_BUFFER,
gVertexBytes,
&gVertexData[0][0],
GL_DYNAMIC_DRAW);
glDisable(GL_DEPTH_TEST);
glDisable(GL_CULL_FACE);
glViewport(0, 0, gScreenWidth, gScreenHeight);
glClearColor(1.0f, 1.0f, 0.0f, 1.0f);
glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
glUseProgram(gGraphicsPipelineShaderProgram);
}
void draw() {
glBindVertexArray(gVertexArrayObject);
glBindBuffer(GL_ARRAY_BUFFER, gVertexBufferObject);
glDrawArrays(GL_TRIANGLES, 0, 3);
glUseProgram(0);
}
void mainLoop() {
while (!gQuit) {
predraw();
draw();
SDL_GL_SwapWindow(gGraphicsApplicationWindow);
}
}
void cleanup() {
SDL_DestroyWindow(gGraphicsApplicationWindow);
SDL_Quit();
}
int main(int argc, char* argv[]) {
initializeProgram();
vertexSpecification();
createGraphicsPipeline();
mainLoop();
cleanup();
return 0;
}
這是頂點着色器代碼:
#version 410 core
layout(location=0) in vec4 position;
layout(location=1) in vec3 vertexColors;
out vec3 v_vertexColors;
void main()
{
v_vertexColors = vertexColors;
gl_Position = vec4(position.x, position.y, position.z, 1.0f);
}
和片段着色器:
#version 410 core
in vec3 v_vertexColors;
out vec4 color;
void main()
{
color = vec4(v_vertexColors.r, v_vertexColors.g, v_vertexColors.b, 1.0f);
}
您必須在頂點着色器中轉換頂點坐標。 請參閱LearnOpenGL - 轉換(頁面底部)
使用mat4
類型的統一變量並在頂點着色器中變換頂點:
#version 410 core
layout(location=0) in vec4 position;
layout(location=1) in vec3 vertexColors;
out vec3 v_vertexColors;
uniform mat4 model_matrix;
void main()
{
v_vertexColors = vertexColors;
gl_Position = model_matrix * vec4(position.xyz, 1.0f);
}
安裝程序后設置矩陣:
int model_loc = glGetUniformLocation(gGraphicsPipelineShaderProgram, "model_matrix")
glm::mat4 rotation_matrix(1.0f);
rotation_matrix = glm::rotate(rotation_matrix, glm::radians(angle), zNorm);
glUseProgram(gGraphicsPipelineShaderProgram);
glUniformMatrix4fv(model_loc, 1, false, glm::value_ptr(rotation_matrix));
可變angle
需要在每一幀中增加。 例如: angle = 0.1f;
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.