GMLscripts.com

Discuss and collaborate on GML scripts
Invert

You are not logged in.

#1 2010-04-09 14:23:47

brac37
Member
Registered: 2010-02-12
Posts: 18

Reflection of trianglestrips.

Hello all,

I wrote scripts for reflecting trianglestrips. The hardest about that is to cut out the part that is behind the mirror. See also http://gmc.yoyogames.com/index.php?showtopic=444886

Expand/*
**  Usage:
**      d3d_model_primitive_reflection_begin (ind, mode, nx, ny, nz, lev)
**
**  Arguments:
**      ind:            index of model
**      mode:           0 = reflect, 1 = no reflect, 
**                      2 = reflect except for normals      
**      nx, ny, nz:     normal of plane of reflection (optional)
**      lev:            level of plane of reflection 
**                      { (x,y,z) | nx * x + ny * y + nz * z = lev }
**
**  Returns:
**      nothing
**
**  Notes:
**      A trianglestrip is created. Use this function along with
**      d3d_model_vertex_reflection (), d3d_model_vertex_normal_reflection ()
**      and d3d_model_primitive_reflection_end ().
**      Vertexes { (x,y,z) | nx * x + ny * y + nz * z > lev } of the shape 
**      are reflected. Vertexes { (x,y,z) | nx * x + ny * y + nz * z > lev }
**      of the shape are cut out. This is useful for making reflections of 
**      models.
**
**  brac37
*/
{
    var i, n;
    
    i = argument0;
    _reflect[i] = argument1 ^ 1;
    if (_reflect[i] & 1) _reflect[i] ^= 2;
    _planenx[i] = argument2;
    _planeny[i] = argument3;
    _planenz[i] = argument4;
    _planene[i] = argument5;
    
    if (_planenx[i] == 0 and _planeny[i] == 0 and _planenz[i] == 0) {
        _planenz[i] = 1;
    }  
    n = sqrt (2 / (sqr(_planenx[i]) + sqr(_planeny[i]) + sqr(_planenz[i])));
    _planenx[i] *= n;
    _planeny[i] *= n;
    _planenz[i] *= n;
    _planene[i] *= n;

    d3d_model_primitive_begin(i, pr_trianglestrip);
    _nvertices[i] = 0;
    _lastnx[i] = 0;
    _lastny[i] = 0;
    _lastnz[i] = 0;
    _thisnx[i] = 0;
    _thisny[i] = 0;
    _thisnz[i] = 0;
}
Expand/*
**  Usage:
**      d3d_model_vertex_reflection (ind, x, y, z, u, v, c, a)
**
**  Arguments:
**      ind:            index of model
**      x, y, z:        coordinates of vertex 
**      u, v:           texture coordinates of vertex (optional)
**      c, a:           color and alpha of vertex (optional)
**
**  Returns:
**      nothing
**
**  Notes:
**      See d3d_model_primitive_reflection_begin ().
**
**  brac37
*/
{
    var i;
    i = argument0;
    if (_nvertices[i] > 1) {
        _lastx[i] = _thisx[i];  
        _lasty[i] = _thisy[i];  
        _lastz[i] = _thisz[i];  
        _lastne[i] = _thisne[i];  
        _lastu[i] = _thisu[i];
        _lastv[i] = _thisv[i];  
        _lastc[i] = _thisc[i];  
        _lasta[i] = _thisa[i];  
    }
    if (_nvertices[i] > 0) {
        _thisx[i] = _nextx[i];  
        _thisy[i] = _nexty[i];  
        _thisz[i] = _nextz[i];  
        _thisne[i] = _nextne[i];  
        _thisu[i] = _nextu[i];
        _thisv[i] = _nextv[i];  
        _thisc[i] = _nextc[i];  
        _thisa[i] = _nexta[i];  
    }
    _nextx[i] = argument1;  
    _nexty[i] = argument2;  
    _nextz[i] = argument3;  
    _nextu[i] = argument4;
    _nextv[i] = argument5;  
    _nextc[i] = argument6;  
    _nexta[i] = argument7;
    if (_nextc[i] == 0 and _nexta[i] == 0 and argument8 == 0) {
        _nextc[i] = c_white;
        _nexta[i] = 1;
    }
    _nextne[i] = _planenx[i]*_nextx[i] + _planeny[i]*_nexty[i] + 
                 _planenz[i]*_nextz[i] - _planene[i];
    if (_reflect[i] & 1) {
        _nextx[i] -= _nextne[i]*_planenx[i];
        _nexty[i] -= _nextne[i]*_planeny[i];
        _nextz[i] -= _nextne[i]*_planenz[i];
    } 
    
    var w1, w2;  
    if (_nvertices[i] == 1) {
        _parity[i] = 0;
        if (_thisne[i] >= 0) {
            d3d_model_vertex_texture_color (i,_thisx[i],_thisy[i],_thisz[i],
                                    _thisu[i],_thisv[i],_thisc[i],_thisa[i]);
            if (_reflect[i] & 1) {                            
                d3d_model_vertex_texture_color (i,_thisx[i],_thisy[i],_thisz[i],
                                        _thisu[i],_thisv[i],_thisc[i],_thisa[i]);
            }
        } else if (_nextne[i] >= 0) {
            w2 = _thisne[i]/(_thisne[i]-_nextne[i]);
            w1 = 1 - w2;
            d3d_model_vertex_texture_color (i,_thisx[i]*w1+_nextx[i]*w2,
                    _thisy[i]*w1+_nexty[i]*w2,_thisz[i]*w1+_nextz[i]*w2,
                    _thisu[i]*w1+_nextu[i]*w2,_thisv[i]*w1+_nextv[i]*w2,
                    merge_color(_thisc[i],_nextc[i],w2),
                    _thisa[i]*w1+_nexta[i]*w2);
            if (_reflect[i] & 1) {                            
                d3d_model_vertex_texture_color (i,_thisx[i]*w1+_nextx[i]*w2,
                        _thisy[i]*w1+_nexty[i]*w2,_thisz[i]*w1+_nextz[i]*w2,
                        _thisu[i]*w1+_nextu[i]*w2,_thisv[i]*w1+_nextv[i]*w2,
                        merge_color(_thisc[i],_nextc[i],w2),
                        _thisa[i]*w1+_nexta[i]*w2);
            }
        }
    } else if (_nvertices[i] > 1) {
        if (_parity[i] == 0 and _thisne[i] >= 0) {
            d3d_model_vertex_texture_color (i,_thisx[i],_thisy[i],_thisz[i],
                                    _thisu[i],_thisv[i],_thisc[i],_thisa[i]);
            _parity[i] = 1;
        } else if (_thisne[i] < 0 and _lastne[i] >= 0) {                             
            w2 = _thisne[i]/(_thisne[i]-_lastne[i]);
            w1 = 1 - w2;
            d3d_model_vertex_texture_color (i,_thisx[i]*w1+_lastx[i]*w2,
                    _thisy[i]*w1+_lasty[i]*w2,_thisz[i]*w1+_lastz[i]*w2,
                    _thisu[i]*w1+_lastu[i]*w2,_thisv[i]*w1+_lastv[i]*w2,
                    merge_color(_thisc[i],_lastc[i],w2),
                    _thisa[i]*w1+_lasta[i]*w2);
            if (_parity[i] and _nextne[i] >= 0) {
                d3d_model_vertex_texture_color (i,_thisx[i]*w1+_lastx[i]*w2,
                        _thisy[i]*w1+_lasty[i]*w2,_thisz[i]*w1+_lastz[i]*w2,
                        _thisu[i]*w1+_lastu[i]*w2,_thisv[i]*w1+_lastv[i]*w2,
                        merge_color(_thisc[i],_lastc[i],w2),
                        _thisa[i]*w1+_lasta[i]*w2);
            }              
            _parity[i] = 1;
        }
        if (_lastne[i]*_nextne[i] <= 0 or (_lastne[i] >= 0 and _thisne[i] < 0)) {
            if (_lastne[i] < 0 and _thisne[i] < 0) {
                d3d_model_primitive_end (i);
                d3d_model_primitive_begin (i, pr_trianglestrip);
                _parity[i] = (_nvertices[i] & 1) == (_reflect[i] & 1);
            }  
            w2 = abs(_lastne[i])/(abs(_lastne[i])+abs(_nextne[i]));
            w1 = 1 - w2;
            d3d_model_vertex_texture_color (i,_lastx[i]*w1+_nextx[i]*w2,
                    _lasty[i]*w1+_nexty[i]*w2,_lastz[i]*w1+_nextz[i]*w2,
                    _lastu[i]*w1+_nextu[i]*w2,_lastv[i]*w1+_nextv[i]*w2,
                    merge_color(_lastc[i],_nextc[i],w2),
                    _lasta[i]*w1+_nexta[i]*w2);
            if (_parity[i] == 0) {
            d3d_model_vertex_texture_color (i,_lastx[i]*w1+_nextx[i]*w2,
                    _lasty[i]*w1+_nexty[i]*w2,_lastz[i]*w1+_nextz[i]*w2,
                    _lastu[i]*w1+_nextu[i]*w2,_lastv[i]*w1+_nextv[i]*w2,
                    merge_color(_lastc[i],_nextc[i],w2),
                    _lasta[i]*w1+_nexta[i]*w2);
            }
            _parity[i] = 0;                
        } 
        if (_parity[i] == 0 and _thisne[i] >= 0) {
            d3d_model_vertex_texture_color (i,_thisx[i],_thisy[i],_thisz[i],
                                    _thisu[i],_thisv[i],_thisc[i],_thisa[i]);
        } else if (_nextne[i] >= 0 and _thisne[i] < 0) {
            w2 = _thisne[i]/(_thisne[i]-_nextne[i]);
            w1 = 1 - w2;
            d3d_model_vertex_texture_color (i,_thisx[i]*w1+_nextx[i]*w2,
                    _thisy[i]*w1+_nexty[i]*w2,_thisz[i]*w1+_nextz[i]*w2,
                    _thisu[i]*w1+_nextu[i]*w2,_thisv[i]*w1+_nextv[i]*w2,
                    merge_color(_thisc[i],_nextc[i],w2),
                    _thisa[i]*w1+_nexta[i]*w2);
            if (_parity[i]) {
                d3d_model_vertex_texture_color (i,_thisx[i]*w1+_nextx[i]*w2,
                        _thisy[i]*w1+_nexty[i]*w2,_thisz[i]*w1+_nextz[i]*w2,
                        _thisu[i]*w1+_nextu[i]*w2,_thisv[i]*w1+_nextv[i]*w2,
                        merge_color(_thisc[i],_nextc[i],w2),
                        _thisa[i]*w1+_nexta[i]*w2);
            }          
            _parity[i] = 0;
        } else {
            _parity[i] = not _parity[i];
        }
    }           
    _nvertices[i] += 1;
}
Expand/*
**  Usage:
**      d3d_model_vertex_normal_reflection (ind, x, y, z, nx, ny, nz, 
**                                          u, v, c, a)
**
**  Arguments:
**      ind:            index of model
**      x, y, z:        coordinates of vertex 
**      nx, ny, nz:     coordinates of vertex normal
**      u, v:           texture coordinates of vertex (optional)
**      c, a:           color and alpha of vertex (optional)
**
**  Returns:
**      nothing
**
**  Notes:
**      See d3d_model_primitive_reflection_begin ().
**
**  brac37
*/
{
    var i;
    i = argument0;
    if (_nvertices[i] > 1) {
        _lastx[i] = _thisx[i];    
        _lasty[i] = _thisy[i];    
        _lastz[i] = _thisz[i];    
        _lastnx[i] = _thisnx[i];    
        _lastny[i] = _thisny[i];    
        _lastnz[i] = _thisnz[i];    
        _lastne[i] = _thisne[i];    
        _lastu[i] = _thisu[i];
        _lastv[i] = _thisv[i];    
        _lastc[i] = _thisc[i];    
        _lasta[i] = _thisa[i];    
    }
    if (_nvertices[i] > 0) {
        _thisx[i] = _nextx[i];    
        _thisy[i] = _nexty[i];    
        _thisz[i] = _nextz[i];    
        _thisnx[i] = _nextnx[i];    
        _thisny[i] = _nextny[i];    
        _thisnz[i] = _nextnz[i];    
        _thisne[i] = _nextne[i];    
        _thisu[i] = _nextu[i];
        _thisv[i] = _nextv[i];    
        _thisc[i] = _nextc[i];    
        _thisa[i] = _nexta[i];    
    }
    _nextx[i] = argument1;    
    _nexty[i] = argument2;    
    _nextz[i] = argument3;    
    _nextnx[i] = argument4;    
    _nextny[i] = argument5;    
    _nextnz[i] = argument6;    
    _nextu[i] = argument7;
    _nextv[i] = argument8;    
    _nextc[i] = argument9;    
    _nexta[i] = argument10;
    if (_nextc[i] == 0 and _nexta[i] == 0 and argument11 == 0) {
        _nextc[i] = c_white;
        _nexta[i] = 1;
    }
    if (_reflect[i] & 2) {
        _nextne[i] = _planenx[i]*_nextnx[i] + _planeny[i]*_nextny[i] + 
                     _planenz[i]*_nextnz[i];
        _nextnx[i] -= _nextne[i]*_planenx[i];
        _nextny[i] -= _nextne[i]*_planeny[i];
        _nextnz[i] -= _nextne[i]*_planenz[i];
    }
    _nextne[i] = _planenx[i]*_nextx[i] + _planeny[i]*_nexty[i] + 
                 _planenz[i]*_nextz[i] - _planene[i];
    if (_reflect[i] & 1) {
        _nextx[i] -= _nextne[i]*_planenx[i];
        _nexty[i] -= _nextne[i]*_planeny[i];
        _nextz[i] -= _nextne[i]*_planenz[i];
    }
    
    var w1, w2, n, nx, ny, nz;    
    if (_nvertices[i] == 1) {
        _parity[i] = 0;
        if (_thisne[i] >= 0) {
            d3d_model_vertex_normal_texture_color (i,_thisx[i],_thisy[i],
                              _thisz[i],_thisnx[i],_thisny[i],_thisnz[i],
                              _thisu[i],_thisv[i],_thisc[i],_thisa[i]);
            if (_reflect[i] & 1) {                                                        
                d3d_model_vertex_normal_texture_color (i,_thisx[i],_thisy[i],
                                                                _thisz[i],_thisnx[i],_thisny[i],_thisnz[i],
                                                                _thisu[i],_thisv[i],_thisc[i],_thisa[i]);
            }
        } else if (_nextne[i] >= 0) {
            w2 = _thisne[i]/(_thisne[i]-_nextne[i]);
            w1 = 1 - w2;
            nx = _thisnx[i]*w1+_nextnx[i]*w2;
            ny = _thisny[i]*w1+_nextny[i]*w2;
            nz = _thisnz[i]*w1+_nextnz[i]*w2;
            n = 1/sqrt(sqr(nx)+sqr(ny)+sqr(nz));
            d3d_model_vertex_normal_texture_color (i,_thisx[i]*w1+_nextx[i]*w2,
                           _thisy[i]*w1+_nexty[i]*w2,_thisz[i]*w1+_nextz[i]*w2,
                           nx*n,ny*n,nz*n,
                           _thisu[i]*w1+_nextu[i]*w2,_thisv[i]*w1+_nextv[i]*w2,
                           merge_color(_thisc[i],_nextc[i],w2),
                           _thisa[i]*w1+_nexta[i]*w2);
            if (_reflect[i] & 1) {                        
                d3d_model_vertex_normal_texture_color (i,_thisx[i]*w1+_nextx[i]*w2,
                               _thisy[i]*w1+_nexty[i]*w2,_thisz[i]*w1+_nextz[i]*w2,
                               nx*n,ny*n,nz*n,
                               _thisu[i]*w1+_nextu[i]*w2,_thisv[i]*w1+_nextv[i]*w2,
                               merge_color(_thisc[i],_nextc[i],w2),
                               _thisa[i]*w1+_nexta[i]*w2);
            }
        }
    } else if (_nvertices[i] > 1) {
        if (_parity[i] == 0 and _thisne[i] >= 0) {
            d3d_model_vertex_normal_texture_color (i,_thisx[i],_thisy[i],
                              _thisz[i],_thisnx[i],_thisny[i],_thisnz[i],
                              _thisu[i],_thisv[i],_thisc[i],_thisa[i]);
            _parity[i] = 1;
        } else if (_thisne[i] < 0 and _lastne[i] >= 0) {                                                         
                w2 = _thisne[i]/(_thisne[i]-_lastne[i]);
                w1 = 1 - w2;
                nx = _thisnx[i]*w1+_lastnx[i]*w2;
                ny = _thisny[i]*w1+_lastny[i]*w2;
                nz = _thisnz[i]*w1+_lastnz[i]*w2;
                n = 1/sqrt(sqr(nx)+sqr(ny)+sqr(nz));
                d3d_model_vertex_normal_texture_color (i,_thisx[i]*w1+_lastx[i]*w2,
                               _thisy[i]*w1+_lasty[i]*w2,_thisz[i]*w1+_lastz[i]*w2,
                               nx*n,ny*n,nz*n,
                               _thisu[i]*w1+_lastu[i]*w2,_thisv[i]*w1+_lastv[i]*w2,
                               merge_color(_thisc[i],_lastc[i],w2),
                               _thisa[i]*w1+_lasta[i]*w2);
                if (_parity[i] and _nextne[i] >= 0) {
                    d3d_model_vertex_normal_texture_color (i,_thisx[i]*w1+_lastx[i]*w2,
                                   _thisy[i]*w1+_lasty[i]*w2,_thisz[i]*w1+_lastz[i]*w2,
                                   nx*n,ny*n,nz*n,
                                   _thisu[i]*w1+_lastu[i]*w2,_thisv[i]*w1+_lastv[i]*w2,
                                   merge_color(_thisc[i],_lastc[i],w2),
                                   _thisa[i]*w1+_lasta[i]*w2);
                }                            
                _parity[i] = 1;
        }
        if (_lastne[i]*_nextne[i] <= 0 or (_lastne[i] >= 0 and _thisne[i] < 0)) {
            if (_lastne[i] < 0 and _thisne[i] < 0) {
                d3d_model_primitive_end (i);
                d3d_model_primitive_begin (i, pr_trianglestrip);
                _parity[i] = (_nvertices[i] & 1) == (_reflect[i] & 1);
            }    
            w2 = abs(_lastne[i])/(abs(_lastne[i])+abs(_nextne[i]));
            w1 = 1 - w2;
            nx = _lastnx[i]*w1+_nextnx[i]*w2;
            ny = _lastny[i]*w1+_nextny[i]*w2;
            nz = _lastnz[i]*w1+_nextnz[i]*w2;
            n = 1/sqrt(sqr(nx)+sqr(ny)+sqr(nz));
            d3d_model_vertex_normal_texture_color (i,_lastx[i]*w1+_nextx[i]*w2,
                           _lasty[i]*w1+_nexty[i]*w2,_lastz[i]*w1+_nextz[i]*w2,
                           nx*n,ny*n,nz*n,
                           _lastu[i]*w1+_nextu[i]*w2,_lastv[i]*w1+_nextv[i]*w2,
                           merge_color(_lastc[i],_nextc[i],w2),
                           _lasta[i]*w1+_nexta[i]*w2);
            if (_parity[i] == 0) {
                d3d_model_vertex_normal_texture_color (i,_lastx[i]*w1+_nextx[i]*w2,
                               _lasty[i]*w1+_nexty[i]*w2,_lastz[i]*w1+_nextz[i]*w2,
                               nx*n,ny*n,nz*n,
                               _lastu[i]*w1+_nextu[i]*w2,_lastv[i]*w1+_nextv[i]*w2,
                               merge_color(_lastc[i],_nextc[i],w2),
                               _lasta[i]*w1+_nexta[i]*w2);
            }
            _parity[i] = 0;                                
        } 
        if (_parity[i] == 0 and _thisne[i] >= 0) {
        d3d_model_vertex_normal_texture_color (i,_thisx[i],_thisy[i],
                          _thisz[i],_thisnx[i],_thisny[i],_thisnz[i],
                          _thisu[i],_thisv[i],_thisc[i],_thisa[i]);
        } else if (_nextne[i] >= 0 and _thisne[i] < 0) {
            w2 = _thisne[i]/(_thisne[i]-_nextne[i]);
            w1 = 1 - w2;
            nx = _thisnx[i]*w1+_nextnx[i]*w2;
            ny = _thisny[i]*w1+_nextny[i]*w2;
            nz = _thisnz[i]*w1+_nextnz[i]*w2;
            n = 1/sqrt(sqr(nx)+sqr(ny)+sqr(nz));
            d3d_model_vertex_normal_texture_color (i,_thisx[i]*w1+_nextx[i]*w2,
                           _thisy[i]*w1+_nexty[i]*w2,_thisz[i]*w1+_nextz[i]*w2,
                           nx*n,ny*n,nz*n,
                           _thisu[i]*w1+_nextu[i]*w2,_thisv[i]*w1+_nextv[i]*w2,
                           merge_color(_thisc[i],_nextc[i],w2),
                           _thisa[i]*w1+_nexta[i]*w2);
            if (_parity[i]) {
                d3d_model_vertex_normal_texture_color (i,_thisx[i]*w1+_nextx[i]*w2,
                                _thisy[i]*w1+_nexty[i]*w2,_thisz[i]*w1+_nextz[i]*w2,
                                nx*n,ny*n,nz*n,
                                _thisu[i]*w1+_nextu[i]*w2,_thisv[i]*w1+_nextv[i]*w2,
                                merge_color(_thisc[i],_nextc[i],w2),
                                _thisa[i]*w1+_nexta[i]*w2);
            }                    
            _parity[i] = 0;
        } else {
            _parity[i] = not _parity[i];
        }
    }                     
    _nvertices[i] += 1;
}
Expand/*
**  Usage:
**      d3d_model_primitive_reflection_end (ind)
**
**  Arguments:
**      ind:            index of model
**
**  Returns:
**      nothing
**
**  Notes:
**      See d3d_model_primitive_reflection_begin ().
**
**  brac37
*/
{
    var i;
    i = argument0;
    if (_nvertices[i] > 2) {
        if (_nextne[i] >= 0) {
        d3d_model_vertex_normal_texture_color (i,_nextx[i],_nexty[i],
                                _nextz[i],_nextnx[i],_nextny[i],_nextnz[i],
                                _nextu[i],_nextv[i],_nextc[i],_nexta[i]);
        } else if (_thisne[i] >= 0) {
            var w1, w2, n, nx, ny, nz;  
            w2 = _nextne[i]/(_nextne[i]-_thisne[i]);
            w1 = 1 - w2;
            nx = _nextnx[i]*w1+_thisnx[i]*w2;
            ny = _nextny[i]*w1+_thisny[i]*w2;
            nz = _nextnz[i]*w1+_thisnz[i]*w2;
            n = 1/sqrt(sqr(nx)+sqr(ny)+sqr(nz));
            d3d_model_vertex_normal_texture_color (i,_nextx[i]*w1+_thisx[i]*w2,
                           _nexty[i]*w1+_thisy[i]*w2,_nextz[i]*w1+_thisz[i]*w2,
                           nx*n,ny*n,nz*n,
                           _nextu[i]*w1+_thisu[i]*w2,_nextv[i]*w1+_thisv[i]*w2,
                           merge_color(_nextc[i],_thisc[i],w2),
                           _nexta[i]*w1+_thisa[i]*w2);
        }        
    }
    d3d_model_primitive_end (i);
}

Offline

#2 2010-04-15 14:47:16

xot
Administrator
Registered: 2007-08-18
Posts: 1,240

Re: Reflection of trianglestrips.

These are a really great idea. Looks like one of the scripts is listed twice, unless I'm missing something.

The demo on GMC is very cool. I especially like how you were able to animate the water. I gather it is exploiting some kind of glitch but I don't really get what's going on. Is that an effected created through z-fighting?


Abusing forum power since 1986.

Offline

#3 2010-07-02 14:34:46

brac37
Member
Registered: 2010-02-12
Posts: 18

Re: Reflection of trianglestrips.

xot wrote:

These are a really great idea. Looks like one of the scripts is listed twice, unless I'm missing something.

Yeah, you missed there are two versions: one with normals and one without.

xot wrote:

The demo on GMC is very cool. I especially like how you were able to animate the water. I gather it is exploiting some kind of glitch but I don't really get what's going on. Is that an effected created through z-fighting?

The water animation is not mine, but by rivosaar. He uses a sprite that is half transparent and animated in a "continuous" manner. Next, he draws the sprite with tiny alpha to set the z-buffer where the sprite is opaque. With that, he combines two drawings of the mirrored sky.

Offline

#4 2010-07-02 16:02:20

xot
Administrator
Registered: 2007-08-18
Posts: 1,240

Re: Reflection of trianglestrips.

Yeah, you missed there are two versions: one with normals and one without.

Whoops. It's obvious when you know.

he draws the sprite with tiny alpha to set the z-buffer

Ah, I get it. That's way better and very flexible. You could get an even nicer effect with a more smoothly animated mask or possibly a series of masks and more than two reflection images.


Abusing forum power since 1986.

Offline

Board footer

Powered by FluxBB