主要分三部分
vao开始
{
//索引缓冲区
//顶点缓冲区
//属性
}
vao结束
其中属性指针是
glVertexAttribPointer(N,,,)
开启属性
glEnableVertexAttribArray(N)
这个N对应着顶点shader中的layout,即(layout=N)
上代码
myshader.h
#pragma once
#include <iostream>
#include "GL/glew.h"
#include "GLFW/glfw3.h"
#include <string>
#include <fstream>
#include <sstream>
#include <iostream>
class myShader
{
public:
myShader(std::string strVertexShaderFileName, std::string strFragmentShaderFileName);
//使用程序
void Use();
private:
//程序ID
GLuint _program;
};
myshader.cpp
#include "myShader.h"
myShader::myShader(std::string strVertexShaderFileName, std::string strFragmentShaderFileName)
{
//从文件路径中获取顶点/片元着色器
std::string vertexCode = "";
std::string fragmentCode = "";
std::ifstream vShaderFile;
std::ifstream fShaderFile;
//保证ifstream对象可以抛出异常
vShaderFile.exceptions(std::ifstream::badbit);
fShaderFile.exceptions(std::ifstream::badbit);
try
{
//打开文件
vShaderFile.open(strVertexShaderFileName);
fShaderFile.open(strFragmentShaderFileName);
std::stringstream vShaderStream, fShaderStream;
//读取文件的缓冲内容到流中
vShaderStream << vShaderFile.rdbuf();
fShaderStream << fShaderFile.rdbuf();
//关闭文件
vShaderFile.close();
fShaderFile.close();
//转换至GLchar数组
vertexCode = vShaderStream.str();
fragmentCode = fShaderStream.str();
}
catch (std::ifstream::failure e)
{
std::cout << "read shader error:" << std::endl;
}
const GLchar* vertexShaderSource = vertexCode.c_str();
const GLchar* fragmentShaderSource = fragmentCode.c_str();
//编译着色器
{
//顶点着色器
//创建顶点着色器
GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER);
{
//把着色器源码附加到着色器对象上
glShaderSource(vertexShader, 1, &vertexShaderSource, NULL);
//编译顶点着色器
glCompileShader(vertexShader);
//检测编译错误
GLint success;
GLchar infoLog[512];
glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &success);
if (!success)
{
glGetShaderInfoLog(vertexShader, 512, NULL, infoLog);
std::cout << "vertexShader Error:" << infoLog << std::endl;
}
}
//片元着色器
//创建片元着色器
GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
{
//把片元着色器源码附加到着色器对象上
glShaderSource(fragmentShader, 1, &fragmentShaderSource, NULL);
//编译片元着色器
glCompileShader(fragmentShader);
//检测编译错误
GLint success;
GLchar infoLog[512];
glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &success);
if (!success)
{
glGetShaderInfoLog(fragmentShader, 512, NULL, infoLog);
std::cout << "fragmentShader Error:" << infoLog << std::endl;
}
}
_program = glCreateProgram();
{
//将编译后的着色器附加到程序对象上
glAttachShader(_program, vertexShader);
glAttachShader(_program, fragmentShader);
//链接着色器
glLinkProgram(_program);
//检测链接错误
GLint success;
GLchar infoLog[512];
glGetProgramiv(_program, GL_LINK_STATUS, &success);
if (!success)
{
glGetProgramInfoLog(_program, 512, NULL, infoLog);
std::cout << "shaderProgram Error:" << infoLog << std::endl;
}
//删除不需要的着色器对象
glDeleteShader(vertexShader);
glDeleteShader(fragmentShader);
}
}
}
void myShader::Use()
{
glUseProgram(_program);
}
调用。cpp
// window.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//
#include "myShader.h"
//按键回调
void key_callback(GLFWwindow* window, int key, int scanCode, int action, int mode);
int main()
{
//初始化GLFW
glfwInit();
//配置GLFW,版本3.3
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);
//创建一个窗口对象,
GLFWwindow* window = glfwCreateWindow(800, 600, "LearnOpenGL", nullptr, nullptr);
if (nullptr == window)
{
std::cout << "创建GLFW窗口失败" << std::endl;
glfwTerminate();
return -1;
}
glfwMakeContextCurrent(window);
//初始化GLEW
//设为GL_TRUE,在GLEW管理OpenGL的函数指针时更多地使用现代化技术
glewExperimental = GL_TRUE;
if (glewInit() != GLEW_OK)
{
std::cout << "初始化glew失败!" << std::endl;
return -1;
}
//设定视口
int width = 0;
int height = 0;
glfwGetFramebufferSize(window, &width, &height);
//设置回调
glfwSetKeyCallback(window, key_callback);
//创建一个VAO
GLuint VAO;
glGenVertexArrays(1, &VAO);
//绑定VAO
glBindVertexArray(VAO);
//绘制内容
{
GLfloat vertices[] =
{
0.5f, 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, //左下角
-0.5f, 0.5f, 0.0f, 1.0f, 0.0f, 1.0f //左上角
};
GLuint indices[] =
{
0,1,3, //第一个三角形
1,2,3 //第二个三角形
};
//创建索引缓冲区对象
{
GLuint EBO;
glGenBuffers(1, &EBO);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
}
//生成一个顶点缓冲对象(vbo)
{
GLuint VBO;
glGenBuffers(1, &VBO);
//把新创建的缓冲绑定到GL_ARRAY_BUFFER目标上
glBindBuffer(GL_ARRAY_BUFFER, VBO);
//把顶点数据复制到当前缓冲的内存中
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
}
//设置属性指针
{
//顶点属性
{
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), (GLvoid*)0);
//启用顶点属性
glEnableVertexAttribArray(0);
}
//颜色属性
{
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), (GLvoid*)(3 * sizeof(GLfloat)));
//启用顶点属性
glEnableVertexAttribArray(1);
}
}
}
//解绑VAO
glBindVertexArray(0);
std::string strVertexShaderFileName = "test.vert";
std::string strFragmentShaderFileName = "test.frag";
myShader theShader(strVertexShaderFileName, strFragmentShaderFileName);
theShader.Use();
//是否用线框模式
//glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
//默认模式是
//glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
//循环
//检查是否要求退出,是则返回,
GLfloat timeValue = 0;
GLfloat greenValue = 0;
while (!glfwWindowShouldClose(window))
{
//清除颜色缓冲
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
//使用着色器程序对象
glBindVertexArray(VAO);
//绘制物体
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
glBindVertexArray(0);
//检查人机交互事件,然后调用事件回调
glfwPollEvents();
//交换颜色缓冲
glfwSwapBuffers(window);
}
//释放资源
glfwTerminate();
return 0;
}
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
#version 330 core
layout (location = 0) in vec3 position;
layout (location = 1) in vec3 color;
out vec3 vertexColor;
void main()
{
gl_Position = vec4(position, 1.0);
vertexColor = color;
}
片元shader
#version 330 core
in vec3 vertexColor;
out vec4 fragcolor;
void main()
{
fragcolor = vec4(vertexColor,1.0);
}