public CharacterShader( Texture2D texture ) { ShaderBuilder vert = new ShaderBuilder( ShaderType.VertexShader, true ); vert.AddUniform( ShaderVarType.Int, "blink_phase" ); vert.AddAttribute( ShaderVarType.Vec2, "in_position" ); vert.AddAttribute( ShaderVarType.Vec2, "in_value" ); vert.AddVarying( ShaderVarType.Vec2, "var_texture" ); vert.AddVarying( ShaderVarType.Vec3, "var_fore_colour" ); vert.AddVarying( ShaderVarType.Vec3, "var_back_colour" ); vert.Logic = @" void main( void ) { gl_Position = in_position; int ch = int( in_value.x ) & 0x7f; int corner = int( in_value.y ); var_texture = vec2( ( ( ch % 16 ) + ( corner % 2 ) ) * 4.0, ( ( ch / 16 ) + ( corner / 2 ) ) * 8.0 ) / 64.0; int fore = ( int( in_value ) >> 12 ) & 0xf; int back = ( int( in_value ) >> 8 ) & 0xf; var_back_colour = vec3( ( back >> 2 ) & 1, ( back >> 1 ) & 1, back & 1 ) * 2.0 / 3.0; if( ( back & 0x8 ) != 0 ) var_back_colour += vec3( 1.0, 1.0, 1.0 ) / 3.0; if( blink_phase == 1 || ( int( in_value.x ) & 0x80 ) == 0 ) { var_fore_colour = vec3( ( fore >> 2 ) & 1, ( fore >> 1 ) & 1, fore & 1 ) * 2.0 / 3.0; if( ( fore & 0x8 ) != 0 ) var_fore_colour += vec3( 1.0, 1.0, 1.0 ) / 3.0; } else var_fore_colour = var_back_colour; } "; ShaderBuilder frag = new ShaderBuilder( ShaderType.FragmentShader, true ); frag.AddUniform( ShaderVarType.Sampler2D, "texture0" ); frag.AddVarying( ShaderVarType.Vec2, "var_texture" ); frag.AddVarying( ShaderVarType.Vec3, "var_fore_colour" ); frag.AddVarying( ShaderVarType.Vec3, "var_back_colour" ); frag.Logic = @" void main( void ) { if( texture2D( texture0, var_texture ).r > 0.5 ) out_frag_colour = vec4( var_fore_colour.rgb, 1.0 ); else out_frag_colour = vec4( var_back_colour.rgb, 1.0 ); } "; VertexSource = vert.Generate( GL3 ); FragmentSource = frag.Generate( GL3 ); myTexture = texture; BeginMode = BeginMode.Quads; }
protected override void OnLoad( EventArgs e ) { String exePath = Path.GetDirectoryName( Assembly.GetExecutingAssembly().GetName().CodeBase ); if ( exePath.StartsWith( "file:\\" ) ) exePath = exePath.Substring( 6 ); myCharacterSet = new Texture2D( new Bitmap( exePath + Path.DirectorySeparatorChar + "charset.png" ) ); myDefaultCharSet = new ushort[ 256 ]; for ( int i = 0; i < 127; ++i ) { for ( int w = 0; w < 2; ++w ) { ushort word = 0x0000; for ( int j = 0; j < 16; ++j ) { int x = ( ( i & 0xf ) << 2 ) + ( w << 1 ) + ( j >> 3 ); int y = ( ( i >> 4 ) << 3 ) + ( j & 7 ); if ( myCharacterSet.GetPixel( x, y ).R >= 128 ) word |= (ushort) ( 1 << ( 15 - j ) ); } myDefaultCharSet[ ( i << 1 ) + w ] = word; } } myCharShader = new CharacterShader( myCharacterSet, Width, Height ); myCharMap = new Character[ VideoBufferLength ]; for ( int i = 0; i < VideoBufferLength; ++i ) { myCharMap[ i ] = new Character( Scale ); myCharMap[ i ].Position = new Vector2( ( i % Columns + 2 ) * 4 * Scale, ( i / Columns + 1 ) * 8 * Scale ); myCharMap[ i ].Value = 0x0000; } CPU.MemoryChanged += delegate( object sender, MemoryChangedEventArgs me ) { if ( myDumping ) return; if ( VideoBufferLoc != 0 && me.Location >= VideoBufferLoc && me.Location < VideoBufferLoc + VideoBufferLength ) { int index = me.Location - VideoBufferLoc; myCharMap[ index ].Value = me.Value; } else if ( CharacterSetLoc != 0 && me.Location >= CharacterSetLoc && me.Location < CharacterSetLoc + 256 ) { int index = me.Location - CharacterSetLoc; int x = ( index % 32 ) * 2; int y = ( index / 32 ) * 8; ushort val = me.Value; for ( int i = 0; i < 16; ++i ) { if ( ( ( val >> i ) & 1 ) == 1 ) myCharacterSet.SetPixel( x + 1 - i / 8, y + i % 8, Color.White ); else myCharacterSet.SetPixel( x + 1 - i / 8, y + i % 8, Color.Black ); } } }; Ready = true; }
public CharacterShader( Texture2D texture, int width, int height ) : this(texture) { Create(); SetScreenSize( width, height ); }
static Texture2D() { Bitmap blankBmp = new Bitmap( 1, 1 ); blankBmp.SetPixel( 0, 0, Color.White ); Blank = new Texture2D( blankBmp ); }