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

Рис.1 Окружность залитая монохромным градиентом
И все хорошо если круг такого же размера как и на Рис.1, но как только размер увеличивается или же уменьшается контраст между центром и краями, то выплывают самые некрасивые вещи...
[spoiler]
Во-первых появляются концентрические окружности (Рис.2).

Рис.2 Проявление концентрических окружностей
Во-вторых этот эффект ни чем не получается устранить: ни увеличением промежутков цветовой составляющей, ни изменением альфа-канала.
При тех же значениях - тот же эффект! Грустно
Многие подумают что это похоже на 8 битное изображение. Тогда вопрос, как проверить какой режим OpenGL выбирает для рисования?
Заранее оговорюсь никаких шейдеров, текстур и тому подобного я не использую. Сейчас все рисуется так:
1) Круг рисуется, как набор из GL_TRIANGLE_FAN;
2) Центр окружности (вершина А треугольника АБЦ) имеет цвет glColor4fv(HI_color) - светлая середина;
3) Вершины Б и Ц - точки на окружности, имеют цвет glColor4fv(LOW_color) - темные края;
4) Градиент OpenGl рисует сам, как в про треугольник со спектральным разложением.
Дело, мне кажется в том, что Джель "не понимает" цвета меньше значения 1/(byte)255 = (float)0.0039
ВОПРОС
Какой предел имеют параметры цвета в модели RGBA (сотые, тысячные, десятитысячные (.00, .000, .0000))? До какой степени можно дробить эти параметры, чтобы была видна разница в цвете?
И как можно обойти подобные ограничения по выводу цвета на экран?
ДЛЯ ЧЕГО ЭТО ВСЕ НУЖНО
Нужно изменяя либо цвет, либо прозрачность (альфа-канал) добиться плавного растворения фигуры в цвете фона сцены так, чтобы четкие переходы не были видны.
Есть у меня одна простая задача, которая не решается почти год (не могу сказать, что я этим горжусь
Нужно нарисовать КРУГ так, чтобы центр был светлым, а ближе к краям цвет плавно изменялся вплоть до черного (Рис.1)

Рис.1 Окружность залитая монохромным градиентом
И все хорошо если круг такого же размера как и на Рис.1, но как только размер увеличивается или же уменьшается контраст между центром и краями, то выплывают самые некрасивые вещи...
[spoiler]
Во-первых появляются концентрические окружности (Рис.2).

Рис.2 Проявление концентрических окружностей
Во-вторых этот эффект ни чем не получается устранить: ни увеличением промежутков цветовой составляющей, ни изменением альфа-канала.
При тех же значениях - тот же эффект! Грустно
Многие подумают что это похоже на 8 битное изображение. Тогда вопрос, как проверить какой режим OpenGL выбирает для рисования?
Заранее оговорюсь никаких шейдеров, текстур и тому подобного я не использую. Сейчас все рисуется так:
1) Круг рисуется, как набор из GL_TRIANGLE_FAN;
2) Центр окружности (вершина А треугольника АБЦ) имеет цвет glColor4fv(HI_color) - светлая середина;
3) Вершины Б и Ц - точки на окружности, имеют цвет glColor4fv(LOW_color) - темные края;
4) Градиент OpenGl рисует сам, как в про треугольник со спектральным разложением.
Дело, мне кажется в том, что Джель "не понимает" цвета меньше значения 1/(byte)255 = (float)0.0039
ВОПРОС
Какой предел имеют параметры цвета в модели RGBA (сотые, тысячные, десятитысячные (.00, .000, .0000))? До какой степени можно дробить эти параметры, чтобы была видна разница в цвете?
И как можно обойти подобные ограничения по выводу цвета на экран?
ДЛЯ ЧЕГО ЭТО ВСЕ НУЖНО
Нужно изменяя либо цвет, либо прозрачность (альфа-канал) добиться плавного растворения фигуры в цвете фона сцены так, чтобы четкие переходы не были видны.
9008
07.05.2011
44



.
Читал про разные подходы, как это можно устранить, предлагали: и bloom-эффект, и шейдеры использовать, и цветовую модель HDR, и про dithering читал, чего только не пишут!!!
Но ни где толком не сказано, КАК КОНКРЕТНО МОЖНО ЭТУ ПРОБЛЕМУ РЕШИТЬ!
Помогите люди добрые, хотя бы идею какую-нибудь свежую дайте, пожалуйста!
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
for(int i=0;i>=360;i++)
{
glColor3f(255,255,255);
glVertex2f(centerX,centerY);
glVertex2f();
glVertex2f();
}
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;
}
Спасибо большое за советы, amid!
Но тут дело не в том, что у меня НЕ получается кружочек нарисовать.
Сейчас ниже новую ветку комментов создам.
Проблема в ЦВЕТЕ, точнее в отображении промежуточных оттенков цвета. Грубо говоря, моя программа не видит разницы между glColor3f(0.501f, 0.501f, 0.501f) и glColor3f(0.502f, 0.502f, 0.502f). Этот пример из головы навскидку, в программе не проверял, там может быть отличие не в «тысячных» разрядах, а в «стотысячных».
Я выложу картинку, которая отображает мою проблему.
Мне нужно получить в программе верхнюю полосу с плавным градиентом, а Джель закрашивает все фигуры как показано на нижней полоске. Т.е. определенный участок оттенка воспринимается как один и тот же цвет.
Вопрос как это исправить?
Пока в голову приходит только попиксельная обработка, но как её сделать не знаю.
И я уже всякую надежду потерял это исправить
Я могу выложить архив с программой для скачивания, чтобы тут не плодить новых веток.
С кодом такая ситуация:
// Инициализация 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();
}
Вот на исходники и пример программы.
А можно по-подробнее про спрайт и его реализацию для конкретного случая?
Ты такой эффект хочешь получить?
Я может не понял, но хочешь чтоб круг растворялся в фоне, почему тогда не привязал фон к LowColor.
P. S. Еще обработчик resize не добавил в events, при изменении размера окна сцену не перерисовывает, а глюки выдает.
Концентрические круги видны
Провел тест в фотошопе=):
— создал фон (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-ый бит не используется.(только в файлах для альфа)
Подскажи пожалуйста, как тогда в фотошопе сам механизм смешивания может быть реализован?
Или тот же инструмент «Размытие» — если жесткость убрать, то там сколько угодно оттенков получить выйдет и при этом глаз не заметит перехода, только «Волшебной полочкой» оттенок можно будет уловить.
8 бит на цвет, мало=).Если размер окружности уменьшить ближе к значению 255(в пикселях) будет плавный переход.Это я уже понял методом тыка
Остается, или же в цвет фона использовать еще биты(127,20,127) или на самой окружности. Давая другой цветовой спектр дополнительные биты сделают плавный переходПро это совсем не понял. Цвет окружности уже не серый будет, или я ошибаюсь?
С чего начать код писать?
Вот еще не понятно:
Вся сцена (и при необходимости и также отдельные ее части) выводится в floating-point-текстуру (FP16 или FP32).
После этого данная текстура преобразуется тем или иным путем и в результате мы получаем обычное (не floating-point) изображение с приведеными цветами, которое и выводится.
Цитата из статьи.Каким конкретно «тем или иным путем»? Что мне нужно с этой текстурой сделать?
С чего начать писать шейдер?
Я на C# сто лет не писал, как включить и использовать расширение в ТАО, понятия не имею. На с++ я использую Glew, а тут фиг его.
О результатах сих метаморфоз сообщу дополнительно
И к сожалению ничего не решилось
Сдам экзамены и буду снова ковырять — дело принципа!