Опубликован: 02.12.2011 | Доступ: свободный | Студентов: 980 / 117 | Оценка: 5.00 / 4.00 | Длительность: 09:26:00
Специальности: Программист
Теги: .net, open source, opengl
Лекция 12:

Устранение эффекта ступенчатости

< Лекция 11 || Лекция 12: 12 || Лекция 13 >

Ниже приведено содержание модуля на Object Pascal, который содержит процедуры, выполняющие операции аналогичные классу Jitter на C# ( пример 11.2).

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.
Листинг 11.2. Исходный текст модуля Jitter.pas

Для управления буфером аккумулятора используется команда Accum.

C#:
  void Accum(AccumOp op, float value);
Object Pascal:
  procedure glAccum (op: GLenum; value: GLfloat);

Аргумент op определяет операцию, выполняемую над буфером, а параметр value – число, которое будет использоваться в этой операции. Возможные значения параметра op приведены в таблица 11.1.

Таблица 11.1. Возможные значения параметра op команды Accum
Описание значения параметра Значение параметра
Библиотека OpenTK, C# Object Pascal
Считывает каждый пиксель из буфера цвета, умножает каждую составляющую цвета пиксела (RGBA) на значение 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 класса Jitter для формирования ортографической проекции сцены на языке программирования 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();
}
Листинг 11.3. Пример устранения эффекта ступенчатости на C# с использованием библиотеки OpenTK

В методе 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;
Листинг 11.4. Пример устранения эффекта ступенчатости на Object Pascal

Краткие итоги

Несмотря на то, что у примитивов есть ряд параметров, которые позволяют изменять визуальное качество изображения, но они не позволяют устанить эффект ступенчатости в изображении объектов сцены.

Для решения этой проблемы обычно применяется эффект "джиттеринга", для реализации которого используется буфер аккумулятора.

Изображение сцены формируется несколько раз с уменьшенной интенсивностью составляющих цвета в буфере аккумулятора и с некоторым смещением относительно реального положения объектов сцены. Результат "накапливается" в буфере аккумулятора и затем копируется в отображаемый буфер.

Для работы с буфером аккумурятора используется команда Accum.

< Лекция 11 || Лекция 12: 12 || Лекция 13 >
Владислав Нагорный
Владислав Нагорный

Подскажите, пожалуйста, планируете ли вы возобновление программ высшего образования? Если да, есть ли какие-то примерные сроки?

Спасибо!

Лариса Парфенова
Лариса Парфенова

1) Можно ли экстерном получить второе высшее образование "Программная инженерия" ?

2) Трудоустраиваете ли Вы выпускников?

3) Можно ли с Вашим дипломом поступить в аспирантуру?