Имя пользователя:
Пароль:  
Помощь | Регистрация | Забыли пароль?  | Правила  

Компьютерный форум OSzone.net » Программирование, базы данных и автоматизация действий » Программирование и базы данных » Теория - Красный матовый шар, освещённый солнцем... [ПАСКАЛЬ]

Ответить
Настройки темы
Теория - Красный матовый шар, освещённый солнцем... [ПАСКАЛЬ]

Аватара для ManHack

Старожил


Сообщения: 361
Благодарности: 6

Профиль | Отправить PM | Цитировать


Суть задачи такова:
нужно построить красный матовый шарик, освещённый вектором света.
Проблема в том, что светлое место на шарике должно переходить в полутень, а потом в тень плавно.
Но линии начала полутени и тени изогнуты по-разному (надо сделать так, чтобы они были изогнуты одинаково).
И, кроме того, при некоторых координатах, линия тени, идущая по экватору шара, становится не круглой (почти треугольной).
Это тоже надо исправить.

Вот уже написанный текст программы на Паскале:

Код: Выделить весь код
Program graph2; {310 190}
uses Graph;
const
	cir: record
   	x, y, r: longint;
      kp, kh, kz :real;
   end =(
      x: 160;
      y: 180;
      r: 60;
      kp: 1;
      kh: 1;
      kz: 0.5

      );
   sun: record
   	x, y, z: integer;
      Ip, Ih: real;
   end =(
   	x: -1; {70}
      y: 1; {120}
      z: 1; {80}
      Ip: 8;
      Ih: 56
      );

   {nabl: record
   	x, y, z :integer;
   end =(
   	x: 20;
      y: -40;
      z: 20
      );}

   n = 200;
   nah = 10;

   long = 100;
   dlin = 200;


var
   xc, yc, zc, xs, ys, zs: integer;
{--------------}
function fX(x, y: real): integer;
begin
	fX := round(x + y/(2*sqrt(2)) + nah);
end;



function fY(y, z: real): integer;
begin
	fY := GetMaxY - nah - round(z + y/(2*sqrt(2)));
end;



function Color(I: real): integer;
var
	j: integer;
begin
	j := round(I);
   if j>95 then
   	j := 95;
	Color := j + 127;
end;




{---------------}

procedure SetPalette;
var
   j          : integer;
   cR, cG, cB : integer;
begin
   for j := 0 to 95 do begin
      if j < 64 then begin
         cR := j; cG := j - j; cB := j - j;
         end;
      {else if (j-64) < 32 then begin
         cR := 255; cG := 255; cB := 255;
         end;}

      SetRGBPalette(j + 127, cR, cG, cB );
   end;
end;

procedure Ris(x, y, z: real; var first: Boolean; col:integer);
begin
	{
	if first then begin
   	MoveTo(fX(x, y), fY(y, z));
   	first := false;
      end
   else
   	SetColor(col);
      LineTo(fX(x, y), fY(y,z));
      }
   {if (cir.x*cir.x - x*x) + (cir.y*cir.y - y*y) + (cir.z*cir.z - z*z) <=
	cir.r then }
   	putpixel(fX(x, y), fY(y, z),col);

end;

procedure RisNew(x, y:integer; col:integer);
begin
	putpixel(x, y, col);

end;


procedure Display;
var
	x,y:integer;
begin
	{OX}
   	line(nah, GetMaxY - nah, nah + long, GetMaxY - nah);
      line(nah + long, GetMaxY - nah, long, GetMaxY - 2*nah);
      line(nah + long, GetMaxY - nah, long, GetMaxY);
      OutTextXY(Long + nah, GetMaxY - nah, 'x');
   {OY}
      line(nah, GetMaxY - nah, fX(0, nah + long), fY(nah + long, 0));
      line(fX(0, nah + long), fY(nah + long, 0), fX(0, nah + long) -
		nah, fY(nah + long, 0));
      line(fX(0, nah + long), fY(nah + long, 0), fX(0, nah + long),
		fY(nah + long, 0) + nah);
      OutTextXY(fX(0, nah + long), fY(nah + long, 0), 'y');
   {OZ}
      line(nah, GetMaxY - nah, nah, GetMaxY - nah - long);
      line(nah, GetMaxY - nah - long, 0, GetMaxY - long);
      line(nah, GetMaxY - nah - long, 2*nah, GetMaxY - long);
      OutTextXY(0, GetMaxY - nah - long, 'z');

	{0 }
      OutTextXY(10, GetMaxY-7, '0');

		SetColor(Yellow);
      For x := 0 to dlin do
         Line(fX(nah + x, nah), fY(nah, 0), fX(nah + x, nah + dlin),
			fY(15 + dlin, 0 ));
      SetColor(White);
end;



procedure Sphere;
var
	z, I, Cosinus, a1, b1, a2, b2, a3, b3: real;
   col: integer;
   x, y: longint;
begin

   { sun.x := round(sun.x+sun.y/sqrt(2)); // искривление координат
   sun.y := round(sun.y/sqrt(2));}             // для задания вида в перспективе
   for x := 0 to GetMaxX do begin
   	for y := 0 to GetMaxY do begin
      	if sqr(cir.x - x) + sqr(cir.y - y) < sqr(cir.r) then begin

         	z := cir.r - sqrt(sqr(cir.x - x) + sqr(cir.y - y)); // координата Z шарика вводится искуственно, 
                                                                                 // пользователь задаёт положение шарика только координатами X и Y

         	{a1 := x - cir.x;
            a2 := (y - cir.y);
            a3 := z;
            b1 := -sun.x;
            b2 := sun.y;
            b3 := sun.z;
            if (sqrt(a1*a1 + a2*a2 + a3*a3)*sqrt(b1*b1 + b2*b2 + b3*b3))=0 then
            	cosinus:=0
            else
            	cosinus:=(a1*b1 + a2*b2 + a3*b3)/
					   (sqrt(a1*a1 + a2*a2 + a3*a3)*sqrt(b1*b1 + b2*b2 + b3*b3));
            if cosinus<0 then
         	   cosinus:=0; }

            a1 := x - cir.x;
            a2 := y - cir.y;
            a3 := z;
            b1 := -sun.x;
            b2 := sun.z;
            b3 := sun.y;
            if (sqrt(a1*a1 + a2*a2 + a3*a3)*sqrt(b1*b1 + b2*b2 + b3*b3))=0 then
            	cosinus:=0
            else
            	cosinus:=(a1*b1 + a2*b2 + a3*b3)/
					   (sqrt(a1*a1 + a2*a2 + a3*a3)*sqrt(b1*b1 + b2*b2 + b3*b3));
            if cosinus<0 then
         	   cosinus:=0;


   		   I:= cir.Kp*sun.Ip +
           	   cir.Kh*sun.Ih*cosinus;  // формула задания освещённости, взята из умной книжки 

            col:=Color(I);

            RisNew(x,y,col);
         end;
      end;
   end;
end;


procedure GraphInit;
var
	grDriver, grMode : integer;
begin
	grDriver := InstallUserDriver( 'SVGA256', nil );
	grMode := 2; { 320x200, 256 ”ХЙЃјХ }
	InitGraph( grDriver, grMode, '' );
end;


procedure Init_Graph;

   {$F+}
   function DetectVGA256:Integer;
   var
      GraphDriver, Graphmode: Integer;
   begin {DetectVGA256}
    if GraphDriver = VGA then
       DetectVga256 := 1
    else
       DetectVGA256 := grError;
   end;  {DetectVGA256}
   {$F-}

var
   VGA256, GD, GM: Integer;

begin {Init_Graph}
   VGA256 := InstallUserDriver('VGA256',@DetectVGA256);
   Gd := VGA256;
   InitGraph(GD,GM,'');

   SetBkColor(Black);
   SetColor(White);
end;  {Init_Graph}

{------------------------}

begin
   GraphInit;   {}
   {Init_Graph;        {}
   SetPalette;
   Display;    {}

   sphere;

   Readln;
   CloseGraph;
end.

Отправлено: 01:03, 05-04-2009

 
pva pva вне форума

Аватара для pva

Ветеран


Сообщения: 1180
Благодарности: 279

Профиль | Отправить PM | Цитировать


Изображения
Тип файла: jpg Безымянный.JPG
(56.0 Kb, 14 просмотров)

1. Возможно дело в квантизации (неравномерная изогнутость линий). То есть заметен переход от RGB(10,10,10) к RGB(11,11,11), Такой же эффект может возникнуть при округлении (при целочисленной арифметике особенно).
2. Проверь ограничение значения косинуса угла между освещающим вектором и нормалью поверхности. Он может принимать отрицательные значения (как бы освещение изнутри). Влияет на появление артефактов освещения в тени.
3. Проверь ограничения на попадание в шар (при сканировании картинки) - освещение вне шара
4. В аттачменте примерно так оно работает (сделано в математике 4.0)
Понимаю, что текст математики выглядит мягко говоря непонятно... Если есть вопросы - охотно объясню.
Это сообщение посчитали полезным следующие участники:

Отправлено: 11:22, 05-04-2009 | #2



Для отключения данного рекламного блока вам необходимо зарегистрироваться или войти с учетной записью социальной сети.

Если же вы забыли свой пароль на форуме, то воспользуйтесь данной ссылкой для восстановления пароля.


Аватара для ManHack

Старожил


Сообщения: 361
Благодарности: 6

Профиль | Отправить PM | Цитировать


1) Если так, как можно исправить?
2) Для отрицательных косинусов значению косинуса присваивается нуль, это я учёл.
3) Не понял...
4) В идеале линия разделения света и тени должна проходить чётко по экватору шарика, на картинке далеко не так...
А текст там и правда не слишком понятный ><

Отправлено: 23:53, 07-04-2009 | #3

pva pva вне форума

Аватара для pva

Ветеран


Сообщения: 1180
Благодарности: 279

Профиль | Отправить PM | Цитировать


Изображения
Тип файла: jpg 1.JPG
(57.5 Kb, 8 просмотров)
Тип файла: jpg 2.JPG
(97.7 Kb, 6 просмотров)

1) Можно использовать диферинг, то есть добавить в цвет шумовую составляющую с разбросом 1-2 значения интенсивности. Глаз "сгладит" соседние пиксели по среднему и получится эффект более плавных переходов.
3) я пробегал каждый пиксель картинки и вычислял в нём 3-мерную нормаль к поверхности. Там, где поверхности нет (вне шара) - за нормаль был принят нулевой вектор.
4) Линия и так чётко по экватору, просто надо помнить, что мы видим проекцию, то есть экватор (круг) вырождается в эллипс или отрезок.

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

Отправлено: 11:36, 08-04-2009 | #4

pva pva вне форума

Аватара для pva

Ветеран


Сообщения: 1180
Благодарности: 279

Профиль | Отправить PM | Цитировать


Изображения
Тип файла: jpg 3.JPG
(64.9 Kb, 8 просмотров)

Без отражения (то есть чисто за счёт матового рассеяния во все стороны) выглядит неестественно, добавляем отражение (будем считать что освещение идёт от бесконечного белого размазанного пятна, расположенного на расстоянии бесконечности)
1. считаем что матовое рассеяние идёт линейно n1.light, где n1 - нормаль к поверхности, light - направление падающей волны, точка - скалярное произведение.
2. считаем что пятно света с учётом всех эффектов даёт экспоненциальную функцию рассеяния. Отражённый луч вычисляем так: reflect1 = light - n1 (2(n1.light)). На экран попадает только его положительно направленная проекция на ось z, то есть reflect = Max[0,reflect1.{0,0,-1}]

Последний раз редактировалось pva, 25-02-2012 в 11:59.


Отправлено: 07:45, 10-04-2009 | #5



Компьютерный форум OSzone.net » Программирование, базы данных и автоматизация действий » Программирование и базы данных » Теория - Красный матовый шар, освещённый солнцем... [ПАСКАЛЬ]

Участник сейчас на форуме Участник сейчас на форуме Участник вне форума Участник вне форума Автор темы Автор темы Шапка темы Сообщение прикреплено

Похожие темы
Название темы Автор Информация о форуме Ответов Последнее сообщение
[решено] Перенаправление шар charodey_mag Microsoft Windows NT/2000/2003 10 19-03-2009 12:03
Экспорт шар charodey_mag Microsoft Windows NT/2000/2003 4 20-02-2009 01:14
Срочно нужен красный ноут. Dino_007 Ноутбуки 1 04-01-2009 18:03
Монтирование шар с NT 4.0 thebas Microsoft Windows NT/2000/2003 2 26-12-2008 17:39
Монитор - глянцевый или матовый? DVDshnik Прочее железо 0 07-11-2008 11:38




 
Переход