mirror of
				https://gitlab.com/freepascal.org/lazarus/lazarus.git
				synced 2025-11-04 16:34:24 +01:00 
			
		
		
		
	
		
			
				
	
	
		
			453 lines
		
	
	
		
			9.8 KiB
		
	
	
	
		
			ObjectPascal
		
	
	
	
	
	
			
		
		
	
	
			453 lines
		
	
	
		
			9.8 KiB
		
	
	
	
		
			ObjectPascal
		
	
	
	
	
	
//
 | 
						|
// AggPas 2.4 RM3 Demo application
 | 
						|
// Note: Press F1 key on run to see more info about this demo
 | 
						|
//
 | 
						|
// Paths: src;src\ctrl;src\svg;src\util;src\platform\win;expat-wrap
 | 
						|
//
 | 
						|
program
 | 
						|
 gouraud ;
 | 
						|
 | 
						|
{DEFINE AGG_GRAY8 }
 | 
						|
{$DEFINE AGG_BGR24 }
 | 
						|
{DEFINE AGG_RGB24 }
 | 
						|
{DEFINE AGG_BGRA32 }
 | 
						|
{DEFINE AGG_RGBA32 }
 | 
						|
{DEFINE AGG_ARGB32 }
 | 
						|
{DEFINE AGG_ABGR32 }
 | 
						|
{DEFINE AGG_RGB565 }
 | 
						|
{DEFINE AGG_RGB555 }
 | 
						|
 | 
						|
uses
 | 
						|
 agg_basics ,
 | 
						|
 agg_platform_support ,
 | 
						|
 | 
						|
 agg_ctrl ,
 | 
						|
 agg_slider_ctrl ,
 | 
						|
 | 
						|
 agg_rasterizer_scanline_aa ,
 | 
						|
 agg_scanline ,
 | 
						|
 agg_scanline_u ,
 | 
						|
 agg_scanline_p ,
 | 
						|
 | 
						|
 agg_renderer_base ,
 | 
						|
 agg_renderer_scanline ,
 | 
						|
 agg_render_scanlines ,
 | 
						|
 | 
						|
 agg_math ,
 | 
						|
 agg_dda_line ,
 | 
						|
 agg_span_allocator ,
 | 
						|
 agg_span_gouraud_rgba ,
 | 
						|
 agg_span_gouraud_gray ,
 | 
						|
 agg_span_solid ,
 | 
						|
 agg_vertex_source ,
 | 
						|
 agg_gamma_functions 
 | 
						|
 | 
						|
{$I pixel_formats.inc }
 | 
						|
{$I agg_mode.inc }
 | 
						|
 | 
						|
const
 | 
						|
 flip_y = true;
 | 
						|
 | 
						|
type
 | 
						|
 the_application = object(platform_support )
 | 
						|
   m_x ,
 | 
						|
   m_y : array[0..2 ] of double;
 | 
						|
 | 
						|
   m_dx ,
 | 
						|
   m_dy : double;
 | 
						|
 | 
						|
   m_idx : int;
 | 
						|
 | 
						|
   m_dilation ,
 | 
						|
   m_gamma    ,
 | 
						|
   m_alpha    : slider_ctrl;
 | 
						|
 | 
						|
   constructor Construct(format_ : pix_format_e; flip_y_ : boolean );
 | 
						|
   destructor  Destruct;
 | 
						|
 | 
						|
   procedure render_gouraud(sl : scanline_ptr; ras : rasterizer_scanline_aa_ptr );
 | 
						|
 | 
						|
   procedure on_draw; virtual;
 | 
						|
 | 
						|
   procedure on_mouse_move       (x ,y : int; flags : unsigned ); virtual;
 | 
						|
   procedure on_mouse_button_down(x ,y : int; flags : unsigned ); virtual;
 | 
						|
   procedure on_mouse_button_up  (x ,y : int; flags : unsigned ); virtual;
 | 
						|
 | 
						|
   procedure on_key(x ,y : int; key ,flags : unsigned ); virtual;
 | 
						|
 | 
						|
  end;
 | 
						|
 | 
						|
{ CONSTRUCT }
 | 
						|
constructor the_application.Construct;
 | 
						|
begin
 | 
						|
 inherited Construct(format_ ,flip_y_ );
 | 
						|
 | 
						|
 m_dilation.Construct(5 ,5 ,400 - 5 ,11 ,not flip_y_ );
 | 
						|
 m_gamma.Construct   (5 ,5 + 15 ,400 - 5 ,11 + 15 ,not flip_y_ );
 | 
						|
 m_alpha.Construct   (5 ,5 + 30 ,400 - 5 ,11 + 30 ,not flip_y_ );
 | 
						|
 | 
						|
 m_idx:=-1;
 | 
						|
 | 
						|
 m_x[0 ]:=57;  m_y[0 ]:=60;
 | 
						|
 m_x[1 ]:=369; m_y[1 ]:=170;
 | 
						|
 m_x[2 ]:=143; m_y[2 ]:=310;
 | 
						|
 | 
						|
 add_ctrl(@m_dilation );
 | 
						|
 add_ctrl(@m_gamma );
 | 
						|
 add_ctrl(@m_alpha );
 | 
						|
 | 
						|
 m_dilation.label_('Dilation=%3.2f' );
 | 
						|
 m_gamma.label_   ('Linear gamma=%3.2f' );
 | 
						|
 m_alpha.label_   ('Opacity=%3.2f' );
 | 
						|
 | 
						|
 m_dilation.value_(0.175 );
 | 
						|
 m_gamma.value_   (0.809 );
 | 
						|
 m_alpha.value_   (1.0 );
 | 
						|
 | 
						|
end;
 | 
						|
 | 
						|
{ DESTRUCT }
 | 
						|
destructor the_application.Destruct;
 | 
						|
begin
 | 
						|
 inherited Destruct;
 | 
						|
 | 
						|
 m_dilation.Destruct;
 | 
						|
 m_gamma.Destruct;
 | 
						|
 m_alpha.Destruct;
 | 
						|
 | 
						|
end;
 | 
						|
 | 
						|
{ RENDER_GOURAUD }
 | 
						|
procedure the_application.render_gouraud;
 | 
						|
var
 | 
						|
 alpha ,brc ,d ,xc ,yc ,x1 ,y1 ,x2 ,y2 ,x3 ,y3 : double; 
 | 
						|
 | 
						|
 pf : pixel_formats;
 | 
						|
 | 
						|
{$IFDEF AGG_GRAY8 }
 | 
						|
 span_gen : span_gouraud_gray;
 | 
						|
 | 
						|
{$ELSE }
 | 
						|
 span_gen : span_gouraud_rgba;
 | 
						|
 | 
						|
{$ENDIF } 
 | 
						|
 | 
						|
 ren_base    : renderer_base;
 | 
						|
 span_alloc  : span_allocator;
 | 
						|
 ren_gouraud : renderer_scanline_aa;
 | 
						|
 | 
						|
 gm_li : gamma_linear;
 | 
						|
 | 
						|
 rgba ,
 | 
						|
 rgbb ,
 | 
						|
 rgbc : aggclr;
 | 
						|
 | 
						|
begin
 | 
						|
 alpha:=m_alpha._value;
 | 
						|
 brc  :=1;
 | 
						|
 | 
						|
// Initialize structures
 | 
						|
 pixfmt(pf ,rbuf_window );
 | 
						|
 | 
						|
 ren_base.Construct   (@pf );
 | 
						|
 span_alloc.Construct;
 | 
						|
 span_gen.Construct   (@span_alloc );
 | 
						|
 ren_gouraud.Construct(@ren_base ,@span_gen );
 | 
						|
 | 
						|
 gm_li.Construct(0.0 ,m_gamma._value );
 | 
						|
 ras.gamma      (@gm_li );
 | 
						|
 | 
						|
 d:=m_dilation._value;
 | 
						|
 | 
						|
// Single triangle
 | 
						|
{ rgba.ConstrDbl   (1 ,0 ,0 ,alpha );
 | 
						|
 rgbb.ConstrDbl   (0 ,1 ,0 ,alpha );
 | 
						|
 rgbc.ConstrDbl   (0 ,0 ,1 ,alpha );
 | 
						|
 span_gen.colors  (@rgba ,@rgbb ,@rgbc );
 | 
						|
 span_gen.triangle(m_x[0 ] ,m_y[0 ] ,m_x[1 ] ,m_y[1 ] ,m_x[2 ] ,m_y[2 ] ,d );
 | 
						|
 | 
						|
 ras.add_path    (@span_gen);
 | 
						|
 render_scanlines(ras ,sl ,@ren_gouraud );{}
 | 
						|
 | 
						|
// Six triangles
 | 
						|
 xc:=(m_x[0 ] + m_x[1 ] + m_x[2 ] ) / 3.0;
 | 
						|
 yc:=(m_y[0 ] + m_y[1 ] + m_y[2 ] ) / 3.0;
 | 
						|
 | 
						|
 x1:=(m_x[1 ] + m_x[0 ] ) / 2 - (xc - (m_x[1 ] + m_x[0 ] ) / 2 );
 | 
						|
 y1:=(m_y[1 ] + m_y[0 ] ) / 2 - (yc - (m_y[1 ] + m_y[0 ] ) / 2 );
 | 
						|
 | 
						|
 x2:=(m_x[2 ] + m_x[1 ] ) / 2 - (xc - (m_x[2 ] + m_x[1 ] ) / 2 );
 | 
						|
 y2:=(m_y[2 ] + m_y[1 ] ) / 2 - (yc - (m_y[2 ] + m_y[1 ] ) / 2 );
 | 
						|
 | 
						|
 x3:=(m_x[0 ] + m_x[2 ] ) / 2 - (xc - (m_x[0 ] + m_x[2 ] ) / 2 );
 | 
						|
 y3:=(m_y[0 ] + m_y[2 ] ) / 2 - (yc - (m_y[0 ] + m_y[2 ] ) / 2 );
 | 
						|
 | 
						|
 rgba.ConstrDbl   (1 ,0 ,0 ,alpha );
 | 
						|
 rgbb.ConstrDbl   (0 ,1 ,0 ,alpha );
 | 
						|
 rgbc.ConstrDbl   (brc ,brc ,brc ,alpha );
 | 
						|
 span_gen.colors_ (@rgba ,@rgbb ,@rgbc );
 | 
						|
 span_gen.triangle(m_x[0 ] ,m_y[0 ] ,m_x[1 ] ,m_y[1 ] ,xc ,yc ,d );
 | 
						|
 | 
						|
 ras.add_path    (@span_gen );
 | 
						|
 render_scanlines(ras ,sl ,@ren_gouraud );
 | 
						|
 | 
						|
 rgba.ConstrDbl   (0 ,1 ,0 ,alpha );
 | 
						|
 rgbb.ConstrDbl   (0 ,0 ,1 ,alpha );
 | 
						|
 rgbc.ConstrDbl   (brc ,brc ,brc ,alpha );
 | 
						|
 span_gen.colors_ (@rgba ,@rgbb ,@rgbc );
 | 
						|
 span_gen.triangle(m_x[1 ] ,m_y[1 ] ,m_x[2 ] ,m_y[2 ] ,xc ,yc ,d );
 | 
						|
 | 
						|
 ras.add_path    (@span_gen );
 | 
						|
 render_scanlines(ras ,sl ,@ren_gouraud );
 | 
						|
 | 
						|
 rgba.ConstrDbl   (0 ,0 ,1 ,alpha );
 | 
						|
 rgbb.ConstrDbl   (1 ,0 ,0 ,alpha );
 | 
						|
 rgbc.ConstrDbl   (brc ,brc ,brc ,alpha );
 | 
						|
 span_gen.colors_ (@rgba ,@rgbb ,@rgbc );
 | 
						|
 span_gen.triangle(m_x[2 ] ,m_y[2 ] ,m_x[0 ] ,m_y[0 ] ,xc ,yc ,d );
 | 
						|
 | 
						|
 ras.add_path    (@span_gen );
 | 
						|
 render_scanlines(ras ,sl ,@ren_gouraud );
 | 
						|
 | 
						|
 brc:=1 - brc;
 | 
						|
 | 
						|
 rgba.ConstrDbl   (1 ,0 ,0 ,alpha );
 | 
						|
 rgbb.ConstrDbl   (0 ,1 ,0 ,alpha );
 | 
						|
 rgbc.ConstrDbl   (brc ,brc ,brc ,alpha );
 | 
						|
 span_gen.colors_ (@rgba ,@rgbb ,@rgbc );
 | 
						|
 span_gen.triangle(m_x[0 ] ,m_y[0 ] ,m_x[1 ] ,m_y[1 ] ,x1 ,y1 ,d );
 | 
						|
 | 
						|
 ras.add_path    (@span_gen );
 | 
						|
 render_scanlines(ras ,sl ,@ren_gouraud );
 | 
						|
 | 
						|
 rgba.ConstrDbl   (0 ,1 ,0 ,alpha );
 | 
						|
 rgbb.ConstrDbl   (0 ,0 ,1 ,alpha );
 | 
						|
 rgbc.ConstrDbl   (brc ,brc ,brc ,alpha );
 | 
						|
 span_gen.colors_ (@rgba ,@rgbb ,@rgbc );
 | 
						|
 span_gen.triangle(m_x[1 ] ,m_y[1 ] ,m_x[2 ] ,m_y[2 ] ,x2 ,y2 ,d );
 | 
						|
 | 
						|
 ras.add_path    (@span_gen);
 | 
						|
 render_scanlines(ras ,sl ,@ren_gouraud );
 | 
						|
 | 
						|
 rgba.ConstrDbl   (0 ,0 ,1 ,alpha );
 | 
						|
 rgbb.ConstrDbl   (1 ,0 ,0 ,alpha );
 | 
						|
 rgbc.ConstrDbl   (brc ,brc ,brc ,alpha );
 | 
						|
 span_gen.colors_ (@rgba ,@rgbb ,@rgbc );
 | 
						|
 span_gen.triangle(m_x[2 ] ,m_y[2 ] ,m_x[0 ] ,m_y[0 ] ,x3 ,y3 ,d );
 | 
						|
 | 
						|
 ras.add_path    (@span_gen );
 | 
						|
 render_scanlines(ras ,sl ,@ren_gouraud );{}
 | 
						|
 | 
						|
// Free AGG resources
 | 
						|
 span_alloc.Destruct;
 | 
						|
 | 
						|
end;
 | 
						|
 | 
						|
{ ON_DRAW }
 | 
						|
procedure the_application.on_draw;
 | 
						|
var
 | 
						|
 pf : pixel_formats;
 | 
						|
 | 
						|
 ren_base  : renderer_base;
 | 
						|
 ren_solid : renderer_scanline_aa_solid;
 | 
						|
 | 
						|
 ras : rasterizer_scanline_aa;
 | 
						|
 sl  : scanline_u8;
 | 
						|
 | 
						|
 rgba  : aggclr;
 | 
						|
 gm_no : vertex_source;
 | 
						|
 | 
						|
begin
 | 
						|
// Initialize structures
 | 
						|
 pixfmt(pf ,rbuf_window );
 | 
						|
 | 
						|
 ren_base.Construct (@pf );
 | 
						|
 ren_solid.Construct(@ren_base );
 | 
						|
 | 
						|
 rgba.ConstrDbl(1 ,1 ,1 );
 | 
						|
 ren_base.clear(@rgba );
 | 
						|
 | 
						|
 sl.Construct;
 | 
						|
 ras.Construct;
 | 
						|
 | 
						|
// Render gouraud
 | 
						|
 render_gouraud(@sl ,@ras );
 | 
						|
 | 
						|
// Render the controls
 | 
						|
 gm_no.Construct;
 | 
						|
 ras.gamma(@gm_no );
 | 
						|
 | 
						|
 render_ctrl(@ras ,@sl ,@ren_solid ,@m_dilation );
 | 
						|
 render_ctrl(@ras ,@sl ,@ren_solid ,@m_gamma );
 | 
						|
 render_ctrl(@ras ,@sl ,@ren_solid ,@m_alpha );
 | 
						|
 | 
						|
// Free AGG resources
 | 
						|
 sl.Destruct;
 | 
						|
 ras.Destruct;
 | 
						|
 | 
						|
end;
 | 
						|
 | 
						|
{ ON_MOUSE_MOVE }
 | 
						|
procedure the_application.on_mouse_move;
 | 
						|
var
 | 
						|
 dx ,dy : double;
 | 
						|
 | 
						|
begin
 | 
						|
 if flags and mouse_left <> 0 then
 | 
						|
  begin
 | 
						|
   if m_idx = 3 then
 | 
						|
    begin
 | 
						|
     dx:=x - m_dx;
 | 
						|
     dy:=y - m_dy;
 | 
						|
 | 
						|
     m_x[1 ]:=m_x[1 ] - (m_x[0 ] - dx );
 | 
						|
     m_y[1 ]:=m_y[1 ] - (m_y[0 ] - dy );
 | 
						|
     m_x[2 ]:=m_x[2 ] - (m_x[0 ] - dx );
 | 
						|
     m_y[2 ]:=m_y[2 ] - (m_y[0 ] - dy );
 | 
						|
     m_x[0 ]:=dx;
 | 
						|
     m_y[0 ]:=dy;
 | 
						|
 | 
						|
     force_redraw;
 | 
						|
     exit;
 | 
						|
 | 
						|
    end;
 | 
						|
 | 
						|
   if m_idx >= 0 then
 | 
						|
    begin
 | 
						|
     m_x[m_idx ]:=x - m_dx;
 | 
						|
     m_y[m_idx ]:=y - m_dy;
 | 
						|
 | 
						|
     force_redraw;
 | 
						|
 | 
						|
    end;
 | 
						|
  
 | 
						|
  end
 | 
						|
 else
 | 
						|
  on_mouse_button_up(x ,y ,flags );
 | 
						|
 | 
						|
end;
 | 
						|
 | 
						|
{ ON_MOUSE_BUTTON_DOWN }
 | 
						|
procedure the_application.on_mouse_button_down;
 | 
						|
var
 | 
						|
 i : unsigned;
 | 
						|
 | 
						|
 sl  : scanline_u8;
 | 
						|
 ras : rasterizer_scanline_aa;
 | 
						|
 buf : array[0..99 ] of char;
 | 
						|
 | 
						|
begin
 | 
						|
 if flags and mouse_right <> 0 then
 | 
						|
  begin
 | 
						|
   sl.Construct;
 | 
						|
   ras.Construct;
 | 
						|
 | 
						|
   start_timer;
 | 
						|
 | 
						|
   for i:=0 to 99 do
 | 
						|
    render_gouraud(@sl ,@ras );
 | 
						|
 | 
						|
   sprintf (@buf[0 ] ,'Time=%2.2f ms' ,elapsed_time );
 | 
						|
   message_(@buf[0 ] );
 | 
						|
 | 
						|
   sl.Destruct;
 | 
						|
   ras.Destruct;
 | 
						|
 | 
						|
  end;
 | 
						|
 | 
						|
 if flags and mouse_left <> 0 then
 | 
						|
  begin
 | 
						|
   i:=0;
 | 
						|
 | 
						|
   while i < 3 do
 | 
						|
    begin
 | 
						|
     if Sqrt((x-m_x[i ] ) * (x-m_x[i ] ) + (y-m_y[i ] ) * (y-m_y[i ] ) ) < 10.0 then
 | 
						|
      begin
 | 
						|
       m_dx :=x - m_x[i ];
 | 
						|
       m_dy :=y - m_y[i ];
 | 
						|
       m_idx:=i;
 | 
						|
 | 
						|
       break;
 | 
						|
 | 
						|
      end;
 | 
						|
 | 
						|
     inc(i );
 | 
						|
 | 
						|
    end;
 | 
						|
 | 
						|
   if i = 3 then
 | 
						|
    if point_in_triangle(m_x[0 ] ,m_y[0 ] ,m_x[1 ] ,m_y[1 ] ,m_x[2 ] ,m_y[2 ] ,x ,y ) then
 | 
						|
     begin
 | 
						|
      m_dx :=x - m_x[0 ];
 | 
						|
      m_dy :=y - m_y[0 ];
 | 
						|
      m_idx:=3;
 | 
						|
 | 
						|
     end;
 | 
						|
 | 
						|
  end;
 | 
						|
 | 
						|
end;
 | 
						|
 | 
						|
{ ON_MOUSE_BUTTON_UP }
 | 
						|
procedure the_application.on_mouse_button_up;
 | 
						|
begin
 | 
						|
 m_idx:=-1;
 | 
						|
 | 
						|
end;
 | 
						|
 | 
						|
{ ON_KEY }
 | 
						|
procedure the_application.on_key;
 | 
						|
var
 | 
						|
 dx ,dy : double;
 | 
						|
 | 
						|
begin
 | 
						|
 dx:=0;
 | 
						|
 dy:=0;
 | 
						|
 | 
						|
 case key of
 | 
						|
  key_left  : dx:=0.1;
 | 
						|
  key_right : dx:=0.1;
 | 
						|
  key_up    : dy:=0.1;
 | 
						|
  key_down  : dy:=-0.1;
 | 
						|
 | 
						|
 end;
 | 
						|
 | 
						|
 m_x[0 ]:=m_x[0 ] + dx;
 | 
						|
 m_y[0 ]:=m_y[0 ] + dy;
 | 
						|
 m_x[1 ]:=m_x[1 ] + dx;
 | 
						|
 m_y[1 ]:=m_y[1 ] + dy;
 | 
						|
 | 
						|
 force_redraw;
 | 
						|
 | 
						|
 if key = key_f1 then
 | 
						|
  message_(
 | 
						|
   'Gouraud shading. It''s a simple method of interpolating colors in a triangle. '#13 +
 | 
						|
   'There''s no "cube" drawn, there''re just 6 triangles. You define a triangle '#13 +
 | 
						|
   'and colors in its vertices. When rendering, the colors will be linearly interpolated. '#13 +
 | 
						|
   'But there''s a problem that appears when drawing adjacent triangles with Anti-Aliasing.'#13 +
 | 
						|
   'Anti-Aliased polygons do not "dock" to each other correctly, there visual artifacts '#13 +
 | 
						|
   'at the edges appear. I call it "the problem of adjacent edges". AGG has a simple '#13 +
 | 
						|
   'mechanism that allows you to get rid of the artifacts, just dilating the polygons '#13 +
 | 
						|
   'and/or changing the gamma-correction value. But it''s tricky, because the values '#13 +
 | 
						|
   'depend on the opacity of the polygons. In this example you can change the opacity, '#13 +
 | 
						|
   'the dilation value and gamma.'#13#13 +
 | 
						|
   'How to play with:'#13#13 +
 | 
						|
   'Use the left mouse button to drag the Red, Green and Blue corners of the "cube".'#13 +
 | 
						|
   'Use the right mouse button to issue a performance test (100x).' +
 | 
						|
   #13#13'Note: F2 key saves current "screenshot" file in this demo''s directory.  ' );
 | 
						|
 | 
						|
end;
 | 
						|
 | 
						|
VAR
 | 
						|
 app : the_application;
 | 
						|
 | 
						|
BEGIN
 | 
						|
 app.Construct(pix_format ,flip_y );
 | 
						|
 app.caption_ ('AGG Example. Gouraud Shading (F1-Help)' );
 | 
						|
 | 
						|
 if app.init(400 ,320 ,window_resize ) then
 | 
						|
  app.run;
 | 
						|
 | 
						|
 app.Destruct;
 | 
						|
 | 
						|
END. |