Skip to content

Instantly share code, notes, and snippets.

@JLChnToZ
Created July 13, 2022 12:10
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save JLChnToZ/8929140b4bae477c0770f0656cb79646 to your computer and use it in GitHub Desktop.
Save JLChnToZ/8929140b4bae477c0770f0656cb79646 to your computer and use it in GitHub Desktop.
A simple shader for VRChat for SBS 3D video playback support with aspect ratio handling.
// Configurations
// 2D: stereoShift = float4(0, 0, 0, 0), stereoExtend = float2(1, 1)
// SBS (LR): stereoShift = float4(0, 0, 0.5, 0), stereoExtend = float2(0.5, 1)
// SBS (RL): stereoShift = float4(0.5, 0, 0, 0), stereoExtend = float2(0.5, 1)
// Over-Under (Left above): stereoShift = float4(0, 0.5, 0, 0), stereoExtend = float2(1, 0.5)
// Over-Under (Right above): stereoShift = float4(0, 0, 0, 0.5), stereoExtend = float2(1, 0.5)
// Size Mode: 0 = Stratch, 1 = Contain, 2 = Cover
float4 getVideoTexture(sampler2D videoTex, float2 uv, float4 texelSize, bool avPro, int sizeMode, float aspectRatio, float4 stereoShift, float2 stereoExtend) {
float srcAspectRatio = texelSize.y * texelSize.z * stereoExtend.x / stereoExtend.y;
if (sizeMode && abs(srcAspectRatio - aspectRatio) > 0.001) {
float2 scale = float2(aspectRatio / srcAspectRatio, srcAspectRatio / aspectRatio);
float4 scale2 = 1;
if (srcAspectRatio > aspectRatio)
scale2.zy = scale;
else
scale2.xw = scale;
float4 uv2 = (uv.xyxy - 0.5) * scale2 + 0.5;
switch (sizeMode) {
case 1: uv = uv2.xy; break;
case 2: uv = uv2.zw; break;
}
}
if (any(uv < 0 || uv > 1)) return 0;
uv = uv * stereoExtend + lerp(stereoShift.xy, stereoShift.zw, unity_StereoEyeIndex);
if (avPro) uv.y = 1 - uv.y;
float4 c = tex2Dlod(videoTex, float4(uv, 0, 0));
if (avPro) c.rgb = pow(c.rgb, 2.2);
return c;
}
float4 getVideoTexture(sampler2D videoTex, float2 uv, float4 texelSize, bool avPro, int sizeMode, float aspectRatio) {
return getVideoTexture(videoTex, uv, texelSize, avPro, sizeMode, aspectRatio, 0, 1);
}
Shader "Unlit/VideoShaderUnlit" {
Properties{
[HDR] _Color ("Color", Color) = (1,1,1,1)
[NoScaleOffset] _MainTex ("Video Texture", 2D) = "black" {}
[Toggle(_)] _IsAVProVideo ("AVPro Video", Int) = 0
[Enum(Stretch, 0, Contain, 1, Cover, 2)]
_ScaleMode ("Scale Mode", Int) = 2
_StereoShift ("Stereo Shift (XY = Left XY, ZW = Right XY)", Vector) = (0, 0, 0, 0)
_StereoExtend ("Stereo Extend (XY)", Vector) = (1, 1, 0, 0)
_AspectRatio ("Target Aspect Ratio", Float) = 1.777778
}
SubShader {
Tags {
"RenderType" = "Transparent"
"Queue" = "Transparent"
}
LOD 100
Blend One OneMinusSrcAlpha
Pass {
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
#include "./VideoShaderCommon.cginc"
struct appdata {
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
UNITY_VERTEX_INPUT_INSTANCE_ID
};
struct v2f {
float2 uv : TEXCOORD0;
float4 vertex : SV_POSITION;
UNITY_VERTEX_OUTPUT_STEREO
};
sampler2D _MainTex;
float4 _Color;
int _IsAVProVideo;
int _ScaleMode;
float _AspectRatio;
float4 _MainTex_TexelSize;
float4 _StereoShift;
float2 _StereoExtend;
v2f vert (appdata v) {
v2f o;
UNITY_SETUP_INSTANCE_ID(v);
UNITY_INITIALIZE_OUTPUT(v2f, o);
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
o.vertex = UnityObjectToClipPos(v.vertex);
o.uv = v.uv;
return o;
}
float4 frag (v2f i) : SV_Target {
UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(i);
return getVideoTexture(_MainTex, i.uv, _MainTex_TexelSize, _IsAVProVideo, _ScaleMode, _AspectRatio, _StereoShift, _StereoExtend);
}
ENDCG
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment