MJW

Texture Merger

97 posts in this topic

This plugin is meant to work in conjunction with my other Height-Map plugins. It's in the "Effects>Height Map" menu.

 

Here is Version 1.1 of the plugin: TextureMerger.zip

 

The effect works similarly to Texture Shader, except instead of an image in the clipboard, the clipboard contains another height map. The height map in the canvas is combined with the height map in the clipboard in various ways. The default method, and the one it was originally written to do, is to add them.

 

If plugins are rated by the number of controls, this is possibly the best plugin ever. The large number is necessary because there are so many things that need to be controlled: the window height scaling and offset, the clipboard orientation, scaling and offset, and the adjustments to the merged height. There are also controls for shading. Shading does not effect the merged height map, but it's necessary to judge the results. Because there's currently no way to automatically disable the shading before exiting, it must be disabled manually. (unless the shaded image is what is wanted). Fortunately, unlike the Texture Smoother, a mistake can easily be corrected with an Undo, followed by rerunning the Texture Merger.

 

Here is the user interface (hide the eyes of sensitive children):

 

TextureMergerUI_zpsqxzzmzzt.png

 

According to the Help Menu:

----------

Texture Merger combines two height maps, one in the canvas and the other in the clipboard. Each height map consists of an 8-bit alpha channel and a 24-bit depth, formed by combining the RGB channels into a single 24-bit unsigned integer.


The controls are:
Clipboard Image: Specifies how pixels outside the clipboard boundaries are treated. Pixels outside the image range of the clipboard can be transparent, Clamped, Tiled, Alternately Tiled, or Brick Tiled. When Alternately Tiled is selected, the tile orientation is reversed for every other tile, so that the tiles match at the edges. The edge pixels are not repeated. When Brick Tiled is selected, every other row is offset by half the image width. The rows do not wrap from the top to the bottom.

Clipboard Image Size: Increases or decreases the size of the clipboard image.

Clipboard Image XY Proportion: Changes the XY proportion of the clipboard. Moving the control right increases the X size while decreasing the Y size. Moving the control left decreases the X size while increasing the Y size.
Clipboard Image Offset: Moves the clipboard image relative to the canvas image.
Clipboard Image Rotation: Specifies a counterclockwise rotation angle for the clipboard image, in degrees.
Clipboard Image Mapping Method: Selects the method used to displace the clipboard image based on the canvas heights. (A number of methods are allowed which have no obvious physical meaning when merging height maps.) The choices are:

  • No Displacement: Does not displace the clipboard image.

  • Surface Offset 1: Uses the height and gradient of the canvas height map to attempt to map the clipboard image onto the canvas height map as if it were painted onto the surface.

  • Surface Offset 2: An alternate method of mapping the clipboard image as if painted onto the surface.

  • Gradient: The simplest mapping method. Displaces the clipboard image in the direction of the gradient, in proportion to the gradient magnitude.

  • Gradient-Z: Displaces the clipboard image in the direction of the gradient, in proportion to the product of the canvas height and the gradient magnitude.

  • Refraction: Displaces the clipboard image as if it were refracted by the canvas height map, in accordance with Snell's Law. The Displacement Scale is proportional to the Index of Refraction

  • Reflection: Displaces the clipboard image as if it were reflected by the canvas height map surface. The Displacement Scale is proportional to the distance from the canvas height map to the reflected plane. Because the angle of reflection equals the angle of incidence, points with gradients of more than 45° will not reflect the image and will be rendered as transparent.

  • Reflection (Ignore Height): Displaces the clipboard image as if it were reflected by the canvas height map surface, but uses only the gradient, ignoring the effect caused by the canvas height.

  • Reflection (with Re-reflection): Applies reflection, but approximates the re-reflection of downward reflection vectors.

  • Faux Reflection: Approximates reflection for gradients of less than 45°, but produces non-transparent pixels for gradients greater that 45°.

  • Faux Reflection (Ignore Height): Applies Faux Reflection, ignoring the effect caused by the canvas height height.

Divide Mapping Displacement by Ten: Specifies that the Mapping Displacement should be divided by 10 to decrease the control's range.

Mapping Displacement: Controls the amount the clipboard heights are displaced. The effect depends on the Mapping Method. For most methods, it acts as a general scaling factor, but for Refraction and Reflection it has a specific physical meaning. For some mapping methods, such as reflection, setting this value to 0 does not result in no displacement.

Divide Merged Height Scale by Ten: Specifies that the Merged Height should be divided by 10 to decrease the control's range.

Merged Height Scale: Increases or decreases the height of the merged height map. The scaling affects the amount of displacement and the effective height for shading. Only the change in displacement changes the values in the merged height map.
Merged Height Curvature: Increases or decreases the curvature of the merged height map.

Merged Height Alpha Source: Selects the source of the alpha values for the Merged height map. The choices are:

  • All Opaque: Make all heights opaque.

  • Canvas Alpha: Use the alphas from the canvas.

  • Clipboard Alpha: Use the alphas from the displaced clipboard.

  • Composite Alpha: Use the composite alpha. This is the sum of the canvas and clipboard alpha minus the product. If either height is opaque, the merged height will be opaque.

Height Merge Method: Selects the method used to combine clipboard heights with the canvas heights. The choices are:

  • Add: Add the clipboard height to the canvas height.

  • Subtract: Subtract the clipboard height from the canvas height.

  • Multiply: Multiply the clipboard height by the canvas height.

  • Maximum: Use the maximum of the clipboard height and the canvas height.

  • Minimum: Use the minimum of the clipboard height and the canvas height.

  • Clipboard: Use the clipboard height as displaced by the Mapping Method.

  • Canvas: Use the canvas height and alpha, as modified by the canvas controls and the merged-height controls.

  • Clipboard (No Displacement): Use the non-displaced clipboard height and alpha, as modified by the clipboard controls and the merged-height controls.

Make Unmodified Canvas Heights Transparent: Specifies that if the merged height is the same as the canvas height, the merged height should be made transparent. This allows heights modified by the clipboard to be shaded separately from unmodified heights.

Canvas Height Scale: Increases or decreases the canvas heights.

Canvas Height Offset: Specifies the offset added to the scaled canvas heights.

Canvas Height Curvature: Specifies the non-linear adjustment to the canvas heights, which increases or decreases the mid-range values while leaving the end-range values unchanged. This adjustment is applied before the scale and offset.

Weight Clipboard Heights by Opacity: Specifies that the influence of a clipboard height on the merged height is proportional to the clipboard height's opacity. In particular, transparent heights are are ignored, and the canvas heights are used as the merged heights. This control is especially useful when offsetting the clipboard height in when the Height Merge Method is Maximum or Minimum.

Invert Clipboard Height Range: Specifies that white clipboard pixels are 0 height and black clipboard pixels are maximum height.

Scale Clipboard Heights by Clipboard Image Size: Specifies that the clipboard heights should be scaled to be proportional to the clipboard image size.

Divide Clipboard Height Scale by Ten: Specifies that the Clipboard Height Scale should be divided by 10 to decrease the control's range.

Clipboard Height Scale: Increases or decreases the clipboard heights.

Clipboard Height Offset: Specifies the offset added to the scaled clipboard heights.

Clipboard Height Curvature: Specifies the non-linear adjustment to the clipboard heights.

Antialias: Specifies that antialiasing should be used. Antialiasing will slow the effect, because many more points need to be processed. but will often significantly improve the results..
Antialias Quality: Specifies the number of samples in each direction per pixel. The total number of samples per pixel is this value squared.

----------The following controls effect only the shaded image.----------

Show Shading (Disable Before Exiting): Specifies that the shaded height map should be shown instead of the actual merged height map. This must be disabled before exiting the effect in order to save the merged height map.

Ambient Light Color: Sets the color of the ambient light source. Ambient Light affects all pixels equally, no matter their orientation. The default color is black (no ambient lighting).
Directional Light Color: Sets the color of the Directional Light. The default color is white.
Directional Light Direction (Use Outer Ring to Reverse): Sets the direction of the Directional Light. The Directional Light's effect on a pixel is determined by light's direction and the texture's gradient at the pixel. Moving the outer ring to the left side of the control reverses the light direction.
Directional Light Intensity: Increases or decreases the intensity of the Directional Light. The directional light contributes both diffuse and specular (reflected) light.
Specularity: Determines the shininess of the surface. Increasing this value decreases the diffuse lighting and increases the specular lighting.
Specular Concentration (Exponent): Determines the sharpness of the specular highlights. Higher values produce sharper highlights.

----------

 

There are several changes from the Texture Shader, most of which I intend to add to the Texture Shader.

 

Inspired by Red ochre, I added a Brick Tiled Clipboard Image option. I didn't include a Reflected Brick Tiled option, because I wasn't sure how useful it would be. Maybe I'll eventually add it.

 

On several slider controls, such as the Texture Height, I added a divide-by-ten option. These are kind of awkward, but almost necessary to support the wide range of height-map heights made possible, especially using the Texture Smoother. Before the Texture Smoother, large height maps were difficult to produce without very noticeable waterlines, making them mostly useless. Some of the slider controls also use a non-linear range. Moving the slider at the low end of the range produces less change than the same movement at the high end. This allows fiver control at the low values.

 

The Clipboard (No Displacement) Merge Method is useful for modifying a height map in the clipboard with no effect from whatever is in the window.

 

I rather expect there will be a few bugs, since there are so many controls, and the interaction between them is quite complex.

 

I'll follow this comment with a few examples of merged height-map images.

 

EDIT: Version 1.1. I explain the changes in another comment.

 

6

Share this post


Link to post
Share on other sites

ReflectedWeirdShpere_zpsgyagklmo.png

 

The clipboard sphere was elongated and subtracted twice from the window sphere.

 

GridSphere_zpstoffcogm.png

 

A  cloth texture was mapped onto the sphere with Add; a grid was mapped onto another sphere with Subtract, then Minimum was used to combine them. The Make Unmodified Canvas Heights Transparent option was used so they could be shaded separately.

 

RedHeartOnCloth_zpsblg9wzbx.png

 

A heart, produced by blurring and smoothing a heart shape, was combined with a sphere using the Multiply merge method.

 

8

Share this post


Link to post
Share on other sites

Very impressive example images MJW!


I haven't had a chance to try this yet but hope to soon - thanks for the share.
(ps. I think 'Curly lines' just beats it for U.I. space  ;) )

0

Share this post


Link to post
Share on other sites

i can't see the plugin in the height map....after i  insert it to the file effects...

 

 

0

Share this post


Link to post
Share on other sites

I don't know why that would be. I just tried it myself, and it worked. If you haven't already done so, check and make sure the Program Files>paint.net>Effects folder contains a file called TextureMerger.dll.

 

One tiny bit of advice. I never Extract the files in the ZIP file. I just go into the ZIP file as if it were a folder, copy the DLL, and paste it into the Effects folder. Works every time, and seems a lot simpler.

 

0

Share this post


Link to post
Share on other sites

When changing the "Clipboard Image Rotation", the image gets a bit noisy... except when set to right angles (0, 90, -90, 180).

Are you using any Interpolation when the image is rotated?

0

Share this post


Link to post
Share on other sites

Needs more options.

 

 

[/sarcasm]

2

Share this post


Link to post
Share on other sites
42 minutes ago, toe_head2001 said:

When changing the "Clipboard Image Rotation", the image gets a bit noisy... except when set to right angles (0, 90, -90, 180).

Are you using any Interpolation when the image is rotated?

 

To be honest, I haven't noticed that problem. All the pixel fetching is done with linear interpolation between samples. There could, of course, be a problem in how I do it.

 

I assume it's the shaded version you're talking about. The unshaded 24-bit height map will always look rather random, because the way colors are assigned isn't intended to be meaningful without shading. Because there are so many options, I'll need a more exact description of what you're doing.

 

The antialiasing option will improve many cases where there's high-frequency variation in the height maps.

0

Share this post


Link to post
Share on other sites
28 minutes ago, MJW said:

The unshaded 24-bit height map will always look rather random, because the way colors are assigned isn't intended to be meaningful without shading.

Ok, that explains it. You're right, it's not an issue with the shading options applied.

0

Share this post


Link to post
Share on other sites
1 hour ago, BoltBait said:

Needs more options.

 

Just what I was thinking :)

 

Time to move from CodeLab to VS and a custom UI....and a help file.

0

Share this post


Link to post
Share on other sites

This is a VS project, not CodeLab, as my perhaps overuse of disabling inapplicable controls proves. It uses IndirectUI, though. The fact is, in my opinion the look-and-feel of most non-IndirectUI plugins leaves a lot to be desired. Shape3D, for instance, is an example of a UI whose concept is quite good, but whose implementation is . . . well  let's just say it could be improved. I see that too often. For example, controls with no reset button -- I expect PDN UI controls to have reset buttons to restore their default values. I've considered using OptionBasedEffects, but that project seems somewhat in limbo, and I'm not fond of the requirement of a second DLL. For right now, I'll probably stick with IndirectUI, despite its sometimes frustrating limitations. I wish IndirectUI supported tabs.

 

I'm not sure what you mean by " ...and a help file." The Texture Merger has a Help Menu, which I quoted from in my opening comment.

 

 

 

 

 

 

1

Share this post


Link to post
Share on other sites
Quote

I wish IndirectUI supported tabs.

Me too!;)

0

Share this post


Link to post
Share on other sites

Doesn't Midora's OptionBasedLibrary support tabs? I know it supports panels.

 

There was another (incomplete) library somewhere....here:

I don't know if this was ever updated. Might be worth a look.

0

Share this post


Link to post
Share on other sites

@MJW...I'm sorry, I can't figure this plugin out at all. I tried to do something similar to a sphere and it looks nothing like yours.

Can you do a quick step-by-step using your sphere example?  Maybe post the images you used?   I'd appreciate it.  I feel kind of stupid here...=O

0

Share this post


Link to post
Share on other sites

Yes, I'll do that later today. It's definitely  a complex plugin that doesn't really work like much else except Texture Shader. I should have added more explanation in my original comment, but it was already approaching the length of a novelette and I didn't want to make it into a novel.

1

Share this post


Link to post
Share on other sites

Part I.

 

This is a short beginner's tutorial on the Texture Merger.

 

Let me preface it by saying that knowing how to use the Texture Shader is a prerequisite to using the Texture Merger. The Texture Merger uses the same ideas as the Texture Shader, but in a more complex way, and the purpose of the Texture Merger is to produce height maps that can be shaded with the Texture Shader. All the example in my second comment were shaded that way. This tutorial will attempt to show the relationship between what the Texture Shader does and what the Texture Merger does.

 

I also need to point out that there are two types of height maps: what I call textures and (for want of a better word) shapes. Textures are things like a cloth surface and such, where the height is small; shapes are things like spheres that are about as high as they are wide. The Texture Shader was originally intended to deal mostly with textures, but I later found many uses for shapes. (I sort of wish I called it Height-Map Shader instead).

 

Height maps can either be black-and-white images, or colored images where the RGB channels are combined into a single 24-bit depth value. Black-and-white maps are easy to produce and modify, but only work well for textures. Since they only have 256 levels, tall objects have steps, which show up as waterlines when shading.

 

For this example I'll use a texture and a shape.

 

The texture is a slightly blurred white-on-black grid. Blurring is often desirable to eliminate high-frequency variations in height, which often cause aliasing problems.

 

Here is the texture:

photo Grid_zpsx2znythx.png

 

The shape is a 24-bit height map sphere on a transparent background produced with a special plugin:

 

SphereTranspBGRA_zps7ho9pazu.png

 

2

Share this post


Link to post
Share on other sites

Part II.

 

First I'll combine them with the Texture Shader.

 

Run PDN, and copy the sphere into a new image.

Copy the grid into the clipboard.

 

Run Texture Shader (from the Height Map submenu).

 

Change the following controls from their defaults:

Image: Clipboard.

Texture Height Scale: 255

Use Alpha from Texture: Checked

Directional Light Direction: 0, -150, 50

Antialias: Checked

 

(Note: To enter a value into a slider's edit box: highlight the current value; type in the new value; then do a mouse click in any other slider's edit box to cause the new value to be accepted.)

 

[Let me insert a short diversion to explain why the Texture Height is 255. The depth range is considered to be an unsigned number from 0 to 1. The sphere map uses all 24 bits, going from black (0) to white (all bits on). Therefore, the unscaled sphere height is 1. The sphere image has a width of 510, so its radius is 255. Thus, the height of the half-sphere that's visible needs to be scaled by 255 to have the same radius. Often, I just adjust the height by eye, but its useful to understand how the depth range works.]

 

The result should look like this:

TextureShaderGridSphere_zpsskdateqt.png

 

Note that this uses the default Image Mapping Method, Surface Offset 1. This mapping method attempts to make the clipboard image (the grid) look like it was painted onto the image in the window image (the sphere).

 

Now undo the effect (or use a different copy of the sphere).

 

Run Texture Merger.

 

Change the following controls from their defaults:

Clipboard Image Mapping Method: Surface Offset 1 (default is No Displacement)

Merged Height Scale: 255

Height Merge Method: Subtract (default is Add)

Clipboard Height Scale: 0.015

Antialias: Checked

Show Shading: Checked

Directional Light Direction: 0, -150, 50

 

Now the result should be:

TextureMergerGridSphere_zpskcvdyrym.png

 

Instead of "painting" the grid image onto the sphere, it subtracted the grid image, interpreted as a height map. The black areas of the grid are 0, so the corresponding areas of the sphere are  unchanged. The white gridlines are 1. They are scaled by the clipboard height and subtracted from the sphere height, leaving the channels. Because the mapping mode is Surface Offset 1, the grid is displaced, just as it was with the Texture Shader.

 

[Another short diversion. If you use Add instead of Subtract, the lines will show up as ridges. However, at the center of the sphere, the sum of the heights will be too large to fit in the 0-to-1 range, so the height will be clipped. What to do? The answer is that the Canvas Height Scale will need to be reduced, and the Merged Height Scale will need to be increased to compensate. If the Canvas Height Scale is set to 0.5, the Merged Height Scale will need to be twice it's original value of 255, which is 510. The Clipboard Height Scale and Displacement will also need to be adjusted. (I usually only reduce the Canvas Height Scale as much as I need to, to avoid overflows.) These adjustments, while sometimes inconvenient, are usually not too difficult, because most everything is just based on appearance, anyway.]

 

Uncheck Show Shading, and the result will be:

TextureMergerGridSphereMap_zpsmlpmaizc.p

This is the height map that when shaded will produce the sphere with the grid channels. Run the Texture Shader with Image changed to White, and the result will look like the Texture Merger. But with the Texture Shader, more complex mapping methods, such as Reflection, are available.

 

For example (using Tiled clipboard and Reflection (with Re-reflection)):

 

TextureMergerGridSphereReflect_zpszcqjws

 

[If something doesn't seem to be working as expected in the Texture Merger, check to see if some control is set to the wrong value. It happens to me all the time. There are so many controls; it's hard to keep track of them all. I especially forget to change the Clipboard Image Mapping Method and the Height Merge Method from the values I used previously.]

 

4

Share this post


Link to post
Share on other sites

Aaahhhhhh...now we're talking.  One of my questions was 'how do you get 24-bit height mapped on a shape'?

I see you have a special plugin for that.  I will try this later today and see if I can get a result similar to yours.

Thanks, MJW!  :)

0

Share this post


Link to post
Share on other sites

Another way to produce 24-bit height maps is to smooth black-and-white images using the Texture Smoother. Under that topic I show an example with a gold earring. The Texture Smoother is very useful, but isn't perfect. The spheres it can produce aren't as nice as the plugin-produced spheres.

 

The images in my second comment all used the sphere height map I posted with my initial Texture Shader comment. I had to erase the black background by hand. The plugin I just published allows a lot better control.

 

 

0

Share this post


Link to post
Share on other sites

This what I came up with.  In my first image, I followed your directions exactly.

Tulip%20Sphere_grid_zps7tfktrko.png

 

Started improvising on the next three.

butterfly_purple_zpslqbrwqmu.png

 

 butterfly_texture%20merger_zpsssgaapuz.p

 

Azalea%20Butterfly_grid_zps3vol5s9y.png

 

I have a much better understanding of all your height map plugins now.  Thanks.  :)

5

Share this post


Link to post
Share on other sites

Wow!  This is a very powerful plugin @MJW.  It certainly 'taxed' my little grey cells for a whole day.  Herewith my attempts thus far.  I will definitely have to play with it more :D.

 

M5ANrFW.png

 

dC7HrtJ.png

5

Share this post


Link to post
Share on other sites

That crystal sphere is really neat, Pixey!

0

Share this post


Link to post
Share on other sites

Tutorial, Part III

 

Now I'll show another useful idea that can produce images like this (and much more complex images, too):

RedAndBlueSphere_zpss238ouah.png

 

----------

First, let me explain the idea behind it.

 

In the above examples, I show two height maps. One map is the original sphere; the second map is the sphere with ridges "cut" into it. In the squares, the heights of those two height maps are virtually the same. In the ridges, the sphere with the grid added is lower. The Texture Merger has a feature that makes all the heights that match the window (or canvas) heights transparent. It also has a merge mode called Minimum which makes the merged height the minimum of the window (canvas) or clipboard height.

 

Suppose the canvas contains the original sphere, and clipboard contains the sphere with the ridges. Inside the squares, the heights should be the same, so the minimums equal the canvas heights (and also the clipboard heights). Therefore, they will be made transparent. Inside the ridges, the clipboard heights will be lower, so will those will be the minimum heights, and those pixels won't be made transparent. The result will be the clipboard image with all the pixels not inside the ridges made transparent.

 

The plan is to make two layers containing the original sphere. The bottom layer is shaded with the Texture Shader. The top layer is modified with the Texture Merger to leave only the ridges, then is shaded differently,

 

One slight modification to the scheme is that inside the squares, the heights don't always match exactly, and sometimes the clipboard height is a tiny bit lower.  (I don't know exactly why.)  To solve this, I add a small offset to the clipboard heights to make them always higher inside the squares. [I now know why. It was a tiny bug. In one case I rounded the height to an integer; in another case I didn't. Even in the fixed version, the result is better when a small offset is added to the clipboard heights. Otherwise the edge where the squares and ridges meet is ragged.]

----------

 

The steps are:

Copy the unmodified sphere height-map as a new image into PDN. (The image from my previous comment.)

SphereTranspBGRA_zps7ho9pazu.png

Run the Texture Merger with the following controls changed from default:

Height Merge Method: Canvas

Antialias: Checked

(This step isn't actually required, but it makes the sphere map antialiased the way the gridded sphere map is. That will make the heights within the squares match more closely, so less of an offset will be need to be added to the clipboard heights to assure that the window heights are minimum within the squares.)

 

Duplicate the layer.

 

Set the Primary Color to Red (the first red in the color palette.)

 

Run the Texture Shader with the following controls changed from default.

Image: Primary Color

Texture Height Scale: 255

Use Alpha from Texture: Checked

Directional Light Direction: 0, -150, 50

Antialias: Checked

 

Move the unshaded layer to the top. Leave the shaded layer visible.

 

Copy the gridded sphere map into the clipboard. (From my previous comment.)

TextureMergerGridSphereMap_zpsmlpmaizc.p

Run the Texture Merger on the top layer with the following controls change from default:

Merged Height Scale: 255

Height Merge Method: Minimum

Make Unmodified Canvas Heights Transparent: Checked (this is the key to making it work)

Antialias: Checked

Show Shading: Checked

Clipboard Height Offset: 0.0010.

 

Uncheck Show Shading and click OK to save the height map.

 

Change the Primary Color to blue. I used the medium blue from the Color Palette.

 

Run the Texture Shader on the layer with the same settings as before.

 

Merge the layers.

 

Of course, both the squares and the lines could be handled in much more complicated ways. For instance, another texture could be combined with the layer that forms the squares (such as I did with the silver and gold sphere example). I wanted to introduce as few complications as possible.

 

2

Share this post


Link to post
Share on other sites

In the Plugin Index, Ego Eram Reputo used the term Canvas for what I called in my program controls the "Window." Canvas might be a better name for it. Any opinions on whether I should I change to Canvas in my next version? (E.g, Make Unmodified Canvas Heights Transparent.)

 

Another change I'm considering is to make the Merged Height-Map Height cover the large range (0-1000) by default, and make the Checkbox scale it by one-tenth to reduce the range. Currently, it's the opposite.

 

Any other suggestions to improve the interface are welcome. (Other than write my own UI forms and controls. That may be a good idea, but I'm not likely to do it anytime soon.)

1

Share this post


Link to post
Share on other sites

I think 'Canvas' might be a better term to use.

On the 2nd point, I'll defer to your better judgement.   (I'm making some wild things with all your texture plugins, now that I know how to properly use them!)

Thanks, MJW!   :D

0

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now