rj-action-library/Runtime/Procedural/Textures/TextureCombiner/TextureCombinerBuffer.cs

164 lines
3.8 KiB
C#

using System.Collections;
using System.Collections.Generic;
using Godot;
using System;
namespace Rokojori
{
public class TextureCombinerBuffer
{
int _width;
public int width => _width;
int _height;
public int height => _height;
Color[] _pixels;
public static TextureCombinerBuffer Create( int w, int h )
{
var tb = new TextureCombinerBuffer();
tb._height = h;
tb._width = w;
tb._pixels = new Color[ w * h ];
return tb;
}
public static TextureCombinerBuffer From( Texture2D texture )
{
var buffer = Create( texture.GetWidth(), texture.GetHeight() );
buffer.CopyFrom( texture.GetImage(), 0, 0, 0, 0, texture.GetWidth(), texture.GetHeight() );
return buffer;
}
public TextureCombinerBuffer Resize( int w, int h )
{
var buffer = Create( w, h );
for ( int i = 0; i < w; i++ )
{
for ( int j = 0; j < h; j++ )
{
var uv = new Vector2( i / (float) w, j / (float) h );
var pixel = SampleBilinearUV( uv );
buffer.SetAt( i, j, pixel );
}
}
return buffer;
}
public void CopyFrom( Image image, int sourceX, int sourceY, int ownX, int ownY, int w, int h )
{
for ( int i = 0; i < w; i++ )
{
for ( int j = 0; j < h; j++ )
{
var sourcePixel = image.GetPixel( sourceX + i, sourceY + j );
SetAt( ownX + i, ownY + j, sourcePixel );
}
}
}
public void CopyTo( int ownX, int ownY, int targetX, int targetY, int w, int h, TextureCombinerBuffer output )
{
for ( int i = 0; i < w; i++ )
{
for ( int j = 0; j < h; j++ )
{
var ownPixel = GetAt( ownX + i, ownY + j );
output.SetAt( targetX + i, targetY + j, ownPixel );
}
}
}
public void CopyTo( int ownX, int ownY, int targetX, int targetY, int w, int h, Image image )
{
for ( int i = 0; i < w; i++ )
{
for ( int j = 0; j < h; j++ )
{
var ownPixel = GetAt( ownX + i, ownY + j );
image.SetPixel( targetX + i, targetY + j, ownPixel );
}
}
}
public int ComputeIndexFromPosition( int x, int y )
{
return x + y * _width;
}
public void SetAt( int x, int y, Color value )
{
SetIndexed( ComputeIndexFromPosition( x, y ), value );
}
public void SetIndexed( int index, Color value )
{
_pixels[ index ] = value;
}
public Color GetAt( int x, int y )
{
return GetIndexed( ComputeIndexFromPosition( x, y ) );
}
public Color GetIndexed( int index )
{
return _pixels[ index ];
}
public Color SampleNearestUV( Vector2 uv )
{
return SampleNearestImage( uv.X * width, uv.Y * height );
}
public Color SampleNearestImage( float imageDimensionsX, float imageDimensionsY )
{
return GetAt( Mathf.RoundToInt( imageDimensionsX ), Mathf.RoundToInt( imageDimensionsY ) );
}
public Color SampleBilinearUV( Vector2 uv )
{
return SampleBilinearImage( uv.X * width, uv.Y * height );
}
public Color SampleBilinearImage( float imageDimensionsX, float imageDimensionsY )
{
var lowX = Mathf.FloorToInt( imageDimensionsX );
var highX = Mathf.Min( lowX + 1, width - 1 );
var lerpX = imageDimensionsX - lowX;
var lowY = Mathf.FloorToInt( imageDimensionsY );
var highY = Mathf.Min( lowY + 1, height - 1 );
var lerpY = imageDimensionsY - lowY;
var ll = GetAt( lowX, lowY );
var hl = GetAt( highX, lowY );
var lh = GetAt( lowX, highY );
var hh = GetAt( highX, highY );
var upper = ll.Lerp( hl, lerpX );
var lower = lh.Lerp( hh, lerpX );
return upper.Lerp( lower, lerpY );
}
}
}