<repo_name>SunHailang/LeranOpenGL<file_sep>/LeranOpenGL/OpenGLAdvanced/src/Mesh.cpp
﻿#include "Mesh.h"
#include <iostream>

#include "GL/glew.h"
#include "GLFW/glfw3.h"

#include "ShaderProgram.h"
#include "GLDebug.h"

Mesh::Mesh(std::vector<Vertex> _vertices, std::vector<unsigned int> _indices, std::vector<Texture> _textures)
	:vertices(_vertices), indices(_indices), textures(_textures)
{
	SetupMesh();
}

Mesh::~Mesh()
{
	//GLCall(glDeleteVertexArrays(1, &VAO));
	//GLCall(glDeleteBuffers(1, &VBO));
	//GLCall(glDeleteBuffers(1, &EBO));
}


void Mesh::Draw(ShaderProgram *shaderProgram) const
{
	unsigned int textureIndex = 0;
	for (unsigned int i = 0; i < textures.size(); i++)
	{
		glActiveTexture(GL_TEXTURE0 + textureIndex); // 在绑定之前激活相应的纹理单元
		std::string name = textures.at(i).type.c_str();
		unsigned int id = textures.at(i).id;
		shaderProgram->SetUniform1i(name, textureIndex);
		textureIndex++;
		glBindTexture(GL_TEXTURE_2D, textures[i].id);
	}


	// 绘制网格
	glBindVertexArray(VAO);
	glDrawElements(GL_TRIANGLES, indices.size(), GL_UNSIGNED_INT, 0);
	glBindVertexArray(0);
}

void Mesh::SetupMesh()
{
	GLCall(glGenVertexArrays(1, &VAO));
	GLCall(glGenBuffers(1, &VBO));
	GLCall(glGenBuffers(1, &EBO));

	GLCall(glBindVertexArray(VAO));
	GLCall(glBindBuffer(GL_ARRAY_BUFFER, VBO));

	GLCall(glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(Vertex), &vertices[0], GL_STATIC_DRAW));

	GLCall(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO));
	GLCall(glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(unsigned int), &indices[0], GL_STATIC_DRAW));

	// 顶点位置
	GLCall(glEnableVertexAttribArray(0));
	GLCall(glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)0));
	// 顶点法线
	GLCall(glEnableVertexAttribArray(1));
	GLCall(glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)offsetof(Vertex, Normal)));
	// 顶点纹理坐标
	GLCall(glEnableVertexAttribArray(2));
	GLCall(glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)offsetof(Vertex, TexCoords)));

	GLCall(glBindVertexArray(0));
}

<file_sep>/LeranOpenGL/OpenGL/src/Application.cpp
﻿#include <GL\glew.h>
#include <GLFW\glfw3.h>

#include <iostream>

#include "Renderer.h"
#include "VertexBuffer.h"
#include "IndexBuffer.h"
#include "VertexArray.h"
#include "VertexBufferLayout.h"
#include "ShaderProgram.h"
#include "Texture.h"

#include "glm/glm.hpp"
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>

#include "imgui/imgui.h"
#include "imgui/imgui_impl_glfw.h"
#include "imgui/imgui_impl_opengl3.h"

#include "Camera.h"
#include "Time.h"


#define SCREEN_WIDTH 960
#define SCREEN_HEIGHT 540


void framebuffer_size_callback(GLFWwindow* window, int width, int height);
void mouse_callback(GLFWwindow* window, double xpos, double ypos);
void scroll_callback(GLFWwindow* window, double xoffset, double yoffset);
void processInput(GLFWwindow *window);

// camera
Camera camera(glm::vec3(0.0f, 0.0f, 3.0f));
float lastX = SCREEN_WIDTH / 2.0f;
float lastY = SCREEN_HEIGHT / 2.0f;
bool firstMouse = true;

// timing
float deltaTime = 0.0f;	// time between current frame and last frame
float lastFrame = 0.0f;


int main(void)
{
	GLFWwindow* window;

	if (!glfwInit())
		return -1;

	// GL 3.0 + GLSL 130
	const char* glsl_version = "#version 130";
	glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
	glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
	glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);


	window = glfwCreateWindow(SCREEN_WIDTH, SCREEN_HEIGHT, "Hello World", NULL, NULL);
	if (!window)
	{
		glfwTerminate();
		return -1;
	}

	glfwMakeContextCurrent(window);
	// Enable vsync
	glfwSwapInterval(1);

	glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);
	glfwSetCursorPosCallback(window, mouse_callback);
	glfwSetScrollCallback(window, scroll_callback);

	// tell GLFW to capture our mouse
	//glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);

	if (glewInit() != GLEW_OK)
	{
		std::cout << "glew init failed." << std::endl;
		glfwTerminate();
		return -1;
	}
	std::cout << "[OpenGL Version]: " << glfwGetVersionString() << std::endl;
	{
		float positions[] = {
			// positions          // normals           // texture coords
			-0.5f, -0.5f, -0.5f,  0.0f,  0.0f, -1.0f,  0.0f,  0.0f,
			0.5f, -0.5f, -0.5f,  0.0f,  0.0f, -1.0f,  1.0f,  0.0f,
			0.5f,  0.5f, -0.5f,  0.0f,  0.0f, -1.0f,  1.0f,  1.0f,
			0.5f,  0.5f, -0.5f,  0.0f,  0.0f, -1.0f,  1.0f,  1.0f,
			-0.5f,  0.5f, -0.5f,  0.0f,  0.0f, -1.0f,  0.0f,  1.0f,
			-0.5f, -0.5f, -0.5f,  0.0f,  0.0f, -1.0f,  0.0f,  0.0f,

			-0.5f, -0.5f,  0.5f,  0.0f,  0.0f,  1.0f,  0.0f,  0.0f,
			0.5f, -0.5f,  0.5f,  0.0f,  0.0f,  1.0f,  1.0f,  0.0f,
			0.5f,  0.5f,  0.5f,  0.0f,  0.0f,  1.0f,  1.0f,  1.0f,
			0.5f,  0.5f,  0.5f,  0.0f,  0.0f,  1.0f,  1.0f,  1.0f,
			-0.5f,  0.5f,  0.5f,  0.0f,  0.0f,  1.0f,  0.0f,  1.0f,
			-0.5f, -0.5f,  0.5f,  0.0f,  0.0f,  1.0f,  0.0f,  0.0f,

			-0.5f,  0.5f,  0.5f, -1.0f,  0.0f,  0.0f,  1.0f,  0.0f,
			-0.5f,  0.5f, -0.5f, -1.0f,  0.0f,  0.0f,  1.0f,  1.0f,
			-0.5f, -0.5f, -0.5f, -1.0f,  0.0f,  0.0f,  0.0f,  1.0f,
			-0.5f, -0.5f, -0.5f, -1.0f,  0.0f,  0.0f,  0.0f,  1.0f,
			-0.5f, -0.5f,  0.5f, -1.0f,  0.0f,  0.0f,  0.0f,  0.0f,
			-0.5f,  0.5f,  0.5f, -1.0f,  0.0f,  0.0f,  1.0f,  0.0f,

			0.5f,  0.5f,  0.5f,  1.0f,  0.0f,  0.0f,  1.0f,  0.0f,
			0.5f,  0.5f, -0.5f,  1.0f,  0.0f,  0.0f,  1.0f,  1.0f,
			0.5f, -0.5f, -0.5f,  1.0f,  0.0f,  0.0f,  0.0f,  1.0f,
			0.5f, -0.5f, -0.5f,  1.0f,  0.0f,  0.0f,  0.0f,  1.0f,
			0.5f, -0.5f,  0.5f,  1.0f,  0.0f,  0.0f,  0.0f,  0.0f,
			0.5f,  0.5f,  0.5f,  1.0f,  0.0f,  0.0f,  1.0f,  0.0f,

			-0.5f, -0.5f, -0.5f,  0.0f, -1.0f,  0.0f,  0.0f,  1.0f,
			0.5f, -0.5f, -0.5f,  0.0f, -1.0f,  0.0f,  1.0f,  1.0f,
			0.5f, -0.5f,  0.5f,  0.0f, -1.0f,  0.0f,  1.0f,  0.0f,
			0.5f, -0.5f,  0.5f,  0.0f, -1.0f,  0.0f,  1.0f,  0.0f,
			-0.5f, -0.5f,  0.5f,  0.0f, -1.0f,  0.0f,  0.0f,  0.0f,
			-0.5f, -0.5f, -0.5f,  0.0f, -1.0f,  0.0f,  0.0f,  1.0f,

			-0.5f,  0.5f, -0.5f,  0.0f,  1.0f,  0.0f,  0.0f,  1.0f,
			0.5f,  0.5f, -0.5f,  0.0f,  1.0f,  0.0f,  1.0f,  1.0f,
			0.5f,  0.5f,  0.5f,  0.0f,  1.0f,  0.0f,  1.0f,  0.0f,
			0.5f,  0.5f,  0.5f,  0.0f,  1.0f,  0.0f,  1.0f,  0.0f,
			-0.5f,  0.5f,  0.5f,  0.0f,  1.0f,  0.0f,  0.0f,  0.0f,
			-0.5f,  0.5f, -0.5f,  0.0f,  1.0f,  0.0f,  0.0f,  1.0f
		};

		// world space positions of our cubes
		glm::vec3 cubePositions[] = {
			glm::vec3(0.0f,  0.0f,  0.0f),
			glm::vec3(2.0f,  5.0f, -15.0f),
			glm::vec3(-1.5f, -2.2f, -2.5f),
			glm::vec3(-3.8f, -2.0f, -12.3f),
			glm::vec3(2.4f, -0.4f, -3.5f),
			glm::vec3(-1.7f,  3.0f, -7.5f),
			glm::vec3(1.3f, -2.0f, -2.5f),
			glm::vec3(1.5f,  2.0f, -2.5f),
			glm::vec3(1.5f,  0.2f, -1.5f),
			glm::vec3(-1.3f,  1.0f, -1.5f)
		};


		GLCall(glEnable(GL_BLEND));
		GLCall(glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA));
		GLCall(glEnable(GL_DEPTH_TEST));

		VertexArray va;
		VertexBuffer vb(positions, sizeof(positions));

		VertexBufferLayout layout;
		layout.Push<float>(3);
		layout.Push<float>(3);
		layout.Push<float>(2);
		va.AddBuffer(vb, layout);

		//IndexBuffer ib(indices, 0);

		VertexArray lightVAO;
		VertexBufferLayout lightLayout;
		lightLayout.Push<float>(3);
		lightLayout.Push<float>(3);
		lightLayout.Push<float>(2);
		lightVAO.AddBuffer(vb, lightLayout);
		lightVAO.Unbind();


		ShaderProgram program("res/shaders/Basic.shader");
		program.Bind();
		program.SetUniform4f("u_Color", 0.2f, 0.3f, 0.3f, 1.0f);

		//Texture texture("res/textures/log.png");
		//texture.Bind();	
		program.SetUniform1i("u_LightTexture", 0);



		//ShaderProgram lithtProgram("res/shaders/Light.shader");
		ShaderProgram lithtProgram("res/shaders/Material.shader");
		Texture tex("res/textures/container2.png");
		tex.Bind();
		lithtProgram.Bind();
		Texture tex1("res/textures/container2_specular.png");
		tex1.Bind();
		//lithtProgram.SetUniform1i("material.diffuse", 0);
		//lithtProgram.SetUniform1i("material.specular", 1);
		


		va.Unbind();
		vb.Unbind();
		//ib.Unbind();
		program.Unbind();
		lithtProgram.Unbind();

		Renderer renderer;

		ImGui::CreateContext();
		ImGuiIO& io = ImGui::GetIO(); (void)io;
		//io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard;     // Enable Keyboard Controls
		//io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad;      // Enable Gamepad Controls

		// Setup Dear ImGui style
		//ImGui::StyleColorsDark();
		ImGui::StyleColorsClassic();

		// Setup Platform/Renderer bindings
		ImGui_ImplGlfw_InitForOpenGL(window, true);
		ImGui_ImplOpenGL3_Init(glsl_version);


		float specularStr = 32.0f;
		glm::vec3 translation(0.0f, -0.5f, -4.0f);

		while (!glfwWindowShouldClose(window))
		{
			/* renderer here */
			renderer.Clear();

			float currentFrame = (float)glfwGetTime();
			deltaTime = currentFrame - lastFrame;
			lastFrame = currentFrame;


			processInput(window);


			// Start the Dear ImGui frame
			ImGui_ImplOpenGL3_NewFrame();
			ImGui_ImplGlfw_NewFrame();
			ImGui::NewFrame();

			program.Bind();

			//renderer.Draw(va, ib, program);

			// create transformations
			glm::mat4 model = glm::mat4(1.0f); // make sure to initialize matrix to identity matrix first
			glm::mat4 view = glm::mat4(1.0f);
			glm::mat4 projection = glm::mat4(1.0f);
			glm::vec3 lightPos(translation.x, translation.y, translation.z);
			model = glm::translate(model, lightPos);
			model = glm::scale(model, glm::vec3(0.3f));
			model = glm::rotate(model, glm::radians(-55.0f), glm::vec3(0.0f, 1.0f, 0.0f));
			//view = glm::translate(view, glm::vec3(0.0f, 0.0f, -3.0f));
			//view = glm::translate(view, translation);
			projection = glm::perspective(glm::radians(camera.Zoom), (float)SCREEN_WIDTH / (float)SCREEN_HEIGHT, 0.1f, 100.0f);
			//projection = glm::ortho(-1.0f, 1.0f, -1.0f, 1.0f, -1.0f, 1.0f);

			float radius = 20.0f;
			float camX = sin((float)glfwGetTime()) * radius;
			float camZ = cos((float)glfwGetTime()) * radius;
			view = camera.GetViewMatrix();
			//view = glm::lookAt(glm::vec3(camX, 0.0, camZ), glm::vec3(0.0, 0.0, 0.0), glm::vec3(0.0, 1.0, 0.0));

			//view = glm::translate(glm::mat4(1.0f), translation);
			glm::mat4 mvp = projection * view * model;
			program.SetUniformMat4f("u_MVP", mvp);

			va.Bind();
			glDrawArrays(GL_TRIANGLES, 0, 36);



			lithtProgram.Bind();
			lithtProgram.SetUniform3f("objectColor", 1.0f, 0.5f, 0.31f);
			lithtProgram.SetUniform3f("lightColor", 1.0f, 1.0f, 1.0f);
			glm::vec3 cubePos(0.2f, -2.5f, -3.0f);
			glm::mat4 lightmodel = glm::mat4(1.0f);
			//glm::mat4 lightprojection = glm::perspective(glm::radians(camera.Zoom), (float)SCREEN_WIDTH / (float)SCREEN_HEIGHT, 0.1f, 100.0f);
			lightmodel = glm::translate(lightmodel, cubePos);
			lightmodel = glm::scale(lightmodel, glm::vec3(3.0f));
			//lightmodel = glm::rotate(lightmodel, glm::radians(-30.0f), glm::vec3(0.0f, 1.0f, 0.0f));
			//glm::mat4 lightMVP = projection * view * lightmodel;


			lithtProgram.SetUniformMat4f("projection", projection);
			lithtProgram.SetUniformMat4f("view", view);
			lithtProgram.SetUniformMat4f("model", lightmodel);

			lithtProgram.SetUniform3f("lightPos", lightPos);
			lithtProgram.SetUniform3f("viewPos", camera.Position);

			glm::vec3 lightColor(1.0f);
			//lightColor.x = sin(glfwGetTime() * 2.0f);
			//lightColor.y = sin(glfwGetTime() * 0.7f);
			//lightColor.z = sin(glfwGetTime() * 1.3f);

			glm::vec3 diffuseColor = lightColor   * glm::vec3(0.5f); // 降低影响
			glm::vec3 ambientColor = diffuseColor * glm::vec3(0.2f); // 很低的影响

			lithtProgram.SetUniform3f("material.ambient", 1.0f, 0.5f, 0.31f);
			lithtProgram.SetUniform3f("material.diffuse", 1.0f, 0.5f, 0.31f); // 将光照调暗了一些以搭配场景
			lithtProgram.SetUniform3f("material.specular", 0.5f, 0.5f, 0.5f);

			//lithtProgram.SetUniform3f("light.ambient", ambientColor);
			//lithtProgram.SetUniform3f("light.diffuse", diffuseColor); // 将光照调暗了一些以搭配场景
			//lithtProgram.SetUniform3f("light.specular", 1.0f, 1.0f, 1.0f);
			lithtProgram.SetUniform1f("material.shininess", specularStr);
			tex.Bind();
			tex1.Bind();

			lightVAO.Bind();
			glDrawArrays(GL_TRIANGLES, 0, 36);

			// 2. Show a simple window that we create ourselves. 
			// We use a Begin/End pair to created a named window.
			{
				ImGui::Begin("Application");

				ImGui::SliderFloat3("TranslationX", &translation.x, -10.0f, 10.0f);
				ImGui::SliderFloat("specular", &specularStr, 8.0f, 256.0f);

				ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate);
				ImGui::End();
			}

			// Rendering
			ImGui::Render();
			ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());

			glfwSwapBuffers(window);
			glfwPollEvents();
		}
	}

	// Cleanup
	ImGui_ImplOpenGL3_Shutdown();
	ImGui_ImplGlfw_Shutdown();
	ImGui::DestroyContext();

	glfwDestroyWindow(window);

	glfwTerminate();
	return 0;
}


// 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);

	if (glfwGetKey(window, GLFW_KEY_W) == GLFW_PRESS)
		camera.ProcessKeyboard(FORWARD, deltaTime);
	if (glfwGetKey(window, GLFW_KEY_S) == GLFW_PRESS)
		camera.ProcessKeyboard(BACKWARD, deltaTime);
	if (glfwGetKey(window, GLFW_KEY_A) == GLFW_PRESS)
		camera.ProcessKeyboard(LEFT, deltaTime);
	if (glfwGetKey(window, GLFW_KEY_D) == GLFW_PRESS)
		camera.ProcessKeyboard(RIGHT, deltaTime);
}

// 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.
	glViewport(0, 0, width, height);
}


// glfw: whenever the mouse moves, this callback is called
// -------------------------------------------------------
void mouse_callback(GLFWwindow* window, double xpos, double ypos)
{
	if (firstMouse)
	{
		lastX = (float)xpos;
		lastY = (float)ypos;
		firstMouse = false;
	}

	float xoffset = (float)xpos - lastX;
	float yoffset = lastY - (float)ypos; // reversed since y-coordinates go from bottom to top

	lastX = (float)xpos;
	lastY = (float)ypos;

	//camera.ProcessMouseMovement(xoffset, yoffset);
}

// glfw: whenever the mouse scroll wheel scrolls, this callback is called
// ----------------------------------------------------------------------
void scroll_callback(GLFWwindow* window, double xoffset, double yoffset)
{
	camera.ProcessMouseScroll((float)yoffset);
}<file_sep>/LeranOpenGL/OpenGLAdvanced/src/Application.cpp
﻿#include <iostream>
#include <vector>

#include "GL/glew.h"
#include "GLFW/glfw3.h"
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>

#include "imgui/imgui.h"
#include "imgui/imgui_impl_glfw.h"
#include "imgui/imgui_impl_opengl3.h"

#include "GLDebug.h"
#include "Mesh.h"
#include "ShaderProgram.h"
#include "Texture2D.h"
#include "Model.h"
#include "Camera.h"
#include "TextureCube.h"

void glfwFramebufferSizeCallback(GLFWwindow *window, int width, int height);
void mouse_callback(GLFWwindow* window, double xpos, double ypos);
void scroll_callback(GLFWwindow* window, double xoffset, double yoffset);
void processInput(GLFWwindow *window);

const int SCR_WIDTH = 800;
const int SCR_HEIGHT = 600;

// camera
Camera camera(glm::vec3(0.0f, 0.0f, 3.0f));
float lastX = SCR_WIDTH / 2.0f;
float lastY = SCR_HEIGHT / 2.0f;
bool firstMouse = true;

// timing
float deltaTime = 0.0f;
float lastFrame = 0.0f;


int main()
{
	GLFWwindow *window;
	if (glfwInit() != GL_TRUE)
	{
		std::cout << "Failed to glfwInit." << std::endl;
		return -1;
	}
	const char* glsl_version = "#version 130";
	glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
	glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
	glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);

	window = glfwCreateWindow(SCR_WIDTH, SCR_HEIGHT, "LeranOpenGL", nullptr, nullptr);
	if (window == nullptr)
	{
		std::cout << "Failed to Create Window." << std::endl;
		glfwTerminate();
		return -1;
	}
	glfwMakeContextCurrent(window);
	glfwSwapInterval(1);

	if (glewInit() != GLEW_OK)
	{
		std::cout << "Failed to glew Init." << std::endl;
		glfwTerminate();
		return -1;
	}
	std::cout << "OpenGL Version: " << glfwGetVersionString() << std::endl;
	glViewport(0, 0, SCR_WIDTH, SCR_HEIGHT);
	glfwSetFramebufferSizeCallback(window, glfwFramebufferSizeCallback);
	glfwSetCursorPosCallback(window, mouse_callback);
	glfwSetScrollCallback(window, scroll_callback);

	// tell GLFW to capture our mouse
	//glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);

	{
		GLCall(glEnable(GL_BLEND));
		GLCall(glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA));
		GLCall(glEnable(GL_DEPTH_TEST));

		glEnable(GL_CULL_FACE);
		glCullFace(GL_BACK);
		glFrontFace(GL_CCW);


		// 加载 shader
		ShaderProgram lightShaderProgram("res/shaders/Light.shader");

		ShaderProgram shaderProgram("res/shaders/Basic.shader");

		shaderProgram.Bind();
		//shaderProgram.SetUniform1i("ourTexture1", 0);
		//shaderProgram.SetUniform1i("ourTexture2", 1);

		Model ourModel("res/models/nanosuit/nanosuit.obj");
		Model lightCube("res/models/cube/cube.obj");


		float transparentVertices[] = {
			// positions         // texture Coords (swapped y coordinates because texture is flipped upside down)
			0.0f,  0.5f,  0.0f,  0.0f,  0.0f,
			0.0f, -0.5f,  0.0f,  0.0f,  1.0f,
			1.0f, -0.5f,  0.0f,  1.0f,  1.0f,

			0.0f,  0.5f,  0.0f,  0.0f,  0.0f,
			1.0f, -0.5f,  0.0f,  1.0f,  1.0f,
			1.0f,  0.5f,  0.0f,  1.0f,  0.0f
		};
		// transparent VAO
		unsigned int transparentVAO, transparentVBO;
		glGenVertexArrays(1, &transparentVAO);
		glGenBuffers(1, &transparentVBO);
		glBindVertexArray(transparentVAO);
		glBindBuffer(GL_ARRAY_BUFFER, transparentVBO);
		glBufferData(GL_ARRAY_BUFFER, sizeof(transparentVertices), transparentVertices, GL_STATIC_DRAW);
		glEnableVertexAttribArray(0);
		glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)0);
		glEnableVertexAttribArray(1);
		glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)(3 * sizeof(float)));
		glBindVertexArray(0);

		std::vector<glm::vec3> vegetation
		{
			glm::vec3(-1.5f, 0.0f, -0.48f),
			glm::vec3(1.5f, 0.0f, 0.51f),
			glm::vec3(0.0f, 0.0f, 0.7f),
			glm::vec3(-0.3f, 0.0f, -2.3f),
			glm::vec3(0.5f, 0.0f, -0.6f)
		};

		ShaderProgram grassShaderProgram("res/shaders/Grass.shader");
		grassShaderProgram.Bind();
		Texture2D grass("res/textures/grass.png");
		grassShaderProgram.SetUniform1i("ourTexture", 0);


#pragma region SkyBox 加载
		ShaderProgram skyboxShaderProgram("res/shaders/SkyBox.shader");
		float skyboxVertices[] = {
			// positions          
			-70.0f,  70.0f, -70.0f,
			-70.0f, -70.0f, -70.0f,
			 70.0f, -70.0f, -70.0f,
			 70.0f, -70.0f, -70.0f,
			 70.0f,  70.0f, -70.0f,
			-70.0f,  70.0f, -70.0f,		//
			-70.0f, -70.0f, 7.00f,
			-70.0f, -70.0f, -70.0f,
			-70.0f,  70.0f, -70.0f,
			-70.0f,  70.0f, -70.0f,
			-70.0f,  70.0f,  70.0f,
			-70.0f, -70.0f,  70.0f,

			 70.0f, -70.0f, -70.0f,
			 70.0f, -70.0f,  70.0f,
			 70.0f,  70.0f,  70.0f,
			 70.0f,  70.0f,  70.0f,
			 70.0f,  70.0f, -70.0f,
			 70.0f, -70.0f, -70.0f,

			-70.0f, -70.0f,  70.0f,
			-70.0f,  70.0f,  70.0f,
			 70.0f,  70.0f,  70.0f,
			 70.0f,  70.0f,  70.0f,
			 70.0f, -70.0f,  70.0f,
			-70.0f, -70.0f,  70.0f,

			-70.0f,  70.0f, -70.0f,
			 70.0f,  70.0f, -70.0f,
			 70.0f,  70.0f,  70.0f,
			 70.0f,  70.0f,  70.0f,
			-70.0f,  70.0f,  70.0f,
			-70.0f,  70.0f, -70.0f,

			-70.0f, -70.0f, -70.0f,
			-70.0f, -70.0f,  70.0f,
			 70.0f, -70.0f, -70.0f,
			 70.0f, -70.0f, -70.0f,
			-70.0f, -70.0f,  70.0f,
			 70.0f, -70.0f,  70.0f
		};
		// skybox VAO

		unsigned int skyboxVAO, skyboxVBO;
		glGenVertexArrays(1, &skyboxVAO);
		glGenBuffers(1, &skyboxVBO);
		glBindVertexArray(skyboxVAO);
		glBindBuffer(GL_ARRAY_BUFFER, skyboxVBO);
		glBufferData(GL_ARRAY_BUFFER, sizeof(skyboxVertices), &skyboxVertices, GL_STATIC_DRAW);
		glEnableVertexAttribArray(0);
		glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
		glBindVertexArray(0);
		std::vector<std::string> faces
		{
			"res/textures/skybox/skybox/right.jpg",
			"res/textures/skybox/skybox/left.jpg",
			"res/textures/skybox/skybox/top.jpg",
			"res/textures/skybox/skybox/bottom.jpg",
			"res/textures/skybox/skybox/front.jpg",
			"res/textures/skybox/skybox/back.jpg"
		};
		TextureCube textureCube(faces);
		skyboxShaderProgram.Bind();
		skyboxShaderProgram.SetUniform1i("skybox", 0);
#pragma endregion
		//tex2D.Unbind();
		shaderProgram.Unbind();

		ImGui::CreateContext();
		ImGuiIO& io = ImGui::GetIO(); (void)io;
		//io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard;     // Enable Keyboard Controls
		//io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad;      // Enable Gamepad Controls

		// Setup Dear ImGui style
		//ImGui::StyleColorsDark();
		ImGui::StyleColorsClassic();

		// Setup Platform/Renderer bindings
		ImGui_ImplGlfw_InitForOpenGL(window, true);
		ImGui_ImplOpenGL3_Init(glsl_version);

		float rotation = 0;
		glm::vec3 lightPos = glm::vec3(-0.5f, 1.0f, 0.0f);

		while (!glfwWindowShouldClose(window))
		{
			// render
			// ------
			glClearColor(0.1f, 0.1f, 0.1f, 1.0f);
			glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

			// Start the Dear ImGui frame
			ImGui_ImplOpenGL3_NewFrame();
			ImGui_ImplGlfw_NewFrame();
			ImGui::NewFrame();

			// per-frame time logic
			// --------------------
			float currentFrame = (float)glfwGetTime();
			deltaTime = currentFrame - lastFrame;
			lastFrame = currentFrame;
			// input
			// -----
			processInput(window);

			glm::mat4 projection = glm::perspective(glm::radians(camera.Zoom), (float)SCR_WIDTH / (float)SCR_HEIGHT, 0.1f, 100.0f);
			glm::mat4 view = camera.GetViewMatrix();

			// 绘制天空盒
			glDepthFunc(GL_LEQUAL);  // change depth function so depth test passes when values are equal to depth buffer's content
			skyboxShaderProgram.Bind();
			//view = glm::mat4(glm::mat3(camera.GetViewMatrix())); // remove translation from the view matrix
			skyboxShaderProgram.SetUniformMat4f("view", view);
			skyboxShaderProgram.SetUniformMat4f("projection", projection);
			// skybox cube
			glBindVertexArray(skyboxVAO);
			textureCube.Bind();
			glDrawArrays(GL_TRIANGLES, 0, 36);
			glBindVertexArray(0);
			glDepthFunc(GL_LESS); // set depth function back to default

			// 绘制一个光源
			lightShaderProgram.Bind();
			lightShaderProgram.SetUniformMat4f("projection", projection);
			lightShaderProgram.SetUniformMat4f("view", view);
			glm::mat4 lightModel = glm::mat4(1.0f);

			lightModel = glm::translate(lightModel, lightPos); // translate it down so it's at the center of the scene
			lightModel = glm::scale(lightModel, glm::vec3(0.1f));	// it's a bit too big for our scene, so scale it down
			lightModel = glm::rotate(lightModel, glm::radians(rotation), glm::vec3(0.0f, 1.0f, 0.0f));
			lightShaderProgram.SetUniformMat4f("model", lightModel);

			lightCube.Draw(&shaderProgram);

			// 绘制3D模型
			shaderProgram.Bind();
			// view/projection transformations			
			shaderProgram.SetUniformMat4f("projection", projection);
			shaderProgram.SetUniformMat4f("view", view);
			// render the loaded model
			glm::mat4 model = glm::mat4(1.0f);
			model = glm::translate(model, glm::vec3(0.0f, -3.0f, -8.0f)); // translate it down so it's at the center of the scene
			model = glm::scale(model, glm::vec3(0.3f));	// it's a bit too big for our scene, so scale it down
			model = glm::rotate(model, glm::radians(rotation), glm::vec3(0.0f, 1.0f, 0.0f));
			shaderProgram.SetUniformMat4f("model", model);

			float x = sin(currentFrame);

			shaderProgram.SetUniform3f("lightColor", glm::vec3(1.0f));
			shaderProgram.SetUniform3f("lightPos", lightPos);
			shaderProgram.SetUniform3f("lightAmbient", glm::vec3(0.05f, 0.05f, 0.05f));
			shaderProgram.SetUniform3f("lightDiffuse", glm::vec3(1.0f, 0.5f, 0.31f));
			shaderProgram.SetUniform3f("lightSpecular", glm::vec3(0.5f, 0.5f, 0.5f));
			shaderProgram.SetUniform3f("viewPos", camera.Position);
			ourModel.Draw(&shaderProgram);

			// grass 
			grassShaderProgram.Bind();
			grassShaderProgram.SetUniformMat4f("projection", projection);
			grassShaderProgram.SetUniformMat4f("view", view);
			glBindVertexArray(transparentVAO);
			grass.Bind();
			for (unsigned int i = 0; i < vegetation.size(); i++)
			{
				glm::mat4 grassModel(1.0);
				grassModel = glm::translate(grassModel, vegetation[i]);
				grassShaderProgram.SetUniformMat4f("model", grassModel);

				glDrawArrays(GL_TRIANGLES, 0, 6);
			}
			glBindVertexArray(0);


			// 2. Show a simple window that we create ourselves. 
			// We use a Begin/End pair to created a named window.
			{
				ImGui::Begin("Application");

				ImGui::SliderFloat3("lightPos", &lightPos.x, -2.0f, 2.0f);
				ImGui::SliderFloat("rotation", &rotation, -180.0f, 180.0f);

				ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate);
				ImGui::End();
			}

			// Rendering
			ImGui::Render();
			ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());

			glfwSwapBuffers(window);
			glfwPollEvents();
		}

		glDeleteVertexArrays(1, &skyboxVAO);
		glDeleteBuffers(1, &skyboxVBO);
		glDeleteVertexArrays(1, &transparentVAO);
		glDeleteBuffers(1, &transparentVBO);
	}

	// Cleanup
	ImGui_ImplOpenGL3_Shutdown();
	ImGui_ImplGlfw_Shutdown();
	ImGui::DestroyContext();

	glfwTerminate();
	return 0;
}

// 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);

	if (glfwGetKey(window, GLFW_KEY_W) == GLFW_PRESS)
		camera.ProcessKeyboard(FORWARD, deltaTime);
	if (glfwGetKey(window, GLFW_KEY_S) == GLFW_PRESS)
		camera.ProcessKeyboard(BACKWARD, deltaTime);
	if (glfwGetKey(window, GLFW_KEY_A) == GLFW_PRESS)
		camera.ProcessKeyboard(RIGHT, deltaTime);
	if (glfwGetKey(window, GLFW_KEY_D) == GLFW_PRESS)
		camera.ProcessKeyboard(LEFT, deltaTime);
}

void glfwFramebufferSizeCallback(GLFWwindow *window, int width, int height)
{
	glViewport(0, 0, width, height);
}
// glfw: whenever the mouse moves, this callback is called
// -------------------------------------------------------
void mouse_callback(GLFWwindow* window, double xpos, double ypos)
{
	if (firstMouse)
	{
		lastX = xpos;
		lastY = ypos;
		firstMouse = false;
	}

	float xoffset = xpos - lastX;
	float yoffset = lastY - ypos; // reversed since y-coordinates go from bottom to top

	lastX = xpos;
	lastY = ypos;

	camera.ProcessMouseMovement(xoffset, yoffset);
}

// glfw: whenever the mouse scroll wheel scrolls, this callback is called
// ----------------------------------------------------------------------
void scroll_callback(GLFWwindow* window, double xoffset, double yoffset)
{
	camera.ProcessMouseScroll(yoffset);
}
<file_sep>/LeranOpenGL/OpenGLAdvanced/include/TextureCube.h
#pragma once

#include <vector>

class TextureCube
{
public:
	TextureCube(const std::vector<std::string> faces);
	~TextureCube();

	void Bind(unsigned int slot = 0) const;
	void Unbind();

private:
	unsigned int m_RendererID;


};<file_sep>/LeranOpenGL/OpenGLAdvanced/src/TextureCube.cpp
#include "TextureCube.h"

#include <iostream>
#include <string>

#include "stb_image/stb_image.h"
#include "GL/glew.h"

#include "GLDebug.h"

TextureCube::TextureCube(const std::vector<std::string> faces)
{
	glGenTextures(1, &m_RendererID);
	glBindTexture(GL_TEXTURE_CUBE_MAP, m_RendererID);
	stbi_set_flip_vertically_on_load(0);
	int width, height, nrChannels;
	for (unsigned int i = 0; i < faces.size(); i++)
	{
		unsigned char *data = stbi_load(faces[i].c_str(), &width, &height, &nrChannels, 0);
		if (data)
		{
			glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, data);
			stbi_image_free(data);
		}
		else {
			std::cout << "Cubemap texture failed to load at path: " << faces[i] << std::endl;
			stbi_image_free(data);
		}
	}
	glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
	glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
	glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
	glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
	glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
}

TextureCube::~TextureCube()
{
	//glDeleteTextures(1, &m_RendererID);
}

void TextureCube::Bind(unsigned int slot /* = 0*/) const
{
	glActiveTexture(GL_TEXTURE0 + slot);
	glBindTexture(GL_TEXTURE_CUBE_MAP, m_RendererID);
}

void TextureCube::Unbind()
{
	
}

<file_sep>/README.md
# LeranOpenGL
基于 glfw 和 glew 编写 OpenGL
<file_sep>/LeranOpenGL/OpenGLAdvanced/imgui.ini
[Window][Debug##Default]
Pos=60,60
Size=400,400
Collapsed=0

[Window][Application]
Pos=61,27
Size=746,100
Collapsed=0

<file_sep>/LeranOpenGL/OpenGLAdvanced/include/Model.h
﻿#pragma once

#include <iostream>
#include <vector>


#include <assimp/Importer.hpp>
#include <assimp/scene.h>
#include <assimp/postprocess.h>

#include "Mesh.h"

class Model
{
public:
	/*函数*/
	Model(const std::string &path, bool gamma = false);
	~Model();

	void Draw(ShaderProgram *shaderProgram) const;

private:
	/*模型数据*/
	std::vector<Mesh> meshs;
	std::string directory;

	std::vector<Texture> textures_loaded;

	bool gammaCorrection;

	/*函数*/
	void loadModel(const std::string &path);
	void processNode(aiNode *node, const aiScene *scene);
	Mesh processMesh(aiMesh *mesh, const aiScene *scene);

	std::vector<Texture> loadMaterialTextures(aiMaterial *material, aiTextureType type, std::string typeName);

	unsigned int TextureFromFile(const char *path, const std::string diectory, bool gamma = false);

};<file_sep>/LeranOpenGL/OpenGLAdvanced/src/Texture2D.cpp
#include "Texture2D.h"

#include "stb_image/stb_image.h"
#include "GL/glew.h"

#include "GLDebug.h"

Texture2D::Texture2D(const std::string path)
	:m_RendererID(0), m_FilePath(path), m_LocalBuffer(NULL),
	m_Width(0), m_Height(0), m_BPP(0)
{
	stbi_set_flip_vertically_on_load(0);
	m_LocalBuffer = stbi_load(path.c_str(), &m_Width, &m_Height, &m_BPP, 4);

	GLCall(glGenTextures(1, &m_RendererID));
	GLCall(glBindTexture(GL_TEXTURE_2D, m_RendererID));

	GLCall(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
	GLCall(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
	//GLCall(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
	//GLCall(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
	GLCall(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT));
	GLCall(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT));

	GLCall(glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, m_Width, m_Height, 0, GL_RGBA, GL_UNSIGNED_BYTE, m_LocalBuffer));
	GLCall(glGenerateMipmap(GL_TEXTURE_2D));

	if (m_LocalBuffer)
	{
		stbi_image_free(m_LocalBuffer);
	}
}

Texture2D::~Texture2D()
{
	GLCall(glDeleteTextures(1, &m_RendererID));
}

void Texture2D::Bind(unsigned int slot /* = 0*/) const
{
	GLCall(glActiveTexture(GL_TEXTURE0 + slot));
	GLCall(glBindTexture(GL_TEXTURE_2D, m_RendererID));
}

void Texture2D::Unbind() const
{
}
<file_sep>/LeranOpenGL/OpenGLAdvanced/include/Mesh.h
﻿#pragma once
#include <iostream>
#include <vector>

#include "glm/glm.hpp"
#include "assimp/types.h"

class ShaderProgram;

struct Vertex
{
	glm::vec3 Position;
	glm::vec3 Normal;
	glm::vec2 TexCoords;
};

struct Texture
{
	unsigned int id;
	std::string type;
	aiString path;  // 我们储存纹理的路径用于与其它纹理进行比较
};

class Mesh
{
public:

	/*函数*/
	Mesh(std::vector<Vertex> _vertices, std::vector<unsigned int> _indices, std::vector<Texture> _textures);
	~Mesh();

	void Draw(ShaderProgram *shaderProgram) const;

	inline unsigned int GetVAO() const { return VAO; }
	inline unsigned int GetVBO() const { return VBO; }
	inline unsigned int GetEBO() const { return EBO; }

private:
	/*网格数据*/
	std::vector<Vertex> vertices;
	std::vector<unsigned int> indices;
	std::vector<Texture> textures;

	/*渲染数据*/
	unsigned int VAO;
	unsigned int VBO;
	unsigned int EBO;

	/*函数*/
	void SetupMesh();

};

