1. 程式人生 > >OpenGl學習 如何畫出一個紅色三角形

OpenGl學習 如何畫出一個紅色三角形

程式碼以及程式碼的解釋如下,使用的是右手座標系,X-大拇指,Y-食指,Z-中指,大拇指指向右邊,食指沖天,注意shader的用法,並不是在編譯器裡面編譯用到,而是在生成exe檔案之後被exe呼叫,所以shader要和exe檔案放在一起

// 引入標頭檔案

#include <stdio.h>
#include <stdlib.h>
#include <GL/glew.h>
#include <GLFW/glfw3.h>
GLFWwindow* window;
#include <glm/glm.hpp>
using namespace glm;


#include <common/shader.hpp>


int main( void )
{
// 初始化GLFW
if( !glfwInit() )
{
fprintf( stderr, "Failed to initialize GLFW\n" );
getchar();
return -1;
}


glfwWindowHint(GLFW_SAMPLES, 4);//4* 反走樣
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);//使用OpenGL core profile
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); // To make MacOS happy; should not be needed
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);


//建立一個視窗並且給它的邊框上寫上內容
window = glfwCreateWindow( 1024, 768, "Tutorial 02 ~~~Red triangle", NULL, NULL);
if( window == NULL ){
fprintf( stderr, "Failed to open GLFW window. If you have an Intel GPU, they are not 3.3 compatible. Try the 2.1 version of the tutorials.\n" );
getchar();
glfwTerminate();
return -1;
}
glfwMakeContextCurrent(window);//??


// 初始化 GLEW
glewExperimental = true; // Needed for core profile
if (glewInit() != GLEW_OK) {
fprintf(stderr, "Failed to initialize GLEW\n");
getchar();
glfwTerminate();
return -1;
}


// 按下任意鍵退出
glfwSetInputMode(window, GLFW_STICKY_KEYS, GL_TRUE);


//背景的顏色
glClearColor(0.2f, 0.3f, 0.4f, 0.0f);


GLuint VertexArrayID;
glGenVertexArrays(1, &VertexArrayID);
glBindVertexArray(VertexArrayID);


//引入兩個shader,這兩個shader並不是編譯的時候用到,而是生成exe檔案之後再呼叫,所以要把它和生成的exe檔案放在一起
GLuint programID = LoadShaders( "SimpleVertexShader.vertexshader", "SimpleFragmentShader.fragmentshader" );


//三角形的三個點,使用右手座標系,X-大拇指,Y-食指,Z-中指,大拇指指向右邊,食指沖天
static const GLfloat g_vertex_buffer_data[] = { 
-1.0f, -1.0f, 0.0f,//原點在(0,0,0),(-1.0f, -1.0f, 0.0f)裡面三個座標對應x,y,z。是最左下角的點
1.0f, -1.0f, 0.0f,//最右下角
0.0f,  0.5f, 0.0f,//最上角
};


GLuint vertexbuffer;//定義頂點緩衝區
glGenBuffers(1, &vertexbuffer);//生成一個緩衝區,在vertexbuffer中放置結果識別符號
glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);//繫結緩衝區
glBufferData(GL_ARRAY_BUFFER, sizeof(g_vertex_buffer_data), g_vertex_buffer_data, GL_STATIC_DRAW);// 把頂點給OpenGL


do{


// Clear the screen
glClear( GL_COLOR_BUFFER_BIT );


// 使用shader
glUseProgram(programID);


// 第一個屬性緩衝區:頂點緩衝區
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
glVertexAttribPointer(
0,                  //要匹配shader的層數
3,                  // 指定每個頂點屬性的元件數量。必須為1、2、3或者4。初始值為4。(如position是由3個(x,y,z)組成,而顏色是4個(r,g,b,a))
GL_FLOAT,           // 型別
GL_FALSE,           // 指定當被訪問時,固定點資料值是否應該被歸一化(GL_TRUE)或者直接轉換為固定點值(GL_FALSE)。
0,                  // 指定連續頂點屬性之間的偏移量。如果為0,那麼頂點屬性會被理解為:它們是緊密排列在一起的。初始值為0。
(void*)0            // 指定一個指標,指向陣列中第一個頂點屬性的第一個元件。初始值為0。
);


// 畫出三角形
glDrawArrays(GL_TRIANGLES, 0, 3); // 從0畫到3


glDisableVertexAttribArray(0);//禁止頂點屬性陣列


//清除快取
glfwSwapBuffers(window);
glfwPollEvents();


} // 檢查esc是否被按下或者視窗被關閉
while( glfwGetKey(window, GLFW_KEY_ESCAPE ) != GLFW_PRESS &&
  glfwWindowShouldClose(window) == 0 );


// 清除VBO,通過VBO我們可以把需要渲染的圖元的頂點資訊,直接上傳儲存在GPU的視訊記憶體中。 而沒有VBO的時候,是需要頻繁賦值給GPU。VBO就是通過那幾個函式,在GPU視訊記憶體中建立一塊BUFFER,用於儲存和頂點以及其屬性相關的資訊
glDeleteBuffers(1, &vertexbuffer);
glDeleteVertexArrays(1, &VertexArrayID);
glDeleteProgram(programID);


// 關閉OpenGL,停止GLFW
glfwTerminate();


return 0;

}

shader的程式碼:

1.片段著色器的程式碼:

#version 330 core


// Ouput data
out vec3 color;


void main()
{


// Output color = red 
color = vec3(1,0,0);//三原色,這裡是只使用紅色


}

2.頂點著色器的程式碼

#version 330 core


// Input vertex data, different for all executions of this shader.
layout(location = 0) in vec3 vertexPosition_modelspace;


void main(){


    gl_Position.xyz = vertexPosition_modelspace;
    gl_Position.w = 1.0;


}