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;
}
半球贴图:旋转过程截图

原图:

浙公网安备 33010602011771号