主页 - LearnOpenGL CN (learnopengl-cn.github.io)
效果图
上代码,其余函数为其他练习,忽略即可
#define STB_IMAGE_IMPLEMENTATION
#include <glad.h>
#include <GLFW/glfw3.h>
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
#include <shader_m.h>
#include <iostream>
#include <random>
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <vector>
void framebuffer_size_callback(GLFWwindow* window, int width, int height);
void processInput(GLFWwindow* window);
void mouse_callback(GLFWwindow* window, double xpos, double ypos);
void scroll_callback(GLFWwindow* window, double xoffset, double yoffset);
void mouse_click_callback(GLFWwindow* window, int button, int action, int mods);
void DoViewChange();
// settings
const unsigned int SCR_WIDTH = 800;
const unsigned int SCR_HEIGHT = 600;
glm::vec3 cameraFront = glm::vec3(-1, 0, 0);
glm::vec3 cameraUp = glm::vec3(0, 1, 0);
glm::vec3 cameraPos = glm::vec3(8, 2, 1);
float deltaTime;
float lastFrame;
float lastX = 400, lastY = 300;
float yaw = 0, pitch = 0;
bool firstMouse = true;
float fov = 45.0f;
float xoffset = 0.0f;
float yoffset = 0.0f;
bool mouseRightIsPress = false;
glm::vec3 lightPos(2.2f, 0.8f, 0.0f);
glm::vec3 doUp(0.0f, 0.001f, 0.0f);
glm::vec3 doDown(0.0f, -0.001f, 0.0f);
glm::vec3 doRight(0.001f, 0.0f, 0.0f);
glm::vec3 doLeft(-0.001f, 0.0f, 0.0f);
glm::vec3 testPos(lightPos);
void test()
{
glm::vec4 vec(1.0f, 0.0f, 0.0f, 1.0f);
glm::mat4 trans = glm::mat4(1.0f);
trans = glm::translate(trans, glm::vec3(1.0f, 1.0f, 0.0f));
vec = trans * vec;
std::cout << vec.x << vec.y << vec.z << std::endl;
}
glm::vec2 P0(-0.7f, -0.8f);
glm::vec2 P1(0.0f, 0.7f);
glm::vec2 P2(0.7f, -0.8f);
glm::vec2 Q0 = P0, Q1 = P1, Point = P0;
float timeTotal = 0;
int main()
{
// glfw: initialize and configure
// ------------------------------
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);
#endif
// glfw window creation
// --------------------
GLFWwindow* window = glfwCreateWindow(SCR_WIDTH, SCR_HEIGHT, "LearnOpenGL", NULL, NULL);
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;
}
const char* vertexSource = "#version 460 core\n"
"layout (location = 0) in vec2 pointFake;\n"
"uniform vec2 point;\n"
"void main()\n"
"{\n"
" gl_Position = vec4(pointFake.x, pointFake.y, 1.0, 1.0);\n"
"}\n\0";
const char* fragmentSource = "#version 460 core\n"
"out vec4 outColor;\n"
"void main()\n"
"{\n"
" outColor = vec4(0.0, 1.0, 1.0, 1.0);\n"
"}\n\0";
const char* vertexSource2 = "#version 460 core\n"
"layout (location = 0) in vec2 pointFake;\n"
"uniform vec2 point;\n"
"void main()\n"
"{\n"
" gl_Position = vec4(pointFake.x, pointFake.y, 1.0, 1.0);\n"
"}\n\0";
const char* fragmentSource2 = "#version 460 core\n"
"out vec4 outColor;\n"
"void main()\n"
"{\n"
" outColor = vec4(0.5, 0.5, 0.5, 1.0);\n"
"}\n\0";
unsigned int VBO, VAO;
glGenVertexArrays(1, &VAO);
glGenBuffers(1, &VBO);
glBindVertexArray(VAO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
Shader shader(SourceType::CODE, vertexSource, fragmentSource);
Shader shader2(SourceType::CODE, vertexSource2, fragmentSource2);
// render loop
// -----------
lastFrame = glfwGetTime();
float speed = 0.1f;
std::random_device rd;
std::mt19937 gen(rd());
std::uniform_int_distribution<> distrib(0, 1000);
while (!glfwWindowShouldClose(window))
{
float currentFrame = static_cast<float>(glfwGetTime());
deltaTime = currentFrame - lastFrame;
lastFrame = currentFrame;
//std::cout << deltaTime << std::endl;
//glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
//glClear(GL_COLOR_BUFFER_BIT);
if (timeTotal >= 0.99 || timeTotal <= 0.01)
{
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
}
processInput(window);
shader.use();
if (timeTotal < 1)
{
Q0 = glm::vec2(P0.x + (P1.x - P0.x) * timeTotal, P0.y + (P1.y - P0.y) * timeTotal);
Q1 = glm::vec2(P1.x + (P2.x - P1.x) * timeTotal, P1.y + (P2.y - P1.y) * timeTotal);
}
else
{
P0.x = (float)distrib(gen) / 1000;
P0.y = (float)distrib(gen) / 1000;
P1.x = (float)distrib(gen) / 1000;
P1.y = (float)distrib(gen) / 1000;
P2.x = (float)distrib(gen) / 1000;
P2.y = (float)distrib(gen) / 1000;
Q0 = P1;
Q1 = P2;
timeTotal = 0;
}
Point = glm::vec2(Q0.x + (Q1.x - Q0.x) * timeTotal, Q0.y + (Q1.y - Q0.y) * timeTotal);
shader.setVec2("point", Point);
timeTotal += deltaTime * speed;
float vertex[] = {
Point.x, Point.y,
(float)(Point.x+0.001), (float)(Point.y +0.001),
};
std::cout << "--------P0.x|" << P0.x << "--------P1.x|" << P1.x << "--------P2.x|" << P2.x << "-------Point.x|" << Point.x << "--------------|" << timeTotal << std::endl;
glBufferData(GL_ARRAY_BUFFER, sizeof(vertex), vertex, GL_STATIC_DRAW);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(float), (void*)0);
glEnableVertexAttribArray(0);
glLineWidth(0.7f);
glDrawArrays(GL_LINES, 0, 2);
float vertex2[] = {
P0.x, P0.y,
P1.x, P1.y,
P2.x, P2.y,
};
shader2.use();
glBufferData(GL_ARRAY_BUFFER, sizeof(vertex2), vertex2, GL_STATIC_DRAW);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(float), (void*)0);
glEnableVertexAttribArray(0);
glPointSize(10.0f);
glDrawArrays(GL_POINTS, 0, 3);
glfwSwapBuffers(window);
glfwPollEvents();
}
//glDeleteVertexArrays(1, &VAO);
//glDeleteBuffers(1, &VBO);
//glDeleteBuffers(1, &EBO);
glfwTerminate();
return 0;
}
void processInput(GLFWwindow* window)
{
float cameraSpeed = 0.001f;
if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
glfwSetWindowShouldClose(window, true);
}
void framebuffer_size_callback(GLFWwindow* window, int width, int height)
{
glViewport(0, 0, width, height);
}
void mouse_callback(GLFWwindow* window, double xpos, double ypos)
{
if (firstMouse)
{
lastX = xpos;
lastY = ypos;
firstMouse = false;
}
xoffset = xpos - lastX;
yoffset = ypos - lastY;
lastX = xpos;
lastY = ypos;
float sensitivity = 0.08f;
xoffset *= sensitivity;
yoffset *= sensitivity;
}
void mouse_click_callback(GLFWwindow* window, int button, int action, int mods)
{
if (button == GLFW_MOUSE_BUTTON_RIGHT) {
if (GLFW_PRESS == action) {
mouseRightIsPress = true;
xoffset = 0;
yoffset = 0;
}
else
mouseRightIsPress = false;
}
}
void DoViewChange()
{
if (mouseRightIsPress) {
yaw += xoffset;
pitch += yoffset;
if (pitch > 89.0f)
pitch = 89.0f;
if (pitch < -89.0f)
pitch = -89.0f;
glm::vec3 front;
front.x = -cos(glm::radians(yaw)) * cos(glm::radians(pitch));
front.y = -sin(glm::radians(pitch));
front.z = -sin(glm::radians(yaw)) * cos(glm::radians(pitch));
cameraFront = glm::normalize(front);
xoffset = 0.0f;
yoffset = 0.0f;
}
}
void scroll_callback(GLFWwindow* window, double xoffset, double yoffset)
{
if (fov >= 1.0f && fov <= 45.0f)
fov -= yoffset;
if (fov <= 1.0f)
fov = 1.0f;
if (fov >= 45.0f)
fov = 45.0f;
}
Shader类
#ifndef SHADER_H
#define SHADER_H
#include <glad.h>
#include <glm/glm.hpp>
#include <string>
#include <fstream>
#include <sstream>
#include <iostream>
enum SourceType
{
CODE = 0,
PATH = 1
};
class Shader
{
public:
unsigned int ID;
// constructor generates the shader on the fly
// ------------------------------------------------------------------------
Shader(SourceType type, const char* vertexPathOrCode, const char* fragmentPathOrCode)
{
const char* vShaderCode;
const char* fShaderCode;
if (type == PATH)
{
// 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(vertexPathOrCode);
fShaderFile.open(fragmentPathOrCode);
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_SUCCESSFULLY_READ: " << e.what() << std::endl;
}
vShaderCode = vertexCode.c_str();
fShaderCode = fragmentCode.c_str();
}
else if (type == CODE)
{
vShaderCode = vertexPathOrCode;
fShaderCode = fragmentPathOrCode;
}
// 2. compile shaders
unsigned int vertex, fragment;
// 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);
}
// activate the shader
// ------------------------------------------------------------------------
void use() const
{
glUseProgram(ID);
}
// utility uniform functions
// ------------------------------------------------------------------------
void setBool(const std::string& name, bool value) const
{
glUniform1i(glGetUniformLocation(ID, name.c_str()), (int)value);
}
// ------------------------------------------------------------------------
void setInt(const std::string& name, int value) const
{
glUniform1i(glGetUniformLocation(ID, name.c_str()), value);
}
// ------------------------------------------------------------------------
void setFloat(const std::string& name, float value) const
{
glUniform1f(glGetUniformLocation(ID, name.c_str()), value);
}
// ------------------------------------------------------------------------
void setVec2(const std::string& name, const glm::vec2& value) const
{
glUniform2fv(glGetUniformLocation(ID, name.c_str()), 1, &value[0]);
}
void setVec2(const std::string& name, float x, float y) const
{
glUniform2f(glGetUniformLocation(ID, name.c_str()), x, y);
}
// ------------------------------------------------------------------------
void setVec3(const std::string& name, const glm::vec3& value) const
{
glUniform3fv(glGetUniformLocation(ID, name.c_str()), 1, &value[0]);
}
void setVec3(const std::string& name, float x, float y, float z) const
{
glUniform3f(glGetUniformLocation(ID, name.c_str()), x, y, z);
}
// ------------------------------------------------------------------------
void setVec4(const std::string& name, const glm::vec4& value) const
{
glUniform4fv(glGetUniformLocation(ID, name.c_str()), 1, &value[0]);
}
void setVec4(const std::string& name, float x, float y, float z, float w) const
{
glUniform4f(glGetUniformLocation(ID, name.c_str()), x, y, z, w);
}
// ------------------------------------------------------------------------
void setMat2(const std::string& name, const glm::mat2& mat) const
{
glUniformMatrix2fv(glGetUniformLocation(ID, name.c_str()), 1, GL_FALSE, &mat[0][0]);
}
// ------------------------------------------------------------------------
void setMat3(const std::string& name, const glm::mat3& mat) const
{
glUniformMatrix3fv(glGetUniformLocation(ID, name.c_str()), 1, GL_FALSE, &mat[0][0]);
}
// ------------------------------------------------------------------------
void setMat4(const std::string& name, const glm::mat4& mat) const
{
glUniformMatrix4fv(glGetUniformLocation(ID, name.c_str()), 1, GL_FALSE, &mat[0][0]);
}
private:
// utility function for checking shader compilation/linking errors.
// ------------------------------------------------------------------------
void checkCompileErrors(GLuint shader, std::string type)
{
GLint success;
GLchar 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;
}
}
}
};
#endif