2016年12月26日 星期一

openGL - GLEW, GLM, GLUT 環境架設

有鑑於環境架設常常會忘記內容,所以特別把openGL基本library的架設寫下來避免忘記,
首先是系統資訊

作業系統:win10
編譯環境:visual studio 2015
使用語言:visual C++

首先是安裝GLM,這是一個小小又簡單的library,只有使用std下的函數寫成,他用來作為openGL的矩陣表示非常方便,還有更多數學運算都很依賴他,也因為他足夠簡單,所以lib的建設方法也很快


網址https://github.com/g-truc/glm/tags
首先先去下載GLM解壓縮到D槽
只要在visual studio專案的屬性→VC++目錄→include目錄→新增D:\glm
即可

再來是simple OpenGL image library
網址http://www.lonesock.net/soil.html
這是用來讀取一般圖片轉成openGL可以使用的matrix type的lib,一樣很方便所以我們也加入他,一樣下載SOIL直接解壓縮到D槽
在visual studio專案的屬性→VC++目錄→include目錄→新增D:\Simple OpenGL Image Library\src
在visual studio專案的屬性→VC++目錄→程式庫目錄→新增D:\Simple OpenGL Image Library\lib
※這裡要注意一點SOIL並沒有幫我們編譯好可以直接使用的.lib檔,也就是說我們要自己編譯,使用SOIL資料夾裡的vs10的project打開並且並且直接執行,然後在debug資料夾裡找到編好的SOIL.lib把他丟到D:\Simple OpenGL Image Library\lib


再來安裝GLEW,這是用來使用shader language的library,一樣下載解壓縮到D槽
網址http://glew.sourceforge.net/
選擇win32版本,基本上所有lib都選擇32bit版本,64bit可能會有問題
在visual studio專案的屬性→VC++目錄→include目錄→新增D:\glew-2.0.0\include
在visual studio專案的屬性→VC++目錄→程式庫目錄→新增D:\glew-2.0.0\lib\Release\Win32


再來安裝GLFW,這是用來簡化openGL開啟視窗以及鍵盤滑鼠event的lib,加入它可以讓程式變得更精簡更好控制。
網址http://www.glfw.org/
一樣下載好到D槽,這裡注意一下版本都是選擇win32,64目前還不構穩定。
在visual studio專案的屬性→VC++目錄→include目錄→新增D:\glfw-3.2.1.bin.WIN32\include
在visual studio專案的屬性→VC++目錄→程式庫目錄→新增D:\glfw-3.2.1.bin.WIN32\lib-vc2015

最後就是在visual studio專案的屬性→連結器→輸入→其他相依性把下面這些lib加入
opengl32.lib
glfw3.lib
SOIL.lib
glew32s.lib
即可

接下來是一個範例程式只要能順利跑起來基本上openGLSL的環境就算架設好了
首先是main
--------------------------------------------------------------------------------------------------------
#include <iostream>

// GLEW
#define GLEW_STATIC
#include <GL/glew.h>

// GLFW
#include <GLFW/glfw3.h>

// Other includes
#include "Shader.h"


// Function prototypes
void key_callback(GLFWwindow* window, int key, int scancode, int action, int mode);

// Window dimensions
const GLuint WIDTH = 800, HEIGHT = 600;

// The MAIN function, from here we start the application and run the game loop
int main()
{
    // Init GLFW
    glfwInit();
    // Set all the required options for GLFW
    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);

    // Create a GLFWwindow object that we can use for GLFW's functions
    GLFWwindow* window = glfwCreateWindow(WIDTH, HEIGHT, "LearnOpenGL", nullptr, nullptr);
    glfwMakeContextCurrent(window);

    // Set the required callback functions
    glfwSetKeyCallback(window, key_callback);

    // Set this to true so GLEW knows to use a modern approach to retrieving function pointers and extensions
    glewExperimental = GL_TRUE;
    // Initialize GLEW to setup the OpenGL Function pointers
    glewInit();

    // Define the viewport dimensions
    glViewport(0, 0, WIDTH, HEIGHT);


    // Build and compile our shader program
    Shader ourShader("vs.txt", "fs.txt");


    // Set up vertex data (and buffer(s)) and attribute pointers
    GLfloat vertices[] = {
        // Positions         // Colors
        0.5f, -0.5f, 0.0f,   1.0f, 0.0f, 0.0f,  // Bottom Right
       -0.5f, -0.5f, 0.0f,   0.0f, 1.0f, 0.0f,  // Bottom Left
        0.0f,  0.5f, 0.0f,   0.0f, 0.0f, 1.0f   // Top
    };
    GLuint VBO, VAO;
    glGenVertexArrays(1, &VAO);
    glGenBuffers(1, &VBO);
    // Bind the Vertex Array Object first, then bind and set vertex buffer(s) and attribute pointer(s).
    glBindVertexArray(VAO);

    glBindBuffer(GL_ARRAY_BUFFER, VBO);
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);

    // Position attribute
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), (GLvoid*)0);
    glEnableVertexAttribArray(0);
    // Color attribute
    glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), (GLvoid*)(3 * sizeof(GLfloat)));
    glEnableVertexAttribArray(1);

    glBindVertexArray(0); // Unbind VAO


    // Game loop
    while (!glfwWindowShouldClose(window))
    {
        // Check if any events have been activiated (key pressed, mouse moved etc.) and call corresponding response functions
        glfwPollEvents();

        // Render
        // Clear the colorbuffer
        glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
        glClear(GL_COLOR_BUFFER_BIT);

        // Draw the triangle
        ourShader.Use();
        glBindVertexArray(VAO);
        glDrawArrays(GL_TRIANGLES, 0, 3);
        glBindVertexArray(0);

        // Swap the screen buffers
        glfwSwapBuffers(window);
    }
    // Properly de-allocate all resources once they've outlived their purpose
    glDeleteVertexArrays(1, &VAO);
    glDeleteBuffers(1, &VBO);
    // Terminate GLFW, clearing any resources allocated by GLFW.
    glfwTerminate();
    return 0;
}

// Is called whenever a key is pressed/released via GLFW
void key_callback(GLFWwindow* window, int key, int scancode, int action, int mode)
{
    if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS)
        glfwSetWindowShouldClose(window, GL_TRUE);
}
-------------------------------------------------------------------------------------------------------------

再來是Shader class,我們用它來作為shader之間溝通的媒介
Shader.h
-------------------------------------------------------------------------------------------------------------
#ifndef SHADER_H
#define SHADER_H

#include <string>
#include <fstream>
#include <sstream>
#include <iostream>

#include <GL/glew.h> // Include glew to get all the required OpenGL headers

class Shader
{
public:
// The program ID
GLuint Program;
// Constructor reads and builds the shader
Shader(const GLchar* vertexPath, const GLchar* fragmentPath);
// Use the program
void Use();
};

#endif

------------------------------------------------------------------------------------------------------------

Shader.cpp
-------------------------------------------------------------------------------------------------------------
#include <string>
#include <fstream>
#include <sstream>
#include <iostream>

#include <GL/glew.h>
#include "Shader.h"

Shader::Shader(const GLchar* vertexPath, const GLchar* fragmentPath)
{
// 1. Retrieve the vertex/fragment source code from filePath
std::string vertexCode;
std::string fragmentCode;
std::ifstream vShaderFile;
std::ifstream fShaderFile;
// ensures ifstream objects can throw exceptions:
vShaderFile.exceptions(std::ifstream::badbit);
fShaderFile.exceptions(std::ifstream::badbit);
try
{
// Open files
vShaderFile.open(vertexPath);
fShaderFile.open(fragmentPath);
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_SUCCESFULLY_READ" << std::endl;
}
const GLchar* vShaderCode = vertexCode.c_str();
const GLchar * fShaderCode = fragmentCode.c_str();
// 2. Compile shaders
GLuint vertex, fragment;
GLint success;
GLchar infoLog[512];
// Vertex Shader
vertex = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertex, 1, &vShaderCode, NULL);
glCompileShader(vertex);
// Print compile errors if any
glGetShaderiv(vertex, GL_COMPILE_STATUS, &success);
if (!success)
{
glGetShaderInfoLog(vertex, 512, NULL, infoLog);
std::cout << "ERROR::SHADER::VERTEX::COMPILATION_FAILED\n" << infoLog << std::endl;
}
// Fragment Shader
fragment = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragment, 1, &fShaderCode, NULL);
glCompileShader(fragment);
// Print compile errors if any
glGetShaderiv(fragment, GL_COMPILE_STATUS, &success);
if (!success)
{
glGetShaderInfoLog(fragment, 512, NULL, infoLog);
std::cout << "ERROR::SHADER::FRAGMENT::COMPILATION_FAILED\n" << infoLog << std::endl;
}
// Shader Program
this->Program = glCreateProgram();
glAttachShader(this->Program, vertex);
glAttachShader(this->Program, fragment);
glLinkProgram(this->Program);
// Print linking errors if any
glGetProgramiv(this->Program, GL_LINK_STATUS, &success);
if (!success)
{
glGetProgramInfoLog(this->Program, 512, NULL, infoLog);
std::cout << "ERROR::SHADER::PROGRAM::LINKING_FAILED\n" << infoLog << std::endl;
}
// Delete the shaders as they're linked into our program now and no longer necessery
glDeleteShader(vertex);
glDeleteShader(fragment);

}
// Uses the current shader
void Shader::Use()
{
glUseProgram(this->Program);
}


-----------------------------------------------------------------------------------------------------------------
最後就是創建fs.txt跟vs.txt注意路徑資料夾要在main同一個理

vs.txt
------------------------------------------------------------------------------------------------------------------
#version 330 core
in vec3 ourColor;

out vec4 color;

void main()
{
    color = vec4(ourColor, 1.0f);
}

-------------------------------------------------------------------------------------------------------------------
fs.txt
------------------------------------------------------------------------------------------------------------------
#version 330 core
in vec3 ourColor;

out vec4 color;

void main()
{
    color = vec4(ourColor, 1.0f);
}

沒有留言:

張貼留言