فهرست منبع

add universal GLSL distortion shader and coefficents to libopenhmd

James Sarrett 8 سال پیش
والد
کامیت
9a96bd4ae9
6فایلهای تغییر یافته به همراه120 افزوده شده و 2 حذف شده
  1. 1 0
      CMakeLists.txt
  2. 24 1
      include/openhmd.h
  3. 32 1
      src/openhmd.c
  4. 2 0
      src/openhmdi.h
  5. 55 0
      src/shaders.c
  6. 6 0
      src/shaders.h

+ 1 - 0
CMakeLists.txt

@@ -24,6 +24,7 @@ set(openhmd_source_files
 	${CMAKE_CURRENT_LIST_DIR}/src/platform-posix.c
 	${CMAKE_CURRENT_LIST_DIR}/src/fusion.c
 	${CMAKE_CURRENT_LIST_DIR}/src/queue.c
+	${CMAKE_CURRENT_LIST_DIR}/src/shaders.c
 )
 
 OPTION(OPENHMD_DRIVER_OCULUS_RIFT "Oculus Rift DK1 and DK2" ON)

+ 24 - 1
include/openhmd.h

@@ -57,6 +57,12 @@ typedef enum {
 	OHMD_PATH      = 2,
 } ohmd_string_value;
 
+/** A collection of string descriptions, used for getting strings with ohmd_gets(). */
+typedef enum {
+	OHMD_GLSL_DISTORTION_VERT_SRC = 0,
+	OHMD_GLSL_DISTORTION_FRAG_SRC = 1,
+} ohmd_string_description;
+
 /** A collection of float value information types, used for getting and setting information with
     ohmd_device_getf() and ohmd_device_setf(). */
 typedef enum {
@@ -109,7 +115,7 @@ typedef enum {
 
 	/** float[6] (get): Device specific distortion value. */
 	OHMD_DISTORTION_K                     = 18,
-	
+
 	/**
 	 * float[10] (set): Perform sensor fusion on values from external sensors.
 	 *
@@ -117,6 +123,12 @@ typedef enum {
 	 **/
 	OHMD_EXTERNAL_SENSOR_FUSION           = 19,
 
+	/** float[4] (get): Universal shader distortion coefficients (PanoTools model <a,b,c,d>. */
+	OHMD_UNIVERSAL_DISTORTION_K           = 20,
+
+	/** float[3] (get): Universal shader aberration coefficients (post warp scaling <r,g,b>. */
+	OHMD_UNIVERSAL_ABERRATION_K           = 21,
+
 } ohmd_float_value;
 
 /** A collection of int value information types used for getting information with ohmd_device_geti(). */
@@ -226,6 +238,17 @@ OHMD_APIENTRYDLL void OHMD_APIENTRY ohmd_ctx_update(ohmd_context* ctx);
 OHMD_APIENTRYDLL int OHMD_APIENTRY ohmd_ctx_probe(ohmd_context* ctx);
 
 /**
+ * Get string from openhmd.
+ *
+ * Gets a string from OpenHMD. This is where non-device specific strings reside.
+ * This is where the distortion shader sources can be retrieved.
+ *
+ * @param type The name of the string to fetch. One of OHMD_GLSL_DISTORTION_FRAG_SRC, and OHMD_GLSL_DISTORTION_FRAG_SRC.
+ * @return a string with a human readable device name.
+ **/
+OHMD_APIENTRYDLL const char* OHMD_APIENTRY ohmd_gets(ohmd_string_description type);
+
+/**
  * Get device description from enumeration list index.
  *
  * Gets a human readable device description string from a zero indexed enumeration index

+ 32 - 1
src/openhmd.c

@@ -8,6 +8,7 @@
 /* Main Lib Implemenation */
 
 #include "openhmdi.h"
+#include "shaders.h"
 #include <stdlib.h>
 #include <string.h>
 #include <stdio.h>
@@ -97,6 +98,18 @@ int OHMD_APIENTRY ohmd_ctx_probe(ohmd_context* ctx)
 	return ctx->list.num_devices;
 }
 
+const char* OHMD_APIENTRY ohmd_gets(ohmd_string_description type)
+{
+	switch(type){
+	case OHMD_GLSL_DISTORTION_VERT_SRC:
+		return distortion_vert;
+	case OHMD_GLSL_DISTORTION_FRAG_SRC:
+		return distortion_frag;
+	default:
+		return NULL;
+	}
+}
+
 const char* OHMD_APIENTRY ohmd_list_gets(ohmd_context* ctx, int index, ohmd_string_value type)
 {
 	if(index >= ctx->list.num_devices)
@@ -303,7 +316,18 @@ static int ohmd_device_getf_unp(ohmd_device* device, ohmd_float_value type, floa
 
 		return OHMD_S_OK;
 	}
-
+	case OHMD_UNIVERSAL_DISTORTION_K: {
+		for (int i = 0; i < 4; i++) {
+			out[i] = device->properties.universal_distortion_k[i];
+		}
+		break;
+	}
+	case OHMD_UNIVERSAL_ABERRATION_K: {
+		for (int i = 0; i < 3; i++) {
+			out[i] = device->properties.universal_aberration_k[i];
+		}
+		break;
+	}
 	default:
 		return device->getf(device, type, out);
 	}
@@ -491,6 +515,13 @@ void ohmd_set_default_device_properties(ohmd_device_properties* props)
 	props->ipd = 0.061f;
 	props->znear = 0.1f;
 	props->zfar = 1000.0f;
+	props->universal_distortion_k[0] = 0.0;
+	props->universal_distortion_k[1] = 0.0;
+	props->universal_distortion_k[2] = 0.0;
+	props->universal_distortion_k[3] = 1.0;
+	props->universal_aberration_k[0] = 1.0;
+	props->universal_aberration_k[1] = 1.0;
+	props->universal_aberration_k[2] = 1.0;
 }
 
 void ohmd_calc_default_proj_matrices(ohmd_device_properties* props)

+ 2 - 0
src/openhmdi.h

@@ -77,6 +77,8 @@ typedef struct {
 
 		mat4x4f proj_left; // adjusted projection matrix for left screen
 		mat4x4f proj_right; // adjusted projection matrix for right screen
+		float universal_distortion_k[4]; //PanoTools lens distiorion model [a,b,c,d]
+		float universal_aberration_k[3]; //post-warp per channel scaling [r,g,b]
 } ohmd_device_properties;
 
 struct ohmd_device_settings

+ 55 - 0
src/shaders.c

@@ -0,0 +1,55 @@
+const char * distortion_vert =
+"#version 120\n"
+"void main(void)\n"
+"{\n"
+	"gl_TexCoord[0] = gl_MultiTexCoord0;\n"
+    "gl_Position = gl_ProjectionMatrix * gl_ModelViewMatrix * gl_Vertex;\n"
+"}";
+
+const char * distortion_frag =
+"#version 120\n"
+"\n"
+"//per eye texture to warp for lens distortion\n"
+"uniform sampler2D warpTexture;\n"
+"\n"
+"//Position of lens center in m (usually eye_w/2, eye_h/2)\n"
+"uniform vec2 LensCenter;\n"
+"//Scale from texture co-ords to m (usually eye_w, eye_h)\n"
+"uniform vec2 ViewportScale;\n"
+"//Distortion overall scale in m (usually ~eye_w/2)\n"
+"uniform float WarpScale;\n"
+"//Distoriton coefficients (PanoTools model) [a,b,c,d]\n"
+"uniform vec4 HmdWarpParam;\n"
+"\n"
+"//chromatic distortion post scaling\n"
+"uniform vec3 aberr;\n"
+"\n"
+"void main()\n"
+"{\n"
+    "//output_loc is the fragment location on screen from [0,1]x[0,1]\n"
+    "vec2 output_loc = vec2(gl_TexCoord[0].s, gl_TexCoord[0].t);\n"
+    "//Compute fragment location in lens-centered co-ordinates at world scale\n"
+	"vec2 r = output_loc * ViewportScale - LensCenter;\n"
+    "//scale for distortion model\n"
+    "//distortion model has r=1 being the largest circle inscribed (e.g. eye_w/2)\n"
+    "r /= WarpScale;\n"
+"\n"
+    "//|r|**2\n"
+    "float r_mag = length(r);\n"
+    "//offset for which fragment is sourced\n"
+    "vec2 r_displaced = r * (HmdWarpParam.w + HmdWarpParam.z * r_mag +\n"
+		"HmdWarpParam.y * r_mag * r_mag +\n"
+		"HmdWarpParam.x * r_mag * r_mag * r_mag);\n"
+    "//back to world scale\n"
+    "r_displaced *= WarpScale;\n"
+    "//back to viewport co-ord\n"
+    "vec2 tc_r = (LensCenter + aberr.r * r_displaced) / ViewportScale;\n"
+    "vec2 tc_g = (LensCenter + aberr.g * r_displaced) / ViewportScale;\n"
+    "vec2 tc_b = (LensCenter + aberr.b * r_displaced) / ViewportScale;\n"
+"\n"
+    "float red = texture2D(warpTexture, tc_r).r;\n"
+    "float green = texture2D(warpTexture, tc_g).g;\n"
+    "float blue = texture2D(warpTexture, tc_b).b;\n"
+    "//Black edges off the texture\n"
+    "gl_FragColor = ((tc_g.x < 0.0) || (tc_g.x > 1.0) || (tc_g.y < 0.0) || (tc_g.y > 1.0)) ? vec4(0.0, 0.0, 0.0, 1.0) : vec4(red, green, blue, 1.0);\n"
+"}";

+ 6 - 0
src/shaders.h

@@ -0,0 +1,6 @@
+#ifndef SHADERS_H
+#define SHADERS_H
+
+const char * distortion_vert;
+const char * distortion_frag;
+#endif /* SHADERS_H */