原图片:
1.左右镜像变换
这里总结下左右颠倒的方法:
就是更改片段着色器
FragColor = mix(texture(texture1,TexCoord), texture(texture2,vec2(1.0 - TexCoord.x, TexCoord.y)),0.78f);
这段代码的意思就是更改图片的纹理坐标
比如:
(0,0) -> (1,0)
(1,0) -> (0,0)
(0,1) -> (1,1)
(1,1) -> (0,1)
2.
把笑脸的环绕方式改为 GL_MIRRORED_REPEAT
然后纹理坐标更改:
变为
(这时候超出的边界会自动填充重复的图象)
3.只显示一部分图象,然后用线性放大
4.使用方向键更改图象透明度
额外设置一个uniform maxValue就可以了
键盘输入
镜像翻转示范代码(库请自己看教程寻找):
OpenGLDemo.cpp
// OpenGLDemo.cpp: 定义控制台应用程序的入口点。
#include "stdafx.h"
#include <glad/glad.h>
#include <GLFW/glfw3.h>
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <fstream>
#include <string>
#include <cstring>
#include "Shader.h"
#include <stb_image/stb_image.h>
#include<filesystem>
using namespace std;
void framebuffer_size_callback(GLFWwindow* window, int width, int height);
void processInput(GLFWwindow* window);
char* readTheFile(string strSource);
int main()
{
//glfw: 初始化
glfwInit();
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR,3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR,3);
glfwWindowHint(GLFW_OPENGL_PROFILE,GLFW_OPENGL_CORE_PROFILE);
//glfw: 窗口创建
GLFWwindow* window = glfwCreateWindow(800, 600, "Oh!I see you!", NULL, NULL);
if (window == NULL) {
std::cout << "Failed to create the windows" << std::endl;
glfwTerminate();
return -1;
}
glfwMakeContextCurrent(window);
glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);
glfwSwapInterval(1);
//glad: 加载OpenGL 函数指针
if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)) {
std::cout << "Failed to initialize GLAD" << std::endl;
return -1;
}
Shader shader("vertexShaderSource.vert", "fragmentShaderSource.frag");
float vertices[] = {
//第一个三角形
// ----位置---- ----颜色---- --纹理坐标-
-.5f,.5f,0.0f, 1.0f,0.0f,0.0f, 0.0f,1.0f, //左上
-.5f,-.5f,.0f, 0.0f,1.0f,0.0f, 0.0f,0.0f, //左下
.5f,-.5f,.0f, 0.0f,0.0f,1.0f, 1.0f,0.0f, //右下
.5f, .5f,.0f, 0.0f,0.0f,1.0f, 1.0f,1.0f //右上
};
unsigned int indices[] = {
0,1,2,
0,3,2
};
unsigned int 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);
//texture 1
//---------
unsigned int texture1,texture2;
glGenTextures(1, &texture1);
glBindTexture(GL_TEXTURE_2D, texture1);
为当前绑定的纹理对象设置环绕、过滤方式
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_MIRRORED_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_MIRRORED_REPEAT);
float borderColor[] = { 1.0f,1.0f,0.0f,1.0f };
glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, borderColor);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
//加载纹理图片
int width, height, nrChannels;
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 {
std::cout << "Failed to load texture" << std::endl;
}
//释放内存
stbi_image_free(data);
//texture 2
//---------
glGenTextures(1, &texture2);
glBindTexture(GL_TEXTURE_2D, texture2);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_MIRRORED_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_MIRRORED_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
stbi_set_flip_vertically_on_load(true);
data = stbi_load("LJW.png", &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
{
std::cout << "Failed to load texture" << std::endl;
}
stbi_image_free(data);
shader.use();
shader.setInt("texture1", 0);
shader.setInt("texture2", 1);
while (!glfwWindowShouldClose(window)) {
//输入处理
processInput(window);
//渲染指令
glClearColor(0.2f,0.3f,0.3f,1.0f);
glClear(GL_COLOR_BUFFER_BIT);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texture1);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, texture2);
shader.use();
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT
, 0);
glBindVertexArray(VAO);
glDrawArrays(GL_TRIANGLES,0,3);
glfwSwapBuffers(window);
glfwPollEvents();
}
glfwTerminate();
return 0;
}
void framebuffer_size_callback(GLFWwindow* windows, int width, int height) {
glViewport(0, 0, width, height);
}
void processInput(GLFWwindow* window) {
if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS) {
glfwSetWindowShouldClose(window, true);
}
}
//.frag .vert文件读取
char* readTheFile(string strSource) {
//fstream 中判断是否成功打开文件
//https://blog.csdn.net/fruitz/article/details/41624921
std::ifstream myfile(strSource);
//打开失败
if (myfile.fail()) {
std::cout << "Can not open it " << std::endl;
throw new runtime_error("IO stream corrupted");
}
//转换成字符串
std::string str((std::istreambuf_iterator<char>(myfile)),
std::istreambuf_iterator<char>());
//关闭文件处理器
myfile.close();
//str数组长度一定要 +1,
/*原因: https://blog.csdn.net/ShiQW5696/article/details/80676290 */
int len = str.length();
char* result = new char[len];
strcpy_s(result, len + 1, str.c_str());
return result;
}
fragmentShaderSource.frag
#version 330 core out vec4 FragColor; in vec2 TexCoord; in vec3 outColor; uniform sampler2D texture1; uniform sampler2D texture2; void main() { FragColor = mix(texture(texture1,TexCoord), texture(texture2,vec2(1.0 - TexCoord.x, TexCoord.y)),0.78f); }
vertexShaderSource.vert
#version 330 core
layout(location = 0) in vec3 aPos;
layout(location = 1) in vec3 aColor;
layout(location = 2) in vec2 aTexCoord;
out vec3 outColor;
out vec2 TexCoord;
void main()
{
gl_Position = vec4(aPos, 1.0);
outColor = aColor;
TexCoord = aTexCoord;
}