Skip to content

Instantly share code, notes, and snippets.

@tolotratlt
Last active February 1, 2023 08:16
Show Gist options
  • Save tolotratlt/70e8a3790cfb1839a21587d70dd2fda2 to your computer and use it in GitHub Desktop.
Save tolotratlt/70e8a3790cfb1839a21587d70dd2fda2 to your computer and use it in GitHub Desktop.
Unity Equirectangular unlit shader for inverted (normal) sphere. Only valid for inverted sphere (made under 3d modeling program or procedurally). Does'nt work for classical sphere
// Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'
Shader "Unlit/Equirectangular"
{
Properties{
_Color("Main Color", Color) = (1,1,1,1)
_MainTex("Diffuse (RGB) Alpha (A)", 2D) = "gray" {}
}
SubShader
{
Pass
{
Tags{ "LightMode" = "Always" }
//Cull Front //activate if shere normal is not inverted
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma fragmentoption ARB_precision_hint_fastest
#pragma glsl
#pragma target 3.0
#include "UnityCG.cginc"
struct appdata
{
float4 vertex : POSITION;
float3 normal : NORMAL;
};
struct v2f
{
float4 pos : SV_POSITION;
float3 normal : TEXCOORD0;
};
v2f vert(appdata v)
{
v2f o;
o.pos = UnityObjectToClipPos(v.vertex);
o.normal = v.normal;
return o;
}
sampler2D _MainTex;
#define PI 3.141592653589793
inline float2 RadialCoords(float3 a_coords)
{
float3 a_coords_n = normalize(a_coords);
float lon = atan2(a_coords_n.z, a_coords_n.x);
float lat = acos(a_coords_n.y);
float2 sphereCoords = float2(lon, lat) * (1.0 / PI);
return float2(1- (sphereCoords.x * 0.5 - 0.5), 1-sphereCoords.y);
}
float4 frag(v2f IN) : COLOR
{
float2 equiUV = RadialCoords(-IN.normal);
return tex2D(_MainTex, equiUV);
}
ENDCG
}
}
FallBack "VertexLit"
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
//NOTE
//put in /Assets/Editor folder
public class InvertedSphere : EditorWindow
{
private string st = "1.0";
[MenuItem("GameObject/Create Other/Inverted Sphere...")]
public static void ShowWindow()
{
EditorWindow.GetWindow(typeof(InvertedSphere));
}
public void OnGUI()
{
GUILayout.Label("Enter sphere size:");
st = GUILayout.TextField(st);
float f;
if (!float.TryParse(st, out f))
f = 1.0f;
if (GUILayout.Button("Create Inverted Sphere"))
{
CreateInvertedSphere(f);
}
}
private void CreateInvertedSphere(float size)
{
GameObject go = GameObject.CreatePrimitive(PrimitiveType.Sphere);
MeshFilter mf = go.GetComponent<MeshFilter>();
Mesh mesh = mf.sharedMesh;
GameObject goNew = new GameObject();
goNew.name = "Inverted Sphere";
MeshFilter mfNew = goNew.AddComponent<MeshFilter>();
mfNew.sharedMesh = new Mesh();
//Scale the vertices;
Vector3[] vertices = mesh.vertices;
for (int i = 0; i < vertices.Length; i++)
vertices[i] = vertices[i] * size;
mfNew.sharedMesh.vertices = vertices;
// Reverse the triangles
int[] triangles = mesh.triangles;
for (int i = 0; i < triangles.Length; i += 3)
{
int t = triangles[i];
triangles[i] = triangles[i + 2];
triangles[i + 2] = t;
}
mfNew.sharedMesh.triangles = triangles;
// Reverse the normals;
Vector3[] normals = mesh.normals;
for (int i = 0; i < normals.Length; i++)
normals[i] = -normals[i];
mfNew.sharedMesh.normals = normals;
mfNew.sharedMesh.uv = mesh.uv;
mfNew.sharedMesh.uv2 = mesh.uv2;
mfNew.sharedMesh.RecalculateBounds();
// Add the same material that the original sphere used
MeshRenderer mr = goNew.AddComponent<MeshRenderer>();
Renderer gorenderer = go.GetComponent<Renderer>();
//mr.sharedMaterial = go.renderer.sharedMaterial;
mr.sharedMaterial = gorenderer.sharedMaterial;
DestroyImmediate(go);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment