Recently, I was looking at graphics programming. It is a bit simple. The exercise is to realize a two-dimensional triangle rotation.
//main.cpp
//
#include<GL/glew.h>
#include<GLFW/glfw3.h>
#include<iostream>
#include<string>
#include"Utils.h"
#include<glm/gtx/string_cast.hpp>
#include<vector>
using namespace std;
using namespace glm;
#define numVAOs 1
GLuint renderingProgram;
GLuint vao[numVAOs];
float x = 0.0f;
float inc = 0.01f;
float scaleRatio = 1.0f;
float scaleRate = 0.05f;
vector<glm::vec4> vecTrianglesVertex;
GLfloat* vecrawTrianglesVertex;
GLuint createShaderProgram() {
GLuint vShader = LoadShaderSource(GL_VERTEX_SHADER, "./shader/vshader.shader", 1);
GLuint fShader = LoadShaderSource(GL_FRAGMENT_SHADER, "./shader/fshader.shader", 1);
GLuint vfProgram = glCreateProgram();
glAttachShader(vfProgram, vShader);
glAttachShader(vfProgram, fShader);
glLinkProgram(vfProgram);
ProgramErrorCheck(vfProgram);
return vfProgram;
}
void init(GLFWwindow* window) {
renderingProgram = createShaderProgram();
glGenVertexArrays(numVAOs, vao);
glBindVertexArray(vao[0]);
}
void InitVertexData() {
vecTrianglesVertex.emplace_back(vec4(0.0, 0.25, 0.0, 1.0));
vecTrianglesVertex.emplace_back(vec4(0.25, 0.0, 0.0, 1.0));
vecTrianglesVertex.emplace_back(vec4(-0.25, 0.0, 0.0, 1.0));
vecrawTrianglesVertex = new GLfloat[3 * 4];
for (int i = 0, vecIndex = 0; i < 12; ++i) {
*(vecrawTrianglesVertex + i) = vecTrianglesVertex[i / 4][i % 4];
}
}
void display(GLFWwindow* window, double currentTime) {
using namespace glm;
auto rotate = [](vector<glm::vec4>& vecTrianglesVertex, float rad) {
for (auto v = vecTrianglesVertex.begin(); v != vecTrianglesVertex.end(); ++v) {
*v = buildRotateMat(rad, RotateAxis::Z) * (*v);
}
};
auto scale = [](vector<glm::vec4>& vecTrianglesVertex, float scaleX, float scaleY, float scaleZ) {
for (auto v = vecTrianglesVertex.begin(); v != vecTrianglesVertex.end(); ++v) {
*v = buildScaleMat(scaleX, scaleY, scaleZ) * (*v);
}
};
glClear(GL_DEPTH_BUFFER_BIT);
glClearColor(0.0, 0.0, 0.0, 1);
glClear(GL_COLOR_BUFFER_BIT);
glUseProgram(renderingProgram);
//旋转
rotate(vecTrianglesVertex, 0.1);
for (int i = 0, vecIndex = 0; i < 12; ++i) {
*(vecrawTrianglesVertex + i) = vecTrianglesVertex[i / 4][i%4];
}
GLuint vertexsLoc = glGetUniformLocation(renderingProgram, "vertexs");
glProgramUniform4fv(renderingProgram,vertexsLoc,3, vecrawTrianglesVertex);
glDrawArrays(GL_TRIANGLES, 0, 3);
}
int main() {
if (!glfwInit()) exit(EXIT_FAILURE);
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
GLFWwindow* windows = glfwCreateWindow(400, 400, "Chapter2", NULL, NULL);
glfwMakeContextCurrent(windows);
if (glewInit() != GLEW_OK)
exit(EXIT_FAILURE);
glfwSwapInterval(1);
init(windows);
InitVertexData();
while (!glfwWindowShouldClose(windows)) {
display(windows, glfwGetTime());
glfwSwapBuffers(windows);
glfwPollEvents();
}
glfwDestroyWindow(windows);
glfwTerminate();
}
shader file
//fshader.shader
#version 430
out vec4 color;
void main(void){
//if (gl_FragCoord.x < 200)
// color = vec4(1.0, 0.0, 0.0, 1.0);
//else
color = vec4(0.0, 0.0, 1.0, 1.0);
}
//vshader.shader
#version 430
//uniform float offset;
//uniform float scaleOffset;
uniform vec4 vertexs[3];
void main(void){
if (gl_VertexID == 0)
gl_Position = vertexs[0];
else if(gl_VertexID == 1)
gl_Position = vertexs[1];
else if (gl_VertexID == 2)
gl_Position = vertexs[2];
}
Self-encapsulated tools
//Utils.h
//简单封装一些工具
#pragma once
#ifndef __TESTOPENGL__
#define __TESTOPENGL__
#include<GL/glew.h>
#include<GLFW/glfw3.h>
#include<string>
#include<iostream>
#include<fstream>
#include<assert.h>
#include<type_traits>
#include<glm/glm.hpp>
enum class RotateAxis {
X = 0,
Y = 1,
Z = 2,
};
std::string ReadGLSL(std::string filePath);
void ProgramErrorCheck(GLint program);
GLuint LoadShaderSource(GLuint flag, std::string shaderSourcePath, GLsizei count); //加载shader文件
glm::mat4 buildTranslateMat(float x, float y, float z);
glm::mat4 buildRotateMat(float rad, RotateAxis axis);
glm::mat4 buildScaleMat(float x, float y, float z);
#endif // !__AUXFUN__
//Utils.cpp
#include"Utils.h"
std::string ReadGLSL(std::string filePath) {
std::ifstream fileStream(filePath.c_str());
assert(fileStream);
return std::string(std::istreambuf_iterator<char>(fileStream), std::istreambuf_iterator<char>());
}
void ProgramErrorCheck(GLint program) {
GLint logLength = 0;
glGetShaderiv(program, GL_INFO_LOG_LENGTH, &logLength);
if (logLength <= 0) return;
std::string errorlog(logLength, '\0');
glGetProgramInfoLog(program, logLength, nullptr, errorlog.data());
std::cerr << errorlog << std::endl;
}
GLuint LoadShaderSource(GLuint flag, std::string shaderSourcePath, GLsizei count) {
auto PrintErrorLog = [](GLuint shader, std::string fileName = "") {
GLint logLength = 0;
glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &logLength);
if (logLength <= 0) return;
std::string errorlog(logLength, '\0');
glGetShaderInfoLog(shader, logLength, nullptr, errorlog.data());
std::cerr << fileName << ": " << errorlog << std::endl;
};
std::string shaderSource = ReadGLSL(shaderSourcePath);
const char* c_strShaderSource = shaderSource.c_str();
GLuint shader = glCreateShader(flag);
glShaderSource(shader, count, &c_strShaderSource, NULL);
glCompileShader(shader);
PrintErrorLog(shader, shaderSourcePath);
return shader;
}
glm::mat4 buildTranslateMat(float x, float y, float z) {
using namespace glm;
return mat4(1.0, 0.0, 0.0, 0.0,
0.0, 1.0, 0.0, 0.0,
0.0, 0.0, 1.0, 0.0,
x, y, z, 1.0
);
}
glm::mat4 buildRotateMat(float rad, RotateAxis axis) {
using namespace glm;
constexpr auto f0 = 0.0;
constexpr auto f1 = 1.0;
if (axis == RotateAxis::X) {
return mat4(f1, f0, f0, f0,
f0, cos(rad), -sin(rad), f0,
f0, sin(rad), cos(rad), f0,
f0, f0, f0, f1
);
}
else if (axis == RotateAxis::Y) {
return mat4(cos(rad), f0,sin(rad), f0,
f0, f1, f0, f0,
-sin(rad), f0, cos(rad), f0,
f0, f0, f0, f1
);
}
else if (axis == RotateAxis::Z) {
return mat4(
cos(rad), -sin(rad), f0, f0,
sin(rad), cos(rad), f0, f0,
f0, f0, f1, f0,
f0, f0, f0, f1
);
}
else {
assert(-1 && "undefine RotateAxis");
}
}
glm::mat4 buildScaleMat(float x, float y, float z) {
using namespace glm;
constexpr auto f0 = 0.0;
constexpr auto f1 = 1.0;
return mat4(x, f0, f0, f0,
f0, y, f0, f0,
f0, f0, z, f0,
f0, f0, f0, f1
);
}