OpenGL_Learn06 (Texture)

Following the previous OpenGL_Learn05 (Texture)-CSDN Blog

1. Modify fragment shader

Modify the fragment shader to only make the smiley face look the other way

== ======>>>>>

The Y-axis of the texture coordinates has not been changed. What needs to be changed is the texture coordinates of the X-axis.

The code snippet is rewritten as follows

#version 330 core
out vec4 FragColor;

in vec3 ourColor;
in vec2 TexCoord;

//texture sampler
uniform sampler2D textureone;
uniform sampler2D texturetwo;

void main()
{
    FragColor = mix(texture(textureone,TexCoord),texture(texturetwo,vec2(1.0-TexCoord.x,TexCoord.y)),0.5);
}

2. Try different texture wrapping methods

Set a range from 0.0f to 2.0f (instead of the original 0.0f to 1.0f ) texture coordinates, try to see if you can place 4 smiley faces in the corners of the box.

Original texture coordinates:

//4. Set vertex data
float vertices[] = {
// positions // colors // texture coords
0.5f, 0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, // top right
0.5f, -0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, // bottom right
-0.5f, -0.5f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, // bottom left
-0.5f, 0.5f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f // top left
};

Change it to the following:

//4. Set vertex data
float vertices[] = {
// positions // colors // texture coords
0.5f, 0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 2.0f, 2.0f, // top right
0.5f, -0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 2.0f, 0.0f, // bottom right
-0.5f, -0.5f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, // bottom left
-0.5f, 0.5f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 2.0f // top left
};

3. Texture filtering

Try displaying only the middle part of the texture image on the rectangle and modifying the texture coordinates to achieve the effect of seeing individual pixels. Try using the GL_NEAREST texture filtering method to make the pixels appear clearer.

#include <glad/glad.h>
#include <GLFW/glfw3.h>

#include <iostream>
#include "stb_image.h"
#include <cmath>
#include "shader.h"
void framebuffer_size_callback(GLFWwindow* window, int width, int height);
void processInput(GLFWwindow* window);

// settings
const unsigned int SCR_WIDTH = 800;
const unsigned int SCR_HEIGHT = 600;

int main() {

//1.Initialization configuration
glfwInit();
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);

#ifdef __APPLE__
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GLFW_TRUE);
#endif // __APPLE__

//2.gltf window creation
GLFWwindow* window = glfwCreateWindow(SCR_WIDTH, SCR_HEIGHT, "LeranOpenGL", NULL, NULL);
if (window == NULL) {
std::cout << "Failed to create GLFW window" << std::endl;
glfwTerminate();
return -1;
}

glfwMakeContextCurrent(window);
glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);

//3. Load all GL function pointers
if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)) {
std::cout << "Failed to initialize GLAD" << std::endl;
return -1;
}

Shader ourShader("./texture.vs", "./texture.fs");

//4. Set vertex data
float vertices[] = {
// positions // colors // texture coords (note that we changed them to 'zoom in' on our texture image)
0.5f, 0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 0.55f, 0.55f, // top right
0.5f, -0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 0.55f, 0.45f, // bottom right
-0.5f, -0.5f, 0.0f, 0.0f, 0.0f, 1.0f, 0.45f, 0.45f, // bottom left
-0.5f, 0.5f, 0.0f, 1.0f, 1.0f, 0.0f, 0.45f, 0.55f // top left
};

unsigned int indices[] = {
0, 1, 3, // first triangle
1, 2, 3 // second triangle
};

unsigned int VBO, VAO, EBO;
glGenVertexArrays(1, & amp;VAO);
glGenBuffers(1, & amp;VBO);
glGenBuffers(1, & amp;EBO);//Element Buffer Object: Element Buffer Object, EBO

glBindVertexArray(VAO);
\t
//Copy the vertex array to the buffer for use by opengl
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);


//Set the vertex attribute pointer
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)0);
glEnableVertexAttribArray(0);
//Set the color attribute pointer
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(3 * sizeof(float)));
glEnableVertexAttribArray(1);
//Set texture attribute pointer
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(6 * sizeof(float)));
glEnableVertexAttribArray(2);

//Load and create texture
unsigned int textureone,texturetwo;
glGenTextures(1, & amp;textureone);
glBindTexture(GL_TEXTURE_2D, textureone);
//Set texture wrapping parameters
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
//Set texture filtering parameters
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);

//Load images and generate mipmaps
int width, height, nrChannels;
stbi_set_flip_vertically_on_load(true);
std::string filePath = R"(D:\CPlusProject\LearnOpenGL\DataSet\container.jpg)";
unsigned char* data = stbi_load(filePath.c_str(), & amp;width, & amp;height, & amp;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);


glGenTextures(1, & amp;texturetwo);
glBindTexture(GL_TEXTURE_2D, texturetwo);
//Set texture wrapping parameters
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
//Set texture filtering parameters
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);

//Load images and generate mipmaps
filePath = R"(D:\CPlusProject\LearnOpenGL\DataSet\awesomeface.png)";
unsigned char* data2 = stbi_load(filePath.c_str(), & amp;width, & amp;height, & amp;nrChannels, 0);

if (data2) {
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data2);
glGenerateMipmap(GL_TEXTURE_2D);
}
else {
std::cout << "Failed to load texture" << std::endl;
}

stbi_image_free(data2);


\t
ourShader.use();
glUniform1i(glGetUniformLocation(ourShader.ID, "textureone"), 0);//Choose one of the two
ourShader.setInt("texturetwo", 1);//Choose one of the two

//5. Loop rendering
while (!glfwWindowShouldClose(window)) {
processInput(window);

// render
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
//Bind texture
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, textureone);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, texturetwo);


ourShader.use();
glBindVertexArray(VAO);
glDrawElements(GL_TRIANGLES,6,GL_UNSIGNED_INT,0);

glfwSwapBuffers(window);
glfwPollEvents();

}

glDeleteVertexArrays(1, & amp;VAO);
glDeleteBuffers(1, & amp;VBO);
glDeleteBuffers(1, & amp;EBO);

glfwTerminate();
return 0;

}

// process all input: query GLFW whether relevant keys are pressed/released this frame and react accordingly
//------------------------------------------------ -------------------------------------------------- -------
void processInput(GLFWwindow* window)
{
if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
glfwSetWindowShouldClose(window, true);
}

// glfw: whenever the window size changed (by OS or user resize) this callback function executes
//------------------------------------------------ ----------------------------------------
void framebuffer_size_callback(GLFWwindow* window, int width, int height)
{
// make sure the viewport matches the new window dimensions; note that width and
// height will be significantly larger than specified on retina displays.
glViewport(0, 0, width, height);
}

4. Dynamically adjust texture visibility

Use a uniform variable as the third argument to the mix function to change the visibility of both textures, and use the up and down keys to change the visibility of the box or smiley.

texture.fs

#version 330 core
out vec4 FragColor;

in vec3 ourColor;
in vec2 TexCoord;

uniform float mixValue;

//texture sampler
uniform sampler2D textureone;
uniform sampler2D texturetwo;

void main()
{
    FragColor = mix(texture(textureone,TexCoord),texture(texturetwo,vec2(1.0-TexCoord.x,TexCoord.y)),mixValue);
}

main.cpp

#include <glad/glad.h>
#include <GLFW/glfw3.h>

#include <iostream>
#include "stb_image.h"
#include <cmath>
#include "shader.h"
void framebuffer_size_callback(GLFWwindow* window, int width, int height);
void processInput(GLFWwindow* window);

// settings
const unsigned int SCR_WIDTH = 800;
const unsigned int SCR_HEIGHT = 600;

float mixValue = 0.2f;

int main() {

//1.Initialization configuration
glfwInit();
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);

#ifdef __APPLE__
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GLFW_TRUE);
#endif // __APPLE__

//2.gltf window creation
GLFWwindow* window = glfwCreateWindow(SCR_WIDTH, SCR_HEIGHT, "LeranOpenGL", NULL, NULL);
if (window == NULL) {
std::cout << "Failed to create GLFW window" << std::endl;
glfwTerminate();
return -1;
}

glfwMakeContextCurrent(window);
glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);

//3. Load all GL function pointers
if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)) {
std::cout << "Failed to initialize GLAD" << std::endl;
return -1;
}

Shader ourShader("./texture.vs", "./texture.fs");

//4. Set vertex data
float vertices[] = {
// positions // colors // texture coords
0.5f, 0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, // top right
0.5f, -0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, // bottom right
-0.5f, -0.5f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, // bottom left
-0.5f, 0.5f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f // top left
};

unsigned int indices[] = {
0, 1, 3, // first triangle
1, 2, 3 // second triangle
};

unsigned int VBO, VAO, EBO;
glGenVertexArrays(1, & amp;VAO);
glGenBuffers(1, & amp;VBO);
glGenBuffers(1, & amp;EBO);//Element Buffer Object: Element Buffer Object, EBO

glBindVertexArray(VAO);
\t
//Copy the vertex array to the buffer for use by opengl
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);


//Set the vertex attribute pointer
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)0);
glEnableVertexAttribArray(0);
//Set the color attribute pointer
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(3 * sizeof(float)));
glEnableVertexAttribArray(1);
//Set texture attribute pointer
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(6 * sizeof(float)));
glEnableVertexAttribArray(2);

//Load and create texture
unsigned int textureone,texturetwo;
glGenTextures(1, & amp;textureone);
glBindTexture(GL_TEXTURE_2D, textureone);
//Set texture wrapping parameters
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
//Set texture filtering parameters
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

//Load images and generate mipmaps
int width, height, nrChannels;
stbi_set_flip_vertically_on_load(true);
std::string filePath = R"(D:\CPlusProject\LearnOpenGL\DataSet\container.jpg)";
unsigned char* data = stbi_load(filePath.c_str(), & amp;width, & amp;height, & amp;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);


glGenTextures(1, & amp;texturetwo);
glBindTexture(GL_TEXTURE_2D, texturetwo);
//Set texture wrapping parameters
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
//Set texture filtering parameters
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

//Load images and generate mipmaps
filePath = R"(D:\CPlusProject\LearnOpenGL\DataSet\awesomeface.png)";
unsigned char* data2 = stbi_load(filePath.c_str(), & amp;width, & amp;height, & amp;nrChannels, 0);

if (data2) {
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data2);
glGenerateMipmap(GL_TEXTURE_2D);
}
else {
std::cout << "Failed to load texture" << std::endl;
}

stbi_image_free(data2);


\t
ourShader.use();
glUniform1i(glGetUniformLocation(ourShader.ID, "textureone"), 0);//Choose one of the two
ourShader.setInt("texturetwo", 1);//Choose one of the two

//5. Loop rendering
while (!glfwWindowShouldClose(window)) {
processInput(window);

// render
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
//Bind texture
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, textureone);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, texturetwo);

ourShader.setFloat("mixValue", mixValue);

ourShader.use();
glBindVertexArray(VAO);
glDrawElements(GL_TRIANGLES,6,GL_UNSIGNED_INT,0);

glfwSwapBuffers(window);
glfwPollEvents();

}

glDeleteVertexArrays(1, & amp;VAO);
glDeleteBuffers(1, & amp;VBO);
glDeleteBuffers(1, & amp;EBO);

glfwTerminate();
return 0;

}

// process all input: query GLFW whether relevant keys are pressed/released this frame and react accordingly
//------------------------------------------------ -------------------------------------------------- -------
void processInput(GLFWwindow* window)
{
if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
glfwSetWindowShouldClose(window, true);

if (glfwGetKey(window, GLFW_KEY_UP) == GLFW_PRESS) {
std::cout << "up" << std::endl;
mixValue + = 0.001f;
if (mixValue >= 1.0f) {
mixValue = 1.0f;
}
}

if (glfwGetKey(window, GLFW_KEY_DOWN) == GLFW_PRESS)
{
std::cout << "down" << std::endl;
mixValue -= 0.001f; // change this value accordingly (might be too slow or too fast based on system hardware)
if (mixValue <= 0.0f)
mixValue = 0.0f;
}
std::cout << "mixValue:" << mixValue <<std::endl;
}

// glfw: whenever the window size changed (by OS or user resize) this callback function executes
//------------------------------------------------ ----------------------------------------
void framebuffer_size_callback(GLFWwindow* window, int width, int height)
{
// make sure the viewport matches the new window dimensions; note that width and
// height will be significantly larger than specified on retina displays.
glViewport(0, 0, width, height);
}

Texture – LearnOpenGL CN (learnopengl-cn.github.io)