这类似于this question,但我有一个2D三角形,我试图只绕z轴旋转,所以我认为我不需要做任何负旋转。我特意选择了一个以屏幕中心为中心的三角形(我用this webpage计算了质心)。基本上,我希望它看起来像是三角形围绕窗口中心顺时针或逆时针旋转,但通过改变我定义顶点的顺序,我发现它似乎是围绕我定义的最后一个顶点旋转的。
以下是我的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);
}
1条答案
按热度按时间dtcbnfnu1#
必须在顶点着色器中变换顶点坐标。见LearnOpenGL - Transformations(页面底部)
使用类型为
mat4
的统一变量并变换顶点着色器中的顶点:安装程序后设置矩阵:
每一帧都需要增加变量
angle
。例如:angle = 0.1f;