(十六)视图变换 正交投影 透视投影

视图变换

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

代码实验

#include <glad/glad.h>//glad必须在glfw头文件之前包含
#include <GLFW/glfw3.h>
#include <iostream>
#define STB_IMAGE_IMPLEMENTATION
#include "stb_image.h"

//GLM
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
#define GLM_ENABLE_EXPERIMENTAL
#include <glm/gtx/string_cast.hpp>

void frameBufferSizeCallbakc(GLFWwindow* window, int width, int height)
{
	glViewport(0, 0, width, height);
}
void glfwKeyCallback(GLFWwindow* window, int key, int scancode, int action, int mods)
{
}

GLuint program = 0;
GLuint vao = 0;
GLuint texture = 0;
glm::mat4 transform(1.0f);//4×4单位矩阵
glm::mat4 viewMatrix(1.0f);

void prepareCamera()
{
	//lookat:生成一个viewMatrix
	//eye:当前摄像机所在的位置
	//center:当前摄像机看向的那个点
	//up:穹顶向量
	viewMatrix = glm::lookAt(glm::vec3(0.5f, 0.0f, 0.5f), glm::vec3(0.5f, 0.0f, 0.0f), glm::vec3(0.0f, 1.0f, 0.0f));
}
void prepareVAO()
{
	//positions
	float positions[] = {
		-0.5f, -0.5f, 0.0f,
		0.5f, -0.5f, 0.0f,
		0.0f,  0.5f, 0.0f,
	};
	//颜色
	float colors[] = {
		1.0f, 0.0f,0.0f,
		0.0f, 1.0f,0.0f,
		0.0f, 0.0f,1.0f
	};
	//索引
	unsigned int indices[] = {
		0, 1, 2,
	};
	//uv坐标
	float uvs[] = {
		0.0f, 0.0f,
		1.0f, 0.0f,
		0.5f, 1.0f,
	};

	//2 VBO创建
	GLuint posVbo = 0;
	GLuint colorVbo = 0;
	GLuint uvVbo = 0;
	glGenBuffers(1, &posVbo);
	glBindBuffer(GL_ARRAY_BUFFER, posVbo);
	glBufferData(GL_ARRAY_BUFFER, sizeof(positions), positions, GL_STATIC_DRAW);

	glGenBuffers(1, &colorVbo);
	glBindBuffer(GL_ARRAY_BUFFER, colorVbo);
	glBufferData(GL_ARRAY_BUFFER, sizeof(colors), colors, GL_STATIC_DRAW);

	glGenBuffers(1, &uvVbo);
	glBindBuffer(GL_ARRAY_BUFFER, uvVbo);
	glBufferData(GL_ARRAY_BUFFER, sizeof(uvs), uvs, GL_STATIC_DRAW);

	//3 EBO创建
	GLuint ebo = 0;
	glGenBuffers(1, &ebo);
	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);
	glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);

	//4 VAO创建
	vao = 0;
	glGenVertexArrays(1, &vao);
	glBindVertexArray(vao);

	//5 绑定vbo ebo 加入属性描述信息
	//5.1 加入位置属性描述信息
	glBindBuffer(GL_ARRAY_BUFFER, posVbo);
	glEnableVertexAttribArray(0);
	glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);

	//5.2 加入颜色属性描述信息
	glBindBuffer(GL_ARRAY_BUFFER, colorVbo);
	glEnableVertexAttribArray(1);
	glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);

	//5.3 加入uv属性描述数据
	glBindBuffer(GL_ARRAY_BUFFER, uvVbo);
	glEnableVertexAttribArray(2);
	glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(float), (void*)0);

	//5.2 加入ebo到当前的vao
	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);

	glBindVertexArray(0);
}
void prepareShader() {
	//1 完成vs与fs的源代码,并且装入字符串
	//aPos作为attribute(属性)传入shader不允许更改的
	const char* vertexShaderSource =
		"#version 330 core\n"
		"layout (location = 0) in vec3 aPos;\n"
		"layout (location = 1) in vec3 aColor;\n"
		"layout (location = 2) in vec2 aUV;\n"
		"out vec3 color;\n"
		"out vec2 uv;\n"
		"uniform mat4 transform;\n"
		"uniform mat4 viewMatrix;\n"
		"void main()\n"
		"{\n"
		"   vec4 position = vec4(aPos, 1.0);\n"
		"   position = viewMatrix * transform * position;\n"
		"   gl_Position = position;\n"
		"   color = aColor;\n"
		"   uv = aUV;\n"
		"}\0";
	const char* fragmentShaderSource =
		"#version 330 core\n"
		"out vec4 FragColor;\n"
		"in vec3 color;\n"
		"in vec2 uv;\n"
		"uniform sampler2D sampler;\n"
		"void main()\n"
		"{\n"
		"   FragColor = texture(sampler, uv);\n"
		"}\n\0";


	//2 创建Shader程序(vs、fs)
	GLuint vertex, fragment;
	vertex = glCreateShader(GL_VERTEX_SHADER);
	fragment = glCreateShader(GL_FRAGMENT_SHADER);


	//3 为shader程序输入shader代码
	glShaderSource(vertex, 1, &vertexShaderSource, NULL);
	glShaderSource(fragment, 1, &fragmentShaderSource, NULL);

	int success = 0;
	char infoLog[1024];
	//4 执行shader代码编译 
	glCompileShader(vertex);
	//检查vertex编译结果
	glGetShaderiv(vertex, GL_COMPILE_STATUS, &success);
	if (!success) {
		glGetShaderInfoLog(vertex, 1024, NULL, infoLog);
		std::cout << "Error: SHADER COMPILE ERROR --VERTEX" << "\n" << infoLog << std::endl;
	}

	glCompileShader(fragment);
	//检查fragment编译结果
	glGetShaderiv(fragment, GL_COMPILE_STATUS, &success);
	if (!success) {
		glGetShaderInfoLog(fragment, 1024, NULL, infoLog);
		std::cout << "Error: SHADER COMPILE ERROR --FRAGMENT" << "\n" << infoLog << std::endl;
	}

	//5 创建一个Program壳子
	program = glCreateProgram();

	//6 将vs与fs编译好的结果放到program这个壳子里
	glAttachShader(program, vertex);
	glAttachShader(program, fragment);

	//7 执行program的链接操作,形成最终可执行shader程序
	glLinkProgram(program);

	//检查链接错误
	glGetProgramiv(program, GL_LINK_STATUS, &success);
	if (!success) {
		glGetProgramInfoLog(program, 1024, NULL, infoLog);
		std::cout << "Error: SHADER LINK ERROR " << "\n" << infoLog << std::endl;
	}

	//清理
	glDeleteShader(vertex);
	glDeleteShader(fragment);
}

void prepareTextrue()
{
	//1 stbImage 读取图片
	int width, height, channels;
	//--反转y轴
	stbi_set_flip_vertically_on_load(true);
	unsigned char* data = stbi_load("goku.jpg", &width, &height, &channels, STBI_rgb_alpha);

	//2 生成纹理并且激活单元绑定
	glGenTextures(1, &texture);
	//--激活纹理单元--
	glActiveTexture(GL_TEXTURE0);
	//--绑定纹理对象--
	glBindTexture(GL_TEXTURE_2D, texture);

	//3 传输纹理数据,开辟显存
	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);

	//***释放数据
	stbi_image_free(data);

	//4 设置纹理的过滤方式
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);

	//5 设置纹理的包裹方式
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);//u
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);//v
}

void render()
{
	//执行opengl画布清理操作
	glClear(GL_COLOR_BUFFER_BIT);

	//1.绑定当前的program
	glUseProgram(program);

	//2 更新Uniform的时候,一定要先UserProgram
	//2.1 通过名称拿到Uniform变量的位置Location
	GLint location = glGetUniformLocation(program, "sampler");
	//2.2 通过Location更新Uniform变量的值
	glUniform1f(location, 0);

	GLint locationTransform = glGetUniformLocation(program, "transform");
	//transpose参数:表示是否对传输进去的矩阵数据进行转置
	glUniformMatrix4fv(locationTransform, 1, GL_FALSE, glm::value_ptr(transform));

	GLint locationviewMatrix = glGetUniformLocation(program, "viewMatrix");
	//transpose参数:表示是否对传输进去的矩阵数据进行转置
	glUniformMatrix4fv(locationviewMatrix, 1, GL_FALSE, glm::value_ptr(viewMatrix));

	//3 绑定当前的vao
	glBindVertexArray(vao);
	//4 发出绘制指令
	//glDrawArrays(GL_TRIANGLE_STRIP, 0, 6);
	glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_INT, 0);
}


int main()
{
	//初始化glfw环境
	glfwInit();
	//设置opengl主版本号
	glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
	//设置opengl次版本号
	glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
	//设置opengl启用核心模式
	glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);

	//创建窗体对象
	GLFWwindow* window = glfwCreateWindow(800, 600, "lenarnOpenGL", nullptr, nullptr);
	//设置当前窗体对象为opengl的绘制舞台
	glfwMakeContextCurrent(window);
	//窗体大小回调
	glfwSetFramebufferSizeCallback(window, frameBufferSizeCallbakc);
	//键盘相应回调
	glfwSetKeyCallback(window, glfwKeyCallback);

	//使用glad加载所有当前版本opengl的函数
	if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
	{
		std::cout << "初始化glad失败" << std::endl;
		return -1;
	}
	;
	//设置opengl视口大小和清理颜色
	glViewport(0, 0, 800, 600);
	glClearColor(0.2f, 0.3f, 0.3f, 1.0f);

	//shader
	prepareShader();
	//vao
	prepareVAO();
	//texture
	prepareTextrue();
	prepareCamera();
	//执行窗体循环
	while (!glfwWindowShouldClose(window))
	{
		//接受并分发窗体消息
		//检查消息队列是否有需要处理的鼠标、键盘等消息
		//如果有的话就将消息批量处理,清空队列
		glfwPollEvents();
		//渲染操作
		render();
		//切换双缓存
		glfwSwapBuffers(window);
	}

	//推出程序前做相关清理
	glfwTerminate();
	return 0;
}

glm中的lookat参数可以生成视图变换矩阵,设置给VS即可。

正交投影

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

总结

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

案例分析

在这里插入图片描述

#include <glad/glad.h>//glad必须在glfw头文件之前包含
#include <GLFW/glfw3.h>
#include <iostream>
#define STB_IMAGE_IMPLEMENTATION
#include "stb_image.h"

//GLM
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
#define GLM_ENABLE_EXPERIMENTAL
#include <glm/gtx/string_cast.hpp>

void frameBufferSizeCallbakc(GLFWwindow* window, int width, int height)
{
	glViewport(0, 0, width, height);
}
void glfwKeyCallback(GLFWwindow* window, int key, int scancode, int action, int mods)
{
}

GLuint program = 0;
GLuint vao = 0;
GLuint texture = 0;
glm::mat4 transform(1.0f);//4×4单位矩阵
glm::mat4 viewMatrix(1.0f);
glm::mat4 orthoMatrix(1.0f);
void prepareCamera()
{
	//lookat:生成一个viewMatrix
	//eye:当前摄像机所在的位置
	//center:当前摄像机看向的那个点
	//up:穹顶向量
	viewMatrix = glm::lookAt(glm::vec3(0.0f, 0.0f, 1.0f), glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(0.0f, 1.0f, 0.0f));
}
void prepareOrtho()
{
	//参数为盒体上下左右远近
	orthoMatrix = glm::ortho(-2.0f, 2.0f, -2.0f, 2.0f, 2.0f, -2.0f);
}
void prepareVAO()
{
	//positions
	float positions[] = {
		-1.0f, 0.0f, 0.0f,
		1.0f, 0.0f, 0.0f,
		0.0f,  1.0f, 0.0f,
	};
	//颜色
	float colors[] = {
		1.0f, 0.0f,0.0f,
		0.0f, 1.0f,0.0f,
		0.0f, 0.0f,1.0f
	};
	//索引
	unsigned int indices[] = {
		0, 1, 2,
	};
	//uv坐标
	float uvs[] = {
		0.0f, 0.0f,
		1.0f, 0.0f,
		0.5f, 1.0f,
	};

	//2 VBO创建
	GLuint posVbo = 0;
	GLuint colorVbo = 0;
	GLuint uvVbo = 0;
	glGenBuffers(1, &posVbo);
	glBindBuffer(GL_ARRAY_BUFFER, posVbo);
	glBufferData(GL_ARRAY_BUFFER, sizeof(positions), positions, GL_STATIC_DRAW);

	glGenBuffers(1, &colorVbo);
	glBindBuffer(GL_ARRAY_BUFFER, colorVbo);
	glBufferData(GL_ARRAY_BUFFER, sizeof(colors), colors, GL_STATIC_DRAW);

	glGenBuffers(1, &uvVbo);
	glBindBuffer(GL_ARRAY_BUFFER, uvVbo);
	glBufferData(GL_ARRAY_BUFFER, sizeof(uvs), uvs, GL_STATIC_DRAW);

	//3 EBO创建
	GLuint ebo = 0;
	glGenBuffers(1, &ebo);
	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);
	glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);

	//4 VAO创建
	vao = 0;
	glGenVertexArrays(1, &vao);
	glBindVertexArray(vao);

	//5 绑定vbo ebo 加入属性描述信息
	//5.1 加入位置属性描述信息
	glBindBuffer(GL_ARRAY_BUFFER, posVbo);
	glEnableVertexAttribArray(0);
	glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);

	//5.2 加入颜色属性描述信息
	glBindBuffer(GL_ARRAY_BUFFER, colorVbo);
	glEnableVertexAttribArray(1);
	glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);

	//5.3 加入uv属性描述数据
	glBindBuffer(GL_ARRAY_BUFFER, uvVbo);
	glEnableVertexAttribArray(2);
	glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(float), (void*)0);

	//5.2 加入ebo到当前的vao
	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);

	glBindVertexArray(0);
}
void prepareShader() {
	//1 完成vs与fs的源代码,并且装入字符串
	//aPos作为attribute(属性)传入shader不允许更改的
	const char* vertexShaderSource =
		"#version 330 core\n"
		"layout (location = 0) in vec3 aPos;\n"
		"layout (location = 1) in vec3 aColor;\n"
		"layout (location = 2) in vec2 aUV;\n"
		"out vec3 color;\n"
		"out vec2 uv;\n"
		"uniform mat4 transform;\n"
		"uniform mat4 viewMatrix;\n"
		"uniform mat4 orthoMatrix;\n"
		"void main()\n"
		"{\n"
		"   vec4 position = vec4(aPos, 1.0);\n"
		"   position = orthoMatrix * viewMatrix * transform * position;\n"
		"   gl_Position = position;\n"
		"   color = aColor;\n"
		"   uv = aUV;\n"
		"}\0";
	const char* fragmentShaderSource =
		"#version 330 core\n"
		"out vec4 FragColor;\n"
		"in vec3 color;\n"
		"in vec2 uv;\n"
		"uniform sampler2D sampler;\n"
		"void main()\n"
		"{\n"
		"   FragColor = texture(sampler, uv);\n"
		"}\n\0";


	//2 创建Shader程序(vs、fs)
	GLuint vertex, fragment;
	vertex = glCreateShader(GL_VERTEX_SHADER);
	fragment = glCreateShader(GL_FRAGMENT_SHADER);


	//3 为shader程序输入shader代码
	glShaderSource(vertex, 1, &vertexShaderSource, NULL);
	glShaderSource(fragment, 1, &fragmentShaderSource, NULL);

	int success = 0;
	char infoLog[1024];
	//4 执行shader代码编译 
	glCompileShader(vertex);
	//检查vertex编译结果
	glGetShaderiv(vertex, GL_COMPILE_STATUS, &success);
	if (!success) {
		glGetShaderInfoLog(vertex, 1024, NULL, infoLog);
		std::cout << "Error: SHADER COMPILE ERROR --VERTEX" << "\n" << infoLog << std::endl;
	}

	glCompileShader(fragment);
	//检查fragment编译结果
	glGetShaderiv(fragment, GL_COMPILE_STATUS, &success);
	if (!success) {
		glGetShaderInfoLog(fragment, 1024, NULL, infoLog);
		std::cout << "Error: SHADER COMPILE ERROR --FRAGMENT" << "\n" << infoLog << std::endl;
	}

	//5 创建一个Program壳子
	program = glCreateProgram();

	//6 将vs与fs编译好的结果放到program这个壳子里
	glAttachShader(program, vertex);
	glAttachShader(program, fragment);

	//7 执行program的链接操作,形成最终可执行shader程序
	glLinkProgram(program);

	//检查链接错误
	glGetProgramiv(program, GL_LINK_STATUS, &success);
	if (!success) {
		glGetProgramInfoLog(program, 1024, NULL, infoLog);
		std::cout << "Error: SHADER LINK ERROR " << "\n" << infoLog << std::endl;
	}

	//清理
	glDeleteShader(vertex);
	glDeleteShader(fragment);
}

void prepareTextrue()
{
	//1 stbImage 读取图片
	int width, height, channels;
	//--反转y轴
	stbi_set_flip_vertically_on_load(true);
	unsigned char* data = stbi_load("goku.jpg", &width, &height, &channels, STBI_rgb_alpha);

	//2 生成纹理并且激活单元绑定
	glGenTextures(1, &texture);
	//--激活纹理单元--
	glActiveTexture(GL_TEXTURE0);
	//--绑定纹理对象--
	glBindTexture(GL_TEXTURE_2D, texture);

	//3 传输纹理数据,开辟显存
	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);

	//***释放数据
	stbi_image_free(data);

	//4 设置纹理的过滤方式
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);

	//5 设置纹理的包裹方式
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);//u
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);//v
}

void render()
{
	//执行opengl画布清理操作
	glClear(GL_COLOR_BUFFER_BIT);

	//1.绑定当前的program
	glUseProgram(program);

	//2 更新Uniform的时候,一定要先UserProgram
	//2.1 通过名称拿到Uniform变量的位置Location
	GLint location = glGetUniformLocation(program, "sampler");
	//2.2 通过Location更新Uniform变量的值
	glUniform1f(location, 0);

	GLint locationTransform = glGetUniformLocation(program, "transform");
	//transpose参数:表示是否对传输进去的矩阵数据进行转置
	glUniformMatrix4fv(locationTransform, 1, GL_FALSE, glm::value_ptr(transform));

	GLint locationviewMatrix = glGetUniformLocation(program, "viewMatrix");
	glUniformMatrix4fv(locationviewMatrix, 1, GL_FALSE, glm::value_ptr(viewMatrix));

	GLint locationorthoMatrix = glGetUniformLocation(program, "orthoMatrix");
	glUniformMatrix4fv(locationorthoMatrix, 1, GL_FALSE, glm::value_ptr(orthoMatrix));

	//3 绑定当前的vao
	glBindVertexArray(vao);
	//4 发出绘制指令
	//glDrawArrays(GL_TRIANGLE_STRIP, 0, 6);
	glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_INT, 0);
}


int main()
{
	//初始化glfw环境
	glfwInit();
	//设置opengl主版本号
	glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
	//设置opengl次版本号
	glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
	//设置opengl启用核心模式
	glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);

	//创建窗体对象
	GLFWwindow* window = glfwCreateWindow(800, 600, "lenarnOpenGL", nullptr, nullptr);
	//设置当前窗体对象为opengl的绘制舞台
	glfwMakeContextCurrent(window);
	//窗体大小回调
	glfwSetFramebufferSizeCallback(window, frameBufferSizeCallbakc);
	//键盘相应回调
	glfwSetKeyCallback(window, glfwKeyCallback);

	//使用glad加载所有当前版本opengl的函数
	if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
	{
		std::cout << "初始化glad失败" << std::endl;
		return -1;
	}
	;
	//设置opengl视口大小和清理颜色
	glViewport(0, 0, 800, 600);
	glClearColor(0.2f, 0.3f, 0.3f, 1.0f);

	//shader
	prepareShader();
	//vao
	prepareVAO();
	//texture
	prepareTextrue();
	prepareCamera();
	prepareOrtho();
	//执行窗体循环
	while (!glfwWindowShouldClose(window))
	{
		//接受并分发窗体消息
		//检查消息队列是否有需要处理的鼠标、键盘等消息
		//如果有的话就将消息批量处理,清空队列
		glfwPollEvents();
		//渲染操作
		render();
		//切换双缓存
		glfwSwapBuffers(window);
	}

	//推出程序前做相关清理
	glfwTerminate();
	return 0;
}

在vao中给入模型坐标,模型坐标经过变换后转换成世界坐标,世界坐标经过视图变换矩阵变换为相机坐标,相机坐标经过正交投影变换为NDC坐标。
在构造正交投影矩阵过程中,传入的参数为盒体的大小,只有在盒体范围内的坐标点才会保留,范围外的将会被裁剪。

透视投影

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

例子

在这里插入图片描述
在这里插入图片描述

#include <glad/glad.h>//glad必须在glfw头文件之前包含
#include <GLFW/glfw3.h>
#include <iostream>
#define STB_IMAGE_IMPLEMENTATION
#include "stb_image.h"

//GLM
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
#define GLM_ENABLE_EXPERIMENTAL
#include <glm/gtx/string_cast.hpp>

void frameBufferSizeCallbakc(GLFWwindow* window, int width, int height)
{
	glViewport(0, 0, width, height);
}
void glfwKeyCallback(GLFWwindow* window, int key, int scancode, int action, int mods)
{
}

GLuint program = 0;
GLuint vao = 0;
GLuint texture = 0;
glm::mat4 transform(1.0f);//4×4单位矩阵
glm::mat4 viewMatrix(1.0f);
glm::mat4 orthoMatrix(1.0f);
glm::mat4 perspectiveMatrix(1.0f);
void prepareCamera()
{
	//lookat:生成一个viewMatrix
	//eye:当前摄像机所在的位置
	//center:当前摄像机看向的那个点
	//up:穹顶向量
	viewMatrix = glm::lookAt(glm::vec3(0.0f, 0.0f, 5.0f), glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(0.0f, 1.0f, 0.0f));
}
void prepareOrtho()
{
	//参数为盒体上下左右远近
	orthoMatrix = glm::ortho(-2.0f, 2.0f, -2.0f, 2.0f, 2.0f, -2.0f);
}
void preparePerspective()
{
	//fovy:y轴方向的视张角,弧度单位
	//aspect:近平面的横纵百分比
	//near:近平面距离
	//far:远平面距离
	perspectiveMatrix = glm::perspective(glm::radians(60.0f), 800.0f / 600, 0.1f, 1000.0f);
}
void prepareVAO()
{
	//positions
	float positions[] = {
		-1.0f, 0.0f, 0.0f,
		1.0f, 0.0f, 0.0f,
		0.0f,  1.0f, 0.0f,
	};
	//颜色
	float colors[] = {
		-1.0f, 0.0f, 0.0f,
		1.0f, 0.0f, 0.0f,
		0.0f,  1.0f, 0.0f,
	};
	//索引
	unsigned int indices[] = {
		0, 1, 2,
	};
	//uv坐标
	float uvs[] = {
		0.0f, 0.0f,
		1.0f, 0.0f,
		0.5f, 1.0f,
	};

	//2 VBO创建
	GLuint posVbo = 0;
	GLuint colorVbo = 0;
	GLuint uvVbo = 0;
	glGenBuffers(1, &posVbo);
	glBindBuffer(GL_ARRAY_BUFFER, posVbo);
	glBufferData(GL_ARRAY_BUFFER, sizeof(positions), positions, GL_STATIC_DRAW);

	glGenBuffers(1, &colorVbo);
	glBindBuffer(GL_ARRAY_BUFFER, colorVbo);
	glBufferData(GL_ARRAY_BUFFER, sizeof(colors), colors, GL_STATIC_DRAW);

	glGenBuffers(1, &uvVbo);
	glBindBuffer(GL_ARRAY_BUFFER, uvVbo);
	glBufferData(GL_ARRAY_BUFFER, sizeof(uvs), uvs, GL_STATIC_DRAW);

	//3 EBO创建
	GLuint ebo = 0;
	glGenBuffers(1, &ebo);
	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);
	glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);

	//4 VAO创建
	vao = 0;
	glGenVertexArrays(1, &vao);
	glBindVertexArray(vao);

	//5 绑定vbo ebo 加入属性描述信息
	//5.1 加入位置属性描述信息
	glBindBuffer(GL_ARRAY_BUFFER, posVbo);
	glEnableVertexAttribArray(0);
	glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);

	//5.2 加入颜色属性描述信息
	glBindBuffer(GL_ARRAY_BUFFER, colorVbo);
	glEnableVertexAttribArray(1);
	glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);

	//5.3 加入uv属性描述数据
	glBindBuffer(GL_ARRAY_BUFFER, uvVbo);
	glEnableVertexAttribArray(2);
	glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(float), (void*)0);

	//5.2 加入ebo到当前的vao
	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);

	glBindVertexArray(0);
}
void prepareShader() {
	//1 完成vs与fs的源代码,并且装入字符串
	//aPos作为attribute(属性)传入shader不允许更改的
	const char* vertexShaderSource =
		"#version 330 core\n"
		"layout (location = 0) in vec3 aPos;\n"
		"layout (location = 1) in vec3 aColor;\n"
		"layout (location = 2) in vec2 aUV;\n"
		"out vec3 color;\n"
		"out vec2 uv;\n"
		"uniform mat4 transform;\n"
		"uniform mat4 viewMatrix;\n"
		"uniform mat4 perspectiveMatrix;\n"
		"void main()\n"
		"{\n"
		"   vec4 position = vec4(aPos, 1.0);\n"
		"   position = perspectiveMatrix * viewMatrix * transform * position;\n"
		"   gl_Position = position;\n"
		"   color = aColor;\n"
		"   uv = aUV;\n"
		"}\0";
	const char* fragmentShaderSource =
		"#version 330 core\n"
		"out vec4 FragColor;\n"
		"in vec3 color;\n"
		"in vec2 uv;\n"
		"uniform sampler2D sampler;\n"
		"void main()\n"
		"{\n"
		"   FragColor = texture(sampler, uv);\n"
		"}\n\0";


	//2 创建Shader程序(vs、fs)
	GLuint vertex, fragment;
	vertex = glCreateShader(GL_VERTEX_SHADER);
	fragment = glCreateShader(GL_FRAGMENT_SHADER);


	//3 为shader程序输入shader代码
	glShaderSource(vertex, 1, &vertexShaderSource, NULL);
	glShaderSource(fragment, 1, &fragmentShaderSource, NULL);

	int success = 0;
	char infoLog[1024];
	//4 执行shader代码编译 
	glCompileShader(vertex);
	//检查vertex编译结果
	glGetShaderiv(vertex, GL_COMPILE_STATUS, &success);
	if (!success) {
		glGetShaderInfoLog(vertex, 1024, NULL, infoLog);
		std::cout << "Error: SHADER COMPILE ERROR --VERTEX" << "\n" << infoLog << std::endl;
	}

	glCompileShader(fragment);
	//检查fragment编译结果
	glGetShaderiv(fragment, GL_COMPILE_STATUS, &success);
	if (!success) {
		glGetShaderInfoLog(fragment, 1024, NULL, infoLog);
		std::cout << "Error: SHADER COMPILE ERROR --FRAGMENT" << "\n" << infoLog << std::endl;
	}

	//5 创建一个Program壳子
	program = glCreateProgram();

	//6 将vs与fs编译好的结果放到program这个壳子里
	glAttachShader(program, vertex);
	glAttachShader(program, fragment);

	//7 执行program的链接操作,形成最终可执行shader程序
	glLinkProgram(program);

	//检查链接错误
	glGetProgramiv(program, GL_LINK_STATUS, &success);
	if (!success) {
		glGetProgramInfoLog(program, 1024, NULL, infoLog);
		std::cout << "Error: SHADER LINK ERROR " << "\n" << infoLog << std::endl;
	}

	//清理
	glDeleteShader(vertex);
	glDeleteShader(fragment);
}

void prepareTextrue()
{
	//1 stbImage 读取图片
	int width, height, channels;
	//--反转y轴
	stbi_set_flip_vertically_on_load(true);
	unsigned char* data = stbi_load("goku.jpg", &width, &height, &channels, STBI_rgb_alpha);

	//2 生成纹理并且激活单元绑定
	glGenTextures(1, &texture);
	//--激活纹理单元--
	glActiveTexture(GL_TEXTURE0);
	//--绑定纹理对象--
	glBindTexture(GL_TEXTURE_2D, texture);

	//3 传输纹理数据,开辟显存
	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);

	//***释放数据
	stbi_image_free(data);

	//4 设置纹理的过滤方式
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);

	//5 设置纹理的包裹方式
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);//u
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);//v
}

void render()
{
	//执行opengl画布清理操作
	glClear(GL_COLOR_BUFFER_BIT);

	//1.绑定当前的program
	glUseProgram(program);

	//2 更新Uniform的时候,一定要先UserProgram
	//2.1 通过名称拿到Uniform变量的位置Location
	GLint location = glGetUniformLocation(program, "sampler");
	//2.2 通过Location更新Uniform变量的值
	glUniform1f(location, 0);

	GLint locationTransform = glGetUniformLocation(program, "transform");
	//transpose参数:表示是否对传输进去的矩阵数据进行转置
	glUniformMatrix4fv(locationTransform, 1, GL_FALSE, glm::value_ptr(transform));

	GLint locationviewMatrix = glGetUniformLocation(program, "viewMatrix");
	glUniformMatrix4fv(locationviewMatrix, 1, GL_FALSE, glm::value_ptr(viewMatrix));

	GLint locationperspectiveMatrix = glGetUniformLocation(program, "perspectiveMatrix");
	glUniformMatrix4fv(locationperspectiveMatrix, 1, GL_FALSE, glm::value_ptr(perspectiveMatrix));

	//3 绑定当前的vao
	glBindVertexArray(vao);
	//4 发出绘制指令
	//glDrawArrays(GL_TRIANGLE_STRIP, 0, 6);
	glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_INT, 0);
}


int main()
{
	//初始化glfw环境
	glfwInit();
	//设置opengl主版本号
	glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
	//设置opengl次版本号
	glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
	//设置opengl启用核心模式
	glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);

	//创建窗体对象
	GLFWwindow* window = glfwCreateWindow(800, 600, "lenarnOpenGL", nullptr, nullptr);
	//设置当前窗体对象为opengl的绘制舞台
	glfwMakeContextCurrent(window);
	//窗体大小回调
	glfwSetFramebufferSizeCallback(window, frameBufferSizeCallbakc);
	//键盘相应回调
	glfwSetKeyCallback(window, glfwKeyCallback);

	//使用glad加载所有当前版本opengl的函数
	if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
	{
		std::cout << "初始化glad失败" << std::endl;
		return -1;
	}
	;
	//设置opengl视口大小和清理颜色
	glViewport(0, 0, 800, 600);
	glClearColor(0.2f, 0.3f, 0.3f, 1.0f);

	//shader
	prepareShader();
	//vao
	prepareVAO();
	//texture
	prepareTextrue();
	prepareCamera();
	preparePerspective();
	//执行窗体循环
	while (!glfwWindowShouldClose(window))
	{
		//接受并分发窗体消息
		//检查消息队列是否有需要处理的鼠标、键盘等消息
		//如果有的话就将消息批量处理,清空队列
		glfwPollEvents();
		//渲染操作
		render();
		//切换双缓存
		glfwSwapBuffers(window);
	}

	//推出程序前做相关清理
	glfwTerminate();
	return 0;
}

相关推荐

  1. 投影的矩阵(基变换与过渡矩阵的例子)

    2024-07-09 22:00:04       27 阅读

最近更新

  1. Python利用psutil库进行监控进程和资源

    2024-07-09 22:00:04       0 阅读
  2. SpringBoot RestHighLevelClient 按版本更新

    2024-07-09 22:00:04       0 阅读
  3. 跨域问题几种解决方法

    2024-07-09 22:00:04       0 阅读
  4. Python面试整理-文件处理

    2024-07-09 22:00:04       0 阅读
  5. 分式

    2024-07-09 22:00:04       0 阅读
  6. Spring WebFlux 介绍与效果演示示例

    2024-07-09 22:00:04       0 阅读
  7. django 需要修改的文件

    2024-07-09 22:00:04       0 阅读
  8. Random,ThreadLocalRandom,SecureRandom有什么区别

    2024-07-09 22:00:04       0 阅读
  9. Python 爬虫技术 第05节 异常处理

    2024-07-09 22:00:04       0 阅读
  10. 微信小程序开发:DOM 相关 API 使用详解

    2024-07-09 22:00:04       0 阅读
  11. QtQuick-QML语法

    2024-07-09 22:00:04       0 阅读
  12. Codeforces Round 960 (Div. 2)VP

    2024-07-09 22:00:04       0 阅读
  13. WebAssembly在前端开发中的创新与应用

    2024-07-09 22:00:04       0 阅读

热门阅读

  1. 【Tools】了解人工通用智能 (AGI):未来的智能体

    2024-07-09 22:00:04       5 阅读
  2. HTML最快速最简单

    2024-07-09 22:00:04       5 阅读
  3. 等保测评推动黑龙江数字化转型中的安全保障

    2024-07-09 22:00:04       5 阅读
  4. 嵌入式硬件电路常用设计软件

    2024-07-09 22:00:04       7 阅读
  5. [终端安全]-2 移动终端之硬件安全(SE)

    2024-07-09 22:00:04       6 阅读
  6. Kafka 典型问题与排查以及相关优化

    2024-07-09 22:00:04       6 阅读
  7. SQL中字符串类型中char和varchar之间的区别是什么

    2024-07-09 22:00:04       5 阅读