Cliff Biffle avatar Cliff Biffle committed 8aa5438

Moved raycasting into a vertex shader. Substantially reduces CPU usage.

Comments (0)

Files changed (3)

 - (void) requestUpdateFromBackgroundThread;
 - (void) markAsDirty;
 
+@property GLuint vertexShader;
+@property GLuint program;
+
 @end
 
 @implementation KVDepthView
 #pragma mark --- Properties ---
 
+@synthesize vertexShader, program;
 @synthesize updateQueued;
 @synthesize lightsOn;
 
 
 #pragma mark --- GL Stuff ---
 
+static const char *vertex_shader_source[] = {
+  "const float halfFov = (57.0 / 180.0 * 3.14159265358) / 2.0;",
+  "void main() {",
+  "  gl_FrontColor = gl_Color;",
+  "  vec2 angles = gl_Vertex.xy * halfFov;",
+  "  vec2 xyPrime = gl_Vertex.z * sin(angles);",
+  "  vec4 vertex = vec4(xyPrime, gl_Vertex.zw);",
+  "  gl_Position = gl_ModelViewProjectionMatrix * vertex;",
+  "}",
+};
+
 - (void) prepareOpenGL {
+  vertexShader = glCreateShader(GL_VERTEX_SHADER);
+  glShaderSource(vertexShader, sizeof(vertex_shader_source) / sizeof(char *), vertex_shader_source, NULL);
+  glCompileShader(vertexShader);
+  
+  program = glCreateProgram();
+  glAttachShader(program, vertexShader);
+  glLinkProgram(program);
+  glUseProgram(program);
+  
   // Sync to vertical blank.
   GLint swapInterval = 1;
   [[self openGLContext] setValues: &swapInterval forParameter: NSOpenGLCPSwapInterval];

KVRayFieldSpaceModel.h

 @interface KVRayFieldSpaceModel : NSObject <KVSpaceModel> {
   // Memoized linearization function for 12-bit depth samples.
   float linearizationTable[2048];
-  // The X coordinate of each unit ray.
-  float unitX[640];
-  // The Y coordinate of each unit ray.
-  float unitY[480];
-    
+
   // The actual scene model.  Alarmingly, gcc generates suboptimal
   // code if we use [480][640].
   vec3f_t rays[480 * 640];

KVRayFieldSpaceModel.m

 
 @interface KVRayFieldSpaceModel ()
 - (void) buildLinearizationTable;
-- (void) buildUnitRays;
+- (void) fillStaticComponents;
 
 @property(assign, nonatomic) double rayCastingTotal;
 @property(assign, nonatomic) NSUInteger rayCastingCount;
 
 - init {
   if ((self = [super init])) {
-    [self buildUnitRays];
+    [self fillStaticComponents];
     [self buildLinearizationTable];
   }
   return self;
         z = 0;
       }
       
-      rays[vidx] = (vec3f_t) {
-        .x = unitX[x] * z,
-        .y = unitY[y] * z,
-        .z = z,
-      };
+      rays[vidx].z = z;
     }
   }
   
   linearizationTable[2047] = 0.F;
 }
 
-- (void) buildUnitRays {
-  // We assume square pixels, and derive the Y FOV from the X.
-  static const float fovXDegrees = 57.F;  // Pretty close to actual?
-  
-  const float fovX = fovXDegrees / 180.F * (float) M_PI;
-  for (int y = 0; y < 240; y++) {
-    float theta = ((y + 0.5F) / 320.F) * fovX/2.F;
-    unitY[y + 240] = -sinf(theta);
-    unitY[239 - y] = sinf(theta);
-  }
-  for (int x = 0; x < 320; x++) {
-    float psi = ((x + 0.5F) / 320.F) * fovX/2.F;
-    unitX[x + 320] = -sinf(psi);
-    unitX[319 - x] = sinf(psi);
+// We pre-fill the X and Y components with distance from the center of
+// the image.  These values never make it to the rasterizer: they are
+// merely input to the vertex shader that performs perspective correction.
+- (void) fillStaticComponents {
+  int vidx = 0;
+  for (int y = 0; y < 480; y++) {
+    for (int x = 0; x < 640; x++, vidx++) {
+      rays[vidx].x = -(float) (x - 320) / 320.f;
+      rays[vidx].y = -(float) (y - 240) / 320.f;
+    }
   }
 }
 
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.