[Shader] Projecting and moving sprite(texture) on sphere mesh
I have a sphere with texture on it (cubemap texture, but that's not important). I want to mix up this texture with another texture with ability to move and scale this texture on sphere.
Here is the code to move, rotate and scale texture on sphere, in vertex function:
Shader "MyShaders/CubeMapShader"
{
Properties
{
_Tint("Tint Color", Color) = (.5, .5, .5, .5)
_Exposure("Exposure", float) = 0
[NoScaleOffset] _Tex("Cubemap", Cube) = "grey" {}
_Rotation("Rotation", float) = 0
_EnableColor("Enable color", Range(0, 1)) = 1
_Smoothness("Specular Smoothness", Range(0.05, 1)) = 0.5
_Smoothness2("Specular Radius", Range(0.1, 0.5)) = 0.5
_LightIntensity("LightIntensity", Range(0.5, 50)) = 1
//Sprite control
_Sprite("Sprite", 2D) = "white" {}
_SpriteRotation("Sprite Rotation", float) = 0
_SpritePivotScale("Sprite Scale", Vector) = (0.5,0.5,1,1)
_SpriteTranslation("Sprite Translation", Vector) = (0,0,0,0)
}
SubShader
{
Tags{ "Queue" = "Background" "RenderType" = "Background" "PreviewType" = "Skybox" "LightMode" = "ForwardBase" }
//Cull Front
//Blend One OneMinusSrcAlpha
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityStandardBRDF.cginc"
float3 RotateAroundYInDegrees (float3 vertex, float degrees)
{
float alpha = degrees * UNITY_PI / 180.0;
float sina, cosa;
sincos(alpha, sina, cosa);
float2x2 m = float2x2(cosa, -sina, sina, cosa);
return float3(mul(m, vertex.xz), vertex.y).xzy;
}
struct appdata
{
float4 vertex : POSITION;
float3 uv : TEXCOORD0;
float3 normal: NORMAL;
};
struct v2f
{
float3 uv : TEXCOORD0;
float4 vertex : SV_POSITION;
float3 normal : TEXCOORD1;
float3 worldPos : TEXCOORD2;
float2 sprite_uv : TEXCOORD3;
};
float _Rotation;
samplerCUBE _Tex;
half4 _Tex_HDR;
float _Exposure;
float4 _Tint;
float _EnableColor;
float _Smoothness;
float _Smoothness2;
float _LightIntensity;
sampler2D _Sprite;
float _SpriteRotation;
Vector _SpritePivotScale;
Vector _SpriteTranslation;
v2f vert (appdata v)
{
v2f o;
float3 rotated = RotateAroundYInDegrees(v.vertex, _Rotation);
o.vertex = UnityObjectToClipPos(v.vertex);
o.uv = v.vertex.xyz;
o.normal = UnityObjectToWorldNormal(v.normal);
o.worldPos = mul(unity_ObjectToWorld, v.vertex);
//sprite uv transform
float2x2 rotationMatrix;
float sinTheta;
float cosTheta;
o.sprite_uv = v.uv - _SpritePivotScale.xy;
sinTheta = sin(_SpriteRotation);
cosTheta = cos(_SpriteRotation);
rotationMatrix = float2x2(cosTheta, -sinTheta, sinTheta, cosTheta);
o.sprite_uv = (mul((o.sprite_uv - _SpriteTranslation.xy) * (1 / _SpritePivotScale.zw), rotationMatrix) + _SpritePivotScale.xy);
return o;
}
fixed4 frag (v2f i) : SV_Target
{
float3 diffuse = (1.0, 1.0, 1.0);
float3 lightDir = _WorldSpaceLightPos0.xyz;
i.normal = normalize(i.normal);
float3 lightColor = _LightColor0.rgb * _LightIntensity;
float3 temp = (DotClamped(lightDir*_Smoothness2, i.normal));
diffuse = max(0.1, pow(lightColor * temp, _Smoothness *100));
half4 tex = texCUBE(_Tex, i.uv);
tex = tex * _Tint.rgba * float4(unity_ColorSpaceDouble.rgb, 1);
tex.rgb *= _Exposure;
tex.rgb *= diffuse;
//adding sprite to existing texture
tex += tex2D(_Sprite, i.sprite_uv);
return tex ;
}
ENDCG
}
}
}
In fragment fuction I just tex2D this textute based on uv i calculated in vertex func and add it to my existing texture (just cubemap tex). Here is what I get in the middle of the sphere: And this is what i get near the top of the sphere:
I understand that it's beacuse how uv coords mapped to the sphere surface, so the question is: is it possible to add second texture/sprite to existing sphere with it's own texture and have ability to move and scale it. I need this second texture into shader so variants like putting a sprite in front of sphere is unsuitable.