| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550 |
- Namespace mojo.graphics
- Using std.resource
- #rem monkeydoc The Image class.
- An image is a rectangular array of pixels that can be drawn to a canvas using one of the [[Canvas.DrawImage]] methods.
- Images are similar to pixmap's, except that they are optimized for rendering, and typically live in GPU memory.
- To load an image from a file, use one of the [[Load]], [[LoadBump]] or [[LoadLight]] functions.
- To create an image from an existing pixmap, use the New( pixmap,... ) constructor.
- To create an image that is a 'window' into an existing image, use the New( image,rect... ) constructor. This allows you to use images as 'atlases',
- To create an 'empty' image, use the New( width,height ) constructor. You can then render to this image by creating a canvas with this image as its render target.
- Images also have several properties that affect how they are rendered, including:
- * Handle - the relative position of the image's centre (or 'pivot point') for rendering, where (0.0,0.0) means the top-left of the image while (1.0,1.0) means the bottom-right.
- * Scale - a fixed scale factor for the image.
- * BlendMode - controls how the image is blended with the contents of the canvas. If this is null, this property is ignored and the current canvas blendmode is used to render the image instead.
- * Color - when rendering an image to a canvas, this property is multiplied by the current canvas color and the result is multiplied by actual image pixel colors to achieve the final color to be rendered.
- * TextureFilter - controls how image texels are sampled. Set to TextureFilter.None for coolio retro style graphics, or TextureFilter.Mipmap for fullon super smoothing.
- #end
- Class Image Extends Resource
- #rem monkeydoc Creates a new Image.
-
- New( pixmap,... ) Creates an image from an existing pixmap.
-
- New( width,height,... ) Creates an image that can be rendered to using a canvas.
-
- New( image,... ) Creates an image from within an 'atlas' image.
-
- Note: `textureFlags` should be null for static images or TextureFlags.Dynamic for dynamic images.
- @param pixmap Source image.
-
- @param textureFlags Image texture flags.
-
- @param shader Image shader.
-
- @param image Source pixmap.
-
- @param rect Source rect.
-
- @param x,y,width,height Source rect
-
- @param width,height Image size.
-
- #end
- Method New( pixmap:Pixmap,textureFlags:TextureFlags=Null,shader:Shader=Null )
-
- Local texture:=New Texture( pixmap,textureFlags )
-
- Init( texture,texture.Rect,shader )
-
- AddDependancy( texture )
- End
- Method New( width:Int,height:Int,textureFlags:TextureFlags=Null,shader:Shader=Null )
-
- Local texture:=New Texture( width,height,PixelFormat.RGBA32,textureFlags )
-
- Init( texture,texture.Rect,shader )
-
- AddDependancy( texture )
- End
- Method New( image:Image )
-
- Init( image._textures[0],image._rect,image._shader )
-
- image.AddDependancy( Self )
-
- For Local i:=1 Until 4
- SetTexture( i,image.GetTexture( i ) )
- Next
-
- BlendMode=image.BlendMode
- TextureFilter=image.TextureFilter
- LightDepth=image.LightDepth
- Handle=image.Handle
- Scale=image.Scale
- Color=image.Color
- End
-
- Method New( image:Image,rect:Recti )
-
- Init( image._textures[0],rect+image._rect.Origin,image._shader )
-
- image.AddDependancy( Self )
-
- For Local i:=1 Until 4
- SetTexture( i,image.GetTexture( i ) )
- Next
-
- BlendMode=image.BlendMode
- TextureFilter=image.TextureFilter
- LightDepth=image.LightDepth
- Handle=image.Handle
- Scale=image.Scale
- Color=image.Color
- End
-
- Method New( image:Image,x:Int,y:Int,width:Int,height:Int )
-
- Self.New( image,New Recti( x,y,x+width,y+height ) )
- End
-
- #rem monkeydoc @hidden
- #end
- Method New( texture:Texture,shader:Shader=Null )
- Init( texture,texture.Rect,shader )
- End
-
- #rem monkeydoc @hidden
- #end
- Method New( texture:Texture,rect:Recti,shader:Shader=Null )
- Init( texture,rect,shader )
- End
-
- #rem monkeydoc The image's primary texture.
- #end
- Property Texture:Texture()
-
- Return _textures[0]
-
- Setter( texture:Texture )
-
- SetTexture( 0,texture )
- End
- #rem monkeydoc The image's texture rect.
-
- Describes the rect the image occupies within its primary texture.
-
- #end
- Property Rect:Recti()
-
- Return _rect
- End
-
- #rem monkeydoc The image handle.
-
- Image handle values are fractional, where 0,0 is the top-left of the image and 1,1 is the bottom-right.
- #end
- Property Handle:Vec2f()
-
- Return _handle
-
- Setter( handle:Vec2f )
-
- _handle=handle
-
- UpdateVertices()
- End
- #rem monkeydoc The image scale.
-
- The scale property provides a simple way to 'pre-scale' an image.
-
- For images with a constant scale, Scaling an image this way is faster than using one of the 'scale' parameters of [[Canvas.DrawImage]].
-
- #end
- Property Scale:Vec2f()
-
- Return _scale
-
- Setter( scale:Vec2f )
-
- _scale=scale
-
- UpdateVertices()
- End
- #rem monkeydoc The image blend mode.
-
- The blend mode used to draw the image.
-
- If set to BlendMode.None, the canvas blend mode is used instead.
-
- Defaults to BlendMode.None.
-
- #end
- Property BlendMode:BlendMode()
-
- Return _blendMode
-
- Setter( blendMode:BlendMode )
-
- _blendMode=blendMode
- End
-
- #rem monkeydoc The image texture filter.
-
- The texture flags used to draw the image.
-
- If set to TextureFilter.None, the canvas texture filter is used instead.
-
- Defaults to TextureFilter.None
-
- #end
- Property TextureFilter:TextureFilter()
-
- Return _textureFilter
-
- Setter( filter:TextureFilter )
-
- _textureFilter=filter
- End
-
- #rem monkeydoc The image color.
-
- The color used to draw the image.
-
- Image color is multiplied by canvas color to achieve the final rendering color.
-
- Defaults to white.
-
- #end
- Property Color:Color()
-
- Return _color
-
- Setter( color:Color )
-
- _color=color
-
- _material.SetVector( "mx2_ImageColor",_color )
- End
- #rem monkeydoc The image light depth.
- #end
- Property LightDepth:Float()
-
- Return _lightDepth
-
- Setter( depth:Float )
-
- _lightDepth=depth
-
- _material.SetScalar( "mx2_LightDepth",_lightDepth )
- End
- #rem monkeydoc Shadow caster attached to image.
- #end
- Property ShadowCaster:ShadowCaster()
-
- Return _shadowCaster
-
- Setter( shadowCaster:ShadowCaster )
-
- _shadowCaster=shadowCaster
- End
- #rem monkeydoc The image bounds.
-
- The bounds rect represents the actual image vertices used when the image is drawn.
-
- Image bounds are affected by [[Scale]] and [[Handle]], and can be used for simple collision detection.
-
- #end
- Property Bounds:Rectf()
-
- Return _bounds
- End
- #rem monkeydoc Image bounds width.
- #end
- Property Width:Float()
-
- Return _bounds.Width
- End
-
- #rem monkeydoc Image bounds height.
- #end
- Property Height:Float()
-
- Return _bounds.Height
- End
- #rem monkeydoc Image bounds radius.
- #end
- Property Radius:Float()
-
- Return _radius
- End
- #rem monkeydoc Image shader.
- #end
- Property Shader:Shader()
-
- Return _shader
- End
-
- #rem monkeydoc Image material.
- #end
- Property Material:UniformBlock()
-
- Return _material
- End
- #rem monkeydoc @hidden Image vertices.
- #end
- Property Vertices:Rectf()
-
- Return _vertices
- End
-
- #rem monkeydoc @hidden Image texture coorinates.
- #end
- Property TexCoords:Rectf()
-
- Return _texCoords
- End
- #rem monkeydoc @hidden Sets an image texture.
- #end
- Method SetTexture( index:Int,texture:Texture )
-
- _textures[index]=texture
-
- _material.SetTexture( "mx2_ImageTexture"+index,texture )
- End
-
- #rem monkeydoc @hidden gets an image texture.
- #end
- Method GetTexture:Texture( index:Int )
-
- Return _textures[index]
- End
-
- #rem monkeydoc Loads an image from file.
- #end
- Function Load:Image( path:String,shader:Shader=Null )
-
- Local pixmap:=Pixmap.Load( path,Null,True )
- If Not pixmap Return Null
- If Not shader shader=mojo.graphics.Shader.GetShader( "sprite" )
-
- Local image:=New Image( pixmap,Null,shader )
-
- image.OnDiscarded+=Lambda()
- pixmap.Discard()
- End
-
- Return image
- End
-
- #rem monkeydoc Loads a bump image from file(s).
-
- `diffuse`, `normal` and `specular` are filepaths of the diffuse, normal and specular image files respectively.
-
- `specular` can be null, in which case `specularScale` is used for the specular component. Otherwise, `specularScale` is used to modulate the red component of the specular texture.
-
- #end
- Function LoadBump:Image( diffuse:String,normal:String,specular:String,specularScale:Float=1,flipNormalY:Bool=True,shader:Shader=Null )
-
- Local texture1:=graphics.Texture.LoadNormal( normal,Null,specular,specularScale,flipNormalY )
- If Not texture1 Return Null
-
- Local texture0:=graphics.Texture.Load( diffuse,Null )
-
- If Not texture0
- Local pdiff:=New Pixmap( texture1.Width,texture1.Height,PixelFormat.I8 )
- pdiff.Clear( std.graphics.Color.White )
- texture0=New graphics.Texture( pdiff,Null )
- Endif
-
- If Not shader shader=graphics.Shader.GetShader( "bump" )
-
- Local image:=New Image( texture0,texture0.Rect,shader )
- image.SetTexture( 1,texture1 )
-
- image.OnDiscarded+=Lambda()
- If texture0 texture0.Discard()
- If texture1 texture1.Discard()
- End
-
- Return image
- End
- #rem monkeydoc Loads a light image from file.
- #end
- Function LoadLight:Image( path:String,shader:Shader=Null )
-
- Local pixmap:=Pixmap.Load( path )
- If Not pixmap Return Null
-
- If Not shader shader=mojo.graphics.Shader.GetShader( "light" )
-
- Select pixmap.Format
- Case PixelFormat.IA16,PixelFormat.RGBA32
-
- pixmap.PremultiplyAlpha()
-
- Case PixelFormat.A8
- Local tpixmap:=pixmap
- pixmap=pixmap.Convert( PixelFormat.IA16 )
- tpixmap.Discard()
- 'Copy A->I
- For Local y:=0 Until pixmap.Height
- Local p:=pixmap.PixelPtr( 0,y )
- For Local x:=0 Until pixmap.Width
- p[0]=p[1]
- p+=2
- Next
- Next
- Case PixelFormat.I8
-
- Local tpixmap:=pixmap
- pixmap=pixmap.Convert( PixelFormat.IA16 )
- tpixmap.Discard()
-
- 'Copy I->A
- For Local y:=0 Until pixmap.Height
- Local p:=pixmap.PixelPtr( 0,y )
- For Local x:=0 Until pixmap.Width
- p[1]=p[0]
- p+=2
- Next
- Next
- Case PixelFormat.RGB24
-
- Local tpixmap:=pixmap
- pixmap=pixmap.Convert( PixelFormat.RGBA32 )
- tpixmap.Discard()
-
- 'Copy Max(R,G,B)->A
- For Local y:=0 Until pixmap.Height
- Local p:=pixmap.PixelPtr( 0,y )
- For Local x:=0 Until pixmap.Width
- p[3]=Max( Max( p[0],p[1] ),p[2] )
- p+=4
- Next
- Next
-
- End
-
- Local texture:=New Texture( pixmap,Null )
-
- Local image:=New Image( texture,shader )
-
- image.OnDiscarded+=Lambda()
- pixmap.Discard()
- End
-
- Return image
- End
- Private
-
- Field _shader:Shader
- Field _material:UniformBlock
- Field _textures:=New Texture[4]
- Field _blendMode:BlendMode
- Field _textureFilter:TextureFilter
- Field _color:Color
- Field _lightDepth:Float
- Field _shadowCaster:ShadowCaster
-
- Field _rect:Recti
- Field _handle:Vec2f
- Field _scale:Vec2f
-
- Field _vertices:Rectf
- Field _texCoords:Rectf
- Field _bounds:Rectf
- Field _radius:Float
-
- Method Init( texture:Texture,rect:Recti,shader:Shader )
-
- If Not shader shader=Shader.GetShader( "sprite" )
-
- _rect=rect
- _shader=shader
- _material=New UniformBlock
-
- AddDependancy( _material )
-
- SetTexture( 0,texture )
-
- BlendMode=BlendMode.None
- TextureFilter=TextureFilter.None
- Color=Color.White
- LightDepth=100
- Handle=New Vec2f( 0 )
- Scale=New Vec2f( 1 )
-
- UpdateVertices()
- UpdateTexCoords()
- End
-
- Method UpdateVertices()
- _vertices.min.x=Float(_rect.Width)*(0-_handle.x)*_scale.x
- _vertices.min.y=Float(_rect.Height)*(0-_handle.y)*_scale.y
- _vertices.max.x=Float(_rect.Width)*(1-_handle.x)*_scale.x
- _vertices.max.y=Float(_rect.Height)*(1-_handle.y)*_scale.y
- _bounds.min.x=Min( _vertices.min.x,_vertices.max.x )
- _bounds.max.x=Max( _vertices.min.x,_vertices.max.x )
- _bounds.min.y=Min( _vertices.min.y,_vertices.max.y )
- _bounds.max.y=Max( _vertices.min.y,_vertices.max.y )
- _radius=_bounds.min.x*_bounds.min.x+_bounds.min.y*_bounds.min.y
- _radius=Max( _radius,_bounds.max.x*_bounds.max.x+_bounds.min.y*_bounds.min.y )
- _radius=Max( _radius,_bounds.max.x*_bounds.max.x+_bounds.max.y*_bounds.max.y )
- _radius=Max( _radius,_bounds.min.x*_bounds.min.x+_bounds.max.y*_bounds.max.y )
- _radius=Sqrt( _radius )
- End
-
- Method UpdateTexCoords()
- _texCoords.min.x=Float(_rect.min.x)/_textures[0].Width
- _texCoords.min.y=Float(_rect.min.y)/_textures[0].Height
- _texCoords.max.x=Float(_rect.max.x)/_textures[0].Width
- _texCoords.max.y=Float(_rect.max.y)/_textures[0].Height
- End
-
- End
- Class ResourceManager Extension
- Method OpenImage:Image( path:String,shader:Shader=Null )
- Local slug:="Image:name="+StripDir( StripExt( path ) )+"&shader="+(shader ? shader.Name Else "null")
-
- Local image:=Cast<Image>( OpenResource( slug ) )
- If image Return image
- Local texture:=OpenTexture( path,Null )
- If texture image=New Image( texture,shader )
-
- AddResource( slug,image )
- Return image
- End
- End
|