11°

OpenGL的变换实例

一个图像的变换:

#define STB_IMAGE_IMPLEMENTATION
#include <glad/glad.h>
#include <GLFW/glfw3.h>
#include <STB_IMAGE/stb_image.h>
#include<glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
#include <Shader/shader_s.h>

#include <iostream>

float mixValue = 0.2f; 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() { // 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

GLFWwindow* window = glfwCreateWindow(SCR_WIDTH, SCR_HEIGHT, "LearnOpenGL", NULL, NULL);
if (window == NULL)
{
	std::cout &lt;&lt; "Failed to create GLFW window" &lt;&lt; std::endl;
	glfwTerminate();
	return -1;
}
glfwMakeContextCurrent(window);
glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);

// glad: load all OpenGL function pointers
if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
{
	std::cout &lt;&lt; "Failed to initialize GLAD" &lt;&lt; std::endl;
	return -1;
}

// build and compile our shader zprogram
Shader ourShader("4.1.texture.vs", "4.1.texture.fs");


float vertices[] = {
	// positions          // colors           // texture coords (note that we changed them to 2.0f!)
	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);

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

// 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;
glGenTextures(1, &amp;texture1);
glBindTexture(GL_TEXTURE_2D, texture1); 

// 为当前绑定的纹理对象设置环绕、过滤方式
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_MIRRORED_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_MIRRORED_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 image, create texture and generate mipmaps
int width, height, nrChannels;
//OpenGL要求y轴0.0坐标是在图片的底部的,但是图片的y轴0.0坐标通常在顶部,故需要倒置
stbi_set_flip_vertically_on_load(true);
//将图片载入生成一个纹理
unsigned char *data1 = stbi_load("F:/C++项目/LibsInclude/src/container.jpg", &amp;width, &amp;height, &amp;nrChannels, 0);
if (data1)
{
	//生成纹理
	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, data1);
	//当前绑定的纹理自动生成所有需要的多级渐远纹理
	glGenerateMipmap(GL_TEXTURE_2D);
}
else
{
	std::cout &lt;&lt; "Failed to load texture" &lt;&lt; std::endl;
}
//释放图像内存
stbi_image_free(data1);


//生成第二个纹理
glGenTextures(1, &amp;texture2);
glBindTexture(GL_TEXTURE_2D, texture2);


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);
data1 = stbi_load("F:/C++项目/LibsInclude/src/face1.jpeg", &amp;width, &amp;height, &amp;nrChannels, 0);
if (data1)
{
	//生成纹理
	//笑脸图片有a通道glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);//参数设置为GL_RGBA
	//第一个参数指定了纹理目标(Target)。设置为GL_TEXTURE_2D意味着会生成与当前绑定的纹理对象在同一个目标上的纹理(任何绑定到GL_TEXTURE_1D和GL_TEXTURE_3D的纹理不会受到影响)。
	//第二个参数为纹理指定多级渐远纹理的级别,如果你希望单独手动设置每个多级渐远纹理的级别的话。这里我们填0,也就是基本级别。
	//第三个参数告诉OpenGL我们希望把纹理储存为何种格式。我们的图像只有RGB值,因此我们也把纹理储存为RGB值。
	//第四个和第五个参数设置最终的纹理的宽度和高度。我们之前加载图像的时候储存了它们,所以我们使用对应的变量。
	//下个参数应该总是被设为0(历史遗留的问题)。
	//第七第八个参数定义了源图的格式和数据类型。我们使用RGB值加载这个图像,并把它们储存为char(byte)数组,我们将会传入对应值。
	//最后一个参数是真正的图像数据。
	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, data1);
	//当前绑定的纹理自动生成所有需要的多级渐远纹理
	glGenerateMipmap(GL_TEXTURE_2D);
}
else
{
	std::cout &lt;&lt; "Failed to load texture" &lt;&lt; std::endl;
}
//释放图像内存
stbi_image_free(data1);


//将着色器采样器与纹理单元进行联系在一起
//设置每个采样器的方式告诉OpenGL每个着色器采样器属于哪个纹理单元
//在设置uniform1前先激活着色器
ourShader.use(); 

//设置uniform值
//texture1着色器采样器接受第一个纹理单元(三种表达方式)
//glUniform1i(glGetUniformLocation(ourShader.ID, "texture1"), 0);
//或者
//ourShader.setInt("texture1", 0);
glUniform1i(glGetUniformLocation(ourShader.ID, "texture1"), GL_TEXTURE0 - GL_TEXTURE0);
//texture2着色器采样器接受第二个纹理单元(三种表达方式)
glUniform1i(glGetUniformLocation(ourShader.ID, "texture2"), GL_TEXTURE1 - GL_TEXTURE0);


// render loop
// -----------
while (!glfwWindowShouldClose(window))
{

	processInput(window);

	glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
	glClear(GL_COLOR_BUFFER_BIT);


	//在纹理单元的状态下,将采样器绑定
	// bind Texture:会自动把纹理赋值给片段着色器的采样器
	//先激活纹理单元,然后再绑定,若只有一个纹理单元,默认激活状态
	//GL_TEXTURE0:就是一个纹理单元,是按顺序定义的,OpenGL至少保证有16个纹理单元
	//texture1:代表着色器采样器
	glActiveTexture(GL_TEXTURE0);
	//会绑定这个纹理到当前激活的纹理单元,于是就将纹理和纹理单元联系在一起了
	glBindTexture(GL_TEXTURE_2D, texture1);
	glActiveTexture(GL_TEXTURE1);
	glBindTexture(GL_TEXTURE_2D, texture2);


	// set the texture mix value in the shader
	ourShader.setFloat("mixValue", mixValue);
	glm::mat4 transform = glm::mat4(1.0f); 
	transform = glm::translate(transform, glm::vec3(0.2f, 0.2f, 0.0f));
	transform = glm::rotate(transform, (float)glfwGetTime(), glm::vec3(0.0f, 0.0f, 1.0f));
	// render container
	ourShader.use();
	glUniformMatrix4fv(glGetUniformLocation(ourShader.ID, "transform"), 1, GL_FALSE, glm::value_ptr(transform));


	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;

}

void processInput(GLFWwindow *window) { if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS) glfwSetWindowShouldClose(window, true);

if (glfwGetKey(window, GLFW_KEY_UP) == GLFW_PRESS)
{
	mixValue += 0.001f; // change this value accordingly (might be too slow or too fast based on system hardware)
	if (mixValue &gt;= 1.0f)
		mixValue = 1.0f;
}
if (glfwGetKey(window, GLFW_KEY_DOWN) == GLFW_PRESS)
{
	mixValue -= 0.001f; // change this value accordingly (might be too slow or too fast based on system hardware)
	if (mixValue &lt;= 0.0f)
		mixValue = 0.0f;
}

}

void framebuffer_size_callback(GLFWwindow* window, int width, int height) { glViewport(0, 0, width, height); }

结果:

两个的变换:

#define STB_IMAGE_IMPLEMENTATION
#include <glad/glad.h>
#include <GLFW/glfw3.h>
#include <STB_IMAGE/stb_image.h>
#include<glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
#include <Shader/shader_s.h>

#include <iostream>

float mixValue = 0.2f; 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() { // 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

GLFWwindow* window = glfwCreateWindow(SCR_WIDTH, SCR_HEIGHT, "LearnOpenGL", NULL, NULL);
if (window == NULL)
{
	std::cout &lt;&lt; "Failed to create GLFW window" &lt;&lt; std::endl;
	glfwTerminate();
	return -1;
}
glfwMakeContextCurrent(window);
glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);

// glad: load all OpenGL function pointers
if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
{
	std::cout &lt;&lt; "Failed to initialize GLAD" &lt;&lt; std::endl;
	return -1;
}

// build and compile our shader zprogram
Shader ourShader("4.1.texture.vs", "4.1.texture.fs");


float vertices[] = {
	// positions          // colors           // texture coords (note that we changed them to 2.0f!)
	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);

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

// 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;
glGenTextures(1, &amp;texture1);
glBindTexture(GL_TEXTURE_2D, texture1); 

// 为当前绑定的纹理对象设置环绕、过滤方式
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_MIRRORED_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_MIRRORED_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 image, create texture and generate mipmaps
int width, height, nrChannels;
//OpenGL要求y轴0.0坐标是在图片的底部的,但是图片的y轴0.0坐标通常在顶部,故需要倒置
stbi_set_flip_vertically_on_load(true);
//将图片载入生成一个纹理
unsigned char *data1 = stbi_load("F:/C++项目/LibsInclude/src/container.jpg", &amp;width, &amp;height, &amp;nrChannels, 0);
if (data1)
{
	//生成纹理
	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, data1);
	//当前绑定的纹理自动生成所有需要的多级渐远纹理
	glGenerateMipmap(GL_TEXTURE_2D);
}
else
{
	std::cout &lt;&lt; "Failed to load texture" &lt;&lt; std::endl;
}
//释放图像内存
stbi_image_free(data1);


//生成第二个纹理
glGenTextures(1, &amp;texture2);
glBindTexture(GL_TEXTURE_2D, texture2);


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);
data1 = stbi_load("F:/C++项目/LibsInclude/src/face1.jpeg", &amp;width, &amp;height, &amp;nrChannels, 0);
if (data1)
{
	//生成纹理
	//笑脸图片有a通道glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);//参数设置为GL_RGBA
	//第一个参数指定了纹理目标(Target)。设置为GL_TEXTURE_2D意味着会生成与当前绑定的纹理对象在同一个目标上的纹理(任何绑定到GL_TEXTURE_1D和GL_TEXTURE_3D的纹理不会受到影响)。
	//第二个参数为纹理指定多级渐远纹理的级别,如果你希望单独手动设置每个多级渐远纹理的级别的话。这里我们填0,也就是基本级别。
	//第三个参数告诉OpenGL我们希望把纹理储存为何种格式。我们的图像只有RGB值,因此我们也把纹理储存为RGB值。
	//第四个和第五个参数设置最终的纹理的宽度和高度。我们之前加载图像的时候储存了它们,所以我们使用对应的变量。
	//下个参数应该总是被设为0(历史遗留的问题)。
	//第七第八个参数定义了源图的格式和数据类型。我们使用RGB值加载这个图像,并把它们储存为char(byte)数组,我们将会传入对应值。
	//最后一个参数是真正的图像数据。
	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, data1);
	//当前绑定的纹理自动生成所有需要的多级渐远纹理
	glGenerateMipmap(GL_TEXTURE_2D);
}
else
{
	std::cout &lt;&lt; "Failed to load texture" &lt;&lt; std::endl;
}
//释放图像内存
stbi_image_free(data1);


//将着色器采样器与纹理单元进行联系在一起
//设置每个采样器的方式告诉OpenGL每个着色器采样器属于哪个纹理单元
//在设置uniform1前先激活着色器
ourShader.use(); 

//设置uniform值
//texture1着色器采样器接受第一个纹理单元(三种表达方式)
//glUniform1i(glGetUniformLocation(ourShader.ID, "texture1"), 0);
//或者
//ourShader.setInt("texture1", 0);
glUniform1i(glGetUniformLocation(ourShader.ID, "texture1"), GL_TEXTURE0 - GL_TEXTURE0);
//texture2着色器采样器接受第二个纹理单元(三种表达方式)
glUniform1i(glGetUniformLocation(ourShader.ID, "texture2"), GL_TEXTURE1 - GL_TEXTURE0);


// render loop
// -----------
while (!glfwWindowShouldClose(window))
{

	processInput(window);

	glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
	glClear(GL_COLOR_BUFFER_BIT);


	//在纹理单元的状态下,将采样器绑定
	// bind Texture:会自动把纹理赋值给片段着色器的采样器
	//先激活纹理单元,然后再绑定,若只有一个纹理单元,默认激活状态
	//GL_TEXTURE0:就是一个纹理单元,是按顺序定义的,OpenGL至少保证有16个纹理单元
	//texture1:代表着色器采样器
	glActiveTexture(GL_TEXTURE0);
	//会绑定这个纹理到当前激活的纹理单元,于是就将纹理和纹理单元联系在一起了
	glBindTexture(GL_TEXTURE_2D, texture1);
	glActiveTexture(GL_TEXTURE1);
	glBindTexture(GL_TEXTURE_2D, texture2);


	// set the texture mix value in the shader
	ourShader.setFloat("mixValue", mixValue);

	glm::mat4 transform = glm::mat4(1.0f); 
	transform = glm::rotate(transform, (float)glfwGetTime(), glm::vec3(0.0f, 0.0f, 1.0f));
	ourShader.use();
	unsigned int transformLoc = glGetUniformLocation(ourShader.ID, "transform");
	glUniformMatrix4fv(transformLoc, 1, GL_FALSE, glm::value_ptr(transform));

	glBindVertexArray(VAO);
	glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);


	transform = glm::mat4(1.0f); // reset it to identity matrix
	transform = glm::translate(transform, glm::vec3(-0.5f, 0.5f, 0.0f));
	float scaleAmount = sin(glfwGetTime());
	transform = glm::scale(transform, glm::vec3(scaleAmount, scaleAmount, scaleAmount));
	ourShader.use();
	glUniformMatrix4fv(transformLoc, 1, GL_FALSE, &amp;transform[0][0]); 
	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;

}

void processInput(GLFWwindow *window) { if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS) glfwSetWindowShouldClose(window, true);

if (glfwGetKey(window, GLFW_KEY_UP) == GLFW_PRESS)
{
	mixValue += 0.001f; // change this value accordingly (might be too slow or too fast based on system hardware)
	if (mixValue &gt;= 1.0f)
		mixValue = 1.0f;
}
if (glfwGetKey(window, GLFW_KEY_DOWN) == GLFW_PRESS)
{
	mixValue -= 0.001f; // change this value accordingly (might be too slow or too fast based on system hardware)
	if (mixValue &lt;= 0.0f)
		mixValue = 0.0f;
}

}

void framebuffer_size_callback(GLFWwindow* window, int width, int height) { glViewport(0, 0, width, height); }

结果:

 

本文由【黑白双键】发布于开源中国,原文链接:https://my.oschina.net/1024and1314/blog/3135923

全部评论: 0

    我有话说: