#include <iostream>
#define GLEW_STATIC
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include "Shader.h"
/*圖像載入數據 翻轉*/
#define STB_IMAGE_IMPLEMENTATION
#include "stb_image.h"
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
using namespace std;
#include "Cameral.h"
#pragma region Model Data
float vertices[] = {
-0.5f, -0.5f, -0.5f, 0.0f, 0.0f,
0.5f, -0.5f, -0.5f, 1.0f, 0.0f,
0.5f, 0.5f, -0.5f, 1.0f, 1.0f,
0.5f, 0.5f, -0.5f, 1.0f, 1.0f,
-0.5f, 0.5f, -0.5f, 0.0f, 1.0f,
-0.5f, -0.5f, -0.5f, 0.0f, 0.0f,
-0.5f, -0.5f, 0.5f, 0.0f, 0.0f,
0.5f, -0.5f, 0.5f, 1.0f, 0.0f,
0.5f, 0.5f, 0.5f, 1.0f, 1.0f,
0.5f, 0.5f, 0.5f, 1.0f, 1.0f,
-0.5f, 0.5f, 0.5f, 0.0f, 1.0f,
-0.5f, -0.5f, 0.5f, 0.0f, 0.0f,
-0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
-0.5f, 0.5f, -0.5f, 1.0f, 1.0f,
-0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
-0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
-0.5f, -0.5f, 0.5f, 0.0f, 0.0f,
-0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
0.5f, 0.5f, -0.5f, 1.0f, 1.0f,
0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
0.5f, -0.5f, 0.5f, 0.0f, 0.0f,
0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
-0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
0.5f, -0.5f, -0.5f, 1.0f, 1.0f,
0.5f, -0.5f, 0.5f, 1.0f, 0.0f,
0.5f, -0.5f, 0.5f, 1.0f, 0.0f,
-0.5f, -0.5f, 0.5f, 0.0f, 0.0f,
-0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
-0.5f, 0.5f, -0.5f, 0.0f, 1.0f,
0.5f, 0.5f, -0.5f, 1.0f, 1.0f,
0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
-0.5f, 0.5f, 0.5f, 0.0f, 0.0f,
-0.5f, 0.5f, -0.5f, 0.0f, 1.0f
};
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)
};
#pragma endregion
//初始化camera類
//Cameral cameral(glm::vec3(0,0,3.0f), glm::vec3(0, 0, 0), glm::vec3(0,1, 0));
Cameral cameral(glm::vec3(0, 0, 3.0f), glm::radians(15.0f), glm::radians(180.0f), glm::vec3(0, 1, 0));
#pragma region Input Declare
void processInput(GLFWwindow* window)
{
if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
glfwSetWindowShouldClose(window, true);
if (glfwGetKey(window, GLFW_KEY_W) == GLFW_PRESS)
cameral.SpeedZ = 1.0f;
else if (glfwGetKey(window, GLFW_KEY_S) == GLFW_PRESS)
cameral.SpeedZ = -1.0f;
else
cameral.SpeedZ = 0;
}
float lastx;
float lasty;
bool firstMouse = true;
void mouse_callback(GLFWwindow* window, double xpos, double ypos)
{
if (firstMouse)
{
lastx = xpos;
lasty = ypos;
firstMouse = false;
}
else
{
float deltax, deltay;
deltax = xpos - lastx;
deltay = ypos - lasty;
lastx = xpos;
lasty = ypos;
cameral.ProcessMouseMovement(deltax, deltay);
}
}
#pragma endregion
#pragma region load and generate the texture
// load and generate the texture
unsigned int loadImgToGPU(const char* fileName, GLint internalFormat, GLenum formate, int textSlot)
{
unsigned int TexBuffer;
glGenTextures(1, &TexBuffer);
glActiveTexture(GL_TEXTURE0 + textSlot);
glBindTexture(GL_TEXTURE_2D, TexBuffer);
// set the texture wrapping/filtering options (on the currently bound texture object)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
int widthT, heightT, nrChannelsT;
stbi_set_flip_vertically_on_load(true); // tell stb_image.h to flip loaded texture's on the y-axis.
unsigned char* data = stbi_load(fileName, &widthT, &heightT, &nrChannelsT, 0);
if (data)
{
glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, widthT, heightT, 0, formate, GL_UNSIGNED_BYTE, data);
glGenerateMipmap(GL_TEXTURE_2D); //多級漸遠紋理
}
else
{
std::cout << "Failed to load texture" << std::endl;
}
stbi_image_free(data);
return TexBuffer;
}
#pragma endregion
int main(int argc, char* argv[])
{
#pragma region Open a Window
glfwInit();
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);
GLFWwindow* window = glfwCreateWindow(800, 600, "LearnOpenGL", nullptr, nullptr);
if (window == nullptr)
{
std::cout << "Failed to create GLFW window" << std::endl;
glfwTerminate();
return EXIT_FAILURE;
}
glfwMakeContextCurrent(window);
//關閉鼠標遊標
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
glfwSetCursorPosCallback(window, mouse_callback);
//////==========================
glewExperimental = GL_TRUE;
if (glewInit() != GLEW_OK)
{
std::cout << "Failed to initialize GLEW" << std::endl;
return EXIT_FAILURE;
}
int width, height;
glfwGetFramebufferSize(window, &width, &height);
glViewport(0, 0, width, height);
//線框模式(Wireframe Mode)
//glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
////三角形默認逆時針繪製--背面剔除
//glEnable(GL_CULL_FACE);
//glCullFace(GL_BACK);
glEnable(GL_DEPTH_TEST);
#pragma endregion
#pragma region Init Shader
Shader* myShader = new Shader("vertexSource.vert", "fragmentSource.frag");
#pragma endregion
#pragma region Init And Load Model To VAO VBO
//VAO Vertex Array Object
// 1. bind Vertex Array Object 綁定頂點數組對象
unsigned int VAO;
glGenVertexArrays(1, &VAO);
glBindVertexArray(VAO);
// vertex buffer objects (VBO) can store a large number of vertices in the GPU's memory.
// 2. copy our vertices array in a buffer for OpenGL to use
unsigned int VBO;
glGenBuffers(1, &VBO); //產生一個bufferID
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
// 4. then set our vertex attributes pointers
// 位置屬性
glVertexAttribPointer(6, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), (GLvoid*)0);
glEnableVertexAttribArray(6);
//// 顏色屬性
//glVertexAttribPointer(7, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (GLvoid*)(3 * sizeof(GLfloat)));
//glEnableVertexAttribArray(7);
// 紋理屬性
glVertexAttribPointer(8, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), (GLvoid*)(3 * sizeof(GLfloat)));
glEnableVertexAttribArray(8);
#pragma endregion
#pragma region load and generate the texture
unsigned int TexBufferA;
TexBufferA = loadImgToGPU("container.jpg", GL_RGB, GL_RGB, 0);
unsigned int TexBufferB;
TexBufferB = loadImgToGPU("awesomeface.png", GL_RGBA, GL_RGBA, 3);
#pragma endregion
#pragma region Prepare MVP Matrix
//變換矩陣 先進行縮放操作,然後是旋轉,最後纔是位移
//矩陣相乘是右邊乘,從右往左讀
glm::mat4 trans = glm::mat4(1.0f);
//trans = glm::translate(trans, glm::vec3(-0.001f, 0, 0));
//trans = glm::rotate(trans, glm::radians(90.0f), glm::vec3(0.0, 0.0, 1.0));
//trans = glm::scale(trans, glm::vec3(0.5, 0.5, 0.5));
//coordinaite openGL 右手座標系(z軸向上)
glm::mat4 modelMat = glm::mat4(1.0f);
modelMat = glm::rotate(modelMat, glm::radians(-55.0f), glm::vec3(1, 0, 0));
glm::mat4 viewMat = glm::mat4(1.0f);
//viewMat = glm::translate(viewMat, glm::vec3(0, 0, -3));
glm::mat4 projMat;
projMat = glm::perspective(glm::radians(45.0f), 800.0f / 600.0f, 0.1f, 100.0f);
#pragma endregion
while (!glfwWindowShouldClose(window))
{
//Process Input
processInput(window);
//Clear Screen
glClearColor(0.2, 0.3, 0.3f, 1.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
viewMat = cameral.getviewMatrix();
for (int i = 0; i < 10; i++)
{
//set model Matrix
modelMat = glm::translate(glm::mat4(1.0f), cubePositions[i]);
//set view and projection Matrixs if you wants
// set material -> shader program
myShader->use();
//set material -> textures
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, TexBufferA);
glActiveTexture(GL_TEXTURE3);
glBindTexture(GL_TEXTURE_2D, TexBufferB);
// set material -> uniform
glUniform1i(glGetUniformLocation(myShader->ID, "ourTexture"), 0);
glUniform1i(glGetUniformLocation(myShader->ID, "ourFace"), 3);
glUniformMatrix4fv(glGetUniformLocation(myShader->ID, "modelMat"), 1, GL_FALSE, glm::value_ptr(modelMat));
glUniformMatrix4fv(glGetUniformLocation(myShader->ID, "viewMat"), 1, GL_FALSE, glm::value_ptr(viewMat));
glUniformMatrix4fv(glGetUniformLocation(myShader->ID, "projMat"), 1, GL_FALSE, glm::value_ptr(projMat));
//set models
glBindVertexArray(VAO);
//drawcall
glDrawArrays(GL_TRIANGLES, 0, 36);
//glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
}
//clean up ,prepare for next render loop
glfwSwapBuffers(window);
glfwPollEvents();
cameral.UpdateCameralPos();
}
//Exit program
glfwTerminate();
return 0;
}
#pragma once
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
class Cameral
{
public:
Cameral(glm::vec3 position, glm::vec3 target, glm::vec3 worldup);
Cameral(glm::vec3 position, float pitch, float yaw, glm::vec3 worldup);
glm::vec3 Positon;
glm::vec3 Forward;
glm::vec3 Right;
glm::vec3 Up;
glm::vec3 Worldup;
float Pitch;
float Yaw;
float senseX = 0.001f; // 縮放因子
float senseY = 0.001f;
float senseZ = 0.01f;
float SpeedZ = 0;
glm::mat4 getviewMatrix();
void ProcessMouseMovement(float deltaX,float deltaY);
void UpdateCameralPos();
private:
void UpdateCameraVectors();
};
#include "Cameral.h"
//目標位置版本
Cameral::Cameral(glm::vec3 position, glm::vec3 target, glm::vec3 worldup) {
Positon = position;
Worldup = worldup;
Forward = glm::normalize( target - position);
Right = glm::normalize(glm::cross(Forward, Worldup)); //x
Up= glm::normalize(glm::cross(Forward, Right)); //y
}
///歐拉角版本
Cameral::Cameral(glm::vec3 position, float pitch, float yaw, glm::vec3 worldup)
{
Positon = position;
Worldup = worldup;
Pitch = pitch;
Yaw = yaw;
Forward.x = glm::cos(Pitch)*sin(Yaw);
Forward.y = glm::sin(Pitch);
Forward.z = glm::cos(Pitch) * cos(Yaw);
Right = glm::normalize(glm::cross(Forward, Worldup));
Up = glm::normalize(glm::cross(Forward, Right));
}
glm::mat4 Cameral::getviewMatrix() {
return glm::lookAt(Positon, Positon + Forward, Worldup);
}
void Cameral::ProcessMouseMovement(float deltaX, float deltaY)
{
Pitch -= deltaY * senseY;
Yaw -= deltaX * senseX;
UpdateCameraVectors();
}
void Cameral::UpdateCameralPos()
{
// Positon += glm::vec3(0,0,-SpeedZ* senseZ);
Positon += Forward * SpeedZ * senseZ;
}
void Cameral::UpdateCameraVectors()
{
Forward.x = glm::cos(Pitch) * sin(Yaw);
Forward.y = glm::sin(Pitch);
Forward.z = glm::cos(Pitch) * cos(Yaw);
Right = glm::normalize(glm::cross(Forward, Worldup));
Up = glm::normalize(glm::cross(Forward, Right));
}
#pragma once
// GLEW
#define GLEW_STATIC
#include <GL/glew.h>
#include <string>
using namespace std;
class Shader
{
public:
Shader(const GLchar* vertexPath, const GLchar* fragmentPath);
string vertexString;
string fragmentString;
const char* vertexSource;
const char* fragmentSource;
unsigned int ID; //shader Program ID
void use();
private:
void checkCompileErrors(unsigned int proID, string type);
};
#include<iostream>
#include "Shader.h"
#include <fstream>
#include <sstream>
using namespace std;
Shader::Shader(const GLchar* vertexPath,const GLchar* fragmentPath)
{
ifstream vertexFile;
ifstream fragmentFile;
stringstream vertexSStream;
stringstream fragmengSStream;
// 打開文件
vertexFile.open(vertexPath);
fragmentFile.open(fragmentPath);
// 保證ifstream對象可以拋出異常:
vertexFile.exceptions(ifstream::failbit || ifstream::badbit );
fragmentFile.exceptions(ifstream::failbit || ifstream::badbit);
try
{
if (!vertexFile.is_open() || !fragmentFile.is_open())
{
throw exception(" file open failure!");
}
// 讀取文件的緩衝內容到流中
vertexSStream << vertexFile.rdbuf();
fragmengSStream << fragmentFile.rdbuf();
// 轉換流至string
vertexString = vertexSStream.str();
fragmentString = fragmengSStream.str();
//轉換string到Char數組
vertexSource = vertexString.c_str();
fragmentSource = fragmentString.c_str();
/*printf(vertexSource);
printf(fragmentSource);*/
unsigned int vertex, fragment;
vertex = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertex, 1, &vertexSource, NULL);
glCompileShader(vertex);
checkCompileErrors(vertex, "VERTEX");
fragment = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragment, 1, &fragmentSource, NULL);
glCompileShader(fragment);
checkCompileErrors(fragment, "FRAGMENT");
ID = glCreateProgram();
glAttachShader(ID, vertex);
glAttachShader(ID, fragment);
glLinkProgram(ID);
checkCompileErrors(ID, "PROGRAM");
glDeleteShader(vertex);
glDeleteShader(fragment);
}
catch (const std::exception& ex)
{
printf(ex.what());
}
}
///使用shaderProgram
void Shader::use()
{
glUseProgram(ID);
}
///檢查編譯錯誤並輸出
void Shader::checkCompileErrors(unsigned int proID, string type)
{
int success;
char infoLog[512];
if (type != "PROGRAM")
{
glGetShaderiv(proID, GL_COMPILE_STATUS, &success);
if (!success)
{
glGetShaderInfoLog(proID, 512, NULL, infoLog);
std::cout << "shader complie error\n" << infoLog << std::endl;
}
}
else
{
glGetProgramiv(proID, GL_LINK_STATUS, &success);
if (!success)
{
glGetProgramInfoLog(proID, 512, NULL, infoLog);
std::cout << "program linking error\n" << infoLog << std::endl;
}
}
}
#version 330 core
layout (location = 6) in vec3 aPos;
layout (location = 7) in vec3 aColor;
layout (location = 8) in vec2 aTexCoord;
out vec4 vertexColor;
out vec2 TexCoord;
//uniform mat4 transform;
uniform mat4 modelMat;
uniform mat4 viewMat;
uniform mat4 projMat;
void main()
{
//gl_Position =transform * vec4(aPos.x, aPos.y, aPos.z, 1.0);
gl_Position =projMat *viewMat *modelMat * vec4(aPos.x, aPos.y, aPos.z, 1.0);
vertexColor=vec4(aColor.x+0.5, aColor.y, aColor.z, 1.0);
TexCoord = aTexCoord;
}
#version 330 core
in vec4 vertexColor;
in vec2 TexCoord;
//uniform vec4 ourColor;
out vec4 FragColor;
uniform sampler2D ourTexture;
uniform sampler2D ourFace;
void main()
{
//FragColor = vertexColor;
//FragColor = texture(ourTexture, TexCoord) * vertexColor;
FragColor = mix(texture(ourTexture, TexCoord) , texture(ourFace, TexCoord),0.2);
}