着色器类头文件
//我们自己的着色器类
#ifndef SHADER_H
#define SHADER_H
#include <GL/glew.h> //包含glew来获取所有的必须Opengl头文件
#include <string>
#include <fstream>
#include <sstream>
#include <iostream>
class Shader {
public:
unsigned int ID; //程序ID
//构造器读取并构建着色器
Shader(const GLchar* vertexPath, const GLchar* fragmentPath);//顶点着色器的源码路径和片段着色器的源码路径
void use(); //使用、激活程序
//uniform工具函数
void setBool(const std::string &name, bool value) const;
void setInt(const std::string &name, int value) const;
void setFloat(const std::string &name, float value) const;
};
Shader::Shader(const GLchar* vertexPath, const GLchar* fragmentPath)
{ //从文件路径中获取顶点、片段着色器
std::string vertexCode;
std::string fragmentCode;
std::ifstream vShaderFile;
std::ifstream fShaderFile;
//确保fstream对象可以抛出异常
vShaderFile.exceptions(std::ifstream::failbit | std::ifstream::badbit);
fShaderFile.exceptions(std::ifstream::failbit | std::ifstream::badbit);
try
{
//打开文件
vShaderFile.open(vertexPath);
fShaderFile.open(fragmentPath);
std::stringstream vShaderStream, fShaderStream;
vShaderStream << vShaderFile.rdbuf(); //读取文件的缓冲内容到数据流中
fShaderStream << fShaderFile.rdbuf();
vShaderFile.close(); //关闭文件处理器
fShaderFile.close();
vertexCode = vShaderStream.str(); //转换数据流到string
fragmentCode = fShaderStream.str();
}
catch (std::ifstream::failure e)
{
std::cout << "ERROR::SHADER::FILE_NOT_SUCCESFULLY_READ" << std::endl;
}
const char* vShaderCode = vertexCode.c_str();
const char* fShaderCode = fragmentCode.c_str();
//2.编译着色器
unsigned int vertex, fragment;
int success;
char infoLog[512];
//顶点着色器
vertex = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertex, 1, &vShaderCode, NULL);
glCompileShader(vertex);
glGetShaderiv(vertex, GL_COMPILE_STATUS, &success);
if (!success)
{
glGetShaderInfoLog(vertex, 512, NULL, infoLog);
std::cout << "ERROR::SHADER::VERTEX::COMPILATION_FAILED!
" << std::endl;
}
fragment = glCreateShader(GL_FRAGMENT_SHADER); //片段着色器
glShaderSource(fragment, 1, &fShaderCode, NULL);
glCompileShader(fragment);
glGetShaderiv(fragment, GL_COMPILE_STATUS, &success);
if (!success)
{
glGetShaderInfoLog(fragment, 512, NULL, infoLog);
std::cout << "ERROR::SHADER::FRAGMENT::COMPILATON_FAILED!
" << std::endl;
}
ID = glCreateProgram(); //着色器程序
glAttachShader(ID, vertex);
glAttachShader(ID, fragment);
glLinkProgram(ID);
glGetProgramiv(ID, GL_LINK_STATUS, &success);
if (!success)
{
glGetProgramInfoLog(ID, 512, NULL, infoLog);
std::cout << "ERROR::SHADER::PROGRAM::LINKING_FAILED!
" << std::endl;
}
glDeleteShader(vertex); //删除着色器,他们已经链接到我们的程序中了,已经不需要了
glDeleteShader(fragment);
}
void Shader::use()
{
glUseProgram(ID); //激活这个着色器程序
}
void Shader::setBool(const std::string& name, bool value) const
{
glUniform1i(glGetUniformLocation(ID, name.c_str()), (int)value);
}
void Shader::setInt(const std::string &name, int value) const
{
glUniform1i(glGetUniformLocation(ID, name.c_str()), value);
}
void Shader::setFloat(const std::string &name, float value) const
{
glUniform1f(glGetUniformLocation(ID, name.c_str()), value);
}
#endif
纹理cpp文件
#include <iostream>
using namespace std;
#define GLEW_STATIC
#include <GL/glew.h>
#include <GLFW/glfw3.h>
//#define STB_IMAGE_IMPLEMENTATION
#include "stb_image.h"
#include "Shader.h"
void framebuffers_size_callback(GLFWwindow* window, int width, int height);
void processInput(GLFWwindow* window);
float mixValue = 0.2f;
int main()
{
glfwInit();
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
GLFWwindow* window = glfwCreateWindow(800, 600, "LearnOpengl", NULL, NULL);
if (window == NULL)
{
cout << "Failed to create window!
" << endl;
glfwTerminate();
return -1;
}
glfwMakeContextCurrent(window);
glfwSetFramebufferSizeCallback(window, framebuffers_size_callback); //改变窗口大小的回调函数
glewExperimental = GL_TRUE;
if (glewInit() != GLEW_OK)
{
cout << "Fail to initialize GLEW!
" << endl;
return -1;
}
/*unsigned vertexShader, fragmentShader;
vertexShader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertexShader, 1, &vertexShaderSource, NULL);
glCompileShader(vertexShader);
int success;
char infolog[512];
glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &success);
if (!success)
{
glGetShaderInfoLog(vertexShader, 512, NULL, infolog);
cout << "ERROR::SHADER::FRAGMENT::COMPILATION_FAILED!
" << infolog << endl;
}
fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource = (fragmentShader, 1, &fragmentShaderSource, NULL);
glCompileShader(fragmentShader);
glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &success);
if (!success)
{
glGetShaderInfoLog(fragmentShader, 512, NULL, infolog);
cout << "ERROR::SHADER::FRAGMENT::COMPILATION_FAILED!
" << infolog << endl;
}
unsigned int shaderProgram;
shaderProgram = glCreateProgram();
glAttachShader(shaderProgram, vertexShader);
glAttachShader(shaderProgram, fragmentShader);
glLinkProgram(shaderProgram);
glGetProgramiv(shaderProgram, GL_LINK_STATUS, &success);
if (!success)
{
glGetProgramInfoLog(shaderProgram, 512, NULL, infolog);
cout << "ERROR::SHADER::PROGRAM::LINKING_FAILED!
" << infolog << endl;
}
glDeleteShader(vertexShader);
glDeleteShader(fragmentShader);*/
Shader ourShader("E:\C++\1.txt", "E:\C++\2.txt");
GLfloat vertices[] = {
0.5f, 0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, //4.0f控制把图赋值多少16份
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
};
unsigned int indices[] = {
0, 1, 3,
1, 2, 3
};
unsigned VBO, VAO, EBO;
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(float), (void*)0);
glEnableVertexAttribArray(0);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(3 * sizeof(float)));
glEnableVertexAttribArray(1);
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(6 * sizeof(float)));
glEnableVertexAttribArray(2);
unsigned int texture1;
glGenTextures(1, &texture1);
glBindTexture(GL_TEXTURE_2D, texture1);
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_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
int width, height, nrChannels;
//stbi_set_flip_vertically_on_load(true); //倒转图片
//stbi_set_flip_vertically_on_load(true); //倒转图片
unsigned char *data = stbi_load("container.jpg", &width, &height, &nrChannels, 0);
if (data)
{
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, data);
glGenerateMipmap(GL_TEXTURE_2D);
}
else
{
cout << "Failed to load texture1!
" << endl;
}
stbi_image_free(data);
unsigned int texture2;
glGenTextures(1, &texture2);
glBindTexture(GL_TEXTURE_2D, texture2);
//texture1和texture2的环绕方式不同的组合效果很不一样
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_MIRRORED_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_MIRRORED_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
data = stbi_load("timg.jpg", &width, &height, &nrChannels, 0);
if (data)
{
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, data);
glGenerateMipmap(GL_TEXTURE_2D);
}
else
{
cout << "Fail to load texture2!
" << endl;
}
stbi_image_free(data);
ourShader.use();
glUniform1i(glGetUniformLocation(ourShader.ID, "texture1"), 0);
glUniform1i(glGetUniformLocation(ourShader.ID, "texture2"), 1);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
while (!glfwWindowShouldClose(window))
{
processInput(window);
glClearColor(0.2f, 0.5f, 0.7f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
//glBindTexture(GL_TEXTURE_2D, texture);
glActiveTexture(GL_TEXTURE1); //在绑定纹理之前需先激活纹理单元
glBindTexture(GL_TEXTURE_2D, texture1);
glActiveTexture(GL_TEXTURE0); //在绑定纹理之前需先激活纹理单元
glBindTexture(GL_TEXTURE_2D, texture2);
ourShader.setFloat("mixValue", mixValue);
//glUseProgram(shaderProgram);
glUseProgram(ourShader.ID);
glBindVertexArray(VAO);
//glDrawArrays(GL_TRIANGLES, 0, 3);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
glfwSwapBuffers(window);
glfwPollEvents();
}
glDeleteVertexArrays(1, &VAO);
glDeleteBuffers(1, &VBO);
glDeleteBuffers(1, &EBO);
return 0;
}
void framebuffers_size_callback(GLFWwindow* window, int width, int height)
{
glViewport(0, 0, width, height);
}
void processInput(GLFWwindow* window)
{
if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
glfwSetWindowShouldClose(window, true);
//用键盘上下键控制两个纹理的可见度比例
if (glfwGetKey(window, GLFW_KEY_UP) == GLFW_PRESS)
{
mixValue += 0.001f;
if (mixValue >= 1.0f)
mixValue = 1.0f;
}
if (glfwGetKey(window, GLFW_KEY_DOWN) == GLFW_PRESS)
{
mixValue -= 0.001f;
if (mixValue <= 0.0f)
mixValue = 0.0f;
}
}