Цель лекции: Изучить команды работы с буфером аккумулятора и метод "джиттеринга" (дрожания), используемого для устранения эффекта ступенчатости изображения OpenGL.
Пример № 11.1 Пример демонстрирует устранение эффекта ступенчатости с помощью "джиттеринга".
В большинстве случаев для отображения изображения используются матричные устройства. В связи с этим часто возникает необходимость устранения или, по крайней мере, уменьшения таких эффектов как ступенчатость линий и резких переходов цвета между объектами.
Одним из вариантов получения эффекта сглаживания изображения сцены является использование буфера накопления. Иногда такой способ называют эффектом дрожания или "джитеринг" (от английского слова
Качество сглаживания обычно пропорционально количеству прорисовок сцены. При выборе координат смещения сцены относительно исходного положения обычно используют набор массивов, значения которых позволяют получить наилучший эффект сглаживания сцены при заданном количестве прорисовок сцены.
Ниже приведено содержание класса на C#, который содержит реализацию методов, используемых для реализации эффекта сглаживания. В классе так же объявлены массивы различного размера, которые содержат смещения, которые используются для получения эффекта сглаживания.
class Jitter
{
public struct PointPloat
{
public float X;
public float Y;
}
public static PointPloat[] j2 = new PointPloat[2]
{
new PointPloat{X= 0.246490f,Y= 0.249999f},
new PointPloat{X= 0.246490f,Y= 0.249999f}
};
public static PointPloat[] j3 = new PointPloat[3]
{
new PointPloat{X= -0.373411f, Y= -0.250550f},
new PointPloat{X= 0.256263f, Y= 0.368119f},
new PointPloat{X= 0.117148f, Y= -0.117570f}
};
public static PointPloat[] j4 = new PointPloat[4]
{
new PointPloat{X= -0.208147f, Y= 0.353730f},
new PointPloat{X= 0.203849f, Y= -0.353780f},
new PointPloat{X= -0.292626f, Y= -0.149945f},
new PointPloat{X= 0.296924f, Y= 0.149994f}
};
public static PointPloat[] j8 = new PointPloat[8]
{
new PointPloat{X= -0.334818f, Y= 0.435331f},
new PointPloat{X= 0.286438f, Y= -0.393495f},
new PointPloat{X= 0.459462f, Y= 0.141540f},
new PointPloat{X= -0.414498f, Y= -0.192829f},
new PointPloat{X= -0.183790f, Y= 0.082102f},
new PointPloat{X= -0.079263f, Y= -0.317383f},
new PointPloat{X= 0.102254f, Y= 0.299133f},
new PointPloat{X= 0.164216f, Y= -0.054399f}
};
public static void AccFrustum(double left, double right,
double bottom, double top,
double anear, double afar, double pdx, double pdy)
{
double xwsize, ywsize, dx, dy;
int[] viewport = new int[4];
GL.GetInteger(GetPName.Viewport, viewport);
xwsize = right - left;
ywsize = top - bottom;
dx = -(pdx * xwsize / viewport[2]);
dy = -(pdy * ywsize / viewport[3]);
GL.MatrixMode(MatrixMode.Projection);
GL.LoadIdentity();
GL.Frustum (left + dx, right + dx, bottom + dy, top + dy, anear, afar);
GL.MatrixMode(MatrixMode.Modelview);
}
public static void AccOrtho(double left, double right,
double bottom, double top,
double anear, double afar, double pdx, double pdy)
{
double xwsize, ywsize, dx, dy;
int[] viewport = new int[4];
GL.GetInteger(GetPName.Viewport, viewport);
xwsize = right - left;
ywsize = top - bottom;
dx = -(pdx*xwsize/viewport[2]);
dy = -(pdy*ywsize/viewport[3]);
GL.MatrixMode(MatrixMode.Projection);
GL.LoadIdentity();
GL.Ortho(left + dx, right + dx, bottom + dy, top + dy, anear, afar);
GL.MatrixMode(MatrixMode.Modelview);
}
}
Ниже приведено содержание модуля на Object Pascal, который содержит процедуры, выполняющие операции аналогичные классу ).
unit Jitter;
interface
uses OpenGL;
Type
TGLPointFloat = record
x,y: GLFloat;
End;
const
j2: array[0..1] of TGLPointFloat =
((x: 0.246490; y: 0.249999), (x: -0.246490; y: -0.249999));
j3: array[0..2] of TGLPointFloat =
((x: -0.373411; y: -0.250550), (x: 0.256263; y: 0.368119),
(x: 0.117148; y: -0.117570));
j4: array[0..3] of TGLPointFloat =
((x: -0.208147; y: 0.353730), (x: 0.203849; y: -0.353780),
(x: -0.292626; y: -0.149945), (x: 0.296924; y: 0.149994));
j8: array[0..7] of TGLPointFloat =
((x: -0.334818; y: 0.435331), (x: 0.286438; y: -0.393495),
(x: 0.459462; y: 0.141540), (x: -0.414498; y: -0.192829),
(x: -0.183790; y: 0.082102), (x: -0.079263; y: -0.317383),
(x: 0.102254; y: 0.299133), (x: 0.164216; y: -0.054399));
procedure AccFrustum(left,right,bottom,top: GLdouble; anear,afar,pdx,pdy: GLdouble);
procedure AccOrtho(left, right, bottom, top: GLdouble; anear, afar, pdx, pdy: GLdouble);
Implementation
procedure AccFrustum(left, right, bottom, top: GLdouble; anear, afar, pdx, pdy: GLdouble);
var
xwsize, ywsize: GLdouble;
dx, dy: GLdouble;
viewport: array[0..3] of GLint;
begin
glGetIntegerv (GL_VIEWPORT, @viewport);
xwsize := right - left;
ywsize := top - bottom;
dx := -(pdx*xwsize/viewport[2]);
dy := -(pdy*ywsize/viewport[3]);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glFrustum (left + dx, right + dx, bottom + dy, top + dy, anear, afar);
glMatrixMode(GL_MODELVIEW);
end;
procedure AccOrtho(left, right, bottom, top: GLdouble; anear, afar, pdx, pdy: GLdouble);
var
xwsize, ywsize : GLdouble;
dx, dy: GLdouble;
viewport: array[0..3] of GLint;
begin
glGetIntegerv (GL_VIEWPORT, @viewport);
xwsize := right - left;
ywsize := top - bottom;
dx := -(pdx*xwsize/viewport[2]);
dy := -(pdy*ywsize/viewport[3]);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(left + dx, right + dx, bottom + dy, top + dy, anear, afar);
glMatrixMode(GL_MODELVIEW);
end;
end.
Для управления буфером аккумулятора используется команда Accum.
C#: void Accum(AccumOp op, float value); Object Pascal: procedure glAccum (op: GLenum; value: GLfloat);
Аргумент .
| Описание значения параметра | Значение параметра | |
|---|---|---|
| Библиотека OpenTK, C# | Object Pascal | |
Считывает каждый пиксель из буфера цвета, умножает каждую составляющую цвета пиксела ( на значение value и добавляет результаты в буфер аккумуляции. | AccumOp.Accum | GL_ACCUM |
Pаботает так же как и параметр AccumOp.Accum/GL_ACCUM за тем исключением, что результирующие значения заменяют уже хранимые в буфере, а не добавляются к ним. | AccumOp.Load | GL_LOAD |
Умножает величины из буфера аккумуляции на значение параметра value и помещает результат в цветовой буфер, выбранный для записи. | AccumOp.Return | GL_RETURN |
Просто добавляют или умножают значения каждого пикселя в буфере аккумуляции на величину value. Для AccumOp.Mult/GL_MULT значение value усекается до диапазона [-1.0, 1.0]. Для AccumOp.Add/GL_ADD усечение не производится | AccumOp.Add и AccumOp.Mult | GL_ADD и GL_MULT |
В листинге 11.3 приведен фрагмент программы с использованием метода AccOrtho класса для формирования ортографической проекции сцены на языке программирования C#.
void DrawObjects()
{
// формирование изображения
GL.Enable(EnableCap.Lighting);
GL.Enable(EnableCap.Light0);
sphere(0.5, 20, 20);
GL.Disable(EnableCap.Lighting);
// завершение формирования изображения
}
void DrawScene(Jitter.PointPloat[] j)
{
GL.Clear(ClearBufferMask.AccumBufferBit);
for (int i = 0; i< j.Length-1; ++i)
{
GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);
Jitter.AccOrtho(-1, 1, -1, 1, -1, 1, j[i].X, j[i].Y);
DrawObjects();
GL.Accum(AccumOp.Accum, 1.0f/j.Length);
}
GL.Accum(AccumOp.Return, 1.0f);
}
private void glControl1_Paint(object sender, PaintEventArgs e)
{
// очистка буферов цвета и глубины
GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);
// поворот изображения
GL.LoadIdentity();
GL.Rotate(AngleX, 1.0, 0.0, 0.0);
GL.Rotate(AngleY, 0.0, 1.0, 0.0);
GL.Rotate(AngleZ, 0.0, 0.0, 1.0);
DrawScene(Jitter.j8);
GL.Flush();
GL.Finish();
glControl1.SwapBuffers();
}
В методе DrawScene вызывается метод DrawObjects, который должен формировать отображаемые объекты в видимой области сцены.
В листинге 11.4 приведен фрагмент программы с использованием процедуры AccOrtho для формирования ортографической проекции сцены на языке программирования Object Pascal.
procedure TForm1.DrawScene(j: array of TGLPointFloat);
var
i: Integer;
begin
glClear(GL_ACCUM_BUFFER_BIT);
for I := 0 to High(j) do
begin
glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);
AccOrtho(-2, 2, -2, 2, -2, 2, j[i].x, j[i].y);
DrawObjects;
glAccum(GL_ACCUM, 1.0/(High(j)+1));
end;
glAccum (GL_RETURN, 1.0);
end;
procedure TForm1.FormPaint(Sender: TObject);
begin
// очистка буфера цвета
glClear (GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT); glLoadIdentity;
// этот фрагмент нужен для придания трёхмерности
glRotatef(AngleX, 1.0, 0.0, 0.0);
glRotatef(AngleY, 0.0, 1.0, 0.0);
glRotatef(AngleZ, 0.0, 0.0, 1.0);
DrawScene(j8);
glFlush;
glFinish;
SwapBuffers(DC);
end;
procedure TForm1.DrawObjects;
begin
// формирование изображения
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
sphere(0.5, 20, 20);
glDisable(GL_LIGHTING);
// завершение формирования изображения
end;
Несмотря на то, что у примитивов есть ряд параметров, которые позволяют изменять визуальное качество изображения, но они не позволяют устанить эффект ступенчатости в изображении объектов сцены.
Для решения этой проблемы обычно применяется эффект "джиттеринга", для реализации которого используется буфер аккумулятора.
Изображение сцены формируется несколько раз с уменьшенной интенсивностью составляющих цвета в буфере аккумулятора и с некоторым смещением относительно реального положения объектов сцены. Результат "накапливается" в буфере аккумулятора и затем копируется в отображаемый буфер.
Для работы с буфером аккумурятора используется команда Accum.
Цель лекции: Изучить команды работы с буфером аккумулятора и метод "джиттеринга" (дрожания), используемого для устранения эффекта ступенчатости изображения OpenGL.
Пример № 11.1 Пример демонстрирует устранение эффекта ступенчатости с помощью "джиттеринга".
В большинстве случаев для отображения изображения используются матричные устройства. В связи с этим часто возникает необходимость устранения или, по крайней мере, уменьшения таких эффектов как ступенчатость линий и резких переходов цвета между объектами.
Одним из вариантов получения эффекта сглаживания изображения сцены является использование буфера накопления. Иногда такой способ называют эффектом дрожания или "джитеринг" (от английского слова
Качество сглаживания обычно пропорционально количеству прорисовок сцены. При выборе координат смещения сцены относительно исходного положения обычно используют набор массивов, значения которых позволяют получить наилучший эффект сглаживания сцены при заданном количестве прорисовок сцены.
Ниже приведено содержание класса на C#, который содержит реализацию методов, используемых для реализации эффекта сглаживания. В классе так же объявлены массивы различного размера, которые содержат смещения, которые используются для получения эффекта сглаживания.
class Jitter
{
public struct PointPloat
{
public float X;
public float Y;
}
public static PointPloat[] j2 = new PointPloat[2]
{
new PointPloat{X= 0.246490f,Y= 0.249999f},
new PointPloat{X= 0.246490f,Y= 0.249999f}
};
public static PointPloat[] j3 = new PointPloat[3]
{
new PointPloat{X= -0.373411f, Y= -0.250550f},
new PointPloat{X= 0.256263f, Y= 0.368119f},
new PointPloat{X= 0.117148f, Y= -0.117570f}
};
public static PointPloat[] j4 = new PointPloat[4]
{
new PointPloat{X= -0.208147f, Y= 0.353730f},
new PointPloat{X= 0.203849f, Y= -0.353780f},
new PointPloat{X= -0.292626f, Y= -0.149945f},
new PointPloat{X= 0.296924f, Y= 0.149994f}
};
public static PointPloat[] j8 = new PointPloat[8]
{
new PointPloat{X= -0.334818f, Y= 0.435331f},
new PointPloat{X= 0.286438f, Y= -0.393495f},
new PointPloat{X= 0.459462f, Y= 0.141540f},
new PointPloat{X= -0.414498f, Y= -0.192829f},
new PointPloat{X= -0.183790f, Y= 0.082102f},
new PointPloat{X= -0.079263f, Y= -0.317383f},
new PointPloat{X= 0.102254f, Y= 0.299133f},
new PointPloat{X= 0.164216f, Y= -0.054399f}
};
public static void AccFrustum(double left, double right,
double bottom, double top,
double anear, double afar, double pdx, double pdy)
{
double xwsize, ywsize, dx, dy;
int[] viewport = new int[4];
GL.GetInteger(GetPName.Viewport, viewport);
xwsize = right - left;
ywsize = top - bottom;
dx = -(pdx * xwsize / viewport[2]);
dy = -(pdy * ywsize / viewport[3]);
GL.MatrixMode(MatrixMode.Projection);
GL.LoadIdentity();
GL.Frustum (left + dx, right + dx, bottom + dy, top + dy, anear, afar);
GL.MatrixMode(MatrixMode.Modelview);
}
public static void AccOrtho(double left, double right,
double bottom, double top,
double anear, double afar, double pdx, double pdy)
{
double xwsize, ywsize, dx, dy;
int[] viewport = new int[4];
GL.GetInteger(GetPName.Viewport, viewport);
xwsize = right - left;
ywsize = top - bottom;
dx = -(pdx*xwsize/viewport[2]);
dy = -(pdy*ywsize/viewport[3]);
GL.MatrixMode(MatrixMode.Projection);
GL.LoadIdentity();
GL.Ortho(left + dx, right + dx, bottom + dy, top + dy, anear, afar);
GL.MatrixMode(MatrixMode.Modelview);
}
}
Ниже приведено содержание модуля на Object Pascal, который содержит процедуры, выполняющие операции аналогичные классу ).
unit Jitter;
interface
uses OpenGL;
Type
TGLPointFloat = record
x,y: GLFloat;
End;
const
j2: array[0..1] of TGLPointFloat =
((x: 0.246490; y: 0.249999), (x: -0.246490; y: -0.249999));
j3: array[0..2] of TGLPointFloat =
((x: -0.373411; y: -0.250550), (x: 0.256263; y: 0.368119),
(x: 0.117148; y: -0.117570));
j4: array[0..3] of TGLPointFloat =
((x: -0.208147; y: 0.353730), (x: 0.203849; y: -0.353780),
(x: -0.292626; y: -0.149945), (x: 0.296924; y: 0.149994));
j8: array[0..7] of TGLPointFloat =
((x: -0.334818; y: 0.435331), (x: 0.286438; y: -0.393495),
(x: 0.459462; y: 0.141540), (x: -0.414498; y: -0.192829),
(x: -0.183790; y: 0.082102), (x: -0.079263; y: -0.317383),
(x: 0.102254; y: 0.299133), (x: 0.164216; y: -0.054399));
procedure AccFrustum(left,right,bottom,top: GLdouble; anear,afar,pdx,pdy: GLdouble);
procedure AccOrtho(left, right, bottom, top: GLdouble; anear, afar, pdx, pdy: GLdouble);
Implementation
procedure AccFrustum(left, right, bottom, top: GLdouble; anear, afar, pdx, pdy: GLdouble);
var
xwsize, ywsize: GLdouble;
dx, dy: GLdouble;
viewport: array[0..3] of GLint;
begin
glGetIntegerv (GL_VIEWPORT, @viewport);
xwsize := right - left;
ywsize := top - bottom;
dx := -(pdx*xwsize/viewport[2]);
dy := -(pdy*ywsize/viewport[3]);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glFrustum (left + dx, right + dx, bottom + dy, top + dy, anear, afar);
glMatrixMode(GL_MODELVIEW);
end;
procedure AccOrtho(left, right, bottom, top: GLdouble; anear, afar, pdx, pdy: GLdouble);
var
xwsize, ywsize : GLdouble;
dx, dy: GLdouble;
viewport: array[0..3] of GLint;
begin
glGetIntegerv (GL_VIEWPORT, @viewport);
xwsize := right - left;
ywsize := top - bottom;
dx := -(pdx*xwsize/viewport[2]);
dy := -(pdy*ywsize/viewport[3]);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(left + dx, right + dx, bottom + dy, top + dy, anear, afar);
glMatrixMode(GL_MODELVIEW);
end;
end.
Для управления буфером аккумулятора используется команда Accum.
C#: void Accum(AccumOp op, float value); Object Pascal: procedure glAccum (op: GLenum; value: GLfloat);
Аргумент .
| Описание значения параметра | Значение параметра | |
|---|---|---|
| Библиотека OpenTK, C# | Object Pascal | |
Считывает каждый пиксель из буфера цвета, умножает каждую составляющую цвета пиксела ( на значение value и добавляет результаты в буфер аккумуляции. | AccumOp.Accum | GL_ACCUM |
Pаботает так же как и параметр AccumOp.Accum/GL_ACCUM за тем исключением, что результирующие значения заменяют уже хранимые в буфере, а не добавляются к ним. | AccumOp.Load | GL_LOAD |
Умножает величины из буфера аккумуляции на значение параметра value и помещает результат в цветовой буфер, выбранный для записи. | AccumOp.Return | GL_RETURN |
Просто добавляют или умножают значения каждого пикселя в буфере аккумуляции на величину value. Для AccumOp.Mult/GL_MULT значение value усекается до диапазона [-1.0, 1.0]. Для AccumOp.Add/GL_ADD усечение не производится | AccumOp.Add и AccumOp.Mult | GL_ADD и GL_MULT |
В листинге 11.3 приведен фрагмент программы с использованием метода AccOrtho класса для формирования ортографической проекции сцены на языке программирования C#.
void DrawObjects()
{
// формирование изображения
GL.Enable(EnableCap.Lighting);
GL.Enable(EnableCap.Light0);
sphere(0.5, 20, 20);
GL.Disable(EnableCap.Lighting);
// завершение формирования изображения
}
void DrawScene(Jitter.PointPloat[] j)
{
GL.Clear(ClearBufferMask.AccumBufferBit);
for (int i = 0; i< j.Length-1; ++i)
{
GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);
Jitter.AccOrtho(-1, 1, -1, 1, -1, 1, j[i].X, j[i].Y);
DrawObjects();
GL.Accum(AccumOp.Accum, 1.0f/j.Length);
}
GL.Accum(AccumOp.Return, 1.0f);
}
private void glControl1_Paint(object sender, PaintEventArgs e)
{
// очистка буферов цвета и глубины
GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);
// поворот изображения
GL.LoadIdentity();
GL.Rotate(AngleX, 1.0, 0.0, 0.0);
GL.Rotate(AngleY, 0.0, 1.0, 0.0);
GL.Rotate(AngleZ, 0.0, 0.0, 1.0);
DrawScene(Jitter.j8);
GL.Flush();
GL.Finish();
glControl1.SwapBuffers();
}
В методе DrawScene вызывается метод DrawObjects, который должен формировать отображаемые объекты в видимой области сцены.
В листинге 11.4 приведен фрагмент программы с использованием процедуры AccOrtho для формирования ортографической проекции сцены на языке программирования Object Pascal.
procedure TForm1.DrawScene(j: array of TGLPointFloat);
var
i: Integer;
begin
glClear(GL_ACCUM_BUFFER_BIT);
for I := 0 to High(j) do
begin
glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);
AccOrtho(-2, 2, -2, 2, -2, 2, j[i].x, j[i].y);
DrawObjects;
glAccum(GL_ACCUM, 1.0/(High(j)+1));
end;
glAccum (GL_RETURN, 1.0);
end;
procedure TForm1.FormPaint(Sender: TObject);
begin
// очистка буфера цвета
glClear (GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT); glLoadIdentity;
// этот фрагмент нужен для придания трёхмерности
glRotatef(AngleX, 1.0, 0.0, 0.0);
glRotatef(AngleY, 0.0, 1.0, 0.0);
glRotatef(AngleZ, 0.0, 0.0, 1.0);
DrawScene(j8);
glFlush;
glFinish;
SwapBuffers(DC);
end;
procedure TForm1.DrawObjects;
begin
// формирование изображения
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
sphere(0.5, 20, 20);
glDisable(GL_LIGHTING);
// завершение формирования изображения
end;
Несмотря на то, что у примитивов есть ряд параметров, которые позволяют изменять визуальное качество изображения, но они не позволяют устанить эффект ступенчатости в изображении объектов сцены.
Для решения этой проблемы обычно применяется эффект "джиттеринга", для реализации которого используется буфер аккумулятора.
Изображение сцены формируется несколько раз с уменьшенной интенсивностью составляющих цвета в буфере аккумулятора и с некоторым смещением относительно реального положения объектов сцены. Результат "накапливается" в буфере аккумулятора и затем копируется в отображаемый буфер.
Для работы с буфером аккумурятора используется команда Accum.
Для получения официальных документов о завершении программы дополнительного профессионального образования (удостоверения о повышении квалификации, дипломов о профессиональной переподготовке и MBA) необходимо предоставить:
Внимание! Вы можете не заказывать доставку бумажной версии официального документы, а скачать его в электронном виде и распечатать самостоятельно. Информация о выданном документе в течение 1 месяца загружается в Федеральную информационную систему «Федеральный реестр сведений о документах об образовании и (или) о квалификации, документах об обучении» - ФИС ФРДО.
Доступ на новый сайт осуществляется с использованием адреса электронной почты, который был указан вами при регистрации на "старом". Мы постарались перенести все ваши данные с прежнего ресурса, однако не исключена вероятность потери части информации.
При возникновении проблемы со входом, воспользуйтесь функцией сброса пароля
Если вы обнаружите несоответствия, пожалуйста, сообщите нам.