Skip to content

Instantly share code, notes, and snippets.

@koturn
Created May 27, 2025 19:57
Show Gist options
  • Save koturn/2626d9e33d3fc2b0ea2237c5afe6d8a3 to your computer and use it in GitHub Desktop.
Save koturn/2626d9e33d3fc2b0ea2237c5afe6d8a3 to your computer and use it in GitHub Desktop.
VRCLightVolumesのサンプルコード(Amplify Shader Editorの出力)を人間向けに読みやすくしたやつ
Shader "Light Volume Samples/Light Volume PBR"
{
Properties
{
_MainTex("Albedo", 2D) = "white" {}
_Color("Color", Color) = (1,1,1,1)
[NoScaleOffset]_MetallicGlossMap("Metal AO Smoothness", 2D) = "white" {}
_Metallic("Metallic", Range( 0 , 1)) = 0
_Glossiness("Smoothness", Range( 0 , 1)) = 1
_OcclusionStrength("AO", Range( 0 , 1)) = 1
[NoScaleOffset]_BumpMap("Normal", 2D) = "bump" {}
_BumpScale("Normal Power", Float) = 1
[HDR][NoScaleOffset]_EmissionMap("Emission Map", 2D) = "white" {}
[HDR]_EmissionColor("Emission Color", Color) = (0,0,0,1)
[Toggle(_LIGHTVOLUMES_ON)] _LightVolumes("Enable Light Volumes", Float) = 1
[Toggle(_ADDITIVEONLY_ON)] _AdditiveOnly("Additive Only", Float) = 0
[Toggle(_SPECULARS_ON)] _Speculars("Speculars", Float) = 1
[Toggle(_DOMINANTDIRSPECULARS_ON)] _DominantDirSpeculars("Dominant Dir Speculars", Float) = 0
[Enum(UnityEngine.Rendering.CullMode)]_Culling("Culling", Float) = 2
[HideInInspector] _texcoord( "", 2D ) = "white" {}
[HideInInspector] __dirty( "", Int ) = 1
}
SubShader
{
Tags{ "RenderType" = "Opaque" "Queue" = "Geometry+0" "IsEmissive" = "true" }
Cull [_Culling]
Blend SrcAlpha OneMinusSrcAlpha
CGINCLUDE
#include "UnityStandardUtils.cginc"
#include "Packages/red.sim.lightvolumes/Shaders/LightVolumes.cginc"
#include "UnityStandardBRDF.cginc"
#include "UnityPBSLighting.cginc"
#include "Lighting.cginc"
#pragma target 5.0
#pragma shader_feature_local _SPECULARS_ON
#pragma shader_feature_local _LIGHTVOLUMES_ON
#pragma shader_feature_local _ADDITIVEONLY_ON
#pragma shader_feature_local _DOMINANTDIRSPECULARS_ON
#define ASE_VERSION 19801
#ifdef UNITY_PASS_SHADOWCASTER
#undef INTERNAL_DATA
#undef WorldReflectionVector
#undef WorldNormalVector
#define INTERNAL_DATA half3 internalSurfaceTtoW0; half3 internalSurfaceTtoW1; half3 internalSurfaceTtoW2;
#define WorldReflectionVector(data,normal) reflect (data.worldRefl, half3(dot(data.internalSurfaceTtoW0,normal), dot(data.internalSurfaceTtoW1,normal), dot(data.internalSurfaceTtoW2,normal)))
#define WorldNormalVector(data,normal) half3(dot(data.internalSurfaceTtoW0,normal), dot(data.internalSurfaceTtoW1,normal), dot(data.internalSurfaceTtoW2,normal))
#endif
struct Input
{
float2 uv_texcoord;
float3 worldNormal;
INTERNAL_DATA
float3 worldPos;
};
uniform float _Culling;
uniform sampler2D _BumpMap;
uniform float _BumpScale;
uniform float4 _Color;
uniform sampler2D _MainTex;
uniform float4 _MainTex_ST;
uniform float4 _EmissionColor;
uniform sampler2D _EmissionMap;
uniform sampler2D _MetallicGlossMap;
uniform float _Metallic;
uniform float _Glossiness;
uniform float _OcclusionStrength;
void surf( Input i , inout SurfaceOutputStandard o )
{
float3 normal = UnpackScaleNormal(tex2D(_BumpMap, i.uv_texcoord), _BumpScale);
o.Normal = normal;
float2 uv_MainTex = i.uv_texcoord * _MainTex_ST.xy + _MainTex_ST.zw;
float3 albedo = (_Color.rgb * tex2D(_MainTex, uv_MainTex).rgb);
o.Albedo = albedo;
float3 worldNormal = normalize((WorldNormalVector(i, normal)));
#if !defined(_LIGHTVOLUMES_ON)
float3 L0 = float3(unity_SHAr.w, unity_SHAg.w, unity_SHAb.w);
float3 L1r = (unity_SHAr).xyz;
float3 L1g = (unity_SHAg).xyz;
float3 L1b = (unity_SHAb).xyz;
#elif defined(_ADDITIVEONLY_ON)
float3 L0 = float3(0, 0, 0);
float3 L1r = float3(0, 0, 0);
float3 L1g = float3(0, 0, 0);
float3 L1b = float3(0, 0, 0);
LightVolumeAdditiveSH(i.worldPos, /* out */ L0, /* out */ L1r, /* out */ L1g, /* out */ L1b);
#else
float3 L0 = float3(0, 0, 0);
float3 L1r = float3(0, 0, 0);
float3 L1g = float3(0, 0, 0);
float3 L1b = float3(0, 0, 0);
LightVolumeSH(i.worldPos, /* out */ L0, /* out */ L1r, /* out */ L1g, /* out */ L1b);
#endif
float3 lvEval = LightVolumeEvaluate(worldNormal, L0, L1r, L1g, L1b);
float4 texMetallic = tex2D(_MetallicGlossMap, i.uv_texcoord);
float metallic = pow(texMetallic.r * _Metallic, 2.0);
float3 indirect = (lvEval * albedo * (1.0 - metallic));
float smoothness = (texMetallic.a * _Glossiness);
float3 worldViewDir = Unity_SafeNormalize(_WorldSpaceCameraPos.xyz - i.worldPos);
float ao = lerp(1.0, texMetallic.g, _OcclusionStrength);
#if defined(_SPECULARS_ON)
#ifdef _DOMINANTDIRSPECULARS_ON
float3 specular = LightVolumeSpecularDominant(albedo, smoothness, metallic, worldNormal, worldViewDir, L0, L1r, L1g, L1b);
#else
float3 specular = LightVolumeSpecular(albedo, smoothness, metallic, worldNormal, worldViewDir, L0, L1r, L1g, L1b);
#endif
float3 indirectAndSpecular = (indirect + specular * ao) * ao;
#else
float3 indirectAndSpecular = indirect * ao;
#endif
o.Emission = (_EmissionColor.rgb * tex2D(_EmissionMap, i.uv_texcoord).rgb) + indirectAndSpecular;
o.Metallic = metallic;
o.Smoothness = smoothness;
o.Occlusion = ao;
o.Alpha = 1;
}
ENDCG
CGPROGRAM
#pragma surface surf Standard keepalpha fullforwardshadows exclude_path:deferred noambient
ENDCG
Pass
{
Name "ShadowCaster"
Tags{ "LightMode" = "ShadowCaster" }
ZWrite On
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma target 5.0
#pragma multi_compile_shadowcaster
#pragma multi_compile UNITY_PASS_SHADOWCASTER
#pragma skip_variants FOG_LINEAR FOG_EXP FOG_EXP2
#include "HLSLSupport.cginc"
#if ( SHADER_API_D3D11 || SHADER_API_GLCORE || SHADER_API_GLES || SHADER_API_GLES3 || SHADER_API_METAL || SHADER_API_VULKAN )
#define CAN_SKIP_VPOS
#endif
#include "UnityCG.cginc"
#include "Lighting.cginc"
#include "UnityPBSLighting.cginc"
struct v2f
{
V2F_SHADOW_CASTER;
float2 customPack1 : TEXCOORD1;
float4 tSpace0 : TEXCOORD2;
float4 tSpace1 : TEXCOORD3;
float4 tSpace2 : TEXCOORD4;
UNITY_VERTEX_INPUT_INSTANCE_ID
UNITY_VERTEX_OUTPUT_STEREO
};
v2f vert( appdata_full v )
{
v2f o;
UNITY_SETUP_INSTANCE_ID( v );
UNITY_INITIALIZE_OUTPUT( v2f, o );
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO( o );
UNITY_TRANSFER_INSTANCE_ID( v, o );
Input customInputData;
float3 worldPos = mul( unity_ObjectToWorld, v.vertex ).xyz;
half3 worldNormal = UnityObjectToWorldNormal( v.normal );
half3 worldTangent = UnityObjectToWorldDir( v.tangent.xyz );
half tangentSign = v.tangent.w * unity_WorldTransformParams.w;
half3 worldBinormal = cross( worldNormal, worldTangent ) * tangentSign;
o.tSpace0 = float4( worldTangent.x, worldBinormal.x, worldNormal.x, worldPos.x );
o.tSpace1 = float4( worldTangent.y, worldBinormal.y, worldNormal.y, worldPos.y );
o.tSpace2 = float4( worldTangent.z, worldBinormal.z, worldNormal.z, worldPos.z );
o.customPack1.xy = customInputData.uv_texcoord;
o.customPack1.xy = v.texcoord;
TRANSFER_SHADOW_CASTER_NORMALOFFSET( o )
return o;
}
half4 frag( v2f IN
#if !defined( CAN_SKIP_VPOS )
, UNITY_VPOS_TYPE vpos : VPOS
#endif
) : SV_Target
{
UNITY_SETUP_INSTANCE_ID( IN );
Input surfIN;
UNITY_INITIALIZE_OUTPUT( Input, surfIN );
surfIN.uv_texcoord = IN.customPack1.xy;
float3 worldPos = float3( IN.tSpace0.w, IN.tSpace1.w, IN.tSpace2.w );
half3 worldViewDir = normalize( UnityWorldSpaceViewDir( worldPos ) );
surfIN.worldPos = worldPos;
surfIN.worldNormal = float3( IN.tSpace0.z, IN.tSpace1.z, IN.tSpace2.z );
surfIN.internalSurfaceTtoW0 = IN.tSpace0.xyz;
surfIN.internalSurfaceTtoW1 = IN.tSpace1.xyz;
surfIN.internalSurfaceTtoW2 = IN.tSpace2.xyz;
SurfaceOutputStandard o;
UNITY_INITIALIZE_OUTPUT( SurfaceOutputStandard, o )
surf( surfIN, o );
#if defined( CAN_SKIP_VPOS )
float2 vpos = IN.pos;
#endif
SHADOW_CASTER_FRAGMENT( IN )
}
ENDCG
}
}
Fallback "Diffuse"
CustomEditor "AmplifyShaderEditor.MaterialInspector"
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment