#ifndef VLBCOMMON_GLSL
#define VLBCOMMON_GLSL

#ifndef VLBSHADERDEFINES_GLSL
#define VLBSHADERDEFINES_GLSL
///
/// VLB configurations
///
#ifndef VLB_ALPHA_AS_BLACK
#define VLB_ALPHA_AS_BLACK  1 // Additive or SoftAdditive
#endif

// Occlusion test using ray casting
#ifndef VLB_OCCLUSION_CLIPPING_PLANE
#define VLB_OCCLUSION_CLIPPING_PLANE 0
#endif

#ifndef VLB_DEPTH_BLEND
#define VLB_DEPTH_BLEND 1
#endif

// Perform depth test and clip in fragment shader
#ifndef VLB_PS_DEPTH_TEST
#define VLB_PS_DEPTH_TEST   1
#endif

#ifndef VLB_COLOR_GRADIENT_MATRIX
#define VLB_COLOR_GRADIENT_MATRIX 0
#endif

#ifndef VLB_MESH_SKEWING
#define VLB_MESH_SKEWING 0
#endif

#ifndef VLB_SHADER_ACCURACY_HIGH
#define VLB_SHADER_ACCURACY_HIGH 0
#endif

// Use right handed projection
#ifndef VLB_PROJECTION_RIGHT_HANDED
#define VLB_PROJECTION_RIGHT_HANDED 0
#endif

/// ****************************************
/// DEBUG
/// ****************************************
#define DEBUG_VALUE_DEPTHBUFFER 1
#define DEBUG_VALUE_DEPTHBLEND 2
// Options
#define DEBUG_DEPTH_MODE 0
#define DEBUG_BLEND_INSIDE_OUTSIDE 0

#if DEBUG_DEPTH_MODE && !VLB_DEPTH_BLEND
#undef VLB_DEPTH_BLEND
#define VLB_DEPTH_BLEND 1
#endif

/// =========================================
/// Internal states
/// =========================================

/// ****************************************
/// OPTIM
/// ****************************************
/// compute most of the intensity in VS => huge perf improvements
#if !VLB_SHADER_ACCURACY_HIGH
    #define OPTIM_VS 1
    /// when OPTIM_VS is enabled, also compute fresnel in VS => better perf,
    /// but require too much tessellation for the same quality
    #define OPTIM_VS_FRESNEL_VS 1
#else
    #define OPTIM_VS 0
    #define OPTIM_VS_FRESNEL_VS 0
#endif

/// ****************************************
/// FIXES
/// ****************************************
#define FIX_DISABLE_DEPTH_BLEND_WITH_OBLIQUE_PROJ 0
/// ****************************************


#endif /* VLBSHADERDEFINES_GLSL */

#ifndef VLBSHADERPROPERTIES_GLSL
#define VLBSHADERPROPERTIES_GLSL

#ifndef IDIOMS_GLSL
#define IDIOMS_GLSL

#define int2 ivec2
#define int3 ivec3
#define int4 ivec4

#define uint2 uvec2
#define uint3 uvec3
#define uint4 uvec4

#define half lowp float
#define half2 lowp vec2
#define half3 lowp vec3
#define half4 lowp vec4

#define float2 vec2
#define float3 vec3
#define float4 vec4

#define float2x2 mat2
#define float2x3 mat2x3
#define float2x4 mat2x4
#define float3x2 mat3x2
#define float3x3 mat3
#define float3x4 mat3x4
#define float4x2 mat4x2
#define float4x3 mat4x3
#define float4x4 mat4

#define lerp(a, b, t) mix(a, b, t)

// Note: _sat(NaN) = 0 in HLSL sematic, but GLSL the value is NaN
#define saturateGenType(genType) genType saturate(genType a) { return clamp(a, genType(0.0), genType(1.0)); }
// #define saturateGenType(genType) genType saturate(genType a) { genType x = clamp(a, genType(0.0), genType(1.0)); return lerp(x, genType(0.0), isnan(x)); }

saturateGenType(float)
saturateGenType(float3)
saturateGenType(float4)

#define mul(v, m) ((m) * (v))

#ifdef _GLSL_FS
void clip(float expr) { if(expr < 0.0) discard; }
#endif

#endif /* IDIOMS_GLSL */

#define VLB_DEFINE_PROP_START(Name)  layout(std140) uniform Name {
#define VLB_DEFINE_PROP_END };
#define VLB_DEFINE_PROP(Type, name) Type name;
#define VLB_PROP_PADDING(Type, num)

#define VLB_GET_PROP(name) name

VLB_DEFINE_PROP_START(PerFrameBuffer)

    VLB_DEFINE_PROP(float4x4, _ViewMatrix)
    VLB_DEFINE_PROP(float4x4, _ViewProjMatrix)

    VLB_DEFINE_PROP(float4, _ProjectionParams) // Clip plane params: NearPlane, FarPlane, FarPlane - NearPlane, 1.0/FarPlane
    VLB_DEFINE_PROP(float4, _WorldSpaceCameraPos)

    VLB_DEFINE_PROP(float3, _InvProjXYZ)

    /// Camera frustum plane world space equations, in this order: left, right, bottom, top, near, far.
    VLB_DEFINE_PROP(float4, _CameraWorldClipPlanes[6])

VLB_DEFINE_PROP_END

/// ****************************************
/// PROPERTIES DECLARATION
/// ****************************************
VLB_DEFINE_PROP_START(PerMaterialBuffer)

    VLB_DEFINE_PROP(float4x4, _WorldToObjectMatrix)
    VLB_DEFINE_PROP(float4x4, _ObjectToWorldMatrix)
    VLB_DEFINE_PROP(float4x4, _ViewToObjectMatrix)

    // if VLB_COLOR_GRADIENT_MATRIX
    VLB_DEFINE_PROP(float4x4, _ColorGradientMatrix)
    // else
    VLB_DEFINE_PROP(float4, _ColorFlat)
    // endif

    VLB_DEFINE_PROP(half, _AlphaInside)
    VLB_DEFINE_PROP(half, _AlphaOutside)
    // VLB_DEFINE_PROP(half, _HDRPExposureWeight)
    VLB_DEFINE_PROP(float2, _ConeSlopeCosSin)   // between -1 and +1
    VLB_DEFINE_PROP(float2, _ConeRadius)        // x = start radius ; y = end radius
    VLB_DEFINE_PROP(float2, _ConeGeomProps)    // x = apex offset z > 0 ; y = mesh sides
    VLB_DEFINE_PROP(float, _AttenuationLerpLinearQuad)
    VLB_PROP_PADDING(float3, 1)

    VLB_DEFINE_PROP(float3, _DistanceFallOff)   // fallOffStart, fallOffEnd, maxGeometryDistance
    VLB_DEFINE_PROP(float, _DistanceCamClipping)
    VLB_DEFINE_PROP(float, _FadeOutFactor)
    VLB_DEFINE_PROP(float, _FresnelPow)             // must be != 0 to avoid infinite fresnel
    VLB_DEFINE_PROP(float, _GlareFrontal)
    VLB_DEFINE_PROP(float, _GlareBehind)
    VLB_DEFINE_PROP(float, _DrawCap)
    VLB_PROP_PADDING(float, 2)
    VLB_PROP_PADDING(float2, 3)
    VLB_DEFINE_PROP(float4, _CameraParams)          // xyz: object space forward vector ; w: cameraIsInsideBeamFactor (-1 : +1)

    // if VLB_OCCLUSION_CLIPPING_PLANE
    VLB_DEFINE_PROP(float4, _DynamicOcclusionClippingPlaneWS)
    VLB_DEFINE_PROP(float,  _DynamicOcclusionClippingPlaneProps)
    // endif

    // if VLB_DEPTH_BLEND
    VLB_DEFINE_PROP(float, _DepthBlendDistance)
    // endif

    VLB_PROP_PADDING(float2, 4)

    // if VLB_MESH_SKEWING
    VLB_DEFINE_PROP(float3, _LocalForwardDirection)
    // endif

    VLB_PROP_PADDING(float, 5)

    VLB_DEFINE_PROP(float2, _TiltVector)
    VLB_PROP_PADDING(float2, 6)
    VLB_DEFINE_PROP(float4, _AdditionalClippingPlaneWS)
VLB_DEFINE_PROP_END

/// ****************************************

#endif /* VLBSHADERPROPERTIES_GLSL */

#ifndef VLBSHADERUTILS_GLSL
#define VLBSHADERUTILS_GLSL

#ifndef VLBSHADERMATHS_GLSL
#define VLBSHADERMATHS_GLSL

float lerpClamped(float a, float b, float t) { return lerp(a, b, saturate(t)); }

float isEqualOrGreater(float a, float b) { return step(b, a); }

// Get signed distance of pos from the plane (normal ; d).
// Normal should be normalized.
// If we want to disable this feature, we could set normal and d to 0 (no discard in this case).
float DistanceToPlane(float3 pos, float4 plane) { return dot(float4(pos, 1.0), plane); }

float invLerpClamped(float a, float b, float t) {
  return saturate( (t - a) / (b - a) );
}

#endif /* VLBSHADERMATHS_GLSL */

#define tex1D texture
#define tex2D texture

#define VLB_CAMERA_NEAR_PLANE _ProjectionParams.x
#define VLB_CAMERA_FAR_PLANE _ProjectionParams.y
#define VLB_CAMERA_NEAR_FAR_PLANE_RANGE _ProjectionParams.z
#define VLB_CAMERA_FAR_PLANE_INV _ProjectionParams.w // 1.0 / FarPlane

// **********************************
// Shader Specitic Builtins
// **********************************
float4 VLBObjectToWorldPos(float4 pos) { return _ObjectToWorldMatrix * pos; }
float4 VLBWorldToViewPos(float4 pos) { return _ViewMatrix * pos; }
float4 VLBWorldToClipPos(float4 pos) {  return _ViewProjMatrix * pos; }

float3 VLBGetCameraPositionObjectSpace() {
    return (_WorldToObjectMatrix * _WorldSpaceCameraPos).xyz;
}

#if VLB_DEPTH_BLEND || VLB_PS_DEPTH_TEST

#ifdef _GLSL_VS
float4 ComputeNonStereoScreenPos(float4 pos) {
    float4 o = pos * 0.5;
    o.xy     = o.xy + o.w;
    o.zw     = pos.zw;
    return o;
}

float4 ComputeScreenPos(float4 pos) {
    return ComputeNonStereoScreenPos(pos);
}

float4 DepthFade_VS_ComputeProjPos(float3 vertexViewSpace, float4 vertexClipSpace)
{
    float4 projPos = ComputeScreenPos(vertexClipSpace);

#if VLB_PROJECTION_RIGHT_HANDED
    projPos.z = -vertexViewSpace.z;
#else
    projPos.z = vertexViewSpace.z;
#endif // VLB_PROJECTION_RIGHT_HANDED

    return projPos;
}
#else // _GLSL_FS

// Nonlinear normalize depth in (0, 1) to linear depth in range (znear, zfar)
float VLB_ZBufferToLinear(float depth) {
    return VLB_CAMERA_NEAR_PLANE / ((VLB_CAMERA_FAR_PLANE - VLB_CAMERA_NEAR_FAR_PLANE_RANGE * depth) * VLB_CAMERA_FAR_PLANE_INV);
}

float VLB_ZBufferToLinear(float depth, float near, float far) {
    float alpha = 1.0 - near / far;
    return near / ( 1.0 - alpha * depth );
}

float VLB_ZBufferLinearToNoneLinear(float z01) {
    return (z01 * VLB_CAMERA_FAR_PLANE) / (VLB_CAMERA_NEAR_PLANE + z01 * VLB_CAMERA_NEAR_FAR_PLANE_RANGE);
}

float VLBSampleDepthTexture(float4 uv) {
    float depthLinear;
    float3 normalView;
    _SampleDepthNormal(uv.xy / uv.w, depthLinear, normalView);
    return depthLinear;
}

#define VLBLinearEyeDepth(depth) (VLB_CAMERA_NEAR_PLANE + VLB_CAMERA_NEAR_FAR_PLANE_RANGE * depth)

float SampleSceneZ_Eye(float4 uv)
{
    float rawDepth = VLBSampleDepthTexture(uv);
    float linearDepthPersp = VLBLinearEyeDepth(rawDepth);
    return linearDepthPersp;
}

#if VLB_DEPTH_BLEND
float DepthFade_PS_BlendDistance(float4 projPos, float distance)
{
    float screenZ = max(0.0, SampleSceneZ_Eye(projPos) - VLB_CAMERA_NEAR_PLANE);
    float partZ  = max(0.0, projPos.z - VLB_CAMERA_NEAR_PLANE);
    return saturate((screenZ - partZ) / distance);
}
#else // VLB_PS_DEPTH_TEST

void DepthTestClip(float4 uv)
{
    float bakDepth = SampleSceneZ_Eye(uv);
    clip(float(bakDepth < (VLB_CAMERA_FAR_PLANE - 0.00001) && uv.z < bakDepth) - 1.0);

    // float rawDepth = VLBSampleDepthTexture(uv);
    // float depth = gl_FragCoord.z;
    // clip(float(depth < rawDepth) - 1.0);
}

#endif // VLB_PS_DEPTH_TEST
#endif // _GLSL_FS
#endif // VLB_DEPTH_BLEND || VLB_PS_DEPTH_TEST

float ComputeAttenuation(float pixDistZ, float fallOffStart, float fallOffEnd, float lerpLinearQuad)
{
    float distFromSourceNormalized = invLerpClamped(fallOffStart, fallOffEnd, pixDistZ);

    // Almost simple linear attenuation between Fade Start and Fade End: Use smoothstep for a better fall to zero rendering
    float attLinear = smoothstep(0.0, 1.0, 1.0 - distFromSourceNormalized);

    // Unity's custom quadratic attenuation https://forum.unity.com/threads/light-attentuation-equation.16006/
    float attQuad = 1.0 / (1.0 + 25.0 * distFromSourceNormalized * distFromSourceNormalized);

    const float kAttQuadStartToFallToZero = 0.6;
    attQuad *= saturate(smoothstep(1.0, kAttQuadStartToFallToZero, distFromSourceNormalized)); // Near the light's range (fade end) we fade to 0 (because quadratic formula never falls to 0)

    return lerp(attLinear, attQuad, lerpLinearQuad);
}


#if VLB_COLOR_GRADIENT_MATRIX

float4 unpackFloat4FromFloat(const float value) {
  const float4 bitSh = float4(256.0*256.0*256.0, 256.0*256.0, 256.0, 1.0);
  const float4 bitMsk = float4(0.0, 1.0/256.0, 1.0/256.0, 1.0/256.0);
  vec4 res = fract(value * bitSh);
  res -= res.xxyz * bitMsk;
  return res;
}

float packFloat4ToFloat(const float4 value) {
  const float4 bitSh = float4(1.0/(256.0*256.0*256.0), 1.0/(256.0*256.0), 1.0/256.0, 1.0);
  return(dot(value, bitSh));
}

half4 UnpackToColor(float packedFloat)
{
    return unpackFloat4FromFloat(packedFloat);
}

float GetAtMatrixIndex(float4x4 mat, int idx) { return mat[idx % 4][idx / 4]; }

half4 DecodeGradient(float t, float4x4 colorMatrix)
{
#define kColorGradientMatrixSize 16
    float sampleIndexFloat = t * float(kColorGradientMatrixSize - 1);
    float ratioPerSample = fract(sampleIndexFloat);
    int sampleIndexInt = min(int(sampleIndexFloat), kColorGradientMatrixSize - 2);
    half4 colorA = UnpackToColor(GetAtMatrixIndex(colorMatrix, sampleIndexInt + 0));
    half4 colorB = UnpackToColor(GetAtMatrixIndex(colorMatrix, sampleIndexInt + 1));
    return lerp(colorA, colorB, ratioPerSample);
}
#endif // VLB_COLOR_GRADIENT_MATRIX


/// *****************************************
/// VLB Shader Specific Helpers
/// *****************************************

float ComputeBoostFactor(float pixDistFromSource, float outsideBeam, float isCap)
{
    pixDistFromSource = max(pixDistFromSource, 0.001); // prevent 1st segment from being boosted when boostFactor is 0
    float glareFrontal = VLB_GET_PROP(_GlareFrontal);
    float insideBoostDistance = glareFrontal * VLB_GET_PROP(_DistanceFallOff).y;
    float boostFactor = 1.0 - smoothstep(0.0, 0.0 + insideBoostDistance + 0.001, pixDistFromSource); // 0 = no boost ; 1 = max boost
    boostFactor = lerp(boostFactor, 0.0, outsideBeam); // no boost for outside pass

    float4 cameraParams = VLB_GET_PROP(_CameraParams);
    float cameraIsInsideBeamFactor = saturate(cameraParams.w); // _CameraParams.w is (-1 ; 1) 
    boostFactor = cameraIsInsideBeamFactor * boostFactor; // no boost for outside pass

    boostFactor = lerp(boostFactor, 1.0, isCap); // cap is always at max boost
    return boostFactor;
}

// boostFactor is normalized
float ComputeFresnel(float3 posObjectSpace, float3 vecCamToPixOSN, float outsideBeam, float boostFactor)
{
    // Compute normal
    float2 cosSinFlat = normalize(posObjectSpace.xy);
    float2 coneSlopeCosSin = VLB_GET_PROP(_ConeSlopeCosSin);
    float3 normalObjectSpace = (float3(cosSinFlat.x * coneSlopeCosSin.x, cosSinFlat.y * coneSlopeCosSin.x, -coneSlopeCosSin.y));
    normalObjectSpace *= (outsideBeam * 2.0 - 1.0); // = outsideBeam ? 1 : -1;

    // real fresnel factor
    float fresnelReal = dot(normalObjectSpace, -vecCamToPixOSN);

    // compute a fresnel factor to support long beams by projecting the viewDir vector
    // on the virtual plane formed by the normal and tangent
    float coneApexOffsetZ = VLB_GET_PROP(_ConeGeomProps).x;
    float3 tangentPlaneNormal = normalize(posObjectSpace.xyz + float3(0, 0, coneApexOffsetZ));
    float distToPlane = dot(-vecCamToPixOSN, tangentPlaneNormal);
    float3 vec2D = normalize(-vecCamToPixOSN - distToPlane * tangentPlaneNormal);
    float fresnelProjOnTangentPlane = dot(normalObjectSpace, vec2D);

    // blend between the 2 fresnels
    float3 localForwardDirN = VLB_GET_PROP(_LocalForwardDirection);
    float vecCamToPixDotZ = dot(vecCamToPixOSN, localForwardDirN);
    float factorNearAxisZ = abs(vecCamToPixDotZ); // factorNearAxisZ is normalized

    float fresnel = lerp(fresnelProjOnTangentPlane, fresnelReal, factorNearAxisZ);

    float fresnelPow = VLB_GET_PROP(_FresnelPow);

    // Lerp the fresnel pow to the glare factor according to how far we are from the axis Z
    const float kMaxGlarePow = 1.5;
    float glareFrontal = VLB_GET_PROP(_GlareFrontal);
    float glareBehind = VLB_GET_PROP(_GlareBehind);
    float glareFactor = kMaxGlarePow * (1.0 - lerp(glareFrontal, glareBehind, outsideBeam));
    fresnelPow = lerp(fresnelPow, min(fresnelPow, glareFactor), factorNearAxisZ);
    
    // Pow the fresnel
    fresnel = smoothstep(0.0, 1.0, fresnel);
    fresnel = (1.0 - isEqualOrGreater(-fresnel, 0.0)) * // fix edges artefacts on android ES2
              (pow(fresnel, fresnelPow));

    // Boost distance inside
    float boostFresnel = lerp(fresnel, 1.0 + 0.001, boostFactor);
    fresnel = lerp(boostFresnel, fresnel, outsideBeam); // no boosted fresnel if outside

    // We do not have to treat cap a special way, since boostFactor is already set to 1 for cap via ComputeBoostFactor
    
    return fresnel;
}

float ComputeFadeWithCamera(float3 posViewSpace, float enabled)
{
    float distCamToPixWS = abs(posViewSpace.z); // only check Z axis (instead of length(posViewSpace.xyz)) to have smoother transition with near plane (which is not curved)
    float camFadeDistStart = VLB_CAMERA_NEAR_PLANE; // cam near place
    float camFadeDistEnd = camFadeDistStart + VLB_GET_PROP(_DistanceCamClipping);
    float fadeWhenTooClose = smoothstep(0.0, 1.0, invLerpClamped(camFadeDistStart, camFadeDistEnd, distCamToPixWS));

    // fade out according to camera's near plane
    return lerp(1.0, fadeWhenTooClose, enabled);
}

half4 ComputeColor(float pixDistFromSource, float outsideBeam)
{
#if VLB_COLOR_GRADIENT_MATRIX
    float distanceFadeEnd = VLB_GET_PROP(_DistanceFallOff).y;
    float4x4 colorGradientMatrix = VLB_GET_PROP(_ColorGradientMatrix);
    float distFromSourceNormalized = invLerpClamped(0.0, distanceFadeEnd, pixDistFromSource);
    half4 color = DecodeGradient(distFromSourceNormalized, colorGradientMatrix);
#else
    half4 color = VLB_GET_PROP(_ColorFlat);
#endif

    half alphaInside  = VLB_GET_PROP(_AlphaInside);
    half alphaOutside = VLB_GET_PROP(_AlphaOutside);
    half alpha = lerp(alphaInside, alphaOutside, outsideBeam);
#if VLB_ALPHA_AS_BLACK
    color.rgb *= color.a;
    color.rgb *= alpha;
#else
    color.a *= alpha;
#endif

    return color;
}

float ComputeInOutBlending(float vecCamToPixDotZ, float outsideBeam)
{
    // smooth blend between inside and outside geometry depending of View Direction
    const float kFaceLightSmoothingLimit = 1.0;

    float factorFaceLightSourcePerPixN = saturate(smoothstep(kFaceLightSmoothingLimit, -kFaceLightSmoothingLimit, vecCamToPixDotZ)); // smoother transition

    return lerp(factorFaceLightSourcePerPixN, 1.0 - factorFaceLightSourcePerPixN, outsideBeam);
}

#if VLB_MESH_SKEWING
float4 SkewVectorOS(float4 vec)
{
    float3 localForwardDirN = VLB_GET_PROP(_LocalForwardDirection);
    vec.xy += vec.z * localForwardDirN.xy / (localForwardDirN.z);
    return vec;
}

float3 UnskewVectorOS(float3 vec)
{
    float3 localForwardDirN = VLB_GET_PROP(_LocalForwardDirection);
    vec.xy -= localForwardDirN.xy * (vec.z / localForwardDirN.z);
    return vec;
}
#endif // VLB_MESH_SKEWING

// Vector Camera to current Pixel, in object space and normalized
float3 ComputeVectorCamToPixOSN(float3 pixPosOS, float3 cameraPosOS)
{
    float3 vecCamToPixOSN = normalize(pixPosOS - cameraPosOS);

    // Deal with ortho camera:
    // With ortho camera, we don't want to change the fresnel according to camera position.
    // So instead of computing the proper vector "Camera to Pixel", we take account of the "Camera Forward" vector (which is not dependant on the pixel position)
    // float4 cameraParams = VLB_GET_PROP(_CameraParams);
    // float3 vecCamForwardOSN = cameraParams.xyz;

// #if VLB_MESH_SKEWING
    // vecCamForwardOSN = normalize(UnskewVectorOS(vecCamForwardOSN));
// #endif // VLB_MESH_SKEWING

    return vecCamToPixOSN;
}

float GetTiltDistanceFactor(float3 posObjectSpace)
{
    float2 tiltVector = VLB_GET_PROP(_TiltVector);
    float pixDistFromSource = abs(posObjectSpace.z);
    return pixDistFromSource + posObjectSpace.x * tiltVector.x + posObjectSpace.y * tiltVector.y;
}

#endif /* VLBSHADERUTILS_GLSL */

#ifndef VLBSHADERINPUTOUTPUT_GLSL
#define VLBSHADERINPUTOUTPUT_GLSL

#ifdef _GLSL_VS

#define IN_ATTRIB_MODIFIER in
#define ATTRIB_MODIFIER out

/// **********************************
/// VS INPUT BEGIN
/// **********************************
// uv is packed into w component of packedPosition
// u indicate 'isCap', v indicate 'outsideBeam'
IN_ATTRIB_MODIFIER float4 packedPosition;

float2 unpackFloatToBool2(const float value) {
    const float2 bitSh = float2(1.0, 2.0);
    const float2 bitMsk = float2(0.5, 0.0);
    float2 res = fract(value * bitSh);
    res -= res.yy * bitMsk;
    return step(float2(0.5), res);
}

/// **********************************
/// VS INPUT END
/// **********************************
#endif

#ifdef _GLSL_FS
#define ATTRIB_MODIFIER in
#endif

/// **********************************
/// VS OUTPUT BEGIN
/// **********************************
#if VLB_MESH_SKEWING
    ATTRIB_MODIFIER float3 vs_posObjectSpace;
#else
    #define vs_posObjectSpace vs_posObjectSpaceNonSkewed
#endif // VLB_MESH_SKEWING
ATTRIB_MODIFIER float3 vs_posObjectSpaceNonSkewed;

ATTRIB_MODIFIER float4 vs_posWorldSpace;
ATTRIB_MODIFIER float4 vs_posViewSpace_extraData;
ATTRIB_MODIFIER float4 vs_camPosObjectSpace_outsideBeam;

#if OPTIM_VS
    ATTRIB_MODIFIER half4 vs_color;
#endif

#if OPTIM_VS
    ATTRIB_MODIFIER float vs_intensity;
#endif

#if VLB_DEPTH_BLEND || VLB_PS_DEPTH_TEST
    ATTRIB_MODIFIER float4 vs_projPos;
#endif
/// **********************************
/// VS OUTPUT END
/// **********************************

#ifdef _GLSL_FS
/// **********************************
/// FS OUTPUT BEGIN
/// **********************************
    out float4 fs_color;
#endif
/// **********************************
/// FS OUTPUT END
/// **********************************

#endif /* VLBSHADERINPUTOUTPUT_GLSL */


#endif /* VLBCOMMON_GLSL */
