Hi all,
I’ve been scratching my head on this for a few days now but couldn’t figure out what the issue is. I have a special line renderer (below). It is working perfectly fine in Editor (both Scene and Game view) but it doesn’t seem to render anything in a build (not even pink). I don’t see any errors on Logcat. Hopefully someone here would be able to point me to the right direction.
Extra context: The shader works fine in Unity 2020.1.17f1 (both build and Editor) but stopped working when I upgraded to 2021.2.8f1.
I am running Unity 2021.2.8f1 with these packages:
{
"dependencies": {
"com.unity.addressables": "1.19.15",
"com.unity.collab-proxy": "1.15.7",
"com.unity.ide.rider": "3.0.9",
"com.unity.ide.visualstudio": "2.0.12",
"com.unity.ide.vscode": "1.2.4",
"com.unity.mobile.android-logcat": "1.2.3",
"com.unity.render-pipelines.universal": "12.1.3",
"com.unity.test-framework": "1.1.29",
"com.unity.textmeshpro": "3.0.6",
"com.unity.timeline": "1.6.3",
"com.unity.ugui": "1.0.0",
"com.unity.xr.interaction.toolkit": "2.0.0-pre.7",
"com.unity.xr.management": "4.2.0",
"com.unity.xr.oculus": "1.11.0",
"com.unity.xr.openvr.standalone": "2.0.5",
"com.unity.modules.ai": "1.0.0",
"com.unity.modules.androidjni": "1.0.0",
"com.unity.modules.animation": "1.0.0",
"com.unity.modules.assetbundle": "1.0.0",
"com.unity.modules.audio": "1.0.0",
"com.unity.modules.cloth": "1.0.0",
"com.unity.modules.director": "1.0.0",
"com.unity.modules.imageconversion": "1.0.0",
"com.unity.modules.imgui": "1.0.0",
"com.unity.modules.jsonserialize": "1.0.0",
"com.unity.modules.particlesystem": "1.0.0",
"com.unity.modules.physics": "1.0.0",
"com.unity.modules.physics2d": "1.0.0",
"com.unity.modules.screencapture": "1.0.0",
"com.unity.modules.terrain": "1.0.0",
"com.unity.modules.terrainphysics": "1.0.0",
"com.unity.modules.tilemap": "1.0.0",
"com.unity.modules.ui": "1.0.0",
"com.unity.modules.uielements": "1.0.0",
"com.unity.modules.umbra": "1.0.0",
"com.unity.modules.unityanalytics": "1.0.0",
"com.unity.modules.unitywebrequest": "1.0.0",
"com.unity.modules.unitywebrequestassetbundle": "1.0.0",
"com.unity.modules.unitywebrequestaudio": "1.0.0",
"com.unity.modules.unitywebrequesttexture": "1.0.0",
"com.unity.modules.unitywebrequestwww": "1.0.0",
"com.unity.modules.vehicles": "1.0.0",
"com.unity.modules.video": "1.0.0",
"com.unity.modules.vr": "1.0.0",
"com.unity.modules.wind": "1.0.0",
"com.unity.modules.xr": "1.0.0"
}
}
Shader:
{
Properties
{
_MainTex("Albedo (RGB)", 2D) = "white" {}
}
SubShader
{
Tags {"RenderPipeline" = "UniversalPipeline" "RenderType" = "Opaque" "Queue" = "Geometry"}
HLSLINCLUDE
#pragma multi_compile_instancing
#pragma prefer_hlslcc gles
#pragma exclude_renderers d3d11_9x
// In regular graphics shaders the compute buffer support requires minimum target of 4.5
#pragma target 4.5
#pragma vertex vert
#pragma fragment frag
#include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Color.hlsl"
#include "Packages/com.unity.render-pipelines.core/ShaderLibrary/UnityInstancing.hlsl"
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl"
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/ShaderGraphFunctions.hlsl"
ENDHLSL
Pass
{
Name "Forward"
Tags { "LightMode" = "UniversalForward" }
Blend One Zero, One Zero
ZWrite On
ZTest LEqual
Offset 0 , 0
ColorMask RGBA
HLSLPROGRAM
sampler2D _MainTex;
float4x4 modelXForm;
float lineWidth;
#if SHADER_TARGET >= 45
StructuredBuffer<float3> aPositionBuffer;
StructuredBuffer<float3> bPositionBuffer;
StructuredBuffer<float3> colorBuffer;
#endif
struct VertexData
{
float4 vertex : POSITION;
float4 tangent : TANGENT;
float3 normal : NORMAL;
float4 texcoord : TEXCOORD0;
float4 texcoord1 : TEXCOORD1;
float4 texcoord2 : TEXCOORD2;
float4 texcoord3 : TEXCOORD3;
half4 color : COLOR;
UNITY_VERTEX_INPUT_INSTANCE_ID
};
struct VertexOutput
{
float4 pos : SV_POSITION;
float2 uv : TEXCOORD0;
float4 color : TEXCOORD1;
UNITY_VERTEX_INPUT_INSTANCE_ID
UNITY_VERTEX_OUTPUT_STEREO
};
VertexOutput vert(VertexData IN, uint instanceID : SV_InstanceID)
{
#if SHADER_TARGET >= 45
float3 dataA = aPositionBuffer[instanceID];
float3 dataB = bPositionBuffer[instanceID];
float3 dataColor = colorBuffer[instanceID];
#else
float3 dataA = 0;
float3 dataB = 0;
float3 dataColor = 0;
#endif
float3 xyz = IN.vertex.xyz;
float isPoint = 0.0;
// We place the instance position at point 1
float3 instancePosition = dataA;
float r = lineWidth;
// TODO comment on how this split works, what it does
// We render an instanced mesh that is two quads, one at z = 1
// The first quad we use to draw the segment between two points,
// and the second quad we use to draw the circle at the first point
if (xyz.z < 0.5)
{
// Drawing the segment
if (IN.texcoord.y > .5)
{
// The top two coordinates we place at point 2
instancePosition = dataB;
}
// Grab the vector direction between the points
float2 diff = normalize(dataB.xy - dataA.xy);
// Take the normal to that direction
float2 n = float2(-diff.y, diff.x);
// Add a scaled version of that normal in either
// direction from the instance points 1 and 2 to
// give the segment thickness
if (IN.texcoord.x > 0)
{
xyz = float3(-r * n, 0);
}
else
{
xyz = float3(r * n, 0);
}
}
else
{
// We store that this quad should be treated as a point in the fragment shader
isPoint = 1;
// We reset the z value we actually render the quad at to 0 (instead of 1)
xyz.z = 0;
// We scale the quad by the width
xyz *= r;
}
float3 worldPosition = instancePosition + xyz;
float3 worldNormal = IN.normal;
VertexOutput OUT;
// We use the passed in model world matrix to multiply against the view projection matrices
OUT.pos = mul(UNITY_MATRIX_VP, mul(modelXForm, float4(worldPosition, 1.0f)));
// We pass along our UVs (needed for circle quads)
OUT.uv = IN.texcoord.xy;
// We pass along our color with the w value specifying whether the quad is to be a circle
OUT.color = float4(dataColor, isPoint);
return OUT;
}
half4 frag(VertexOutput IN) : SV_Target
{
UNITY_SETUP_INSTANCE_ID(IN);
UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(IN);
// We use the .w component of color not for alpha as normally unused, but to
// store whether or not we treat this quad as a point (circle render)
if (IN.color.w > 0.0f)
{
// If this is the quad representing a point on the line,
// we use a radius check to see if we fill in the fragment.
// With uv values in the range [0,0] - [1,1] for a quad,
// if the radius^2 > 0.5^2 means we are outside the circle
float2 uv = IN.uv;
float dx = uv.x - 0.5f;
float dy = uv.y - 0.5f;
float d = dx * dx + dy * dy;
if (d > .25)
{
discard;
}
}
half4 OUT = half4(IN.color.xyz, 1.0f);
return OUT;
}
ENDHLSL
}
}
}
I have the shader in Graphics settings “Always Included Shaders” and I am using OpenGLES3.
I’m absolutely out of ideas on what else I should try; any help is welcome.
Thanks in advance.