第五课,OpenGL图像变换
glm 下载&环境配置
GLM常⽤函数及使⽤
引⾃
头⽂件
GLM对于矩阵数据类型的定义位于glm/glm.hpp头⽂件中。
⽣成变换矩阵的函数位于glm/gtc/matrix_transform.hpp头⽂件中。
⽣成投影矩阵的函数位于glm/ext/matrix_clip_space.hpp头⽂件中。
将数组转换成矩阵的函数位于头⽂件glm/gtc/type_ptr.hpp中。
glm::value_ptr函数位于头⽂件glm/gtc/type_ptr.hpp中
GLM常⽤函数
glm::radians()
⾓度制转弧度制,可应⽤于glm::rotate()中。
glm::translate()
返回⼀个平移矩阵,第⼀个参数是⽬标矩阵,第⼆个参数是平移的⽅向向量。
glm::rotate()
返回⼀个将点绕某个轴逆时针旋转⼀定弧度的旋转矩阵,第⼀个参数是弧度,第⼆个参数是旋转轴。
glm::scale()
返回⼀个缩放矩阵,第⼀个参数是⽬标矩阵,第⼆个参数是在各坐标轴上的缩放系数。
glm::ortho(float left, float right, float bottom, float top, float zNear, float zFar);
正交投影矩阵。前四个参数分别是视⼝的左、右、上、下坐标。第五和第六个参数则定义了近平⾯和远平⾯的距离。
glm::perspective(float fovy, float aspect, float zNear, float zFar);
透视投影矩阵。第⼀个参数为视锥上下⾯之间的夹⾓,第⼆个参数为视⼝宽⾼⽐,第三、四个参数分别为近平⾯和远平⾯的深度。glm::value_ptr()
传⼊⼀个矩阵,返回⼀个数组。
glm的使⽤详解
1.设置变化矩阵
平移
transform = glm::translate(transform, glm::vec3(0.5f,-0.5f,0.0f));
glm::translate() 返回⼀个平移矩阵,第⼀个参数是⽬标矩阵,第⼆个参数是平移的⽅向向量。
顶点的范围为[-1.0,1.0]。
glm::vec3(0.5f, -0.5f, 0.0f)表⽰:将所有x轴顶点+0.5f , 所有y轴顶点-0.5f,z轴不变。
旋转
transform = glm::rotate(transform,(float)glfwGetTime(), glm::vec3(0.0f,0.0f,1.0f));
glm::rotate() 返回⼀个将点绕某个轴逆时针旋转⼀定弧度的旋转矩阵,第⼆个参数是弧度(glm::radians() ⾓度制转弧度制),第三个参数是旋转轴(起点为(0.0.0)的向量)。
缩放
glm::scale 这个函数⼀般⽤于将物体进⾏缩放
transform = glm::scale(transform, glm::vec3(0.5,0.5,0.5));
第⼆个参数三维向量表⽰对xyz轴的缩⼩倍数。⼤于1为缩⼩,⼩于1为扩⼤。
2.传⼊变化矩阵
PVPCShader.setMat4("transform", transform);
⾃定义shader函数,原函数为:
void Shader::setMat4(const std::string& name,const glm::mat4& mat)const{
glUniformMatrix4fv(glGetUniformLocation(ID, name.c_str()),1, GL_FALSE,&mat[0][0]);
}
第三个参数询问我们我们是否希望对我们的矩阵进⾏置换(Transpose),也就是说交换我们矩阵的⾏和列。该步将transfrom变化矩阵传⼊顶点着⾊器中名为transform的四阶矩阵。
3.在顶点着⾊器中使⽤变化矩阵
gl_Position = transform *vec4(aPos,1.0);
将变化矩阵与各顶点相乘。即可。
避免影响其他管道的运⾏
可将tranform初始化为单位矩阵
.vs
uniform mat4 transform ={{1,0,0,0},{0,1,0,0},{0,0,1,0},{0,0,0,1}};
否则将必须在使⽤该顶点着⾊器的所有管线前添加uniform初值。
transform = glm::mat4(1.0f);
ChangingColorShader.setMat4("transform", transform);
rotate属性全部代码
main.cpp
#include<iostream>
//包含命名空间std
#include<glad/glad.h>
#include<GLFW/glfw3.h>
//glad需要在glfw之前,因为GLAD的头⽂件包含了正确的OpenGL头⽂件,glfw依赖于OpenGL
//glm
#include<glm/glm.hpp>
#include<glm/gtc/matrix_transform.hpp>
#include<glm/gtc/type_ptr.hpp>
/
/stb_image
#define STB_IMAGE_IMPLEMENTATION
#include"stb_image.h"
//⾃定义
#include"Shader.h"//着⾊器设置
#include"call_back.h"//回调函数设置
int main(){
glfwInit();
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR,3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR,3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
/
/ glfw window creation
//---------------------
GLFWwindow* window =glfwCreateWindow(800,600,"LearnOpenGL",nullptr,nullptr);
if(window ==nullptr){
std::cout <<"Failed to create GLFW window"<< std::endl;
glfwTerminate();
return-1;
}
glfwMakeContextCurrent(window);
glfwSetKeyCallback(window, key_callback);
glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);
/
/glad初始化(GLAD是⽤来管理OpenGL的函数指针的)
//load all OpenGL function pointers
if(!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)){
std::cout <<"Failed to initialize GLAD"<< std::endl;
return-1;
}
设置视⼝
//int width, height;
//glfwGetFramebufferSize(window, &width, &height);
//glViewport(0, 0, width, height);
//⽣成着⾊器
Shader PVPCShader("./Normal.vs","./setcolor.fs");
Shader ChangingColorShader("./Normal.vs","./Changing.fs");
/*
第⼀组数据处理----两个填充三⾓形************************
*/
//添加顶点数据
GLfloat vertices[]={
//location(顶点坐标) color texture coords(纹理坐标)
-1.0f,0.0f,0.0f, 1.0f,0.0f,0.0f,0.0f,2.0f,//左中--左上
-1.0f,-1.0f,0.0f,0.0f,0.0f,1.0f,0.0f,0.0f,//左下--左下
0.0f,-1.0f,0.0f,0.0f,1.0f,0.0f,1.0f,0.0f,//中下--右下
0.0f,0.0f,0.0f,0.3f,0.3f,0.3f,1.0f,2.0f,//居中--右上
-1.0f,0.0f,0.0f, 1.0f,0.0f,0.0f,0.0f,2.0f,//左中--左上
0.0f,-1.0f,0.0f,0.0f,1.0f,0.0f,1.0f,0.0f,//中下--右下
};
//set up buffers and configure vertex attributes
//设置缓存区配置顶点属性
GLuint VBO, VAO;
glGenBuffers(1,&VBO);//获取⼀个buffer名为VBO
glGenVertexArrays(1,&VAO);// 获取⼀个VertexArrays名为VAO
glBindVertexArray(VAO);//绑定VAO为当前使⽤顶点数组
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER,sizeof(vertices), vertices, GL_STATIC_DRAW); glVertexAttribPointer(0,3, GL_FLOAT, GL_FALSE,8*sizeof(float),(void*)(0)); glEnableVertexAttribArray(0);//启⽤顶点属性,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);
//加载创建纹理
//------------
GLuint texture1;
//texture 1
//-----------
glGenTextures(1,&texture1);
glGenTextures(1,&texture1);
glBindTexture(GL_TEXTURE_2D, texture1);
// set the texture wrapping parameters
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_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_LINEAR);
// load image, create texture and generate mipmaps(纹理映射)
int width, height, nrChannels;
stbi_set_flip_vertically_on_load(true);// y轴翻转纹理
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);
//glTexImage2D(纹理⽬标,多级渐远纹理的级别,储存为何种格式,宽,⾼,0,源图的格式,数据类型,真正的图像数据)
//当前绑定的纹理对象就会被附加上纹理图像。
glGenerateMipmap(GL_TEXTURE_2D);//为当前绑定的纹理⾃动⽣成所有需要的多级渐远纹理。
}
else
{
std::cout <<"Failed to load texture"<< std::endl;
}
stbi_image_free(data);//释放图像的内存
//纹理2
GLuint texture2;
glGenTextures(1,&texture2);//传⼊引⽤,初始化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_MIRRORED_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
//glTexParameteri(纹理维度,改变类型,改变值);
unsigned char* data2 =stbi_load("./awesomeface.png",&width,&height,&nrChannels,0);
if(data2)
{
glTexImage2D(GL_TEXTURE_2D,0, GL_RGBA8, width, height,0, GL_RGBA, GL_UNSIGNED_BYTE, data2);//png格式加载为GL_RGBA格式glGenerateMipmap(GL_TEXTURE_2D);
}
else
{
std::cout <<"Failed to load texture"<< std::endl;
}
stbi_image_free(data2);
// glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
// glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
// glBlendFunc(GL_ONE_MINUS_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
//给纹理采样器分配⼀个位置值(默认纹理单元是0,所以多个纹理单元需要分配)
//OpenGL⾄少保证有16个纹理单元供你使⽤
PVPCShader.use();//激活要绑定的着⾊器后才可分配
PVPCShader.setInt("sampler1",0);//将着⾊器中texture1采样器分配到GL_TEXTURE0
PVPCShader.setInt("sampler2",1);//将着⾊器中texture2采样器分配到GL_TEXTURE1
/*
第⼆组数据处理----两个线框三⾓形************************************
*/
//使⽤索引数据存储点的顺序,⽤IBO索引缓冲对象管理
GLfloat vertices1[]={
0.5f,0.5f,0.0f,// 右上⾓
0.5f,-0.5f,0.0f,// 右下⾓
-0.5f,-0.5f,0.0f,// 左下⾓
-0.5f,-0.5f,0.0f,// 左下⾓
-0.5f,0.5f,0.0f// 左上⾓
};
unsigned int indices1[]={// 注意索引从0开始!
0,1,3,// 第⼀个三⾓形
1,2,3// 第⼆个三⾓形
};
//设置缓存区配置顶点属性
GLuint VBO1,EBO1,VAO1;
//⽣成三类对象,不分先后顺序
glGenBuffers(1,&EBO1);
glGenBuffers(1,&VBO1);
glGenVertexArrays(1,&VAO1);
//绑定三类对象
glBindVertexArray(VAO1);//VAO必须为第⼀
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO1);
glBindBuffer(GL_ARRAY_BUFFER, VBO1);
//绑定缓冲数据
glBufferData(GL_ARRAY_BUFFER,sizeof(vertices1), vertices1, GL_STATIC_DRAW);
glBufferData(GL_ELEMENT_ARRAY_BUFFER,sizeof(indices1), indices1, GL_STATIC_DRAW);
glVertexAttribPointer(0,3, GL_FLOAT, GL_FALSE,3*sizeof(float),(void*)0);
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER,0);
glBindVertexArray(0);
//Loop
while(!glfwWindowShouldClose(window)){//检查glfw是否被要求退出//
glfwPollEvents();
//检查有没有触发什么事件,然后调⽤对应的回调函数.
glClearColor(0.2f,0.3f,0.3f,1.0f);
glClear(GL_COLOR_BUFFER_BIT);
PVPCShader.use();
glActiveTexture(GL_TEXTURE0);// 在绑定纹理之前先激活纹理单元
glBindTexture(GL_TEXTURE_2D, texture1);//绑定这个纹理到当前激活的纹理单元
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, texture2);
// create transformations
glm::mat4 transform = glm::mat4(1.0f);// make sure to initialize matrix to identity matrix first //transform = glm::translate(transform, glm::vec3(0.5f, -0.5f, 0.0f));
//glm::translate() 返回⼀个平移矩阵,第⼀个参数是⽬标矩阵,第⼆个参数是平移的⽅向向量。
transform = glm::rotate(transform,(float)glfwGetTime(), glm::vec3(0.0f,0.0f,1.0f));
//glm::rotate() 返回⼀个将点绕某个轴逆时针旋转⼀定弧度的旋转矩阵,第⼀个参数是弧度,第⼆个参数是旋转轴。 transform = glm::scale(transform, glm::vec3(0.5,0.5,0.5));
// get matrix's uniform location and set matrix
PVPCShader.setMat4("transform", transform);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
//glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
//glBlendFunc(GL_ONE_MINUS_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);//设置为填充模式(默认)
glBindVertexArray(VAO);
glDrawArrays(GL_TRIANGLES,0,2*3);//数量必须为3的倍数
glDisable(GL_BLEND);
float timeValue =glfwGetTime();
float greenValue =(sin(timeValue)/2.0f)+0.5f;
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论