效果如图
准备第三方库 glew、freeglut、glm
代码包括主程序源文件mainApp.cpp、顶点着色器shader.vs、片元着色器shader.fs
 
mainApp.cpp如下
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <fstream>
#include <sstream>
#include <GL/glew.h>
#include <GL/freeglut.h>
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp> using namespace std;
using namespace glm; //shader文件
const char* vsShaderName = "shader.vs";//顶点着色器
const char* fsShaderName = "shader.fs";//片元着色器 GLuint VBO;//顶点缓冲对象
GLuint IBO;//索引缓冲对象 static GLfloat *vertices;//顶点数组
static unsigned int *indices; //索引数组
GLuint ShaderProgram;
GLuint MatrixID;
int windowWidth = 800;
int windowHeight = 800;
//球体参数
float radius=5.0f;//半径
int longPart=19;//经线数
int latPart=18;//纬线数
int verticeNum = longPart * latPart + 2 * longPart; //相机参数
glm::mat4 ViewMatrix;//视图矩阵
glm::mat4 ProjectionMatrix; //投影矩阵
glm::mat4 MVP;//模型视图矩阵
glm::mat4 ModelMatrix;//模型矩阵
glm::vec3 position = glm::vec3(5, 5, 5); //相机位置
float horizontalAngle = 3.14f;
float verticalAngle = 0.0f;
float initialFoV = 45.0f; //相机视场角
float speed = 0.05f; //平移速度
float mouseSpeed = 0.05f;
int mouseX, mouseY;//鼠标位置 窗口坐标 // 传递键盘事件
static void SpecialKeyboardCB(int Key, int x, int y)
{
glm::vec3 direction(
cos(verticalAngle) * sin(horizontalAngle),
sin(verticalAngle),
cos(verticalAngle) * cos(horizontalAngle)
);
glm::vec3 right = glm::vec3(
sin(horizontalAngle - 3.14f / 2.0f),
0,
cos(horizontalAngle - 3.14f / 2.0f)
);
glm::vec3 up = glm::cross(right, direction); switch (Key) {
case GLUT_KEY_UP:
position += direction * speed;
fprintf(stderr, "up key\n");
break;
case GLUT_KEY_RIGHT:
position += right * speed;
fprintf(stderr, "right key\n");
break;
case GLUT_KEY_DOWN:
position -= direction * speed;
fprintf(stderr, "down key\n");
break;
case GLUT_KEY_LEFT:
position -= right * speed;
fprintf(stderr, "left key\n");
break;
case GLUT_KEY_F4:
exit(1);
default:
fprintf(stderr, "Unimplemented GLUT key\n");
//exit(1);
} float FoV = initialFoV;
ProjectionMatrix = glm::perspective(glm::radians(FoV), 4.0f / 3.0f, 0.1f, 100.0f);
ViewMatrix = glm::lookAt(
position,
position + direction,
up
);
ModelMatrix = glm::mat4(1.0);
MVP = ProjectionMatrix * ViewMatrix * ModelMatrix;
glutPostRedisplay();//设置窗口重绘
}
//传递鼠标事件
static void PassiveMouseCB(int x, int y)
{
horizontalAngle += mouseSpeed * float(x - mouseX);
verticalAngle += mouseSpeed * float(y - mouseY);
mouseX = x;
mouseY = y;
SpecialKeyboardCB(0, 0, 0);
} //渲染回调函数
void RenderScenceCB() {
// 清空颜色缓存
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);//线框模式
//传递mvp
glUniformMatrix4fv(MatrixID, 1, GL_FALSE, &MVP[0][0]);
//传递顶点、索引
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, IBO);
////test
//glDrawElements(GL_TRIANGLES, 3*4, GL_UNSIGNED_SHORT, 0);
glDrawElements(GL_TRIANGLES_ADJACENCY, (longPart - 1)* latPart * 3 * 2 * 4, GL_UNSIGNED_SHORT, 0);
glDisableVertexAttribArray(0);
//交换前后缓存
glutSwapBuffers();
} //创建顶点
static void CreateVertexBuffer()
{
////test
//vertices = new GLfloat[3* 3];
//vertices[0] = -1.0f;
//vertices[1] = -1.0f;
//vertices[2] = -1.0f;
//vertices[3] = -1.0f;
//vertices[4] = -1.0f;
//vertices[5] = 1.0f;
//vertices[6] = -1.0f;
//vertices[7] = 1.0f;
//vertices[8] = 1.0f; vertices= new GLfloat[verticeNum * 3];
for (int i = 0; i < longPart; i++)
{
vertices[i * 3] = 0;
vertices[i * 3 + 1] = 0;
vertices[i * 3 + 2] = radius;
}
float degreesToRadians = 3.141593f/ 180.0f; //弧度转换
float deltaLong = 360.0f / (longPart - 1);//经度每份对应度数
float deltaLat = 180.0f / (latPart + 2);//纬度每份对应度数
for (int tempLat = 0; tempLat < latPart; tempLat++)
{
float tempAngle1 = ((tempLat + 1)* deltaLat) * degreesToRadians;
for (int tempLong = 0; tempLong < longPart; tempLong++)
{
float tempAngle2 = (tempLong*deltaLong) * degreesToRadians;
int tempIndex = tempLong + tempLat* longPart + longPart;
vertices[tempIndex * 3] = sin(tempAngle1) * cos(tempAngle2)* radius;
vertices[tempIndex * 3 + 1] = sin(tempAngle1) * sin(tempAngle2)* radius;
vertices[tempIndex * 3 + 2] = cos(tempAngle1)* radius;
}
}
for (int i = 0; i < longPart; i++)
{
vertices[(verticeNum - 1 - i) * 3] = 0;
vertices[(verticeNum - 1 - i) * 3 + 1] = 0;
vertices[(verticeNum - 1 - i) * 3 + 2] = -1.0f*radius;
}
glGenBuffers(1, &VBO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
////test
//glBufferData(GL_ARRAY_BUFFER, 3 * 3 * sizeof(GLfloat), vertices, GL_STATIC_DRAW);
glBufferData(GL_ARRAY_BUFFER, verticeNum * 3 * sizeof(GLfloat), vertices, GL_STATIC_DRAW);
}
//创建索引
static void CreateIndexBuffer()
{
////test
//indices = new unsigned int[3];
//indices[0] = 2;
//indices[1] = 1;
//indices[2] = 0; indices = new unsigned int[(longPart - 1)* latPart * 3 * 2];
int k = 0;
for (int i = 0; i < longPart - 1; i++)
{
indices[k++] = i;
indices[k++] = i + longPart;
indices[k++] = i + longPart + 1;
}
for (int tempLat = 0; tempLat < latPart-1; tempLat++)
{
for (int tempLong = 0; tempLong < longPart - 1; tempLong++)
{
indices[k++] = tempLong + tempLat * longPart + longPart;
indices[k++] = tempLong + tempLat * longPart + 2 * longPart;
indices[k++] = tempLong + tempLat * longPart + longPart + 1; indices[k++] = tempLong + tempLat * longPart + 2 * longPart;
indices[k++] = tempLong + tempLat * longPart + 1 + 2 * longPart;
indices[k++] = tempLong + tempLat * longPart + 1 + longPart;
}
}
for (int i = 0; i < longPart - 1; i++)
{
indices[k++] = verticeNum - 1 - i;
indices[k++] = verticeNum - 1 - i - longPart;
indices[k++] = verticeNum - 2 - i - longPart;
}
glGenBuffers(1, &IBO);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, IBO);
////test
//glBufferData(GL_ELEMENT_ARRAY_BUFFER, 3* sizeof(unsigned int), indices, GL_STATIC_DRAW); glBufferData(GL_ELEMENT_ARRAY_BUFFER, (longPart - 1)* latPart * 3 * 2 * sizeof(unsigned int), indices, GL_STATIC_DRAW);
} // 使用shader文本编译shader对象,并绑定shader到着色器程序中
static void AddShader(GLuint ShaderProgram, const char* pShaderText, GLenum ShaderType)
{
// 根据shader类型参数定义两个shader对象
GLuint ShaderObj = glCreateShader(ShaderType);
// 检查是否定义成功
if (ShaderObj == 0) {
fprintf(stderr, "Error creating shader type %d\n", ShaderType);
exit(0);
}
// 定义shader的代码源
const GLchar* p[1];
p[0] = pShaderText;
GLint Lengths[1];
Lengths[0] = strlen(pShaderText);
glShaderSource(ShaderObj, 1, p, Lengths);
glCompileShader(ShaderObj);// 编译shader对象
// 检查和shader相关的错误
GLint success;
glGetShaderiv(ShaderObj, GL_COMPILE_STATUS, &success);
if (!success) {
GLchar InfoLog[1024];
glGetShaderInfoLog(ShaderObj, 1024, NULL, InfoLog);
fprintf(stderr, "Error compiling shader type %d: '%s'\n", ShaderType, InfoLog);
exit(1);
}
// 将编译好的shader对象绑定到program object程序对象上
glAttachShader(ShaderProgram, ShaderObj);
} // 编译着色器函数
static void CompileShaders()
{
// 创建着色器程序
ShaderProgram = glCreateProgram();
// 检查是否创建成功
if (ShaderProgram == 0) {
fprintf(stderr, "Error creating shader program\n");
exit(1);
}
// 存储着色器文本的字符串
string vs, fs;
// 分别读取着色器文件中的文本到字符串
std::ifstream VertexShaderStream(vsShaderName, std::ios::in);
if (VertexShaderStream.is_open()) {
std::stringstream sstr;
sstr << VertexShaderStream.rdbuf();
vs = sstr.str();
VertexShaderStream.close();
}
else {
printf("Error to open %s\n", vsShaderName);
getchar();
exit(0);
}
std::ifstream FragmentShaderStream(fsShaderName, std::ios::in);
if (FragmentShaderStream.is_open()) {
std::stringstream sstr;
sstr << FragmentShaderStream.rdbuf();
fs = sstr.str();
FragmentShaderStream.close();
} // 添加顶点着色器和片段着色器
AddShader(ShaderProgram, vs.c_str(), GL_VERTEX_SHADER);
AddShader(ShaderProgram, fs.c_str(), GL_FRAGMENT_SHADER);
// 链接shader着色器程序,并检查程序相关错误
GLint Success = 0;
GLchar ErrorLog[1024] = { 0 };
glLinkProgram(ShaderProgram);
glGetProgramiv(ShaderProgram, GL_LINK_STATUS, &Success);
if (Success == 0) {
glGetProgramInfoLog(ShaderProgram, sizeof(ErrorLog), NULL, ErrorLog);
fprintf(stderr, "Error linking shader program: '%s'\n", ErrorLog);
exit(1);
}
// 检查验证在当前的管线状态程序是否可以被执行
glValidateProgram(ShaderProgram);
glGetProgramiv(ShaderProgram, GL_VALIDATE_STATUS, &Success);
if (!Success) {
glGetProgramInfoLog(ShaderProgram, sizeof(ErrorLog), NULL, ErrorLog);
fprintf(stderr, "Invalid shader program: '%s'\n", ErrorLog);
exit(1);
}
// 设置到管线声明中来使用上面成功建立的shader程序
glUseProgram(ShaderProgram);
MatrixID = glGetUniformLocation(ShaderProgram, "gWVP");
} int main(int argc, char ** argv) {
// 初始化GLUT
glutInit(&argc, argv);
// 显示模式:双缓冲、RGBA
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA);
glutInitWindowSize(windowWidth, windowHeight);
glutInitWindowPosition(100, 100);
glutCreateWindow("sphere");
GLenum res = glewInit();
if (res != GLEW_OK) {
fprintf(stderr, "Error: '%s'\n", glewGetErrorString(res));
return 1;
}
// 开始渲染
glutDisplayFunc(RenderScenceCB);
// 注册键盘事件
glutSpecialFunc(SpecialKeyboardCB);
//注册鼠标事件
glutPassiveMotionFunc(PassiveMouseCB);
mouseX = windowWidth / 2;
mouseY = windowHeight / 2;
// 缓存清空后的颜色值
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
//创建顶点
CreateVertexBuffer();
//创建索引
CreateIndexBuffer();
// 编译着色器
CompileShaders();
//开启深度测试
glEnable(GL_DEPTH_TEST);
// 通知开始GLUT的内部循环
glutMainLoop();
delete vertices;
return 0;
}
shader.vs如下
#version 330
layout (location = 0) in vec3 Position;
// WVP标准
uniform mat4 gWVP;
void main()
{
gl_Position = gWVP * vec4(Position, 1.0);
}
shader.fs如下
#version 330
out vec3 FragColor;
void main()
{
FragColor = vec3(1.0, 0.0, 0.0);
}

本文链接https://www.cnblogs.com/gucheng/p/10134582.html

opengl球形网格生成的更多相关文章

  1. OpenGL shader 中关于顶点坐标值的思考

    今天工作中需要做一个事情: 在shader内部做一些空间距离上的计算,而且需要对所有的点进行计算,符合条件的显示,不符合条件的点不显示. 思路很简单,在vertex shader内知道顶点坐标,进行计 ...

  2. CSharpGL(27)讲讲清楚OpenGL坐标变换

    CSharpGL(27)讲讲清楚OpenGL坐标变换 在理解OpenGL的坐标变换问题的路上,有好几个难点和易错点.且OpenGL秉持着程序难以调试.难点互相纠缠的特色,更让人迷惑.本文依序整理出关于 ...

  3. opengl入门学习

    OpenGL入门学习 说起编程作图,大概还有很多人想起TC的#include <graphics.h>吧? 但是各位是否想过,那些画面绚丽的PC游戏是如何编写出来的?就靠TC那可怜的640 ...

  4. OpenGL的glOrtho平行投影函数详解[转]

    glortho函数可以将当前的可视空间设置为正投影空间.基参数的意义如图,如果绘制的图空间本身就是二维的,可以使gluOrtho2D.他的使用类似于glOrtho 原型是: void glOrtho( ...

  5. NeHe OpenGL教程 第二十三课:球面映射

    转自[翻译]NeHe OpenGL 教程 前言 声明,此 NeHe OpenGL教程系列文章由51博客yarin翻译(2010-08-19),本博客为转载并稍加整理与修改.对NeHe的OpenGL管线 ...

  6. OpenGL入门学习(转)

    OpenGL入门学习 http://www.cppblog.com/doing5552/archive/2009/01/08/71532.html 说起编程作图,大概还有很多人想起TC的#includ ...

  7. opengl 扳回一球

    本文介绍了使用两种方法opengl画一个球体,一个是一个球形点位置计算,然后绘制出,还有一个glut套件自带功能. 一.直接绘制法 直接贴代码,解释都写在凝视里了.绘制时先移动好坐标系.然后调用这方法 ...

  8. OpenGL理解

    说起编程作图,大概还有很多人想起TC的#include <graphics.h>吧? 但是各位是否想过,那些画面绚丽的PC游戏是如何编写出来的?就靠TC那可怜的640*480分辨率.16色 ...

  9. OpenGL 用三角形模拟生成球面

    在看OpenGL红皮书,看到生成球体这节,讲了很多,总感觉不如自己动手写一些代码来的实在,用OpenGL中三角形模拟球形生成.主要要点,模型视图变换,多边形表面环绕一致性,矩阵堆栈.先贴上代码. 虽然 ...

随机推荐

  1. HttpClient获取数据

    HttpClient 是Apache Jakarta Common 下的子项目,可以用来提供高效的.最新的.功能丰富的支持 HTTP 协议的客户端编程工具包,并且它支持 HTTP 协议最新的版本和建议 ...

  2. python_模块2

    1.sys模块 import sys # 获取一个值的应用计数 a = [11,22,33] b = a print(sys.getrefcount(a)) # python默认支持的递归数量 v1 ...

  3. 15、Spring Boot 2.x 集成 Swagger UI

    1.15.Spring Boot 2.x 集成 Swagger UI 完整源码: Spring-Boot-Demos 1.15.1 pom文件添加swagger包 <swagger2.versi ...

  4. Java Part 001( 02_01_理解面向对象 )

    Java完全支持面向对象的三个基本特征: 继承.封装.多态 面向对象的方式实际上由OOA(面向对象分析).OOD(面向对象设计).OOP(面向对象编程)三个部分有机组成 目前业界统一采用UML(统一建 ...

  5. mysql 常见ALTER TABLE操作

    删除列 alter table table-name drop col-name; 增加列(单列) alter table table-name add col-name col-type comme ...

  6. 006_linuxC++之_引用

    1. 什么是“引用”?申明和使用“引用”要注意哪些问题? 答:引用就是某个目标变量的“别名”(alias),对应用的操作与对变量直接操作效果完全相同.申明一个引用的时候,切记要对其进行初始化.引用声明 ...

  7. MySQL 5.7 OOM问题诊断——就是这么简单

    转载自:http://www.sohu.com/a/114903225_487483 Inside君最近把金庸先生的笑傲江湖重看了三遍,感慨良多.很多工作.管理.生活.学习上的问题都能在其中一窥究竟, ...

  8. CF920C Swap Adjacent Elements 贪心

    我也不知道该说啥,水就是了~ code: #include <bits/stdc++.h> #define N 300004 #define setIO(s) freopen(s" ...

  9. Codevs 1038 一元三次方程求解 NOIP 2001(导数 牛顿迭代)

    1038 一元三次方程求解 2001年NOIP全国联赛提高组 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 白银 Silver 题目描述 Description 有形如:ax3+b ...

  10. DRF-解析器组件源码解析

    解析器组件源码解析 解析器组件源码解析 1 执行request.data 开始找重装的request中的data方法 2 在dispatch找到重装的request def dispatch(self ...