19,473
社区成员
头文件:
#pragma once // 为了避免同一个头文件被包含(include)多次
#include<string>
#include<fstream>
#include<sstream>
#include<iostream>
using namespace std;
#include"GL\glew.h" // 注:这一部分要根据个人情况进行设定
#include"GLFW\glfw3.h"
// 我们自己的着色器
class Shader
{
private:
GLuint vertex, fragment; // 顶点着色器 和 片元着色器
public:
GLuint Program; // 着色器程序的ID
// Constructor(着色器构造函数)
Shader(const GLchar* vertexPath, const GLchar* fragmentPath)
{
// 文件读取系列的变量定义
string vertexCode;
string fragmentCode;
ifstream vShaderFile;
ifstream fShaderFile;
// 异常机制处理:保证ifstream对象可以抛出异常:
vShaderFile.exceptions(ifstream::badbit);
fShaderFile.exceptions(ifstream::badbit);
try
{
// 打开文件
vShaderFile.open(vertexPath);
fShaderFile.open(fragmentPath);
stringstream vShaderStream, fShaderStream;
// 读取文件的缓冲内容到数据流中
vShaderStream << vShaderFile.rdbuf();
fShaderStream << fShaderFile.rdbuf();
// 关闭文件处理器
vShaderFile.close();
fShaderFile.close();
// 转换数据流到string
vertexCode = vShaderStream.str();
fragmentCode = fShaderStream.str();
}
catch (ifstream::failure e) { // 发生异常时输出
cout << "ERROR::SHADER::FILE_NOT_SUCCESSFULLY_READ" << endl;
}
/* 将 string 类型的字符串转化为 char数组 类型 */
const GLchar* vShaderCode = vertexCode.c_str();
const GLchar* fShaderCode = fragmentCode.c_str();
/* 顶点着色器 */
vertex = glCreateShader(GL_VERTEX_SHADER); // 创建顶点着色器对象
glShaderSource(vertex, 1, &vShaderCode, NULL); // 将顶点着色器的内容传进来
glCompileShader(vertex); // 编译顶点着色器
GLint flag; // 用于判断编译是否成功
GLchar infoLog[512];
glGetShaderiv(vertex, GL_COMPILE_STATUS, &flag); // 获取编译状态
if (!flag)
{
glGetShaderInfoLog(vertex, 512, NULL, infoLog);
cout << "ERROR::SHADER::VERTEX::COMPILATION_FAILED\n" << infoLog << endl;
}
/* 片元着色器 */
fragment = glCreateShader(GL_FRAGMENT_SHADER); // 创建片元着色器对象
glShaderSource(fragment, 1, &fShaderCode, NULL); // 将片元着色器的内容传进来
glCompileShader(fragment); // 编译顶点着色器
glGetShaderiv(fragment, GL_COMPILE_STATUS, &flag); // 获取编译状态
if (!flag)
{
glGetShaderInfoLog(fragment, 512, NULL, infoLog);
cout << "ERROR::SHADER::FRAGMENT::COMPILATION_FAILED\n" << infoLog << endl;
}
/* 着色器程序 */
this->Program = glCreateProgram();
glAttachShader(this->Program, vertex);
glAttachShader(this->Program, fragment);
glLinkProgram(this->Program);
if (!flag)
{
glGetProgramInfoLog(this->Program, 512, NULL, infoLog);
cout << "ERROR::SHADER::PROGRAM::LINKING_FAILED\n" << infoLog << endl;
}
// 删除着色器,它们已经链接到我们的程序中了,已经不再需要了
glDeleteShader(vertex);
glDeleteShader(fragment);
}
// Deconstructor(析构函数)
~Shader()
{
glDetachShader(this->Program, vertex);
glDetachShader(this->Program, fragment);
glDeleteShader(vertex);
glDeleteShader(fragment);
glDeleteProgram(this->Program);
}
void Use()
{
glUseProgram(this->Program);
}
};
main函数:
/* 引入相应的库 */
#include <iostream>
using namespace std;
#define GLEW_STATIC
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include "Shader.h"
/* 编写各顶点位置与颜色 */
GLfloat vertices_1[] =
{ // position // color
0.0f, 0.5f, 0.0f, 1.0f, 0.0f, 0.0f, // 上顶点(红色)
-0.5f, -0.5f, 0.0f, 0.0f, 1.0f, 0.0f, // 左顶点(绿色)
0.5f, -0.5f, 0.0f, 0.0f, 0.0f, 1.0f // 右顶点(蓝色)
};
const GLint WIDTH = 800, HEIGHT = 600; // 窗口的长和宽
int main()
{
/* 初始化 */
glfwInit();
GLFWwindow* window_1 = glfwCreateWindow(WIDTH, HEIGHT, "A Beautiful Triangle", nullptr, nullptr);
int screenWidth_1, screenHeight_1;
glfwGetFramebufferSize(window_1, &screenWidth_1, &screenHeight_1);
glfwMakeContextCurrent(window_1);
glewInit();
/* 将我们自己设置的着色器文本传进来 */
Shader ourShader = Shader("shader_v.txt", "shader_f.txt"); // 相对路径
/* 设置顶点缓冲对象(VBO) + 设置顶点数组对象(VAO) */
GLuint VAO, VBO;
glGenVertexArrays(1, &VAO);
glGenBuffers(1, &VBO);
glBindVertexArray(VAO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices_1), vertices_1, GL_STATIC_DRAW);
/* 设置链接顶点属性 */
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), (GLvoid*)0);
glEnableVertexAttribArray(0); // 通道 0 打开
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), (GLvoid*)(3 * sizeof(GLfloat)));
glEnableVertexAttribArray(1); // 通道 1 打开
// draw loop 画图循环
while (!glfwWindowShouldClose(window_1))
{
glViewport(0, 0, screenWidth_1, screenHeight_1);
glfwPollEvents();
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
/* 第九步:绘制三角形 */
ourShader.Use(); // 图形渲染
glBindVertexArray(VAO); // 绑定 VAO
glDrawArrays(GL_TRIANGLES, 0, 3); // 画三角形 从第0个顶点开始 一共画3次
glBindVertexArray(0); // 解绑定
glfwSwapBuffers(window_1);
}
glDeleteVertexArrays(1, &VAO); // 释放资源
glDeleteBuffers(1, &VBO);
glfwTerminate(); // 结束
return 0;
}
顶点,片段着色器
// 文件名为 “shader_v.txt”
#version 330 core // 3.30版本
layout(location = 0) in vec3 position; // 位置变量的属性位置值为0
layout(location = 1) in vec3 color; // 颜色变量的属性位置值为1
out vec3 ourColor; // 颜色输出
void main()
{
gl_Position = vec4(position, 1.0f); // 核心函数(位置信息赋值)
ourColor = color;
}
// 文件名为 “shader_f.txt”
#version 330 core // 3.30版本
in vec3 ourColor; // 输入(3维)颜色向量
out vec4 FragColor; // 输出到四个浮点数构成的一个(4维)向量 FragColor
void main()
{
FragColor = vec4(ourColor, 1.0f); // 核心函数(颜色信息赋值)
}
glBegin(GL_TRIANGLES);
glColor3f(1,0,0);
glVertex3f(0,0,0);
glColor3f(0,1,0);
glVertex3f(200,0,0);
glColor3f(0,0,1);
glVertex3f(200,0,200);
glEnd();
光照未开?