проблемы с рисованием тени при использовании OpenGL

Модератор: Модераторы разделов

aureli0
Сообщения: 3

проблемы с рисованием тени при использовании OpenGL

Сообщение aureli0 »

Сейчас я делаю скрул шутер-леталка сверху, на подобии Tyrian, Raptor, Raiden и т.п. Пишу на с++ с использованием SDL+OpenGL

Я использовал для вывода спрайта затекстурированный полигон, каждый спрайт(его текстура) находиться в отдельных *.png файлах.
Эта процедура имеет примерно такой вид (процедура 1):

Код: Выделить всё

//рисуем затекстурированый полигон
void DrawTXT (float x,
              float y,
              float dX,
              float dY,
              float delta,
              int center)
{
    glLoadIdentity();
    glTranslatef(x,y,0);
    glRotatef(delta,0,0,-1);
    if (center==1) {glTranslatef(-dX/2,-dY/2,0);}//смещаем по центре

    glBegin( GL_QUADS );
        // Верхний левый угол
        glTexCoord2i(0,0);      glVertex2f( 0, 0 );
        //Нижний левый угол
        glTexCoord2i( 0, 1 );  glVertex2f( 0, dY );
        //Нижний правый угол
        glTexCoord2i( 1, 1 );  glVertex2f( dX, dY );
        //Верхний правый угол
        glTexCoord2i( 1, 0 );  glVertex2f( dX, 0 );
    glEnd();
    glLoadIdentity();
}

Захотелось использовать одну общую текстуру (с набором спрайтов). Спрайт получать закрашивая полигон задавая текстурные координаты, и процедура стала иметь вид (процедура 2):

Код: Выделить всё

//рисуем затекстурированый полигон из общей текстуры
void _DrawTXT (float W,//размеры всей текстуры
              float H,
              float t_x,//координаты верхнего левого угла в текстуре
              float t_y,
              float t_dx,//размеры куска текстуры
              float t_dy,

              float x,
              float y,
              float dX,
              float dY,
              float delta,//угол поворота
              int center)
{
    glLoadIdentity();
    glTranslatef(x,y,0);
    glRotatef(delta,0,0,-1);
    if (center==1) {glTranslatef(-dX/2,-dY/2,0);}//смещаем по центре

    glBegin( GL_QUADS );
        // Верхний левый угол
        glTexCoord2f((t_x/W),(t_y/H));      glVertex2f( 0, 0 );
        //Нижний левый угол
        glTexCoord2f((t_x/W),((t_y+t_dy)/H));  glVertex2f( 0, dY );
        //Нижний правый угол
        glTexCoord2f(((t_x+t_dx)/W),((t_y+t_dy)/H));  glVertex2f( dX, dY );
        //Верхний правый угол
        glTexCoord2f(((t_x+t_dx)/W), (t_y/H) );  glVertex2f( dX, 0 );
    glEnd();

  glLoadIdentity();

}


В игре для летающих объектов хочется сделать тень, отбрасываемую ими на землю. Посоветовали использовать для этих целей буфер трафарета, вот примерно так это выглядит:

Код: Выделить всё

//цвета теней не смешиваються!!! работает с глюками при выводе уровня из единой текстуры
      glEnable(GL_STENCIL_TEST);//включаем трафарет
      glStencilFunc(GL_ALWAYS, 1, 255);//в том месте где рисуется трафарет значение буфера заменяем на 1
      glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
      glEnable(GL_ALPHA_TEST);      //надо отсечь рисования прозрачных пикселей уровня
      glAlphaFunc(GL_GREATER,0.5f); //выводим только те пиксели уровня у которых alpha > 0.5f
        level_draw();//уровень является трафаретом-только на нем видна тень
      glStencilFunc(GL_EQUAL, 1, 255);// тень будет рисоваться только в тех местах,где значение в буфере 1
      glStencilOp(GL_KEEP, GL_KEEP, GL_ZERO);
      glAlphaFunc(GL_GREATER,0.45f); //выводим только те пиксели тени у которых alpha > 0.45f
        player_shadow_draw();
        enemy_air_shadow_draw();
      glDisable(GL_ALPHA_TEST);
      glDisable(GL_STENCIL_TEST);//отключаем трафарет


Если использовать для вывода трафарета level_draw процедуру 1, то тень рисуется как надо-только на трафарете, учитываются спрайты с "дырками" альфа канала (на дырках тени не должно быть), тени не смешиваются. НО мне хочется использовать для вывода level_draw процедуру 2, так проще. Если так сделать то начинаются появлятся глюки-тени иногда мигают, пропадают на некоторое время или просто не рисуются. Я думаю что это из-за альфа теста и альфа функа , если их убрать тени будут рисоваться на всех спрайтах level_draw, включая "дыры" альфа канала.

Хочется вывода нормальных теней при использовании процедуры 2, как при использовании процедуры 1. То есть, чтобы тени не смешивались, хотя бы не рисовались на "дырах". Как это исправить ?

ЗЫ:я не очень хорошо знаю OpenGL(
Спасибо сказали:
Nibelung
Сообщения: 21

Re: проблемы с рисованием тени при использовании OpenGL

Сообщение Nibelung »

aureli0 писал(а):
16.09.2009 20:47
Сейчас я делаю скрул шутер-леталка сверху, на подобии Tyrian, Raptor, Raiden и т.п. Пишу на с++ с использованием SDL+OpenGL

Я использовал для вывода спрайта затекстурированный полигон, каждый спрайт(его текстура) находиться в отдельных *.png файлах.
Эта процедура имеет примерно такой вид (процедура 1):

Код: Выделить всё

//рисуем затекстурированый полигон
void DrawTXT (float x,
              float y,
              float dX,
              float dY,
              float delta,
              int center)
{
    glLoadIdentity();
    glTranslatef(x,y,0);
    glRotatef(delta,0,0,-1);
    if (center==1) {glTranslatef(-dX/2,-dY/2,0);}//смещаем по центре

    glBegin( GL_QUADS );
        // Верхний левый угол
        glTexCoord2i(0,0);      glVertex2f( 0, 0 );
        //Нижний левый угол
        glTexCoord2i( 0, 1 );  glVertex2f( 0, dY );
        //Нижний правый угол
        glTexCoord2i( 1, 1 );  glVertex2f( dX, dY );
        //Верхний правый угол
        glTexCoord2i( 1, 0 );  glVertex2f( dX, 0 );
    glEnd();
    glLoadIdentity();
}

Захотелось использовать одну общую текстуру (с набором спрайтов). Спрайт получать закрашивая полигон задавая текстурные координаты, и процедура стала иметь вид (процедура 2):

Код: Выделить всё

//рисуем затекстурированый полигон из общей текстуры
void _DrawTXT (float W,//размеры всей текстуры
              float H,
              float t_x,//координаты верхнего левого угла в текстуре
              float t_y,
              float t_dx,//размеры куска текстуры
              float t_dy,

              float x,
              float y,
              float dX,
              float dY,
              float delta,//угол поворота
              int center)
{
    glLoadIdentity();
    glTranslatef(x,y,0);
    glRotatef(delta,0,0,-1);
    if (center==1) {glTranslatef(-dX/2,-dY/2,0);}//смещаем по центре

    glBegin( GL_QUADS );
        // Верхний левый угол
        glTexCoord2f((t_x/W),(t_y/H));      glVertex2f( 0, 0 );
        //Нижний левый угол
        glTexCoord2f((t_x/W),((t_y+t_dy)/H));  glVertex2f( 0, dY );
        //Нижний правый угол
        glTexCoord2f(((t_x+t_dx)/W),((t_y+t_dy)/H));  glVertex2f( dX, dY );
        //Верхний правый угол
        glTexCoord2f(((t_x+t_dx)/W), (t_y/H) );  glVertex2f( dX, 0 );
    glEnd();

  glLoadIdentity();

}


В игре для летающих объектов хочется сделать тень, отбрасываемую ими на землю. Посоветовали использовать для этих целей буфер трафарета, вот примерно так это выглядит:

Код: Выделить всё

//цвета теней не смешиваються!!! работает с глюками при выводе уровня из единой текстуры
      glEnable(GL_STENCIL_TEST);//включаем трафарет
      glStencilFunc(GL_ALWAYS, 1, 255);//в том месте где рисуется трафарет значение буфера заменяем на 1
      glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
      glEnable(GL_ALPHA_TEST);      //надо отсечь рисования прозрачных пикселей уровня
      glAlphaFunc(GL_GREATER,0.5f); //выводим только те пиксели уровня у которых alpha > 0.5f
        level_draw();//уровень является трафаретом-только на нем видна тень
      glStencilFunc(GL_EQUAL, 1, 255);// тень будет рисоваться только в тех местах,где значение в буфере 1
      glStencilOp(GL_KEEP, GL_KEEP, GL_ZERO);
      glAlphaFunc(GL_GREATER,0.45f); //выводим только те пиксели тени у которых alpha > 0.45f
        player_shadow_draw();
        enemy_air_shadow_draw();
      glDisable(GL_ALPHA_TEST);
      glDisable(GL_STENCIL_TEST);//отключаем трафарет


Если использовать для вывода трафарета level_draw процедуру 1, то тень рисуется как надо-только на трафарете, учитываются спрайты с "дырками" альфа канала (на дырках тени не должно быть), тени не смешиваются. НО мне хочется использовать для вывода level_draw процедуру 2, так проще. Если так сделать то начинаются появлятся глюки-тени иногда мигают, пропадают на некоторое время или просто не рисуются. Я думаю что это из-за альфа теста и альфа функа , если их убрать тени будут рисоваться на всех спрайтах level_draw, включая "дыры" альфа канала.

Хочется вывода нормальных теней при использовании процедуры 2, как при использовании процедуры 1. То есть, чтобы тени не смешивались, хотя бы не рисовались на "дырах". Как это исправить ?

ЗЫ:я не очень хорошо знаю OpenGL(


Это тебе надо тут спрашивать
тыц
Intel Core Duo E5400@2,7 GHz, 2048 RAM, 750 Gb Seagate HDD , nVidia 450 GTS, OpenSUSE 11.4 x86_64
Спасибо сказали:
NickLion
Сообщения: 3408
Статус: аватар-невидимка
ОС: openSUSE Tumbleweed x86_64

Re: проблемы с рисованием тени при использовании OpenGL

Сообщение NickLion »

Nibelung, а зачем цитировать весь пост было?

aureli0, если это еще актуально. Хотелось бы увидеть скриншоты - нормального отображения и с глюком, потому что так навскидку причину не увидел. Еще лучше - получить программу (пусть с урезанной функциональностью) в 2-х вариантах.
Спасибо сказали: