OpenGL GLM围绕Z轴旋转2D形状



这与这个问题类似,但我有一个2D三角形,我试图只绕z轴旋转,所以我认为我不必做任何负旋转。我有意选择了一个以屏幕中心为中心的三角形(我用这个网页计算了质心(。从本质上讲,我希望三角形看起来像是围绕窗口中心顺时针或逆时针旋转,但通过改变我定义顶点的顺序,我发现它似乎是围绕我定义的最后一个顶点旋转。

这是我的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 gon";
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));

需要在每一帧中增加变量CCD_ 2。例如:angle = 0.1f;

最新更新