PMG

Форумы по созданию игр
Текущее время: 28 мар 2024 16:18

Часовой пояс: UTC + 3 часа [ Летнее время ]




Начать новую тему Ответить на тему  [ Сообщений: 11 ] 
Автор Сообщение
 Заголовок сообщения: Синхронизация отрисовки формы с разверткой экрана для TFT
СообщениеДобавлено: 07 авг 2006 16:49 
Не в сети
Новичок

Зарегистрирован: 07 авг 2006 16:47
Сообщения: 7
Откуда: Киев, Украина
Изначально проблема возникла при попытке в реальном режиме времени параллельно с проигрыванием звука из *.wav файла прокручивать по экрану соответствующий ему график. При этом есть два момента. Во-первых, для выигрыша в скорости при прокрутке уже построенный график просто смещался на канве простым копированием (например функцией CopyRect), а достраивались только новые точки. Во-вторых, операции непосредственного копирования на экран синхронизировались с разверткой монитора средствами DirectX.

Для обкатки на практике такого способа быстрого вывода графики был создан дополнительный проект, который условно можно назвать «Осцилографом». С помощью генератора псевдослучайных чисел генерируется новые точки, которые в реальном режиме времени выводятся на экран. Таким образом, график все время смещается вправо. Основная идея, как уже упоминалось выше – уже построенный график просто копируется вправо на канве, а на новое место слева достраивается новая точка. И т.д. Если такую операцию выполнять без синхронизации с разверткой монитора, то изображение будет дергаться, смыкаться и т.д. Основная причина – если обновление графика при копировании происходит, когда «луч» монитора находится на нем, то часть графика выше луча еще не будет сдвинута, а часть ниже луча – будет. Возникает эффект смещения, который визуально выливается в нехорошие вещи.

В моем вспомогательном проекте синхронизация с разверткой монитора выполнена на DirectX. При этом должен отметить, что стандартная для таких целей функция WaitForVerticalBlank не использовалась, так как забирает практически 100 процентов времени процессора (не известно на что!). Синхронизация выполнена с помощью функции GetScanLine – более подробно можете посмотреть внизу, я выложу код.

Основная идея такая. Есть две буферные поверхности (как я их назвал – активная и пассивная) и одна первичная. Есть два потока. Один поток осуществляет блиттинг с активной поверхности на первичную, а также блиттинг со смещением с активной поверхности на пассивную. Второй поток просто достраивает на пассивную поверхность новую точку. Эти операции длятся на протяжении одного кадра. Потом активная поверхность меняется местами с пассивной и т.д. Блиттинг осуществляется не всей поверхности сразу, а отслеживает в цикле положение луча и блиттится полосками над лучем. Это сложно объяснить словами, кому интересно – лучше в коде посмотрите.

Приведенный ниже код является полностью рабочим и удовлетворяет всем требованиям, которые выдвигались вначале разработки. НО С ОДНИМ НО (в котором, собственно, и заключается проблема и из-за которого я и пишу данный пост). График движется абсолютно нормально, без дерганий и мерцаний, четко виден и т.п. на трубчатых мониторах. При этом желательно конечно, чтобы компьютер был довольно мощным (процессор от 2 ГГц), либо же не раскрывайте окно на весь экран. Проблема возникает на жидко-кристаллических мониторах. График как и раньше не дергается, но при этом линии графика при смещении выглядят размытыми. При чем чем больше смещение на одну точку, тем более размытыми выглядят линии графика. В этом Вы сможете убедиться самостоятельно, так как в программе предусмотрена опция изменения величины смещения. Я акцентирую внимание: при прочих равных условиях (тот же самый компьютер, та же самая программа, то же разрешение монитора и частота обновления) на трубчатом мониторе все класно, а на TFT график выглядит размытым. В чем может быть причина такого эффекта? На сколько я понимаю, ТФТ монитор иначе, чем трубчатый, обновляет свой экран. Я, конечно же, понимаю, что такое понятие, как «луч» в случае жидко кристаллических мониторов вырождается, но тем не менее в документации к DirectX я не встречал упоминаний, что данная функция относится лишь к какому то виду мониторов или что этот код надо писать так-то для таких мониторов, и так-то для таких.
У меня возникает куча вопросов по тому, как именно ТФТ монитор обновляет свой экран. Я искал какую-нибудь литературу на эту тему как в книжках, так и в Инете, но ничего не нашел. Может кто-нибудь что-нибудь встречал, киньте пожалуйста линк или отошлите мне на почту volkovych(собака)gmail.com. Например, ТФТ обновляет экран строчка за строчкой сверху вниз или же по мере поступления данных и необходимости обновить ту или иную часть экрана? Он обновляет экран со стабильной частотой и весь, или же по мере поступления данных и только те части, которые изменились? Он изменяет в данный момент лишь какой-то один кусок данных, или же может обновлять сразу две области? Ответы на эти вопросы дали бы пищу для дальнейших рассуждений.

И еще. Мерцание на ТФТ-мониторах, про которое я писал, наблюдается как при DVI, так и при VGA-подключении. Кстати, я слышал, что вроде бы DVI имеет свою собственную синхронизацию, кто-нибудь встречал инфу на эту тему?

Исполняемый файл можно закачать здесь (489 кБ): http://rapidshare.de/files/28504278/Project1.exe.html

Вот код:

Заголовочный файл

Цитата:
//---------------------------------------------------------------------------

#ifndef Unit1H
#define Unit1H
//---------------------------------------------------------------------------
#include <Classes.hpp>
#include <Controls.hpp>
#include <StdCtrls.hpp>
#include <Forms.hpp>
#include <ExtCtrls.hpp>
//---------------------------------------------------------------------------
class TForm1 : public TForm
{
__published: // IDE-managed Components
TPanel *Panel1;
TGroupBox *GroupBox2;
TEdit *EditOffsetPerPoint;
TLabel *LabelOffsetPerPoint;
TButton *ButtonApplySettings;
TLabel *Label1;
void __fastcall FormDestroy(TObject *Sender);
void __fastcall ButtonApplySettingsClick(TObject *Sender);
private: // User declarations
public: // User declarations
__fastcall TForm1(TComponent* Owner);
float __fastcall Rando();
LPDIRECTDRAW lpDD;
LPDIRECTDRAWSURFACE lpPrimaryDDSurface, lpBackDDSurface[2];
LPDIRECTDRAWCLIPPER lpDDClipper;
bool RepaintOfPassiveBackDDSurfaceWasFinished;
DWORD ActiveBackDDSurface, PassiveBackDDSurface;
HANDLE RepaintBackDDSurface, RepaintBackDDSurfaceThread, UpdateScreenThread;
void __fastcall ApplySettings();
};
//---------------------------------------------------------------------------
extern PACKAGE TForm1 *Form1;
//---------------------------------------------------------------------------
#endif


Файл реализации

Цитата:
//---------------------------------------------------------------------------

#include <vcl.h>
#include <ddraw.h>
#include <mmsystem.h>
#include <stdio.h>
#pragma hdrstop

#include "Unit1.h"

//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"

#define min(a, b) (((a) < (b)) ? (a) : (b))
#define max(a, b) (((a) > (b)) ? (a) : (b))

TForm1 *Form1;
int d;
int dnew;
bool TerminateRepaintBackDDSurfaceThread = false;
bool TerminateUpdateScreenThread = false;
DWORD VerticalResolution, HorizontalResolution;

//Функиция потока прорисовки графиков

unsigned long WINAPI RepaintBackDDSurfaces(LPVOID param)
{
HDC PassiveBackDDSurfaceDC;
HPEN hpen;
double OldValue = 0, NewValue, GraphMin = 0, GraphMax = 1, gx, gy;
while (!TerminateRepaintBackDDSurfaceThread)
{
WaitForSingleObject(Form1->RepaintBackDDSurface, INFINITE);
Form1->lpBackDDSurface[Form1->PassiveBackDDSurface]->Blt(&Rect(d, 0, d + 1, Form1->Panel1->Top), Form1->lpBackDDSurface[Form1->ActiveBackDDSurface], &Rect(0, 0, 1, Form1->Panel1->Top), DDBLT_WAIT, NULL);
Form1->lpBackDDSurface[Form1->PassiveBackDDSurface]->GetDC(&PassiveBackDDSurfaceDC);
hpen = (HPEN)SelectObject(PassiveBackDDSurfaceDC, GetStockObject(WHITE_PEN));
Rectangle(PassiveBackDDSurfaceDC, 0, 0, d, Form1->Panel1->Top);
SelectObject(PassiveBackDDSurfaceDC, hpen);
//Получаем новую точку
NewValue = Form1->Rando();
gy = Form1->Panel1->Top - 1.0 * Form1->Panel1->Top*(OldValue-GraphMin)/(GraphMax-GraphMin);
gx = d;
MoveToEx(PassiveBackDDSurfaceDC, gx, gy, NULL);
//Рисуем линию графика
gy = Form1->Panel1->Top - 1.0 * Form1->Panel1->Top*(NewValue-GraphMin)/(GraphMax-GraphMin);
gx = 0;
LineTo(PassiveBackDDSurfaceDC, gx, gy);
OldValue = NewValue;
Form1->lpBackDDSurface[Form1->PassiveBackDDSurface]->ReleaseDC(PassiveBackDDSurfaceDC);
Form1->RepaintOfPassiveBackDDSurfaceWasFinished = true;
}
return(0);
}

//Функция потока обновление графика

unsigned long WINAPI UpdateScreen(LPVOID param)
{
bool PaintActiveBackDDSurface = false;
DWORD ScanLine, BeginLine, EndLine, LastPaintedLine, Dopom, OldScanLine = 0;
timeBeginPeriod(1); //Необходима для того, чтобы Sleep(1) действительно спал порядка 1-2 мс
DWORD BltXBegin, BltXEnd, BltYBegin, BltYEnd, ClientOriginYConst;
while (!TerminateUpdateScreenThread)
{
while (!TerminateUpdateScreenThread)
{
if (Form1->lpDD->GetScanLine(&ScanLine) == DDERR_VERTICALBLANKINPROGRESS || ScanLine < OldScanLine) break;
if (PaintActiveBackDDSurface && (ScanLine > BeginLine) && (LastPaintedLine < EndLine))
{
if (Form1->ClientOrigin.x >= 0 && Form1->ClientOrigin.x + Form1->ClientWidth - 1 <= HorizontalResolution - 1) {BltXBegin = 0; BltXEnd = Form1->ClientWidth - 1;}
else
{
if (Form1->ClientOrigin.x < 0) {BltXBegin = - Form1->ClientOrigin.x; BltXEnd = Form1->ClientWidth - 1;}
else {BltXBegin = 0; BltXEnd = HorizontalResolution - 1 - Form1->ClientOrigin.x;}
}
Form1->lpPrimaryDDSurface->Blt(&Rect(Form1->ClientOrigin.x + BltXBegin, LastPaintedLine, Form1->ClientOrigin.x + BltXEnd, min(ScanLine, EndLine)), Form1->lpBackDDSurface[Form1->ActiveBackDDSurface], &Rect(BltXBegin, LastPaintedLine - ClientOriginYConst, BltXEnd, min(ScanLine, EndLine) - ClientOriginYConst), DDBLT_WAIT, NULL); // != DD_OK) Application->MessageBox("Помилка при бліттінгу", "погано", MB_OK);
Form1->lpBackDDSurface[Form1->PassiveBackDDSurface]->Blt(&Rect(d + 1, LastPaintedLine - ClientOriginYConst, Form1->ClientWidth - 1, min(ScanLine, EndLine) - ClientOriginYConst), Form1->lpBackDDSurface[Form1->ActiveBackDDSurface], &Rect(1, LastPaintedLine - ClientOriginYConst, Form1->ClientWidth - 1 - d - 1 + 1, min(ScanLine, EndLine) - ClientOriginYConst), DDBLT_WAIT, NULL); // != DD_OK) Application->MessageBox("Помилка при бліттінгу", "погано", MB_OK);
LastPaintedLine = min(ScanLine, EndLine);
}
OldScanLine = ScanLine;
Sleep(1);
}
OldScanLine = 0;
if (PaintActiveBackDDSurface && LastPaintedLine < EndLine)
{
Form1->lpPrimaryDDSurface->Blt(&Rect(Form1->ClientOrigin.x + BltXBegin, LastPaintedLine, Form1->ClientOrigin.x + BltXEnd, EndLine), Form1->lpBackDDSurface[Form1->ActiveBackDDSurface], &Rect(BltXBegin, LastPaintedLine - ClientOriginYConst, BltXEnd, EndLine - ClientOriginYConst), DDBLT_WAIT, NULL);
Form1->lpBackDDSurface[Form1->PassiveBackDDSurface]->Blt(&Rect(d + 1, LastPaintedLine - ClientOriginYConst, Form1->ClientWidth - 1, EndLine - ClientOriginYConst), Form1->lpBackDDSurface[Form1->ActiveBackDDSurface], &Rect(1, LastPaintedLine - ClientOriginYConst, Form1->ClientWidth - 1 - d - 1 + 1, EndLine - ClientOriginYConst), DDBLT_WAIT, NULL);
LastPaintedLine = EndLine;
}
PaintActiveBackDDSurface = Form1->RepaintOfPassiveBackDDSurfaceWasFinished;
if (Form1->RepaintOfPassiveBackDDSurfaceWasFinished)
{
Dopom = Form1->ActiveBackDDSurface;
Form1->ActiveBackDDSurface = Form1->PassiveBackDDSurface;
Form1->PassiveBackDDSurface = Dopom;
Form1->RepaintOfPassiveBackDDSurfaceWasFinished = false;
SetEvent(Form1->RepaintBackDDSurface);
BeginLine = Form1->ClientOrigin.y;
EndLine = BeginLine + Form1->Panel1->Top;
ClientOriginYConst = Form1->ClientOrigin.y;
LastPaintedLine = BeginLine;
}
Form1->ApplySettings();
if (Form1->lpDD->GetScanLine(&ScanLine) == DDERR_VERTICALBLANKINPROGRESS) Sleep(1);
}
return(0);
}

//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{

DDSURFACEDESC ddsd;
//Создание объекта DirectDraw
lpDD = NULL;
if (DirectDrawCreate(NULL, &lpDD, NULL) != DD_OK)
{
Application->MessageBox("Проблемы при создании DirectDraw!", "Плохо!", MB_OK);
return;
}
//Установление уровня кооперации для интерфейса DirectDraw
if (lpDD->SetCooperativeLevel(Handle, DDSCL_NORMAL) != DD_OK)
{
Application->MessageBox("Проблемы при установлении уровня кооперации!", "Плохо!", MB_OK);
return;
}
//Заполнение полей структуры DDSURFACEDESC для создания первичной поверхности
ZeroMemory(&ddsd, sizeof(ddsd));
ddsd.dwSize = sizeof(ddsd);
ddsd.dwFlags = DDSD_CAPS;
ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
//Создание первичной поверхности
if (lpDD->CreateSurface(&ddsd, &lpPrimaryDDSurface, NULL) != DD_OK)
{
Application->MessageBox("Проблемы при создании первичной поверхности!", "Плохо!", MB_OK);
return;
}
//Создание объекта отсечения
if (lpDD->CreateClipper(NULL, &lpDDClipper, NULL) != DD_OK)
{
Application->MessageBox("Проблемы при создании объекта Clipper!", "Плохо!", MB_OK);
return;
}
//Связывание объекта отсечения с окном
if (lpDDClipper->SetHWnd(NULL, Handle) != DD_OK)
{
Application->MessageBox("Проблемы при привязке метки окна к Clipper'у!", "Плохо!", MB_OK);
return;
}
//Привязка объекта отсечение к первичной поверхности
if (lpPrimaryDDSurface->SetClipper(lpDDClipper) != DD_OK)
{
Application->MessageBox("Проблемы при привязке Clipper'a к первичной поверхности!", "Плохо!", MB_OK);
return;
}
//Определение параметров монитора
ZeroMemory(&ddsd, sizeof(ddsd));
ddsd.dwSize = sizeof(ddsd);
if (lpDD->GetDisplayMode(&ddsd) != DD_OK)
{
Application->MessageBox("Проблемы при определении режима монитора!", "Плохо!", MB_OK);
return;
}
VerticalResolution = ddsd.dwHeight;
HorizontalResolution = ddsd.dwWidth;
//Создание буферных поверхностей в видеопамяти
ZeroMemory(&ddsd, sizeof(ddsd));
ddsd.dwSize = sizeof(ddsd);
ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY;
ddsd.dwWidth = HorizontalResolution;
ddsd.dwHeight = VerticalResolution;
if (lpDD->CreateSurface(&ddsd, &lpBackDDSurface[0], NULL) != DD_OK || lpDD->CreateSurface(&ddsd, &lpBackDDSurface[1], NULL) != DD_OK)
{
Application->MessageBox("Проблемы при создании буферных поверхностей в видеопамяти!", "Плохо!", MB_OK);
return;
}

ActiveBackDDSurface = 1;
PassiveBackDDSurface = 0;
RepaintOfPassiveBackDDSurfaceWasFinished = false;

//Определение настроек
ButtonApplySettingsClick(NULL);
ApplySettings();

RepaintBackDDSurface = CreateEvent(NULL, FALSE, TRUE, NULL);

RepaintBackDDSurfaceThread = CreateThread(NULL, NULL, RepaintBackDDSurfaces, NULL, CREATE_SUSPENDED, NULL);
SetThreadPriority(RepaintBackDDSurfaceThread, THREAD_PRIORITY_ABOVE_NORMAL);
ResumeThread(RepaintBackDDSurfaceThread);

UpdateScreenThread = CreateThread(NULL, NULL, UpdateScreen, NULL, CREATE_SUSPENDED, NULL);
SetThreadPriority(UpdateScreenThread, THREAD_PRIORITY_TIME_CRITICAL);
ResumeThread(UpdateScreenThread);
}
//---------------------------------------------------------------------------

void __fastcall TForm1::FormDestroy(TObject *Sender)
{
TerminateUpdateScreenThread = true;
TerminateRepaintBackDDSurfaceThread = true;
Sleep(100);
if (lpDD != NULL)
{
if (lpPrimaryDDSurface != NULL)
{
if (lpDDClipper != NULL)
{
lpDDClipper->Release();
lpDDClipper = NULL;
}
lpPrimaryDDSurface->Release();
lpPrimaryDDSurface = NULL;
}
if (lpBackDDSurface[0] != NULL)
{
lpBackDDSurface[0]->Release();
lpBackDDSurface[0] = NULL;
}
if (lpBackDDSurface[1] != NULL)
{
lpBackDDSurface[1]->Release();
lpBackDDSurface[1] = NULL;
}
lpDD->Release();
lpDD = NULL;
}
}

//---------------------------------------------------------------------------

//Генератор псевдослучайных чисел в диапазоне 0 < r < 1

long in_rndm=1; //Начальное значение последовательности

float __fastcall TForm1::Rando()
{
static float r;
m2: in_rndm *= 331804469l;
r=in_rndm*0.232832e-9+0.5;
if(r >=1. || r <= 0.)goto m2;
return r;
}

//---------------------------------------------------------------------------

void __fastcall TForm1::ButtonApplySettingsClick(TObject *Sender)
{
dnew = StrToInt(EditOffsetPerPoint->Text);
}
//---------------------------------------------------------------------------

void __fastcall TForm1::ApplySettings()
{
d = dnew;
}


Буду благодарен за любую помощь!

ПС. В случае необходимости могу выложить и весь билдеровский проект.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения:
СообщениеДобавлено: 07 авг 2006 18:03 
Не в сети
Опытный
Аватара пользователя

Зарегистрирован: 11 авг 2004 17:00
Сообщения: 283
Откуда: Москва
Надеюсь мое сообщение поможет вам. Сразу оговорюсь, что в случае необходимости более подробно смогу написать только через неделю.

1. Функция WaitForVerticalBlank - эта функция просто ждет окончания развертки кадра. То есть вы создали новое изображение во вторичном буфере, затем вызываете эту функцию, она ждет, и сразу после нее вызываете функцию, которая выполняет копирование на основную поверхность. Естественно, ожидание занимает практически все время процессора. Лучше указывать необходимость синхронизации с разверткой при инициализации.

2. Два потока для данной задачи слишком много - достаточно одного. Иначе возникает задача синхронизации потоков. Да и три поверхности избыточно. Первичная - отображается. Вторичная - по набору точек строится график. Вы храните массив точек (для полноэкранного режима 800*600 - 800 точек, реально - еще меньше). Потом на вторичной поверхности строите новый график целиком, синхронизируетесь с кадровым ипульсом и обновляете изображение. 2ГГц вполне достаточно (и даже много).

3. По поводу размытости. На двух моих мониторах в вашем проекте никакой размытости не наблюдается. Проверьте время отклика вашего монитора. (У меня Celeron 1 ГГц, мониторы Samsung 710N и BenQ FP71G)


Вернуться к началу
 Профиль  
 
 Заголовок сообщения:
СообщениеДобавлено: 08 авг 2006 02:13 
Не в сети
Новичок

Зарегистрирован: 07 авг 2006 16:47
Сообщения: 7
Откуда: Киев, Украина
NetLib, спасибо за ответ.
1. Функцию WaitForVerticalBlank не использую именно из-за необоснованого использования всего времени процессора. У меня многооконное приложение. Если каждое дочернее окно будет вызывать WaitForVerticalBlank, то и ресет не поможет =)

2. Поясню, почему использую три поверхности. С первичной все ясно, а буферных две, потому что паралельно выполняются операции блиттинга и построения нового куска графика. Обе эти операции требуют блокировки поверхности, поэтому одновременно строить на поверхности новые точки и блитить эту поверхность на первичную не возможно. Поэтому мы одну поверхность блитим на первичную, а на второй стротим паралельно новый кусок графика. Соответственно для такого распаралеливания надо два потока. Синхронизация потоков выполнена с помощью функции WaitForSingleObject. Перестраивать все точки на каждый кадр - это тормоза страшные. Дело в том, что на каждый пиксел приходится по две точки (в реальных приложениях) и разрешение намного больше, чем 800х600. Плюс сначала нужно сделать заливку поверхности, построить координатную сетку и т.д. Это не те вещи, которые можно успеть сделать за время одного кадра.

3. Скорее всего размытость на ТФТ возникает именно из-за времени отклика. Я вот почитал, пишут, что время отклика - время, необходимое пикселю, чтобы увеличить яркость от 0,1 до 0,9 и назад. То есть выходит, что для того, чтобы черный пиксел стал белым, необходимо половину этого времени? Например, если у матрицы время отклика 25 мс, то на загорание пиксела тогда уходит 12.5 мс. Если частота монитора 60 Гц, то обновление экрана происходит каждые 16 мс. В этом случае время отклика не должно быть помехой (по-идее, могу конечно и ошибаться). Если же частота выше, например 85 Гц, то тогда пиксели просто не успевают загораться полностью до белого света и мы видим размытость графика.
За гипотезу пойдет =)
Говорите, размытости у вас нет? В документации пишут, что оба Ваших монитора имеют время отклика 12 мс... Гм, действительно, может быть в этом дело. А какая частота стоит? И шаг Вы оставили 5 пикселей в программе?

А у меня на ViewSonic VP171 с 16 мс размытие есть =\


Вернуться к началу
 Профиль  
 
 Заголовок сообщения:
СообщениеДобавлено: 08 авг 2006 08:25 
Не в сети
Опытный
Аватара пользователя

Зарегистрирован: 11 авг 2004 17:00
Сообщения: 283
Откуда: Москва
Цитата:
И шаг Вы оставили 5 пикселей в программе?


Шаг ставил разный (от 3 до 20).


Вернуться к началу
 Профиль  
 
 Заголовок сообщения:
СообщениеДобавлено: 08 авг 2006 08:42 
Не в сети
Гуру
Аватара пользователя

Зарегистрирован: 03 авг 2004 10:37
Сообщения: 2694
Есть два основных способа вывода динамического изображения без подергивания:
1. На фоновой поверхности формируете кадр - целиком его копируете на активную.
2. На фоновой поверхности формируете кадр - делаете ее активной.

По поводу WaitForVerticalBlank - как я заметил использовать ее практически бесмысленно.

Мониторы: есть два типа матриц LCD, как я понял, первый тип для геймеров - с маленьким временем отклика и пониженым качеством матрицы; второй - качественная матрица, большое время отклика.

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

_________________
С уважением, Сергей


Вернуться к началу
 Профиль  
 
 Заголовок сообщения:
СообщениеДобавлено: 08 авг 2006 09:35 
Не в сети
Новичок

Зарегистрирован: 07 авг 2006 16:47
Сообщения: 7
Откуда: Киев, Украина
MagicWolf, я использую первый способ, хотя немного модифицирую. То есть я не жду, пока луч дойдет до нижнего края моей формы и не копирую все сразу. Я копирую частями по мере движения луча. Второй способ, как я понимаю это переключение страниц, в моем случае не актуальный ввиду того, что он не работает в окне, то есть с объектом отсечения.

Проблема в том, что прога у меня же не для геймеров. Проблематично как-то в программе представлять требования к времени отклика монитора ;/


Вернуться к началу
 Профиль  
 
 Заголовок сообщения:
СообщениеДобавлено: 08 авг 2006 11:14 
Не в сети
Опытный
Аватара пользователя

Зарегистрирован: 11 авг 2004 17:00
Сообщения: 283
Откуда: Москва
Давайте проверим кто виноват - монитор или программа. Измените цвета графика - выводите его темно серым цветом на черном фоне - если размытость уменьшится, то виноват скорее всего монитор. Если же останется прежней, то это скорее всего софтовая проблема (причем она не обязательно в программе).

Для софтовой проблемы можно попробовать обновить DirectX и посмотреть какой монитор указан в операционной системе.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения:
СообщениеДобавлено: 08 авг 2006 14:56 
Не в сети
Новичок

Зарегистрирован: 07 авг 2006 16:47
Сообщения: 7
Откуда: Киев, Украина
NetLib, спасибо, сейчас попробую. А нет, черт, я ж сейчас дома, а у меня дома трубка :) Ну, буду на работе - попробую :)


Вернуться к началу
 Профиль  
 
 Заголовок сообщения:
СообщениеДобавлено: 16 окт 2007 11:22 
Не в сети
Новичок

Зарегистрирован: 16 окт 2007 11:02
Сообщения: 3
Откуда: Занзибар
NightWishMaster писал(а):
NetLib, спасибо за ответ.
....
3. Скорее всего размытость на ТФТ возникает именно из-за времени отклика. Я вот почитал, пишут, что время отклика - время, необходимое пикселю, чтобы увеличить яркость от 0,1 до 0,9 и назад. То есть выходит, что для того, чтобы черный пиксел стал белым, необходимо половину этого времени? Например, если у матрицы время отклика 25 мс, то на загорание пиксела тогда уходит 12.5 мс. Если частота монитора 60 Гц, то обновление экрана происходит каждые 16 мс. В этом случае время отклика не должно быть помехой (по-идее, могу конечно и ошибаться). Если же частота выше, например 85 Гц, то тогда пиксели просто не успевают загораться полностью до белого света и мы видим размытость графика.
За гипотезу пойдет =)
...
А у меня на ViewSonic VP171 с 16 мс размытие есть =\


За гипотезу пойдет, да не очень!
Вы говорили:

"То есть выходит, что для того, чтобы черный пиксел стал белым"

на самом деле подавляющее большинство матриц TN (LCD) и NT+Film (TFT) работают не на то, что бы сделать черный пиксель белым, а ровно наоборот, потому они потребляют мало энергии, потому у них и цветопередача паршивая по сравнению с матрицами типа MVA, PVA, IPS...жидкие кристаллы которых, в нормальном состоянии не пропускают свет и только при подаче напряжения на тонкопленочные транзисторы (film) происходит поворачивание пикселей в нужную сторону для пропуска через себя света лампы...соответственно и энергопотребляемость таких матриц выше, т.к. требуется высокое напряжение для того, что бы пиксели располагались "к свету лицом".

вы сказали:
"Если же частота выше, например 85 Гц, то тогда пиксели просто не успевают загораться полностью до белого света и мы видим размытость графика. "

поправлю что частота выше чем в 60 Гц на ЖК-матрицах в принципе не нужна, т.к. там нет модулирующего луча, к тому же спешить перерисовывать содержимое экрана нет смысла по той причине, что инерционные способности жидких кристаллов выше чем у люминофора, другими словами после того как кристалл был возбужден - ему требуется больше времени что бы выйти из этого состояния, в то время как люминофор быстро тухнет, потому-то и требует частоту развертки выше 60 Гц (вплоть до 110-120, что является идеальным).

Ну а если же частоту на ЖК-мониторах повышать насильственно, то результатом может являтся как раз ваш случай, когда инерционные свойства кристаллов, из-за высокой частоты их возбуждения, начинают усиливаться, в результате чего пиксели не успевают потухнуть как их уже заново пытаются инициализировать другим значением цвета...надеюсь понятно? какая у вас стоит частота? поставьте на 60 Гц. Думаю есть еще одна причина - перегрев матрицы,
но он в большинстве случаев происходит из-за высокой частоты...
А время отклика у вашего монитора 16 мс? скажу это не так
уж много :(

_________________
не замужем


Вернуться к началу
 Профиль  
 
 Заголовок сообщения:
СообщениеДобавлено: 16 окт 2007 11:51 
Не в сети
Новичок

Зарегистрирован: 16 окт 2007 11:02
Сообщения: 3
Откуда: Занзибар
MagicWolf писал(а):
Есть два основных способа вывода динамического изображения без подергивания:
1. На фоновой поверхности формируете кадр - целиком его копируете на активную.

(блиттинг)
MagicWolf писал(а):
2. На фоновой поверхности формируете кадр - делаете ее активной.

(флиппинг, который работает быстрее)

MagicWolf писал(а):
Мониторы: есть два типа матриц LCD, как я понял, первый тип для геймеров - с маленьким временем отклика и пониженым качеством матрицы; второй - качественная матрица, большое время отклика.
Соответственно у вас качественная матрица с большим временем отклика, и действительно на ней при быстрой смене изображения, будет некая размытость, шлейф от быстро меняющего объекта, с этим ничего не поделать, кроме как заменить монитор.


LCD - это не матрица, это Liquid Crystal Display - жидко кристаллический дисплей, а матрицы это TN, PVA и т.д.
К тому же понятие "качественных матриц" весьма не сомнительное, ведь "качественные" матрицы вроде PVA хоть и обладают хорошей цветопередачей, приближающейся к качеству CRT (мониторы на электронно-лучевой трубке), но в связи с особенностями своей архитектуры являются "пассивными" матрицами, из-за чего время отклика, а следовательно и частота вывода у них медленней чем в TN, из-за того что не существуют "качественных по всем параметрам" матриц и была создана MVA (гибрид в общем).
MagicWolf писал(а):
Соответственно у вас качественная матрица с большим временем отклика, и действительно на ней при быстрой смене изображения, будет некая размытость, шлейф от быстро меняющего объекта, с этим ничего не поделать, кроме как заменить монитор.

Вряд ли у него качественная матрица, мониторы с такой стоят от 500 у.е., это скорее специализированные мониторы для работы с графикой, с тем же фотошопом, где для редактирования фотографий важное значение играет цветопередача монитора, т.е. истинность тех цветов, которые он передает.
Некой размытости от "быстро" меняющегося объекта быть не может по той причине, что у кристаллов высокая инерционность, из-за чего у них есть ограничение в скорости обовления, вместо того что бы работать быстрее они как раз и начинают тормозить, так что их торопить не стоит :)

Единственное что я могу посоветовать, что если проблема действительно в мониторе, то поставить настройки по умолчанию, понизить частоту до 60 Гц (если она стоит выше), или в конечном итоге сменить монитор, взять этак за 220 баксов обычный 15" TFT с TN+FILM матрицей, у них высокая скорость отклика.

_________________
не замужем


Вернуться к началу
 Профиль  
 
 Заголовок сообщения:
СообщениеДобавлено: 16 окт 2007 12:04 
Не в сети
Новичок

Зарегистрирован: 16 окт 2007 11:02
Сообщения: 3
Откуда: Занзибар
NightWishMaster писал(а):
MagicWolf, я использую первый способ, хотя немного модифицирую. То есть я не жду, пока луч...

опять вы про луч? :? так вы говорите про жидкокристаллический или электронно-лучевой монитор?
Я только что дочитал еще одно ваше сообщение и догадываюсь в чем дело...у вас DirectX 6 SDK? :) в любом случае ваш код оптимизирован для работы с лучем: "если луч проходит...то копируем", "пока луч не вернулся в первоначальную позицию -> изменяем", это все относится к вашему "телевизору" :), которые я весьма уважаю.
Я вот о чем, в связи с тем что луча у TFT-монитора нет (он же LCD),
то видеокарта не знает куда деваться, когда вы заставляете выполнять ее код, оптимизированный под другой тип мониторов (они все таки серьезно отличаются), я с такими случаем не встречался лично, но мне КАЖЕТСЯ что проблема именно в этом, попробуйте изменить код, без оптимизации под луч CRT-монитора, я догадываюсь конечно что ваш "модифицированный" код блиттинга, работающий с учетом многопоточности будет утодвинут в сторону...но а как иначе?
Попробовать можно.

_________________
не замужем


Вернуться к началу
 Профиль  
 
Показать сообщения за:  Поле сортировки  
Начать новую тему Ответить на тему  [ Сообщений: 11 ] 

Часовой пояс: UTC + 3 часа [ Летнее время ]


Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 10


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения

Найти:
Перейти:  
cron
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group
Русская поддержка phpBB