Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Почтовая рассылка

Подписчиков: -1
Последний выпуск: 19.06.2015

Подозрительно низкая скорость... OpenGL

3.4K
10 апреля 2006 года
Dark Magician
37 / / 15.08.2004
Насколько я понимаю, многие навороченные игры работают через OpenGL... И со скоростью у них все в порядке... Я использую OpenGL, GLUT...

Правда, на каждой отрисовке перегенерирую всю сцену, но я понять не могу, как сделать 4 крутящиеся шестеренки без полной перегенерации...

Итак... Крутится 2 шестеренки, сгенерированные из кубиков (через 30 градусов по внутреннему диаметру, и через 60 по внешнему). И так 4 штуки. Все поворачиваю / двигаю /меняю через glScalef, glRotatef, glTransformf.

В полноэкранном режиме FPS равен 3 (!!!), в мелком окошке 200х200 доходит до 20. Но, понятно что что-то не так... Тормоза дикие... Почему, не понимаю... Весь код ниже. Помогите glutSolidTeapot'у...... Плиз...

Тут прога, крутит шестерни (физики нет). Если нажать пробел, выскочит 2D окошко.

И еще вопрос: как сделать так чтобы наложить друг на друга несколько полупрозрачных объектов? А то я рисую два, нормально. На третьем траблы. (Белые линии в окне при появлении / сокрытии)

Заранее ОЧЕНЬ благодарен...

Код:
#include <stdio.h>
#include <GL/glut.h>
#include <GL/gl.h>

// Глобальные переменные
int      WindW, WindH;
int      i, frames = 0, time2, elapsedTime;
int      isDrawMenu = 0, isDMProc = 0, lab = 3;
int      oldx, oldy, mtn = 0;
float    mBlend = 0.0;
bool     isByTimer = false;
GLfloat  alpha = 0.0f, beta = 0.0f, automat = 0.0f;

void timf(int) // Idle function
{
  isByTimer = true;
  glutTimerFunc(40, timf, 0);            // Set up timer for 40ms, about 25 fps
  glutPostRedisplay();  // Redraw windows
}

void Reshape(int width, int height) // Reshape function
{
  glViewport(0, 0, width, height);
  /*glMatrixMode(GL_PROJECTION);
  glLoadIdentity();
  */gluOrtho2D(-1, 1, -1, 1);
  glMatrixMode(GL_MODELVIEW);
 
  WindW = width;
  WindH = height;
}

void DrawCubes(int ft, float basic)
{
    GLfloat diffCoeff [] = {0.2, 0.4, 0.9, 1.0};
    GLfloat splrCoeff [] = {1.0, 1.0, 1.0, 1.0};
    GLfloat angle = 0.0f;

    // Создаем кубики
    while (angle <= 360.0)
    {
        if ( ft )
        {
            glPushMatrix();
                glRotatef(angle + basic, 0.0f, 0.0f, 1.0f);
                glTranslatef(0.8f, 0.0f, 1.0f);
                glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, diffCoeff);
                glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, splrCoeff);
                glutSolidCube(0.4f * (1.0f - mBlend)); 
            glPopMatrix();
        }
        glPushMatrix();
            glRotatef(angle + basic, 0.0f, 0.0f, 1.0f);
            glTranslatef(0.5f, 0.0f, 1.0f);
            glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, diffCoeff);
            glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, splrCoeff);
            glutSolidCube(0.4f * (1.0f - mBlend)); 
        glPopMatrix();
        angle += 30.0f;
        ft = !ft;
    }
}

void DrawScene(GLfloat base)
{
    glPushMatrix();
    glScalef(0.5, 0.5, 0.5);
    glRotatef(automat,  1.0f, 1.0f, 1.0f);

        glPushMatrix();
            glRotatef(90.0f, 0.0f, 1.0f, 0.0f);
            DrawCubes(0, base);
            glRotatef(180.0f, 0.0f, 1.0f, 0.0f);
            DrawCubes(0, base);
        glPopMatrix();

        glPushMatrix();
            glRotatef(90.0f, 1.0f, 0.0f, 0.0f);
            DrawCubes(0, -base);
            glRotatef(180.0f, 1.0f, 0.0f, 0.0f);
            DrawCubes(0, -base);
        glPopMatrix();
    glPopMatrix();
}

void Draw2D(void)
{
  float mB = mBlend * mBlend;

  glEnable(GL_BLEND);
  glDepthMask(GL_FALSE);
  glLineWidth(2);
  glPushMatrix();
  glScalef(1.0,mBlend,1.0);
  glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

    glLineWidth(2);

    glEnable(GL_POLYGON_STIPPLE);
        glPolygonMode(GL_FRONT, GL_FILL);
        glColor4f(0.2f, 0.2f, 0.2f, 0.5f * mB);
        glRectf(-0.7f, -0.7f, 0.7f, 0.7f);
        glColor4f(0.2f, 0.2f, 0.2f, 0.5f * mB);
        glRectf(-0.75f, -0.75f, 0.75f, 0.75f);
    glDisable(GL_POLYGON_STIPPLE);

    glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);

    glColor4f(1.0f, 1.0f, 1.0f, 1.0f * mB);

    // Линии, по очереди
    glBegin(GL_LINE_STRIP);
        glVertex2f(-0.6f, -0.6f);
        glVertex2f(-0.1f, -0.6f);
        glVertex2f(-0.6f, -0.35f);
        glVertex2f(-0.1f, -0.35f);
        glVertex2f(-0.6f, -0.1f);
        glVertex2f(-0.1f, -0.1f);
    glEnd();

    // Линии, циклом
    glBegin(GL_LINE_LOOP);
        glVertex2f(0.6f, -0.6f);
        glVertex2f(0.1f, -0.6f);
        glVertex2f(0.6f, -0.35f);
        glVertex2f(0.1f, -0.35f);
        glVertex2f(0.6f, -0.1f);
        glVertex2f(0.1f, -0.1f);
    glEnd();

    // Треугольники
    glBegin(GL_TRIANGLE_STRIP);
        glVertex2f(0.1f, 0.35f);
        glVertex2f(0.2f, 0.1f);
        glVertex2f(0.2f, 0.6f);

        glVertex2f(0.5f, 0.1f);
        glVertex2f(0.5f, 0.6f);
        glVertex2f(0.6f, 0.35f);
    glEnd();

    // Треугольники
    glBegin(GL_QUAD_STRIP);
        glVertex2f(-0.1f, 0.35f);
        glVertex2f(-0.2f, 0.1f);
        glVertex2f(-0.2f, 0.6f);

        glVertex2f(-0.5f, 0.1f);
        glVertex2f(-0.5f, 0.6f);
        glVertex2f(-0.6f, 0.35f);
    glEnd();

    glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);

  glPopMatrix();
  glDepthMask(GL_TRUE);
  glDisable(GL_BLEND);
}

void Draw(void) // Window redraw function
{

  GLfloat whiteColor [] = {1.0, 1.0, 1.0, 1.0};

  isByTimer = false;

  glLoadIdentity();
  glClear(GL_COLOR_BUFFER_BIT);
  glClear(GL_DEPTH_BUFFER_BIT);

  glEnable(GL_DEPTH_TEST);
  glEnable(GL_LIGHTING);

  glColor3f (0, 1, 0);

  GLfloat light1 [] = {-10.0, -10.0, -10.0, 1.0};
  glLightfv(GL_LIGHT1, GL_POSITION, light1);
  glLightfv(GL_LIGHT1, GL_DIFFUSE, whiteColor);
  glEnable(GL_LIGHT1);

  // Крутим шестеренки
  glPushMatrix();
    glRotatef(alpha,    1.0f, 0.0f, 0.0f);
    glRotatef(beta ,    0.0f, 1.0f, 0.0f);
    DrawScene(automat);
  glPopMatrix();

  // Отключаем свет и 3D

  glDisable(GL_LIGHTING);
  glDisable(GL_DEPTH_TEST);
 
  if ( !mtn ) {
      automat += 1;
      if (automat > 359) automat = 0;
  }

  // Далее рисуем Меню
  if ( isDrawMenu || mBlend > 0.0 ) Draw2D();
 

  // Выводим FPS
  frames++;

  if(!(frames % 5))
  {
        int   time2 = glutGet( GLUT_ELAPSED_TIME );
        char  str[256];
        float fps  = (float) frames / (0.001 *(time2 - elapsedTime));
        elapsedTime = time2;
        frames = 0;
        sprintf ( str, "Лабораторная %d (Сидристый Ст. А. 2341): FPS = %5.2f", lab, fps );
        glutSetWindowTitle( str );
  }

  if( mBlend >= 1.0 &&  isDrawMenu ) isDMProc = 0;
  if( mBlend <= 0.0 && !isDrawMenu ) isDMProc = 0;
  if( isDMProc ) mBlend += ( isDrawMenu ? 1.0 : (-1.0) ) * 0.16333;
 
  glFlush();
}

void kbFunc(unsigned char key, int x, int y)
{
    if ( key == ' ' ) {
        isDrawMenu = (isDrawMenu == 0 ? 1 : 0 );
        lab        = (isDrawMenu == 0 ? 3 : 1 );
        //mBlend     = float(!isDrawMenu);
        isDMProc   = 1;
    }
}

void motion (int x, int y)
{
    if(mtn)
    {
        alpha += (oldy - y) / 3.0;
        beta  += (oldx - x) / 3.0;
        oldy = y;
        oldx = x;
    }
}
void mouse (int button, int state, int x, int y)
{
    if ( button == GLUT_LEFT_BUTTON )
    {
        if (!mtn) { oldx = x; oldy = y; }
        mtn = ( state == GLUT_DOWN );
    }
}

int main(int argc, char *argv[])
{
  WindW = 400;
  WindH = 400;
 
  glutInit(&argc, argv);
  glutInitWindowSize(WindW, WindH);
  glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH);
  (void)glutCreateWindow("Лабораторная 1");

  glutReshapeFunc  ( Reshape );              // Set up reshape function
  glutDisplayFunc  ( Draw );                 // Set up redisplay function
  glutTimerFunc    ( 40, timf, 0 );          // Set up timer for 40ms, about 25 fps
  glutMouseFunc    ( mouse );
  glutMotionFunc   ( motion );
  glutKeyboardFunc ( kbFunc );
  glClearColor(0, 0, 0, 0);

  isByTimer = true;
  glutMainLoop();
  return 0;
}
279
10 апреля 2006 года
bave
456 / / 07.03.2004
То что сцена переирисовыется каждый кадр - это нормально, это стандартная практика, все так делают. Но дело вот в чем:
1.Зачем тебе GLUT - тебе нужна переносимость на разные ОСи? Если пишешь под
конктрктную ОС используй её API.
2. Не увидел у тебя двоной буфферизации (может плохо смотрел) - ну и следственно: нету синхронизации с частотой монитора (если время кадра не кратно обновлению монитора - это еще тормоза (только при двойно буфферизации - некоторые функции переключения буфферов ждут
обновления экрана)).
3. Для визуализации одинаковых шестерёнок используй списки отображения (Dispaly Lists).
----------------------------------------------
По какому из этих пунктов написать подробней?
3.4K
10 апреля 2006 года
Dark Magician
37 / / 15.08.2004
По двойной буферизации... Не понял... А как тогда надо?
279
10 апреля 2006 года
bave
456 / / 07.03.2004
Уже увидел вот это - GLUT_DOUBLE - видимо в
GLUT двоиная буфферизация так и задаётся, но
я невижу где у тебя буфферы переключаются.
GLUT сам выполняет функцию SwapBuffers()?
-----------------------------------------------
У тебя есть возможность писать на чистом WinAPI +
OpenGL или надо обязон GLUT использовать?
-----------------------------------------------
До выходных время есть? - Я бы в выходные
переписал твой код посвоему и посмотрел бы как у меня поидёт. А то я GLUTом то никогда не пользуюсь.
255
11 апреля 2006 года
Dart Bobr
1.4K / / 09.04.2004
Юзай списки, как сказал товарищ выше - это раз.
Поворот выполняй при помощи вертексного шейдера - это два.
Чем меньше glBegin()/glEnd(), тем быстрее - это три.
Проверь так же вывод fps. Возможно sprintf - тормозит все. Точно не скажу - надо проверить. Я таких функций никогда не юзаю. :)
534
11 апреля 2006 года
HarryAxe
448 / / 19.01.2006
И ещё задние грани отсекай там, где не используешь полупрозрачность (да даже если и используещь, ситуации, где тебе нужен именно двусторонний материал, можно по пальцам сосчитать). Вместо флага GL_FRONT_AND_BACK используй GL_FRONT.
3.4K
13 апреля 2006 года
Dark Magician
37 / / 15.08.2004
Ой, народ, спасибо!! Я думал, ответов не будет, решил просто так зайти... :) А тут... дофига всего :).

Ну 3Д я отрубаю когда не пользуюсь и прозрачность тут врубается только когда надо...
Тут основная ф-ия - Draw. В в зависимости от режима основной будет либо DrawScene (шестеренки) либо полупрозрачность ( Draw2D - меню поверх всего ). DrawCubes рисует шестеренку.

Насчет переключения буферов - это делается в основной ф-ии ( Draw ). Тут написано glFlush(); но у меня сейчас - glutSwapBuffers(); Скорость та же, ничего не меняется.

А вообще в качестве библиотеки (LIB файлов при компиляции) использую MesaGL и GLUT Mesa. Но она существует довольно давно и вещь довольно крутая, так что думаю, дело не в ней...

GLUT мне действительно нужен для переносимости. Хотя если окажется что собака порылась именно в GLUT, придется писать разные main.cpp чтоб стыковать с разными оконными системами разных ОС...

GL_FRONT_AND_BACK я использую для отрисовки каркаса некоторых фигур (но не пугайтесь, фичу с отрисовкой линий треугольниками я знаю, каркасы работают только в 2D, в 3D они отключены...)

sprintf сильно тормозить не должен... За N лет существования стандартной библиотеки я думаю, он оптимизирован :) да и параметров там не много... Да и проверял я уже... :)

Огромное спасибо за ответы... Буду рад если bave посмотрит на выходных, очень рад :)
3.4K
13 апреля 2006 года
Dark Magician
37 / / 15.08.2004
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
я заменил на GL_BACK (почему-то GL_FRONT выдал задние стороны) особого прироста производительности не нашел...
С видяхой заранее все нормаьльно... DOOM III идет без тормозов...
3.4K
14 апреля 2006 года
Dark Magician
37 / / 15.08.2004
Да... Не думал что GLUT настолько тормозной...
WinApi дает 90 FPS... Победа!
Только не понятно почему перестали грани давать разную освещенность, т.е. при любом угле наклона цвет один...
Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог