开发环境:
xcode
第三方库:
glfw、glew、glm、SOIL
代码:
1. ShaderAdmin.hpp
//
// ShaderAdmin.hpp
// GL_Program
//
//
#ifndef ShaderAdmin_hpp
#define ShaderAdmin_hpp
#include <stdio.h>
#include <fstream>
#include <sstream>
#include <iostream>
#include <GL/glew.h>
using namespace std;
class ShaderAdmin
{
public:
//着色器ID;
GLuint m_program;
//构造器读取并构建着色器
ShaderAdmin(const GLchar *vertexPath,const GLchar *fragmentPath);
~ShaderAdmin();
//加载纹理资源
void Use();
private:
void compileShader(const GLchar *vShaderCode,const GLchar *fShaderCode);
void getCompileShaderErrorLog(GLuint shader);
void getLinkShaderProgramErrorLog(GLuint shaderProgram);
};
#endif /* ShaderAdmin_hpp */
2. ShaderAdmin.cpp
//
// ShaderAdmin.cpp
// GL_Program
//
// Created by LiYong on 2018/3/12.
// Copyright © 2018年 feiyu. All rights reserved.
//
#include "ShaderAdmin.hpp"
ShaderAdmin::ShaderAdmin(const GLchar *vertexPath,const GLchar *fragmentPath)
{
// 1. 从文件路径中获取顶点/片段着色器
string vertexCode;
string fragmentCode;
ifstream vShaderFile;
ifstream fShaderFile;
//保证ifstream对象可以抛出异常
vShaderFile.exceptions(ifstream::badbit);
fShaderFile.exceptions(ifstream::badbit);
try
{
//打开文件
vShaderFile.open(vertexPath);
fShaderFile.open(fragmentPath);
if (!vShaderFile.is_open()||!fShaderFile.is_open())
{
cout << "无法打开文件!" << endl;
return;
}
stringstream vShaderStream,fShaderStream;
//读取文件的缓冲内容到流中
vShaderStream << vShaderFile.rdbuf();
fShaderStream << fShaderFile.rdbuf();
//关闭文件
vShaderFile.close();
fShaderFile.close();
//转换流至字符串
vertexCode = vShaderStream.str();
fragmentCode = fShaderStream.str();
}
catch (ifstream::failure e)
{
cout << "ERROR::SHADER::FILE_NOT_SUCCESFULLY_READ" << endl;
}
const GLchar *vShaderCode = vertexCode.c_str();
const GLchar *fShaderCode = fragmentCode.c_str();
compileShader(vShaderCode, fShaderCode);
}
ShaderAdmin::~ShaderAdmin()
{
}
void ShaderAdmin::Use()
{
glUseProgram(this->m_program);
}
void ShaderAdmin::compileShader(const GLchar *vShaderCode, const GLchar *fShaderCode)
{
GLuint vShader,fShader;
vShader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vShader,1,&vShaderCode,NULL);
glCompileShader(vShader);
getCompileShaderErrorLog(vShader);
fShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fShader,1,&fShaderCode,NULL);
glCompileShader(fShader);
getCompileShaderErrorLog(fShader);
m_program = glCreateProgram();
glAttachShader(m_program,vShader);
glAttachShader(m_program,fShader);
glLinkProgram(m_program);
getLinkShaderProgramErrorLog(m_program);
glDeleteShader(vShader);
glDeleteShader(fShader);
}
void ShaderAdmin::getCompileShaderErrorLog(GLuint shader)
{
GLint sucess;
GLchar infoLog[512];
glGetShaderiv(shader,GL_COMPILE_STATUS,&sucess);
if (!sucess)
{
glGetShaderInfoLog(shader, 512, NULL, infoLog);
std::cout << "ERROR::SHADER::VERTEX::COMPILATION_FAILED\n" << infoLog << std::endl;
}
}
void ShaderAdmin::getLinkShaderProgramErrorLog(GLuint shaderProgram)
{
GLint success;
GLchar infoLog[512];
glGetProgramiv(shaderProgram,GL_LINK_STATUS,&success);
if (!success)
{
glGetShaderInfoLog(shaderProgram,512,NULL,infoLog);
}
}
3. TextureAdmin.hpp
//
// texture.hpp
// GL_Program
#ifndef TextureAdmin_hpp
#define TextureAdmin_hpp
#include <stdio.h>
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <SOIL/SOIL.h>
#include <iostream>
using namespace std;
class TextureAdmin
{
public:
TextureAdmin(const string imagePath);
~TextureAdmin();
//绑定纹理单元
void BindTexture();
public:
//纹理ID
GLuint m_pTexture;
};
#endif /* texture_hpp */
4. TextureAdmin.cpp
//
// texture.cpp
// GL_Program
//
// Created by LiYong on 2018/3/13.
// Copyright © 2018年 feiyu. All rights reserved.
//
#include "TextureAdmin.hpp"
TextureAdmin::TextureAdmin(const string imagePath)
{
glGenTextures(1, &m_pTexture);
glBindTexture(GL_TEXTURE_2D, m_pTexture);
//设置纹理的采样方式
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
//设置纹理的过滤方式
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
//加载纹理图片
int width , height;
unsigned char *image = SOIL_load_image(imagePath.data(), &width, &height, 0, SOIL_LOAD_RGB);
glTexImage2D(GL_TEXTURE_2D, 0,GL_RGB, width, height,0, GL_RGB, GL_UNSIGNED_BYTE, image);
glGenerateMipmap(GL_TEXTURE_2D);
SOIL_free_image_data(image);
glBindTexture(GL_TEXTURE_2D, 0);
}
TextureAdmin::~TextureAdmin()
{
}
void TextureAdmin::BindTexture()
{
glBindTexture(GL_TEXTURE_2D, m_pTexture);
}
4. main.cpp
#include <iostream>
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include "ShaderAdmin.hpp"
#include "TextureAdmin.hpp"
#include <glm/glm.hpp>
#include <glm/gtc/type_ptr.hpp>
#include <glm/gtc/matrix_transform.hpp>
#define WIDTH 800
#define HEIGHT 600
#define TITLE "OpenGL"
#define NUM 2
using namespace std;
GLuint VAO,VBO,EBO;
GLuint VAOs[NUM],VBOs[NUM],EBOs[NUM];
void initGL();
void initGLForOSX();
void key_callback(GLFWwindow* window, int key, int scancode, int action, int mode);
void renderRectangle();
int main(int argc, const char * argv[]) {
// initGL();
initGLForOSX();
GLFWwindow *win = glfwCreateWindow(WIDTH, HEIGHT, TITLE, nullptr, nullptr);
if (!win)
{
printf("Failed to create GLFW window!\n");
glfwTerminate();
return NULL;
}
glfwMakeContextCurrent(win);
glfwSetKeyCallback(win, key_callback);
glewExperimental = GL_TRUE;
if(glewInit() != GLEW_OK)
{
printf("Failed to initialize GLEW !\n");
}
int nWidth,nHeight;
glfwGetFramebufferSize(win, &nWidth, &nHeight);
glViewport(0, 0, nWidth, nHeight);
ShaderAdmin shader("Shaders/vShader.vsh","Shaders/fShader.fsh");
renderRectangle();
TextureAdmin texture("Image/container.jpg");
TextureAdmin texture2("Image/awesomeface.png");
while (!glfwWindowShouldClose(win))
{
glfwPollEvents();
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
//激活纹理单元0
glActiveTexture(GL_TEXTURE0);
texture.BindTexture();
glUniform1i(glGetUniformLocation(shader.m_program,"ourTexture"),0);
//激活纹理单元1
glActiveTexture(GL_TEXTURE1);
texture2.BindTexture();
glUniform1i(glGetUniformLocation(shader.m_program,"ourTexture2"),1);
shader.Use();
glBindVertexArray(VAO);
//创建变换矩阵
//1.第一个纹理
glm::mat4 trans;
trans = glm::translate(trans, glm::vec3(0.5f, -0.5f, 0.0f));
trans = glm::rotate(trans,(GLfloat)sin(glfwGetTime()) * 10.0f, glm::vec3(0.0f, 1.0f, 0.0f));
GLuint transform = glGetUniformLocation(shader.m_program,"transform");
glUniformMatrix4fv(transform,1,GL_FALSE,glm::value_ptr(trans));
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
//2.第二个纹理
glm::mat4 trans1;
trans1 = glm::translate(trans1, glm::vec3(-0.5f, 0.5f, 0.0f));
GLfloat scale = sin(glfwGetTime());
trans1 = glm::scale(trans1, glm::vec3(scale,scale,scale));
GLuint transform1 = glGetUniformLocation(shader.m_program,"transform");
glUniformMatrix4fv(transform1,1,GL_FALSE,glm::value_ptr(trans1));
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
glBindVertexArray(0);
glfwSwapBuffers(win);
}
return 0;
}
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 renderRectangle()
{
GLfloat vertices[] = {
// ---- 位置 ---- ---- 颜色 ---- - 纹理坐标 -
0.5f, 0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, // 右上
0.5f, -0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, // 右下
-0.5f, -0.5f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, // 左下
-0.5f, 0.5f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f // 左上
};
GLuint indices[] = {
0,1,2,
2,3,0
};
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,8 * sizeof(GLfloat),(GLvoid *)0);
glEnableVertexAttribArray(0);
//颜色属性
glVertexAttribPointer(1,3,GL_FLOAT,GL_FALSE,8 * sizeof(GLfloat),(GLvoid *)(3*sizeof(GLfloat)));
glEnableVertexAttribArray(1);
//纹理坐标
glVertexAttribPointer(2,2,GL_FLOAT,GL_FALSE,8 * sizeof(GLfloat),(GLvoid *)(6*sizeof(GLfloat)));
glEnableVertexAttribArray(2);
glBindBuffer(GL_ARRAY_BUFFER,0);
glBindVertexArray(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);
}
void initGLForOSX()
{
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);
}
4. 顶点着色器
#version 330 core
layout (location = 0) in vec3 position;
layout (location = 1) in vec3 color;
layout (location = 2) in vec2 texCoord;
out vec3 ourColor;
out vec2 TexCoord;
uniform mat4 transform;
void main()
{
gl_Position = transform * vec4(position, 1.0f);
ourolor = color;
TexCoord = texCoord;
}
5. 片段着色器
#version 330 core
in vec3 ourColor;
in vec2 TexCoord;
out vec4 color;
uniform sampler2D ourTexture;
uniform sampler2D ourTexture2;
void main()
{
color = mix(texture(ourTexture, TexCoord),texture(ourTexture2,TexCoord),0.2);
color = color*vec4(ourColor,1.0);
}