openGL 入門——攝像機類+Shader類

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

}

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章