Created
February 6, 2026 09:50
-
-
Save cnlohr/8d28a0768ad53eb81b1561c776d51b0a to your computer and use it in GitHub Desktop.
Example geometry shader running in Unity on Quest.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Shader "Unlit/QuestGEO" | |
| { | |
| Properties | |
| { | |
| } | |
| SubShader | |
| { | |
| Tags { "RenderType"="Opaque" } | |
| Pass | |
| { | |
| GLSLPROGRAM | |
| #version 320 es | |
| // See discussion here https://discussions.unity.com/t/geometry-shaders-in-opengl-multiview/911294 | |
| // It's not "perfect" | |
| #ifdef STEREO_INSTANCING_ON | |
| // Not used. | |
| #extension GL_NV_viewport_array2 : enable | |
| #extension GL_AMD_vertex_shader_layer : enable | |
| #extension GL_ARB_fragment_layer_viewport : enable | |
| #endif | |
| // ON QUEST, STEREO_MULTIVIEW_ON is enabled. | |
| #ifdef STEREO_MULTIVIEW_ON | |
| #extension GL_EXT_multiview_tessellation_geometry_shader : enable | |
| #extension GL_OVR_multiview2 : enable | |
| #endif | |
| #include "UnityCG.glslinc" | |
| #include "UnityStereoSupport.glslinc" | |
| #pragma vertex vert | |
| #pragma fragment frag | |
| #pragma geometry geo | |
| #ifdef VERTEX | |
| in vec2 in_TEXCOORD0; | |
| in vec4 in_POSITION0; | |
| out VS_OUT { | |
| vec2 ouv; | |
| float eye; | |
| } vs_out; | |
| uniform OVR_multiview | |
| { | |
| uint _ViewID; | |
| uint numViews_2; | |
| }; | |
| layout(std140) uniform UnityStereoEyeIndices { | |
| vec4 unity_StereoEyeIndices[2]; | |
| }; | |
| void main () | |
| { | |
| vs_out.ouv = in_TEXCOORD0; | |
| vs_out.eye = 0.0; | |
| //vs_out.eye = float(gl_ViewID); | |
| //vs_out.eye = float(_ViewID); // Always 0. | |
| //vs_out.eye = float(gl_InstanceID); // Always 0. | |
| //vs_out.eye = float(unity_StereoEyeIndices[gl_ViewID_OVR].x); // Flashes back and forth, just as gl_ViewID_OVR is random. | |
| //vs_out.eye = float(gl_ViewID_OVR&uint(1)); // view ID is kinda random. | |
| //vs_out.eye = float(unity_StereoEyeIndex); // Always 0 | |
| gl_Position = in_POSITION0; | |
| } | |
| #endif | |
| #ifdef GEOMETRY | |
| layout(triangles) in; | |
| layout(triangle_strip, max_vertices=6) out; | |
| /* | |
| out gl_PerVertex { | |
| vec4 gl_Position; | |
| float gl_PointSize; | |
| float gl_ClipDistance[]; | |
| }; | |
| */ | |
| in VS_OUT { | |
| vec2 ouv; | |
| float eye; | |
| } gs_in[]; | |
| out vec2 ouvf; | |
| layout(num_views = 2) in; | |
| // For now, each invocation outputs a triangle to each eye. | |
| void main() | |
| { | |
| int eyeid = 0; | |
| #if defined(STEREO_MULTIVIEW_ON) || defined(STEREO_INSTANCING_ON) | |
| for( eyeid = 0; eyeid < 2; eyeid++ ) | |
| //eyeid = int(gs_in[0].eye); // If testing the input instance ID code, uncomment this, and comment out the above line. | |
| #endif | |
| { | |
| #if defined(STEREO_MULTIVIEW_ON) || defined(STEREO_INSTANCING_ON) | |
| mat4 stereoVP = unity_StereoMatrixVP[eyeid]; | |
| #else | |
| mat4 stereoVP = unity_MatrixVP; | |
| #endif | |
| for(int i=0; i<3; i++) | |
| { | |
| gl_Position = stereoVP * unity_ObjectToWorld * gl_in[i].gl_Position; | |
| vec2 o = vec2( gs_in[i].ouv ); | |
| gl_Layer = eyeid; | |
| ouvf = o; | |
| EmitVertex(); | |
| } | |
| EndPrimitive(); | |
| } | |
| } | |
| #endif | |
| #ifdef FRAGMENT | |
| in vec2 ouvf; | |
| layout (location = 0) out vec4 color; | |
| void main() | |
| { | |
| color = vec4( mod((ouvf *10.0), 1.0), .1, 1.0 ); | |
| } | |
| #endif | |
| ENDGLSL | |
| } | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment