原圖片:

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;
}
