Рисование круга с помощью OpenGL

Я пытаюсь нарисовать простой круг с помощью C ++ / OpenGl

мой код:

#include <GL/glut.h>
#include <math.h>

void Draw() {
    glClear(GL_COLOR_BUFFER_BIT);
    glColor3f(1.0, 1.0, 1.0);

    glBegin(GL_QUADS);
      glColor3f (0.0, 0.0, 0.0);

      glVertex3f (0.1, 0.1, 0.0);
      glVertex3f (0.9, 0.1, 0.0);
      glVertex3f (0.9, 0.9, 0.0);
      glVertex3f (0.1, 0.9, 0.0);

    glEnd();

    glFlush();
}

void DrawCircle(float cx, float cy, float r, int num_segments)
{
    glBegin(GL_LINE_LOOP);
    for(int ii = 0; ii < num_segments; ii++)
    {
        float theta = 2.0f * 3.1415926f * float(ii) / float(num_segments);//get the current angle

        float x = r * cosf(theta);//calculate the x component
        float y = r * sinf(theta);//calculate the y component

        glVertex2f(x + cx, y + cy);//output vertex

    }
    glEnd();
}


void Initialize() {
    glClearColor(1.0, 1.0, 1.0, 0.0);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    glOrtho(0.0, 1.0, 0.0, 1.0, -1.0, 1.0);
}

int main(int iArgc, char** cppArgv) {
    glutInit(&iArgc, cppArgv);
    glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
    glutInitWindowSize(950, 500);
    glutInitWindowPosition(200, 200);
    glutCreateWindow("Universum");
    Initialize();
    glutDisplayFunc(Draw);
    glClear(GL_COLOR_BUFFER_BIT);
    glColor3f(1.0, 1.0, 1.0);
    DrawCircle(0.5, 0.5, 0.2, 5);

    glutMainLoop();
    return 0;

}

Я новичок в OpenGL, и теперь я начинаю учиться. Может кто-нибудь, пожалуйста, объясните мне, почему я не вижу кружок (я вижу только черный ящик), Спасибо!


person tonyhlav    schedule 16.03.2014    source источник


Ответы (7)


Похоже, что сразу после того, как вы нарисуете круг, вы перейдете в основной цикл перенасыщения, где вы установили функцию Draw() для рисования каждый раз в цикле. Так что, вероятно, он рисует круг, затем сразу стирает его и рисует квадрат. Вам, вероятно, следует либо сделать DrawCircle() свой glutDisplayFunc(), либо позвонить DrawCircle() из Draw().

person user1118321    schedule 16.03.2014
comment
Тай! вызов DrawCircle () из Draw () - это сработало! Кстати, есть ли способ сделать круг заполненным цветом? - person tonyhlav; 17.03.2014
comment
Чтобы получить закрашенный круг, вы можете изменить GL_LINE_LOOP на GL_TRIANGLE_FAN. - person user3256930; 17.03.2014
comment
Как упоминалось выше, используйте GL_TRIANGLE_FAN, но обратите внимание, что вам нужно поставить первую точку в центре круга. - person user1118321; 17.03.2014
comment
@ user1118321: Вершина в центре на самом деле не нужна, так как форма выпуклая. - person Ben Voigt; 19.07.2014

#include <Windows.h>
#include <GL/glu.h>
#include <GL/glut.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#define window_width  1080  
#define window_height 720 
void drawFilledSun(){
    //static float angle;
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glLoadIdentity();
    glTranslatef(0, 0, -10);
    int i, x, y;
    double radius = 0.30;
    //glColor3ub(253, 184, 19);     
    glColor3ub(255, 0, 0);
    double twicePi = 2.0 * 3.142;
    x = 0, y = 0;
    glBegin(GL_TRIANGLE_FAN); //BEGIN CIRCLE
    glVertex2f(x, y); // center of circle
    for (i = 0; i <= 20; i++)   {
        glVertex2f (
            (x + (radius * cos(i * twicePi / 20))), (y + (radius * sin(i * twicePi / 20)))
            );
    }
    glEnd(); //END
}
void DrawCircle(float cx, float cy, float r, int num_segments) {
    glBegin(GL_LINE_LOOP);
    for (int ii = 0; ii < num_segments; ii++)   {
        float theta = 2.0f * 3.1415926f * float(ii) / float(num_segments);//get the current angle 
        float x = r * cosf(theta);//calculate the x component 
        float y = r * sinf(theta);//calculate the y component 
        glVertex2f(x + cx, y + cy);//output vertex 
    }
    glEnd();
}
void main_loop_function() {
    int c;
    drawFilledSun();
    DrawCircle(0, 0, 0.7, 100);
    glutSwapBuffers();
    c = getchar();
}
void GL_Setup(int width, int height) {
    glViewport(0, 0, width, height);
    glMatrixMode(GL_PROJECTION);
    glEnable(GL_DEPTH_TEST);
    gluPerspective(45, (float)width / height, .1, 100);
    glMatrixMode(GL_MODELVIEW);
}
int main(int argc, char** argv) {
    glutInit(&argc, argv);
    glutInitWindowSize(window_width, window_height);
    glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE);
    glutCreateWindow("GLUT Example!!!");
    glutIdleFunc(main_loop_function);
    GL_Setup(window_width, window_height);
    glutMainLoop();
}

Вот что я сделал. Надеюсь, это поможет. Здесь есть два типа кругов. Заполненные и незаполненные.

person Farah Nazifa    schedule 19.07.2014

Есть еще один способ нарисовать круг - нарисовать его во фрагментном шейдере. Создайте четырехугольник:

float right = 0.5;
float bottom = -0.5;
float left = -0.5;
float top = 0.5;
float quad[20] = {
    //x, y, z, lx, ly
    right, bottom, 0, 1.0, -1.0,
    right, top, 0, 1.0, 1.0,
    left, top, 0, -1.0, 1.0,
    left, bottom, 0, -1.0, -1.0,
};

Привязать VBO:

unsigned int glBuffer;
glGenBuffers(1, &glBuffer);
glBindBuffer(GL_ARRAY_BUFFER, glBuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(float)*20, quad, GL_STATIC_DRAW);

и нарисуйте:

#define BUFFER_OFFSET(i) ((char *)NULL + (i))
glEnableVertexAttribArray(ATTRIB_VERTEX);
glEnableVertexAttribArray(ATTRIB_VALUE);
glVertexAttribPointer(ATTRIB_VERTEX , 3, GL_FLOAT, GL_FALSE, 20, 0);
glVertexAttribPointer(ATTRIB_VALUE , 2, GL_FLOAT, GL_FALSE, 20, BUFFER_OFFSET(12));
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);

Вершинный шейдер

attribute vec2 value;
uniform mat4 viewMatrix;
uniform mat4 projectionMatrix;
varying vec2 val;
void main() {
    val = value;
    gl_Position = projectionMatrix*viewMatrix*vertex;
}

Фрагментный шейдер

varying vec2 val;
void main() {
    float R = 1.0;
    float R2 = 0.5;
    float dist = sqrt(dot(val,val));
    if (dist >= R || dist <= R2) {
        discard;
    }
    float sm = smoothstep(R,R-0.01,dist);
    float sm2 = smoothstep(R2,R2+0.01,dist);
    float alpha = sm*sm2;
    gl_FragColor = vec4(0.0, 0.0, 1.0, alpha);
}

Не забудьте включить альфа-смешивание:

glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);

ОБНОВЛЕНИЕ: Подробнее…

person S.Lapin    schedule 18.05.2018

Мы найдем значения X и Y на этом изображении. Мы знаем, что sinθ = вертикаль / гипотенуза и cosθ = основание / гипотенуза из изображения, мы можем сказать base = X и Y = vertical. Теперь мы можем написать X = гипотенуза  * cosθ и Y = гипотенуза * sinθ. Мы найдем значения X и Y на этом изображении. Мы знаем, что sinθ = вертикаль / гипотенуза и cosθ = база / гипотенуза из изображения, мы можем сказать, что X = база и Y = вертикаль. Теперь мы можем записать X = гипотенуза * cosθ и Y = гипотенуза * sinθ.

Теперь посмотрим на этот код

void display(){
float x,y;
glColor3f(1, 1, 0);
for(double i =0; i <= 360;){
    glBegin(GL_TRIANGLES);
    x=5*cos(i);
    y=5*sin(i);
    glVertex2d(x, y);
    i=i+.5;
    x=5*cos(i);
    y=5*sin(i);
    glVertex2d(x, y);
    glVertex2d(0, 0);
    glEnd();
    i=i+.5;
}
glEnd();

glutSwapBuffers();
}
person Habibur Rahman    schedule 04.10.2018

Вот код для рисования эллипса заливки, вы можете использовать тот же метод, но заменив de xcenter и y center на радиус

void drawFilledelipse(GLfloat x, GLfloat y, GLfloat xcenter,GLfloat ycenter) {
    int i;
    int triangleAmount = 20; //# of triangles used to draw circle

    //GLfloat radius = 0.8f; //radius
    GLfloat twicePi = 2.0f * PI;

    glBegin(GL_TRIANGLE_FAN);
    glVertex2f(x, y); // center of circle
    for (i = 0; i <= triangleAmount; i++) {
        glVertex2f(
            x + ((xcenter+1)* cos(i * twicePi / triangleAmount)),
            y + ((ycenter-1)* sin(i * twicePi / triangleAmount))
        );
    }
    glEnd();
}
person Ginnelle Gracia    schedule 04.10.2019

Я сделал это, используя следующий код,

glBegin(GL.GL_LINE_LOOP);
     for(int i =0; i <= 300; i++){
         double angle = 2 * Math.PI * i / 300;
         double x = Math.cos(angle);
         double y = Math.sin(angle);
         gl.glVertex2d(x,y);
     }
glEnd();
person Codemaker    schedule 24.07.2018

person    schedule
comment
// Я сделал это с помощью следующего кода, // но убедитесь, что вы импортировали нужную библиотеку - person Darken_Cat; 12.02.2021
comment
Хотя этот код может ответить на вопрос, предоставление дополнительного контекста относительно того, почему и / или как этот код отвечает на вопрос, улучшает его долгосрочную ценность. - person Tyler2P; 12.02.2021