![](/img/trans.png)
[英]How the heck do you use GL_TRIANGLE_FAN to draw a circle in OpenGL?
[英]GL_TRIANGLE_FAN to draw a circle
我正在使用GL_TRIANGLE_FAN画一个圆。 当我使用其他Triangle类型的原语时,会得到一些三角形,但是当我使用GL_TRIANGLE_FAN时,会出现空白屏幕。 我对此并不陌生,但我没有弄错我要去的地方。
#include <string>
#include <fstream>
#include <iostream>
#include <sstream>
#include <vector>
//Include GLEW
#include <GL/glew.h>
//Include GLFW
#include <glfw3.h>
#include <GL/glut.h>
#include <GL/gl.h>
#include <math.h>
int width;
int height;
float r;
float theta;
GLuint vboHandle[1];
GLuint indexVBO;
struct vertex
{
double x, y;
double u, v;
double r, g, b;
}temp;
std::vector<vertex> vertices;
std::vector<GLuint64> indeces;
void initNormal(){
float a=0;
int value1 = 1;
double radius = 0.3;
double centerX = 0;
double centerY = 0;
double theta = 0;
//u,v,r,g,b are dummy for now
temp.x = 0;
temp.y = 0;
temp.u = a;
temp.v = a;
temp.r = a;
temp.g = a;
temp.b = a;
vertices.push_back(temp);
indeces.push_back(0);
for (int i = 1; i <= 72; i++){
a = a+0.10;
temp.x = radius*cos(((22 / 7.0) / 180.0)*theta);
temp.y = radius*sin(((22 / 7.0) / 180.0)*theta);
temp.u = a;
temp.v = a;//value1 / (i * 2);
temp.r = a;//value1 / i;
temp.g = a; //value1 / (i * 2);
temp.b = a;//value1 / i;
std::ofstream ofs;
vertices.push_back(temp);
indeces.push_back(i);
theta = theta + 10;
}
}
void initVbo(){
GLenum err = glewInit();
if (err != GLEW_OK) {
fprintf(stderr, "Error: %s\n", glewGetErrorString(err));
//return -1;
}
glPointSize(10);
glGenBuffers(1, &vboHandle[0]); // create a VBO handle
glBindBuffer(GL_ARRAY_BUFFER, vboHandle[0]); // bind the handle to the current VBO
glBufferData(GL_ARRAY_BUFFER, sizeof(vertex)* vertices.size(), &vertices[0], GL_DYNAMIC_DRAW); // allocate space and copy the data over
glBindBuffer(GL_ARRAY_BUFFER, 0); // clean up
glGenBuffers(1, &indexVBO);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexVBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLuint64)*indeces.size(), &indeces[0], GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); //clean up
}
void display(){
glClearColor(0, 0, 0, 1);
glClear(GL_COLOR_BUFFER_BIT);
glColor4f(1, 1, 1, 1);
glEnableClientState(GL_VERTEX_ARRAY);
glBindBuffer(GL_ARRAY_BUFFER, vboHandle[0]);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexVBO);
glVertexPointer(2, GL_DOUBLE, sizeof(vertex), 0);
glDrawElements(GL_TRIANGLES, indeces.size(), GL_UNSIGNED_INT, (char*)NULL + 0);//2 indeces needed to make one line
glFlush();
}
void initializeGlut(int argc, char** argv){
std::cout << "entered";
glutInit(&argc, argv);
width = 800;
height = 800;
glutInitDisplayMode(GLUT_RGB | GLUT_SINGLE);
glutInitWindowSize(width, height);
glutCreateWindow("Bhavya's Program");
glutDisplayFunc(display);
}
void main(int argc, char** argv){
initializeGlut(argc, argv);
initNormal();
initVbo();
//glutReshapeFunc(reshape);
glutMainLoop();
}
代码中的主要问题是索引值使用的类型错误:
std::vector<GLuint64> indeces;
GLuint64
不是有效的索引类型,并且它肯定与draw命令中指定的索引类型不匹配:
glDrawElements(GL_TRIANGLES, indeces.size(), GL_UNSIGNED_INT, ...);
将所有出现的GLuint64
替换为正确的类型GLuint
,您应该开始看到一些东西。
如果使用错误的类型来绘制索引缓冲区的内存布局,则在使用GL_TRIANGLE_FAN
进行绘制时根本看不到任何东西的原因变得更加清楚。 如果您编写一个由64位值组成的序列,然后将其解释为32位值,则每个第二个值将被读取为值0。
使用GL_TRIANGLE_FAN
,所有三角形均由第一个索引(您将其设置为0)和数组中的两个顺序索引组成。 在第二个索引读取为0的情况下,这意味着每个三角形都有两个值为0的索引。这又意味着所有三角形均退化,并且不会点亮任何像素。
圆图绘制代码也将需要一些改进。 现在,您正在从0到720度循环播放,它将绕圆旋转两次。 同样,22/7是pi的非常近似值。 您可能想使用数学头文件中更精确的常量定义。
虽然这不是正确性问题,但我也将避免对顶点属性使用双精度值。 OpenGL实现在内部使用浮点数。 如果将属性指定为double,则将仅使用额外的内存,并增加开销以将值从double转换为float。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.