OpenGL半球贴图

#version 330 core
out vec4 FragColor;
in vec2 tex_coord;
uniform sampler2D tex;
void main()
{
    //FragColor = vec4(1.0,0.635,0.345,1.0);
   FragColor = texture(tex, tex_coord);
}
#version 330 core
layout (location = 0) in vec3 aPos;
uniform mat4 face_matrix;
out vec2 tex_coord;

void main()
{

   
    float dist = 2*sqrt(pow(aPos.x,2)+pow(aPos.y,2)+pow(aPos.z,2));
    vec4 vpos =  face_matrix *vec4(aPos.x/dist,aPos.y/dist,aPos.z/dist,1.0);//顶点坐标旋转

    tex_coord =   vec2((aPos.x+1)/2 ,(aPos.z+1)/2);    // -1~1 移动到0~1;((*+1)/2),写错了可能会有黑条(不要去乘MVP)
    gl_Position =  vpos;

}

 

#include <glad/glad.h>
#include <GLFW/glfw3.h>
#include <shader.h>
#include <iostream>
#include <math.h>
#include <vector>
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
#include <windows.h>  
#define STB_IMAGE_IMPLEMENTATION
#include "stb_image.h"
const unsigned int screen_width = 780;
const unsigned int screen_height = 780;

const GLfloat  PI = 3.14159265358979323846f;

//将球横纵划分成X*Y的网格
const int Y_SEGMENTS = 40;
const int X_SEGMENTS = 40;
;

unsigned int testureID = 99;
glm::mat4 pos_matrix, face_matrix, projection;
GLuint pos_matrix_idx, face_matrix_idx,projID;



int main()
{
	// 初始化GLFW
	glfwInit();                                                     // 初始化GLFW
	glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);                  // OpenGL版本为3.3,主次版本号均设为3
	glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
	glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);  // 使用核心模式(无需向后兼容性)
	glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);            // 如果使用的是Mac OS X系统,需加上这行
	glfwWindowHint(GLFW_RESIZABLE, 0);						    // 不可改变窗口大小

																	// 创建窗口(宽、高、窗口名称)
	auto window = glfwCreateWindow(screen_width, screen_height, "Sphere", nullptr, nullptr);
	if (window == nullptr) {                                        // 如果窗口创建失败,输出Failed to Create OpenGL Context
		std::cout << "Failed to Create OpenGL Context" << std::endl;
		glfwTerminate();
		return -1;
	}

	
	glfwMakeContextCurrent(window);                                 // 将窗口的上下文设置为当前线程的主上下文

					// 初始化GLAD,加载OpenGL函数指针地址的函数
	if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
	{
		std::cout << "Failed to initialize GLAD" << std::endl;
		return -1;
	}

	// 指定当前视口尺寸(前两个参数为左下角位置,后两个参数是渲染窗口宽、高)
	glViewport(0, 0, screen_width, screen_height);

	Shader shader("vertexShader.glsl", "fragmentShader.glsl");//加载,编译着色器


	//加载图片
	//加载图片-----------------------------------------------------------------

	shader.use();

	glGenTextures(1, &testureID);
	glActiveTexture(GL_TEXTURE0);
	glBindTexture(GL_TEXTURE_2D, testureID);
	//为bind的纹理设置环绕,过滤方式
	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_LINEAR);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
	//stbi是一个图片载入的开源组件,文件名,宽高,通道数,你期望的通道数
	int W, H, desired_channels;
	//注意图片是24位的
	unsigned char* data = stbi_load("./21.jpg", &W, &H, &desired_channels, 0);
	if (data)
	{
		//数据生成纹理;根据指定的参数,把输入数据生成一张2D纹理
		glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, W, H, 0, GL_RGB, GL_UNSIGNED_BYTE, data);
		//生成mipmap数组
		glUniform1i(glGetUniformLocation(shader.ID, "tex"), 0);//这句话一定要写,不然没法采样
		glGenerateMipmap(GL_TEXTURE_2D);
	}
	stbi_image_free(data);
	//-----------------------------------------------------------

	std::vector<float> sphereVertices;
	
	// Y_SEGMENTS 和 X_SEGMENTS 分别表 示将α 和β 分割了多少份,
	//y 和 x 分别表示是第几份,以此进行遍历, xSegment*2.0f*PI 即β 角,ySegment*PI 即α 角。
	for (int y = -(Y_SEGMENTS / 2); y <= 0; y++)
	{
		for (int x = 0; x <= X_SEGMENTS; x++)
		{
			float xSegment = (float)x / (float)X_SEGMENTS;
			float ySegment = (float)y / (float)Y_SEGMENTS;
			float xPos = std::cos(xSegment * 2.0f * PI) * std::cos(ySegment * PI);
			float yPos = std::sin(ySegment * PI);
			float zPos = std::sin(xSegment * 2.0f * PI) * std::cos(ySegment * PI);
			

			sphereVertices.push_back(xPos);
			sphereVertices.push_back(yPos);
			sphereVertices.push_back(zPos);

		}
	}

	// 生成球的三角形索引;六个点两个三角;
	std::vector<int> sphereIndices;
	for (int i = 0; i < Y_SEGMENTS/2 ; i++)
	{
		for (int j = 0; j < X_SEGMENTS; j++)
		{

			sphereIndices.push_back(i * (X_SEGMENTS + 1) + j);
			sphereIndices.push_back((i + 1) * (X_SEGMENTS + 1) + j);
			sphereIndices.push_back((i + 1) * (X_SEGMENTS + 1) + j + 1);

			sphereIndices.push_back(i * (X_SEGMENTS + 1) + j);
			sphereIndices.push_back((i + 1) * (X_SEGMENTS + 1) + j + 1);
			sphereIndices.push_back(i * (X_SEGMENTS + 1) + j + 1);
		}
	}


	// 球
	unsigned int VBO, VAO;
	glGenVertexArrays(1, &VAO);
	glGenBuffers(1, &VBO);
	//生成并绑定球体的VAO和VBO
	glBindVertexArray(VAO);

	glBindBuffer(GL_ARRAY_BUFFER, VBO);
	// 将顶点数据绑定至当前默认的缓冲中
	glBufferData(GL_ARRAY_BUFFER, sphereVertices.size() * sizeof(float), &sphereVertices[0], GL_STATIC_DRAW);
	
	GLuint element_buffer_object; //EBO
	glGenBuffers(1, &element_buffer_object);
	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, element_buffer_object);
	glBufferData(GL_ELEMENT_ARRAY_BUFFER, sphereIndices.size() * sizeof(int), &sphereIndices[0], GL_STATIC_DRAW);

	// 设置顶点属性指针
	glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
	glEnableVertexAttribArray(0);

	// 解绑VAO和VBO
	glBindBuffer(GL_ARRAY_BUFFER, 0);
	glBindVertexArray(0);

	
	
   // pos_matrix_idx = glGetUniformLocation(shader.ID, "pos_matrix");
	//projID = glGetUniformLocation(shader.ID, "projection");
	glm::mat4 view = glm::mat4(1.0f);

	////平移
	//pos_matrix = glm::translate(view, glm::vec3(0.0f, 0.00f, 0.0f));
	//glUniformMatrix4fv(pos_matrix_idx, 1, GL_FALSE, &pos_matrix[0][0]);
	////旋转
	//face_matrix = glm::rotate(view, glm::radians(30.0f), glm::vec3(0.0f, 1.0f, 0.0f));
	//glUniformMatrix4fv(face_matrix_idx, 1, GL_FALSE, &face_matrix[0][0]);
	////s视角
	//projection = glm::perspective((float)glfwGetTime(), (float)screen_width / (float)screen_height, 0.1f, 10.0f);
	//glUniformMatrix4fv(projID, 1, GL_FALSE, &projection[0][0]);
	//-------------------------------------------------------------------------------
	int i = 0;
	// 渲染循环
	while (!glfwWindowShouldClose(window))
	{
		
		// 清空颜色缓冲
		glClearColor(0.0f, 0.3f, 0.2f, 1.0f);
		i = (i++)% 12;
		//旋转
		face_matrix = glm::rotate(view, glm::radians(30.0f*i), glm::vec3(1.0f, 0.0f, 0.0f));
		face_matrix_idx = glGetUniformLocation(shader.ID, "face_matrix");
		glUniformMatrix4fv(face_matrix_idx, 1, GL_FALSE, &face_matrix[0][0]);


		shader.use();
		//绘制球
		//glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
		glClearDepth(1.0);
		glEnable(GL_DEPTH_TEST);
		glBindVertexArray(VAO);
		glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
		glBindBuffer(GL_ARRAY_BUFFER, VAO);


		glDrawElements(GL_TRIANGLES,(X_SEGMENTS)*(Y_SEGMENTS/2) * 6, GL_UNSIGNED_INT, (GLvoid *)(0));
		
		glBindVertexArray(0);
		glfwSwapBuffers(window);
		glfwPollEvents();
		Sleep(2000);//1s
	}

	// 删除VAO和VBO,EBO
	glDeleteVertexArrays(1, &VAO);
	glDeleteBuffers(1, &VBO);
	glDeleteBuffers(1, &element_buffer_object);

	// 清理所有的资源并正确退出程序
	glfwTerminate();
	return 0;
}

 半球贴图:旋转过程截图

 

 原图:

 

 

 




posted on 2022-12-29 23:15  邗影  阅读(165)  评论(0编辑  收藏  举报

导航