要实现旋转的操作就会用到旋转公式,这里先贴出2d平面内的旋转公式:
x' = x*cos(a) - y*sin(a);
y' = x*sin(a) + y*cos(a)
也就是 [x,y] *
这里只需要将a动态的传递给shader程序就行了
顶点着色器为:shader.vs
#version 330 core
layout(location = 0) in vec3 aPos;
layout(location = 1) in vec3 aColor;
out vec3 outputColor;
float tempx;
float tempy;
uniform float degree;
void main()
{
tempx = aPos.x*cos(radians(degree)) - aPos.y * sin(radians(degree));
tempy = aPos.x*sin(radians(degree)) + aPos.y * cos(radians(degree));
gl_Position = vec4(tempx,tempy,aPos.z,1.0f);
outputColor = aColor;
}
片段着色器:shader.fs
#version 330 core
in vec3 outputColor;
out vec4 fragColor;
uniform vec4 outcolor;
void main(){
fragColor = vec4(outputColor,1.0f);
}
其中degree这个变量就是程序传递到shader中的变量
main.cpp:
#include "shader.h"
#include <glad/glad.h>
#include <gl/GL.h>
#include <GLFW/glfw3.h>
#include <string>
#include <iostream>
typedef unsigned int uint;
using namespace std;
void framebuffer_size_callback(GLFWwindow* window, int width, int height);
void processInput(GLFWwindow *window);
GLFWwindow* showWindowSomething();
// template<class T, int N>
void renderTriangle(int shaderProgram, unsigned int VAO, unsigned int VBO, unsigned int EBO,uint verticesSizeof,uint indicesSizeof,float* elementVertices,uint* indices);
void drawSomgthing();
// settings
void renderTwoTriangle(unsigned int VAO, unsigned int VBO, float* vertices, uint verticesSizeof);
// 渲染带颜色值的顶点数组
void renderObjByMoreP(unsigned int VAO, unsigned int VBO, float* vertices, uint verticesSizeof);
int dealError(GLFWwindow* window);
const unsigned int SCR_WIDTH = 800;
const unsigned int SCR_HEIGHT = 600;
uint VAO, VBO;
float vertices[] = {
1.0f,0.0f,0.0f,1.0f,0.0f,0.0f,
-1.0f,0.0f,0.0f,0.0f,1.0f,0.0f,
0.0f,1.0f,0.0f,0.0f,0.0f,1.0f
};
int main()
{
//gladLoadGLLoader();
// 设置线框模式
// glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
GLFWwindow* window = showWindowSomething();
// 初始化glload
dealError(window);
Shader shaderItem = Shader("shader.vs","shader.fs");
shaderItem.use();
glGenVertexArrays(1, &VAO);
glGenBuffers(1, &VBO);
renderObjByMoreP(VAO,VBO,vertices,sizeof(vertices));
// render loop
// -----------
while (!glfwWindowShouldClose(window))
{
// input
// -----
processInput(window);
double curTime = glfwGetTime();
shaderItem.setFloat("degree",curTime);
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
// draw
drawSomgthing();
// -------------------------------------------------------------------------------
glfwSwapBuffers(window);
glfwPollEvents();
}
glDeleteProgram(shaderItem.ID);
glDeleteBuffers(1,&VBO);
glDeleteVertexArrays(1,&VAO);
// glfw: terminate, clearing all previously allocated GLFW resources.
// 回收占用的内存
// ------------------------------------------------------------------
glfwTerminate();
return 0;
}
void drawSomgthing() {
glBindVertexArray(VAO);
glDrawArrays(GL_TRIANGLES,0,3);
}
int dealError(GLFWwindow* window) {
if (window == NULL)
{
std::cout << "Failed to create GLFW window" << std::endl;
glfwTerminate();
return -1;
}
glfwMakeContextCurrent(window);
glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);
// glad: load all OpenGL function pointers
// ---------------------------------------
if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
{
std::cout << "Failed to initialize GLAD" << std::endl;
return -1;
}
}
// 渲染具体的物体对象方法
/**
绘制三角形对象
*/
void renderTriangle(int shaderProgram, unsigned int VAO, unsigned int VBO, unsigned int EBO, uint verticesSizeof, uint indicesSizeof, float* elementVertices, uint* indices)
{
cout << "顶点数组的sizeof is " << verticesSizeof << endl;
// 定义顶点缓冲对象 GL_ARRAY_BUFFER
glBindVertexArray(VAO);
// 绑定缓冲对象 修改opengl状态机从此以后任何的缓冲调用都会来配置当前绑定的缓冲
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, verticesSizeof, elementVertices, GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, indicesSizeof, indices, GL_STATIC_DRAW);
// 配置顶点属性指针
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void *)0);
glEnableVertexAttribArray(0);
// 链接都对象后删除着色器对象我们不在需要了
// 数据已经送往了GPU内存中了可以解绑了
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
}
//渲染两个相连的三角形
void renderTwoTriangle(unsigned int VAO,unsigned int VBO,float* vertices,uint verticesSizeof) {
glBindVertexArray(VAO);
glBindBuffer(GL_ARRAY_BUFFER,VBO);
glBufferData(GL_ARRAY_BUFFER,verticesSizeof,vertices,GL_STATIC_DRAW);
// 配置顶点属性指针
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void *)0);
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
}
/**
测试在顶点数组中加入更多的属性比如颜色值信息
*/
void renderObjByMoreP(unsigned int VAO,unsigned int VBO,float* vertices,uint verticesSizeof) {
glBindVertexArray(VAO);
glBindBuffer(GL_ARRAY_BUFFER,VBO);
glBufferData(GL_ARRAY_BUFFER, verticesSizeof, vertices, GL_STATIC_DRAW);
// 配置顶点属性指针 位置属性
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void *)0);
glEnableVertexAttribArray(0);
// 颜色属性
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void *)(3 * sizeof(float)));
glEnableVertexAttribArray(1);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
}
GLFWwindow* showWindowSomething() {
// glfw: initialize and configure
// ------------------------------
glfwInit();
// glfwInit();
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
#ifdef __APPLE__
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); // uncomment this statement to fix compilation on OS X
#endif
// glfw window creation
// --------------------
GLFWwindow* window = glfwCreateWindow(SCR_WIDTH, SCR_HEIGHT, "OpenGL_GAME", NULL, NULL);
return window;
}
// process all input: query GLFW whether relevant keys are pressed/released this frame and react accordingly
// ---------------------------------------------------------------------------------------------------------
void processInput(GLFWwindow *window)
{
if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
glfwSetWindowShouldClose(window, true);
}
// glfw: whenever the window size changed (by OS or user resize) this callback function executes
// ---------------------------------------------------------------------------------------------
void framebuffer_size_callback(GLFWwindow* window, int width, int height)
{
// make sure the viewport matches the new window dimensions; note that width and
// height will be significantly larger than specified on retina displays.
cout << "width is " << width << "height is " << height << endl;
glViewport(0, 0, width, height);
}
shader.h:
#ifndef SHADER_H
#define SHADER_H
#include <string>
using namespace std;
class Shader
{
public:
unsigned int ID;
// constructor generates the shader on the fly
// ------------------------------------------------------------------------
Shader(const char* vertexPath, const char* fragmentPath);
// activate the shader
// ------------------------------------------------------------------------
void use();
// utility uniform functions
// -----------------------------------------------------
void setBool(const string &name, bool value) const;
void setInt(const string &name, int value) const;
void setFloat(const string &name, float value) const;
private:
// utility function for checking shader compilation/linking errors.
// ------------------------------------------------------------------------
void checkCompileErrors(unsigned int shader, string type);
};
#endif
shader.cpp:
#include "shader.h"
#include <glad/glad.h>
#include <gl/GL.h>
#include <GLFW/glfw3.h>
#include <climits>
#include <string>
#include <fstream>
#include <sstream>
#include <iostream>
using namespace std;
Shader::Shader(const char* vertexPath,const char* fragmentPath) {
// 1. retrieve the vertex/fragment source code from filePath
std::string vertexCode;
std::string fragmentCode;
std::ifstream vShaderFile;
std::ifstream fShaderFile;
// ensure ifstream objects can throw exceptions:
vShaderFile.exceptions(std::ifstream::failbit | std::ifstream::badbit);
fShaderFile.exceptions(std::ifstream::failbit | std::ifstream::badbit);
try
{
// open files
vShaderFile.open(vertexPath);
fShaderFile.open(fragmentPath);
std::stringstream vShaderStream, fShaderStream;
// read file's buffer contents into streams
vShaderStream << vShaderFile.rdbuf();
fShaderStream << fShaderFile.rdbuf();
// close file handlers
vShaderFile.close();
fShaderFile.close();
// convert stream into string
vertexCode = vShaderStream.str();
fragmentCode = fShaderStream.str();
}
catch (std::ifstream::failure e)
{
std::cout << "ERROR::SHADER::FILE_NOT_SUCCESFULLY_READ" << std::endl;
}
const char* vShaderCode = vertexCode.c_str();
const char * fShaderCode = fragmentCode.c_str();
// 2. compile shaders
unsigned int vertex, fragment;
cout << UINT64_MAX << endl;
cout << glUseProgram << endl;
cout << glCreateShader << endl;
// vertex shader
vertex = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertex, 1, &vShaderCode, NULL);
glCompileShader(vertex);
checkCompileErrors(vertex, "VERTEX");
// fragment Shader
fragment = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragment, 1, &fShaderCode, NULL);
glCompileShader(fragment);
checkCompileErrors(fragment, "FRAGMENT");
// shader Program
ID = glCreateProgram();
glAttachShader(ID, vertex);
glAttachShader(ID, fragment);
glLinkProgram(ID);
checkCompileErrors(ID, "PROGRAM");
// delete the shaders as they're linked into our program now and no longer necessary
glDeleteShader(vertex);
glDeleteShader(fragment);
}
void Shader::use() {
glUseProgram(ID);
}
void Shader::setBool(const string &name, bool value) const
{
//glUniform
glUniform1i(glGetUniformLocation(ID, name.c_str()), (int)value);
}
void Shader::setInt(const string &name, int value) const
{
glUniform1i(glGetUniformLocation(ID, name.c_str()), value);
}
void Shader::setFloat(const string &name, float value) const
{
glUniform1f(glGetUniformLocation(ID, name.c_str()), value);
}
void Shader::checkCompileErrors(unsigned int shader,string type)
{
int success;
char infoLog[1024];
if (type != "PROGRAM")
{
glGetShaderiv(shader, GL_COMPILE_STATUS, &success);
if (!success)
{
glGetShaderInfoLog(shader, 1024, NULL, infoLog);
std::cout << "ERROR::SHADER_COMPILATION_ERROR of type: " << type << "\n" << infoLog << "\n -- --------------------------------------------------- -- " << std::endl;
}
}
else
{
glGetProgramiv(shader, GL_LINK_STATUS, &success);
if (!success)
{
glGetProgramInfoLog(shader, 1024, NULL, infoLog);
std::cout << "ERROR::PROGRAM_LINKING_ERROR of type: " << type << "\n" << infoLog << "\n -- --------------------------------------------------- -- " << std::endl;
}
}
}