说明:本系列视频使用 mac平台的Xcode来实现,windows平台和Linux平台与之类似。
1 程序功能简介
主要是通过实战 理解双重纹理。上图中的纹理由下面两张纹理混合各50%构成,如下:
2 程序代码-双重纹理
2.1 核心源码
#include <glad/glad.h>
#include <GLFW/glfw3.h>
#include <iostream>
#include <learnopengl/filesystem.h>
#include <cmath>
#include <stb_image.h>
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
//===================macro & header process start===================
//triangle draw test
#include <learnopengl/shader_s.h>
//===================macro & header process end===================
#define SHADER_ROOT_DIR "/Users/wangdaosheng/Desktop/X-Project/AGS_Repository/OpenGL/OpenGL-demo/openGLtest1/shader/"
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.1 glfw: initialize and configure---------------------
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, GL_TRUE); // uncomment this statement to fix compilation on OS X
#endif
// @1.2 glfw window creation---------------------
GLFWwindow* window = glfwCreateWindow(SCR_WIDTH, SCR_HEIGHT, "DaoshengOpenGL", NULL, NULL);
if (window == NULL)
{
std::cout << "Failed to create GLFW window" << std::endl;
glfwTerminate();
return -1;
}
glfwMakeContextCurrent(window);
glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);
// @1.3 glad: load all OpenGL function pointers---------------------
if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
{
std::cout << "Failed to initialize GLAD" << std::endl;
return -1;
}
// @2 shader op
Shader texture_box_Shader(SHADER_ROOT_DIR"texture.vs", SHADER_ROOT_DIR"texture.fs");
float texture_box_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 texture_box_indices[] = {
0, 1, 3, // first triangle
1, 2, 3 // second triangle
};
unsigned int texture_box_VBO, texture_box_VAO, texture_box_EBO;
glGenVertexArrays(1, &texture_box_VAO);
glGenBuffers(1, &texture_box_VBO);
glGenBuffers(1, &texture_box_EBO);
glBindVertexArray(texture_box_VAO);
glBindBuffer(GL_ARRAY_BUFFER, texture_box_VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(texture_box_vertices), texture_box_vertices, GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, texture_box_EBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(texture_box_indices), texture_box_indices, GL_STATIC_DRAW);
// position attribute
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)0);
glEnableVertexAttribArray(0);
// color attribute
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(3 * sizeof(float)));
glEnableVertexAttribArray(1);
// texture coord attribute
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(6 * sizeof(float)));
glEnableVertexAttribArray(2);
unsigned int texture1,texture2;
int width,height,nrChannels;
//texture1 op start
glGenTextures(1, &texture1);
glBindTexture(GL_TEXTURE_2D, texture1); // all upcoming GL_TEXTURE_2D operations now have effect on this texture object
// set the texture wrapping parameters
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); // set texture wrapping to GL_REPEAT (default wrapping method)
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);
stbi_set_flip_vertically_on_load(true); // tell stb_image.h to flip loaded texture's on the y-axis.
unsigned char *texture1_data = stbi_load(FileSystem::getPath("resources/textures/container.jpg").c_str(), &width, &height, &nrChannels, 0);
if (texture1_data)
{
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, texture1_data);
glGenerateMipmap(GL_TEXTURE_2D);
}
else
{
std::cout << "Failed to load texture1" << std::endl;
}
stbi_image_free(texture1_data);
//texture1 op end
//texture2 op start
glGenTextures(1, &texture2);
glBindTexture(GL_TEXTURE_2D, texture2); // all upcoming GL_TEXTURE_2D operations now have effect on this texture object
// set the texture wrapping parameters
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); // set texture wrapping to GL_REPEAT (default wrapping method)
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);
stbi_set_flip_vertically_on_load(true); // tell stb_image.h to flip loaded texture's on the y-axis.
unsigned char *texture2_data = stbi_load(FileSystem::getPath("resources/textures/brickwall_normal.jpg").c_str(), &width, &height, &nrChannels, 0);
if (texture2_data)
{
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, texture2_data);
glGenerateMipmap(GL_TEXTURE_2D);
}
else
{
std::cout << "Failed to load texture2" << std::endl;
}
stbi_image_free(texture2_data);
//texture2 op end
// render loop
while (!glfwWindowShouldClose(window))
{
// input process
processInput(window);
// render process
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
texture_box_Shader.use();
// render container
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texture1);
glUniform1i(glGetUniformLocation(texture_box_Shader.getID(), "texture1"), 0);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, texture2);
glUniform1i(glGetUniformLocation(texture_box_Shader.getID(), "texture2"), 1);
glBindVertexArray(texture_box_VAO);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
glBindVertexArray(0);
// glfw: swap buffers and poll IO events (keys pressed/released, mouse moved etc.)
glfwSwapBuffers(window);
glfwPollEvents();
}
// optional: de-allocate all resources once they've outlived their purpose:
glDeleteVertexArrays(1, &texture_box_VAO);
glDeleteBuffers(1, &texture_box_VBO);
glDeleteBuffers(1, &texture_box_EBO);
glfwTerminate(); // glfw: terminate, clearing all previously allocated GLFW resources.
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);
}
2.2 关键头文件
参考上一章节OpenGL基础(10)纹理四边形 源码&显示效果即可。
2.3 纹理代码
@1 texture.vs 顶点着色器代码
#version 330 core
layout (location = 0) in vec3 aPos;
layout (location = 1) in vec3 aColor;
layout (location = 2) in vec2 aTexCoord;
out vec3 ourColor;
out vec2 TexCoord;
void main()
{
gl_Position = vec4(aPos, 1.0);
ourColor = aColor;
TexCoord = vec2(aTexCoord.x, aTexCoord.y);
}
@1 texture.fs 片段着色器代码
#version 330 core
out vec4 FragColor;
in vec3 ourColor;
in vec2 TexCoord;
// texture sampler
uniform sampler2D texture1;
uniform sampler2D texture2;
void main()
{
FragColor = mix(texture(texture1, TexCoord), texture(texture2, TexCoord), 0.5);
}
该系列文章主要参考openGL官网 和学习 learnopenGL官网 进行知识体系的梳理和重构,重在形成自己对openGL知识的理解和知识体系。
- 参考相关链接总站:https://learnopengl-cn.readthedocs.io/zh/latest/
- 参考OpenGL官网:https://www.opengl.org/about/
- 同时也参考了网上其他内容知识 进而 进行整合。