Градиент в OpenGL

Всем-всем, добрый день!!!
Есть у меня одна простая задача, которая не решается почти год (не могу сказать, что я этим горжусь :)
Нужно нарисовать КРУГ так, чтобы центр был светлым, а ближе к краям цвет плавно изменялся вплоть до черного (Рис.1)

Рис.1 Окружность залитая монохромным градиентом

И все хорошо если круг такого же размера как и на Рис.1, но как только размер увеличивается или же уменьшается контраст между центром и краями, то выплывают самые некрасивые вещи...


Во-первых появляются концентрические окружности (Рис.2).

Рис.2 Проявление концентрических окружностей

Во-вторых этот эффект ни чем не получается устранить: ни увеличением промежутков цветовой составляющей, ни изменением альфа-канала.
При тех же значениях - тот же эффект! Грустно :(

Многие подумают что это похоже на 8 битное изображение. Тогда вопрос, как проверить какой режим OpenGL выбирает для рисования?

Заранее оговорюсь никаких шейдеров, текстур и тому подобного я не использую. Сейчас все рисуется так:
1) Круг рисуется, как набор из GL_TRIANGLE_FAN;
2) Центр окружности (вершина А треугольника АБЦ) имеет цвет glColor4fv(HI_color) - светлая середина;
3) Вершины Б и Ц - точки на окружности, имеют цвет glColor4fv(LOW_color) - темные края;
4) Градиент OpenGl рисует сам, как в Уроке 5.3 про треугольник со спектральным разложением.

Дело, мне кажется в том, что Джель "не понимает" цвета меньше значения 1/(byte)255 = (float)0.0039

ВОПРОС
Какой предел имеют параметры цвета в модели RGBA (сотые, тысячные, десятитысячные (.00, .000, .0000))? До какой степени можно дробить эти параметры, чтобы была видна разница в цвете?
И как можно обойти подобные ограничения по выводу цвета на экран?

ДЛЯ ЧЕГО ЭТО ВСЕ НУЖНО
Нужно изменяя либо цвет, либо прозрачность (альфа-канал) добиться плавного растворения фигуры в цвете фона сцены так, чтобы четкие переходы не были видны.
0       3165        07.05.2011        44

0  
07.05.2011 00:00:00
Проблема усложняется тем, что весь этот градиент планируется не «от балды» (как сейчас :) рисовать, а через задание функции градиента. Т.е. цвет может быть задан нелинейно. Такой вариант я уже запрограммировал, но там та же беда, с теми же цветовыми значениями: всё те же концентрические круги, овалы, линии и плавного перехода нет как ни крути.

Читал про разные подходы, как это можно устранить, предлагали: и bloom-эффект, и шейдеры использовать, и цветовую модель HDR, и про dithering читал, чего только не пишут!!!

Но ни где толком не сказано, КАК КОНКРЕТНО МОЖНО ЭТУ ПРОБЛЕМУ РЕШИТЬ!

Помогите люди добрые, хотя бы идею какую-нибудь свежую дайте, пожалуйста!
0  
12.05.2011 00:00:00
Пока ни каких соображений не появилось, кроме как переписать этот же код на Директе или Флеше и посмотреть на результат. Может быть там есть встроенный инструмент для удаления подобных дефектов.
0  
22.05.2011 00:00:00
что мешает сделать:

for(int i=0;i>=r;r++)
{
glBegin(GL_POINT);
glColor3f(плавный градиент зависит от i);
for(int j=0; j<=9999; j+=0.01)
float y = centerY + (y * sin(j));
float x = centerX + (r * cos(j));
glVertex2f(x,y);
glEnd;
}
я зная что маньяк, r*9999 циклов — это хорошо, но там можно радианы в градусы перевести и оптимизировать количество обходов с 9999 до 360
0  
22.05.2011 00:00:00
блин, а можно же это всё через трианглы сделать… тогда и цвет вычислять не надо и радиусы обходить
for(int i=0;i>=360;i++)
{
glColor3f(255,255,255);
glVertex2f(centerX,centerY);

glVertex2f();
glVertex2f();
}
0  
22.05.2011 00:00:00
Point,oldPoint:struct2d={0,0};
x,y=0;
for(int i=0;i>=360;i++)
{
glColor3f(255,255,255);
glVertex2f(centerX,centerY);
glColor3f(0,0,0);
glVertex2f(oldPoint.x,oldPoint.y);
Point.x=centerX + (r * sin(i/Math.PI*180));
Point.y=centerY + (r * cos(i/Math.PI*180));
glVertex2f(Point.x,Point.y);
oldPoint=Point;
}
0  
22.05.2011 00:00:00
Почему нельзя редактировать сообщения?
0  
16.06.2011 00:00:00
Ура, наконец-то я свободен и могу вернуться на сайт!
Спасибо большое за советы, amid!

Но тут дело не в том, что у меня НЕ получается кружочек нарисовать.
Сейчас ниже новую ветку комментов создам.
0  
16.06.2011 00:00:00
Круг рисуется по такому же алгоритму как ты предлагаешь — через трианглы. Все гуд, рисует правильно!
Проблема в ЦВЕТЕ, точнее в отображении промежуточных оттенков цвета. Грубо говоря, моя программа не видит разницы между glColor3f(0.501f, 0.501f, 0.501f) и glColor3f(0.502f, 0.502f, 0.502f). Этот пример из головы навскидку, в программе не проверял, там может быть отличие не в «тысячных» разрядах, а в «стотысячных».

Я выложу картинку, которая отображает мою проблему.

Мне нужно получить в программе верхнюю полосу с плавным градиентом, а Джель закрашивает все фигуры как показано на нижней полоске. Т.е. определенный участок оттенка воспринимается как один и тот же цвет.
Вопрос как это исправить?
0  
16.06.2011 00:00:00
Может быть какой-то особый цветовой режим нужно включить? Или еще что-то :(
Пока в голову приходит только попиксельная обработка, но как её сделать не знаю.
0  
16.06.2011 00:00:00
я делал трианглы с плавным гардиентом как в уроке у Anvi. Эсли такими же трианглами создать кружок, то не должно быть разницы… 0_о
0  
01.07.2011 00:00:00
Эсли такими же трианглами создать кружок, то не должно быть разницы… 0_оА она есть!!! При малом отличии соседних цветов и большом радиусе особенно видно становится.
И я уже всякую надежду потерял это исправить :(
0  
02.07.2011 00:00:00
Код в студию плиз=)
0  
04.07.2011 00:00:00
Сегодня вечером отпишусь и код выложу.
Я могу выложить архив с программой для скачивания, чтобы тут не плодить новых веток.
0  
04.07.2011 00:00:00
0  
07.07.2011 00:00:00
где код? Можно нарисовать спрайт и это выйдет экономичнее
0  
08.07.2011 00:00:00
Прошу прошения, что отсутствовал — где-то был, а где не помню :)

С кодом такая ситуация:
// Инициализация OpenGL
void InitGl()
{
Glut.glutInitDisplayMode(Glut.GLUT_RGBA|
Glut.GLUT_DEPTH|Glut.GLUT_DOUBLE|
Glut.GLUT_ALPHA);
Gl.glEnable(Gl.GL_DEPTH_TEST);
Gl.glClearDepth(1.0f);
Gl.glDepthFunc(Gl.GL_LEQUAL);
Gl.glShadeModel(Gl.GL_SMOOTH);
Gl.glHint(Gl.GL_PERSPECTIVE_CORRECTION_HINT, Gl.GL_NICEST);
Gl.glEnable(Gl.GL_BLEND);
Gl.glBlendFunc(Gl.GL_SRC_ALPHA, Gl.GL_ONE_MINUS_SRC_ALPHA);
Gl.glEnable(Gl.GL_ALPHA_TEST);
}

// Изменение размеров сцены;
void ResizeGlScene()
{
Gl.glViewport(0, 0, OpenGlControl.Width, OpenGlControl.Height);
Gl.glMatrixMode(Gl.GL_PROJECTION);
Gl.glLoadIdentity();
Glu.gluPerspective(45.0f, (float)OpenGlControl.Width /
(float)OpenGlControl.Height, 0.1f, 100.0f);
Gl.glMatrixMode(Gl.GL_MODELVIEW);
Gl.glLoadIdentity();
}

// Создание круга в памяти;
private void GradienCircle(float[] HI_color, float[] LOW_color)
{
float rad = 0.3f; // Радиус круга;
// Количество точек на окружности
// чем больше, тем круг плавнее;
int cv = 72;
// Массив координат точек окружности;
float[] va = new float[cv*2+2];
CreateCircle(rad, cv, va); // Создаем координаты окружности;
ResizeBlurStep(1); // Обнулим дисплейные списки;

Gl.glPushMatrix();
Gl.glNewList(LIST_net, Gl.GL_COMPILE);

Gl.glBegin(Gl.GL_TRIANGLE_FAN);
// ОШИБКА В ОТОБРАЖЕНИИ ЦВЕТОВ ЗДЕСЬ
// Центр круга рисуется светлым;
Gl.glColor4fv(HI_color);
Gl.glVertex2f(va[0], va[1]);
// Остальные точки окружности темным;
Gl.glColor4fv(LOW_color);
for (int i=2; i<va.Length; i+=2)
{
Gl.glVertex2f(va, va[i+1]);
}
Gl.glVertex2f(va[2], va[3]);
Gl.glEnd();
Gl.glEndList();
Gl.glPopMatrix();
}

// Рисование сцены;
private void DrawGlScene()
{
float[] HiColor = { 1, 1, 1, 1 };
float[] LowColor = { 0, 0, 0, 1 };
HiColor[3] = LowColor[3] = CONTRAST_ALPHA / 100;
// Начинаем рисование с очистки экрана;
// Цвет фона сцены серый;
Gl.glClearColor(0.5f, 0.5f, 0.5f, 1.0f);
Gl.glClear(Gl.GL_COLOR_BUFFER_BIT | Gl.GL_DEPTH_BUFFER_BIT);
Gl.glLoadIdentity();
Gl.glTranslatef(0, 0, -1);

Gl.glPushMatrix();
// Создаем градиентно закрашеный круг в памяти;
GradienCircle(HiColor, LowColor);
// Отрисовуем список отображения;
Gl.glCallList(LIST_net);

Gl.glPopMatrix();
Gl.glFlush();
OpenGlControl.Invalidate();
}

Вот на исходники и пример программы.

А можно по-подробнее про спрайт и его реализацию для конкретного случая?
0  
09.07.2011 00:00:00

Ты такой эффект хочешь получить?
0  
09.07.2011 00:00:00

Я может не понял, но хочешь чтоб круг растворялся в фоне, почему тогда не привязал фон к LowColor.
P. S. Еще обработчик resize не добавил в events, при изменении размера окна сцену не перерисовывает, а глюки выдает.
0  
09.07.2011 00:00:00
Ты такой эффект хочешь получить? Нет, мне нужно чтобы фон был (127, 127, 127); яркая точка в центре круга (0, 0, 0); темные края круга (255, 255, 255). И постепенно края и центр круга становятся такого же цвета, как и фончик :)
0  
09.07.2011 00:00:00
Изменил цвет, как был, все работает без артефактов.
0  
09.07.2011 00:00:00
значение альфа если меня не подводит память от 1.0f до 0.0f а у тебя и до 100 доходит.
0  
09.07.2011 00:00:00
извени функцию не увидел, все ок с альфа
0  
09.07.2011 00:00:00
, что получилось, у себя артефактов(те внутренние кружки что у тя на скрине) не увидел. Круг равномерно исчезает, а потом появляется. Мне кажеться можно добиться более интересного эффекта если цвет краев заставить постепенно сливаться с цветом фона.
0  
09.07.2011 00:00:00
Круг равномерно исчезает, а потом появляется.Если бы это для игры какой-то, то все было бы супер, а тут точность нужна высокая. Потому что от этого эффекта зависит как я буду проводить калибровку конкретного монитора.
0  
09.07.2011 00:00:00
Вообще вместо круга лучше нарисовать сферу, а яркое пятно получить с помощью источника света(всех рассеянного, диффузного и отраженного) и присвоить материалу объекта зеркальное отражение(макс. фокусировку отражения). Получиться красивый зеркальный блик. А потом сделать постепенно уменьшение альфа(как сейчас и есть) и будет супер и без градиента.
0  
09.07.2011 00:00:00
а яркое пятно получить с помощью источника светаЗадача совсем в другом градиент не с потолка берется, а для каждой точки окружности рассчитывается.

Концентрические круги видны :((( Ты пробовал запускать приложение в полноэкранном режиме (клавиша F2).
0  
09.07.2011 00:00:00
Задача совсем в другом градиент не с потолка берется, а для каждой точки окружности рассчитывается.А из-за этого эффекта формула бессмысленна!
0  
09.07.2011 00:00:00
Понимаешь еще в чем дело, даже при меньшем радиусе окружности получается тоже самое, с той лишь разницей, что эти кружочки ступенчатые меньше по размеру.
0  
10.07.2011 00:00:00
Я попробовал в фотошопе 32 битный режим на канал вместо 8 бит, переходы стали практически не заметны. Может все таки HDRI поможет…
0  
09.07.2011 00:00:00
Попробовал, да.., видны..(
Провел тест в фотошопе=):
— создал фон (127, 127, 127);
выделил окружность в центре сделал радиальный градиент центр=(255, 255, 255) края =(255, 255, 255)(у тя кстати в одном комменте наоборот, ошибся?))
— окружность рисовал на новый слой, потом менял непрозрачность(альфа) слоя, оказалось тоже есть артефакты хотя и меньшие. Я думаю меньше из за того что светлое пятно получилось больше, черный был только по краям(не знаю с чем это связано)

Может цветовой спектр изначально неудачен, не вписывается в 8 бит на цвет, мало=).
Фон(127,127,127) находиться в середине от центра окружности до края, это само по себе под "зубья подводит". При том что у нас каждый бит использует одно значение. получается только 255 шагов в спектре, при высоком разрешении, хотя бы 1280Х720монитора, на окружность приходиться большая часть) ясно дело, что ступеньки выходят.
Если размер окружности уменьшить ближе к значению 255(в пикселях) будет плавный переход.
А так как монитор может потянуть только 8 бит на цвет(24 битовый режим).
Остается, или же в цвет фона использовать еще биты(127,20,127) или на самой окружности. Давая другой цветовой спектр дополнительные биты сделают плавный переход, а то так получается у нас 8 битовый режим.
Кстати 32 битный режим монитора, нужен только для оптимизации памяти, так как слово у 32 битных машин = 32 бита))) 4-ый бит не используется.(только в файлах для альфа)
0  
10.07.2011 00:00:00
Приплыли, замечательно… Даже не знаю куда теперь грести?!

Подскажи пожалуйста, как тогда в фотошопе сам механизм смешивания может быть реализован?
Или тот же инструмент «Размытие» — если жесткость убрать, то там сколько угодно оттенков получить выйдет и при этом глаз не заметит перехода, только «Волшебной полочкой» оттенок можно будет уловить.

8 бит на цвет, мало=).Если размер окружности уменьшить ближе к значению 255(в пикселях) будет плавный переход.Это я уже понял методом тыка :)

Остается, или же в цвет фона использовать еще биты(127,20,127) или на самой окружности. Давая другой цветовой спектр дополнительные биты сделают плавный переходПро это совсем не понял. Цвет окружности уже не серый будет, или я ошибаюсь?
0  
10.07.2011 00:00:00
В фотошопе если RGB 8 бит на канал то будет то что у тя в проге, но если использовать 32 бита, то артефактов вроде вообще не видно.
0  
10.07.2011 00:00:00
32 это уже кажись HDRI/
0  
10.07.2011 00:00:00
про HDRI читал, действительно есть над чем подумать, но дело в том, что я не пойму через что это можно реализовать в Джеле.

С чего начать код писать?

Вот еще не понятно:
Вся сцена (и при необходимости и также отдельные ее части) выводится в floating-point-текстуру (FP16 или FP32).
После этого данная текстура преобразуется тем или иным путем и в результате мы получаем обычное (не floating-point) изображение с приведеными цветами, которое и выводится.

Цитата из статьи.Каким конкретно «тем или иным путем»? Что мне нужно с этой текстурой сделать?

С чего начать писать шейдер?
0  
10.07.2011 00:00:00
Даже, не знаю.
Я на C# сто лет не писал, как включить и использовать расширение в ТАО, понятия не имею. На с++ я использую Glew, а тут фиг его.
0  
10.07.2011 00:00:00
Мне не принципиально на Шарпе, саму методику понять хочу.
0  
10.07.2011 00:00:00
давай в личку
0  
10.07.2011 00:00:00
Нашел еще одну отличную статью про эффекты постобработки, кому нужно берите на заметку.
0  
10.07.2011 00:00:00
Слушай, а ты не пробовал просто, увеличивать цвет LowColor до 127, и и при этом уменьшать HiColor до 127? Я проверил артефактов кажись не видно.
0  
10.07.2011 00:00:00
Ответил в личку =)
0  
22.07.2011 00:00:00
Почитал какую нашел информацию, да и ребята подсказали, буду пробовать сделать так: в Фотошопе создам текстуру 128*128, сделаю заливку серым (127,127,127) цветом, далее добавлю монохромный шум и изменяя прозрачность буду натягивать её поверх изображенной на сцене окружности (2-й рисунок этого топика).
О результатах сих метаморфоз сообщу дополнительно :)
0  
10.05.2012 00:00:00
А где дополнительно? уже почти год нету((
0  
11.05.2012 00:00:00
Да, да, да :(
И к сожалению ничего не решилось :(
Сдам экзамены и буду снова ковырять — дело принципа!
0  
11.05.2012 00:00:00
Буду ждать!>))
^