|
08.09.2009, 16:49
|
#1
|
ПроЭктировщик
Регистрация: 19.03.2007
Сообщений: 134
Написано 10 полезных сообщений (для 20 пользователей)
|
2d в OpenGL. вывод тени от спрайта
Сейчас делаю игрушку-скролл шутер. Появились трудности с выводом теней.
На данный момент тени от спрайтов вывожу следующим образом:
void enemy_air_shadow_draw()//рисование тени от воздушных юнитов
{
glColor4f(0,0,0,0.5);
glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
for(i=0; i < enemy_max; i++)
{
if (enemy[i].air==1)
{
glBindTexture(GL_TEXTURE_2D,enemy_texture[enemy[i].texture]);
DrawTXT (enemy[i].x*grid_DX+enemy_move_x[i]+x_cam+0.2*(enemy[i].x*grid_DX+enemy_move_x[i]-win_DX/2),
enemy[i].y*grid_DY+enemy_move_y[i]+y_cam+40,
enemy[i].dx,
enemy[i].dy,
0,1);
}
}
glColor4f(1,1,1,1);
glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
}
Но здесь есть ряд проблем: тени выводятся на все элементы уровня и задний фон, а также они смешиваються, становясь темнее.
Как сделать так, чтобы тень появлялась ТОЛЬКО на декорациях уровня(зеленые элементы), а не на картинке заднего плана(космос)?
Как исправить смешение теней?
Последний раз редактировалось aureli0, 08.09.2009 в 20:54.
|
(Offline)
|
|
08.09.2009, 17:00
|
#2
|
|
Ответ: 2d в OpenGL. вывод тени от спрайта
aureli0
можно использовать буфер трафарета (stencil), принцип простой : рисуем задний фон и в трафарет для пикселя пишется 0, рисуем декорации - в трафарет для пикселя пишется 1, ставим условие что рисуем пиксель только если в трафарете 1 и рисуем тени, таким же способом делается отсечения смешивания - после рисования тени пишем в буфер трафарета 2, в итоге следуйшие пиксели тени не смогут быть выведены на этот место потому что в буфере трафарета стоит не 1, а 2
ps. никогда не юзал stencil (но буду), вышенаписанное это мои теоретические знания
|
|
|
Сообщение было полезно следующим пользователям:
|
|
08.09.2009, 20:34
|
#3
|
ПроЭктировщик
Регистрация: 19.03.2007
Сообщений: 134
Написано 10 полезных сообщений (для 20 пользователей)
|
Re: 2d в OpenGL. вывод тени от спрайта
спасибо)
эээээ, значит както так??
//ИНИЦИАЛИЗАЦИЯ
// очищаем все буферы
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
// разрешаем тест трафарета
glEnable(GL_STENCIL_TEST);
//Где то в главном цикле программы
рисуем задний фон
//в трафарет для пикселя пишется 0
glStencilFunc(GL_ALWAYS, 0, 0);
рисуем дикорации
//в трафарет для пикселя пишется 1
glStencilFunc(GL_ALWAYS, 1, 0);
//ставим условие что рисуем пиксель только если в трафарете 1
glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
рисуем тень
//в трафарет для пикселя пишется 2-делаем отсечение смешивания
glStencilFunc(GL_ALWAYS, 2, 0);
рисуем все остальное
смотрел сюда
http://www.opengl.org.ru/books/open_gl/chapter4.12.html
с синтаксисом glStencilFunc и glStencilFunc я так и не разобрался (
У себя ы программе сделал так:
//гдето в главном цикле
//в трафарет для пикселя пишется 0
glStencilFunc(GL_ALWAYS, 0, 0);
level_draw();
enemy_ground_draw();//рисование и анимация наземных врагов
starwind_draw();
//в трафарет для пикселя пишется 1
glStencilFunc(GL_ALWAYS, 1, 0);
//ставим условие что рисуем пиксель только если в трафарете 1
glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
player_shadow_draw();
enemy_air_shadow_draw();
//в трафарет для пикселя пишется 2-делаем отсечение смешивания
glStencilFunc(GL_ALWAYS, 2, 0);
enemy_air_draw();//рисование и анимация летающих врагов
enemy_blast_draw();//рисуем патрон врага
player_draw();//Рисуем корабль игрока
player_ammo_draw();//Рисуем патрон игрока
effect_draw();
ничего не получилось. картинка осталась без изменения
что делать?
Последний раз редактировалось aureli0, 08.09.2009 в 20:58.
|
(Offline)
|
|
08.09.2009, 22:22
|
#4
|
ПроЭктировщик
Регистрация: 19.03.2007
Сообщений: 134
Написано 10 полезных сообщений (для 20 пользователей)
|
Re: 2d в OpenGL. вывод тени от спрайта
получилось вот таким образом, но тени смешиваются,как это исправить?
// Значение, которым будет заполняться буфер стенсила при его очистке
glClearStencil(0);//значение фона буфера стенсила фона
glStencilMask(0xFF);//Определяем, какие биты могут писаться в стенсил буфер
glClear( GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);// Очищаем все буферы
//Задний фон
glColor4f(1,1,1,1);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D,background_texture);
DrawTXT(win_DX/2,win_DY/2,win_DX,win_DY,0,1);
level_draw();
enemy_ground_draw();//рисование и анимация наземных врагов
starwind_draw();
glEnable(GL_STENCIL_TEST);//включаем трафарет
//определяем область где тень рисуется
glStencilFunc(GL_NEVER, 1, 0);
//в том месте где рисуется трафарет значение буфера заменяем на 1
glStencilOp(GL_REPLACE, GL_KEEP, GL_KEEP);
level_draw();//уровень является трафаретом-только на нем видна тень
// тень будет рисоваться только в тех местах,где значение в буфере 1
glStencilFunc(GL_EQUAL, 1, 255);
player_shadow_draw();
enemy_air_shadow_draw();
glDisable(GL_STENCIL_TEST);//отключаем трафарет
enemy_air_draw();//рисование и анимация летающих врагов
enemy_blast_draw();//рисуем патрон врага
player_draw();//Рисуем корабль игрока
player_ammo_draw();//Рисуем патрон игрока
effect_draw();
|
(Offline)
|
|
08.09.2009, 22:39
|
#5
|
|
Ответ: 2d в OpenGL. вывод тени от спрайта
ммм по-идее так должно работать
glEnable(GL_STENCIL_TEST);//включаем трафарет
//мы в любом случае будем писать в трафарет
glStencilFunc(GL_ALWAYS, 0, 255);
//в том месте где рисуется трафарет значение буфера заменяем на 1
glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
level_draw();//уровень является трафаретом-только на нем видна тень
// тень будет рисоваться только в тех местах,где значение в буфере 1
glStencilFunc(GL_EQUAL, 1, 255);
glStencilOp(GL_KEEP, GL_KEEP, GL_ZERO);
player_shadow_draw();
enemy_air_shadow_draw();
glDisable(GL_STENCIL_TEST);//отключаем трафарет
|
|
|
Сообщение было полезно следующим пользователям:
|
|
08.09.2009, 22:50
|
#6
|
ПроЭктировщик
Регистрация: 19.03.2007
Сообщений: 134
Написано 10 полезных сообщений (для 20 пользователей)
|
Re: 2d в OpenGL. вывод тени от спрайта
// Значение, которым будет заполняться буфер стенсила при его очистке
glClearStencil(0);//значение фона буфера стенсила фона
glStencilMask(0xFF);//Определяем, какие биты могут писаться в стенсил буфер
//Очищаем экран перед рисованием и буфер стенсила
glClear( GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);// Очищаем все буферы
рисуем задник
glEnable(GL_STENCIL_TEST);//включаем трафарет
//мы в любом случае будем писать в трафарет
glStencilFunc(GL_ALWAYS, 1, 255); //!!!!!!!!!!! не 0 а 1
//в том месте где рисуется трафарет значение буфера заменяем на 1
glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
level_draw();//уровень является трафаретом-только на нем видна тень
// тень будет рисоваться только в тех местах,где значение в буфере 1
glStencilFunc(GL_EQUAL, 1, 255);
glStencilOp(GL_KEEP, GL_KEEP, GL_ZERO);
player_shadow_draw();
enemy_air_shadow_draw();
glDisable(GL_STENCIL_TEST);//отключаем трафарет
заработало так, причем цвета теней больше не смешиваются ура
спасибо)
А как сделать чтобы тени еще не выводились на дырах(альфа канал) в спрайтах?
|
(Offline)
|
|
08.09.2009, 23:05
|
#7
|
|
Ответ: 2d в OpenGL. вывод тени от спрайта
А как сделать чтобы тени еще не выводились на дырах(альфа канал) в спрайтах?
|
хм, ну можно сделать такой альфа тест что при alpha < 0.5 пиксель не будет выводится, собсно в буфере трафарета будет 0 и не будет там тень рисоваться
|
|
|
08.09.2009, 23:08
|
#8
|
ПроЭктировщик
Регистрация: 19.03.2007
Сообщений: 134
Написано 10 полезных сообщений (для 20 пользователей)
|
Re: 2d в OpenGL. вывод тени от спрайта
тоже теперь не все хорошо тени от объектов одного типа режут друг друга
|
(Offline)
|
|
08.09.2009, 23:15
|
#9
|
|
Ответ: 2d в OpenGL. вывод тени от спрайта
aureli0
так приделай еще альфа тест для теней тоже с каким нибудь условием что если альфа = 0 то не рисовать пиксель
|
|
|
Сообщение было полезно следующим пользователям:
|
|
08.09.2009, 23:35
|
#10
|
ПроЭктировщик
Регистрация: 19.03.2007
Сообщений: 134
Написано 10 полезных сообщений (для 20 пользователей)
|
Re: Ответ: 2d в OpenGL. вывод тени от спрайта
Сообщение от jimon
aureli0
так приделай еще альфа тест для теней тоже с каким нибудь условием что если альфа = 0 то не рисовать пиксель
|
эт я понял только опять же какие параметры давать в glAlphaFunc?
//цвета теней не смешиваються!!!
glEnable(GL_STENCIL_TEST);//включаем трафарет
//мы в любом случае будем писать в трафарет
glStencilFunc(GL_ALWAYS, 1, 255);
//в том месте где рисуется трафарет значение буфера заменяем на 1
glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
level_draw();//уровень является трафаретом-только на нем видна тень
// тень будет рисоваться только в тех местах,где значение в буфере 1
glStencilFunc(GL_EQUAL, 1, 255);
glStencilOp(GL_KEEP, GL_KEEP, GL_ZERO);
glEnable(GL_ALPHA_TEST);
glAlphaFunc(GL_EQUAL,1);//выводить тени только на видимых пикселях с альфа 1
player_shadow_draw();
enemy_air_shadow_draw();
glDisable(GL_ALPHA_TEST);
glDisable(GL_STENCIL_TEST);//отключаем трафарет
по идее тени должны рисоваться только на пикселях с альфа=1, но тени просто полностью пропали(( опять я чето перепутал)
Последний раз редактировалось aureli0, 08.09.2009 в 23:41.
|
(Offline)
|
|
08.09.2009, 23:39
|
#11
|
|
Ответ: 2d в OpenGL. вывод тени от спрайта
хм
//цвета теней не смешиваються!!!
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();//уровень является трафаретом-только на нем видна тень
// тень будет рисоваться только в тех местах,где значение в буфере 1
glStencilFunc(GL_EQUAL, 1, 255);
glStencilOp(GL_KEEP, GL_KEEP, GL_ZERO);
glAlphaFunc(GL_GREATER,0.2f); //выводим только те пиксели тени у которых alpha > 0.2f
player_shadow_draw();
enemy_air_shadow_draw();
glDisable(GL_ALPHA_TEST);
glDisable(GL_STENCIL_TEST);//отключаем трафарет
там где 0.2f надо будет эксперементировать, в принципе если тени наложатся то в границе наложения будут небольшие баги, имхо тени надо сумировать
|
|
|
Сообщение было полезно следующим пользователям:
|
|
09.09.2009, 00:02
|
#12
|
ПроЭктировщик
Регистрация: 19.03.2007
Сообщений: 134
Написано 10 полезных сообщений (для 20 пользователей)
|
Re: 2d в OpenGL. вывод тени от спрайта
вот спасибо)) теперь все как надо. Да глюки есть. Поменял значение с 0.2 на 0.4 границы пропали но тени стали четче ну и фиг с ним все здорово))
Еще раз спасибо))
|
(Offline)
|
|
14.09.2009, 22:25
|
#13
|
ПроЭктировщик
Регистрация: 19.03.2007
Сообщений: 134
Написано 10 полезных сообщений (для 20 пользователей)
|
Re: 2d в OpenGL. вывод тени от спрайта
опять появились проблемы с тенями. Раньше каждая текстура хранилась в отдельном файле, и все работало без проблем. Теперь я использую для вывода level один файл с несколькими текстурами-появились глюки:
то иень периодически пропадает, то пооявляется. В трафарет помимо level_draw я добавил еще наземных юнитов enemy_groumd_Draw. Так вот они стали тоже "моргать".
//цвета теней не смешиваються!!! работает с глюками при выводе уровня из 1 текстуры
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();//уровень является трафаретом-только на нем видна тень
// enemy_ground_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);//отключаем трафарет
чето гдето нето чтото с альфой?
|
(Offline)
|
|
Ваши права в разделе
|
Вы не можете создавать темы
Вы не можете отвечать на сообщения
Вы не можете прикреплять файлы
Вы не можете редактировать сообщения
HTML код Выкл.
|
|
|
Часовой пояс GMT +4, время: 11:19.
|