#define GLEW_STATIC
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <iostream>
#include "Shader.h"
#include "stb_image.h"
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, 3,
1, 2, 3
};
void processInput(GLFWwindow* window) {
if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
glfwSetWindowShouldClose(window, true);
}
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, "test", nullptr, nullptr);
if (window == nullptr)
{
std::cout << "Failed to create GLFW window" << std::endl;
glfwTerminate();
return -1;
}
glfwMakeContextCurrent(window);
glewExperimental = GL_TRUE;
if (glewInit() != GLEW_OK)
{
std::cout << "Failed to initialize GLEW" << std::endl;
glfwTerminate();
return -1;
}
glViewport(0, 0, 800, 600);
GLuint VAO;
glGenVertexArrays(1, &VAO);
glBindVertexArray(VAO);
GLuint VBO;
glGenBuffers(1, &VBO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
GLuint EBO;
glGenBuffers(1, &EBO);
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);
glBindVertexArray(0);
GLuint texture;
glGenTextures(1, &texture); //输入生成纹理的数量,储存在第二个参数。参数:1.用来生成纹理的数量,2.存储纹理的索引
glBindTexture(GL_TEXTURE_2D, texture); //绑定纹理,告诉openGL状态机,后续对纹理的操作都用在此纹理
//参数:1.纹理目标,2.要设置的纹理属性,纹理轴(s,t,r/等价于x,y,z),缩小,放大 3.设置的值
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 = stbi_load("container.jpg", &width, &height, 0, 0);
//参数:1.文件路径,2.宽,3.高,4.指定图片的通道数,5.加载图片的方式
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, image); //将纹理图形附加到当前绑定的纹理对象
/*参数:1.指定纹理目标, 2.多级纹理的级别,mipmap的层级, 3.纹理存储格式
4.宽, 5.高, 6.必须为0, 7.源图格式, 8.源图数据(生成纹理的存储数据) 9. 图像数据,指向图像的指针*/
glGenerateMipmap(GL_TEXTURE_2D);
//glTexImage2D多级纹理为0的话,只加载基本级别。调用该函数可自动生成多级渐远纹理。或者在glTexImage2D第二个参数设置更高级别
stbi_image_free(image); //释放图像内存
glBindTexture(GL_TEXTURE_2D, 0); //解绑纹理
GLuint texture1;
glGenTextures(1, &texture1); //输入生成纹理的数量,储存在第二个参数。参数:1.用来生成纹理的数量,2.存储纹理的索引
glBindTexture(GL_TEXTURE_2D, texture1);
int width1, height1;
unsigned char* image1 = stbi_load("awesomeface.png", &width1, &height1, 0, 0);
if (image1) {
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width1, height1, 0, GL_RGBA, GL_UNSIGNED_BYTE, image1);
//注意,从官网保存的图片,载入的时候要带上alpha通道,即GL_RGBA
glGenerateMipmap(GL_TEXTURE_2D);
}
else {
std::cout << "Failed to load texture" << std::endl;
}
stbi_image_free(image1);
Shader* testShader = new Shader("test.vert", "test.frag");
while (!glfwWindowShouldClose(window))
{
processInput(window);
glfwPollEvents();
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
testShader->Use();
glActiveTexture(GL_TEXTURE0);//在绑定纹理之前先激活纹理单元,为了关联sampler2D和纹理
glBindTexture(GL_TEXTURE_2D, texture); //将texture与激活的当前纹理单元关联GL_TEXTURE0
glUniform1i(glGetUniformLocation(testShader->getProgram(), "ourTexture"), 0); //GL_TEXTURE0与采样器ourTexture关联
//单张纹理不需要glActiveTexture,默认激活的纹理单元为GL_TEXTURE0,采样器的默认值也为0,默认关联
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, texture1);
glUniform1i(glGetUniformLocation(testShader->getProgram(), "ourTexture1"), 1);
glBindVertexArray(VAO);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
glBindVertexArray(0);
glfwSwapBuffers(window);
}
glfwTerminate();
return 0;
}
顶点着色器
#version 330 core
layout (location = 0) in vec3 position; // position变量的属性位置值为0
layout (location = 1) in vec3 color; // color变量的属性位置值为1
layout (location = 2) in vec2 textCoord; // textCoord变量的属性位置值为2
out vec4 vertexColor; // 为片段着色器指定一个颜色输出
out vec2 TextCoord;
void main() //每个着色器的入口点都是main函数
{
gl_Position = vec4(position, 1.0);
vertexColor = vec4(color, 1.0f);
TextCoord = vec2(textCoord.x, 1.0-textCoord.y);
}
#version 330 core
in vec4 vertexColor; // 从顶点着色器传来的输入变量(名称相同、类型相同)
in vec2 TextCoord;
out vec4 color; // 片段着色器输出的变量名可以任意命名,类型必须是vec4
uniform sampler2D ourTexture;
//uniform采样器,不用glUniform赋值。使用glUniform1i,给纹理采样器分配一个位置值,在一个FS中设置多个纹理。
//一个纹理位置值称为一个纹理单元。默认激活的为0。
//纹理单元使着色器可以使用多个纹理。赋值一个纹理单元到采样器,可以绑定多个纹理。
uniform sampler2D ourTexture1;
void main()
{
//FragColor = texture(texture1, texcoord);
color = mix(texture(ourTexture, TextCoord), texture(ourTexture1, TextCoord), 0.2);
//输出两个纹理的结合。根据第三个参数进行线性插值,0则返回第一个输入,1则返回第二个
}
练习一:
#version 330 core
in vec4 vertexColor; // 从顶点着色器传来的输入变量(名称相同、类型相同)
in vec2 TextCoord;
out vec4 color; // 片段着色器输出的变量名可以任意命名,类型必须是vec4
uniform sampler2D ourTexture;
//uniform采样器,不用glUniform赋值。使用glUniform1i,给纹理采样器分配一个位置值,在一个FS中设置多个纹理。
//一个纹理位置值称为一个纹理单元。默认激活的为0。
//纹理单元使着色器可以使用多个纹理。赋值一个纹理单元到采样器,可以绑定多个纹理。
uniform sampler2D ourTexture1;
void main()
{
//FragColor = texture(texture1, texcoord);
color = mix(texture(ourTexture, TextCoord), texture(ourTexture1, vec2(1.0-TextCoord.x,TextCoord.y)), 0.2);
//输出两个纹理的结合。根据第三个参数进行线性插值,0则返回第一个输入,1则返回第二个
}
练习二:
#define GLEW_STATIC
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <iostream>
#include "Shader.h"
#include "stb_image.h"
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, 3,
1, 2, 3
};
void processInput(GLFWwindow* window) {
if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
glfwSetWindowShouldClose(window, true);
}
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, "test", nullptr, nullptr);
if (window == nullptr)
{
std::cout << "Failed to create GLFW window" << std::endl;
glfwTerminate();
return -1;
}
glfwMakeContextCurrent(window);
glewExperimental = GL_TRUE;
if (glewInit() != GLEW_OK)
{
std::cout << "Failed to initialize GLEW" << std::endl;
glfwTerminate();
return -1;
}
glViewport(0, 0, 800, 600);
GLuint VAO;
glGenVertexArrays(1, &VAO);
glBindVertexArray(VAO);
GLuint VBO;
glGenBuffers(1, &VBO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
GLuint EBO;
glGenBuffers(1, &EBO);
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);
glBindVertexArray(0);
GLuint texture;
glGenTextures(1, &texture); //输入生成纹理的数量,储存在第二个参数。参数:1.用来生成纹理的数量,2.存储纹理的索引
glBindTexture(GL_TEXTURE_2D, texture); //绑定纹理,告诉openGL状态机,后续对纹理的操作都用在此纹理
//参数:1.纹理目标,2.要设置的纹理属性,纹理轴(s,t,r/等价于x,y,z),缩小,放大 3.设置的值
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 = stbi_load("container.jpg", &width, &height, 0, 0);
//参数:1.文件路径,2.宽,3.高,4.指定图片的通道数,5.加载图片的方式
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, image); //将纹理图形附加到当前绑定的纹理对象
/*参数:1.指定纹理目标, 2.多级纹理的级别,mipmap的层级, 3.纹理存储格式
4.宽, 5.高, 6.必须为0, 7.源图格式, 8.源图数据(生成纹理的存储数据) 9. 图像数据,指向图像的指针*/
glGenerateMipmap(GL_TEXTURE_2D);
//glTexImage2D多级纹理为0的话,只加载基本级别。调用该函数可自动生成多级渐远纹理。或者在glTexImage2D第二个参数设置更高级别
stbi_image_free(image); //释放图像内存
glBindTexture(GL_TEXTURE_2D, 0); //解绑纹理
GLuint texture1;
glGenTextures(1, &texture1); //输入生成纹理的数量,储存在第二个参数。参数:1.用来生成纹理的数量,2.存储纹理的索引
glBindTexture(GL_TEXTURE_2D, texture1);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_MIRRORED_REPEAT);
int width1, height1;
unsigned char* image1 = stbi_load("awesomeface.png", &width1, &height1, 0, 0);
if (image1) {
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width1, height1, 0, GL_RGBA, GL_UNSIGNED_BYTE, image1);
//注意,从官网保存的图片,载入的时候要带上alpha通道,即GL_RGBA
glGenerateMipmap(GL_TEXTURE_2D);
}
else {
std::cout << "Failed to load texture" << std::endl;
}
stbi_image_free(image1);
Shader* testShader = new Shader("test.vert", "test.frag");
while (!glfwWindowShouldClose(window))
{
processInput(window);
glfwPollEvents();
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
testShader->Use();
glActiveTexture(GL_TEXTURE0);//在绑定纹理之前先激活纹理单元,为了关联sampler2D和纹理
glBindTexture(GL_TEXTURE_2D, texture); //将texture与激活的当前纹理单元关联GL_TEXTURE0
glUniform1i(glGetUniformLocation(testShader->getProgram(), "ourTexture"), 0); //GL_TEXTURE0与采样器ourTexture关联
//单张纹理不需要glActiveTexture,默认激活的纹理单元为GL_TEXTURE0,采样器的默认值也为0,默认关联
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, texture1);
glUniform1i(glGetUniformLocation(testShader->getProgram(), "ourTexture1"), 1);
glBindVertexArray(VAO);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
glBindVertexArray(0);
glfwSwapBuffers(window);
}
glfwTerminate();
return 0;
}
#version 330 core
in vec4 vertexColor; // 从顶点着色器传来的输入变量(名称相同、类型相同)
in vec2 TextCoord;
out vec4 color; // 片段着色器输出的变量名可以任意命名,类型必须是vec4
uniform sampler2D ourTexture;
//uniform采样器,不用glUniform赋值。使用glUniform1i,给纹理采样器分配一个位置值,在一个FS中设置多个纹理。
//一个纹理位置值称为一个纹理单元。默认激活的为0。
//纹理单元使着色器可以使用多个纹理。赋值一个纹理单元到采样器,可以绑定多个纹理。
uniform sampler2D ourTexture1;
void main()
{
//FragColor = texture(texture1, texcoord);
color = mix(texture(ourTexture, TextCoord), texture(ourTexture1, vec2(1.0-TextCoord.x,TextCoord.y)*2.0), 0.2);
//输出两个纹理的结合。根据第三个参数进行线性插值,0则返回第一个输入,1则返回第二个
}
练习三:
#define GLEW_STATIC
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <iostream>
#include "Shader.h"
#include "stb_image.h"
GLfloat vertices[] = {
// ---- 位置 ---- ---- 颜色 ---- - 纹理坐标 -
0.5f, 0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 0.6f, 0.6f, // 右上
0.5f, -0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 0.6f, 0.4f, // 右下
-0.5f, -0.5f, 0.0f, 0.0f, 0.0f, 1.0f, 0.4f, 0.4f, // 左下
-0.5f, 0.5f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 0.6f // 左上
};
GLuint indices[] = {
0, 1, 3,
1, 2, 3
};
void processInput(GLFWwindow* window) {
if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
glfwSetWindowShouldClose(window, true);
}
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, "test", nullptr, nullptr);
if (window == nullptr)
{
std::cout << "Failed to create GLFW window" << std::endl;
glfwTerminate();
return -1;
}
glfwMakeContextCurrent(window);
glewExperimental = GL_TRUE;
if (glewInit() != GLEW_OK)
{
std::cout << "Failed to initialize GLEW" << std::endl;
glfwTerminate();
return -1;
}
glViewport(0, 0, 800, 600);
GLuint VAO;
glGenVertexArrays(1, &VAO);
glBindVertexArray(VAO);
GLuint VBO;
glGenBuffers(1, &VBO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
GLuint EBO;
glGenBuffers(1, &EBO);
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);
glBindVertexArray(0);
GLuint texture;
glGenTextures(1, &texture); //输入生成纹理的数量,储存在第二个参数。参数:1.用来生成纹理的数量,2.存储纹理的索引
glBindTexture(GL_TEXTURE_2D, texture); //绑定纹理,告诉openGL状态机,后续对纹理的操作都用在此纹理
//参数:1.纹理目标,2.要设置的纹理属性,纹理轴(s,t,r/等价于x,y,z),缩小,放大 3.设置的值
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;
unsigned char* image = stbi_load("container.jpg", &width, &height, 0, 0);
//参数:1.文件路径,2.宽,3.高,4.指定图片的通道数,5.加载图片的方式
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, image); //将纹理图形附加到当前绑定的纹理对象
/*参数:1.指定纹理目标, 2.多级纹理的级别,mipmap的层级, 3.纹理存储格式
4.宽, 5.高, 6.必须为0, 7.源图格式, 8.源图数据(生成纹理的存储数据) 9. 图像数据,指向图像的指针*/
glGenerateMipmap(GL_TEXTURE_2D);
//glTexImage2D多级纹理为0的话,只加载基本级别。调用该函数可自动生成多级渐远纹理。或者在glTexImage2D第二个参数设置更高级别
stbi_image_free(image); //释放图像内存
glBindTexture(GL_TEXTURE_2D, 0); //解绑纹理
GLuint texture1;
glGenTextures(1, &texture1); //输入生成纹理的数量,储存在第二个参数。参数:1.用来生成纹理的数量,2.存储纹理的索引
glBindTexture(GL_TEXTURE_2D, texture1);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_MIRRORED_REPEAT);
int width1, height1;
unsigned char* image1 = stbi_load("awesomeface.png", &width1, &height1, 0, 0);
if (image1) {
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width1, height1, 0, GL_RGBA, GL_UNSIGNED_BYTE, image1);
//注意,从官网保存的图片,载入的时候要带上alpha通道,即GL_RGBA
glGenerateMipmap(GL_TEXTURE_2D);
}
else {
std::cout << "Failed to load texture" << std::endl;
}
stbi_image_free(image1);
Shader* testShader = new Shader("test.vert", "test.frag");
while (!glfwWindowShouldClose(window))
{
processInput(window);
glfwPollEvents();
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
testShader->Use();
glActiveTexture(GL_TEXTURE0);//在绑定纹理之前先激活纹理单元,为了关联sampler2D和纹理
glBindTexture(GL_TEXTURE_2D, texture); //将texture与激活的当前纹理单元关联GL_TEXTURE0
glUniform1i(glGetUniformLocation(testShader->getProgram(), "ourTexture"), 0); //GL_TEXTURE0与采样器ourTexture关联
//单张纹理不需要glActiveTexture,默认激活的纹理单元为GL_TEXTURE0,采样器的默认值也为0,默认关联
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, texture1);
glUniform1i(glGetUniformLocation(testShader->getProgram(), "ourTexture1"), 1);
glBindVertexArray(VAO);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
glBindVertexArray(0);
glfwSwapBuffers(window);
}
glfwTerminate();
return 0;
}
练习四:
#define GLEW_STATIC
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <iostream>
#include "Shader.h"
#include "stb_image.h"
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, 3,
1, 2, 3
};
GLfloat mixAlpha = 0.2;
void processInput(GLFWwindow* window) {
if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
glfwSetWindowShouldClose(window, true);
if (glfwGetKey(window, GLFW_KEY_UP) == GLFW_PRESS) {
mixAlpha += 0.1;
if (mixAlpha > 1.0) mixAlpha = 1.0;
}
if (glfwGetKey(window, GLFW_KEY_DOWN) == GLFW_PRESS)
mixAlpha -= 0.1;
if (mixAlpha < 0.0) mixAlpha = 0.0;
}
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, "test", nullptr, nullptr);
if (window == nullptr)
{
std::cout << "Failed to create GLFW window" << std::endl;
glfwTerminate();
return -1;
}
glfwMakeContextCurrent(window);
glewExperimental = GL_TRUE;
if (glewInit() != GLEW_OK)
{
std::cout << "Failed to initialize GLEW" << std::endl;
glfwTerminate();
return -1;
}
glViewport(0, 0, 800, 600);
GLuint VAO;
glGenVertexArrays(1, &VAO);
glBindVertexArray(VAO);
GLuint VBO;
glGenBuffers(1, &VBO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
GLuint EBO;
glGenBuffers(1, &EBO);
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);
glBindVertexArray(0);
GLuint texture;
glGenTextures(1, &texture); //输入生成纹理的数量,储存在第二个参数。参数:1.用来生成纹理的数量,2.存储纹理的索引
glBindTexture(GL_TEXTURE_2D, texture); //绑定纹理,告诉openGL状态机,后续对纹理的操作都用在此纹理
//参数:1.纹理目标,2.要设置的纹理属性,纹理轴(s,t,r/等价于x,y,z),缩小,放大 3.设置的值
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 = stbi_load("container.jpg", &width, &height, 0, 0);
//参数:1.文件路径,2.宽,3.高,4.指定图片的通道数,5.加载图片的方式
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, image); //将纹理图形附加到当前绑定的纹理对象
/*参数:1.指定纹理目标, 2.多级纹理的级别,mipmap的层级, 3.纹理存储格式
4.宽, 5.高, 6.必须为0, 7.源图格式, 8.源图数据(生成纹理的存储数据) 9. 图像数据,指向图像的指针*/
glGenerateMipmap(GL_TEXTURE_2D);
//glTexImage2D多级纹理为0的话,只加载基本级别。调用该函数可自动生成多级渐远纹理。或者在glTexImage2D第二个参数设置更高级别
stbi_image_free(image); //释放图像内存
glBindTexture(GL_TEXTURE_2D, 0); //解绑纹理
GLuint texture1;
glGenTextures(1, &texture1); //输入生成纹理的数量,储存在第二个参数。参数:1.用来生成纹理的数量,2.存储纹理的索引
glBindTexture(GL_TEXTURE_2D, texture1);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_MIRRORED_REPEAT);
int width1, height1;
unsigned char* image1 = stbi_load("awesomeface.png", &width1, &height1, 0, 0);
if (image1) {
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width1, height1, 0, GL_RGBA, GL_UNSIGNED_BYTE, image1);
//注意,从官网保存的图片,载入的时候要带上alpha通道,即GL_RGBA
glGenerateMipmap(GL_TEXTURE_2D);
}
else {
std::cout << "Failed to load texture" << std::endl;
}
stbi_image_free(image1);
Shader* testShader = new Shader("test.vert", "test.frag");
while (!glfwWindowShouldClose(window))
{
processInput(window);
glfwPollEvents();
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
testShader->Use();
glActiveTexture(GL_TEXTURE0);//在绑定纹理之前先激活纹理单元,为了关联sampler2D和纹理
glBindTexture(GL_TEXTURE_2D, texture); //将texture与激活的当前纹理单元关联GL_TEXTURE0
glUniform1i(glGetUniformLocation(testShader->getProgram(), "ourTexture"), 0); //GL_TEXTURE0与采样器ourTexture关联
//单张纹理不需要glActiveTexture,默认激活的纹理单元为GL_TEXTURE0,采样器的默认值也为0,默认关联
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, texture1);
glUniform1i(glGetUniformLocation(testShader->getProgram(), "ourTexture1"), 1);
glUniform1f(glGetUniformLocation(testShader->getProgram(), "mixAlpha"), mixAlpha);
glBindVertexArray(VAO);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
glBindVertexArray(0);
glfwSwapBuffers(window);
}
glfwTerminate();
return 0;
}
#version 330 core
in vec4 vertexColor; // 从顶点着色器传来的输入变量(名称相同、类型相同)
in vec2 TextCoord;
out vec4 color; // 片段着色器输出的变量名可以任意命名,类型必须是vec4
uniform sampler2D ourTexture;
//uniform采样器,不用glUniform赋值。使用glUniform1i,给纹理采样器分配一个位置值,在一个FS中设置多个纹理。
//一个纹理位置值称为一个纹理单元。默认激活的为0。
//纹理单元使着色器可以使用多个纹理。赋值一个纹理单元到采样器,可以绑定多个纹理。
uniform sampler2D ourTexture1;
uniform float mixAlpha;
void main()
{
//FragColor = texture(texture1, texcoord);
color = mix(texture(ourTexture, TextCoord), texture(ourTexture1, vec2(1.0-TextCoord.x,TextCoord.y)), mixAlpha);
//输出两个纹理的结合。根据第三个参数进行线性插值,0则返回第一个输入,1则返回第二个
}