From 38e51e4a5f6f35c658df10f6d48a33e3ffaea2f3 Mon Sep 17 00:00:00 2001
From: Sven Gothel
+ <-------------left eye------------->| |<-----------right eye-------------->
+ <------------------------------------screenSizeInMeters.Width----------------------------------->
+ <------interpupillaryDistanceInMeters------>
+ <--centerFromLeftInMeters->
+ ^
+ center of pupil
+ *
+ *
+ * @param screenWidthInMeters
+ * @param interpupillaryDistanceInMeters
+ */
+ public static float[] getHorizPupilCenterFromLeft(final float screenWidthInMeters, final float interpupillaryDistanceInMeters) {
+ final float visibleWidthOfOneEye = 0.5f * screenWidthInMeters;
+ final float leftPupilCenterFromLeftInMeters = ( screenWidthInMeters - interpupillaryDistanceInMeters ) * 0.5f;
+ final float rightPupilCenterFromMiddleInMeters = leftPupilCenterFromLeftInMeters + interpupillaryDistanceInMeters - visibleWidthOfOneEye;
+ return new float[] { leftPupilCenterFromLeftInMeters / visibleWidthOfOneEye,
+ rightPupilCenterFromMiddleInMeters / visibleWidthOfOneEye };
+ }
+
+ private void init() {
+ final float[] eyeReliefInMeters = new float[defaultEyeParam.length];
+ if( 0 < defaultEyeParam.length ) {
+ eyeReliefInMeters[0] = defaultEyeParam[0].eyeReliefZ;
+ }
+ if( 1 < defaultEyeParam.length ) {
+ eyeReliefInMeters[1] = defaultEyeParam[1].eyeReliefZ;
+ }
+ if( null != distortionMeshProducer ) {
+ distortionMeshProducer.init(this, eyeReliefInMeters);
+ }
+ }
+
+ @Override
+ public String toString() { return "StereoConfig["+name+", shutter "+shutterType+", surfaceSize "+surfaceSizeInPixels+
+ ", screenSize "+screenSizeInMeters[0]+" x "+screenSizeInMeters[0]+
+ " [m], eyeTexSize "+eyeTextureSize+", IPD "+interpupillaryDistanceInMeters+
+ " [m], eyeParam "+Arrays.toString(defaultEyeParam)+
+ ", distortionBits[supported ["+StereoUtil.distortionBitsToString(supportedDistortionBits)+
+ "], recommended ["+StereoUtil.distortionBitsToString(recommendedDistortionBits)+
+ "], minimum ["+StereoUtil.distortionBitsToString(minimumDistortionBits)+"]]]";
+ }
+
+ /** Configuration Name */
+ public final String name;
+ public final ShutterType shutterType;
+
+ public final DimensionImmutable surfaceSizeInPixels;
+ public final float[] screenSizeInMeters;
+ /** Texture size per eye */
+ public final DimensionImmutable eyeTextureSize;
+
+ /** Vertical distance from pupil to screen-top in meters */
+ public final float pupilCenterFromScreenTopInMeters;
+ /** Horizontal interpupillary distance (IPD) in meters */
+ public final float interpupillaryDistanceInMeters;
+ /**
+ * Pupil center from top left per eye, ranging from [0..1], maybe used to produce FovHVHalves,
+ * see {@link #getHorizPupilCenterFromLeft(float, float)} and {@link #getVertPupilCenterFromTop(float, float)}.
+ */
+ public final float[/*per-eye*/][/*xy*/] pupilCenterFromTopLeft;
+ public final int[] eyeRenderOrder;
+ public final EyeParameter[] defaultEyeParam;
+ public final DistortionMesh.Producer distortionMeshProducer;
+
+ public final int supportedDistortionBits;
+ public final int recommendedDistortionBits;
+ public final int minimumDistortionBits;
+ }
+
+ /** A mono view configuration, only one eye is supported */
+ public static final Config config01Mono01;
+
+ /** A default stereo SBS view configuration */
+ public static final Config config02StereoSBS01;
+
+ /** A default stereo SBS lense view configuration, utilizing similar settings as OculusVR DK1 */
+ public static final Config config03StereoSBSLense01;
+
+ private static final Config[] configs;
+
+ static {
+ final float[] DEFAULT_EYE_POSITION_OFFSET_STEREO_LENSES = { 0.0f, 1.6f, -5.0f }; // 1.6 up, 5 forward
+ final float[] DEFAULT_EYE_POSITION_OFFSET_STEREO = { 0.0f, 0.3f, 3.0f }; // 0.3 up, 3 back
+ final float[] DEFAULT_EYE_POSITION_OFFSET_MONO = { 0.0f, 0.0f, 3.0f }; // 3 back
+
+ final float d2r = FloatUtil.PI / 180.0f;
+ {
+ config01Mono01 = new Config(
+ "Def01Mono01",
+ ShutterType.RollingTopToBottom,
+ new Dimension(1280, 800), // resolution
+ new float[] { 0.1498f, 0.0936f }, // screenSize [m]
+ new Dimension(1280, 800), // eye textureSize
+ 0.0936f/2f, // pupilCenterFromScreenTop [m]
+ 0.0635f, // IPD [m]
+ new int[] { 0 }, // eye order
+ new EyeParameter[] {
+ new EyeParameter(0, DEFAULT_EYE_POSITION_OFFSET_MONO,
+ // degrees: 45/2 l, 45/2 r, 45/2 * aspect t, 45/2 * aspect b
+ FovHVHalves.byFovyRadianAndAspect(45f*d2r, 1280f / 800f),
+ 0f /* distNoseToPupil */, 0f /* verticalDelta */, 0f /* eyeReliefInMeters */) },
+ null, // mash producer distortion bits
+ 0, // supported distortion bits
+ 0, // recommended distortion bits
+ 0 // minimum distortion bits
+ );
+ }
+
+ {
+ final DimensionImmutable surfaceSizeInPixel = new Dimension(1280, 800);
+ final float[] screenSizeInMeters = new float[] { 0.1498f, 0.0936f };
+ final float interpupillaryDistanceInMeters = 0.0635f;
+ final float pupilCenterFromScreenTopInMeters = screenSizeInMeters[1] / 2f;
+ final float[] horizPupilCenterFromLeft = Config.getHorizPupilCenterFromLeft(screenSizeInMeters[0], interpupillaryDistanceInMeters);
+ final float vertPupilCenterFromTop = Config.getVertPupilCenterFromTop(screenSizeInMeters[1], pupilCenterFromScreenTopInMeters);
+ final float fovy = 45f;
+ final float aspect = ( surfaceSizeInPixel.getWidth() / 2.0f ) / surfaceSizeInPixel.getHeight();
+ final FovHVHalves defaultSBSEyeFovLeft = FovHVHalves.byFovyRadianAndAspect(fovy * d2r, vertPupilCenterFromTop, aspect, horizPupilCenterFromLeft[0]);
+ final FovHVHalves defaultSBSEyeFovRight = FovHVHalves.byFovyRadianAndAspect(fovy * d2r, vertPupilCenterFromTop, aspect, horizPupilCenterFromLeft[1]);
+
+ config02StereoSBS01 = new Config(
+ "Def02StereoSBS01",
+ ShutterType.RollingTopToBottom,
+ surfaceSizeInPixel, // resolution
+ screenSizeInMeters, // screenSize [m]
+ new Dimension(1280/2, 800), // eye textureSize
+ 0.0936f/2f, // pupilCenterFromScreenTop [m]
+ interpupillaryDistanceInMeters, // IPD [m]
+ new int[] { 0, 1 }, // eye order
+ new EyeParameter[] {
+ new EyeParameter(0, DEFAULT_EYE_POSITION_OFFSET_STEREO, defaultSBSEyeFovLeft,
+ 0.032f /* distNoseToPupil */, 0f /* verticalDelta */, 0.010f /* eyeReliefInMeters */),
+ new EyeParameter(1, DEFAULT_EYE_POSITION_OFFSET_STEREO, defaultSBSEyeFovRight,
+ -0.032f /* distNoseToPupil */, 0f /* verticalDelta */, 0.010f /* eyeReliefInMeters */) },
+ null, // mash producer distortion bits
+ 0, // supported distortion bits
+ 0, // recommended distortion bits
+ 0 // minimum distortion bits
+ );
+ }
+
+ {
+ DistortionMesh.Producer lenseDistMeshProduce = null;
+ try {
+ lenseDistMeshProduce =
+ (DistortionMesh.Producer)
+ ReflectionUtil.createInstance("jogamp.opengl.oculusvr.stereo.lense.DistortionMeshProducer", GenericStereoDevice.class.getClassLoader());
+ } catch (final Throwable t) {
+ if(StereoDevice.DEBUG) { System.err.println("Caught: "+t.getMessage()); t.printStackTrace(); }
+ }
+
+ final DimensionImmutable surfaceSizeInPixel = new Dimension(1280, 800);
+ final float[] screenSizeInMeters = new float[] { 0.1498f, 0.0936f };
+ final DimensionImmutable eyeTextureSize = new Dimension(1122, 1553);
+ final float interpupillaryDistanceInMeters = 0.0635f;
+ final float pupilCenterFromScreenTopInMeters = screenSizeInMeters[1] / 2f;
+ final float[] horizPupilCenterFromLeft = Config.getHorizPupilCenterFromLeft(screenSizeInMeters[0], interpupillaryDistanceInMeters);
+ final float vertPupilCenterFromTop = Config.getVertPupilCenterFromTop(screenSizeInMeters[1], pupilCenterFromScreenTopInMeters);
+ final float fovy = 129f;
+ final float aspect = eyeTextureSize.getWidth() / eyeTextureSize.getHeight();
+ final FovHVHalves defaultSBSEyeFovLenseLeft = FovHVHalves.byFovyRadianAndAspect(fovy * d2r, vertPupilCenterFromTop, aspect, horizPupilCenterFromLeft[0]);
+ final FovHVHalves defaultSBSEyeFovLenseRight = FovHVHalves.byFovyRadianAndAspect(fovy * d2r, vertPupilCenterFromTop, aspect, horizPupilCenterFromLeft[1]);
+
+ config03StereoSBSLense01 = null == lenseDistMeshProduce ? null :
+ new Config(
+ "Def03StereoSBSLense01",
+ ShutterType.RollingTopToBottom,
+ surfaceSizeInPixel, // resolution
+ screenSizeInMeters, // screenSize [m]
+ eyeTextureSize, // eye textureSize
+ pupilCenterFromScreenTopInMeters, // pupilCenterFromScreenTop [m]
+ interpupillaryDistanceInMeters, // IPD [m]
+ new int[] { 0, 1 }, // eye order
+ new EyeParameter[] {
+ new EyeParameter(0, DEFAULT_EYE_POSITION_OFFSET_STEREO_LENSES, defaultSBSEyeFovLenseLeft,
+ 0.032f /* distNoseToPupil */, 0f /* verticalDelta */, 0.010f /* eyeReliefInMeters */),
+ new EyeParameter(1, DEFAULT_EYE_POSITION_OFFSET_STEREO_LENSES, defaultSBSEyeFovLenseRight,
+ -0.032f /* distNoseToPupil */, 0f /* verticalDelta */, 0.010f /* eyeReliefInMeters */) },
+ lenseDistMeshProduce,
+ // supported distortion bits
+ StereoDeviceRenderer.DISTORTION_BARREL | StereoDeviceRenderer.DISTORTION_CHROMATIC | StereoDeviceRenderer.DISTORTION_VIGNETTE,
+ // recommended distortion bits
+ StereoDeviceRenderer.DISTORTION_BARREL | StereoDeviceRenderer.DISTORTION_CHROMATIC | StereoDeviceRenderer.DISTORTION_VIGNETTE,
+ // minimum distortion bits
+ StereoDeviceRenderer.DISTORTION_BARREL
+ );
+ }
+ configs = new Config[] { config01Mono01, config02StereoSBS01, config03StereoSBSLense01 };
+ }
+
+ public final int deviceIndex;
+ public final Config config;
+
+ public final Point surfacePos;
+ private final FovHVHalves[] defaultEyeFov;
+
+ private boolean sensorsStarted = false;
+
+ public GenericStereoDevice(final int deviceIndex, final StereoDevice.Config customConfig) {
+ this.deviceIndex = deviceIndex;
+
+ if( customConfig instanceof GenericStereoDevice.Config) {
+ this.config = (GenericStereoDevice.Config) customConfig;
+ } else {
+ final int cfgIdx = Math.min(deviceIndex % 10, configs.length-1);
+ this.config = null != configs[cfgIdx] ? configs[cfgIdx] : config02StereoSBS01;
+ }
+ config.init();
+
+ this.surfacePos = new Point(0, 0);
+
+ defaultEyeFov = new FovHVHalves[config.defaultEyeParam.length];
+ for(int i=0; i
fovHVHalves
.
+ */
+ public ScaleAndOffset2D(final FovHVHalves fovHVHalves) {
+ final FovHVHalves tanFovHVHalves = fovHVHalves.toTangents();
+ final float projXScale = 2.0f / ( tanFovHVHalves.left+ tanFovHVHalves.right);
+ final float projYScale = 2.0f / ( tanFovHVHalves.top + tanFovHVHalves.bottom );
+ final float projXOffset = ( tanFovHVHalves.left - tanFovHVHalves.right ) * projXScale * 0.5f;
+ final float projYOffset = ( tanFovHVHalves.top - tanFovHVHalves.bottom ) * projYScale * 0.5f;
+
+ this.scale = new float[] { projXScale, projYScale };
+ this.offset = new float[] { projXOffset, projYOffset };
+ }
+
+ /**
+ * Create the Normalized Device Coordinate Space (NDC) [-1,+1] instance
+ * from the given fovHVHalves
, for the subsection of the render-viewport
within the rendertarget-size
.
+ */
+ public ScaleAndOffset2D(final FovHVHalves fovHVHalves, final DimensionImmutable rendertargetSize, final RectangleImmutable renderViewport) {
+ final ScaleAndOffset2D eyeToSourceNDC = new ScaleAndOffset2D(fovHVHalves);
+ final float[] vec2Tmp1 = new float[2];
+ final float[] vec2Tmp2 = new float[2];
+ final float[] scale = VectorUtil.scaleVec2(vec2Tmp1, eyeToSourceNDC.scale, 0.5f);
+ final float[] offset = VectorUtil.addVec2(vec2Tmp2, VectorUtil.scaleVec2(vec2Tmp2, eyeToSourceNDC.offset, 0.5f), vec2Half);
+
+ final float[] scale2 = new float[] { (float)renderViewport.getWidth() / (float)rendertargetSize.getWidth(),
+ (float)renderViewport.getHeight() / (float)rendertargetSize.getHeight() };
+
+ final float[] offset2 = new float[] { (float)renderViewport.getX() / (float)rendertargetSize.getWidth(),
+ (float)renderViewport.getY() / (float)rendertargetSize.getHeight() };
+
+ VectorUtil.scaleVec2(scale, scale, scale2);
+ VectorUtil.addVec2(offset, VectorUtil.scaleVec2(offset, offset, scale2), offset2);
+
+ this.scale = scale;
+ this.offset = offset;
+ }
+
+ /**
+ * Return the tangent FOV space of this eye to source NDC instance.
+ */
+ public final float[] convertToTanFovSpace(final float[] rendertargetNDC) {
+ final float[] vec2Tmp1 = new float[2];
+ return VectorUtil.divVec2(vec2Tmp1, VectorUtil.subVec2(vec2Tmp1, rendertargetNDC, this.offset), this.scale);
+ }
+
+}
\ No newline at end of file
diff --git a/src/jogl/classes/jogamp/opengl/util/stereo/shader/dist01_chroma.fp b/src/jogl/classes/jogamp/opengl/util/stereo/shader/dist01_chroma.fp
new file mode 100644
index 000000000..4ac404729
--- /dev/null
+++ b/src/jogl/classes/jogamp/opengl/util/stereo/shader/dist01_chroma.fp
@@ -0,0 +1,26 @@
+//Copyright 2014 JogAmp Community. All rights reserved.
+
+#if __VERSION__ >= 130
+ #define varying in
+ out vec4 svr_FragColor;
+ #define texture2D texture
+#else
+ #define svr_FragColor gl_FragColor
+#endif
+
+uniform sampler2D svr_Texture0;
+
+varying vec3 svv_Fade;
+varying vec2 svv_TexCoordR;
+varying vec2 svv_TexCoordG;
+varying vec2 svv_TexCoordB;
+
+void main (void)
+{
+ // 3 samples for fixing chromatic aberrations
+ vec3 color = vec3(texture2D(svr_Texture0, svv_TexCoordR).r,
+ texture2D(svr_Texture0, svv_TexCoordG).g,
+ texture2D(svr_Texture0, svv_TexCoordB).b);
+ svr_FragColor = vec4(svv_Fade * color, 1.0); // include vignetteFade
+}
+
diff --git a/src/jogl/classes/jogamp/opengl/util/stereo/shader/dist01_chroma.vp b/src/jogl/classes/jogamp/opengl/util/stereo/shader/dist01_chroma.vp
new file mode 100644
index 000000000..d4ab585d5
--- /dev/null
+++ b/src/jogl/classes/jogamp/opengl/util/stereo/shader/dist01_chroma.vp
@@ -0,0 +1,33 @@
+//Copyright 2014 JogAmp Community. All rights reserved.
+
+#if __VERSION__ >= 130
+ #define attribute in
+ #define varying out
+#endif
+
+uniform vec2 svr_EyeToSourceUVScale;
+uniform vec2 svr_EyeToSourceUVOffset;
+
+attribute vec2 svr_Position;
+attribute vec2 svr_Params;
+attribute vec2 svr_TexCoordR;
+attribute vec2 svr_TexCoordG;
+attribute vec2 svr_TexCoordB;
+
+varying vec3 svv_Fade;
+varying vec2 svv_TexCoordR;
+varying vec2 svv_TexCoordG;
+varying vec2 svv_TexCoordB;
+
+void main(void)
+{
+ gl_Position = vec4(svr_Position.xy, 0.5, 1.0);
+ svv_Fade = vec3(svr_Params.r); // vignetteFade
+
+ svv_TexCoordR = svr_TexCoordR * svr_EyeToSourceUVScale + svr_EyeToSourceUVOffset;
+ svv_TexCoordR.y = 1.0-svv_TexCoordR.y;
+ svv_TexCoordG = svr_TexCoordG * svr_EyeToSourceUVScale + svr_EyeToSourceUVOffset;
+ svv_TexCoordG.y = 1.0-svv_TexCoordG.y;
+ svv_TexCoordB = svr_TexCoordB * svr_EyeToSourceUVScale + svr_EyeToSourceUVOffset;
+ svv_TexCoordB.y = 1.0-svv_TexCoordB.y;
+}
diff --git a/src/jogl/classes/jogamp/opengl/util/stereo/shader/dist01_plain.fp b/src/jogl/classes/jogamp/opengl/util/stereo/shader/dist01_plain.fp
new file mode 100644
index 000000000..2df890648
--- /dev/null
+++ b/src/jogl/classes/jogamp/opengl/util/stereo/shader/dist01_plain.fp
@@ -0,0 +1,22 @@
+//Copyright 2014 JogAmp Community. All rights reserved.
+
+#if __VERSION__ >= 130
+ #define varying in
+ out vec4 svr_FragColor;
+ #define texture2D texture
+#else
+ #define svr_FragColor gl_FragColor
+#endif
+
+uniform sampler2D svr_Texture0;
+
+varying vec3 svv_Fade;
+varying vec2 svv_TexCoordR;
+
+void main (void)
+{
+ // 3 samples for fixing chromatic aberrations
+ vec3 color = texture2D(svr_Texture0, svv_TexCoordR).rgb;
+ svr_FragColor = vec4(svv_Fade * color, 1.0); // include vignetteFade
+}
+
diff --git a/src/jogl/classes/jogamp/opengl/util/stereo/shader/dist01_plain.vp b/src/jogl/classes/jogamp/opengl/util/stereo/shader/dist01_plain.vp
new file mode 100644
index 000000000..335d3f0f6
--- /dev/null
+++ b/src/jogl/classes/jogamp/opengl/util/stereo/shader/dist01_plain.vp
@@ -0,0 +1,27 @@
+//Copyright 2014 JogAmp Community. All rights reserved.
+
+#if __VERSION__ >= 130
+ #define attribute in
+ #define varying out
+#endif
+
+uniform vec2 svr_EyeToSourceUVScale;
+uniform vec2 svr_EyeToSourceUVOffset;
+
+attribute vec2 svr_Position;
+attribute vec2 svr_Params;
+attribute vec2 svr_TexCoordR;
+
+varying vec3 svv_Fade;
+varying vec2 svv_TexCoordR;
+
+void main(void)
+{
+ gl_Position = vec4(svr_Position.xy, 0.5, 1.0);
+ svv_Fade = vec3(svr_Params.r); // vignetteFade
+
+ // Vertex inputs are in TanEyeAngle space for the R,G,B channels (i.e. after chromatic aberration and distortion).
+ // Scale them into the correct [0-1],[0-1] UV lookup space (depending on eye)
+ svv_TexCoordR = svr_TexCoordR * svr_EyeToSourceUVScale + svr_EyeToSourceUVOffset;
+ svv_TexCoordR.y = 1.0-svv_TexCoordR.y;
+}
diff --git a/src/jogl/classes/jogamp/opengl/util/stereo/shader/dist01_timewarp.vp b/src/jogl/classes/jogamp/opengl/util/stereo/shader/dist01_timewarp.vp
new file mode 100644
index 000000000..c4461ec3e
--- /dev/null
+++ b/src/jogl/classes/jogamp/opengl/util/stereo/shader/dist01_timewarp.vp
@@ -0,0 +1,44 @@
+//Copyright 2014 JogAmp Community. All rights reserved.
+
+#if __VERSION__ >= 130
+ #define attribute in
+ #define varying out
+#endif
+
+uniform vec2 svr_EyeToSourceUVScale;
+uniform vec2 svr_EyeToSourceUVOffset;
+uniform mat4 svr_EyeRotationStart;
+uniform mat4 svr_EyeRotationEnd;
+
+attribute vec2 svr_Position;
+attribute vec2 svr_Params;
+attribute vec2 svr_TexCoordR;
+
+varying vec3 svv_Fade;
+varying vec2 svv_TexCoordR;
+
+void main(void)
+{
+ gl_Position = vec4(svr_Position.xy, 0.0, 1.0);
+ svv_Fade = vec3(svr_Params.r); // vignetteFade
+
+ // Vertex inputs are in TanEyeAngle space for the R,G,B channels (i.e. after chromatic aberration and distortion).
+ // These are now "real world" vectors in direction (x,y,1) relative to the eye of the HMD.
+ vec3 TanEyeAngle = vec3 ( svr_TexCoordR, 1.0 );
+
+ // Accurate time warp lerp vs. faster
+ // Apply the two 3x3 timewarp rotations to these vectors.
+ vec3 TransformedStart = (svr_EyeRotationStart * vec4(TanEyeAngle, 0)).xyz;
+ vec3 TransformedEnd = (svr_EyeRotationEnd * vec4(TanEyeAngle, 0)).xyz;
+ // And blend between them.
+ vec3 Transformed = mix ( TransformedStart, TransformedEnd, svr_Params.g /* timewarpLerpFactor */ );
+
+ // Project them back onto the Z=1 plane of the rendered images.
+ float RecipZ = 1.0 / Transformed.z;
+ vec2 Flattened = vec2 ( Transformed.x * RecipZ, Transformed.y * RecipZ );
+
+ // These are now still in TanEyeAngle space.
+ // Scale them into the correct [0-1],[0-1] UV lookup space (depending on eye)
+ svv_TexCoordR = Flattened * svr_EyeToSourceUVScale + svr_EyeToSourceUVOffset;
+ svv_TexCoordR.y = 1.0-svv_TexCoordR.y;
+}
diff --git a/src/jogl/classes/jogamp/opengl/util/stereo/shader/dist01_timewarp_chroma.vp b/src/jogl/classes/jogamp/opengl/util/stereo/shader/dist01_timewarp_chroma.vp
new file mode 100644
index 000000000..c08ed3113
--- /dev/null
+++ b/src/jogl/classes/jogamp/opengl/util/stereo/shader/dist01_timewarp_chroma.vp
@@ -0,0 +1,65 @@
+//Copyright 2014 JogAmp Community. All rights reserved.
+
+#if __VERSION__ >= 130
+ #define attribute in
+ #define varying out
+#endif
+
+uniform vec2 svr_EyeToSourceUVScale;
+uniform vec2 svr_EyeToSourceUVOffset;
+uniform mat4 svr_EyeRotationStart;
+uniform mat4 svr_EyeRotationEnd;
+
+attribute vec2 svr_Position;
+attribute vec2 svr_Params;
+attribute vec2 svr_TexCoordR;
+attribute vec2 svr_TexCoordG;
+attribute vec2 svr_TexCoordB;
+
+varying vec3 svv_Fade;
+varying vec2 svv_TexCoordR;
+varying vec2 svv_TexCoordG;
+varying vec2 svv_TexCoordB;
+
+void main(void)
+{
+ gl_Position = vec4(svr_Position.xy, 0.0, 1.0);
+ svv_Fade = vec3(svr_Params.r); // vignetteFade
+
+ // Vertex inputs are in TanEyeAngle space for the R,G,B channels (i.e. after chromatic aberration and distortion).
+ // These are now "real world" vectors in direction (x,y,1) relative to the eye of the HMD.
+ vec3 TanEyeAngleR = vec3 ( svr_TexCoordR, 1.0 );
+ vec3 TanEyeAngleG = vec3 ( svr_TexCoordG, 1.0 );
+ vec3 TanEyeAngleB = vec3 ( svr_TexCoordB, 1.0 );
+
+ // Accurate time warp lerp vs. faster
+ // Apply the two 3x3 timewarp rotations to these vectors.
+ vec3 TransformedRStart = (svr_EyeRotationStart * vec4(TanEyeAngleR, 0)).xyz;
+ vec3 TransformedGStart = (svr_EyeRotationStart * vec4(TanEyeAngleG, 0)).xyz;
+ vec3 TransformedBStart = (svr_EyeRotationStart * vec4(TanEyeAngleB, 0)).xyz;
+ vec3 TransformedREnd = (svr_EyeRotationEnd * vec4(TanEyeAngleR, 0)).xyz;
+ vec3 TransformedGEnd = (svr_EyeRotationEnd * vec4(TanEyeAngleG, 0)).xyz;
+ vec3 TransformedBEnd = (svr_EyeRotationEnd * vec4(TanEyeAngleB, 0)).xyz;
+
+ // And blend between them.
+ vec3 TransformedR = mix ( TransformedRStart, TransformedREnd, svr_Params.g /* timewarpLerpFactor */ );
+ vec3 TransformedG = mix ( TransformedGStart, TransformedGEnd, svr_Params.g /* timewarpLerpFactor */ );
+ vec3 TransformedB = mix ( TransformedBStart, TransformedBEnd, svr_Params.g /* timewarpLerpFactor */ );
+
+ // Project them back onto the Z=1 plane of the rendered images.
+ float RecipZR = 1.0 / TransformedR.z;
+ float RecipZG = 1.0 / TransformedG.z;
+ float RecipZB = 1.0 / TransformedB.z;
+ vec2 FlattenedR = vec2 ( TransformedR.x * RecipZR, TransformedR.y * RecipZR );
+ vec2 FlattenedG = vec2 ( TransformedG.x * RecipZG, TransformedG.y * RecipZG );
+ vec2 FlattenedB = vec2 ( TransformedB.x * RecipZB, TransformedB.y * RecipZB );
+
+ // These are now still in TanEyeAngle space.
+ // Scale them into the correct [0-1],[0-1] UV lookup space (depending on eye)
+ svv_TexCoordR = FlattenedR * svr_EyeToSourceUVScale + svr_EyeToSourceUVOffset;
+ svv_TexCoordR.y = 1.0-svv_TexCoordR.y;
+ svv_TexCoordG = FlattenedG * svr_EyeToSourceUVScale + svr_EyeToSourceUVOffset;
+ svv_TexCoordG.y = 1.0-svv_TexCoordG.y;
+ svv_TexCoordB = FlattenedB * svr_EyeToSourceUVScale + svr_EyeToSourceUVOffset;
+ svv_TexCoordB.y = 1.0-svv_TexCoordB.y;
+}
--
cgit v1.2.3