I just started using the foundation framework to see how it works out. During testing I wondered how to use a proper linear camera background shader instead of the default one. Seems like the background image is to bright when setting the player settings to linear. I tried to plug the arkit camera shader into a material and use this as override, but this gives me black background. Is there a sample shader available that will work?
I'm using AR Foundation version 1.0.0-preview.17 and ARKit XR Plugin version 1.0.0-preview.13. Here's the solution I'm using. Create a new shader by coping the shader code from Packages/ARKit XR Plugin/Runtime/iOS/Resource/ARKitShader. Change this line (near the end of the file): Code (CSharp): return mul(ycbcrToRGBTransform, ycbcr); ...to this... Code (CSharp): return pow(mul(ycbcrToRGBTransform, ycbcr), 2.2); Then create a new material that uses that shader and assign that material to your AR Camera's "AR Camera Background" component's "Custom Material" property.
@Krxtopher Thanks for that hint. But how would I do this if I have to support both Android and iOS? (I am looking for a way to create my own custom shader to dim the background video programmatically. If there's any other way to do this, I would be happy to know about it.)
Hey guys, I'm having troubles with that. I have tried with this solution (https://github.com/Unity-Technologies/arfoundation-samples/issues/46) and this other (https://github.com/google-ar/arcore-unity-sdk/issues/268) but stills, everytime I launch the android app I get a black screen from the begining, it doesnt even load the Unity splash screen. :/ I have checked on LogCat and I'm getting this error: [EGL] Failed to create window surface: EGL_BAD_MATCH: Arguments are inconsitent (for example, a valid context requires buffers not supplied by a valid surface) Do you guys have any idea of what might be it or what I might be doing wrong? Thanks
Just in case anyone else is facing this problem, we fixed it enabling on "ProjectSettings/Resolution and Presentation" the checkbox "Use 32-bit Display Buffer" (Unity 2018.2.14)
Hi all, to support linear color space for android and ios you need a script to do the job and two materials with a dedicated shader for ARCore and ARKit (as @tdmowrer suggested). you can use this script. attach it to the game object where your ARCameraBackground script resides in your AR scene. Code (CSharp): // // // purpose: set camera background material depending on platform used // // // author: ge // // (c) 2019 innovation.rocks consulting gmbh // using UnityEngine; using UnityEngine.XR.ARFoundation; [RequireComponent(typeof(ARCameraBackground))] public class ARCameraPlatformBackground : MonoBehaviour { public Material _ARCoreBackground; public Material _ARKitBackground; void Start () { ARCameraBackground arcbg = GetComponent<ARCameraBackground> (); arcbg.useCustomMaterial = true; #if UNITY_IOS arcbg.customMaterial = _ARKitBackground; #else arcbg.customMaterial = _ARCoreBackground; #endif } } make two materials for ARCore and ARKit with the following shaders attached ARCore Shader Code (CSharp): Shader "inr/AR/ARCore Background Linear" { Properties { _MainTex ("Texture", 2D) = "white" {} _UvTopLeftRight ("UV of top corners", Vector) = (0, 1, 1, 1) _UvBottomLeftRight ("UV of bottom corners", Vector) = (0 , 0, 1, 0) _Gamma("Gamma", Float) = 2.2 } // For GLES3 SubShader { Pass { ZWrite Off GLSLPROGRAM #pragma only_renderers gles3 #ifdef SHADER_API_GLES3 #extension GL_OES_EGL_image_external_essl3 : require #endif uniform vec4 _UvTopLeftRight; uniform vec4 _UvBottomLeftRight; #ifdef VERTEX varying vec2 textureCoord; void main() { #ifdef SHADER_API_GLES3 vec2 uvTop = mix(_UvTopLeftRight.xy, _UvTopLeftRight.zw, gl_MultiTexCoord0.x); vec2 uvBottom = mix(_UvBottomLeftRight.xy, _UvBottomLeftRight.zw, gl_MultiTexCoord0.x); textureCoord = mix(uvTop, uvBottom, gl_MultiTexCoord0.y); gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex; #endif } #endif #ifdef FRAGMENT varying vec2 textureCoord; uniform samplerExternalOES _MainTex; uniform float _Gamma; void main() { #ifdef SHADER_API_GLES3 vec4 color = texture(_MainTex, textureCoord); color.rgb = pow(color.rgb, vec3(_Gamma, _Gamma, _Gamma)); color.rgb = clamp(color.rgb, 0.0, 0.996); gl_FragColor = color; #endif } #endif ENDGLSL } } Subshader { Pass { ZWrite Off CGPROGRAM #pragma exclude_renderers gles3 #pragma vertex vert #pragma fragment frag #include "UnityCG.cginc" uniform float4 _UvTopLeftRight; uniform float4 _UvBottomLeftRight; uniform float _Gamma; struct appdata { float4 vertex : POSITION; float2 uv : TEXCOORD0; }; struct v2f { float2 uv : TEXCOORD0; float4 vertex : SV_POSITION; }; v2f vert(appdata v) { float2 uvTop = lerp(_UvTopLeftRight.xy, _UvTopLeftRight.zw, v.uv.x); float2 uvBottom = lerp(_UvBottomLeftRight.xy, _UvBottomLeftRight.zw, v.uv.x); v2f o; o.vertex = UnityObjectToClipPos(v.vertex); o.uv = lerp(uvTop, uvBottom, v.uv.y); // Instant preview's texture is transformed differently. o.uv = o.uv.yx; o.uv.x = 1.0 - o.uv.x; return o; } sampler2D _MainTex; fixed4 frag(v2f i) : SV_Target { fixed4 color = tex2D(_MainTex, i.uv); color.rgb = pow(color.rgb, _Gamma); color.rgb = clamp(color.rgb, 0.0, 0.996); return color; } ENDCG } } FallBack Off } ARKit Shader Code (CSharp): Shader "inr/AR/ARKit Background Linear" { Properties { _textureY ("TextureY", 2D) = "white" {} _textureCbCr ("TextureCbCr", 2D) = "black" {} _Gamma("Gamma", Float) = 2.2 } SubShader { Cull Off Tags { "RenderType"="Opaque" } LOD 100 Pass { ZWrite Off CGPROGRAM #pragma vertex vert #pragma fragment frag #include "UnityCG.cginc" float4x4 _UnityDisplayTransform; struct Vertex { float4 position : POSITION; float2 texcoord : TEXCOORD0; }; struct TexCoordInOut { float4 position : SV_POSITION; float2 texcoord : TEXCOORD0; }; TexCoordInOut vert (Vertex vertex) { TexCoordInOut o; o.position = UnityObjectToClipPos(vertex.position); float texX = vertex.texcoord.x; float texY = vertex.texcoord.y; o.texcoord.x = (_UnityDisplayTransform[0].x * texX + _UnityDisplayTransform[1].x * (texY) + _UnityDisplayTransform[2].x); o.texcoord.y = (_UnityDisplayTransform[0].y * texX + _UnityDisplayTransform[1].y * (texY) + (_UnityDisplayTransform[2].y)); return o; } // samplers sampler2D _textureY; sampler2D _textureCbCr; float _Gamma; fixed4 frag (TexCoordInOut i) : SV_Target { // sample the texture float2 texcoord = i.texcoord; float y = tex2D(_textureY, texcoord).r; float4 ycbcr = float4(y, tex2D(_textureCbCr, texcoord).rg, 1.0); const float4x4 ycbcrToRGBTransform = float4x4( float4(1.0, +0.0000, +1.4020, -0.7010), float4(1.0, -0.3441, -0.7141, +0.5291), float4(1.0, +1.7720, +0.0000, -0.8860), float4(0.0, +0.0000, +0.0000, +1.0000) ); float4 color = mul(ycbcrToRGBTransform, ycbcr); color.rgb = pow(color.rgb, float3 (_Gamma, _Gamma, _Gamma)); return color; } ENDCG } } } enjoy the beauty of linear color space...
First of all, thank you very much for that! But when I use your ARCore Shader my Camera has a wrong orientation in Portrait mode. In Landscape mode everything works fine but as soon as I flip my phone to Portrait mode the camera still stays in landscape and stretches the picture to portrait. Any solution for that?
I am having the same problem that SilverBugi said. It only works on "Lanscape Left" Oriantation, other orientations show incorrect camera behaviour. But also I have another problem, the detected planes are wrong, when you detect the plane and then move the camera the plane moves like if it has wrong transform values. I mean, like if the plane is far that it should be. Any solution?
@SilverBugi I found a solution for Android. I duplicate the ARCore Shader inside packages\packages.unity.com\com.unity.xr.arcore@1.0.0-preview.23\Runtime\Android\Resources\ARCoreShader.shader And just add this line of code at the end of the line 48. Source: https://github.com/google-ar/arcore-unity-sdk/issues/268 //gamma to linear conversion gl_FragColor.rgb = pow(gl_FragColor.rgb, vec3(2.2));
ARCore Background Linear - Portrait. Code (CSharp): Shader "ALEXWICK/ARCore/ARBackground(Linear)" { Properties { _MainTex ("Texture", 2D) = "white" {} _UvTopLeftRight ("UV of top corners", Vector) = (0, 1, 1, 1) _UvBottomLeftRight ("UV of bottom corners", Vector) = (0 , 0, 1, 0) } // For GLES3 SubShader { Pass { ZWrite Off GLSLPROGRAM #pragma only_renderers gles3 #ifdef SHADER_API_GLES3 #extension GL_OES_EGL_image_external_essl3 : require #endif uniform vec4 _UvTopLeftRight; uniform vec4 _UvBottomLeftRight; #ifdef VERTEX varying vec2 textureCoord; void main() { #ifdef SHADER_API_GLES3 vec2 uvTop = mix(_UvTopLeftRight.zy, _UvTopLeftRight.xw, gl_MultiTexCoord0.y); vec2 uvBottom = mix(_UvBottomLeftRight.zy, _UvBottomLeftRight.xw, gl_MultiTexCoord0.y); textureCoord = mix(uvTop, uvBottom, gl_MultiTexCoord0.x); gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex; #endif } #endif #ifdef FRAGMENT varying vec2 textureCoord; uniform samplerExternalOES _MainTex; void main() { #ifdef SHADER_API_GLES3 gl_FragColor = texture(_MainTex, textureCoord); //gamma to linear conversion gl_FragColor.rgb = pow(gl_FragColor.rgb, vec3(2.2)); #endif } #endif ENDGLSL } } Subshader { Pass { ZWrite Off CGPROGRAM #pragma exclude_renderers gles3 #pragma vertex vert #pragma fragment frag #include "UnityCG.cginc" uniform float4 _UvTopLeftRight; uniform float4 _UvBottomLeftRight; struct appdata { float4 vertex : POSITION; float2 uv : TEXCOORD0; }; struct v2f { float2 uv : TEXCOORD0; float4 vertex : SV_POSITION; }; v2f vert(appdata v) { float2 uvTop = lerp(_UvTopLeftRight.zy, _UvTopLeftRight.xw, v.uv.y); float2 uvBottom = lerp(_UvBottomLeftRight.zy, _UvBottomLeftRight.xw, v.uv.y); v2f o; o.vertex = UnityObjectToClipPos(v.vertex); o.uv = lerp(uvTop, uvBottom, v.uv.x); // Instant preview's texture is transformed differently. o.uv = o.uv.yx; //o.uv.x = 1.0 - o.uv.x; //o.uv.y = 1.0 - o.uv.y; return o; } sampler2D _MainTex; fixed4 frag(v2f i) : SV_Target { return tex2D(_MainTex, i.uv); } ENDCG } } FallBack Off }