Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > IT форум > Помощь студентам
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 13.12.2014, 03:46   #11
Smogg
Участник клуба
 
Регистрация: 14.06.2011
Сообщений: 1,138
По умолчанию

О, а это уже интересно))
Можете на словах пояснить, как получился такой перелив?

И как приделать вращающийся свет?
Smogg вне форума Ответить с цитированием
Старый 13.12.2014, 05:14   #12
BDA
МегаМодератор
СуперМодератор
 
Аватар для BDA
 
Регистрация: 09.11.2010
Сообщений: 7,291
По умолчанию

Код:
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, GDIPAPI, GDIPOBJ, ExtCtrls;

type
  TForm1 = class(TForm)
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    procedure FormPaint(Sender: TObject);
    procedure FormMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;
  GPSource: TGPBitmap;
  GPEffect: TGPBitmap;

const
  Xoffset = 150;
  Yoffset = 100;

implementation

{$R *.dfm}

procedure cut(a: real; var b: byte);
begin
  a := a + b;
  if a > 255 then
    b := 255
  else if a < 0 then
    b := 0
  else
    b := round(a);
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  GPSource := TGPBitmap.Create('borders2.png');
  GPEffect := TGPBitmap.Create('borders2.png');
end;

procedure TForm1.FormMouseMove(Sender: TObject; Shift: TShiftState;
  X, Y: Integer);
type
  pix = array [0 .. 1] of byte;
const
  dist = 15;
  k = 127;
  shadow = 0.2;
var
  bmData: TBitmapData;
  bmEf: TBitmapData;
  p: TGPPoint;
  s: TGPSize;
  i, j: Integer;
  b1, b2: ^pix;
  g, h: Integer;
  sumF: real;
  mindist, tmpdist: real;
  ip, jp: Integer;
begin
  p := MakePoint(0, 0);
  s := MakeSize(Integer(GPSource.GetWidth), Integer(GPSource.GetHeight));
  GPSource.LockBits(MakeRect(p, s), ImageLockModeRead,
    PixelFormat32bppARGB, bmData);
  GPEffect.LockBits(MakeRect(p, s), ImageLockModeRead and ImageLockModeWrite,
    PixelFormat32bppARGB, bmEf);
  b1 := bmData.Scan0;
  b2 := bmEf.Scan0;
  X := X - Xoffset - bmData.Width div 2;
  Y := Y - Yoffset - bmData.Height div 2;
  if (X = 0) and (Y = 0) then
  begin
    GPSource.UnlockBits(bmData);
    GPEffect.UnlockBits(bmEf);
    exit;
  end;
  MoveMemory(b2, b1, bmData.Width * bmData.Height * 4);
  for i := 0 to bmData.Height - 1 - 2 * dist do
  begin
    for j := 0 to bmData.Width - 1 - 2 * dist do
    begin
      // BGRA
      if b1[(i + dist) * bmData.stride + 4 * (j + dist) + 3] = 0 then
        continue;
      mindist := sqr(2 * dist);
      for g := i to i + 2 * dist do
        for h := j to j + 2 * dist do
          if (b1[g * bmData.stride + 4 * h + 3] = 0) then
          begin
            tmpdist := sqr(abs(i + dist - g)) + sqr(abs(j + dist - h));
            if tmpdist < mindist then
            begin
              ip := g;
              jp := h;
              mindist := tmpdist;
            end;
          end;
      mindist := sqrt(mindist);
      if mindist > dist then
        continue;
      ip := i + dist - ip;
      jp := j + dist - jp;
//      sumF := k * (-(ip * Y + jp * X) / (sqrt(ip * ip + jp * jp) *
//        sqrt(Y * Y + X * X)) * mindist / dist - shadow);
      sumF := k * (-(ip * Y + jp * X) / (sqrt(Y * Y + X * X) * dist) - shadow);//вроде то же самое, не проверял
      cut(sumF, b2[(i + dist) * bmEf.stride + 4 * (j + dist)]);
      cut(sumF, b2[(i + dist) * bmEf.stride + 4 * (j + dist) + 1]);
      cut(sumF, b2[(i + dist) * bmEf.stride + 4 * (j + dist) + 2]);
    end;
  end;
  GPSource.UnlockBits(bmData);
  GPEffect.UnlockBits(bmEf);
  repaint;
end;

procedure TForm1.FormPaint(Sender: TObject);
var
  graphicsGDIPlus: TGPGraphics;
begin
  graphicsGDIPlus := TGPGraphics.Create(Canvas.Handle);
  graphicsGDIPlus.SetSmoothingMode(4);
  graphicsGDIPlus.DrawImage(GPEffect, Xoffset, Yoffset);
  graphicsGDIPlus.Free;
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
  GPSource.Free;
  GPEffect.Free;
end;

end.
Курсор - источник света. Не гарантирую, что где-нибудь не вылезет деление на ноль
Оптимальности реализации также не гарантирую, так как не знаю GDI+.
Если в 2 словах. Ищется в радиусе прозрачная точка, к которой проводится нормаль. Ищется косинус угла между 2 векторами: первый вектор - центр картинки и курсор мыши, 2 вектор - нормаль.
Пишите язык программирования - это форум программистов, а не экстрасенсов. (<= это подпись )

Последний раз редактировалось BDA; 13.12.2014 в 06:57.
BDA вне форума Ответить с цитированием
Старый 13.12.2014, 13:53   #13
Smogg
Участник клуба
 
Регистрация: 14.06.2011
Сообщений: 1,138
По умолчанию

Большое Спасибо))
Направление освещения, правда, сбоит, ну да это мелочи и тригонометрия.
Осталось лишь перевести на свой ЯП и радоваться))))

А то я убил неделю, написал жуткую портянку, которая все равно выдает дрянь и безбожно тормозит.
Smogg вне форума Ответить с цитированием
Старый 13.12.2014, 17:03   #14
BDA
МегаМодератор
СуперМодератор
 
Аватар для BDA
 
Регистрация: 09.11.2010
Сообщений: 7,291
По умолчанию

Пожалуйста. Скажите, как именно сбоит.
Код:
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, GDIPAPI, GDIPOBJ, ExtCtrls, Vcl.Imaging.pngimage;

type
  TForm1 = class(TForm)
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    procedure FormPaint(Sender: TObject);
    procedure FormMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;
  GPSource: TGPBitmap;
  GPEffect: TGPBitmap;

const
  Xoffset = 150;
  Yoffset = 100;

implementation

{$R *.dfm}

procedure cut(a: real; var b: byte);
begin
  a := a + b;
  if a > 255 then
    b := 255
  else if a < 0 then
    b := 0
  else
    b := round(a);
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  GPSource := TGPBitmap.Create('borders2.png');
  GPEffect := TGPBitmap.Create('borders2.png');
end;

procedure TForm1.FormMouseMove(Sender: TObject; Shift: TShiftState;
  X, Y: Integer);
type
  pix = array [0 .. 1] of byte;
const
  dist = 15;
  k = 127;
var
  bmData: TBitmapData;
  bmEf: TBitmapData;
  p: TGPPoint;
  s: TGPSize;
  i, j: Integer;
  b1, b2: ^pix;
  g, h: Integer;
  sumF: real;
  mindist, tmpdist: real;
  ip, jp: Integer;
begin
  p := MakePoint(0, 0);
  s := MakeSize(Integer(GPSource.GetWidth), Integer(GPSource.GetHeight));
  GPSource.LockBits(MakeRect(p, s), ImageLockModeRead,
    PixelFormat32bppARGB, bmData);
  GPEffect.LockBits(MakeRect(p, s), ImageLockModeRead and ImageLockModeWrite,
    PixelFormat32bppARGB, bmEf);
  b1 := bmData.Scan0;
  b2 := bmEf.Scan0;
  X := X - Xoffset - dist;
  Y := Y - Yoffset - dist;
  MoveMemory(b2, b1, bmData.Width * bmData.Height * 4);
  for i := 0 to bmData.Height - 1 - 2 * dist do
  begin
    for j := 0 to bmData.Width - 1 - 2 * dist do
    begin
      // BGRA
      if b1[(i + dist) * bmData.stride + 4 * (j + dist) + 3] = 0 then
        continue;
      mindist := sqr(2 * dist);
      for g := i to i + 2 * dist do
        for h := j to j + 2 * dist do
          if (b1[g * bmData.stride + 4 * h + 3] = 0) then
          begin
            tmpdist := sqr(abs(i + dist - g)) + sqr(abs(j + dist - h));
            if tmpdist < mindist then
            begin
              ip := g;
              jp := h;
              mindist := tmpdist;
            end;
          end;
      mindist := sqrt(mindist);
      if mindist > dist then
        continue;
      if (Y - i = 0) and (X - j = 0) then
        continue;
      ip := i + dist - ip;
      jp := j + dist - jp;
      sumF := k * (-(ip * (Y - i) + jp * (X - j)) /
        (dist * sqrt(sqr(Y - i) + sqr(X - j))));
      cut(sumF, b2[(i + dist) * bmEf.stride + 4 * (j + dist)]);
      cut(sumF, b2[(i + dist) * bmEf.stride + 4 * (j + dist) + 1]);
      cut(sumF, b2[(i + dist) * bmEf.stride + 4 * (j + dist) + 2]);
    end;
  end;
  GPSource.UnlockBits(bmData);
  GPEffect.UnlockBits(bmEf);
  repaint;
end;

procedure TForm1.FormPaint(Sender: TObject);
var
  graphicsGDIPlus: TGPGraphics;
begin
  graphicsGDIPlus := TGPGraphics.Create(Canvas.Handle);
  graphicsGDIPlus.SetSmoothingMode(4);
  graphicsGDIPlus.DrawImage(GPEffect, Xoffset, Yoffset, GPEffect.GetWidth,
    GPEffect.GetHeight);
  graphicsGDIPlus.Free;
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
  GPSource.Free;
  GPEffect.Free;
end;

end.
Теперь более честная модель - косинус угла между вектором падения света и нормалью.
Приближаемся к модели Фонга (https://ru.wikipedia.org/wiki/Затенение_по_Фонгу)
Изображения
Тип файла: png 3d4.png (55.2 Кб, 59 просмотров)
Пишите язык программирования - это форум программистов, а не экстрасенсов. (<= это подпись )

Последний раз редактировалось BDA; 13.12.2014 в 17:13.
BDA вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Постоянно слетает галочка "автоматически" в "Параметры Excel", "Формулы", "Вычисления в книге" Alexsandrr Microsoft Office Excel 4 19.10.2013 14:22
Создать класс "Фигура", от него наследованием создать 3 класса ("треугольник", "четырехугольник", "окружность") funnyy Помощь студентам 3 17.10.2012 17:40
как можно отключить сообщение "поля раздела выходят за границы области печати. Продолжить?" Dadosh Microsoft Office Word 7 29.07.2012 11:58
Вывести название соответствующей карты вида "шестерка бубен", "дама червей","туз треф" и т.п. воваава Помощь студентам 3 01.12.2011 12:50
при вводе на листе "магазин"- код товара появлялось "описание" товара из "склада" с "продажной ценой" aleksei78 Microsoft Office Excel 13 25.08.2009 12:04