Skip to content

Instantly share code, notes, and snippets.

@zwzmzd
Last active November 21, 2022 09:22
Show Gist options
  • Save zwzmzd/0195733fa1210346b00d to your computer and use it in GitHub Desktop.
Save zwzmzd/0195733fa1210346b00d to your computer and use it in GitHub Desktop.
[OpenGL] An example to draw a sphere with vao and vbo
#include "sphere.h"
#include <vector>
#include <iostream>
#include <glm/gtc/matrix_inverse.hpp>
#include <glm/gtc/type_ptr.hpp>
#include <glm/gtx/string_cast.hpp>
Sphere::Sphere()
{
isInited = false;
m_vao = 0;
m_vboVertex = 0;
m_vboIndex = 0;
lats = 40;
longs = 40;
}
Sphere::~Sphere()
{
}
void Sphere::init(GLuint vertexPositionID)
{
int i, j;
std::vector<GLfloat> vertices;
std::vector<GLuint> indices;
int indicator = 0;
for(i = 0; i <= lats; i++) {
double lat0 = glm::pi<double>() * (-0.5 + (double) (i - 1) / lats);
double z0 = sin(lat0);
double zr0 = cos(lat0);
double lat1 = glm::pi<double>() * (-0.5 + (double) i / lats);
double z1 = sin(lat1);
double zr1 = cos(lat1);
for(j = 0; j <= longs; j++) {
double lng = 2 * glm::pi<double>() * (double) (j - 1) / longs;
double x = cos(lng);
double y = sin(lng);
vertices.push_back(x * zr0);
vertices.push_back(y * zr0);
vertices.push_back(z0);
indices.push_back(indicator);
indicator++;
vertices.push_back(x * zr1);
vertices.push_back(y * zr1);
vertices.push_back(z1);
indices.push_back(indicator);
indicator++;
}
indices.push_back(GL_PRIMITIVE_RESTART_FIXED_INDEX);
}
// 创建并绑定环境
glGenVertexArrays(1, &m_vao);
glBindVertexArray(m_vao);
glGenBuffers(1, &m_vboVertex);
glBindBuffer(GL_ARRAY_BUFFER, m_vboVertex);
glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(GLfloat), &vertices[0], GL_STATIC_DRAW);
glVertexAttribPointer(vertexPositionID, 3, GL_FLOAT, GL_FALSE, 0, NULL);
glEnableVertexAttribArray (vertexPositionID);
glGenBuffers(1, &m_vboIndex);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_vboIndex);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(GLuint), &indices[0], GL_STATIC_DRAW);
numsToDraw = indices.size();
isInited = true;
}
void Sphere::cleanup()
{
if (!isInited) {
return;
}
if(m_vboVertex) {
glDeleteBuffers(1, &m_vboVertex);
}
if(m_vboIndex) {
glDeleteBuffers(1, &m_vboIndex);
}
if (m_vao) {
glDeleteVertexArrays(1, &m_vao);
}
isInited = false;
m_vao = 0;
m_vboVertex = 0;
m_vboIndex = 0;
}
void Sphere::draw()
{
if (!isInited) {
std::cout << "please call init() before draw()" << std::endl;
}
// draw sphere
glBindVertexArray(m_vao);
glEnable(GL_PRIMITIVE_RESTART);
glPrimitiveRestartIndex(GL_PRIMITIVE_RESTART_FIXED_INDEX);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_vboIndex);
glDrawElements(GL_QUAD_STRIP, numsToDraw, GL_UNSIGNED_INT, NULL);
}
#ifndef SPHERE_H
#define SPHERE_H
#include <GL/glew.h>
class Sphere
{
public:
Sphere();
~Sphere();
void init(GLuint vertexPositionID);
void cleanup();
void draw();
private:
int lats, longs;
bool isInited;
GLuint m_vao, m_vboVertex, m_vboIndex;
int numsToDraw;
};
#endif // SPHERE_H
#version 120
void main(){
// Output color = color of the texture at the specified UV
gl_FragColor = vec4 (1.0, 0.0, 0.0, 1.0);
}
#version 120
// Input vertex data, different for all executions of this shader.
attribute vec3 vertexPosition_modelspace;
// Output data ; will be interpolated for each fragment.
varying vec2 UV;
uniform mat4 projMatrix;
uniform mat4 mvMatrix;
void main()
{
gl_Position = projMatrix * mvMatrix * vec4(vertexPosition_modelspace, 1);
}
void initializeGL()
{
// Load shaders, link program for drawing sphere
m_sphereProgramID = LoadShaders("shader/sphereShader.vert", "shader/sphereShader.frag");
GLuint vertexPosition_modelspaceID = glGetAttribLocation(m_sphereProgramID, "vertexPosition_modelspace");
// load OpenGL resources needed by the sphere
// pass the vertex position id to it
sphere.init(vertexPosition_modelspaceID);
}
void paintGL() {
// use corresponding shader program, and set the transformation matrices
glUseProgram(m_sphereProgramID);
GLuint projMatrixID = glGetUniformLocation(m_sphereProgramID, "projMatrix");
GLuint mvMatrixID = glGetUniformLocation(m_sphereProgramID, "mvMatrix");
glUniformMatrix4fv(projMatrixID, 1, GL_FALSE, glm::value_ptr(m_projMatrix));
glUniformMatrix4fv(mvMatrixID, 1, GL_FALSE, glm::value_ptr(m_mvMatrix));
sphere.draw();
}
void cleanUp() {
sphere.cleanup();
}
@zwzmzd
Copy link
Author

zwzmzd commented Mar 10, 2015

OpenGL: An example to draw a sphere with vao and vbo

@alharbin
Copy link

Hi, could you upload the Usage's header file please?

@zivshek
Copy link

zivshek commented Feb 23, 2018

Nice code, but how to set up the UV coordinates, I tried to add uv, but nothings draws.

@lewa-j
Copy link

lewa-j commented Nov 21, 2022

That's not how you use GL_PRIMITIVE_RESTART_FIXED_INDEX.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment