I am trying to achieve to hide my UI elements such as text, images etc. behind another transparent image. The problem is that I am using the latest Unity version and these custom shaders have no effect on hiding the UI shaders. The two custom shaders I have applied for testing are:
Shader "Custom/DepthReserve"
{
Properties
{
}
SubShader
{
Tags { "RenderType" = "Opaque" "Queue"="Geometry-1" }
LOD 100
Blend Zero One
Pass
{
}
}
}
and
Shader "Custom/InvisibleMask" {
SubShader {
// draw after all opaque objects (queue = 2001):
Tags { "Queue"="Geometry+1" }
Pass {
Blend Zero One // keep the image behind it
}
}
}
So is there a way to use a transparent image to hide text, images and even gameobjects?
Related
I have created a custom shader that is used to blend two materials easily. How do I include properties such as Normal map and emission properties and other properties as well from Unity's Standard (Roughness) shader?
Shader "Myshaders/ChangeMaterial" {
Properties {
_Tint ("Tint Color", Color) = (.9, .9, .9, 1.0)
_TexMat1 ("Base (RGB)", 2D) = "white" {}
_TexMat2 ("Base (RGB)", 2D) = "white" {}
_Blend ("Blend", Range(0.0,1.0)) = 0.0
}
Category {
ZWrite On
Alphatest Greater 0
Tags {Queue=Transparent}
Blend SrcAlpha OneMinusSrcAlpha
ColorMask RGB
SubShader {
Pass {
Material {
Diffuse [_Tint]
Ambient [_Tint]
}
Lighting On
SetTexture [_TexMat1] { combine texture }
SetTexture [_TexMat2] { constantColor (0,0,0,[_Blend]) combine texture lerp(constant) previous }
SetTexture [_TexMat2] { combine previous +- primary, previous * primary }
}
}
FallBack " Diffuse", 1
}
}
In your example, you are incorrectly using the legacy ShaderLab passes which do not apply to the Physically Based Rendering pipeline (contemporary) nor the scriptable rendering pipeline (bleeding edge).
You should get familiar with the built in shader code located at https://github.com/TwoTailsGames/Unity-Built-in-Shaders. Observe the #include statements located in the various passes here: https://github.com/TwoTailsGames/Unity-Built-in-Shaders/blob/master/DefaultResourcesExtra/Standard.shader
In my chess game, I have a scene of pieces choice - black or white. After the user clicks on one of the pawns he/she gets a popup message/ It looks like this:
On Ok button click, the scene changes to the one with the board:
When the user chose black pieces he/she should see them closer to him/her, while if the user chose white pieces, they should be at the front. By default, in my scene pieces which are closer are black. I tried to achieve this by adding a texture change script on each figure (they will differ for white and black pieces):
void Start () {
GetComponent<Renderer>().material = Resources.Load<Material>)"Materials/Pieces/Marble/White Pawn");
}
However, how can I disable this script when I redirect to the scene if the user chose black pieces and the default view is needed.
Here is my code for popup window:
void OnGUI()
{
if (showPopUp)
{
GUI.Window(0, new Rect((Screen.width / 2) - 200, (Screen.height / 2) - 115
, 420, 180), ShowGUI, "Figures choice");
}
}
void ShowGUI(int windowID)
{
RedirectToMenu redirect = new RedirectToMenu();
guiStyle.fontSize = 22;
guiStyle.normal.textColor = Color.white;
GUI.Label(new Rect(80, 40, 200, 30), "You have chosen black pieces", guiStyle);
if (GUI.Button(new Rect(180, 110, 75, 35), "OK")){
showPopUp = false;
redirect.LoadAsset("UpgradedRoom");
SceneManager.LoadScene("UpgradedRoom");
}
}
I suppose I should access this script before loading the scene and disable if needed. But how can I access it outside of the scene with table, chessboard, and pieces? Or can I change the textures of game objects on another scene?
What I would do is use a static variable to remember whether the pieces are black or white. So, you'd set the variable before the scene loads and then check it after it is loaded. Therefore, if your class is called chess manager, your code for setting the variable might look like this:
public class ChessManager : Monobehavior {
public enum ChessColor { Black, White }
public static ChessColor playerColor
public void OnGUI() {
if(user chooses black) {
playerColor = ChessColor.Black;
//Load scene
}
else if(user chooses white) {
playerColor = ChessColor.White;
//Load scene
}
}
}
...And your code for enabling/disabling the script might be something like this, where ColorChanger is the script that sets the color:
public class ColorChanger : Monobehavior {
public void Start() {
if(ChessManager.playerColor == ChessManager.ChessColor.White) {
//Set texture
}
}
}
This would set the texture to something else when the user chooses white once the new scene is loaded. Don't forget to replace the if statements in ChessManager with the code that executes when a chess piece is selected (I'm assuming you're using legacy buttons for that, so you should replace if(user chooses color) with if(GUI.Button)). Hope I could help!
Also, as previously noted by someone else in the comments, it would probably be best if you used UnityEngine.UI instead of Unity's outdated legacy GUI system, but depending upon the project it might not be worth the effort.
I'm using Xamarin.Forms.GoogleMaps in my portable project.
it's working pretty well for iOS and Android.
right now I'm working on the pin/markers of the googleMap.
I'm trying to add pins with different colors, but not all colors are working.
How I'm doing it right now:
var pin = new Xamarin.Forms.GoogleMaps.Pin();
pin.Label = ... etc etc etc
pin.Icon = BitmapDescriptorFactory.DefaultMarker(Color.Azure);
The example above works well. But if I change it to Color.Black, for example, it doesn't work and show the marker with the default red color. And it also have problem with different platforms, in iOS, Black works, in Android don't. (no errors appear, just show the default red instead of Black)
So my question is:
Is there a list of acceptable colors to use as marker/pin color? Does every color should work or just some predefined colors?
Also, how do i change the default icon to another icon image? I tried with "FromBundle", but it throws an error, at least for me.(maybe I did it wrong. It told about image need to be a bitmap)
If possible, I want to avoid custom renderers, because right now it is working very well without any custom render (except some colors as I said).
If you prefer not to use Custom Renderers, Xamarin Forms Map markers/pins only have 300+ colors available to use.
But if you want to represent marker/pins colors as you would like them to be, you would need to implement the Xamarin Forms Custom Renderers to achieve/capture the exact marker/pin color that you want.
After you follow the steps in the Xamarin Forms custom renderer documentation, override the following method:
protected override MarkerOptions CreateMarker(Pin pin)
{
CustomPin customPin = (CustomPin)pin;
var marker = new MarkerOptions();
marker.SetPosition(new LatLng(pin.Position.Latitude, pin.Position.Longitude));
marker.SetTitle(pin.Label);
marker.SetSnippet(pin.Address);
marker.SetIcon(GetCustomBitmapDescriptor(customPin.Color));
return marker;
}
Then I created the following method that will do the actual changes to marker/pin colors that will be the exact color from your RGB/Hex color code:
private BitmapDescriptor GetCustomBitmapDescriptor(string text)
{
using (Paint paint = new Paint(PaintFlags.AntiAlias))
{
using (Rect bounds = new Rect())
{
using (Bitmap baseBitmap = BitmapFactory.DecodeResource(Resources, Resource.Drawable.marker))
{
Bitmap resultBitmap = Bitmap.CreateBitmap(baseBitmap, 0, 0, baseBitmap.Width - 1, baseBitmap.Height - 1);
Paint p = new Paint();
ColorFilter filter = new PorterDuffColorFilter(Android.Graphics.Color.ParseColor(text), PorterDuff.Mode.SrcAtop);
p.SetColorFilter(filter);
Canvas canvas = new Canvas(resultBitmap);
canvas.DrawBitmap(resultBitmap, 0, 0, p);
Bitmap scaledImage = Bitmap.CreateScaledBitmap(resultBitmap, 94, 150, false);
BitmapDescriptor icon = BitmapDescriptorFactory.FromBitmap(scaledImage);
resultBitmap.Recycle();
return (icon);
}
}
}
}
NOTES:
This sample code is just for Android. Not sure for iOS.
The Resource.Drawable.marker can be any marker that you can use. I just downloaded a generic red map marker online. It will be covered anyway by the GetCustomBitmapDescriptor method anyway.
The resultBitmap.Recycle(); is VERY important. Because bitmaps takes a lot of memory and the device application might stall so you need to reuse bitmap memory.
CustomPin is a class extending the Xamarin.Forms.Map.Pin class. I added a string attribute for the string Hex value of the color I want for my marker pin.
See sample image of a map with colors that are customized.
I am currently following this tutorial for adding a polygon to a map. I need to be able to add multiple polygons to my map, so I have slightly altered the code so that I can use addOverlays which takes in an array of IMKOverlay objects instead of one addOverlay which just takes in a single IMKOverlay object.
This doesn't work however... It only draws the first polygon on the map!
void addPolygonsToMap()
{
overlayList = new List<IMKOverlay>();
for (int i = 0; i < polygons.Count; i++)
{
CLLocationCoordinate2D[] coords = new CLLocationCoordinate2D[polygons[i].Count];
int index=0;
foreach (var position in polygons[i])
{
coords[index] = new CLLocationCoordinate2D(position.Latitude, position.Longitude);
index++;
}
var blockOverlay = MKPolygon.FromCoordinates(coords);
overlayList.Add(blockOverlay);
}
IMKOverlay[] imko = overlayList.ToArray();
nativeMap.AddOverlays(imko);
}
In this discussion, it would appear that I have to call a new instance of MKPolygonRenderer each time I need to add another polygon to my map, but I'm unsure how this example translates to my code. Here is my MKPolygonRenderer function:
MKOverlayRenderer GetOverlayRenderer(MKMapView mapView, IMKOverlay overlayWrapper)
{
if (polygonRenderer == null && !Equals(overlayWrapper, null)) {
var overlay = Runtime.GetNSObject(overlayWrapper.Handle) as IMKOverlay;
polygonRenderer = new MKPolygonRenderer(overlay as MKPolygon) {
FillColor = UIColor.Red,
StrokeColor = UIColor.Blue,
Alpha = 0.4f,
LineWidth = 9
};
}
return polygonRenderer;
}
Create a new renderer instance each time OverlayRenderer is called, there is no need to cache the renderer in a class level variable as the MKMapView will cache the renderers as needed.
Subclass MKMapViewDelegate:
class MyMapDelegate : MKMapViewDelegate
{
public override MKOverlayRenderer OverlayRenderer(MKMapView mapView, IMKOverlay overlay)
{
switch (overlay)
{
case MKPolygon polygon:
var prenderer = new MKPolygonRenderer(polygon)
{
FillColor = UIColor.Red,
StrokeColor = UIColor.Blue,
Alpha = 0.4f,
LineWidth = 9
};
return prenderer;
default:
throw new Exception($"Not supported: {overlay.GetType()}");
}
}
}
Instance and assign the delegate to your map:
mapDelegate = new MyMapDelegate();
map.Delegate = mapDelegate;
Note: Store the instance of your MyMapDelegate in a class level variable as you do not want to get GC'd
Update:
MKMapView has two steps involved to display an overlay on its map.
1. Calling `AddOverlay` and `AddOverlays`
First you add overlays to the map that conform to IMKOverlay. There are basic built-in types such as MKCircle, MKPolygon, etc... but you can also design your own overlays; i.e. overlays that define the location of severe weather (lightning, storm clouds, tornados, etc..). These MKOverlays describe the geo-location of the item but not how to draw it.
2. Responding to `OverlayRenderer` requests
When the display area of the map intersects with one of the overlays, the map need to draw it on the screen. The map's delegate (your MKMapViewDelegate subclass) is called to supply a MKOverlayRenderer that defines the drawing routines to paint the overlay on the map.
This drawing involves converting the geo-coordinates of the overlay to local display coordinates (helper methods are available) using Core Graphics routines (UIKit can be used with some limitations). There are basic built-in renderers for MKCircleRenderer, MKPolygonRenderer, etc.. that can be used or you can write your own MKOverlayRenderer subclass.
You could supply a custom way to renderer a MKCircle overlay, maybe a target-style red/white multi-ringed bullseye, instead of the way the default circle renderer draws it, or custom renderers that draw severe storm symbols within the bounds of a MKPolygon to match your custom severe storm overlays.
My Example code:
Since you are using MKPolygon to build your overlays, you can use the MKPolygonRenderer to display them. In my example, I provide a pattern matching switch (C# 6) that returns a semi-transparent Red/Blue MKPolygonRenderer for every MKPolygon that you added to the map (if you added a non-MKPolygon based overlay it will throw an exception).
I was also stuck in this issue and I have found the way to create the sub class of MKPolygon.
I have checked it with my example and it works like a charm. But not sure that Apple may reject my app or not.
public class CvPolyon : MKPolygon
{
public CustomObject BoundaryOption { get; }
public CvPolyon1(MKPolygon polygon, CustomObject boundaryOption)
:base(polygon.Handle)
{
BoundaryOption = boundaryOption;
}
}
We can add polygon on map like this.
var polygon = MKPolygon.FromCoordinates(coordinates);
var overlay = new CvPolyon(polygon, new CustomObject());
mapView.AddOverlay(overlay);
We can recognize our polygon in the class which extends MKMapViewDelegate like this.
public override MKOverlayRenderer OverlayRenderer(MKMapView mapView, IMKOverlay overlay)
{
if (overlay is CvPolyon polygon)
{
var polygonRenderer = new MKPolygonRenderer(polygon)
{
FillColor = polygon.BoundaryOption.AreaColor,
StrokeColor = polygon.BoundaryOption.LineColor,
Alpha = polygon.BoundaryOption.Alpha,
LineWidth = polygon.BoundaryOption.LineWidth
};
if (polygon.BoundaryOption.IsDashedLine)
polygonRenderer.LineDashPattern = new[] { new NSNumber(2), new NSNumber(5) };
return polygonRenderer;
}
return mapView.RendererForOverlay(overlay);
}
this is for anyone familiar with Revit, Dynamo, or C#.
I'm trying to create a custom zero-touch node using C# that will highlight a chosen curve as colored geometry in the preview window, while remaining inside of a loop.
So far I can only preview geometry by returning it, and I can't apply a color to the geometry without using the Display.ByGeometry node on the canvas.
Here is the most sensible attempt at this I have so far, and it still doesn't work. The code runs without errors, but I also don't perceive any change on the display.
public static void ColorTest (Curve crv)
{
Cone cylinder = Cone.ByPointsRadii(crv.StartPoint, crv.EndPoint, 1, 1);
DSCore.Color red = DSCore.Color.ByARGB(255, 255, 0, 0);
for (int i = 0; i < 1000; i++)
{
Display.Display.ByGeometryColor(cylinder, red);
}
temp.Dispose();
}
Any ideas would be much appreciated.