参考
/*
Student Information
Student ID:
Student Name:
*/
#include "Dependencies/glew/glew.h"
#include "Dependencies/GLFW/glfw3.h"
#include "Dependencies/glm/glm.hpp"
#include "Dependencies/glm/gtc/matrix_transform.hpp"
#include "Shader.h"
#include "Texture.h"
#include
#include
#include
#include
using namespace std;
unsigned int VBO, VAO, EBO;
Shader shader;
Texture texture;
// screen setting
const int SCR_WIDTH = 1200;
const int SCR_HEIGHT = 1200;
// struct for storing the obj file
struct Vertex {
glm::vec3 position;
glm::vec2 uv;
glm::vec3 normal;
};
struct Model {
std::vector<Vertex> vertices;
std::vector<unsigned int> indices;
};
Model loadOBJ(const char* objPath)
{
// function to load the obj file
// Note: this simple function cannot load all obj files.
struct V {
// struct for identify if a vertex has showed up
unsigned int index_position, index_uv, index_normal;
bool operator == (const V& v) const {
return index_position == v.index_position && index_uv == v.index_uv && index_normal == v.index_normal;
}
bool operator < (const V& v) const {
return (index_position < v.index_position) ||
(index_position == v.index_position && index_uv < v.index_uv) ||
(index_position == v.index_position && index_uv == v.index_uv && index_normal < v.index_normal);
}
};
std::vector<glm::vec3> temp_positions;
std::vector<glm::vec2> temp_uvs;
std::vector<glm::vec3> temp_normals;
std::map<V, unsigned int> temp_vertices;
Model model;
unsigned int num_vertices = 0;
std::cout << "\nLoading OBJ file " << objPath << "..." << std::endl;
std::ifstream file;
file.open(objPath);
// Check for Error
if (file.fail()) {
std::cerr << "Impossible to open the file! Do you use the right path? See Tutorial 6 for details" << std::endl;
exit(1);
}
while (!file.eof()) {
// process the object file
char lineHeader[128];
file >> lineHeader;
if (strcmp(lineHeader, "v") == 0) {
// geometric vertices
glm::vec3 position;
file >> position.x >> position.y >> position.z;
temp_positions.push_back(position);
}
else if (strcmp(lineHeader, "vt") == 0) {
// texture coordinates
glm::vec2 uv;
file >> uv.x >> uv.y;
temp_uvs.push_back(uv);
}
else if (strcmp(lineHeader, "vn") == 0) {
// vertex normals
glm::vec3 normal;
file >> normal.x >> normal.y >> normal.z;
temp_normals.push_back(normal);
}
else if (strcmp(lineHeader, "f") == 0) {
// Face elements
V vertices[3];
for (int i = 0; i < 3; i++) {
char ch;
file >> vertices[i].index_position >> ch >> vertices[i].index_uv >> ch >> vertices[i].index_normal;
}
// Check if there are more than three vertices in one face.
std::string redundency;
std::getline(file, redundency);
if (redundency.length() >= 5) {
std::cerr << "There may exist some errors while load the obj file. Error content: [" << redundency << " ]" << std::endl;
std::cerr << "Please note that we only support the faces drawing with triangles. There are more than three vertices in one face." << std::endl;
std::cerr << "Your obj file can't be read properly by our simple parser :-( Try exporting with other options." << std::endl;
exit(1);
}
for (int i = 0; i < 3; i++) {
if (temp_vertices.find(vertices[i]) == temp_vertices.end()) {
// the vertex never shows before
Vertex vertex;
vertex.position = temp_positions[vertices[i].index_position - 1];
vertex.uv = temp_uvs[vertices[i].index_uv - 1];
vertex.normal = temp_normals[vertices[i].index_normal - 1];
model.vertices.push_back(vertex);
model.indices.push_back(num_vertices);
temp_vertices[vertices[i]] = num_vertices;
num_vertices += 1;
}
else {
// reuse the existing vertex
unsigned int index = temp_vertices[vertices[i]];
model.indices.push_back(index);
}
} // for
} // else if
else {
// it's not a vertex, texture coordinate, normal or face
char stupidBuffer[1024];
file.getline(stupidBuffer, 1024);
}
}
file.close();
std::cout << "There are " << num_vertices << " vertices in the obj file.\n" << std::endl;
return model;
}
void get_OpenGL_info()
{
// OpenGL information
const GLubyte* name = glGetString(GL_VENDOR);
const GLubyte* renderer = glGetString(GL_RENDERER);
const GLubyte* glversion = glGetString(GL_VERSION);
std::cout << "OpenGL company: " << name << std::endl;
std::cout << "Renderer name: " << renderer << std::endl;
std::cout << "OpenGL version: " << glversion << std::endl;
}
void sendDataToOpenGL()
{
//TODO
//Load objects and bind to VAO and VBO
//Load textures
texture.setupTexture("./container.jpg");
float vertices[] = {
// positions // colors // texture coords
0.5f, 0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, // top right
0.5f, -0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, // bottom right
-0.5f, -0.5f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, // bottom left
-0.5f, 0.5f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f // top left
};
unsigned int indices[] = {
0, 1, 3, // first triangle
1, 2, 3 // second triangle
};
glGenVertexArrays(1, &VAO);
glGenBuffers(1, &VBO);
glGenBuffers(1, &EBO);
glBindVertexArray(VAO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)0);
glEnableVertexAttribArray(0);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (char*)(3 * sizeof(float)));
glEnableVertexAttribArray(1);
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(6 * sizeof(float)));
glEnableVertexAttribArray(2);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
}
void initializedGL(void) //run only once
{
if (glewInit() != GLEW_OK) {
std::cout << "GLEW not OK." << std::endl;
}
get_OpenGL_info();
sendDataToOpenGL();
//TODO: set up the camera parameters
//TODO: set up the vertex shader and fragment shader
shader.setupShader("VertexShaderCode.glsl", "FragmentShaderCode.glsl");
glEnable(GL_DEPTH_TEST);
//glEnable(GL_CULL_FACE);
}
void paintGL(void) //always run
{
glClearColor(0.5f, 0.5f, 0.5f, 0.5f); //specify the background color, this is just an example
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
//TODO:
//Set lighting information, such as position and color of lighting source
//Set transformation matrix
//Bind different textures
shader.use();
glm::mat4 projection = glm::mat4(1.0f);
glm::mat4 model = glm::mat4(1.0f);
glm::mat4 view = glm::mat4(1.0f);
shader.setMat4("projection", projection);
shader.setMat4("model", model);
shader.setMat4("view", view);
texture.bind(0);
glBindVertexArray(VAO);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
}
void framebuffer_size_callback(GLFWwindow* window, int width, int height)
{
glViewport(0, 0, width, height);
}
void mouse_button_callback(GLFWwindow* window, int button, int action, int mods)
{
// Sets the mouse-button callback for the current window.
}
void cursor_position_callback(GLFWwindow* window, double x, double y)
{
// Sets the cursor position callback for the current window
}
void scroll_callback(GLFWwindow* window, double xoffset, double yoffset)
{
// Sets the scoll callback for the current window.
}
void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods)
{
// Sets the Keyboard callback for the current window.
if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
glfwSetWindowShouldClose(window, true);
}
int main(int argc, char* argv[])
{
GLFWwindow* window;
/* Initialize the glfw */
if (!glfwInit()) {
std::cout << "Failed to initialize GLFW" << std::endl;
return -1;
}
/* glfw: configure; necessary for MAC */
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
#ifdef __APPLE__
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
#endif
/* Create a windowed mode window and its OpenGL context */
window = glfwCreateWindow(SCR_WIDTH, SCR_HEIGHT, "Assignment 2", NULL, NULL);
if (!window) {
std::cout << "Failed to create GLFW window" << std::endl;
glfwTerminate();
return -1;
}
/* Make the window's context current */
glfwMakeContextCurrent(window);
/*register callback functions*/
glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);
glfwSetKeyCallback(window, key_callback); //
glfwSetScrollCallback(window, scroll_callback);
glfwSetCursorPosCallback(window, cursor_position_callback);
glfwSetMouseButtonCallback(window, mouse_button_callback);
initializedGL();
while (!glfwWindowShouldClose(window)) {
/* Render here */
paintGL();
/* Swap front and back buffers */
glfwSwapBuffers(window);
/* Poll for and process events */
glfwPollEvents();
}
glfwTerminate();
return 0;
}
顶点着色器:
#version 330 core
layout (location = 0) in vec3 aPos; // 位置变量的属性位置值为 0
layout (location = 1) in vec3 aColor; // 颜色变量的属性位置值为 1
layout (location = 2) in vec2 aTexCoord;
out vec3 ourColor; // 向片段着色器输出一个颜色
out vec2 TexCoord;
uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;
void main(){
gl_Position=vec4(aPos, 1.0);
ourColor = aColor ;
TexCoord = aTexCoord;
}
片元着色器:
#version 330 core
out vec4 FragColor;
in vec3 ourColor;
in vec2 TexCoord;
uniform sampler2D ourTexture;
void main()
{
FragColor = texture(ourTexture, TexCoord);
}
纹理颜色和顶点颜色混合:
FragColor = texture(ourTexture, TexCoord)* vec4(ourColor, 1.0);
uniform sampler2D texture1;
uniform sampler2D texture2;
void main()
{
FragColor = mix(texture(texture1, TexCoord), texture(texture2, TexCoord), 0.2);
}
加载两张纹理:
texture[0].setupTexture("./container.jpg");
texture[1].setupTexture("./awesomeface.png");
绑定并传输数据:
texture[0].bind(0);
shader.setInt("texture1", 0);
texture[1].bind(1);
shader.setInt("texture2", 1);
工程文件