OpenGL學習之繪製三角形
阿新 • • 發佈:2019-01-31
開發環境:
MAC、xcode
上程式碼:
1.main.cpp
//
// main.cpp
// GL_example
//
// Created by LiYong on 2018/2/28.
//
#include <iostream>
#include "Argument.h"
#include "Function.h"
using namespace std;
int main()
{
initGL();
GLFWwindow *window = glfwCreateWindow(800, 600, "LEARN OPENGL!", nullptr, nullptr );
if (window == nullptr)
{
cout << "Failed to create GLFW window" << endl;
glfwTerminate();
return -1;
}
glfwMakeContextCurrent(window);
glfwSetKeyCallback(window, key_callback);
glewExperimental = GL_TRUE;
if (glewInit() != GLEW_OK)
{
std ::cout << "Failed to initialize GLEW" << std::endl;
return -1;
}
int width,height;
glfwGetFramebufferSize(window, &width, &height);
glViewport(0, 0, width, height);
initShader();
//1.繪製一個三角形
// renderTriangle();
//2.繪製兩個三角形組成一個矩形
// ElementBufferTest();
//3.繪製兩個三角形
// drawTwoTriangles();
//4.使用不同的VAO、VBO繪製兩個三角形
drawTwoSameTriangles();
while (!glfwWindowShouldClose(window))
{
glfwPollEvents();
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
glUseProgram(shaderProgram);
// glBindVertexArray(VAO);
// glDrawArrays(GL_TRIANGLES, 0, 6);
// glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);//以填充模式繪製(預設)
glBindVertexArray(VAOs[0]);
glDrawArrays(GL_TRIANGLES, 0, 3);
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);//以線框模式繪製
glUseProgram(shaderProgramYellow);
glBindVertexArray(VAOs[1]);
glDrawArrays(GL_TRIANGLES, 0, 3);
glBindVertexArray(0);
glfwSwapBuffers(window);
}
glDeleteVertexArrays(1, &VAO);
glDeleteBuffers(1, &VBO);
glDeleteBuffers(1, &EBO);
glfwTerminate();
return 0;
}
void initGL()
{
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);
//Mac環境下必須新增這一行
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
}
void key_callback(GLFWwindow* window, int key, int scancode, int action, int mode)
{
// 當用戶按下ESC鍵,我們設定window視窗的WindowShouldClose屬性為true
// 關閉應用程式
if(key == GLFW_KEY_ESCAPE && action == GLFW_PRESS)
glfwSetWindowShouldClose(window, GL_TRUE);
}
void initShader()
{
GLuint vertexShader;//定義頂點著色器物件
vertexShader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertexShader,1,&vertexShaderSource,NULL);
glCompileShader(vertexShader);
//編譯著色器
compileVertex(vertexShader);
GLuint fragmentShader;
fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
//編譯片段著色器
glShaderSource(fragmentShader,1,&fragmentShaderSource,NULL);
glCompileShader(fragmentShader);
compileVertex(fragmentShader);
GLuint fragmentShaderYellow;
fragmentShaderYellow = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentShaderYellow,1,&fragmentShader2Source,NULL);
glCompileShader(fragmentShaderYellow);
compileVertex(fragmentShaderYellow);
//連線著色器
shaderProgram = glCreateProgram();
glAttachShader(shaderProgram,vertexShader);
glAttachShader(shaderProgram,fragmentShader);
glLinkProgram(shaderProgram);
detectShaderLink(shaderProgram);
shaderProgramYellow = glCreateProgram();
glAttachShader(shaderProgramYellow,vertexShader);
glAttachShader(shaderProgramYellow,fragmentShaderYellow);
glLinkProgram(shaderProgramYellow);
detectShaderLink(shaderProgramYellow);
glDeleteShader(vertexShader);
glDeleteShader(fragmentShader);
glDeleteShader(fragmentShaderYellow);
}
void compileVertex(GLuint vertex)
{
GLint sucess;
GLchar infoLog[512];
glGetShaderiv(vertex,GL_COMPILE_STATUS,&sucess);
if (!sucess)
{
glGetShaderInfoLog(vertex, 512, NULL, infoLog);
std::cout << "ERROR::SHADER::VERTEX::COMPILATION_FAILED\n" << infoLog << std::endl;
}
}
void detectShaderLink(GLuint shaderProgram)
{
GLint success;
GLchar infoLog[512];
glGetProgramiv(shaderProgram,GL_LINK_STATUS,&success);
if (!success)
{
glGetShaderInfoLog(shaderProgram,512,NULL,infoLog);
}
}
void renderTriangle()
{
GLfloat vertices[] = {
-0.5f, -0.5f, 0.0f,
0.5f, -0.5f, 0.0f,
0.0f, 0.5f, 0.0f
};
glGenVertexArrays(1, &VAO);
glGenBuffers(1, &VBO);
glBindVertexArray(VAO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), (GLvoid*)0);
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
}
void ElementBufferTest()
{
//繪製兩個三角形組成矩形,這裡只儲存不同的頂點
GLfloat vertices[] = {
0.5f, 0.5f, 0.0f, // 右上角
0.5f, -0.5f, 0.0f, // 右下角
-0.5f, -0.5f, 0.0f, // 左下角
-0.5f, 0.5f, 0.0f // 左上角
};
//繪製順序
GLuint indices[] = {
0,1,3,//第一個三角形
1,2,3 //第二個三角形
};
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);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,EBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER,sizeof(indices),indices,GL_STATIC_DRAW);
glVertexAttribPointer(0,3,GL_FLOAT,GL_FALSE,3*sizeof(GLfloat),(GLvoid*)0);
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER,0);
glBindVertexArray(0);
}
void drawTwoTriangles()
{
GLfloat vertices[] = {
-0.9f, -0.5f, 0.0f, // Left
-0.0f, -0.5f, 0.0f, // Right
-0.45f, 0.5f, 0.0f, // Top
0.0f, -0.5f, 0.0f, // Left
0.9f, -0.5f, 0.0f, // Right
0.45f, 0.5f, 0.0f // Top
};
glGenVertexArrays(1, &VAO);
glGenBuffers(1, &VBO);
glBindVertexArray(VAO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), (GLvoid*)0);
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
}
void drawTwoSameTriangles()
{
GLfloat vertices1[] = {
-0.9f, -0.5f, 0.0f, // Left
-0.0f, -0.5f, 0.0f, // Right
-0.45f, 0.5f, 0.0f, // Top
};
GLfloat vertices2[] = {
0.0f, -0.5f, 0.0f, // Left
0.9f, -0.5f, 0.0f, // Right
0.45f, 0.5f, 0.0f // Top
};
glGenVertexArrays(NUM,VAOs);
glGenBuffers(NUM,VBOs);
glBindVertexArray(VAOs[0]);
glBindBuffer(GL_ARRAY_BUFFER,VBOs[0]);
glBufferData(GL_ARRAY_BUFFER,sizeof(vertices1),vertices1,GL_STATIC_DRAW);
glVertexAttribPointer(0,3,GL_FLOAT,GL_FALSE,3*sizeof(GLfloat),(GLvoid*)0);
glEnableVertexAttribArray(0);
glBindVertexArray(0);
glBindVertexArray(VAOs[1]);
glBindBuffer(GL_ARRAY_BUFFER,VBOs[1]);
glBufferData(GL_ARRAY_BUFFER,sizeof(vertices2),vertices2,GL_STATIC_DRAW);
glVertexAttribPointer(0,3,GL_FLOAT,GL_FALSE,3*sizeof(GLfloat),(GLvoid*)0);
glEnableVertexAttribArray(0);
glBindVertexArray(0);
}
2.Function.h
//
// Function.h
// GL_example
//
// Created by LiYong on 2018/3/9.
//
#ifndef Function_h
#define Function_h
#define GLEW_STATIC
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <iostream>
#include "Argument.h"
using namespace std;
void initGL();
void key_callback(GLFWwindow* window, int key, int scancode, int action, int mode);
void compileVertex(GLuint vertex);
void detectShaderLink(GLuint shaderProgram);
void initShader();
//繪製三角形
void renderTriangle();
//索引緩衝物件
void ElementBufferTest();
//繪製兩個連續的三角形
void drawTwoTriangles();
//建立兩個相同的三角形
void drawTwoSameTriangles();
#endif /* Function_h */
3. Argument.h
//
// Argument.h
// GL_example
//
// Created by LiYong on 2018/3/9.
//
#ifndef Argument_h
#define Argument_h
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#define NUM 2
const GLchar* vertexShaderSource = "#version 330 core\n"
"layout (location = 0) in vec3 position;\n"
"void main()\n"
"{\n"
"gl_Position = vec4(position.x, position.y, position.z, 1.0);\n"
"}\0";
const GLchar* fragmentShaderSource = "#version 330 core\n"
"out vec4 color;\n"
"void main()\n"
"{\n"
"color = vec4(1.0f, 0.5f, 0.2f, 1.0f);\n"
"}\n\0";
const GLchar* fragmentShader2Source = "#version 330 core\n"
"out vec4 color;\n"
"void main()\n"
"{\n"
"color = vec4(0.0f, 1.0f, 0.0f, 1.0f); // The color yellow \n"
"}\n\0";
GLuint VBO, VAO, EBO;
GLuint VBOs[NUM],VAOs[NUM],EBOs[NUM];
//定義著色器
GLuint shaderProgram;
GLuint shaderProgramYellow;
#endif /* Argument_h */