I have a Unity project using MRTK.
After I changed the MRTK/Standard shader with the following shader, it only renders the object to the left eye.
How can I render the object to both eyes?
Shader "HoloUS/BrightnessContrast"
{
Properties
{
_MainTex("Texture", 2D) = "white" {}
_Width("Width", Float) = 1
_Center("Center", Float) = 0.5
}
SubShader
{
Tags { "RenderType" = "Opaque" }
LOD 100
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
struct VInp
{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
};
struct VOut
{
float2 uv : TEXCOORD0;
float4 vertex : SV_POSITION;
};
sampler2D _MainTex;
float4 _MainTex_ST;
float _Center;
float _Width;
VOut vert(VInp inp)
{
VOut o;
o.vertex = UnityObjectToClipPos(inp.vertex);
o.uv = TRANSFORM_TEX(inp.uv, _MainTex);
return o;
}
fixed4 frag(VOut inp) : SV_Target
{
float min = _Center - _Width / 2;
return tex2D(_MainTex, inp.uv) * _Width + min;
}
ENDCG
}
}
}
For shaders with Hololens and MRTK2, there is an upgrade path perhaps that needs to be clicked through:
https://learn.microsoft.com/en-us/windows/mixed-reality/mrtk-unity/mrtk2/features/rendering/mrtk-standard-shader?q=shader&view=mrtkunity-2022-05
Also, Unity defines following on stereo rendering for HoloLens for shader script requirements:
https://docs.unity3d.com/Manual/SinglePassStereoRenderingHoloLens.html
From version of Unity, could not tell the specific version and MRTK version using in sample above. If have further details, perhaps can assist further too with community.
If you are using single pass vr, there are few changes in shader declaration, in order to recognise stereo texture input in single pass.
//add this in struct appdata
UNITY_VERTEX_INPUT_INSTANCE_ID
//add this in struct v2f
UNITY_VERTEX_OUTPUT_STEREO
//replace sampler2D
UNITY_DECLARE_SCREENSPACE_TEXTURE(_MainTex);
//add these inside v2f vert()
UNITY_SETUP_INSTANCE_ID(v);
UNITY_INITIALIZE_OUTPUT(v2f, o);
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
Additional link: Single Pass Instanced rendering
Related
I'm trying to solve how to paint a texture in Unity at runtime. But the idea is to have a Canvas, an Image (with a texture) and paint over it using GPU (shader pass). But I don't really know how to start, or where to look at.
There's a very interesting project but it does uses 3D Meshes, and solves the problem with Metallic, Smoothness integration. Also solves the hard edges problem, making the solution very difficult to start with for a beginner.
Mesh Texture painting in Unity Using Shaders and the repo https://github.com/IRCSS/TexturePaint.
My guess is that this shader is the basic and probably the foundation of how to solve this:
Shader "Unlit/TexturePaint"
{
SubShader
{
Tags { "RenderType"="Opaque" }
LOD 100
ZTest Always
ZWrite Off
Cull Off
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma exclude_renderers d3d9 d3d11 xbox360 ps3 flash
#include "UnityCG.cginc"
struct appdata
{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
};
struct v2f
{
float4 vertex : SV_POSITION;
float3 worldPos : TEXCOORD0;
float2 uv : TEXCOORD1;
};
float4 _Mouse;
float4x4 mesh_Object2World;
sampler2D _MainTex;
fixed4 _BrushColor;
float _BrushOpacity;
float _BrushHardness;
float _BrushSize;
v2f vert (appdata v)
{
v2f o;
float2 uvRemapped = v.uv.xy;
#if UNITY_UV_STARTS_AT_TOP
uvRemapped.y = 1. - uvRemapped.y;
#endif
uvRemapped = uvRemapped * 2 - 1;
o.vertex = float4(uvRemapped.xy, 0, 1);
o.worldPos= mul(mesh_Object2World, v.vertex);
o.uv = v.uv;
return o;
}
fixed4 frag (v2f i) : SV_Target
{
float4 col = tex2D(_MainTex, i.uv);
float size = _BrushSize;
float soft = _BrushHardness;
float f = distance(_Mouse.xz, i.worldPos.xz);
f = 1. - smoothstep(size * soft, size, f);
col = lerp(col, _BrushColor, f);
col = saturate(col);
return col;
}
ENDCG
}
}
Fallback Off
}
I am creating a 2D unity game and my idea was to make pixel lighting. that is, as you approach the lantern, the objects will change color (according to the color palette).
the effect I want to get is shown below (this is a drawing so far).
I have no idea how such "lighting" can be implemented, at first I thought to do it using shader graph, but out of my stupidity I could not do it. (I tried many more options, but I never managed to implement my plans) for this, I ask for help from those who know.
I haven't worked with 2d lighting, so I'm not certain, but I have an old post processing shader that can pixelize and use a limited color pallet for the default render pipeline that might work for you.
Shader:
Shader "Custom/PixelPallet"
{
Properties
{
_MainTex ("Texture", 2D) = "white" {}
_ColorTheme("Theme", 2D) = "white" {}
}
SubShader
{
Tags { "RenderType"="Opaque" }
LOD 100
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
struct appdata
{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
};
struct v2f
{
float2 uv : TEXCOORD0;
float4 vertex : SV_POSITION;
};
sampler2D _MainTex;
sampler2D _ColorTheme;
float4 _MainTex_ST;
int _PixelDensity;
float2 _ScreenAspectRatioMultiplier;
float2 _SpriteAspectRatioMultiplier;
v2f vert (appdata v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
o.uv = TRANSFORM_TEX(v.uv, _MainTex);
return o;
}
fixed4 frag (v2f i) : SV_Target
{
float2 pixelScaling = _PixelDensity * _ScreenAspectRatioMultiplier;
float2 pixelCoord = round(i.uv * pixelScaling)/ pixelScaling;
fixed4 value = tex2D(_MainTex, pixelCoord);
float2 coord = float2(value.r,value.g);
return tex2D(_ColorTheme, coord);
}
ENDCG
}
}
}
Post Process Script:
using UnityEngine;
public class PostEfect : MonoBehaviour
{
private Material mat;
public Texture texture;
public int pixelDensity = 80;
void Start()
{
mat = new Material(Shader.Find("Custom/PixelPallet"));
mat.SetTexture("_ColorTheme", texture);
}
void OnRenderImage(RenderTexture src, RenderTexture dest)
{
Vector2 aspectRatioData;
if (Screen.height > Screen.width)
aspectRatioData = new Vector2((float)Screen.width / Screen.height, 1);
else
aspectRatioData = new Vector2(1, (float)Screen.height / Screen.width);
mat.SetVector("_ScreenAspectRatioMultiplier", aspectRatioData);
mat.SetInt("_PixelDensity", pixelDensity);
// Read pixels from the source RenderTexture, apply the material, copy the updated results to the destination RenderTexture
Graphics.Blit(src, dest, mat);
}
}
Just drop the script on the camera and select a color pallet sprite with point filter. Adjust the pixel Density according to your needs.
I'm trying to archieve a chilindrical effect like this on Unity3D:
But every solution is using material based shader, sadly I must have a Post Process effect or an Image Effect, for these reasons:
One map out of 30 needs to use this effect and there are many materials that are shared between them...
Every solution is vertex based. I've done some experiments but I have models with different polygon count, this means that the effect would create visual artifacts (but this can by fixed by editing the 3d models eventually).
I'm at an advanced stage of development.
Do you think it's possible to create a simple effect (even a fake one) that moves the pixels downwards/upwards based on the distance to the camera? (I assume I need to use the depth map)
I've tried very hard but I had no success, the effect doesn't do anything or just won't compile :(
This is the best I could come up with, the grayscale in the frag method is only to check if the shader is working, but once I define the Vert function the grayscale disappears and the shader does nothing.
Shader "Hidden/Custom/WorldCurvature"
{
HLSLINCLUDE
#include "Packages/com.unity.postprocessing/PostProcessing/Shaders/StdLib.hlsl"
TEXTURE2D_SAMPLER2D(_MainTex, sampler_MainTex);
float _Bend;
struct Attributes
{
float4 vertex : POSITION;
float2 texcoord : TEXCOORD0;
};
struct Varyings
{
float4 vertex : SV_POSITION;
float2 texcoord : TEXCOORD0;
};
float4 Frag(Varyings i) : SV_Target
{
float4 color = SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, i.texcoord);
float luminance = dot(color.rgb, float3(0.2126729, 0.7151522, 0.0721750));
color.rgb = lerp(color.rgb, luminance.xxx, _Bend.xxx);
return color;
}
Varyings Vert(Attributes v)
{
Varyings o;
float4 vv = mul(unity_ObjectToWorld, v.vertex );
vv.xyz -= _WorldSpaceCameraPos.xyz;
vv = float4( 0.0f, (vv.x * vv.x) * - _Bend, 0.0f, 0.0f );
v.vertex += mul(unity_WorldToCamera, vv);
o.vertex = mul(unity_WorldToCamera, vv);
o.texcoord = v.texcoord;
return o;
}
ENDHLSL
SubShader
{
Cull Off ZWrite Off ZTest Always
Pass
{
HLSLPROGRAM
#pragma vertex Vert
#pragma fragment Frag
ENDHLSL
}
}
}
I've done another experiment but I think it would only work in a 2D environment, here the image stops once I activate the image effect:
Shader "Hidden/Custom/CylinderImageEffect" {
Properties {
_MainTex ("Texture", 2D) = "white" {}
}
SubShader {
Cull Off ZWrite Off ZTest Always
Pass {
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
struct v2f {
float4 vertex : SV_POSITION;
float2 uv : TEXCOORD0;
};
v2f vert( appdata_img v )
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
o.uv = v.texcoord.xy;
return o;
}
sampler2D _MainTex;
fixed4 frag (v2f i) : SV_Target {
i.uv.x = 1 - acos(i.uv.x * 2 - 1) / 3.14159265;
return tex2D(_MainTex, i.uv);
}
ENDCG
}
}
}
I'm currently stuck in a shader that i'm writing.
I'm trying to create a rain shader.
I have set up 3 particle system which simulates rain, and a
camera to look at this simulation. The camera view is what I
use as texture. In my shader I am now trying to make a normal map
from that texture map, but I don't know how to do it.
Shader "Unlit/Rain"
{
Properties
{
_MainTex("Albedo (RGB)", 2D) = "white" {}
_Color("Color", Color) = (1,1,1,1)
_NormalIntensity("NormalIntensity",Float) = 1
}
SubShader
{
Tags { "RenderType" = "Opaque" }
LOD 100
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
#include "Lighting.cginc"
#include "AutoLight.cginc"
struct VertexInput {
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
float4 normal : NORMAL;
float3 tangent : TANGENT;
};
struct VertexOutput {
float2 uv : TEXCOORD0;
float4 vertex : SV_POSITION;
float2 uv1 : TEXCOORD1;
float4 normals : NORMAL;
float3 tangentSpaceLight: TANGENT;
};
sampler2D _MainTex;
float4 _MainTex_ST;
half4 _Color;
float _NormalIntensity;
VertexOutput vert(VertexInput v) {
VertexOutput o;
o.normals = v.normal;
o.uv1 = v.uv;
o.vertex = UnityObjectToClipPos( v.vertex );
// o.uv = TRANSFORM_TEX( v.uv, _MainTex ); // used for texture
return o;
}
float4 frag(VertexOutput i) : COLOR{
float4 col2 = tex2D(_MainTex, i.uv1);
return col2 * i.normals * 5;
}
ENDCG
}
}
}
This is what the camera sees. I set the TargetTexture for this camera to be a texture I created.
In my shader I then put that texture as an albedo property
So what I wanna do is now find the normal for that texture to create a bumpmap.
It looks like your "TargetTexture" is giving you back a height map. Here is a post I found about how to turn a height map into a normal map. I've mashed the code you had originally together with the core of that forum post and output the normals as color so you can test and see how this works:
Shader "Unlit/HeightToNormal"
{
Properties
{
_MainTex("Albedo (RGB)", 2D) = "white" {}
_Color("Color", Color) = (1,1,1,1)
_NormalIntensity("NormalIntensity",Float) = 1
_HeightMapSizeX("HeightMapSizeX",Float) = 1024
_HeightMapSizeY("HeightMapSizeY",Float) = 1024
}
SubShader
{
Tags { "RenderType" = "Opaque" }
LOD 100
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
#include "Lighting.cginc"
#include "AutoLight.cginc"
struct VertexInput {
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
float4 normal : NORMAL;
float3 tangent : TANGENT;
};
struct VertexOutput {
float2 uv : TEXCOORD0;
float4 vertex : SV_POSITION;
float2 uv1 : TEXCOORD1;
float4 normals : NORMAL;
//float3 tangentSpaceLight: TANGENT;
};
sampler2D _MainTex;
float4 _MainTex_ST;
half4 _Color;
float _NormalIntensity;
float _HeightMapSizeX;
float _HeightMapSizeY;
VertexOutput vert(VertexInput v) {
VertexOutput o;
o.uv = TRANSFORM_TEX( v.uv, _MainTex ); // used for texture
o.uv1 = v.uv;
o.normals = v.normal;
o.vertex = UnityObjectToClipPos(v.vertex);
return o;
}
float4 frag(VertexOutput i) : COLOR
{
float me = tex2D(_MainTex,i.uv1).x;
float n = tex2D(_MainTex,float2(i.uv1.x, i.uv1.y + 1.0 / _HeightMapSizeY)).x;
float s = tex2D(_MainTex,float2(i.uv1.x, i.uv1.y - 1.0 / _HeightMapSizeY)).x;
float e = tex2D(_MainTex,float2(i.uv1.x + 1.0 / _HeightMapSizeX,i.uv1.y)).x;
float w = tex2D(_MainTex,float2(i.uv1.x - 1.0 / _HeightMapSizeX,i.uv1.y)).x;
// defining starting normal as color has some interesting effects, generally makes this more flexible
float3 norm = _Color;
float3 temp = norm; //a temporary vector that is not parallel to norm
if (norm.x == 1)
temp.y += 0.5;
else
temp.x += 0.5;
//form a basis with norm being one of the axes:
float3 perp1 = normalize(cross(i.normals,temp));
float3 perp2 = normalize(cross(i.normals,perp1));
//use the basis to move the normal i its own space by the offset
float3 normalOffset = -_NormalIntensity * (((n - me) - (s - me)) * perp1 + ((e - me) - (w - me)) * perp2);
norm += normalOffset;
norm = normalize(norm);
// it's also interesting to output temp, perp1, and perp1, or combinations of the float samples.
return float4(norm, 1);
}
ENDCG
}
}
}
To generate a normal map from a height map, you're trying to use the oriented rate of change in your height map to come up with a normal vector which can be represented using 3 float values (or color channels, if it's an image). You can sample the point of image you are on, and then small steps away from that point in four cardinal directions. Using the cross product to guarantee orthogonality you can define a basis. Using your oriented steps on your image, you can scale the two basis vectors and add them together to find a "normal offset", which is the 3D representation approximating the oriented change in value on your heightmap. Basically it's your normal.
You can see the effects of me playing with normal intensity here, and the "normal color" here. When this looks right for your use case, you can try using normals as normals instead of colored output.
Some tweaking of values will probably still be required. Good luck!
I want to merge the functionality of these two shaders for Unity.
First shader is main shader that adds a glitch hologram effect.
The Second shader is making a surface texture flimmer for added visual effect.
I am trying to merge my versions of the code, alternatively different passes that allows me to implement both features on same material, if possible.
I have tried shaderpass function, but cannot make it work.
Is it possible to do?
1st shadercode
Shader "Custom/Cool Hologram Original"
{
Properties
{
//This program takes an existing shader script and builds upon it, by adding the features :
//Tintcolor - allowing for manipulation of colors
//Transparency - Changing opaque in tags to transparency so that the model becomes transparent
//Properties allow defining public manipulative variables
_MainTex ("AlbedoTexture", 2D) = "white" {} //braces are useless leftover braces no longer needed according to Unity developer
_TintColor("Tint Color", Color) = (1,1,1,1) //Public variable appearing in inspector
_Transparency("Transparency", Range(0.0,0.5)) = 0.25
_CutoutTresh("Cutout Threshold", Range(0.0,1.0)) = 0.2
_Distance("Distance", Float) = 1
_Amplitude("Amplitude", Float) = 1
_Speed("Speed", Float) = 1
_Amount("Amount", Range(0.0,1.0)) = 1
}
//The actual shader program
SubShader
{
Tags {"Queue"="Transparent" "RenderType"="Transparent" } //Added queue and transparent elements because order matters (see render order queu tag)
LOD 100 //LOD means level of details and used for when player is close or far away
ZWrite Off //This is related to culling and depth testing, controlling if something is written to depth buffer. Zwrite off is for transparent objects
Blend SrcAlpha OneMinusSrcAlpha //See blend factors in unity doc. It is about render order and how they should blend
Pass //A pass can be made for each type of situation, like Virtual Reality etc
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc" //Shaders does not use inheritance, it has got monobehaviour instead, so it must be defined as #included
struct appdata //Structs are objects with 2 objects each. appdata is passed in to v2f vert as argument
{
float4 vertex : POSITION; //Variable with 4 floating point numbers x,y,z,w. POSITION is a semantic binding telling where it is to be used
float2 uv : TEXCOORD0;
};
struct v2f
{
float2 uv : TEXCOORD0;
float4 vertex : SV_POSITION; //SV_Position corresponds to screen position in Unity
};
sampler2D _MainTex;
float4 _MainTex_ST;
float4 _TintColor;
float _Transparency;
float _CutoutThresh;
float _Distance;
float _Amplitude;
float _Speed;
float _Amount;
v2f vert (appdata v)
{
v2f o;
v.vertex.x += sin(_Time.y * _Speed + v.vertex.y * _Amplitude) * _Distance * _Amount; //Allows sinusoidal movement to vertices in object space b4 translation to clip
o.vertex = UnityObjectToClipPos(v.vertex); //See learnopengl.com to see 5 spaces: local space, world space, view space, clip space, screen space
o.uv = TRANSFORM_TEX(v.uv, _MainTex); //Taking uv data from model and data from maintexture (see the shader texture in inspector)
return o; //Returns struct after it has been build in coordinate system, it will then be passed to fragment function
}
fixed4 frag (v2f i) : SV_Target //Takes in v2f struct calling it i and then bind it to render target, which is frame buffer for screen
{
// sample the texture
fixed4 col = tex2D(_MainTex, i.uv) + _TintColor; //fixed 4 col is color. Can be fixed rgbA for 3 colors and an alpha channel. tex2D reads in colors from maintex and struct data from i
col.a = _Transparency; //The colors are what actually drawed in this feature with tex3D
clip(col.r - _CutoutThresh); //Not drawing pixels with certain amount of red color
return col;
}
ENDCG
}
}
}
2nd shadercode
Shader "Custom/Offset 1"
{
Properties {
_MainTex ("Texture", 2D) = "white" {}
_ScrollSpeeds ("Scroll Speeds", vector) = (0, -3, 0, 0)
}
SubShader
{
Tags { "RenderType"="Opaque" }
LOD 100
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
// make fog work
#pragma multi_compile_fog
#include "UnityCG.cginc"
struct appdata
{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
};
struct v2f
{
float2 uv : TEXCOORD0;
UNITY_FOG_COORDS(1)
float4 vertex : SV_POSITION;
};
sampler2D _MainTex;
float4 _MainTex_ST;
// Declare our new parameter here so it's visible to the CG shader
float4 _ScrollSpeeds;
v2f vert (appdata v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
o.uv = TRANSFORM_TEX(v.uv, _MainTex);
// Shift the uvs over time.
o.uv += _ScrollSpeeds * _Time.x;
UNITY_TRANSFER_FOG(o,o.vertex);
return o;
}
fixed4 frag (v2f i) : SV_Target
{
// sample the texture
fixed4 col = tex2D(_MainTex, i.uv);
// apply fog
UNITY_APPLY_FOG(i.fogCoord, col);
return col;
}
ENDCG
}
}
}
3rd shadercode
Shader "Custom/Combined"
{
Properties
{
_MainTex ("AlbedoTexture", 2D) = "white" {}
_HoloColor("Hologram Color", Color) = (1,1,1,1)
_Transparency("Transparency", Range(0.0,0.5)) = 0.25
_CutoutTresh("Cutout Threshold", Range(0.0,1.0)) = 0.2
_Distance("Distance", Float) = 1
_Amplitude("Amplitude", Float) = 1
_Speed("Speed", Float) = 1
_ScrollSpeeds("Scroll Speeds", vector) = (0,-3,0,0) //added from offset shader
_Amount("Amount", Range(0.0,1.0)) = 1
}
SubShader {
Tags {"Queue"="Transparent" "RenderType"="Transparent" }
LOD 100
ZWrite Off
Blend SrcAlpha OneMinusSrcAlpha
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
struct appdata {
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
};
struct v2f {
float2 uv : TEXCOORD0;
UNITY_FOG_COORDS(1) //added from offset shader
float4 vertex : SV_POSITION;
};
sampler2D _MainTex;
float4 _MainTex_ST;
float4 _HoloColor;
float4 _ScrollSpeeds;
float _Transparency;
float _CutoutThresh;
float _Distance;
float _Amplitude;
float _Speed;
float _Amount;
v2f vert (appdata v)
{
v2f o;
v.vertex.x += sin(_Time.y * _Speed + v.vertex.y * _Amplitude) * _Distance * _Amount;
o.vertex = UnityObjectToClipPos(v.vertex);
o.uv = TRANSFORM_TEX(v.uv, _MainTex);
o.uv += _ScrollSpeeds * _Time.x; //Added from offset shader
UNITY_TRANSFER_FOG(o,o.vertex); //added from offset shader
return o;
}
fixed4 frag (v2f i) : SV_Target
{
fixed4 col = tex2D(_MainTex, i.uv) + _HoloColor;
col.a = _Transparency;
clip(col.r - _CutoutThresh);
UNITY_APPLY_FOG(i.fogCoord, col); //Added from offset shader
return col;
}
ENDCG
}
}
Fallback "Diffuse"
}