summaryrefslogtreecommitdiffstats
path: root/Samples/OculusRoomTiny
diff options
context:
space:
mode:
authorBrad Davis <[email protected]>2013-07-03 10:28:24 -0700
committerBrad Davis <[email protected]>2013-07-03 10:28:24 -0700
commitb71a796bd6efc9fffd78045025eabd4b276adc69 (patch)
treedec98b43ce0b59b0eb4a778ac7c6c516007524fe /Samples/OculusRoomTiny
parentd46694c91c2bec4eb1e282c0c0101e6dab26e082 (diff)
Fixed crlf issue
Diffstat (limited to 'Samples/OculusRoomTiny')
-rw-r--r--Samples/OculusRoomTiny/OSX_OculusRoomTiny.h446
-rw-r--r--Samples/OculusRoomTiny/OSX_OculusRoomTiny.mm1722
-rw-r--r--Samples/OculusRoomTiny/OculusRoomModel.cpp520
-rw-r--r--Samples/OculusRoomTiny/OculusRoomTiny_Msvc2010.vcxproj372
-rw-r--r--Samples/OculusRoomTiny/OculusRoomTiny_Msvc2010.vcxproj.filters32
-rw-r--r--Samples/OculusRoomTiny/RenderTiny_D3D1X_Device.cpp2622
-rw-r--r--Samples/OculusRoomTiny/RenderTiny_D3D1X_Device.h546
-rw-r--r--Samples/OculusRoomTiny/RenderTiny_Device.cpp884
-rw-r--r--Samples/OculusRoomTiny/RenderTiny_Device.h1448
-rw-r--r--Samples/OculusRoomTiny/RenderTiny_GL_Device.cpp1568
-rw-r--r--Samples/OculusRoomTiny/RenderTiny_GL_Device.h456
-rw-r--r--Samples/OculusRoomTiny/Win32_OculusRoomTiny.cpp1424
-rw-r--r--Samples/OculusRoomTiny/Win32_OculusRoomTiny.h378
13 files changed, 6209 insertions, 6209 deletions
diff --git a/Samples/OculusRoomTiny/OSX_OculusRoomTiny.h b/Samples/OculusRoomTiny/OSX_OculusRoomTiny.h
index dc51509..280fda5 100644
--- a/Samples/OculusRoomTiny/OSX_OculusRoomTiny.h
+++ b/Samples/OculusRoomTiny/OSX_OculusRoomTiny.h
@@ -1,223 +1,223 @@
-/************************************************************************************
-
- Filename : OSX_OculusRoomTiny.h
- Content : Simplest possible first-person view test application for Oculus Rift
- Created : May 7, 2013
- Authors : Michael Antonov, Andrew Reisse, Artem Bolgar
-
- Copyright : Copyright 2013 Oculus, Inc. All Rights reserved.
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- *************************************************************************************/
-#ifndef INC_OSX_OculusRoomTiny_h
-#define INC_OSX_OculusRoomTiny_h
-
-#import <Cocoa/Cocoa.h>
-
-#import <CoreGraphics/CoreGraphics.h>
-#import <CoreGraphics/CGDirectDisplay.h>
-
-
-#include "OVR.h"
-#include "Util/Util_Render_Stereo.h"
-#include "../../LibOVR/Src/Kernel/OVR_Timer.h"
-#include "RenderTiny_GL_Device.h"
-
-using namespace OVR;
-using namespace OVR::RenderTiny;
-
-class OculusRoomTinyApp;
-
-@interface OVRApp : NSApplication
-
-@property (assign) IBOutlet NSWindow* win;
-@property (assign) OculusRoomTinyApp* App;
-
--(void) run;
-
-@end
-
-@interface OVRView : NSOpenGLView <NSWindowDelegate>
-
-//@property (assign) OVR::Platform::OSX::PlatformCore* Platform;
-@property (assign) OculusRoomTinyApp* App;
-@property unsigned long Modifiers;
-
--(void)ProcessMouse:(NSEvent*)event;
--(void)warpMouseToCenter;
-
-+(CGDirectDisplayID) displayFromScreen:(NSScreen*)s;
-
-@end
-
-//-------------------------------------------------------------------------------------
-// ***** OculusRoomTiny Description
-
-// This app renders a simple flat-shaded room allowing the user to move along the
-// floor and look around with an HMD, mouse, keyboard and gamepad.
-// By default, the application will start full-screen on Oculus Rift.
-//
-// The following keys work:
-//
-// 'W', 'S', 'A', 'D' - Move forward, back; strafe left/right.
-// F1 - No stereo, no distortion.
-// F2 - Stereo, no distortion.
-// F3 - Stereo and distortion.
-//
-
-// The world RHS coordinate system is defines as follows (as seen in perspective view):
-// Y - Up
-// Z - Back
-// X - Right
-const Vector3f UpVector(0.0f, 1.0f, 0.0f);
-const Vector3f ForwardVector(0.0f, 0.0f, -1.0f);
-const Vector3f RightVector(1.0f, 0.0f, 0.0f);
-
-// We start out looking in the positive Z (180 degree rotation).
-const float YawInitial = 3.141592f;
-const float Sensitivity = 1.0f;
-const float MoveSpeed = 3.0f; // m/s
-
-namespace OSX
-{
- class RenderDevice : public GL::RenderDevice
- {
- public:
- void* Context; // NSOpenGLContext
-
- // osview = NSView*
- RenderDevice(const RendererParams& p, void* osview, void* context);
-
- virtual void Shutdown();
- virtual void Present();
-
- virtual bool SetFullscreen(DisplayMode fullscreen);
-
- // osview = NSView*
- static RenderDevice* CreateDevice(const RendererParams& rp, void* osview);
- };
-}
-
-//-------------------------------------------------------------------------------------
-// ***** OculusRoomTiny Application class
-
-// An instance of this class is created on application startup (main/WinMain).
-//
-// It then works as follows:
-//
-// OnStartup - Window, graphics and HMD setup is done here.
-// This function will initialize OVR::DeviceManager and HMD,
-// creating SensorDevice and attaching it to SensorFusion.
-// This needs to be done before obtaining sensor data.
-//
-// OnIdle - Does per-frame processing, processing SensorFusion and
-// movement input and rendering the frame.
-
-class OculusRoomTinyApp : public MessageHandler
-{
- friend class OSX::RenderDevice;
-public:
- OculusRoomTinyApp(OVRApp* nsapp);
- ~OculusRoomTinyApp();
-
- // Initializes graphics, Rift input and creates world model.
- virtual int OnStartup(const char* args);
- // Called per frame to sample SensorFucion and render the world.
- virtual void OnIdle();
-
- // Installed for Oculus device messages. Optional.
- virtual void OnMessage(const Message& msg);
-
- // Handle input events for movement.
- virtual void OnMouseMove(int x, int y, int modifiers);
- virtual void OnKey(unsigned vk, bool down);
-
- // Render the view for one eye.
- void Render(const StereoEyeParams& stereo);
-
- // Main application loop.
- int Run();
- void Exit();
-
- // Return amount of time passed since application started in seconds.
- double GetAppTime() const
- {
- return (OVR::Timer::GetTicks() - StartupTicks) * (1.0 / (double)OVR::Timer::MksPerSecond);
- }
- bool IsQuiting() const { return Quit; }
-
- int GetWidth() const { return Width; }
- int GetHeight() const { return Height; }
-
- bool SetFullscreen(const RendererParams& rp, int fullscreen);
-
-protected:
- bool setupWindow();
- void destroyWindow();
-
- NSView* View;
- NSWindow* Win;
- OVRApp* NsApp;
-
- static OculusRoomTinyApp* pApp;
-
- // *** Rendering Variables
- Ptr<OSX::RenderDevice> pRender;
- RendererParams RenderParams;
- int Width, Height;
-
- bool Quit;
-
- // *** Oculus HMD Variables
-
- Ptr<DeviceManager> pManager;
- Ptr<SensorDevice> pSensor;
- Ptr<HMDDevice> pHMD;
- SensorFusion SFusion;
- OVR::HMDInfo HMDInfo;
-
- // Last update seconds, used for move speed timing.
- double LastUpdate;
- OVR::UInt64 StartupTicks;
-
- // Position and look. The following apply:
- Vector3f EyePos;
- float EyeYaw; // Rotation around Y, CCW positive when looking at RHS (X,Z) plane.
- float EyePitch; // Pitch. If sensor is plugged in, only read from sensor.
- float EyeRoll; // Roll, only accessible from Sensor.
- float LastSensorYaw; // Stores previous Yaw value from to support computing delta.
-
- // Movement state; different bits may be set based on the state of keys.
- UByte MoveForward;
- UByte MoveBack;
- UByte MoveLeft;
- UByte MoveRight;
-
- Matrix4f ViewMat;
- RenderTiny::Scene Scene;
-
- // Stereo view parameters.
- StereoConfig SConfig;
- PostProcessType PostProcess;
-
- // Shift accelerates movement/adjustment velocity.
- bool ShiftDown;
- bool ControlDown;
-};
-
-// Adds sample models and lights to the argument scene.
-void PopulateRoomScene(Scene* scene, RenderDevice* render);
-
-
-#endif
+/************************************************************************************
+
+ Filename : OSX_OculusRoomTiny.h
+ Content : Simplest possible first-person view test application for Oculus Rift
+ Created : May 7, 2013
+ Authors : Michael Antonov, Andrew Reisse, Artem Bolgar
+
+ Copyright : Copyright 2013 Oculus, Inc. All Rights reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+ *************************************************************************************/
+#ifndef INC_OSX_OculusRoomTiny_h
+#define INC_OSX_OculusRoomTiny_h
+
+#import <Cocoa/Cocoa.h>
+
+#import <CoreGraphics/CoreGraphics.h>
+#import <CoreGraphics/CGDirectDisplay.h>
+
+
+#include "OVR.h"
+#include "Util/Util_Render_Stereo.h"
+#include "../../LibOVR/Src/Kernel/OVR_Timer.h"
+#include "RenderTiny_GL_Device.h"
+
+using namespace OVR;
+using namespace OVR::RenderTiny;
+
+class OculusRoomTinyApp;
+
+@interface OVRApp : NSApplication
+
+@property (assign) IBOutlet NSWindow* win;
+@property (assign) OculusRoomTinyApp* App;
+
+-(void) run;
+
+@end
+
+@interface OVRView : NSOpenGLView <NSWindowDelegate>
+
+//@property (assign) OVR::Platform::OSX::PlatformCore* Platform;
+@property (assign) OculusRoomTinyApp* App;
+@property unsigned long Modifiers;
+
+-(void)ProcessMouse:(NSEvent*)event;
+-(void)warpMouseToCenter;
+
++(CGDirectDisplayID) displayFromScreen:(NSScreen*)s;
+
+@end
+
+//-------------------------------------------------------------------------------------
+// ***** OculusRoomTiny Description
+
+// This app renders a simple flat-shaded room allowing the user to move along the
+// floor and look around with an HMD, mouse, keyboard and gamepad.
+// By default, the application will start full-screen on Oculus Rift.
+//
+// The following keys work:
+//
+// 'W', 'S', 'A', 'D' - Move forward, back; strafe left/right.
+// F1 - No stereo, no distortion.
+// F2 - Stereo, no distortion.
+// F3 - Stereo and distortion.
+//
+
+// The world RHS coordinate system is defines as follows (as seen in perspective view):
+// Y - Up
+// Z - Back
+// X - Right
+const Vector3f UpVector(0.0f, 1.0f, 0.0f);
+const Vector3f ForwardVector(0.0f, 0.0f, -1.0f);
+const Vector3f RightVector(1.0f, 0.0f, 0.0f);
+
+// We start out looking in the positive Z (180 degree rotation).
+const float YawInitial = 3.141592f;
+const float Sensitivity = 1.0f;
+const float MoveSpeed = 3.0f; // m/s
+
+namespace OSX
+{
+ class RenderDevice : public GL::RenderDevice
+ {
+ public:
+ void* Context; // NSOpenGLContext
+
+ // osview = NSView*
+ RenderDevice(const RendererParams& p, void* osview, void* context);
+
+ virtual void Shutdown();
+ virtual void Present();
+
+ virtual bool SetFullscreen(DisplayMode fullscreen);
+
+ // osview = NSView*
+ static RenderDevice* CreateDevice(const RendererParams& rp, void* osview);
+ };
+}
+
+//-------------------------------------------------------------------------------------
+// ***** OculusRoomTiny Application class
+
+// An instance of this class is created on application startup (main/WinMain).
+//
+// It then works as follows:
+//
+// OnStartup - Window, graphics and HMD setup is done here.
+// This function will initialize OVR::DeviceManager and HMD,
+// creating SensorDevice and attaching it to SensorFusion.
+// This needs to be done before obtaining sensor data.
+//
+// OnIdle - Does per-frame processing, processing SensorFusion and
+// movement input and rendering the frame.
+
+class OculusRoomTinyApp : public MessageHandler
+{
+ friend class OSX::RenderDevice;
+public:
+ OculusRoomTinyApp(OVRApp* nsapp);
+ ~OculusRoomTinyApp();
+
+ // Initializes graphics, Rift input and creates world model.
+ virtual int OnStartup(const char* args);
+ // Called per frame to sample SensorFucion and render the world.
+ virtual void OnIdle();
+
+ // Installed for Oculus device messages. Optional.
+ virtual void OnMessage(const Message& msg);
+
+ // Handle input events for movement.
+ virtual void OnMouseMove(int x, int y, int modifiers);
+ virtual void OnKey(unsigned vk, bool down);
+
+ // Render the view for one eye.
+ void Render(const StereoEyeParams& stereo);
+
+ // Main application loop.
+ int Run();
+ void Exit();
+
+ // Return amount of time passed since application started in seconds.
+ double GetAppTime() const
+ {
+ return (OVR::Timer::GetTicks() - StartupTicks) * (1.0 / (double)OVR::Timer::MksPerSecond);
+ }
+ bool IsQuiting() const { return Quit; }
+
+ int GetWidth() const { return Width; }
+ int GetHeight() const { return Height; }
+
+ bool SetFullscreen(const RendererParams& rp, int fullscreen);
+
+protected:
+ bool setupWindow();
+ void destroyWindow();
+
+ NSView* View;
+ NSWindow* Win;
+ OVRApp* NsApp;
+
+ static OculusRoomTinyApp* pApp;
+
+ // *** Rendering Variables
+ Ptr<OSX::RenderDevice> pRender;
+ RendererParams RenderParams;
+ int Width, Height;
+
+ bool Quit;
+
+ // *** Oculus HMD Variables
+
+ Ptr<DeviceManager> pManager;
+ Ptr<SensorDevice> pSensor;
+ Ptr<HMDDevice> pHMD;
+ SensorFusion SFusion;
+ OVR::HMDInfo HMDInfo;
+
+ // Last update seconds, used for move speed timing.
+ double LastUpdate;
+ OVR::UInt64 StartupTicks;
+
+ // Position and look. The following apply:
+ Vector3f EyePos;
+ float EyeYaw; // Rotation around Y, CCW positive when looking at RHS (X,Z) plane.
+ float EyePitch; // Pitch. If sensor is plugged in, only read from sensor.
+ float EyeRoll; // Roll, only accessible from Sensor.
+ float LastSensorYaw; // Stores previous Yaw value from to support computing delta.
+
+ // Movement state; different bits may be set based on the state of keys.
+ UByte MoveForward;
+ UByte MoveBack;
+ UByte MoveLeft;
+ UByte MoveRight;
+
+ Matrix4f ViewMat;
+ RenderTiny::Scene Scene;
+
+ // Stereo view parameters.
+ StereoConfig SConfig;
+ PostProcessType PostProcess;
+
+ // Shift accelerates movement/adjustment velocity.
+ bool ShiftDown;
+ bool ControlDown;
+};
+
+// Adds sample models and lights to the argument scene.
+void PopulateRoomScene(Scene* scene, RenderDevice* render);
+
+
+#endif
diff --git a/Samples/OculusRoomTiny/OSX_OculusRoomTiny.mm b/Samples/OculusRoomTiny/OSX_OculusRoomTiny.mm
index 0a59afd..7c5d81f 100644
--- a/Samples/OculusRoomTiny/OSX_OculusRoomTiny.mm
+++ b/Samples/OculusRoomTiny/OSX_OculusRoomTiny.mm
@@ -1,861 +1,861 @@
-/************************************************************************************
-
- Filename : OSX_OculusRoomTiny.mm
- Content : Simplest possible first-person view test application for Oculus Rift
- Created : May 7, 2013
- Authors : Michael Antonov, Andrew Reisse, Artem Bolgar
-
- Copyright : Copyright 2013 Oculus, Inc. All Rights reserved.
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- *************************************************************************************/
-
-#import "OSX_OculusRoomTiny.h"
-#include "RenderTiny_GL_Device.h"
-
-#include "Kernel/OVR_KeyCodes.h"
-
-using namespace OVR;
-
-//-------------------------------------------------------------------------------------
-// ***** OculusRoomTiny Class
-
-// Static pApp simplifies routing the window function.
-OculusRoomTinyApp* OculusRoomTinyApp::pApp = 0;
-
-
-OculusRoomTinyApp::OculusRoomTinyApp(OVRApp* nsapp)
- : pRender(0),
- LastUpdate(0),
- NsApp(nsapp),
- Quit(0),
-
- // Initial location
- EyePos(0.0f, 1.6f, -5.0f),
- EyeYaw(YawInitial), EyePitch(0), EyeRoll(0),
- LastSensorYaw(0),
- SConfig(),
- PostProcess(PostProcess_Distortion),
- ShiftDown(false),
- ControlDown(false)
-{
- pApp = this;
-
- Width = 1280;
- Height = 800;
-
- StartupTicks = OVR::Timer::GetTicks();
-
- MoveForward = MoveBack = MoveLeft = MoveRight = 0;
-}
-
-OculusRoomTinyApp::~OculusRoomTinyApp()
-{
- RemoveHandlerFromDevices();
- pSensor.Clear();
- pHMD.Clear();
- destroyWindow();
- pApp = 0;
-}
-
-
-int OculusRoomTinyApp::OnStartup(const char* args)
-{
- OVR_UNUSED(args);
-
-
- // *** Oculus HMD & Sensor Initialization
-
- // Create DeviceManager and first available HMDDevice from it.
- // Sensor object is created from the HMD, to ensure that it is on the
- // correct device.
-
- pManager = *DeviceManager::Create();
-
- // We'll handle it's messages in this case.
- pManager->SetMessageHandler(this);
-
- CFOptionFlags detectionResult;
- const char* detectionMessage;
-
- do
- {
- // Release Sensor/HMD in case this is a retry.
- pSensor.Clear();
- pHMD.Clear();
- RenderParams.MonitorName.Clear();
-
- pHMD = *pManager->EnumerateDevices<HMDDevice>().CreateDevice();
- if (pHMD)
- {
- pSensor = *pHMD->GetSensor();
-
- // This will initialize HMDInfo with information about configured IPD,
- // screen size and other variables needed for correct projection.
- // We pass HMD DisplayDeviceName into the renderer to select the
- // correct monitor in full-screen mode.
- if (pHMD->GetDeviceInfo(&HMDInfo))
- {
- RenderParams.MonitorName = HMDInfo.DisplayDeviceName;
- RenderParams.DisplayId = HMDInfo.DisplayId;
- SConfig.SetHMDInfo(HMDInfo);
- }
- }
- else
- {
- // If we didn't detect an HMD, try to create the sensor directly.
- // This is useful for debugging sensor interaction; it is not needed in
- // a shipping app.
- pSensor = *pManager->EnumerateDevices<SensorDevice>().CreateDevice();
- }
-
-
- // If there was a problem detecting the Rift, display appropriate message.
- detectionResult = kCFUserNotificationAlternateResponse;
-
- if (!pHMD && !pSensor)
- detectionMessage = "Oculus Rift not detected.";
- else if (!pHMD)
- detectionMessage = "Oculus Sensor detected; HMD Display not detected.";
- else if (!pSensor)
- detectionMessage = "Oculus HMD Display detected; Sensor not detected.";
- else if (HMDInfo.DisplayDeviceName[0] == '\0')
- detectionMessage = "Oculus Sensor detected; HMD display EDID not detected.";
- else
- detectionMessage = 0;
-
- if (detectionMessage)
- {
- String messageText(detectionMessage);
- messageText += "\n\n"
- "Press 'Try Again' to run retry detection.\n"
- "Press 'Continue' to run full-screen anyway.";
-
- CFStringRef headerStrRef = CFStringCreateWithCString(NULL, "Oculus Rift Detection", kCFStringEncodingMacRoman);
- CFStringRef messageStrRef = CFStringCreateWithCString(NULL, messageText, kCFStringEncodingMacRoman);
-
- //launch the message box
- CFUserNotificationDisplayAlert(0,
- kCFUserNotificationNoteAlertLevel,
- NULL, NULL, NULL,
- headerStrRef, // header text
- messageStrRef, // message text
- CFSTR("Try again"),
- CFSTR("Continue"),
- CFSTR("Cancel"),
- &detectionResult);
-
- //Clean up the strings
- CFRelease(headerStrRef);
- CFRelease(messageStrRef);
-
- if (detectionResult == kCFUserNotificationCancelResponse ||
- detectionResult == kCFUserNotificationOtherResponse)
- return 1;
- }
-
- } while (detectionResult != kCFUserNotificationAlternateResponse);
-
-
- if (HMDInfo.HResolution > 0)
- {
- Width = HMDInfo.HResolution;
- Height = HMDInfo.VResolution;
- }
-
-
- if (!setupWindow())
- return 1;
-
- if (pSensor)
- {
- // We need to attach sensor to SensorFusion object for it to receive
- // body frame messages and update orientation. SFusion.GetOrientation()
- // is used in OnIdle() to orient the view.
- SFusion.AttachToSensor(pSensor);
- SFusion.SetDelegateMessageHandler(this);
- SFusion.SetPredictionEnabled(true);
- }
-
-
- // *** Initialize Rendering
-
- // Enable multi-sampling by default.
- RenderParams.Multisample = 4;
- RenderParams.Fullscreen = false;//true; //?
-
- // Setup Graphics.
- pRender = *OSX::RenderDevice::CreateDevice(RenderParams, (void*)View);
- if (!pRender)
- return 1;
-
-
- // *** Configure Stereo settings.
-
- SConfig.SetFullViewport(Viewport(0,0, Width, Height));
- SConfig.SetStereoMode(Stereo_LeftRight_Multipass);
-
- // Configure proper Distortion Fit.
- // For 7" screen, fit to touch left side of the view, leaving a bit of invisible
- // screen on the top (saves on rendering cost).
- // For smaller screens (5.5"), fit to the top.
- if (HMDInfo.HScreenSize > 0.0f)
- {
- if (HMDInfo.HScreenSize > 0.140f) // 7"
- SConfig.SetDistortionFitPointVP(-1.0f, 0.0f);
- else
- SConfig.SetDistortionFitPointVP(0.0f, 1.0f);
- }
-
- pRender->SetSceneRenderScale(SConfig.GetDistortionScale());
-
- SConfig.Set2DAreaFov(DegreeToRad(85.0f));
-
-
- // *** Populate Room Scene
-
- // This creates lights and models.
- PopulateRoomScene(&Scene, pRender);
-
-
- LastUpdate = GetAppTime();
- return 0;
-}
-
-void OculusRoomTinyApp::OnMessage(const Message& msg)
-{
- if (msg.Type == Message_DeviceAdded && msg.pDevice == pManager)
- {
- LogText("DeviceManager reported device added.\n");
- }
- else if (msg.Type == Message_DeviceRemoved && msg.pDevice == pManager)
- {
- LogText("DeviceManager reported device removed.\n");
- }
- else if (msg.Type == Message_DeviceAdded && msg.pDevice == pSensor)
- {
- LogText("Sensor reported device added.\n");
- }
- else if (msg.Type == Message_DeviceRemoved && msg.pDevice == pSensor)
- {
- LogText("Sensor reported device removed.\n");
- }
-}
-
-bool OculusRoomTinyApp::setupWindow()
-{
- NSRect winrect;
- winrect.origin.x = 0;
- winrect.origin.y = 1000;
- winrect.size.width = Width;
- winrect.size.height = Height;
- NSWindow* win = [[NSWindow alloc] initWithContentRect:winrect styleMask:NSTitledWindowMask|NSClosableWindowMask backing:NSBackingStoreBuffered defer:NO];
-
- OVRView* view = [[OVRView alloc] initWithFrame:winrect];
- [win setContentView:view];
- [win setAcceptsMouseMovedEvents:YES];
- [win setDelegate:view];
- [view setApp:pApp];
- Win = win;
- View = view;
-
- const char* title = "OculusRoomTiny";
- [((NSWindow*)Win) setTitle:[[NSString alloc] initWithBytes:title length:strlen(title) encoding:NSUTF8StringEncoding]];
-
- [NSCursor hide];
- [view warpMouseToCenter];
- CGAssociateMouseAndMouseCursorPosition(false);
-
- SetFullscreen(RenderParams, true);
- return true;
-}
-
-void OculusRoomTinyApp::destroyWindow()
-{
- SetFullscreen(RenderParams, false);
- [((NSWindow*)Win) close];
-}
-
-void OculusRoomTinyApp::OnMouseMove(int x, int y, int modifiers)
-{
- OVR_UNUSED(modifiers);
-
- // Mouse motion here is always relative.
- int dx = x, dy = y;
- const float maxPitch = ((3.1415f/2)*0.98f);
-
- // Apply to rotation. Subtract for right body frame rotation,
- // since yaw rotation is positive CCW when looking down on XZ plane.
- EyeYaw -= (Sensitivity * dx)/ 360.0f;
-
- if (!pSensor)
- {
- EyePitch -= (Sensitivity * dy)/ 360.0f;
-
- if (EyePitch > maxPitch)
- EyePitch = maxPitch;
- if (EyePitch < -maxPitch)
- EyePitch = -maxPitch;
- }
-}
-
-
-void OculusRoomTinyApp::OnKey(unsigned vk, bool down)
-{
- switch (vk)
- {
- case 'Q':
- if (down && ControlDown)
- Exit();;
- break;
- case Key_Escape:
- if (!down)
- Exit();
- break;
-
- // Handle player movement keys.
- // We just update movement state here, while the actual translation is done in OnIdle()
- // based on time.
- case 'W': MoveForward = down ? (MoveForward | 1) : (MoveForward & ~1); break;
- case 'S': MoveBack = down ? (MoveBack | 1) : (MoveBack & ~1); break;
- case 'A': MoveLeft = down ? (MoveLeft | 1) : (MoveLeft & ~1); break;
- case 'D': MoveRight = down ? (MoveRight | 1) : (MoveRight & ~1); break;
- case Key_Up: MoveForward = down ? (MoveForward | 2) : (MoveForward & ~2); break;
- case Key_Down: MoveBack = down ? (MoveBack | 2) : (MoveBack & ~2); break;
-
- case 'R':
- SFusion.Reset();
- break;
-
- case 'P':
- if (down)
- {
- // Toggle chromatic aberration correction on/off.
- RenderDevice::PostProcessShader shader = pRender->GetPostProcessShader();
-
- if (shader == RenderDevice::PostProcessShader_Distortion)
- {
- pRender->SetPostProcessShader(RenderDevice::PostProcessShader_DistortionAndChromAb);
- }
- else if (shader == RenderDevice::PostProcessShader_DistortionAndChromAb)
- {
- pRender->SetPostProcessShader(RenderDevice::PostProcessShader_Distortion);
- }
- else
- OVR_ASSERT(false);
- }
- break;
-
- // Switch rendering modes/distortion.
- case Key_F1:
- SConfig.SetStereoMode(Stereo_None);
- PostProcess = PostProcess_None;
- break;
- case Key_F2:
- SConfig.SetStereoMode(Stereo_LeftRight_Multipass);
- PostProcess = PostProcess_None;
- break;
- case Key_F3:
- SConfig.SetStereoMode(Stereo_LeftRight_Multipass);
- PostProcess = PostProcess_Distortion;
- break;
-
- // Stereo IPD adjustments, in meter (default IPD is 64mm).
- case '+':
- case '=':
- if (down)
- SConfig.SetIPD(SConfig.GetIPD() + 0.0005f * (ShiftDown ? 5.0f : 1.0f));
- break;
- case '-':
- case '_':
- if (down)
- SConfig.SetIPD(SConfig.GetIPD() - 0.0005f * (ShiftDown ? 5.0f : 1.0f));
- break;
-
- // Holding down Shift key accelerates adjustment velocity.
- case Key_Shift:
- ShiftDown = down;
- break;
- case Key_Meta:
- ControlDown = down;
- break;
- }
-}
-
-
-void OculusRoomTinyApp::OnIdle()
-{
- double curtime = GetAppTime();
- float dt = float(curtime - LastUpdate);
- LastUpdate = curtime;
-
-
- // Handle Sensor motion.
- // We extract Yaw, Pitch, Roll instead of directly using the orientation
- // to allow "additional" yaw manipulation with mouse/controller.
- if (pSensor)
- {
- Quatf hmdOrient = SFusion.GetOrientation();
- float yaw = 0.0f;
-
- hmdOrient.GetEulerAngles<Axis_Y, Axis_X, Axis_Z>(&yaw, &EyePitch, &EyeRoll);
-
- EyeYaw += (yaw - LastSensorYaw);
- LastSensorYaw = yaw;
- }
-
-
- if (!pSensor)
- {
- const float maxPitch = ((3.1415f/2)*0.98f);
- if (EyePitch > maxPitch)
- EyePitch = maxPitch;
- if (EyePitch < -maxPitch)
- EyePitch = -maxPitch;
- }
-
- // Handle keyboard movement.
- // This translates EyePos based on Yaw vector direction and keys pressed.
- // Note that Pitch and Roll do not affect movement (they only affect view).
- if (MoveForward || MoveBack || MoveLeft || MoveRight)
- {
- Vector3f localMoveVector(0,0,0);
- Matrix4f yawRotate = Matrix4f::RotationY(EyeYaw);
-
- if (MoveForward)
- localMoveVector = ForwardVector;
- else if (MoveBack)
- localMoveVector = -ForwardVector;
-
- if (MoveRight)
- localMoveVector += RightVector;
- else if (MoveLeft)
- localMoveVector -= RightVector;
-
- // Normalize vector so we don't move faster diagonally.
- localMoveVector.Normalize();
- Vector3f orientationVector = yawRotate.Transform(localMoveVector);
- orientationVector *= MoveSpeed * dt * (ShiftDown ? 3.0f : 1.0f);
-
- EyePos += orientationVector;
- }
-
- // Rotate and position View Camera, using YawPitchRoll in BodyFrame coordinates.
- //
- Matrix4f rollPitchYaw = Matrix4f::RotationY(EyeYaw) * Matrix4f::RotationX(EyePitch) *
- Matrix4f::RotationZ(EyeRoll);
- Vector3f up = rollPitchYaw.Transform(UpVector);
- Vector3f forward = rollPitchYaw.Transform(ForwardVector);
-
-
- // Minimal head modelling.
- float headBaseToEyeHeight = 0.15f; // Vertical height of eye from base of head
- float headBaseToEyeProtrusion = 0.09f; // Distance forward of eye from base of head
-
- Vector3f eyeCenterInHeadFrame(0.0f, headBaseToEyeHeight, -headBaseToEyeProtrusion);
- Vector3f shiftedEyePos = EyePos + rollPitchYaw.Transform(eyeCenterInHeadFrame);
- shiftedEyePos.y -= eyeCenterInHeadFrame.y; // Bring the head back down to original height
-
- ViewMat = Matrix4f::LookAtRH(shiftedEyePos, shiftedEyePos + forward, up);
-
- // This is what transformation would be without head modeling.
- // View = Matrix4f::LookAtRH(EyePos, EyePos + forward, up);
-
- switch(SConfig.GetStereoMode())
- {
- case Stereo_None:
- Render(SConfig.GetEyeRenderParams(StereoEye_Center));
- break;
-
- case Stereo_LeftRight_Multipass:
- Render(SConfig.GetEyeRenderParams(StereoEye_Left));
- Render(SConfig.GetEyeRenderParams(StereoEye_Right));
- break;
- }
-
- pRender->Present();
- // Force GPU to flush the scene, resulting in the lowest possible latency.
- pRender->ForceFlushGPU();
-}
-
-
-// Render the scene for one eye.
-void OculusRoomTinyApp::Render(const StereoEyeParams& stereo)
-{
- pRender->BeginScene(PostProcess);
-
- // Apply Viewport/Projection for the eye.
- pRender->ApplyStereoParams(stereo);
- pRender->Clear();
- pRender->SetDepthMode(true, true);
-
- Scene.Render(pRender, stereo.ViewAdjust * ViewMat);
-
- pRender->FinishScene();
-}
-
-void OculusRoomTinyApp::Exit()
-{
- [NsApp stop:nil];
- Quit = true;
-}
-
-bool OculusRoomTinyApp::SetFullscreen(const RenderTiny::RendererParams& rp, int fullscreen)
-{
- if (fullscreen == RenderTiny::Display_Window)
- [(OVRView*)View exitFullScreenModeWithOptions:nil];
- else
- {
- NSScreen* usescreen = [NSScreen mainScreen];
- NSArray* screens = [NSScreen screens];
- for (int i = 0; i < [screens count]; i++)
- {
- NSScreen* s = (NSScreen*)[screens objectAtIndex:i];
- CGDirectDisplayID disp = [OVRView displayFromScreen:s];
-
- if (disp == rp.DisplayId)
- usescreen = s;
- }
-
- [(OVRView*)View enterFullScreenMode:usescreen withOptions:nil];
- }
-
- if (pRender)
- pRender->SetFullscreen((RenderTiny::DisplayMode)fullscreen);
- return 1;
-}
-
-//-------------------------------------------------------------------------------------
-// ***** OS X-Specific Logic
-
-@implementation OVRApp
-
-- (void)dealloc
-{
- [super dealloc];
-}
-
-- (void)run
-{
- NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
- _running = YES;
- OculusRoomTinyApp* app;
-
- // Initializes LibOVR. This LogMask_All enables maximum logging.
- // Custom allocator can also be specified here.
- OVR::System::Init(OVR::Log::ConfigureDefaultLog(OVR::LogMask_All));
-
- int exitCode = 0;
- do
- {
- {
- using namespace OVR;
-
- // CreateApplication must be the first call since it does OVR::System::Initialize.
- app = new OculusRoomTinyApp(self);
- // The platform attached to an app will be deleted by DestroyApplication.
-
- [self setApp:app];
-
- const char* argv[] = {"OVRApp"};
- exitCode = app->OnStartup(argv[0]);
- if (exitCode)
- break;
- }
- [self finishLaunching];
- [pool drain];
-
- while ([self isRunning])
- {
- pool = [[NSAutoreleasePool alloc] init];
- NSEvent* event = [self nextEventMatchingMask:NSAnyEventMask untilDate:nil inMode:NSDefaultRunLoopMode dequeue:YES];
- if (event)
- {
- [self sendEvent:event];
- }
- _App->OnIdle();
- [pool drain];
- }
- } while(0);
-
- delete app;
-
- // No OVR functions involving memory are allowed after this.
- OVR::System::Destroy();
-}
-
-@end
-
-static int KeyMap[][2] =
-{
- { NSDeleteFunctionKey, OVR::Key_Delete },
- { '\t', OVR::Key_Tab },
- { '\n', OVR::Key_Return },
- { NSPauseFunctionKey, OVR::Key_Pause },
- { 27, OVR::Key_Escape },
- { 127, OVR::Key_Backspace },
- { ' ', OVR::Key_Space },
- { NSPageUpFunctionKey, OVR::Key_PageUp },
- { NSPageDownFunctionKey, OVR::Key_PageDown },
- { NSNextFunctionKey, OVR::Key_PageDown },
- { NSEndFunctionKey, OVR::Key_End },
- { NSHomeFunctionKey, OVR::Key_Home },
- { NSLeftArrowFunctionKey, OVR::Key_Left },
- { NSUpArrowFunctionKey, OVR::Key_Up },
- { NSRightArrowFunctionKey, OVR::Key_Right },
- { NSDownArrowFunctionKey, OVR::Key_Down },
- { NSInsertFunctionKey, OVR::Key_Insert },
- { NSDeleteFunctionKey, OVR::Key_Delete },
- { NSHelpFunctionKey, OVR::Key_Insert },
-};
-
-
-static KeyCode MapToKeyCode(wchar_t vk)
-{
- unsigned key = Key_None;
-
- if ((vk >= 'a') && (vk <= 'z'))
- {
- key = vk - 'a' + Key_A;
- }
- else if ((vk >= ' ') && (vk <= '~'))
- {
- key = vk;
- }
- else if ((vk >= '0') && (vk <= '9'))
- {
- key = vk - '0' + Key_Num0;
- }
- else if ((vk >= NSF1FunctionKey) && (vk <= NSF15FunctionKey))
- {
- key = vk - NSF1FunctionKey + Key_F1;
- }
- else
- {
- for (unsigned i = 0; i< (sizeof(KeyMap) / sizeof(KeyMap[1])); i++)
- {
- if (vk == KeyMap[i][0])
- {
- key = KeyMap[i][1];
- break;
- }
- }
- }
-
- return (KeyCode)key;
-}
-
-@implementation OVRView
-
--(BOOL) acceptsFirstResponder
-{
- return YES;
-}
--(BOOL) acceptsFirstMouse:(NSEvent *)ev
-{
- return YES;
-}
-
-+(CGDirectDisplayID) displayFromScreen:(NSScreen *)s
-{
- NSNumber* didref = (NSNumber*)[[s deviceDescription] objectForKey:@"NSScreenNumber"];
- CGDirectDisplayID disp = (CGDirectDisplayID)[didref longValue];
- return disp;
-}
-
--(void) warpMouseToCenter
-{
- NSPoint w;
- w.x = _App->GetWidth()/2.0f;
- w.y = _App->GetHeight()/2.0f;
- w = [[self window] convertBaseToScreen:w];
- CGDirectDisplayID disp = [OVRView displayFromScreen:[[self window] screen]];
- CGPoint p = {w.x, CGDisplayPixelsHigh(disp)-w.y};
- CGDisplayMoveCursorToPoint(disp, p);
-}
-
--(void) keyDown:(NSEvent*)ev
-{
- NSString* chars = [ev charactersIgnoringModifiers];
- if ([chars length])
- {
- wchar_t ch = [chars characterAtIndex:0];
- OVR::KeyCode key = MapToKeyCode(ch);
- _App->OnKey(key, true);
- }
-}
--(void) keyUp:(NSEvent*)ev
-{
- NSString* chars = [ev charactersIgnoringModifiers];
- if ([chars length])
- {
- wchar_t ch = [chars characterAtIndex:0];
- OVR::KeyCode key = MapToKeyCode(ch);
- _App->OnKey(key, false);
-
- }
-}
-
-
--(void)flagsChanged:(NSEvent *)ev
-{
- static const OVR::KeyCode ModifierKeys[] = {OVR::Key_None, OVR::Key_Shift, OVR::Key_Control, OVR::Key_Alt, OVR::Key_Meta};
-
- unsigned long cmods = [ev modifierFlags];
- if ((cmods & 0xffff0000) != _Modifiers)
- {
- uint32_t mods = 0;
- if (cmods & NSShiftKeyMask)
- mods |= 0x01;
- if (cmods & NSControlKeyMask)
- mods |= 0x02;
- if (cmods & NSAlternateKeyMask)
- mods |= 0x04;
- if (cmods & NSCommandKeyMask)
- mods |= 0x08;
-
- for (int i = 1; i <= 4; i++)
- {
- unsigned long m = (1 << (16+i));
- if ((cmods & m) != (_Modifiers & m))
- {
- if (cmods & m)
- _App->OnKey(ModifierKeys[i], true);
- else
- _App->OnKey(ModifierKeys[i], false);
- }
- }
- _Modifiers = cmods & 0xffff0000;
- }
-}
-
--(void)ProcessMouse:(NSEvent*)ev
-{
- switch ([ev type])
- {
- case NSLeftMouseDragged:
- case NSRightMouseDragged:
- case NSOtherMouseDragged:
- case NSMouseMoved:
- {
- int dx = [ev deltaX];
- int dy = [ev deltaY];
-
- if (dx != 0 || dy != 0)
- {
- _App->OnMouseMove(dx, dy, 0);
- [self warpMouseToCenter];
- }
- }
- break;
- case NSLeftMouseDown:
- case NSRightMouseDown:
- case NSOtherMouseDown:
- break;
- }
-}
-
--(void) mouseMoved:(NSEvent*)ev
-{
- [self ProcessMouse:ev];
-}
--(void) mouseDragged:(NSEvent*)ev
-{
- [self ProcessMouse:ev];
-}
-
--(void) mouseDown:(NSEvent*)ev
-{
- [self warpMouseToCenter];
- CGAssociateMouseAndMouseCursorPosition(false);
- [NSCursor hide];
-}
-
-//-(void)
-
--(id) initWithFrame:(NSRect)frameRect
-{
- NSOpenGLPixelFormatAttribute attr[] =
- {NSOpenGLPFAWindow, NSOpenGLPFADoubleBuffer, NSOpenGLPFADepthSize, 24, nil};
-
- NSOpenGLPixelFormat *pf = [[[NSOpenGLPixelFormat alloc] initWithAttributes:attr] autorelease];
-
- self = [super initWithFrame:frameRect pixelFormat:pf];
- GLint swap = 0;
- [[self openGLContext] setValues:&swap forParameter:NSOpenGLCPSwapInterval];
- //[self setWantsBestResolutionOpenGLSurface:YES];
- return self;
-}
-
--(BOOL)windowShouldClose:(id)sender
-{
- _App->Exit();
- return 1;
-}
-
-@end
-
-// GL OSX-specific logic
-namespace OSX {
-
- RenderDevice::RenderDevice(const RendererParams& p, void* osview, void* context)
- : GL::RenderDevice(p), Context(context)
- {
- OVRView* view = (OVRView*)osview;
- NSRect bounds = [view bounds];
- WindowWidth = bounds.size.width;
- WindowHeight= bounds.size.height;
-
- }
-
- RenderDevice* RenderDevice::CreateDevice(const RendererParams& rp, void* osview)
- {
- OVRView* view = (OVRView*)osview;
- NSOpenGLContext *context = [view openGLContext];
- if (!context)
- return NULL;
-
- [context makeCurrentContext];
- [[view window] makeKeyAndOrderFront:nil];
-
- return new OSX::RenderDevice(rp, osview, context);
- }
-
- void RenderDevice::Present()
- {
- NSOpenGLContext *context = (NSOpenGLContext*)Context;
- [context flushBuffer];
- }
-
- void RenderDevice::Shutdown()
- {
- Context = NULL;
- }
-
- bool RenderDevice::SetFullscreen(DisplayMode fullscreen)
- {
- Params.Fullscreen = fullscreen;
- return 1;
- }
-
-}
-
-
-int main(int argc, char *argv[])
-{
- NSApplication* nsapp = [OVRApp sharedApplication];
- [nsapp run];
- return 0;
-}
-
+/************************************************************************************
+
+ Filename : OSX_OculusRoomTiny.mm
+ Content : Simplest possible first-person view test application for Oculus Rift
+ Created : May 7, 2013
+ Authors : Michael Antonov, Andrew Reisse, Artem Bolgar
+
+ Copyright : Copyright 2013 Oculus, Inc. All Rights reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+ *************************************************************************************/
+
+#import "OSX_OculusRoomTiny.h"
+#include "RenderTiny_GL_Device.h"
+
+#include "Kernel/OVR_KeyCodes.h"
+
+using namespace OVR;
+
+//-------------------------------------------------------------------------------------
+// ***** OculusRoomTiny Class
+
+// Static pApp simplifies routing the window function.
+OculusRoomTinyApp* OculusRoomTinyApp::pApp = 0;
+
+
+OculusRoomTinyApp::OculusRoomTinyApp(OVRApp* nsapp)
+ : pRender(0),
+ LastUpdate(0),
+ NsApp(nsapp),
+ Quit(0),
+
+ // Initial location
+ EyePos(0.0f, 1.6f, -5.0f),
+ EyeYaw(YawInitial), EyePitch(0), EyeRoll(0),
+ LastSensorYaw(0),
+ SConfig(),
+ PostProcess(PostProcess_Distortion),
+ ShiftDown(false),
+ ControlDown(false)
+{
+ pApp = this;
+
+ Width = 1280;
+ Height = 800;
+
+ StartupTicks = OVR::Timer::GetTicks();
+
+ MoveForward = MoveBack = MoveLeft = MoveRight = 0;
+}
+
+OculusRoomTinyApp::~OculusRoomTinyApp()
+{
+ RemoveHandlerFromDevices();
+ pSensor.Clear();
+ pHMD.Clear();
+ destroyWindow();
+ pApp = 0;
+}
+
+
+int OculusRoomTinyApp::OnStartup(const char* args)
+{
+ OVR_UNUSED(args);
+
+
+ // *** Oculus HMD & Sensor Initialization
+
+ // Create DeviceManager and first available HMDDevice from it.
+ // Sensor object is created from the HMD, to ensure that it is on the
+ // correct device.
+
+ pManager = *DeviceManager::Create();
+
+ // We'll handle it's messages in this case.
+ pManager->SetMessageHandler(this);
+
+ CFOptionFlags detectionResult;
+ const char* detectionMessage;
+
+ do
+ {
+ // Release Sensor/HMD in case this is a retry.
+ pSensor.Clear();
+ pHMD.Clear();
+ RenderParams.MonitorName.Clear();
+
+ pHMD = *pManager->EnumerateDevices<HMDDevice>().CreateDevice();
+ if (pHMD)
+ {
+ pSensor = *pHMD->GetSensor();
+
+ // This will initialize HMDInfo with information about configured IPD,
+ // screen size and other variables needed for correct projection.
+ // We pass HMD DisplayDeviceName into the renderer to select the
+ // correct monitor in full-screen mode.
+ if (pHMD->GetDeviceInfo(&HMDInfo))
+ {
+ RenderParams.MonitorName = HMDInfo.DisplayDeviceName;
+ RenderParams.DisplayId = HMDInfo.DisplayId;
+ SConfig.SetHMDInfo(HMDInfo);
+ }
+ }
+ else
+ {
+ // If we didn't detect an HMD, try to create the sensor directly.
+ // This is useful for debugging sensor interaction; it is not needed in
+ // a shipping app.
+ pSensor = *pManager->EnumerateDevices<SensorDevice>().CreateDevice();
+ }
+
+
+ // If there was a problem detecting the Rift, display appropriate message.
+ detectionResult = kCFUserNotificationAlternateResponse;
+
+ if (!pHMD && !pSensor)
+ detectionMessage = "Oculus Rift not detected.";
+ else if (!pHMD)
+ detectionMessage = "Oculus Sensor detected; HMD Display not detected.";
+ else if (!pSensor)
+ detectionMessage = "Oculus HMD Display detected; Sensor not detected.";
+ else if (HMDInfo.DisplayDeviceName[0] == '\0')
+ detectionMessage = "Oculus Sensor detected; HMD display EDID not detected.";
+ else
+ detectionMessage = 0;
+
+ if (detectionMessage)
+ {
+ String messageText(detectionMessage);
+ messageText += "\n\n"
+ "Press 'Try Again' to run retry detection.\n"
+ "Press 'Continue' to run full-screen anyway.";
+
+ CFStringRef headerStrRef = CFStringCreateWithCString(NULL, "Oculus Rift Detection", kCFStringEncodingMacRoman);
+ CFStringRef messageStrRef = CFStringCreateWithCString(NULL, messageText, kCFStringEncodingMacRoman);
+
+ //launch the message box
+ CFUserNotificationDisplayAlert(0,
+ kCFUserNotificationNoteAlertLevel,
+ NULL, NULL, NULL,
+ headerStrRef, // header text
+ messageStrRef, // message text
+ CFSTR("Try again"),
+ CFSTR("Continue"),
+ CFSTR("Cancel"),
+ &detectionResult);
+
+ //Clean up the strings
+ CFRelease(headerStrRef);
+ CFRelease(messageStrRef);
+
+ if (detectionResult == kCFUserNotificationCancelResponse ||
+ detectionResult == kCFUserNotificationOtherResponse)
+ return 1;
+ }
+
+ } while (detectionResult != kCFUserNotificationAlternateResponse);
+
+
+ if (HMDInfo.HResolution > 0)
+ {
+ Width = HMDInfo.HResolution;
+ Height = HMDInfo.VResolution;
+ }
+
+
+ if (!setupWindow())
+ return 1;
+
+ if (pSensor)
+ {
+ // We need to attach sensor to SensorFusion object for it to receive
+ // body frame messages and update orientation. SFusion.GetOrientation()
+ // is used in OnIdle() to orient the view.
+ SFusion.AttachToSensor(pSensor);
+ SFusion.SetDelegateMessageHandler(this);
+ SFusion.SetPredictionEnabled(true);
+ }
+
+
+ // *** Initialize Rendering
+
+ // Enable multi-sampling by default.
+ RenderParams.Multisample = 4;
+ RenderParams.Fullscreen = false;//true; //?
+
+ // Setup Graphics.
+ pRender = *OSX::RenderDevice::CreateDevice(RenderParams, (void*)View);
+ if (!pRender)
+ return 1;
+
+
+ // *** Configure Stereo settings.
+
+ SConfig.SetFullViewport(Viewport(0,0, Width, Height));
+ SConfig.SetStereoMode(Stereo_LeftRight_Multipass);
+
+ // Configure proper Distortion Fit.
+ // For 7" screen, fit to touch left side of the view, leaving a bit of invisible
+ // screen on the top (saves on rendering cost).
+ // For smaller screens (5.5"), fit to the top.
+ if (HMDInfo.HScreenSize > 0.0f)
+ {
+ if (HMDInfo.HScreenSize > 0.140f) // 7"
+ SConfig.SetDistortionFitPointVP(-1.0f, 0.0f);
+ else
+ SConfig.SetDistortionFitPointVP(0.0f, 1.0f);
+ }
+
+ pRender->SetSceneRenderScale(SConfig.GetDistortionScale());
+
+ SConfig.Set2DAreaFov(DegreeToRad(85.0f));
+
+
+ // *** Populate Room Scene
+
+ // This creates lights and models.
+ PopulateRoomScene(&Scene, pRender);
+
+
+ LastUpdate = GetAppTime();
+ return 0;
+}
+
+void OculusRoomTinyApp::OnMessage(const Message& msg)
+{
+ if (msg.Type == Message_DeviceAdded && msg.pDevice == pManager)
+ {
+ LogText("DeviceManager reported device added.\n");
+ }
+ else if (msg.Type == Message_DeviceRemoved && msg.pDevice == pManager)
+ {
+ LogText("DeviceManager reported device removed.\n");
+ }
+ else if (msg.Type == Message_DeviceAdded && msg.pDevice == pSensor)
+ {
+ LogText("Sensor reported device added.\n");
+ }
+ else if (msg.Type == Message_DeviceRemoved && msg.pDevice == pSensor)
+ {
+ LogText("Sensor reported device removed.\n");
+ }
+}
+
+bool OculusRoomTinyApp::setupWindow()
+{
+ NSRect winrect;
+ winrect.origin.x = 0;
+ winrect.origin.y = 1000;
+ winrect.size.width = Width;
+ winrect.size.height = Height;
+ NSWindow* win = [[NSWindow alloc] initWithContentRect:winrect styleMask:NSTitledWindowMask|NSClosableWindowMask backing:NSBackingStoreBuffered defer:NO];
+
+ OVRView* view = [[OVRView alloc] initWithFrame:winrect];
+ [win setContentView:view];
+ [win setAcceptsMouseMovedEvents:YES];
+ [win setDelegate:view];
+ [view setApp:pApp];
+ Win = win;
+ View = view;
+
+ const char* title = "OculusRoomTiny";
+ [((NSWindow*)Win) setTitle:[[NSString alloc] initWithBytes:title length:strlen(title) encoding:NSUTF8StringEncoding]];
+
+ [NSCursor hide];
+ [view warpMouseToCenter];
+ CGAssociateMouseAndMouseCursorPosition(false);
+
+ SetFullscreen(RenderParams, true);
+ return true;
+}
+
+void OculusRoomTinyApp::destroyWindow()
+{
+ SetFullscreen(RenderParams, false);
+ [((NSWindow*)Win) close];
+}
+
+void OculusRoomTinyApp::OnMouseMove(int x, int y, int modifiers)
+{
+ OVR_UNUSED(modifiers);
+
+ // Mouse motion here is always relative.
+ int dx = x, dy = y;
+ const float maxPitch = ((3.1415f/2)*0.98f);
+
+ // Apply to rotation. Subtract for right body frame rotation,
+ // since yaw rotation is positive CCW when looking down on XZ plane.
+ EyeYaw -= (Sensitivity * dx)/ 360.0f;
+
+ if (!pSensor)
+ {
+ EyePitch -= (Sensitivity * dy)/ 360.0f;
+
+ if (EyePitch > maxPitch)
+ EyePitch = maxPitch;
+ if (EyePitch < -maxPitch)
+ EyePitch = -maxPitch;
+ }
+}
+
+
+void OculusRoomTinyApp::OnKey(unsigned vk, bool down)
+{
+ switch (vk)
+ {
+ case 'Q':
+ if (down && ControlDown)
+ Exit();;
+ break;
+ case Key_Escape:
+ if (!down)
+ Exit();
+ break;
+
+ // Handle player movement keys.
+ // We just update movement state here, while the actual translation is done in OnIdle()
+ // based on time.
+ case 'W': MoveForward = down ? (MoveForward | 1) : (MoveForward & ~1); break;
+ case 'S': MoveBack = down ? (MoveBack | 1) : (MoveBack & ~1); break;
+ case 'A': MoveLeft = down ? (MoveLeft | 1) : (MoveLeft & ~1); break;
+ case 'D': MoveRight = down ? (MoveRight | 1) : (MoveRight & ~1); break;
+ case Key_Up: MoveForward = down ? (MoveForward | 2) : (MoveForward & ~2); break;
+ case Key_Down: MoveBack = down ? (MoveBack | 2) : (MoveBack & ~2); break;
+
+ case 'R':
+ SFusion.Reset();
+ break;
+
+ case 'P':
+ if (down)
+ {
+ // Toggle chromatic aberration correction on/off.
+ RenderDevice::PostProcessShader shader = pRender->GetPostProcessShader();
+
+ if (shader == RenderDevice::PostProcessShader_Distortion)
+ {
+ pRender->SetPostProcessShader(RenderDevice::PostProcessShader_DistortionAndChromAb);
+ }
+ else if (shader == RenderDevice::PostProcessShader_DistortionAndChromAb)
+ {
+ pRender->SetPostProcessShader(RenderDevice::PostProcessShader_Distortion);
+ }
+ else
+ OVR_ASSERT(false);
+ }
+ break;
+
+ // Switch rendering modes/distortion.
+ case Key_F1:
+ SConfig.SetStereoMode(Stereo_None);
+ PostProcess = PostProcess_None;
+ break;
+ case Key_F2:
+ SConfig.SetStereoMode(Stereo_LeftRight_Multipass);
+ PostProcess = PostProcess_None;
+ break;
+ case Key_F3:
+ SConfig.SetStereoMode(Stereo_LeftRight_Multipass);
+ PostProcess = PostProcess_Distortion;
+ break;
+
+ // Stereo IPD adjustments, in meter (default IPD is 64mm).
+ case '+':
+ case '=':
+ if (down)
+ SConfig.SetIPD(SConfig.GetIPD() + 0.0005f * (ShiftDown ? 5.0f : 1.0f));
+ break;
+ case '-':
+ case '_':
+ if (down)
+ SConfig.SetIPD(SConfig.GetIPD() - 0.0005f * (ShiftDown ? 5.0f : 1.0f));
+ break;
+
+ // Holding down Shift key accelerates adjustment velocity.
+ case Key_Shift:
+ ShiftDown = down;
+ break;
+ case Key_Meta:
+ ControlDown = down;
+ break;
+ }
+}
+
+
+void OculusRoomTinyApp::OnIdle()
+{
+ double curtime = GetAppTime();
+ float dt = float(curtime - LastUpdate);
+ LastUpdate = curtime;
+
+
+ // Handle Sensor motion.
+ // We extract Yaw, Pitch, Roll instead of directly using the orientation
+ // to allow "additional" yaw manipulation with mouse/controller.
+ if (pSensor)
+ {
+ Quatf hmdOrient = SFusion.GetOrientation();
+ float yaw = 0.0f;
+
+ hmdOrient.GetEulerAngles<Axis_Y, Axis_X, Axis_Z>(&yaw, &EyePitch, &EyeRoll);
+
+ EyeYaw += (yaw - LastSensorYaw);
+ LastSensorYaw = yaw;
+ }
+
+
+ if (!pSensor)
+ {
+ const float maxPitch = ((3.1415f/2)*0.98f);
+ if (EyePitch > maxPitch)
+ EyePitch = maxPitch;
+ if (EyePitch < -maxPitch)
+ EyePitch = -maxPitch;
+ }
+
+ // Handle keyboard movement.
+ // This translates EyePos based on Yaw vector direction and keys pressed.
+ // Note that Pitch and Roll do not affect movement (they only affect view).
+ if (MoveForward || MoveBack || MoveLeft || MoveRight)
+ {
+ Vector3f localMoveVector(0,0,0);
+ Matrix4f yawRotate = Matrix4f::RotationY(EyeYaw);
+
+ if (MoveForward)
+ localMoveVector = ForwardVector;
+ else if (MoveBack)
+ localMoveVector = -ForwardVector;
+
+ if (MoveRight)
+ localMoveVector += RightVector;
+ else if (MoveLeft)
+ localMoveVector -= RightVector;
+
+ // Normalize vector so we don't move faster diagonally.
+ localMoveVector.Normalize();
+ Vector3f orientationVector = yawRotate.Transform(localMoveVector);
+ orientationVector *= MoveSpeed * dt * (ShiftDown ? 3.0f : 1.0f);
+
+ EyePos += orientationVector;
+ }
+
+ // Rotate and position View Camera, using YawPitchRoll in BodyFrame coordinates.
+ //
+ Matrix4f rollPitchYaw = Matrix4f::RotationY(EyeYaw) * Matrix4f::RotationX(EyePitch) *
+ Matrix4f::RotationZ(EyeRoll);
+ Vector3f up = rollPitchYaw.Transform(UpVector);
+ Vector3f forward = rollPitchYaw.Transform(ForwardVector);
+
+
+ // Minimal head modelling.
+ float headBaseToEyeHeight = 0.15f; // Vertical height of eye from base of head
+ float headBaseToEyeProtrusion = 0.09f; // Distance forward of eye from base of head
+
+ Vector3f eyeCenterInHeadFrame(0.0f, headBaseToEyeHeight, -headBaseToEyeProtrusion);
+ Vector3f shiftedEyePos = EyePos + rollPitchYaw.Transform(eyeCenterInHeadFrame);
+ shiftedEyePos.y -= eyeCenterInHeadFrame.y; // Bring the head back down to original height
+
+ ViewMat = Matrix4f::LookAtRH(shiftedEyePos, shiftedEyePos + forward, up);
+
+ // This is what transformation would be without head modeling.
+ // View = Matrix4f::LookAtRH(EyePos, EyePos + forward, up);
+
+ switch(SConfig.GetStereoMode())
+ {
+ case Stereo_None:
+ Render(SConfig.GetEyeRenderParams(StereoEye_Center));
+ break;
+
+ case Stereo_LeftRight_Multipass:
+ Render(SConfig.GetEyeRenderParams(StereoEye_Left));
+ Render(SConfig.GetEyeRenderParams(StereoEye_Right));
+ break;
+ }
+
+ pRender->Present();
+ // Force GPU to flush the scene, resulting in the lowest possible latency.
+ pRender->ForceFlushGPU();
+}
+
+
+// Render the scene for one eye.
+void OculusRoomTinyApp::Render(const StereoEyeParams& stereo)
+{
+ pRender->BeginScene(PostProcess);
+
+ // Apply Viewport/Projection for the eye.
+ pRender->ApplyStereoParams(stereo);
+ pRender->Clear();
+ pRender->SetDepthMode(true, true);
+
+ Scene.Render(pRender, stereo.ViewAdjust * ViewMat);
+
+ pRender->FinishScene();
+}
+
+void OculusRoomTinyApp::Exit()
+{
+ [NsApp stop:nil];
+ Quit = true;
+}
+
+bool OculusRoomTinyApp::SetFullscreen(const RenderTiny::RendererParams& rp, int fullscreen)
+{
+ if (fullscreen == RenderTiny::Display_Window)
+ [(OVRView*)View exitFullScreenModeWithOptions:nil];
+ else
+ {
+ NSScreen* usescreen = [NSScreen mainScreen];
+ NSArray* screens = [NSScreen screens];
+ for (int i = 0; i < [screens count]; i++)
+ {
+ NSScreen* s = (NSScreen*)[screens objectAtIndex:i];
+ CGDirectDisplayID disp = [OVRView displayFromScreen:s];
+
+ if (disp == rp.DisplayId)
+ usescreen = s;
+ }
+
+ [(OVRView*)View enterFullScreenMode:usescreen withOptions:nil];
+ }
+
+ if (pRender)
+ pRender->SetFullscreen((RenderTiny::DisplayMode)fullscreen);
+ return 1;
+}
+
+//-------------------------------------------------------------------------------------
+// ***** OS X-Specific Logic
+
+@implementation OVRApp
+
+- (void)dealloc
+{
+ [super dealloc];
+}
+
+- (void)run
+{
+ NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
+ _running = YES;
+ OculusRoomTinyApp* app;
+
+ // Initializes LibOVR. This LogMask_All enables maximum logging.
+ // Custom allocator can also be specified here.
+ OVR::System::Init(OVR::Log::ConfigureDefaultLog(OVR::LogMask_All));
+
+ int exitCode = 0;
+ do
+ {
+ {
+ using namespace OVR;
+
+ // CreateApplication must be the first call since it does OVR::System::Initialize.
+ app = new OculusRoomTinyApp(self);
+ // The platform attached to an app will be deleted by DestroyApplication.
+
+ [self setApp:app];
+
+ const char* argv[] = {"OVRApp"};
+ exitCode = app->OnStartup(argv[0]);
+ if (exitCode)
+ break;
+ }
+ [self finishLaunching];
+ [pool drain];
+
+ while ([self isRunning])
+ {
+ pool = [[NSAutoreleasePool alloc] init];
+ NSEvent* event = [self nextEventMatchingMask:NSAnyEventMask untilDate:nil inMode:NSDefaultRunLoopMode dequeue:YES];
+ if (event)
+ {
+ [self sendEvent:event];
+ }
+ _App->OnIdle();
+ [pool drain];
+ }
+ } while(0);
+
+ delete app;
+
+ // No OVR functions involving memory are allowed after this.
+ OVR::System::Destroy();
+}
+
+@end
+
+static int KeyMap[][2] =
+{
+ { NSDeleteFunctionKey, OVR::Key_Delete },
+ { '\t', OVR::Key_Tab },
+ { '\n', OVR::Key_Return },
+ { NSPauseFunctionKey, OVR::Key_Pause },
+ { 27, OVR::Key_Escape },
+ { 127, OVR::Key_Backspace },
+ { ' ', OVR::Key_Space },
+ { NSPageUpFunctionKey, OVR::Key_PageUp },
+ { NSPageDownFunctionKey, OVR::Key_PageDown },
+ { NSNextFunctionKey, OVR::Key_PageDown },
+ { NSEndFunctionKey, OVR::Key_End },
+ { NSHomeFunctionKey, OVR::Key_Home },
+ { NSLeftArrowFunctionKey, OVR::Key_Left },
+ { NSUpArrowFunctionKey, OVR::Key_Up },
+ { NSRightArrowFunctionKey, OVR::Key_Right },
+ { NSDownArrowFunctionKey, OVR::Key_Down },
+ { NSInsertFunctionKey, OVR::Key_Insert },
+ { NSDeleteFunctionKey, OVR::Key_Delete },
+ { NSHelpFunctionKey, OVR::Key_Insert },
+};
+
+
+static KeyCode MapToKeyCode(wchar_t vk)
+{
+ unsigned key = Key_None;
+
+ if ((vk >= 'a') && (vk <= 'z'))
+ {
+ key = vk - 'a' + Key_A;
+ }
+ else if ((vk >= ' ') && (vk <= '~'))
+ {
+ key = vk;
+ }
+ else if ((vk >= '0') && (vk <= '9'))
+ {
+ key = vk - '0' + Key_Num0;
+ }
+ else if ((vk >= NSF1FunctionKey) && (vk <= NSF15FunctionKey))
+ {
+ key = vk - NSF1FunctionKey + Key_F1;
+ }
+ else
+ {
+ for (unsigned i = 0; i< (sizeof(KeyMap) / sizeof(KeyMap[1])); i++)
+ {
+ if (vk == KeyMap[i][0])
+ {
+ key = KeyMap[i][1];
+ break;
+ }
+ }
+ }
+
+ return (KeyCode)key;
+}
+
+@implementation OVRView
+
+-(BOOL) acceptsFirstResponder
+{
+ return YES;
+}
+-(BOOL) acceptsFirstMouse:(NSEvent *)ev
+{
+ return YES;
+}
+
++(CGDirectDisplayID) displayFromScreen:(NSScreen *)s
+{
+ NSNumber* didref = (NSNumber*)[[s deviceDescription] objectForKey:@"NSScreenNumber"];
+ CGDirectDisplayID disp = (CGDirectDisplayID)[didref longValue];
+ return disp;
+}
+
+-(void) warpMouseToCenter
+{
+ NSPoint w;
+ w.x = _App->GetWidth()/2.0f;
+ w.y = _App->GetHeight()/2.0f;
+ w = [[self window] convertBaseToScreen:w];
+ CGDirectDisplayID disp = [OVRView displayFromScreen:[[self window] screen]];
+ CGPoint p = {w.x, CGDisplayPixelsHigh(disp)-w.y};
+ CGDisplayMoveCursorToPoint(disp, p);
+}
+
+-(void) keyDown:(NSEvent*)ev
+{
+ NSString* chars = [ev charactersIgnoringModifiers];
+ if ([chars length])
+ {
+ wchar_t ch = [chars characterAtIndex:0];
+ OVR::KeyCode key = MapToKeyCode(ch);
+ _App->OnKey(key, true);
+ }
+}
+-(void) keyUp:(NSEvent*)ev
+{
+ NSString* chars = [ev charactersIgnoringModifiers];
+ if ([chars length])
+ {
+ wchar_t ch = [chars characterAtIndex:0];
+ OVR::KeyCode key = MapToKeyCode(ch);
+ _App->OnKey(key, false);
+
+ }
+}
+
+
+-(void)flagsChanged:(NSEvent *)ev
+{
+ static const OVR::KeyCode ModifierKeys[] = {OVR::Key_None, OVR::Key_Shift, OVR::Key_Control, OVR::Key_Alt, OVR::Key_Meta};
+
+ unsigned long cmods = [ev modifierFlags];
+ if ((cmods & 0xffff0000) != _Modifiers)
+ {
+ uint32_t mods = 0;
+ if (cmods & NSShiftKeyMask)
+ mods |= 0x01;
+ if (cmods & NSControlKeyMask)
+ mods |= 0x02;
+ if (cmods & NSAlternateKeyMask)
+ mods |= 0x04;
+ if (cmods & NSCommandKeyMask)
+ mods |= 0x08;
+
+ for (int i = 1; i <= 4; i++)
+ {
+ unsigned long m = (1 << (16+i));
+ if ((cmods & m) != (_Modifiers & m))
+ {
+ if (cmods & m)
+ _App->OnKey(ModifierKeys[i], true);
+ else
+ _App->OnKey(ModifierKeys[i], false);
+ }
+ }
+ _Modifiers = cmods & 0xffff0000;
+ }
+}
+
+-(void)ProcessMouse:(NSEvent*)ev
+{
+ switch ([ev type])
+ {
+ case NSLeftMouseDragged:
+ case NSRightMouseDragged:
+ case NSOtherMouseDragged:
+ case NSMouseMoved:
+ {
+ int dx = [ev deltaX];
+ int dy = [ev deltaY];
+
+ if (dx != 0 || dy != 0)
+ {
+ _App->OnMouseMove(dx, dy, 0);
+ [self warpMouseToCenter];
+ }
+ }
+ break;
+ case NSLeftMouseDown:
+ case NSRightMouseDown:
+ case NSOtherMouseDown:
+ break;
+ }
+}
+
+-(void) mouseMoved:(NSEvent*)ev
+{
+ [self ProcessMouse:ev];
+}
+-(void) mouseDragged:(NSEvent*)ev
+{
+ [self ProcessMouse:ev];
+}
+
+-(void) mouseDown:(NSEvent*)ev
+{
+ [self warpMouseToCenter];
+ CGAssociateMouseAndMouseCursorPosition(false);
+ [NSCursor hide];
+}
+
+//-(void)
+
+-(id) initWithFrame:(NSRect)frameRect
+{
+ NSOpenGLPixelFormatAttribute attr[] =
+ {NSOpenGLPFAWindow, NSOpenGLPFADoubleBuffer, NSOpenGLPFADepthSize, 24, nil};
+
+ NSOpenGLPixelFormat *pf = [[[NSOpenGLPixelFormat alloc] initWithAttributes:attr] autorelease];
+
+ self = [super initWithFrame:frameRect pixelFormat:pf];
+ GLint swap = 0;
+ [[self openGLContext] setValues:&swap forParameter:NSOpenGLCPSwapInterval];
+ //[self setWantsBestResolutionOpenGLSurface:YES];
+ return self;
+}
+
+-(BOOL)windowShouldClose:(id)sender
+{
+ _App->Exit();
+ return 1;
+}
+
+@end
+
+// GL OSX-specific logic
+namespace OSX {
+
+ RenderDevice::RenderDevice(const RendererParams& p, void* osview, void* context)
+ : GL::RenderDevice(p), Context(context)
+ {
+ OVRView* view = (OVRView*)osview;
+ NSRect bounds = [view bounds];
+ WindowWidth = bounds.size.width;
+ WindowHeight= bounds.size.height;
+
+ }
+
+ RenderDevice* RenderDevice::CreateDevice(const RendererParams& rp, void* osview)
+ {
+ OVRView* view = (OVRView*)osview;
+ NSOpenGLContext *context = [view openGLContext];
+ if (!context)
+ return NULL;
+
+ [context makeCurrentContext];
+ [[view window] makeKeyAndOrderFront:nil];
+
+ return new OSX::RenderDevice(rp, osview, context);
+ }
+
+ void RenderDevice::Present()
+ {
+ NSOpenGLContext *context = (NSOpenGLContext*)Context;
+ [context flushBuffer];
+ }
+
+ void RenderDevice::Shutdown()
+ {
+ Context = NULL;
+ }
+
+ bool RenderDevice::SetFullscreen(DisplayMode fullscreen)
+ {
+ Params.Fullscreen = fullscreen;
+ return 1;
+ }
+
+}
+
+
+int main(int argc, char *argv[])
+{
+ NSApplication* nsapp = [OVRApp sharedApplication];
+ [nsapp run];
+ return 0;
+}
+
diff --git a/Samples/OculusRoomTiny/OculusRoomModel.cpp b/Samples/OculusRoomTiny/OculusRoomModel.cpp
index 74e60cf..e12751a 100644
--- a/Samples/OculusRoomTiny/OculusRoomModel.cpp
+++ b/Samples/OculusRoomTiny/OculusRoomModel.cpp
@@ -1,260 +1,260 @@
-/************************************************************************************
-
-Filename : OculusRoomModel.cpp
-Content : Creates a simple room scene from hard-coded geometry
-Created : October 4, 2012
-
-Copyright : Copyright 2012-2013 Oculus, Inc. All Rights reserved.
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-
-*************************************************************************************/
-
-#include "RenderTiny_Device.h"
-
-using namespace OVR;
-using namespace OVR::RenderTiny;
-
-
-//-------------------------------------------------------------------------------------
-// ***** Room Model
-
-// This model is hard-coded out of axis-aligned solid-colored slabs.
-// Room unit dimensions are in meters. Player starts in the middle.
-//
-
-enum BuiltinTexture
-{
- Tex_None,
- Tex_Checker,
- Tex_Block,
- Tex_Panel,
- Tex_Count
-};
-
-struct Slab
-{
- float x1, y1, z1;
- float x2, y2, z2;
- Color c;
-};
-
-struct SlabModel
-{
- int Count;
- Slab* pSlabs;
- BuiltinTexture tex;
-};
-
-Slab FloorSlabs[] =
-{
- // Floor
- { -10.0f, -0.1f, -20.0f, 10.0f, 0.0f, 20.1f, Color(128,128,128) }
-};
-
-SlabModel Floor = {sizeof(FloorSlabs)/sizeof(Slab), FloorSlabs, Tex_Checker};
-
-Slab CeilingSlabs[] =
-{
- { -10.0f, 4.0f, -20.0f, 10.0f, 4.1f, 20.1f, Color(128,128,128) }
-};
-
-SlabModel Ceiling = {sizeof(FloorSlabs)/sizeof(Slab), CeilingSlabs, Tex_Panel};
-
-Slab RoomSlabs[] =
-{
- // Left Wall
- { -10.1f, 0.0f, -20.0f, -10.0f, 4.0f, 20.0f, Color(128,128,128) },
- // Back Wall
- { -10.0f, -0.1f, -20.1f, 10.0f, 4.0f, -20.0f, Color(128,128,128) },
-
- // Right Wall
- { 10.0f, -0.1f, -20.0f, 10.1f, 4.0f, 20.0f, Color(128,128,128) },
-};
-
-SlabModel Room = {sizeof(RoomSlabs)/sizeof(Slab), RoomSlabs, Tex_Block};
-
-Slab FixtureSlabs[] =
-{
- // Right side shelf
- { 9.5f, 0.75f, 3.0f, 10.1f, 2.5f, 3.1f, Color(128,128,128) }, // Verticals
- { 9.5f, 0.95f, 3.7f, 10.1f, 2.75f, 3.8f, Color(128,128,128) },
- { 9.5f, 1.20f, 2.5f, 10.1f, 1.30f, 3.8f, Color(128,128,128) }, // Horizontals
- { 9.5f, 2.00f, 3.0f, 10.1f, 2.10f, 4.2f, Color(128,128,128) },
-
- // Right railing
- { 5.0f, 1.1f, 20.0f, 10.0f, 1.2f, 20.1f, Color(128,128,128) },
- // Bars
- { 9.0f, 1.1f, 20.0f, 9.1f, 0.0f, 20.1f, Color(128,128,128) },
- { 8.0f, 1.1f, 20.0f, 8.1f, 0.0f, 20.1f, Color(128,128,128) },
- { 7.0f, 1.1f, 20.0f, 7.1f, 0.0f, 20.1f, Color(128,128,128) },
- { 6.0f, 1.1f, 20.0f, 6.1f, 0.0f, 20.1f, Color(128,128,128) },
- { 5.0f, 1.1f, 20.0f, 5.1f, 0.0f, 20.1f, Color(128,128,128) },
-
- // Left railing
- { -10.0f, 1.1f, 20.0f, -5.0f, 1.2f, 20.1f, Color(128,128,128) },
- // Bars
- { -9.0f, 1.1f, 20.0f, -9.1f, 0.0f, 20.1f, Color(128,128,128) },
- { -8.0f, 1.1f, 20.0f, -8.1f, 0.0f, 20.1f, Color(128,128,128) },
- { -7.0f, 1.1f, 20.0f, -7.1f, 0.0f, 20.1f, Color(128,128,128) },
- { -6.0f, 1.1f, 20.0f, -6.1f, 0.0f, 20.1f, Color(128,128,128) },
- { -5.0f, 1.1f, 20.0f, -5.1f, 0.0f, 20.1f, Color(128,128,128) },
-
- // Bottom Floor 2
- { -15.0f, -6.1f, 18.0f, 15.0f, -6.0f, 30.0f, Color(128,128,128) },
-};
-
-SlabModel Fixtures = {sizeof(FixtureSlabs)/sizeof(Slab), FixtureSlabs};
-
-Slab FurnitureSlabs[] =
-{
- // Table
- { -1.8f, 0.7f, 1.0f, 0.0f, 0.8f, 0.0f, Color(128,128,88) },
- { -1.8f, 0.7f, 0.0f, -1.8f+0.1f, 0.0f, 0.0f+0.1f, Color(128,128,88) }, // Leg 1
- { -1.8f, 0.7f, 1.0f, -1.8f+0.1f, 0.0f, 1.0f-0.1f, Color(128,128,88) }, // Leg 2
- { 0.0f, 0.7f, 1.0f, 0.0f-0.1f, 0.0f, 1.0f-0.1f, Color(128,128,88) }, // Leg 2
- { 0.0f, 0.7f, 0.0f, 0.0f-0.1f, 0.0f, 0.0f+0.1f, Color(128,128,88) }, // Leg 2
-
- // Chair
- { -1.4f, 0.5f, -1.1f, -0.8f, 0.55f, -0.5f, Color(88,88,128) }, // Set
- { -1.4f, 1.0f, -1.1f, -1.4f+0.06f, 0.0f, -1.1f+0.06f, Color(88,88,128) }, // Leg 1
- { -1.4f, 0.5f, -0.5f, -1.4f+0.06f, 0.0f, -0.5f-0.06f, Color(88,88,128) }, // Leg 2
- { -0.8f, 0.5f, -0.5f, -0.8f-0.06f, 0.0f, -0.5f-0.06f, Color(88,88,128) }, // Leg 2
- { -0.8f, 1.0f, -1.1f, -0.8f-0.06f, 0.0f, -1.1f+0.06f, Color(88,88,128) }, // Leg 2
- { -1.4f, 0.97f,-1.05f,-0.8f, 0.92f, -1.10f, Color(88,88,128) }, // Back high bar
-};
-
-SlabModel Furniture = {sizeof(FurnitureSlabs)/sizeof(Slab), FurnitureSlabs};
-
-Slab PostsSlabs[] =
-{
- // Posts
- { 0, 0.0f, 0.0f, 0.1f, 1.3f, 0.1f, Color(128,128,128) },
- { 0, 0.0f, 0.4f, 0.1f, 1.3f, 0.5f, Color(128,128,128) },
- { 0, 0.0f, 0.8f, 0.1f, 1.3f, 0.9f, Color(128,128,128) },
- { 0, 0.0f, 1.2f, 0.1f, 1.3f, 1.3f, Color(128,128,128) },
- { 0, 0.0f, 1.6f, 0.1f, 1.3f, 1.7f, Color(128,128,128) },
- { 0, 0.0f, 2.0f, 0.1f, 1.3f, 2.1f, Color(128,128,128) },
- { 0, 0.0f, 2.4f, 0.1f, 1.3f, 2.5f, Color(128,128,128) },
- { 0, 0.0f, 2.8f, 0.1f, 1.3f, 2.9f, Color(128,128,128) },
- { 0, 0.0f, 3.2f, 0.1f, 1.3f, 3.3f, Color(128,128,128) },
- { 0, 0.0f, 3.6f, 0.1f, 1.3f, 3.7f, Color(128,128,128) },
-};
-
-SlabModel Posts = {sizeof(PostsSlabs)/sizeof(Slab), PostsSlabs};
-
-
-// Temporary helper class used to initialize fills used by model.
-class FillCollection
-{
-public:
- Ptr<ShaderFill> LitSolid;
- Ptr<ShaderFill> LitTextures[4];
-
- FillCollection(RenderDevice* render);
-
-};
-
-FillCollection::FillCollection(RenderDevice* render)
-{
- Ptr<Texture> builtinTextures[Tex_Count];
-
- // Create floor checkerboard texture.
- {
- Color checker[256*256];
- for (int j = 0; j < 256; j++)
- for (int i = 0; i < 256; i++)
- checker[j*256+i] = (((i/4 >> 5) ^ (j/4 >> 5)) & 1) ?
- Color(180,180,180,255) : Color(80,80,80,255);
- builtinTextures[Tex_Checker] = *render->CreateTexture(Texture_RGBA|Texture_GenMipmaps, 256, 256, checker);
- builtinTextures[Tex_Checker]->SetSampleMode(Sample_Anisotropic|Sample_Repeat);
- }
-
- // Ceiling panel texture.
- {
- Color panel[256*256];
- for (int j = 0; j < 256; j++)
- for (int i = 0; i < 256; i++)
- panel[j*256+i] = (i/4 == 0 || j/4 == 0) ?
- Color(80,80,80,255) : Color(180,180,180,255);
- builtinTextures[Tex_Panel] = *render->CreateTexture(Texture_RGBA|Texture_GenMipmaps, 256, 256, panel);
- builtinTextures[Tex_Panel]->SetSampleMode(Sample_Anisotropic|Sample_Repeat);
- }
-
- // Wall brick textures.
- {
- Color block[256*256];
- for (int j = 0; j < 256; j++)
- for (int i = 0; i < 256; i++)
- block[j*256+i] = (((j/4 & 15) == 0) || (((i/4 & 15) == 0) && ((((i/4 & 31) == 0) ^ ((j/4 >> 4) & 1)) == 0))) ?
- Color(60,60,60,255) : Color(180,180,180,255);
- builtinTextures[Tex_Block] = *render->CreateTexture(Texture_RGBA|Texture_GenMipmaps, 256, 256, block);
- builtinTextures[Tex_Block]->SetSampleMode(Sample_Anisotropic|Sample_Repeat);
- }
-
- LitSolid = *new ShaderFill(*render->CreateShaderSet());
- LitSolid->GetShaders()->SetShader(render->LoadBuiltinShader(Shader_Vertex, VShader_MVP));
- LitSolid->GetShaders()->SetShader(render->LoadBuiltinShader(Shader_Fragment, FShader_LitGouraud));
-
- for (int i = 1; i < Tex_Count; i++)
- {
- LitTextures[i] = *new ShaderFill(*render->CreateShaderSet());
- LitTextures[i]->GetShaders()->SetShader(render->LoadBuiltinShader(Shader_Vertex, VShader_MVP));
- LitTextures[i]->GetShaders()->SetShader(render->LoadBuiltinShader(Shader_Fragment, FShader_LitTexture));
- LitTextures[i]->SetTexture(0, builtinTextures[i]);
- }
-
-}
-
-
-
-// Helper function to create a model out of Slab arrays.
-Model* CreateModel(Vector3f pos, SlabModel* sm, const FillCollection& fills)
-{
- Model* m = new Model(Prim_Triangles);
- m->SetPosition(pos);
-
- for(int i=0; i< sm->Count; i++)
- {
- Slab &s = sm->pSlabs[i];
- m->AddSolidColorBox(s.x1, s.y1, s.z1, s.x2, s.y2, s.z2, s.c);
- }
-
- if (sm->tex > 0)
- m->Fill = fills.LitTextures[sm->tex];
- else
- m->Fill = fills.LitSolid;
- return m;
-}
-
-
-// Adds sample models and lights to the argument scene.
-void PopulateRoomScene(Scene* scene, RenderDevice* render)
-{
- FillCollection fills(render);
-
- scene->World.Add(Ptr<Model>(*CreateModel(Vector3f(0,0,0), &Room, fills)));
- scene->World.Add(Ptr<Model>(*CreateModel(Vector3f(0,0,0), &Floor, fills)));
- scene->World.Add(Ptr<Model>(*CreateModel(Vector3f(0,0,0), &Ceiling, fills)));
- scene->World.Add(Ptr<Model>(*CreateModel(Vector3f(0,0,0), &Fixtures, fills)));
- scene->World.Add(Ptr<Model>(*CreateModel(Vector3f(0,0,0), &Furniture, fills)));
- scene->World.Add(Ptr<Model>(*CreateModel(Vector3f(0,0,4), &Furniture, fills)));
- scene->World.Add(Ptr<Model>(*CreateModel(Vector3f(-3,0,3), &Posts, fills)));
-
-
- scene->SetAmbient(Vector4f(0.65f,0.65f,0.65f,1));
- scene->AddLight(Vector3f(-2,4,-2), Vector4f(8,8,8,1));
- scene->AddLight(Vector3f(3,4,-3), Vector4f(2,1,1,1));
- scene->AddLight(Vector3f(-4,3,25), Vector4f(3,6,3,1));
-}
-
+/************************************************************************************
+
+Filename : OculusRoomModel.cpp
+Content : Creates a simple room scene from hard-coded geometry
+Created : October 4, 2012
+
+Copyright : Copyright 2012-2013 Oculus, Inc. All Rights reserved.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+*************************************************************************************/
+
+#include "RenderTiny_Device.h"
+
+using namespace OVR;
+using namespace OVR::RenderTiny;
+
+
+//-------------------------------------------------------------------------------------
+// ***** Room Model
+
+// This model is hard-coded out of axis-aligned solid-colored slabs.
+// Room unit dimensions are in meters. Player starts in the middle.
+//
+
+enum BuiltinTexture
+{
+ Tex_None,
+ Tex_Checker,
+ Tex_Block,
+ Tex_Panel,
+ Tex_Count
+};
+
+struct Slab
+{
+ float x1, y1, z1;
+ float x2, y2, z2;
+ Color c;
+};
+
+struct SlabModel
+{
+ int Count;
+ Slab* pSlabs;
+ BuiltinTexture tex;
+};
+
+Slab FloorSlabs[] =
+{
+ // Floor
+ { -10.0f, -0.1f, -20.0f, 10.0f, 0.0f, 20.1f, Color(128,128,128) }
+};
+
+SlabModel Floor = {sizeof(FloorSlabs)/sizeof(Slab), FloorSlabs, Tex_Checker};
+
+Slab CeilingSlabs[] =
+{
+ { -10.0f, 4.0f, -20.0f, 10.0f, 4.1f, 20.1f, Color(128,128,128) }
+};
+
+SlabModel Ceiling = {sizeof(FloorSlabs)/sizeof(Slab), CeilingSlabs, Tex_Panel};
+
+Slab RoomSlabs[] =
+{
+ // Left Wall
+ { -10.1f, 0.0f, -20.0f, -10.0f, 4.0f, 20.0f, Color(128,128,128) },
+ // Back Wall
+ { -10.0f, -0.1f, -20.1f, 10.0f, 4.0f, -20.0f, Color(128,128,128) },
+
+ // Right Wall
+ { 10.0f, -0.1f, -20.0f, 10.1f, 4.0f, 20.0f, Color(128,128,128) },
+};
+
+SlabModel Room = {sizeof(RoomSlabs)/sizeof(Slab), RoomSlabs, Tex_Block};
+
+Slab FixtureSlabs[] =
+{
+ // Right side shelf
+ { 9.5f, 0.75f, 3.0f, 10.1f, 2.5f, 3.1f, Color(128,128,128) }, // Verticals
+ { 9.5f, 0.95f, 3.7f, 10.1f, 2.75f, 3.8f, Color(128,128,128) },
+ { 9.5f, 1.20f, 2.5f, 10.1f, 1.30f, 3.8f, Color(128,128,128) }, // Horizontals
+ { 9.5f, 2.00f, 3.0f, 10.1f, 2.10f, 4.2f, Color(128,128,128) },
+
+ // Right railing
+ { 5.0f, 1.1f, 20.0f, 10.0f, 1.2f, 20.1f, Color(128,128,128) },
+ // Bars
+ { 9.0f, 1.1f, 20.0f, 9.1f, 0.0f, 20.1f, Color(128,128,128) },
+ { 8.0f, 1.1f, 20.0f, 8.1f, 0.0f, 20.1f, Color(128,128,128) },
+ { 7.0f, 1.1f, 20.0f, 7.1f, 0.0f, 20.1f, Color(128,128,128) },
+ { 6.0f, 1.1f, 20.0f, 6.1f, 0.0f, 20.1f, Color(128,128,128) },
+ { 5.0f, 1.1f, 20.0f, 5.1f, 0.0f, 20.1f, Color(128,128,128) },
+
+ // Left railing
+ { -10.0f, 1.1f, 20.0f, -5.0f, 1.2f, 20.1f, Color(128,128,128) },
+ // Bars
+ { -9.0f, 1.1f, 20.0f, -9.1f, 0.0f, 20.1f, Color(128,128,128) },
+ { -8.0f, 1.1f, 20.0f, -8.1f, 0.0f, 20.1f, Color(128,128,128) },
+ { -7.0f, 1.1f, 20.0f, -7.1f, 0.0f, 20.1f, Color(128,128,128) },
+ { -6.0f, 1.1f, 20.0f, -6.1f, 0.0f, 20.1f, Color(128,128,128) },
+ { -5.0f, 1.1f, 20.0f, -5.1f, 0.0f, 20.1f, Color(128,128,128) },
+
+ // Bottom Floor 2
+ { -15.0f, -6.1f, 18.0f, 15.0f, -6.0f, 30.0f, Color(128,128,128) },
+};
+
+SlabModel Fixtures = {sizeof(FixtureSlabs)/sizeof(Slab), FixtureSlabs};
+
+Slab FurnitureSlabs[] =
+{
+ // Table
+ { -1.8f, 0.7f, 1.0f, 0.0f, 0.8f, 0.0f, Color(128,128,88) },
+ { -1.8f, 0.7f, 0.0f, -1.8f+0.1f, 0.0f, 0.0f+0.1f, Color(128,128,88) }, // Leg 1
+ { -1.8f, 0.7f, 1.0f, -1.8f+0.1f, 0.0f, 1.0f-0.1f, Color(128,128,88) }, // Leg 2
+ { 0.0f, 0.7f, 1.0f, 0.0f-0.1f, 0.0f, 1.0f-0.1f, Color(128,128,88) }, // Leg 2
+ { 0.0f, 0.7f, 0.0f, 0.0f-0.1f, 0.0f, 0.0f+0.1f, Color(128,128,88) }, // Leg 2
+
+ // Chair
+ { -1.4f, 0.5f, -1.1f, -0.8f, 0.55f, -0.5f, Color(88,88,128) }, // Set
+ { -1.4f, 1.0f, -1.1f, -1.4f+0.06f, 0.0f, -1.1f+0.06f, Color(88,88,128) }, // Leg 1
+ { -1.4f, 0.5f, -0.5f, -1.4f+0.06f, 0.0f, -0.5f-0.06f, Color(88,88,128) }, // Leg 2
+ { -0.8f, 0.5f, -0.5f, -0.8f-0.06f, 0.0f, -0.5f-0.06f, Color(88,88,128) }, // Leg 2
+ { -0.8f, 1.0f, -1.1f, -0.8f-0.06f, 0.0f, -1.1f+0.06f, Color(88,88,128) }, // Leg 2
+ { -1.4f, 0.97f,-1.05f,-0.8f, 0.92f, -1.10f, Color(88,88,128) }, // Back high bar
+};
+
+SlabModel Furniture = {sizeof(FurnitureSlabs)/sizeof(Slab), FurnitureSlabs};
+
+Slab PostsSlabs[] =
+{
+ // Posts
+ { 0, 0.0f, 0.0f, 0.1f, 1.3f, 0.1f, Color(128,128,128) },
+ { 0, 0.0f, 0.4f, 0.1f, 1.3f, 0.5f, Color(128,128,128) },
+ { 0, 0.0f, 0.8f, 0.1f, 1.3f, 0.9f, Color(128,128,128) },
+ { 0, 0.0f, 1.2f, 0.1f, 1.3f, 1.3f, Color(128,128,128) },
+ { 0, 0.0f, 1.6f, 0.1f, 1.3f, 1.7f, Color(128,128,128) },
+ { 0, 0.0f, 2.0f, 0.1f, 1.3f, 2.1f, Color(128,128,128) },
+ { 0, 0.0f, 2.4f, 0.1f, 1.3f, 2.5f, Color(128,128,128) },
+ { 0, 0.0f, 2.8f, 0.1f, 1.3f, 2.9f, Color(128,128,128) },
+ { 0, 0.0f, 3.2f, 0.1f, 1.3f, 3.3f, Color(128,128,128) },
+ { 0, 0.0f, 3.6f, 0.1f, 1.3f, 3.7f, Color(128,128,128) },
+};
+
+SlabModel Posts = {sizeof(PostsSlabs)/sizeof(Slab), PostsSlabs};
+
+
+// Temporary helper class used to initialize fills used by model.
+class FillCollection
+{
+public:
+ Ptr<ShaderFill> LitSolid;
+ Ptr<ShaderFill> LitTextures[4];
+
+ FillCollection(RenderDevice* render);
+
+};
+
+FillCollection::FillCollection(RenderDevice* render)
+{
+ Ptr<Texture> builtinTextures[Tex_Count];
+
+ // Create floor checkerboard texture.
+ {
+ Color checker[256*256];
+ for (int j = 0; j < 256; j++)
+ for (int i = 0; i < 256; i++)
+ checker[j*256+i] = (((i/4 >> 5) ^ (j/4 >> 5)) & 1) ?
+ Color(180,180,180,255) : Color(80,80,80,255);
+ builtinTextures[Tex_Checker] = *render->CreateTexture(Texture_RGBA|Texture_GenMipmaps, 256, 256, checker);
+ builtinTextures[Tex_Checker]->SetSampleMode(Sample_Anisotropic|Sample_Repeat);
+ }
+
+ // Ceiling panel texture.
+ {
+ Color panel[256*256];
+ for (int j = 0; j < 256; j++)
+ for (int i = 0; i < 256; i++)
+ panel[j*256+i] = (i/4 == 0 || j/4 == 0) ?
+ Color(80,80,80,255) : Color(180,180,180,255);
+ builtinTextures[Tex_Panel] = *render->CreateTexture(Texture_RGBA|Texture_GenMipmaps, 256, 256, panel);
+ builtinTextures[Tex_Panel]->SetSampleMode(Sample_Anisotropic|Sample_Repeat);
+ }
+
+ // Wall brick textures.
+ {
+ Color block[256*256];
+ for (int j = 0; j < 256; j++)
+ for (int i = 0; i < 256; i++)
+ block[j*256+i] = (((j/4 & 15) == 0) || (((i/4 & 15) == 0) && ((((i/4 & 31) == 0) ^ ((j/4 >> 4) & 1)) == 0))) ?
+ Color(60,60,60,255) : Color(180,180,180,255);
+ builtinTextures[Tex_Block] = *render->CreateTexture(Texture_RGBA|Texture_GenMipmaps, 256, 256, block);
+ builtinTextures[Tex_Block]->SetSampleMode(Sample_Anisotropic|Sample_Repeat);
+ }
+
+ LitSolid = *new ShaderFill(*render->CreateShaderSet());
+ LitSolid->GetShaders()->SetShader(render->LoadBuiltinShader(Shader_Vertex, VShader_MVP));
+ LitSolid->GetShaders()->SetShader(render->LoadBuiltinShader(Shader_Fragment, FShader_LitGouraud));
+
+ for (int i = 1; i < Tex_Count; i++)
+ {
+ LitTextures[i] = *new ShaderFill(*render->CreateShaderSet());
+ LitTextures[i]->GetShaders()->SetShader(render->LoadBuiltinShader(Shader_Vertex, VShader_MVP));
+ LitTextures[i]->GetShaders()->SetShader(render->LoadBuiltinShader(Shader_Fragment, FShader_LitTexture));
+ LitTextures[i]->SetTexture(0, builtinTextures[i]);
+ }
+
+}
+
+
+
+// Helper function to create a model out of Slab arrays.
+Model* CreateModel(Vector3f pos, SlabModel* sm, const FillCollection& fills)
+{
+ Model* m = new Model(Prim_Triangles);
+ m->SetPosition(pos);
+
+ for(int i=0; i< sm->Count; i++)
+ {
+ Slab &s = sm->pSlabs[i];
+ m->AddSolidColorBox(s.x1, s.y1, s.z1, s.x2, s.y2, s.z2, s.c);
+ }
+
+ if (sm->tex > 0)
+ m->Fill = fills.LitTextures[sm->tex];
+ else
+ m->Fill = fills.LitSolid;
+ return m;
+}
+
+
+// Adds sample models and lights to the argument scene.
+void PopulateRoomScene(Scene* scene, RenderDevice* render)
+{
+ FillCollection fills(render);
+
+ scene->World.Add(Ptr<Model>(*CreateModel(Vector3f(0,0,0), &Room, fills)));
+ scene->World.Add(Ptr<Model>(*CreateModel(Vector3f(0,0,0), &Floor, fills)));
+ scene->World.Add(Ptr<Model>(*CreateModel(Vector3f(0,0,0), &Ceiling, fills)));
+ scene->World.Add(Ptr<Model>(*CreateModel(Vector3f(0,0,0), &Fixtures, fills)));
+ scene->World.Add(Ptr<Model>(*CreateModel(Vector3f(0,0,0), &Furniture, fills)));
+ scene->World.Add(Ptr<Model>(*CreateModel(Vector3f(0,0,4), &Furniture, fills)));
+ scene->World.Add(Ptr<Model>(*CreateModel(Vector3f(-3,0,3), &Posts, fills)));
+
+
+ scene->SetAmbient(Vector4f(0.65f,0.65f,0.65f,1));
+ scene->AddLight(Vector3f(-2,4,-2), Vector4f(8,8,8,1));
+ scene->AddLight(Vector3f(3,4,-3), Vector4f(2,1,1,1));
+ scene->AddLight(Vector3f(-4,3,25), Vector4f(3,6,3,1));
+}
+
diff --git a/Samples/OculusRoomTiny/OculusRoomTiny_Msvc2010.vcxproj b/Samples/OculusRoomTiny/OculusRoomTiny_Msvc2010.vcxproj
index c031772..4bc37a8 100644
--- a/Samples/OculusRoomTiny/OculusRoomTiny_Msvc2010.vcxproj
+++ b/Samples/OculusRoomTiny/OculusRoomTiny_Msvc2010.vcxproj
@@ -1,187 +1,187 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
- <ItemGroup Label="ProjectConfigurations">
- <ProjectConfiguration Include="Debug|Win32">
- <Configuration>Debug</Configuration>
- <Platform>Win32</Platform>
- </ProjectConfiguration>
- <ProjectConfiguration Include="Debug|x64">
- <Configuration>Debug</Configuration>
- <Platform>x64</Platform>
- </ProjectConfiguration>
- <ProjectConfiguration Include="Release|Win32">
- <Configuration>Release</Configuration>
- <Platform>Win32</Platform>
- </ProjectConfiguration>
- <ProjectConfiguration Include="Release|x64">
- <Configuration>Release</Configuration>
- <Platform>x64</Platform>
- </ProjectConfiguration>
- </ItemGroup>
- <PropertyGroup Label="Globals">
- <ProjectGuid>{80523489-2881-4F64-8C3B-FAF88B60ABCD}</ProjectGuid>
- <Keyword>Win32Proj</Keyword>
- <RootNamespace>OculusRoomTiny</RootNamespace>
- <ProjectName>OculusRoomTiny</ProjectName>
- </PropertyGroup>
- <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
- <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
- <ConfigurationType>Application</ConfigurationType>
- <UseDebugLibraries>true</UseDebugLibraries>
- <CharacterSet>Unicode</CharacterSet>
- </PropertyGroup>
- <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
- <ConfigurationType>Application</ConfigurationType>
- <UseDebugLibraries>true</UseDebugLibraries>
- <CharacterSet>Unicode</CharacterSet>
- </PropertyGroup>
- <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
- <ConfigurationType>Application</ConfigurationType>
- <UseDebugLibraries>false</UseDebugLibraries>
- <WholeProgramOptimization>true</WholeProgramOptimization>
- <CharacterSet>Unicode</CharacterSet>
- </PropertyGroup>
- <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
- <ConfigurationType>Application</ConfigurationType>
- <UseDebugLibraries>false</UseDebugLibraries>
- <WholeProgramOptimization>true</WholeProgramOptimization>
- <CharacterSet>Unicode</CharacterSet>
- </PropertyGroup>
- <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
- <ImportGroup Label="ExtensionSettings">
- </ImportGroup>
- <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
- <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
- </ImportGroup>
- <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
- <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
- </ImportGroup>
- <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
- <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
- </ImportGroup>
- <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
- <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
- </ImportGroup>
- <PropertyGroup Label="UserMacros" />
- <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
- <LinkIncremental>true</LinkIncremental>
- <IntDir>$(Configuration)\Obj\</IntDir>
- <OutDir>$(ProjectDir)$(Configuration)\</OutDir>
- </PropertyGroup>
- <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
- <LinkIncremental>true</LinkIncremental>
- <IntDir>$(Configuration)\Obj\</IntDir>
- <OutDir>$(ProjectDir)$(Configuration)\</OutDir>
- </PropertyGroup>
- <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
- <LinkIncremental>false</LinkIncremental>
- <IntDir>$(Configuration)\Obj\</IntDir>
- <OutDir>$(ProjectDir)$(Configuration)\</OutDir>
- </PropertyGroup>
- <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
- <LinkIncremental>false</LinkIncremental>
- <IntDir>$(Configuration)\Obj\</IntDir>
- <OutDir>$(ProjectDir)$(Configuration)\</OutDir>
- </PropertyGroup>
- <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
- <ClCompile>
- <PrecompiledHeader>
- </PrecompiledHeader>
- <WarningLevel>Level4</WarningLevel>
- <Optimization>Disabled</Optimization>
- <PreprocessorDefinitions>OVR_BUILD_DEBUG;WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
- <AdditionalIncludeDirectories>../../LibOVR/Include;../../LibOVR/Src;../../3rdParty/glext;$(DXSDK_DIR)/Include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
- <DebugInformationFormat>OldStyle</DebugInformationFormat>
- <MultiProcessorCompilation>true</MultiProcessorCompilation>
- <MinimalRebuild>false</MinimalRebuild>
- </ClCompile>
- <Link>
- <SubSystem>Windows</SubSystem>
- <GenerateDebugInformation>true</GenerateDebugInformation>
- <AdditionalDependencies>libovrd.lib;dxgi.lib;d3d10.lib;d3d11.lib;d3dcompiler.lib;opengl32.lib;winmm.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
- <AdditionalLibraryDirectories>../../LibOVR/Lib/Win32;$(DXSDK_DIR)/Lib/x86;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
- </Link>
- </ItemDefinitionGroup>
- <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
- <ClCompile>
- <PrecompiledHeader>
- </PrecompiledHeader>
- <WarningLevel>Level4</WarningLevel>
- <Optimization>Disabled</Optimization>
- <PreprocessorDefinitions>OVR_BUILD_DEBUG;WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
- <AdditionalIncludeDirectories>../../LibOVR/Include;../../LibOVR/Src;../../3rdParty/glext;$(DXSDK_DIR)/Include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
- <DebugInformationFormat>OldStyle</DebugInformationFormat>
- <MultiProcessorCompilation>true</MultiProcessorCompilation>
- <MinimalRebuild>false</MinimalRebuild>
- </ClCompile>
- <Link>
- <SubSystem>Windows</SubSystem>
- <GenerateDebugInformation>true</GenerateDebugInformation>
- <AdditionalDependencies>libovr64d.lib;dxgi.lib;d3d10.lib;d3d11.lib;d3dcompiler.lib;opengl32.lib;winmm.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
- <AdditionalLibraryDirectories>../../LibOVR/Lib/x64;$(DXSDK_DIR)/Lib/x64;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
- </Link>
- </ItemDefinitionGroup>
- <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
- <ClCompile>
- <WarningLevel>Level4</WarningLevel>
- <PrecompiledHeader>
- </PrecompiledHeader>
- <Optimization>MaxSpeed</Optimization>
- <FunctionLevelLinking>true</FunctionLevelLinking>
- <IntrinsicFunctions>true</IntrinsicFunctions>
- <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
- <AdditionalIncludeDirectories>../../LibOVR/Include;../../LibOVR/Src;../../3rdParty/glext;$(DXSDK_DIR)/Include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
- <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
- <MultiProcessorCompilation>true</MultiProcessorCompilation>
- <DebugInformationFormat>OldStyle</DebugInformationFormat>
- </ClCompile>
- <Link>
- <SubSystem>Windows</SubSystem>
- <GenerateDebugInformation>false</GenerateDebugInformation>
- <EnableCOMDATFolding>true</EnableCOMDATFolding>
- <OptimizeReferences>true</OptimizeReferences>
- <AdditionalLibraryDirectories>../../LibOVR/Lib/Win32;$(DXSDK_DIR)/Lib/x86;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
- <AdditionalDependencies>libovr.lib;dxgi.lib;d3d10.lib;d3d11.lib;d3dcompiler.lib;opengl32.lib;winmm.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
- </Link>
- </ItemDefinitionGroup>
- <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
- <ClCompile>
- <WarningLevel>Level4</WarningLevel>
- <PrecompiledHeader>
- </PrecompiledHeader>
- <Optimization>MaxSpeed</Optimization>
- <FunctionLevelLinking>true</FunctionLevelLinking>
- <IntrinsicFunctions>true</IntrinsicFunctions>
- <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
- <AdditionalIncludeDirectories>../../LibOVR/Include;../../LibOVR/Src;../../3rdParty/glext;$(DXSDK_DIR)/Include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
- <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
- <MultiProcessorCompilation>true</MultiProcessorCompilation>
- <DebugInformationFormat>OldStyle</DebugInformationFormat>
- </ClCompile>
- <Link>
- <SubSystem>Windows</SubSystem>
- <GenerateDebugInformation>true</GenerateDebugInformation>
- <EnableCOMDATFolding>true</EnableCOMDATFolding>
- <OptimizeReferences>true</OptimizeReferences>
- <AdditionalLibraryDirectories>../../LibOVR/Lib/x64;$(DXSDK_DIR)/Lib/x64;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
- <AdditionalDependencies>libovr64.lib;dxgi.lib;d3d10.lib;d3d11.lib;d3dcompiler.lib;opengl32.lib;winmm.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
- </Link>
- </ItemDefinitionGroup>
- <ItemGroup>
- <ClCompile Include="OculusRoomModel.cpp" />
- <ClCompile Include="RenderTiny_D3D1X_Device.cpp" />
- <ClCompile Include="RenderTiny_Device.cpp" />
- <ClCompile Include="Win32_OculusRoomTiny.cpp" />
- </ItemGroup>
- <ItemGroup>
- <ClInclude Include="RenderTiny_D3D1X_Device.h" />
- <ClInclude Include="RenderTiny_Device.h" />
- <ClInclude Include="Win32_OculusRoomTiny.h" />
- </ItemGroup>
- <ItemGroup>
- <ResourceCompile Include="OculusRoomTiny.rc" />
- </ItemGroup>
- <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
- <ImportGroup Label="ExtensionTargets">
- </ImportGroup>
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Debug|x64">
+ <Configuration>Debug</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|x64">
+ <Configuration>Release</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{80523489-2881-4F64-8C3B-FAF88B60ABCD}</ProjectGuid>
+ <Keyword>Win32Proj</Keyword>
+ <RootNamespace>OculusRoomTiny</RootNamespace>
+ <ProjectName>OculusRoomTiny</ProjectName>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <LinkIncremental>true</LinkIncremental>
+ <IntDir>$(Configuration)\Obj\</IntDir>
+ <OutDir>$(ProjectDir)$(Configuration)\</OutDir>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <LinkIncremental>true</LinkIncremental>
+ <IntDir>$(Configuration)\Obj\</IntDir>
+ <OutDir>$(ProjectDir)$(Configuration)\</OutDir>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <LinkIncremental>false</LinkIncremental>
+ <IntDir>$(Configuration)\Obj\</IntDir>
+ <OutDir>$(ProjectDir)$(Configuration)\</OutDir>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <LinkIncremental>false</LinkIncremental>
+ <IntDir>$(Configuration)\Obj\</IntDir>
+ <OutDir>$(ProjectDir)$(Configuration)\</OutDir>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <ClCompile>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>Level4</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ <PreprocessorDefinitions>OVR_BUILD_DEBUG;WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>../../LibOVR/Include;../../LibOVR/Src;../../3rdParty/glext;$(DXSDK_DIR)/Include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <DebugInformationFormat>OldStyle</DebugInformationFormat>
+ <MultiProcessorCompilation>true</MultiProcessorCompilation>
+ <MinimalRebuild>false</MinimalRebuild>
+ </ClCompile>
+ <Link>
+ <SubSystem>Windows</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <AdditionalDependencies>libovrd.lib;dxgi.lib;d3d10.lib;d3d11.lib;d3dcompiler.lib;opengl32.lib;winmm.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <AdditionalLibraryDirectories>../../LibOVR/Lib/Win32;$(DXSDK_DIR)/Lib/x86;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <ClCompile>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>Level4</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ <PreprocessorDefinitions>OVR_BUILD_DEBUG;WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>../../LibOVR/Include;../../LibOVR/Src;../../3rdParty/glext;$(DXSDK_DIR)/Include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <DebugInformationFormat>OldStyle</DebugInformationFormat>
+ <MultiProcessorCompilation>true</MultiProcessorCompilation>
+ <MinimalRebuild>false</MinimalRebuild>
+ </ClCompile>
+ <Link>
+ <SubSystem>Windows</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <AdditionalDependencies>libovr64d.lib;dxgi.lib;d3d10.lib;d3d11.lib;d3dcompiler.lib;opengl32.lib;winmm.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <AdditionalLibraryDirectories>../../LibOVR/Lib/x64;$(DXSDK_DIR)/Lib/x64;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <ClCompile>
+ <WarningLevel>Level4</WarningLevel>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>../../LibOVR/Include;../../LibOVR/Src;../../3rdParty/glext;$(DXSDK_DIR)/Include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+ <MultiProcessorCompilation>true</MultiProcessorCompilation>
+ <DebugInformationFormat>OldStyle</DebugInformationFormat>
+ </ClCompile>
+ <Link>
+ <SubSystem>Windows</SubSystem>
+ <GenerateDebugInformation>false</GenerateDebugInformation>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ <AdditionalLibraryDirectories>../../LibOVR/Lib/Win32;$(DXSDK_DIR)/Lib/x86;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalDependencies>libovr.lib;dxgi.lib;d3d10.lib;d3d11.lib;d3dcompiler.lib;opengl32.lib;winmm.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <ClCompile>
+ <WarningLevel>Level4</WarningLevel>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>../../LibOVR/Include;../../LibOVR/Src;../../3rdParty/glext;$(DXSDK_DIR)/Include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+ <MultiProcessorCompilation>true</MultiProcessorCompilation>
+ <DebugInformationFormat>OldStyle</DebugInformationFormat>
+ </ClCompile>
+ <Link>
+ <SubSystem>Windows</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ <AdditionalLibraryDirectories>../../LibOVR/Lib/x64;$(DXSDK_DIR)/Lib/x64;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalDependencies>libovr64.lib;dxgi.lib;d3d10.lib;d3d11.lib;d3dcompiler.lib;opengl32.lib;winmm.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClCompile Include="OculusRoomModel.cpp" />
+ <ClCompile Include="RenderTiny_D3D1X_Device.cpp" />
+ <ClCompile Include="RenderTiny_Device.cpp" />
+ <ClCompile Include="Win32_OculusRoomTiny.cpp" />
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="RenderTiny_D3D1X_Device.h" />
+ <ClInclude Include="RenderTiny_Device.h" />
+ <ClInclude Include="Win32_OculusRoomTiny.h" />
+ </ItemGroup>
+ <ItemGroup>
+ <ResourceCompile Include="OculusRoomTiny.rc" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
</Project> \ No newline at end of file
diff --git a/Samples/OculusRoomTiny/OculusRoomTiny_Msvc2010.vcxproj.filters b/Samples/OculusRoomTiny/OculusRoomTiny_Msvc2010.vcxproj.filters
index f7ec303..3c09bd5 100644
--- a/Samples/OculusRoomTiny/OculusRoomTiny_Msvc2010.vcxproj.filters
+++ b/Samples/OculusRoomTiny/OculusRoomTiny_Msvc2010.vcxproj.filters
@@ -1,17 +1,17 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
- <ItemGroup>
- <ClCompile Include="OculusRoomModel.cpp" />
- <ClCompile Include="RenderTiny_D3D1X_Device.cpp" />
- <ClCompile Include="RenderTiny_Device.cpp" />
- <ClCompile Include="Win32_OculusRoomTiny.cpp" />
- </ItemGroup>
- <ItemGroup>
- <ClInclude Include="RenderTiny_Device.h" />
- <ClInclude Include="RenderTiny_D3D1X_Device.h" />
- <ClInclude Include="Win32_OculusRoomTiny.h" />
- </ItemGroup>
- <ItemGroup>
- <ResourceCompile Include="OculusRoomTiny.rc" />
- </ItemGroup>
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <ClCompile Include="OculusRoomModel.cpp" />
+ <ClCompile Include="RenderTiny_D3D1X_Device.cpp" />
+ <ClCompile Include="RenderTiny_Device.cpp" />
+ <ClCompile Include="Win32_OculusRoomTiny.cpp" />
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="RenderTiny_Device.h" />
+ <ClInclude Include="RenderTiny_D3D1X_Device.h" />
+ <ClInclude Include="Win32_OculusRoomTiny.h" />
+ </ItemGroup>
+ <ItemGroup>
+ <ResourceCompile Include="OculusRoomTiny.rc" />
+ </ItemGroup>
</Project> \ No newline at end of file
diff --git a/Samples/OculusRoomTiny/RenderTiny_D3D1X_Device.cpp b/Samples/OculusRoomTiny/RenderTiny_D3D1X_Device.cpp
index 64887dd..a1a567a 100644
--- a/Samples/OculusRoomTiny/RenderTiny_D3D1X_Device.cpp
+++ b/Samples/OculusRoomTiny/RenderTiny_D3D1X_Device.cpp
@@ -1,1311 +1,1311 @@
-/************************************************************************************
-
-Filename : RenderTiny_D3D1x.cpp
-Content : RenderDevice implementation for D3DX10/11.
-Created : September 10, 2012
-Authors : Andrew Reisse
-
-Copyright : Copyright 2012 Oculus VR, Inc. All Rights reserved.
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-
-************************************************************************************/
-
-#include "Kernel/OVR_Log.h"
-#include "Kernel/OVR_Std.h"
-
-#include "RenderTiny_D3D1X_Device.h"
-
-#include <d3dcompiler.h>
-
-namespace OVR { namespace RenderTiny { namespace D3D10 {
-
-
-//-------------------------------------------------------------------------------------
-// Vertex format
-static D3D1x_(INPUT_ELEMENT_DESC) ModelVertexDesc[] =
-{
- {"Position", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, offsetof(Vertex, Pos), D3D1x_(INPUT_PER_VERTEX_DATA), 0},
- {"Color", 0, DXGI_FORMAT_R8G8B8A8_UNORM, 0, offsetof(Vertex, C), D3D1x_(INPUT_PER_VERTEX_DATA), 0},
- {"TexCoord", 0, DXGI_FORMAT_R32G32_FLOAT, 0, offsetof(Vertex, U), D3D1x_(INPUT_PER_VERTEX_DATA), 0},
- {"Normal", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, offsetof(Vertex, Norm), D3D1x_(INPUT_PER_VERTEX_DATA), 0},
-};
-
-// These shaders are used to render the world, including lit vertex-colored and textured geometry.
-
-// Used for world geometry; has projection matrix.
-static const char* StdVertexShaderSrc =
- "float4x4 Proj;\n"
- "float4x4 View;\n"
- "struct Varyings\n"
- "{\n"
- " float4 Position : SV_Position;\n"
- " float4 Color : COLOR0;\n"
- " float2 TexCoord : TEXCOORD0;\n"
- " float3 Normal : NORMAL;\n"
- " float3 VPos : TEXCOORD4;\n"
- "};\n"
- "void main(in float4 Position : POSITION, in float4 Color : COLOR0, in float2 TexCoord : TEXCOORD0,"
- " in float3 Normal : NORMAL,\n"
- " out Varyings ov)\n"
- "{\n"
- " ov.Position = mul(Proj, mul(View, Position));\n"
- " ov.Normal = mul(View, Normal);\n"
- " ov.VPos = mul(View, Position);\n"
- " ov.TexCoord = TexCoord;\n"
- " ov.Color = Color;\n"
- "}\n";
-
-// Used for text/clearing; no projection.
-static const char* DirectVertexShaderSrc =
- "float4x4 View : register(c4);\n"
- "void main(in float4 Position : POSITION, in float4 Color : COLOR0,\n"
- " in float2 TexCoord : TEXCOORD0, in float3 Normal : NORMAL,\n"
- " out float4 oPosition : SV_Position, out float4 oColor : COLOR,\n"
- " out float2 oTexCoord : TEXCOORD0,"
- " out float3 oNormal : NORMAL)\n"
- "{\n"
- " oPosition = mul(View, Position);\n"
- " oTexCoord = TexCoord;\n"
- " oColor = Color;\n"
- " oNormal = mul(View, Normal);\n"
- "}\n";
-
-static const char* SolidPixelShaderSrc =
- "float4 Color;\n"
- "struct Varyings\n"
- "{\n"
- " float4 Position : SV_Position;\n"
- " float4 Color : COLOR0;\n"
- " float2 TexCoord : TEXCOORD0;\n"
- "};\n"
- "float4 main(in Varyings ov) : SV_Target\n"
- "{\n"
- " return Color;\n"
- "}\n";
-
-static const char* GouraudPixelShaderSrc =
- "struct Varyings\n"
- "{\n"
- " float4 Position : SV_Position;\n"
- " float4 Color : COLOR0;\n"
- " float2 TexCoord : TEXCOORD0;\n"
- "};\n"
- "float4 main(in Varyings ov) : SV_Target\n"
- "{\n"
- " return ov.Color;\n"
- "}\n";
-
-static const char* TexturePixelShaderSrc =
- "Texture2D Texture : register(t0);\n"
- "SamplerState Linear : register(s0);\n"
- "struct Varyings\n"
- "{\n"
- " float4 Position : SV_Position;\n"
- " float4 Color : COLOR0;\n"
- " float2 TexCoord : TEXCOORD0;\n"
- "};\n"
- "float4 main(in Varyings ov) : SV_Target\n"
- "{\n"
- " float4 color2 = ov.Color * Texture.Sample(Linear, ov.TexCoord);\n"
- " if (color2.a <= 0.4)\n"
- " discard;\n"
- " return color2;\n"
- "}\n";
-
-
-#define LIGHTING_COMMON \
- "cbuffer Lighting : register(b1)\n" \
- "{\n" \
- " float3 Ambient;\n" \
- " float3 LightPos[8];\n" \
- " float4 LightColor[8];\n" \
- " float LightCount;\n" \
- "};\n" \
- "struct Varyings\n" \
- "{\n" \
- " float4 Position : SV_Position;\n" \
- " float4 Color : COLOR0;\n" \
- " float2 TexCoord : TEXCOORD0;\n" \
- " float3 Normal : NORMAL;\n" \
- " float3 VPos : TEXCOORD4;\n" \
- "};\n" \
- "float4 DoLight(Varyings v)\n" \
- "{\n" \
- " float3 norm = normalize(v.Normal);\n" \
- " float3 light = Ambient;\n" \
- " for (uint i = 0; i < LightCount; i++)\n"\
- " {\n" \
- " float3 ltp = (LightPos[i] - v.VPos);\n" \
- " float ldist = dot(ltp,ltp);\n" \
- " ltp = normalize(ltp);\n" \
- " light += saturate(LightColor[i] * v.Color.rgb * dot(norm, ltp) / sqrt(ldist));\n"\
- " }\n" \
- " return float4(light, v.Color.a);\n" \
- "}\n"
-
-static const char* LitSolidPixelShaderSrc =
- LIGHTING_COMMON
- "float4 main(in Varyings ov) : SV_Target\n"
- "{\n"
- " return DoLight(ov) * ov.Color;\n"
- "}\n";
-
-static const char* LitTexturePixelShaderSrc =
- "Texture2D Texture : register(t0);\n"
- "SamplerState Linear : register(s0);\n"
- LIGHTING_COMMON
- "float4 main(in Varyings ov) : SV_Target\n"
- "{\n"
- " return DoLight(ov) * Texture.Sample(Linear, ov.TexCoord);\n"
- "}\n";
-
-
-//-------------------------------------------------------------------------------------
-// ***** Distortion Post-process Shaders
-
-static const char* PostProcessVertexShaderSrc =
- "float4x4 View : register(c4);\n"
- "float4x4 Texm : register(c8);\n"
- "void main(in float4 Position : POSITION, in float4 Color : COLOR0, in float2 TexCoord : TEXCOORD0,\n"
- " out float4 oPosition : SV_Position, out float4 oColor : COLOR, out float2 oTexCoord : TEXCOORD0)\n"
- "{\n"
- " oPosition = mul(View, Position);\n"
- " oTexCoord = mul(Texm, float4(TexCoord,0,1));\n"
- " oColor = Color;\n"
- "}\n";
-
-// Shader with just lens distortion correction.
-static const char* PostProcessPixelShaderSrc =
- "Texture2D Texture : register(t0);\n"
- "SamplerState Linear : register(s0);\n"
- "float2 LensCenter;\n"
- "float2 ScreenCenter;\n"
- "float2 Scale;\n"
- "float2 ScaleIn;\n"
- "float4 HmdWarpParam;\n"
- "\n"
-
- // Scales input texture coordinates for distortion.
- // ScaleIn maps texture coordinates to Scales to ([-1, 1]), although top/bottom will be
- // larger due to aspect ratio.
- "float2 HmdWarp(float2 in01)\n"
- "{\n"
- " float2 theta = (in01 - LensCenter) * ScaleIn;\n" // Scales to [-1, 1]
- " float rSq = theta.x * theta.x + theta.y * theta.y;\n"
- " float2 theta1 = theta * (HmdWarpParam.x + HmdWarpParam.y * rSq + "
- " HmdWarpParam.z * rSq * rSq + HmdWarpParam.w * rSq * rSq * rSq);\n"
- " return LensCenter + Scale * theta1;\n"
- "}\n"
-
- "float4 main(in float4 oPosition : SV_Position, in float4 oColor : COLOR,\n"
- " in float2 oTexCoord : TEXCOORD0) : SV_Target\n"
- "{\n"
- " float2 tc = HmdWarp(oTexCoord);\n"
- " if (any(clamp(tc, ScreenCenter-float2(0.25,0.5), ScreenCenter+float2(0.25, 0.5)) - tc))\n"
- " return 0;\n"
- " return Texture.Sample(Linear, tc);\n"
- "}\n";
-
-// Shader with lens distortion and chromatic aberration correction.
-static const char* PostProcessPixelShaderWithChromAbSrc =
- "Texture2D Texture : register(t0);\n"
- "SamplerState Linear : register(s0);\n"
- "float2 LensCenter;\n"
- "float2 ScreenCenter;\n"
- "float2 Scale;\n"
- "float2 ScaleIn;\n"
- "float4 HmdWarpParam;\n"
- "float4 ChromAbParam;\n"
- "\n"
-
- // Scales input texture coordinates for distortion.
- // ScaleIn maps texture coordinates to Scales to ([-1, 1]), although top/bottom will be
- // larger due to aspect ratio.
- "float4 main(in float4 oPosition : SV_Position, in float4 oColor : COLOR,\n"
- " in float2 oTexCoord : TEXCOORD0) : SV_Target\n"
- "{\n"
- " float2 theta = (oTexCoord - LensCenter) * ScaleIn;\n" // Scales to [-1, 1]
- " float rSq= theta.x * theta.x + theta.y * theta.y;\n"
- " float2 theta1 = theta * (HmdWarpParam.x + HmdWarpParam.y * rSq + "
- " HmdWarpParam.z * rSq * rSq + HmdWarpParam.w * rSq * rSq * rSq);\n"
- " \n"
- " // Detect whether blue texture coordinates are out of range since these will scaled out the furthest.\n"
- " float2 thetaBlue = theta1 * (ChromAbParam.z + ChromAbParam.w * rSq);\n"
- " float2 tcBlue = LensCenter + Scale * thetaBlue;\n"
- " if (any(clamp(tcBlue, ScreenCenter-float2(0.25,0.5), ScreenCenter+float2(0.25, 0.5)) - tcBlue))\n"
- " return 0;\n"
- " \n"
- " // Now do blue texture lookup.\n"
- " float blue = Texture.Sample(Linear, tcBlue).b;\n"
- " \n"
- " // Do green lookup (no scaling).\n"
- " float2 tcGreen = LensCenter + Scale * theta1;\n"
- " float green = Texture.Sample(Linear, tcGreen).g;\n"
- " \n"
- " // Do red scale and lookup.\n"
- " float2 thetaRed = theta1 * (ChromAbParam.x + ChromAbParam.y * rSq);\n"
- " float2 tcRed = LensCenter + Scale * thetaRed;\n"
- " float red = Texture.Sample(Linear, tcRed).r;\n"
- " \n"
- " return float4(red, green, blue, 1);\n"
- "}\n";
-
-
-static const char* VShaderSrcs[VShader_Count] =
-{
- DirectVertexShaderSrc,
- StdVertexShaderSrc,
- PostProcessVertexShaderSrc
-};
-static const char* FShaderSrcs[FShader_Count] =
-{
- SolidPixelShaderSrc,
- GouraudPixelShaderSrc,
- TexturePixelShaderSrc,
- PostProcessPixelShaderSrc,
- PostProcessPixelShaderWithChromAbSrc,
- LitSolidPixelShaderSrc,
- LitTexturePixelShaderSrc
-};
-
-
-//-------------------------------------------------------------------------------------
-// ***** Buffer
-
-Buffer::~Buffer()
-{
-}
-
-bool Buffer::Data(int use, const void *buffer, size_t size)
-{
- if (D3DBuffer && Size >= size)
- {
- if (Dynamic)
- {
- if (!buffer)
- return true;
-
- void* v = Map(0, size, Map_Discard);
- if (v)
- {
- memcpy(v, buffer, size);
- Unmap(v);
- return true;
- }
- }
- else
- {
- Ren->Context->UpdateSubresource(D3DBuffer, 0, NULL, buffer, 0, 0);
- return true;
- }
- }
- if (D3DBuffer)
- {
- D3DBuffer = NULL;
- Size = 0;
- Use = 0;
- Dynamic = 0;
- }
-
- D3D1x_(BUFFER_DESC) desc;
- memset(&desc, 0, sizeof(desc));
- if (use & Buffer_ReadOnly)
- {
- desc.Usage = D3D1x_(USAGE_IMMUTABLE);
- desc.CPUAccessFlags = 0;
- }
- else
- {
- desc.Usage = D3D1x_(USAGE_DYNAMIC);
- desc.CPUAccessFlags = D3D1x_(CPU_ACCESS_WRITE);
- Dynamic = 1;
- }
-
- switch(use & Buffer_TypeMask)
- {
- case Buffer_Vertex: desc.BindFlags = D3D1x_(BIND_VERTEX_BUFFER); break;
- case Buffer_Index: desc.BindFlags = D3D1x_(BIND_INDEX_BUFFER); break;
- case Buffer_Uniform:
- desc.BindFlags = D3D1x_(BIND_CONSTANT_BUFFER);
- size += ((size + 15) & ~15) - size;
- break;
- }
-
- desc.ByteWidth = (unsigned)size;
-
- D3D1x_(SUBRESOURCE_DATA) sr;
- sr.pSysMem = buffer;
- sr.SysMemPitch = 0;
- sr.SysMemSlicePitch = 0;
-
- HRESULT hr = Ren->Device->CreateBuffer(&desc, buffer ? &sr : NULL, &D3DBuffer.GetRawRef());
- if (SUCCEEDED(hr))
- {
- Use = use;
- Size = desc.ByteWidth;
- return 1;
- }
- return 0;
-}
-
-void* Buffer::Map(size_t start, size_t size, int flags)
-{
- OVR_UNUSED(size);
-
- D3D1x_(MAP) mapFlags = D3D1x_(MAP_WRITE);
- if (flags & Map_Discard)
- mapFlags = D3D1x_(MAP_WRITE_DISCARD);
- if (flags & Map_Unsynchronized)
- mapFlags = D3D1x_(MAP_WRITE_NO_OVERWRITE);
-
- void* map = 0;
- if (SUCCEEDED(D3DBuffer->Map(mapFlags, 0, &map)))
- return ((char*)map) + start;
- return NULL;
-}
-
-bool Buffer::Unmap(void *m)
-{
- OVR_UNUSED(m);
-
- D3DBuffer->Unmap();
- return true;
-}
-
-
-//-------------------------------------------------------------------------------------
-// Shaders
-
-template<> bool Shader<RenderTiny::Shader_Vertex, ID3D10VertexShader>::Load(void* shader, size_t size)
-{
- return SUCCEEDED(Ren->Device->CreateVertexShader(shader, size, &D3DShader));
-}
-template<> bool Shader<RenderTiny::Shader_Pixel, ID3D10PixelShader>::Load(void* shader, size_t size)
-{
- return SUCCEEDED(Ren->Device->CreatePixelShader(shader, size, &D3DShader));
-}
-
-template<> void Shader<RenderTiny::Shader_Vertex, ID3D10VertexShader>::Set(PrimitiveType) const
-{
- Ren->Context->VSSetShader(D3DShader);
-}
-template<> void Shader<RenderTiny::Shader_Pixel, ID3D10PixelShader>::Set(PrimitiveType) const
-{
- Ren->Context->PSSetShader(D3DShader);
-}
-
-template<> void Shader<RenderTiny::Shader_Vertex, ID3D1xVertexShader>::SetUniformBuffer(RenderTiny::Buffer* buffer, int i)
-{
- Ren->Context->VSSetConstantBuffers(i, 1, &((Buffer*)buffer)->D3DBuffer.GetRawRef());
-}
-template<> void Shader<RenderTiny::Shader_Pixel, ID3D1xPixelShader>::SetUniformBuffer(RenderTiny::Buffer* buffer, int i)
-{
- Ren->Context->PSSetConstantBuffers(i, 1, &((Buffer*)buffer)->D3DBuffer.GetRawRef());
-}
-
-
-//-------------------------------------------------------------------------------------
-// ***** Shader Base
-
-ShaderBase::ShaderBase(RenderDevice* r, ShaderStage stage)
- : RenderTiny::Shader(stage), Ren(r), UniformData(0)
-{
-}
-ShaderBase::~ShaderBase()
-{
- if (UniformData)
- OVR_FREE(UniformData);
-}
-
-bool ShaderBase::SetUniform(const char* name, int n, const float* v)
-{
- for(unsigned i = 0; i < UniformInfo.GetSize(); i++)
- {
- if (!strcmp(UniformInfo[i].Name.ToCStr(), name))
- {
- memcpy(UniformData + UniformInfo[i].Offset, v, n * sizeof(float));
- return 1;
- }
- }
- return 0;
-}
-
-void ShaderBase::InitUniforms(ID3D10Blob* s)
-{
- ID3D10ShaderReflection* ref = NULL;
- D3D10ReflectShader(s->GetBufferPointer(), s->GetBufferSize(), &ref);
- ID3D10ShaderReflectionConstantBuffer* buf = ref->GetConstantBufferByIndex(0);
- D3D10_SHADER_BUFFER_DESC bufd;
- if (FAILED(buf->GetDesc(&bufd)))
- {
- UniformsSize = 0;
- if (UniformData)
- {
- OVR_FREE(UniformData);
- UniformData = 0;
- }
- return;
- }
-
- for(unsigned i = 0; i < bufd.Variables; i++)
- {
- ID3D10ShaderReflectionVariable* var = buf->GetVariableByIndex(i);
- if (var)
- {
- D3D10_SHADER_VARIABLE_DESC vd;
- if (SUCCEEDED(var->GetDesc(&vd)))
- {
- Uniform u;
- u.Name = vd.Name;
- u.Offset = vd.StartOffset;
- u.Size = vd.Size;
- UniformInfo.PushBack(u);
- }
- }
- }
-
- UniformsSize = bufd.Size;
- UniformData = (unsigned char*)OVR_ALLOC(bufd.Size);
-}
-
-void ShaderBase::UpdateBuffer(Buffer* buf)
-{
- if (UniformsSize)
- {
- buf->Data(Buffer_Uniform, UniformData, UniformsSize);
- }
-}
-
-
-//-------------------------------------------------------------------------------------
-// ***** Texture
-//
-Texture::Texture(RenderDevice* ren, int fmt, int w, int h)
- : Ren(ren), Tex(NULL), TexSv(NULL), TexRtv(NULL), TexDsv(NULL), Width(w), Height(h)
-{
- OVR_UNUSED(fmt);
- Sampler = Ren->GetSamplerState(0);
-}
-
-Texture::~Texture()
-{
-}
-
-void Texture::Set(int slot, RenderTiny::ShaderStage stage) const
-{
- Ren->SetTexture(stage, slot, this);
-}
-
-void Texture::SetSampleMode(int sm)
-{
- Sampler = Ren->GetSamplerState(sm);
-}
-
-
-
-//-------------------------------------------------------------------------------------
-// ***** Render Device
-
-RenderDevice::RenderDevice(const RendererParams& p, HWND window)
-{
- RECT rc;
- GetClientRect(window, &rc);
- UINT width = rc.right - rc.left;
- UINT height = rc.bottom - rc.top;
- WindowWidth = width;
- WindowHeight = height;
- Window = window;
- Params = p;
-
- HRESULT hr = CreateDXGIFactory(__uuidof(IDXGIFactory), (void**)(&DXGIFactory.GetRawRef()));
- if (FAILED(hr))
- return;
-
- // Find the adapter & output (monitor) to use for fullscreen, based on the reported name of the HMD's monitor.
- if (Params.MonitorName.GetLength() > 0)
- {
- for(UINT AdapterIndex = 0; ; AdapterIndex++)
- {
- HRESULT hr = DXGIFactory->EnumAdapters(AdapterIndex, &Adapter.GetRawRef());
- if (hr == DXGI_ERROR_NOT_FOUND)
- break;
-
- DXGI_ADAPTER_DESC Desc;
- Adapter->GetDesc(&Desc);
-
- UpdateMonitorOutputs();
-
- if (FullscreenOutput)
- break;
- }
-
- if (!FullscreenOutput)
- Adapter = NULL;
- }
-
- if (!Adapter)
- {
- DXGIFactory->EnumAdapters(0, &Adapter.GetRawRef());
- }
-
- int flags = 0;
-
- hr = D3D10CreateDevice(Adapter, D3D10_DRIVER_TYPE_HARDWARE, NULL, flags, D3D1x_(SDK_VERSION),
- &Device.GetRawRef());
- Context = Device;
- Context->AddRef();
-
- if (FAILED(hr))
- return;
-
- if (!RecreateSwapChain())
- return;
-
- if (Params.Fullscreen)
- SwapChain->SetFullscreenState(1, FullscreenOutput);
-
- CurRenderTarget = NULL;
- for(int i = 0; i < Shader_Count; i++)
- {
- UniformBuffers[i] = *CreateBuffer();
- MaxTextureSet[i] = 0;
- }
-
- ID3D10Blob* vsData = CompileShader("vs_4_0", DirectVertexShaderSrc);
- VertexShaders[VShader_MV] = *new VertexShader(this, vsData);
- for(int i = 1; i < VShader_Count; i++)
- {
- VertexShaders[i] = *new VertexShader(this, CompileShader("vs_4_0", VShaderSrcs[i]));
- }
-
- for(int i = 0; i < FShader_Count; i++)
- {
- PixelShaders[i] = *new PixelShader(this, CompileShader("ps_4_0", FShaderSrcs[i]));
- }
-
- SPInt bufferSize = vsData->GetBufferSize();
- const void* buffer = vsData->GetBufferPointer();
- ID3D1xInputLayout** objRef = &ModelVertexIL.GetRawRef();
-
- HRESULT validate = Device->CreateInputLayout(ModelVertexDesc, sizeof(ModelVertexDesc)/sizeof(D3D1x_(INPUT_ELEMENT_DESC)),
- buffer, bufferSize, objRef);
- OVR_UNUSED(validate);
-
- Ptr<ShaderSet> gouraudShaders = *new ShaderSet();
- gouraudShaders->SetShader(VertexShaders[VShader_MVP]);
- gouraudShaders->SetShader(PixelShaders[FShader_Gouraud]);
- DefaultFill = *new ShaderFill(gouraudShaders);
-
- D3D1x_(BLEND_DESC) bm;
- memset(&bm, 0, sizeof(bm));
- bm.BlendEnable[0] = true;
- bm.BlendOp = bm.BlendOpAlpha = D3D1x_(BLEND_OP_ADD);
- bm.SrcBlend = bm.SrcBlendAlpha = D3D1x_(BLEND_SRC_ALPHA);
- bm.DestBlend = bm.DestBlendAlpha = D3D1x_(BLEND_INV_SRC_ALPHA);
- bm.RenderTargetWriteMask[0] = D3D1x_(COLOR_WRITE_ENABLE_ALL);
- Device->CreateBlendState(&bm, &BlendState.GetRawRef());
-
- D3D1x_(RASTERIZER_DESC) rs;
- memset(&rs, 0, sizeof(rs));
- rs.AntialiasedLineEnable = true;
- rs.CullMode = D3D1x_(CULL_BACK);
- rs.DepthClipEnable = true;
- rs.FillMode = D3D1x_(FILL_SOLID);
- Device->CreateRasterizerState(&rs, &Rasterizer.GetRawRef());
-
- QuadVertexBuffer = *CreateBuffer();
- const RenderTiny::Vertex QuadVertices[] =
- { Vertex(Vector3f(0, 1, 0)), Vertex(Vector3f(1, 1, 0)),
- Vertex(Vector3f(0, 0, 0)), Vertex(Vector3f(1, 0, 0)) };
- QuadVertexBuffer->Data(Buffer_Vertex, QuadVertices, sizeof(QuadVertices));
-
- SetDepthMode(0, 0);
-}
-
-RenderDevice::~RenderDevice()
-{
- if (SwapChain && Params.Fullscreen)
- {
- SwapChain->SetFullscreenState(false, NULL);
- }
-}
-
-
-// Implement static initializer function to create this class.
-RenderTiny::RenderDevice* RenderDevice::CreateDevice(const RendererParams& rp, void* oswnd)
-{
- return new RenderDevice(rp, (HWND)oswnd);
-}
-
-
-// Fallback monitor enumeration in case newly plugged in monitor wasn't detected.
-// Added originally for the FactoryTest app.
-// New Outputs don't seem to be detected unless adapter is re-created, but that would also
-// require us to re-initialize D3D10 (recreating objects, etc). This bypasses that for "fake"
-// fullscreen modes.
-BOOL CALLBACK MonitorEnumFunc(HMONITOR hMonitor, HDC, LPRECT, LPARAM dwData)
-{
- RenderDevice* renderer = (RenderDevice*)dwData;
-
- MONITORINFOEX monitor;
- monitor.cbSize = sizeof(monitor);
-
- if (::GetMonitorInfo(hMonitor, &monitor) && monitor.szDevice[0])
- {
- DISPLAY_DEVICE dispDev;
- memset(&dispDev, 0, sizeof(dispDev));
- dispDev.cb = sizeof(dispDev);
-
- if (::EnumDisplayDevices(monitor.szDevice, 0, &dispDev, 0))
- {
- if (strstr(String(dispDev.DeviceName).ToCStr(), renderer->GetParams().MonitorName.ToCStr()))
- {
- renderer->FSDesktopX = monitor.rcMonitor.left;
- renderer->FSDesktopY = monitor.rcMonitor.top;
- return FALSE;
- }
- }
- }
-
- return TRUE;
-}
-
-
-void RenderDevice::UpdateMonitorOutputs()
-{
- HRESULT hr;
-
- bool deviceNameFound = false;
-
- for(UINT OutputIndex = 0; ; OutputIndex++)
- {
- Ptr<IDXGIOutput> Output;
- hr = Adapter->EnumOutputs(OutputIndex, &Output.GetRawRef());
- if (hr == DXGI_ERROR_NOT_FOUND)
- {
- break;
- }
-
- DXGI_OUTPUT_DESC OutDesc;
- Output->GetDesc(&OutDesc);
-
- MONITORINFOEX monitor;
- monitor.cbSize = sizeof(monitor);
- if (::GetMonitorInfo(OutDesc.Monitor, &monitor) && monitor.szDevice[0])
- {
- DISPLAY_DEVICE dispDev;
- memset(&dispDev, 0, sizeof(dispDev));
- dispDev.cb = sizeof(dispDev);
-
- if (::EnumDisplayDevices(monitor.szDevice, 0, &dispDev, 0))
- {
- if (strstr(String(dispDev.DeviceName).ToCStr(), Params.MonitorName.ToCStr()))
- {
- deviceNameFound = true;
- FullscreenOutput = Output;
- FSDesktopX = monitor.rcMonitor.left;
- FSDesktopY = monitor.rcMonitor.top;
- break;
- }
- }
- }
- }
-
- if (!deviceNameFound && !Params.MonitorName.IsEmpty())
- {
- EnumDisplayMonitors(0, 0, MonitorEnumFunc, (LPARAM)this);
- }
-}
-
-bool RenderDevice::RecreateSwapChain()
-{
- DXGI_SWAP_CHAIN_DESC scDesc;
- memset(&scDesc, 0, sizeof(scDesc));
- scDesc.BufferCount = 1;
- scDesc.BufferDesc.Width = WindowWidth;
- scDesc.BufferDesc.Height = WindowHeight;
- scDesc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
- scDesc.BufferDesc.RefreshRate.Numerator = 60;
- scDesc.BufferDesc.RefreshRate.Denominator = 1;
- scDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
- scDesc.OutputWindow = Window;
- scDesc.SampleDesc.Count = Params.Multisample;
- scDesc.SampleDesc.Quality = 0;
- scDesc.Windowed = (Params.Fullscreen != Display_Fullscreen);
- scDesc.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH;
-
- if (SwapChain)
- {
- SwapChain->SetFullscreenState(FALSE, NULL);
- SwapChain->Release();
- SwapChain = NULL;
- }
-
- Ptr<IDXGISwapChain> newSC;
- if (FAILED(DXGIFactory->CreateSwapChain(Device, &scDesc, &newSC.GetRawRef())))
- return false;
- SwapChain = newSC;
-
- BackBuffer = NULL;
- BackBufferRT = NULL;
- HRESULT hr = SwapChain->GetBuffer(0, __uuidof(ID3D1xTexture2D), (void**)&BackBuffer.GetRawRef());
- if (FAILED(hr))
- return false;
-
- hr = Device->CreateRenderTargetView(BackBuffer, NULL, &BackBufferRT.GetRawRef());
- if (FAILED(hr))
- return false;
-
- Texture* depthBuffer = GetDepthBuffer(WindowWidth, WindowHeight, Params.Multisample);
- CurDepthBuffer = depthBuffer;
- if (CurRenderTarget == NULL)
- {
- Context->OMSetRenderTargets(1, &BackBufferRT.GetRawRef(), depthBuffer->TexDsv);
- }
- return true;
-}
-
-bool RenderDevice::SetParams(const RendererParams& newParams)
-{
- String oldMonitor = Params.MonitorName;
-
- Params = newParams;
- if (newParams.MonitorName != oldMonitor)
- {
- UpdateMonitorOutputs();
- }
-
- // Cause this to be recreated with the new multisample mode.
- pSceneColorTex = NULL;
- return RecreateSwapChain();
-}
-
-
-bool RenderDevice::SetFullscreen(DisplayMode fullscreen)
-{
- if (fullscreen == Params.Fullscreen)
- return true;
-
- HRESULT hr = SwapChain->SetFullscreenState(fullscreen, fullscreen ? FullscreenOutput : NULL);
- if (FAILED(hr))
- {
- return false;
- }
-
- Params.Fullscreen = fullscreen;
- return true;
-}
-
-void RenderDevice::SetRealViewport(const Viewport& vp)
-{
- D3DViewport.Width = vp.w;
- D3DViewport.Height = vp.h;
- D3DViewport.MinDepth = 0;
- D3DViewport.MaxDepth = 1;
- D3DViewport.TopLeftX = vp.x;
- D3DViewport.TopLeftY = vp.y;
- Context->RSSetViewports(1, &D3DViewport);
-}
-
-static int GetDepthStateIndex(bool enable, bool write, RenderDevice::CompareFunc func)
-{
- if (!enable)
- return 0;
- return 1 + int(func) * 2 + write;
-}
-
-void RenderDevice::SetDepthMode(bool enable, bool write, CompareFunc func)
-{
- int index = GetDepthStateIndex(enable, write, func);
- if (DepthStates[index])
- {
- CurDepthState = DepthStates[index];
- Context->OMSetDepthStencilState(DepthStates[index], 0);
- return;
- }
-
- D3D1x_(DEPTH_STENCIL_DESC) dss;
- memset(&dss, 0, sizeof(dss));
- dss.DepthEnable = enable;
- switch(func)
- {
- case Compare_Always: dss.DepthFunc = D3D1x_(COMPARISON_ALWAYS); break;
- case Compare_Less: dss.DepthFunc = D3D1x_(COMPARISON_LESS); break;
- case Compare_Greater: dss.DepthFunc = D3D1x_(COMPARISON_GREATER); break;
- default:
- assert(0);
- }
- dss.DepthWriteMask = write ? D3D1x_(DEPTH_WRITE_MASK_ALL) : D3D1x_(DEPTH_WRITE_MASK_ZERO);
- Device->CreateDepthStencilState(&dss, &DepthStates[index].GetRawRef());
- Context->OMSetDepthStencilState(DepthStates[index], 0);
- CurDepthState = DepthStates[index];
-}
-
-Texture* RenderDevice::GetDepthBuffer(int w, int h, int ms)
-{
- for(unsigned i = 0; i < DepthBuffers.GetSize(); i++)
- {
- if (w == DepthBuffers[i]->Width && h == DepthBuffers[i]->Height &&
- ms == DepthBuffers[i]->Samples)
- return DepthBuffers[i];
- }
-
- Ptr<Texture> newDepth = *CreateTexture(Texture_Depth | Texture_RenderTarget | ms, w, h, NULL);
- if (newDepth == NULL)
- {
- OVR_DEBUG_LOG(("Failed to get depth buffer."));
- return NULL;
- }
-
- DepthBuffers.PushBack(newDepth);
- return newDepth.GetPtr();
-}
-
-void RenderDevice::Clear(float r, float g, float b, float a, float depth)
-{
- const float color[] = {r, g, b, a};
-
- // Needed for each eye to do its own clear, since ClearRenderTargetView doesn't honor viewport.
-
- // Save state that is affected by clearing this way
- ID3D1xDepthStencilState* oldDepthState = CurDepthState;
- StandardUniformData clearUniforms;
-
- SetDepthMode(true, true, Compare_Always);
-
- Context->IASetInputLayout(ModelVertexIL);
- Context->GSSetShader(NULL);
-
- ID3D1xShaderResourceView* sv[8] = {0, 0, 0, 0, 0, 0, 0, 0};
- if (MaxTextureSet[Shader_Fragment])
- {
- Context->PSSetShaderResources(0, MaxTextureSet[Shader_Fragment], sv);
- }
-
- ID3D1xBuffer* vertexBuffer = QuadVertexBuffer->GetBuffer();
- UINT vertexStride = sizeof(Vertex);
- UINT vertexOffset = 0;
- Context->IASetVertexBuffers(0, 1, &vertexBuffer, &vertexStride, &vertexOffset);
-
- clearUniforms.View = Matrix4f(2, 0, 0, 0,
- 0, 2, 0, 0,
- 0, 0, 0, 0,
- -1, -1, depth, 1);
- UniformBuffers[Shader_Vertex]->Data(Buffer_Uniform, &clearUniforms, sizeof(clearUniforms));
-
- ID3D1xBuffer* vertexConstants = UniformBuffers[Shader_Vertex]->GetBuffer();
- Context->VSSetConstantBuffers(0, 1, &vertexConstants);
- Context->IASetPrimitiveTopology(D3D1x_(PRIMITIVE_TOPOLOGY_TRIANGLESTRIP));
- VertexShaders[VShader_MV]->Set(Prim_TriangleStrip);
- PixelShaders[FShader_Solid]->Set(Prim_TriangleStrip);
-
- UniformBuffers[Shader_Pixel]->Data(Buffer_Uniform, color, sizeof(color));
- PixelShaders[FShader_Solid]->SetUniformBuffer(UniformBuffers[Shader_Pixel]);
-
- // Clear Viewport
- Context->OMSetBlendState(NULL, NULL, 0xffffffff);
- Context->Draw(4, 0);
-
- // reset
- CurDepthState = oldDepthState;
- Context->OMSetDepthStencilState(CurDepthState, 0);
-}
-
-// Buffers
-
-Buffer* RenderDevice::CreateBuffer()
-{
- return new Buffer(this);
-}
-
-
-ID3D10Blob* RenderDevice::CompileShader(const char* profile, const char* src, const char* mainName)
-{
- ID3D10Blob* shader;
- ID3D10Blob* errors;
- HRESULT hr = D3DCompile(src, strlen(src), NULL, NULL, NULL, mainName, profile,
- 0, 0, &shader, &errors);
- if (FAILED(hr))
- {
- OVR_DEBUG_LOG(("Compiling D3D shader for %s failed\n%s\n\n%s",
- profile, src, errors->GetBufferPointer()));
- OutputDebugStringA((char*)errors->GetBufferPointer());
- return NULL;
- }
- if (errors)
- {
- errors->Release();
- }
- return shader;
-}
-
-void RenderDevice::SetCommonUniformBuffer(int i, RenderTiny::Buffer* buffer)
-{
- CommonUniforms[i] = (Buffer*)buffer;
-
- Context->PSSetConstantBuffers(1, 1, &CommonUniforms[1]->D3DBuffer.GetRawRef());
- Context->VSSetConstantBuffers(1, 1, &CommonUniforms[1]->D3DBuffer.GetRawRef());
-}
-
-RenderTiny::Shader *RenderDevice::LoadBuiltinShader(ShaderStage stage, int shader)
-{
- switch(stage)
- {
- case Shader_Vertex:
- return VertexShaders[shader];
- case Shader_Pixel:
- return PixelShaders[shader];
- default:
- return NULL;
- }
-}
-
-
-ID3D1xSamplerState* RenderDevice::GetSamplerState(int sm)
-{
- if (SamplerStates[sm])
- return SamplerStates[sm];
-
- D3D1x_(SAMPLER_DESC) ss;
- memset(&ss, 0, sizeof(ss));
- if (sm & Sample_Clamp)
- ss.AddressU = ss.AddressV = ss.AddressW = D3D1x_(TEXTURE_ADDRESS_CLAMP);
- else if (sm & Sample_ClampBorder)
- ss.AddressU = ss.AddressV = ss.AddressW = D3D1x_(TEXTURE_ADDRESS_BORDER);
- else
- ss.AddressU = ss.AddressV = ss.AddressW = D3D1x_(TEXTURE_ADDRESS_WRAP);
-
- if (sm & Sample_Nearest)
- {
- ss.Filter = D3D1x_(FILTER_MIN_MAG_MIP_POINT);
- }
- else if (sm & Sample_Anisotropic)
- {
- ss.Filter = D3D1x_(FILTER_ANISOTROPIC);
- ss.MaxAnisotropy = 8;
- }
- else
- {
- ss.Filter = D3D1x_(FILTER_MIN_MAG_MIP_LINEAR);
- }
- ss.MaxLOD = 15;
- Device->CreateSamplerState(&ss, &SamplerStates[sm].GetRawRef());
- return SamplerStates[sm];
-}
-
-
-void RenderDevice::SetTexture(RenderTiny::ShaderStage stage, int slot, const Texture* t)
-{
- if (MaxTextureSet[stage] <= slot)
- MaxTextureSet[stage] = slot + 1;
-
- ID3D1xShaderResourceView* sv = t ? t->TexSv : NULL;
- switch(stage)
- {
- case Shader_Fragment:
- Context->PSSetShaderResources(slot, 1, &sv);
- if (t)
- {
- Context->PSSetSamplers(slot, 1, &t->Sampler.GetRawRef());
- }
- break;
-
- case Shader_Vertex:
- Context->VSSetShaderResources(slot, 1, &sv);
- break;
- }
-}
-
-Texture* RenderDevice::CreateTexture(int format, int width, int height, const void* data, int mipcount)
-{
- OVR_UNUSED(mipcount);
-
- DXGI_FORMAT d3dformat;
- int bpp;
- switch(format & Texture_TypeMask)
- {
- case Texture_RGBA:
- bpp = 4;
- d3dformat = DXGI_FORMAT_R8G8B8A8_UNORM;
- break;
- case Texture_Depth:
- bpp = 0;
- d3dformat = DXGI_FORMAT_D32_FLOAT;
- break;
- default:
- return NULL;
- }
-
- int samples = (format & Texture_SamplesMask);
- if (samples < 1)
- {
- samples = 1;
- }
-
- Texture* NewTex = new Texture(this, format, width, height);
- NewTex->Samples = samples;
-
- D3D1x_(TEXTURE2D_DESC) dsDesc;
- dsDesc.Width = width;
- dsDesc.Height = height;
- dsDesc.MipLevels = (format == (Texture_RGBA | Texture_GenMipmaps) && data) ? GetNumMipLevels(width, height) : 1;
- dsDesc.ArraySize = 1;
- dsDesc.Format = d3dformat;
- dsDesc.SampleDesc.Count = samples;
- dsDesc.SampleDesc.Quality = 0;
- dsDesc.Usage = D3D1x_(USAGE_DEFAULT);
- dsDesc.BindFlags = D3D1x_(BIND_SHADER_RESOURCE);
- dsDesc.CPUAccessFlags = 0;
- dsDesc.MiscFlags = 0;
-
- if (format & Texture_RenderTarget)
- {
- if ((format & Texture_TypeMask) == Texture_Depth)
- { // We don't use depth textures, and creating them in d3d10 requires different options.
- dsDesc.BindFlags = D3D1x_(BIND_DEPTH_STENCIL);
- }
- else
- {
- dsDesc.BindFlags |= D3D1x_(BIND_RENDER_TARGET);
- }
- }
-
- HRESULT hr = Device->CreateTexture2D(&dsDesc, NULL, &NewTex->Tex.GetRawRef());
- if (FAILED(hr))
- {
- OVR_DEBUG_LOG_TEXT(("Failed to create 2D D3D texture."));
- NewTex->Release();
- return NULL;
- }
- if (dsDesc.BindFlags & D3D1x_(BIND_SHADER_RESOURCE))
- {
- Device->CreateShaderResourceView(NewTex->Tex, NULL, &NewTex->TexSv.GetRawRef());
- }
-
- if (data)
- {
- Context->UpdateSubresource(NewTex->Tex, 0, NULL, data, width * bpp, width * height * bpp);
- if (format == (Texture_RGBA | Texture_GenMipmaps))
- {
- int srcw = width, srch = height;
- int level = 0;
- UByte* mipmaps = NULL;
- do
- {
- level++;
- int mipw = srcw >> 1;
- if (mipw < 1)
- {
- mipw = 1;
- }
- int miph = srch >> 1;
- if (miph < 1)
- {
- miph = 1;
- }
- if (mipmaps == NULL)
- {
- mipmaps = (UByte*)OVR_ALLOC(mipw * miph * 4);
- }
- FilterRgba2x2(level == 1 ? (const UByte*)data : mipmaps, srcw, srch, mipmaps);
- Context->UpdateSubresource(NewTex->Tex, level, NULL, mipmaps, mipw * bpp, miph * bpp);
- srcw = mipw;
- srch = miph;
- }
- while(srcw > 1 || srch > 1);
-
- if (mipmaps != NULL)
- {
- OVR_FREE(mipmaps);
- }
- }
- }
-
- if (format & Texture_RenderTarget)
- {
- if ((format & Texture_TypeMask) == Texture_Depth)
- {
- Device->CreateDepthStencilView(NewTex->Tex, NULL, &NewTex->TexDsv.GetRawRef());
- }
- else
- {
- Device->CreateRenderTargetView(NewTex->Tex, NULL, &NewTex->TexRtv.GetRawRef());
- }
- }
-
- return NewTex;
-}
-
-
-// Rendering
-
-void RenderDevice::BeginRendering()
-{
- Context->RSSetState(Rasterizer);
-}
-
-void RenderDevice::SetRenderTarget(RenderTiny::Texture* colorTex,
- RenderTiny::Texture* depth, RenderTiny::Texture* stencil)
-{
- OVR_UNUSED(stencil);
-
- CurRenderTarget = (Texture*)colorTex;
- if (colorTex == NULL)
- {
- Texture* newDepthBuffer = GetDepthBuffer(WindowWidth, WindowHeight, Params.Multisample);
- if (newDepthBuffer == NULL)
- {
- OVR_DEBUG_LOG(("New depth buffer creation failed."));
- }
- if (newDepthBuffer != NULL)
- {
- CurDepthBuffer = GetDepthBuffer(WindowWidth, WindowHeight, Params.Multisample);
- Context->OMSetRenderTargets(1, &BackBufferRT.GetRawRef(), CurDepthBuffer->TexDsv);
- }
- return;
- }
- if (depth == NULL)
- {
- depth = GetDepthBuffer(colorTex->GetWidth(), colorTex->GetHeight(), CurRenderTarget->Samples);
- }
-
- ID3D1xShaderResourceView* sv[8] = {0, 0, 0, 0, 0, 0, 0, 0};
- if (MaxTextureSet[Shader_Fragment])
- {
- Context->PSSetShaderResources(0, MaxTextureSet[Shader_Fragment], sv);
- }
- memset(MaxTextureSet, 0, sizeof(MaxTextureSet));
-
- CurDepthBuffer = (Texture*)depth;
- Context->OMSetRenderTargets(1, &((Texture*)colorTex)->TexRtv.GetRawRef(), ((Texture*)depth)->TexDsv);
-}
-
-
-void RenderDevice::SetWorldUniforms(const Matrix4f& proj)
-{
- StdUniforms.Proj = proj.Transposed();
- // Shader constant buffers cannot be partially updated.
-}
-
-
-void RenderDevice::Render(const Matrix4f& matrix, Model* model)
-{
- // Store data in buffers if not already
- if (!model->VertexBuffer)
- {
- Ptr<Buffer> vb = *CreateBuffer();
- vb->Data(Buffer_Vertex, &model->Vertices[0], model->Vertices.GetSize() * sizeof(Vertex));
- model->VertexBuffer = vb;
- }
- if (!model->IndexBuffer)
- {
- Ptr<Buffer> ib = *CreateBuffer();
- ib->Data(Buffer_Index, &model->Indices[0], model->Indices.GetSize() * 2);
- model->IndexBuffer = ib;
- }
-
- Render(model->Fill ? model->Fill : DefaultFill,
- model->VertexBuffer, model->IndexBuffer,
- matrix, 0, (unsigned)model->Indices.GetSize(), model->GetPrimType());
-}
-
-void RenderDevice::Render(const ShaderFill* fill, RenderTiny::Buffer* vertices, RenderTiny::Buffer* indices,
- const Matrix4f& matrix, int offset, int count, PrimitiveType rprim)
-{
- Context->IASetInputLayout(ModelVertexIL);
- if (indices)
- {
- Context->IASetIndexBuffer(((Buffer*)indices)->GetBuffer(), DXGI_FORMAT_R16_UINT, 0);
- }
-
- ID3D1xBuffer* vertexBuffer = ((Buffer*)vertices)->GetBuffer();
- UINT vertexStride = sizeof(Vertex);
- UINT vertexOffset = offset;
- Context->IASetVertexBuffers(0, 1, &vertexBuffer, &vertexStride, &vertexOffset);
-
- ShaderSet* shaders = ((ShaderFill*)fill)->GetShaders();
-
- ShaderBase* vshader = ((ShaderBase*)shaders->GetShader(Shader_Vertex));
- unsigned char* vertexData = vshader->UniformData;
- if (vertexData)
- {
- StandardUniformData* stdUniforms = (StandardUniformData*) vertexData;
- stdUniforms->View = matrix.Transposed();
- stdUniforms->Proj = StdUniforms.Proj;
- UniformBuffers[Shader_Vertex]->Data(Buffer_Uniform, vertexData, vshader->UniformsSize);
- vshader->SetUniformBuffer(UniformBuffers[Shader_Vertex]);
- }
-
- for(int i = Shader_Vertex + 1; i < Shader_Count; i++)
- if (shaders->GetShader(i))
- {
- ((ShaderBase*)shaders->GetShader(i))->UpdateBuffer(UniformBuffers[i]);
- ((ShaderBase*)shaders->GetShader(i))->SetUniformBuffer(UniformBuffers[i]);
- }
-
- D3D1x_(PRIMITIVE_TOPOLOGY) prim;
- switch(rprim)
- {
- case Prim_Triangles:
- prim = D3D1x_(PRIMITIVE_TOPOLOGY_TRIANGLELIST);
- break;
- case Prim_Lines:
- prim = D3D1x_(PRIMITIVE_TOPOLOGY_LINELIST);
- break;
- case Prim_TriangleStrip:
- prim = D3D1x_(PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);
- break;
- default:
- assert(0);
- return;
- }
- Context->IASetPrimitiveTopology(prim);
-
- fill->Set(rprim);
-
- if (indices)
- {
- Context->DrawIndexed(count, 0, 0);
- }
- else
- {
- Context->Draw(count, 0);
- }
-}
-
-
-void RenderDevice::Present()
-{
- SwapChain->Present(0, 0);
-}
-
-void RenderDevice::ForceFlushGPU()
-{
- D3D1x_QUERY_DESC queryDesc = { D3D1x_(QUERY_EVENT), 0 };
- Ptr<ID3D1xQuery> query;
- BOOL done = FALSE;
-
- if (Device->CreateQuery(&queryDesc, &query.GetRawRef()) == S_OK)
- {
- // Begin() not used for EVENT query.
- query->End();
- // GetData will returns S_OK for both done == TRUE or FALSE.
- // Exit on failure to avoid infinite loop.
- do { }
- while(!done && !FAILED(query->GetData(&done, sizeof(BOOL), 0)));
- }
-}
-
-}}}
-
+/************************************************************************************
+
+Filename : RenderTiny_D3D1x.cpp
+Content : RenderDevice implementation for D3DX10/11.
+Created : September 10, 2012
+Authors : Andrew Reisse
+
+Copyright : Copyright 2012 Oculus VR, Inc. All Rights reserved.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+************************************************************************************/
+
+#include "Kernel/OVR_Log.h"
+#include "Kernel/OVR_Std.h"
+
+#include "RenderTiny_D3D1X_Device.h"
+
+#include <d3dcompiler.h>
+
+namespace OVR { namespace RenderTiny { namespace D3D10 {
+
+
+//-------------------------------------------------------------------------------------
+// Vertex format
+static D3D1x_(INPUT_ELEMENT_DESC) ModelVertexDesc[] =
+{
+ {"Position", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, offsetof(Vertex, Pos), D3D1x_(INPUT_PER_VERTEX_DATA), 0},
+ {"Color", 0, DXGI_FORMAT_R8G8B8A8_UNORM, 0, offsetof(Vertex, C), D3D1x_(INPUT_PER_VERTEX_DATA), 0},
+ {"TexCoord", 0, DXGI_FORMAT_R32G32_FLOAT, 0, offsetof(Vertex, U), D3D1x_(INPUT_PER_VERTEX_DATA), 0},
+ {"Normal", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, offsetof(Vertex, Norm), D3D1x_(INPUT_PER_VERTEX_DATA), 0},
+};
+
+// These shaders are used to render the world, including lit vertex-colored and textured geometry.
+
+// Used for world geometry; has projection matrix.
+static const char* StdVertexShaderSrc =
+ "float4x4 Proj;\n"
+ "float4x4 View;\n"
+ "struct Varyings\n"
+ "{\n"
+ " float4 Position : SV_Position;\n"
+ " float4 Color : COLOR0;\n"
+ " float2 TexCoord : TEXCOORD0;\n"
+ " float3 Normal : NORMAL;\n"
+ " float3 VPos : TEXCOORD4;\n"
+ "};\n"
+ "void main(in float4 Position : POSITION, in float4 Color : COLOR0, in float2 TexCoord : TEXCOORD0,"
+ " in float3 Normal : NORMAL,\n"
+ " out Varyings ov)\n"
+ "{\n"
+ " ov.Position = mul(Proj, mul(View, Position));\n"
+ " ov.Normal = mul(View, Normal);\n"
+ " ov.VPos = mul(View, Position);\n"
+ " ov.TexCoord = TexCoord;\n"
+ " ov.Color = Color;\n"
+ "}\n";
+
+// Used for text/clearing; no projection.
+static const char* DirectVertexShaderSrc =
+ "float4x4 View : register(c4);\n"
+ "void main(in float4 Position : POSITION, in float4 Color : COLOR0,\n"
+ " in float2 TexCoord : TEXCOORD0, in float3 Normal : NORMAL,\n"
+ " out float4 oPosition : SV_Position, out float4 oColor : COLOR,\n"
+ " out float2 oTexCoord : TEXCOORD0,"
+ " out float3 oNormal : NORMAL)\n"
+ "{\n"
+ " oPosition = mul(View, Position);\n"
+ " oTexCoord = TexCoord;\n"
+ " oColor = Color;\n"
+ " oNormal = mul(View, Normal);\n"
+ "}\n";
+
+static const char* SolidPixelShaderSrc =
+ "float4 Color;\n"
+ "struct Varyings\n"
+ "{\n"
+ " float4 Position : SV_Position;\n"
+ " float4 Color : COLOR0;\n"
+ " float2 TexCoord : TEXCOORD0;\n"
+ "};\n"
+ "float4 main(in Varyings ov) : SV_Target\n"
+ "{\n"
+ " return Color;\n"
+ "}\n";
+
+static const char* GouraudPixelShaderSrc =
+ "struct Varyings\n"
+ "{\n"
+ " float4 Position : SV_Position;\n"
+ " float4 Color : COLOR0;\n"
+ " float2 TexCoord : TEXCOORD0;\n"
+ "};\n"
+ "float4 main(in Varyings ov) : SV_Target\n"
+ "{\n"
+ " return ov.Color;\n"
+ "}\n";
+
+static const char* TexturePixelShaderSrc =
+ "Texture2D Texture : register(t0);\n"
+ "SamplerState Linear : register(s0);\n"
+ "struct Varyings\n"
+ "{\n"
+ " float4 Position : SV_Position;\n"
+ " float4 Color : COLOR0;\n"
+ " float2 TexCoord : TEXCOORD0;\n"
+ "};\n"
+ "float4 main(in Varyings ov) : SV_Target\n"
+ "{\n"
+ " float4 color2 = ov.Color * Texture.Sample(Linear, ov.TexCoord);\n"
+ " if (color2.a <= 0.4)\n"
+ " discard;\n"
+ " return color2;\n"
+ "}\n";
+
+
+#define LIGHTING_COMMON \
+ "cbuffer Lighting : register(b1)\n" \
+ "{\n" \
+ " float3 Ambient;\n" \
+ " float3 LightPos[8];\n" \
+ " float4 LightColor[8];\n" \
+ " float LightCount;\n" \
+ "};\n" \
+ "struct Varyings\n" \
+ "{\n" \
+ " float4 Position : SV_Position;\n" \
+ " float4 Color : COLOR0;\n" \
+ " float2 TexCoord : TEXCOORD0;\n" \
+ " float3 Normal : NORMAL;\n" \
+ " float3 VPos : TEXCOORD4;\n" \
+ "};\n" \
+ "float4 DoLight(Varyings v)\n" \
+ "{\n" \
+ " float3 norm = normalize(v.Normal);\n" \
+ " float3 light = Ambient;\n" \
+ " for (uint i = 0; i < LightCount; i++)\n"\
+ " {\n" \
+ " float3 ltp = (LightPos[i] - v.VPos);\n" \
+ " float ldist = dot(ltp,ltp);\n" \
+ " ltp = normalize(ltp);\n" \
+ " light += saturate(LightColor[i] * v.Color.rgb * dot(norm, ltp) / sqrt(ldist));\n"\
+ " }\n" \
+ " return float4(light, v.Color.a);\n" \
+ "}\n"
+
+static const char* LitSolidPixelShaderSrc =
+ LIGHTING_COMMON
+ "float4 main(in Varyings ov) : SV_Target\n"
+ "{\n"
+ " return DoLight(ov) * ov.Color;\n"
+ "}\n";
+
+static const char* LitTexturePixelShaderSrc =
+ "Texture2D Texture : register(t0);\n"
+ "SamplerState Linear : register(s0);\n"
+ LIGHTING_COMMON
+ "float4 main(in Varyings ov) : SV_Target\n"
+ "{\n"
+ " return DoLight(ov) * Texture.Sample(Linear, ov.TexCoord);\n"
+ "}\n";
+
+
+//-------------------------------------------------------------------------------------
+// ***** Distortion Post-process Shaders
+
+static const char* PostProcessVertexShaderSrc =
+ "float4x4 View : register(c4);\n"
+ "float4x4 Texm : register(c8);\n"
+ "void main(in float4 Position : POSITION, in float4 Color : COLOR0, in float2 TexCoord : TEXCOORD0,\n"
+ " out float4 oPosition : SV_Position, out float4 oColor : COLOR, out float2 oTexCoord : TEXCOORD0)\n"
+ "{\n"
+ " oPosition = mul(View, Position);\n"
+ " oTexCoord = mul(Texm, float4(TexCoord,0,1));\n"
+ " oColor = Color;\n"
+ "}\n";
+
+// Shader with just lens distortion correction.
+static const char* PostProcessPixelShaderSrc =
+ "Texture2D Texture : register(t0);\n"
+ "SamplerState Linear : register(s0);\n"
+ "float2 LensCenter;\n"
+ "float2 ScreenCenter;\n"
+ "float2 Scale;\n"
+ "float2 ScaleIn;\n"
+ "float4 HmdWarpParam;\n"
+ "\n"
+
+ // Scales input texture coordinates for distortion.
+ // ScaleIn maps texture coordinates to Scales to ([-1, 1]), although top/bottom will be
+ // larger due to aspect ratio.
+ "float2 HmdWarp(float2 in01)\n"
+ "{\n"
+ " float2 theta = (in01 - LensCenter) * ScaleIn;\n" // Scales to [-1, 1]
+ " float rSq = theta.x * theta.x + theta.y * theta.y;\n"
+ " float2 theta1 = theta * (HmdWarpParam.x + HmdWarpParam.y * rSq + "
+ " HmdWarpParam.z * rSq * rSq + HmdWarpParam.w * rSq * rSq * rSq);\n"
+ " return LensCenter + Scale * theta1;\n"
+ "}\n"
+
+ "float4 main(in float4 oPosition : SV_Position, in float4 oColor : COLOR,\n"
+ " in float2 oTexCoord : TEXCOORD0) : SV_Target\n"
+ "{\n"
+ " float2 tc = HmdWarp(oTexCoord);\n"
+ " if (any(clamp(tc, ScreenCenter-float2(0.25,0.5), ScreenCenter+float2(0.25, 0.5)) - tc))\n"
+ " return 0;\n"
+ " return Texture.Sample(Linear, tc);\n"
+ "}\n";
+
+// Shader with lens distortion and chromatic aberration correction.
+static const char* PostProcessPixelShaderWithChromAbSrc =
+ "Texture2D Texture : register(t0);\n"
+ "SamplerState Linear : register(s0);\n"
+ "float2 LensCenter;\n"
+ "float2 ScreenCenter;\n"
+ "float2 Scale;\n"
+ "float2 ScaleIn;\n"
+ "float4 HmdWarpParam;\n"
+ "float4 ChromAbParam;\n"
+ "\n"
+
+ // Scales input texture coordinates for distortion.
+ // ScaleIn maps texture coordinates to Scales to ([-1, 1]), although top/bottom will be
+ // larger due to aspect ratio.
+ "float4 main(in float4 oPosition : SV_Position, in float4 oColor : COLOR,\n"
+ " in float2 oTexCoord : TEXCOORD0) : SV_Target\n"
+ "{\n"
+ " float2 theta = (oTexCoord - LensCenter) * ScaleIn;\n" // Scales to [-1, 1]
+ " float rSq= theta.x * theta.x + theta.y * theta.y;\n"
+ " float2 theta1 = theta * (HmdWarpParam.x + HmdWarpParam.y * rSq + "
+ " HmdWarpParam.z * rSq * rSq + HmdWarpParam.w * rSq * rSq * rSq);\n"
+ " \n"
+ " // Detect whether blue texture coordinates are out of range since these will scaled out the furthest.\n"
+ " float2 thetaBlue = theta1 * (ChromAbParam.z + ChromAbParam.w * rSq);\n"
+ " float2 tcBlue = LensCenter + Scale * thetaBlue;\n"
+ " if (any(clamp(tcBlue, ScreenCenter-float2(0.25,0.5), ScreenCenter+float2(0.25, 0.5)) - tcBlue))\n"
+ " return 0;\n"
+ " \n"
+ " // Now do blue texture lookup.\n"
+ " float blue = Texture.Sample(Linear, tcBlue).b;\n"
+ " \n"
+ " // Do green lookup (no scaling).\n"
+ " float2 tcGreen = LensCenter + Scale * theta1;\n"
+ " float green = Texture.Sample(Linear, tcGreen).g;\n"
+ " \n"
+ " // Do red scale and lookup.\n"
+ " float2 thetaRed = theta1 * (ChromAbParam.x + ChromAbParam.y * rSq);\n"
+ " float2 tcRed = LensCenter + Scale * thetaRed;\n"
+ " float red = Texture.Sample(Linear, tcRed).r;\n"
+ " \n"
+ " return float4(red, green, blue, 1);\n"
+ "}\n";
+
+
+static const char* VShaderSrcs[VShader_Count] =
+{
+ DirectVertexShaderSrc,
+ StdVertexShaderSrc,
+ PostProcessVertexShaderSrc
+};
+static const char* FShaderSrcs[FShader_Count] =
+{
+ SolidPixelShaderSrc,
+ GouraudPixelShaderSrc,
+ TexturePixelShaderSrc,
+ PostProcessPixelShaderSrc,
+ PostProcessPixelShaderWithChromAbSrc,
+ LitSolidPixelShaderSrc,
+ LitTexturePixelShaderSrc
+};
+
+
+//-------------------------------------------------------------------------------------
+// ***** Buffer
+
+Buffer::~Buffer()
+{
+}
+
+bool Buffer::Data(int use, const void *buffer, size_t size)
+{
+ if (D3DBuffer && Size >= size)
+ {
+ if (Dynamic)
+ {
+ if (!buffer)
+ return true;
+
+ void* v = Map(0, size, Map_Discard);
+ if (v)
+ {
+ memcpy(v, buffer, size);
+ Unmap(v);
+ return true;
+ }
+ }
+ else
+ {
+ Ren->Context->UpdateSubresource(D3DBuffer, 0, NULL, buffer, 0, 0);
+ return true;
+ }
+ }
+ if (D3DBuffer)
+ {
+ D3DBuffer = NULL;
+ Size = 0;
+ Use = 0;
+ Dynamic = 0;
+ }
+
+ D3D1x_(BUFFER_DESC) desc;
+ memset(&desc, 0, sizeof(desc));
+ if (use & Buffer_ReadOnly)
+ {
+ desc.Usage = D3D1x_(USAGE_IMMUTABLE);
+ desc.CPUAccessFlags = 0;
+ }
+ else
+ {
+ desc.Usage = D3D1x_(USAGE_DYNAMIC);
+ desc.CPUAccessFlags = D3D1x_(CPU_ACCESS_WRITE);
+ Dynamic = 1;
+ }
+
+ switch(use & Buffer_TypeMask)
+ {
+ case Buffer_Vertex: desc.BindFlags = D3D1x_(BIND_VERTEX_BUFFER); break;
+ case Buffer_Index: desc.BindFlags = D3D1x_(BIND_INDEX_BUFFER); break;
+ case Buffer_Uniform:
+ desc.BindFlags = D3D1x_(BIND_CONSTANT_BUFFER);
+ size += ((size + 15) & ~15) - size;
+ break;
+ }
+
+ desc.ByteWidth = (unsigned)size;
+
+ D3D1x_(SUBRESOURCE_DATA) sr;
+ sr.pSysMem = buffer;
+ sr.SysMemPitch = 0;
+ sr.SysMemSlicePitch = 0;
+
+ HRESULT hr = Ren->Device->CreateBuffer(&desc, buffer ? &sr : NULL, &D3DBuffer.GetRawRef());
+ if (SUCCEEDED(hr))
+ {
+ Use = use;
+ Size = desc.ByteWidth;
+ return 1;
+ }
+ return 0;
+}
+
+void* Buffer::Map(size_t start, size_t size, int flags)
+{
+ OVR_UNUSED(size);
+
+ D3D1x_(MAP) mapFlags = D3D1x_(MAP_WRITE);
+ if (flags & Map_Discard)
+ mapFlags = D3D1x_(MAP_WRITE_DISCARD);
+ if (flags & Map_Unsynchronized)
+ mapFlags = D3D1x_(MAP_WRITE_NO_OVERWRITE);
+
+ void* map = 0;
+ if (SUCCEEDED(D3DBuffer->Map(mapFlags, 0, &map)))
+ return ((char*)map) + start;
+ return NULL;
+}
+
+bool Buffer::Unmap(void *m)
+{
+ OVR_UNUSED(m);
+
+ D3DBuffer->Unmap();
+ return true;
+}
+
+
+//-------------------------------------------------------------------------------------
+// Shaders
+
+template<> bool Shader<RenderTiny::Shader_Vertex, ID3D10VertexShader>::Load(void* shader, size_t size)
+{
+ return SUCCEEDED(Ren->Device->CreateVertexShader(shader, size, &D3DShader));
+}
+template<> bool Shader<RenderTiny::Shader_Pixel, ID3D10PixelShader>::Load(void* shader, size_t size)
+{
+ return SUCCEEDED(Ren->Device->CreatePixelShader(shader, size, &D3DShader));
+}
+
+template<> void Shader<RenderTiny::Shader_Vertex, ID3D10VertexShader>::Set(PrimitiveType) const
+{
+ Ren->Context->VSSetShader(D3DShader);
+}
+template<> void Shader<RenderTiny::Shader_Pixel, ID3D10PixelShader>::Set(PrimitiveType) const
+{
+ Ren->Context->PSSetShader(D3DShader);
+}
+
+template<> void Shader<RenderTiny::Shader_Vertex, ID3D1xVertexShader>::SetUniformBuffer(RenderTiny::Buffer* buffer, int i)
+{
+ Ren->Context->VSSetConstantBuffers(i, 1, &((Buffer*)buffer)->D3DBuffer.GetRawRef());
+}
+template<> void Shader<RenderTiny::Shader_Pixel, ID3D1xPixelShader>::SetUniformBuffer(RenderTiny::Buffer* buffer, int i)
+{
+ Ren->Context->PSSetConstantBuffers(i, 1, &((Buffer*)buffer)->D3DBuffer.GetRawRef());
+}
+
+
+//-------------------------------------------------------------------------------------
+// ***** Shader Base
+
+ShaderBase::ShaderBase(RenderDevice* r, ShaderStage stage)
+ : RenderTiny::Shader(stage), Ren(r), UniformData(0)
+{
+}
+ShaderBase::~ShaderBase()
+{
+ if (UniformData)
+ OVR_FREE(UniformData);
+}
+
+bool ShaderBase::SetUniform(const char* name, int n, const float* v)
+{
+ for(unsigned i = 0; i < UniformInfo.GetSize(); i++)
+ {
+ if (!strcmp(UniformInfo[i].Name.ToCStr(), name))
+ {
+ memcpy(UniformData + UniformInfo[i].Offset, v, n * sizeof(float));
+ return 1;
+ }
+ }
+ return 0;
+}
+
+void ShaderBase::InitUniforms(ID3D10Blob* s)
+{
+ ID3D10ShaderReflection* ref = NULL;
+ D3D10ReflectShader(s->GetBufferPointer(), s->GetBufferSize(), &ref);
+ ID3D10ShaderReflectionConstantBuffer* buf = ref->GetConstantBufferByIndex(0);
+ D3D10_SHADER_BUFFER_DESC bufd;
+ if (FAILED(buf->GetDesc(&bufd)))
+ {
+ UniformsSize = 0;
+ if (UniformData)
+ {
+ OVR_FREE(UniformData);
+ UniformData = 0;
+ }
+ return;
+ }
+
+ for(unsigned i = 0; i < bufd.Variables; i++)
+ {
+ ID3D10ShaderReflectionVariable* var = buf->GetVariableByIndex(i);
+ if (var)
+ {
+ D3D10_SHADER_VARIABLE_DESC vd;
+ if (SUCCEEDED(var->GetDesc(&vd)))
+ {
+ Uniform u;
+ u.Name = vd.Name;
+ u.Offset = vd.StartOffset;
+ u.Size = vd.Size;
+ UniformInfo.PushBack(u);
+ }
+ }
+ }
+
+ UniformsSize = bufd.Size;
+ UniformData = (unsigned char*)OVR_ALLOC(bufd.Size);
+}
+
+void ShaderBase::UpdateBuffer(Buffer* buf)
+{
+ if (UniformsSize)
+ {
+ buf->Data(Buffer_Uniform, UniformData, UniformsSize);
+ }
+}
+
+
+//-------------------------------------------------------------------------------------
+// ***** Texture
+//
+Texture::Texture(RenderDevice* ren, int fmt, int w, int h)
+ : Ren(ren), Tex(NULL), TexSv(NULL), TexRtv(NULL), TexDsv(NULL), Width(w), Height(h)
+{
+ OVR_UNUSED(fmt);
+ Sampler = Ren->GetSamplerState(0);
+}
+
+Texture::~Texture()
+{
+}
+
+void Texture::Set(int slot, RenderTiny::ShaderStage stage) const
+{
+ Ren->SetTexture(stage, slot, this);
+}
+
+void Texture::SetSampleMode(int sm)
+{
+ Sampler = Ren->GetSamplerState(sm);
+}
+
+
+
+//-------------------------------------------------------------------------------------
+// ***** Render Device
+
+RenderDevice::RenderDevice(const RendererParams& p, HWND window)
+{
+ RECT rc;
+ GetClientRect(window, &rc);
+ UINT width = rc.right - rc.left;
+ UINT height = rc.bottom - rc.top;
+ WindowWidth = width;
+ WindowHeight = height;
+ Window = window;
+ Params = p;
+
+ HRESULT hr = CreateDXGIFactory(__uuidof(IDXGIFactory), (void**)(&DXGIFactory.GetRawRef()));
+ if (FAILED(hr))
+ return;
+
+ // Find the adapter & output (monitor) to use for fullscreen, based on the reported name of the HMD's monitor.
+ if (Params.MonitorName.GetLength() > 0)
+ {
+ for(UINT AdapterIndex = 0; ; AdapterIndex++)
+ {
+ HRESULT hr = DXGIFactory->EnumAdapters(AdapterIndex, &Adapter.GetRawRef());
+ if (hr == DXGI_ERROR_NOT_FOUND)
+ break;
+
+ DXGI_ADAPTER_DESC Desc;
+ Adapter->GetDesc(&Desc);
+
+ UpdateMonitorOutputs();
+
+ if (FullscreenOutput)
+ break;
+ }
+
+ if (!FullscreenOutput)
+ Adapter = NULL;
+ }
+
+ if (!Adapter)
+ {
+ DXGIFactory->EnumAdapters(0, &Adapter.GetRawRef());
+ }
+
+ int flags = 0;
+
+ hr = D3D10CreateDevice(Adapter, D3D10_DRIVER_TYPE_HARDWARE, NULL, flags, D3D1x_(SDK_VERSION),
+ &Device.GetRawRef());
+ Context = Device;
+ Context->AddRef();
+
+ if (FAILED(hr))
+ return;
+
+ if (!RecreateSwapChain())
+ return;
+
+ if (Params.Fullscreen)
+ SwapChain->SetFullscreenState(1, FullscreenOutput);
+
+ CurRenderTarget = NULL;
+ for(int i = 0; i < Shader_Count; i++)
+ {
+ UniformBuffers[i] = *CreateBuffer();
+ MaxTextureSet[i] = 0;
+ }
+
+ ID3D10Blob* vsData = CompileShader("vs_4_0", DirectVertexShaderSrc);
+ VertexShaders[VShader_MV] = *new VertexShader(this, vsData);
+ for(int i = 1; i < VShader_Count; i++)
+ {
+ VertexShaders[i] = *new VertexShader(this, CompileShader("vs_4_0", VShaderSrcs[i]));
+ }
+
+ for(int i = 0; i < FShader_Count; i++)
+ {
+ PixelShaders[i] = *new PixelShader(this, CompileShader("ps_4_0", FShaderSrcs[i]));
+ }
+
+ SPInt bufferSize = vsData->GetBufferSize();
+ const void* buffer = vsData->GetBufferPointer();
+ ID3D1xInputLayout** objRef = &ModelVertexIL.GetRawRef();
+
+ HRESULT validate = Device->CreateInputLayout(ModelVertexDesc, sizeof(ModelVertexDesc)/sizeof(D3D1x_(INPUT_ELEMENT_DESC)),
+ buffer, bufferSize, objRef);
+ OVR_UNUSED(validate);
+
+ Ptr<ShaderSet> gouraudShaders = *new ShaderSet();
+ gouraudShaders->SetShader(VertexShaders[VShader_MVP]);
+ gouraudShaders->SetShader(PixelShaders[FShader_Gouraud]);
+ DefaultFill = *new ShaderFill(gouraudShaders);
+
+ D3D1x_(BLEND_DESC) bm;
+ memset(&bm, 0, sizeof(bm));
+ bm.BlendEnable[0] = true;
+ bm.BlendOp = bm.BlendOpAlpha = D3D1x_(BLEND_OP_ADD);
+ bm.SrcBlend = bm.SrcBlendAlpha = D3D1x_(BLEND_SRC_ALPHA);
+ bm.DestBlend = bm.DestBlendAlpha = D3D1x_(BLEND_INV_SRC_ALPHA);
+ bm.RenderTargetWriteMask[0] = D3D1x_(COLOR_WRITE_ENABLE_ALL);
+ Device->CreateBlendState(&bm, &BlendState.GetRawRef());
+
+ D3D1x_(RASTERIZER_DESC) rs;
+ memset(&rs, 0, sizeof(rs));
+ rs.AntialiasedLineEnable = true;
+ rs.CullMode = D3D1x_(CULL_BACK);
+ rs.DepthClipEnable = true;
+ rs.FillMode = D3D1x_(FILL_SOLID);
+ Device->CreateRasterizerState(&rs, &Rasterizer.GetRawRef());
+
+ QuadVertexBuffer = *CreateBuffer();
+ const RenderTiny::Vertex QuadVertices[] =
+ { Vertex(Vector3f(0, 1, 0)), Vertex(Vector3f(1, 1, 0)),
+ Vertex(Vector3f(0, 0, 0)), Vertex(Vector3f(1, 0, 0)) };
+ QuadVertexBuffer->Data(Buffer_Vertex, QuadVertices, sizeof(QuadVertices));
+
+ SetDepthMode(0, 0);
+}
+
+RenderDevice::~RenderDevice()
+{
+ if (SwapChain && Params.Fullscreen)
+ {
+ SwapChain->SetFullscreenState(false, NULL);
+ }
+}
+
+
+// Implement static initializer function to create this class.
+RenderTiny::RenderDevice* RenderDevice::CreateDevice(const RendererParams& rp, void* oswnd)
+{
+ return new RenderDevice(rp, (HWND)oswnd);
+}
+
+
+// Fallback monitor enumeration in case newly plugged in monitor wasn't detected.
+// Added originally for the FactoryTest app.
+// New Outputs don't seem to be detected unless adapter is re-created, but that would also
+// require us to re-initialize D3D10 (recreating objects, etc). This bypasses that for "fake"
+// fullscreen modes.
+BOOL CALLBACK MonitorEnumFunc(HMONITOR hMonitor, HDC, LPRECT, LPARAM dwData)
+{
+ RenderDevice* renderer = (RenderDevice*)dwData;
+
+ MONITORINFOEX monitor;
+ monitor.cbSize = sizeof(monitor);
+
+ if (::GetMonitorInfo(hMonitor, &monitor) && monitor.szDevice[0])
+ {
+ DISPLAY_DEVICE dispDev;
+ memset(&dispDev, 0, sizeof(dispDev));
+ dispDev.cb = sizeof(dispDev);
+
+ if (::EnumDisplayDevices(monitor.szDevice, 0, &dispDev, 0))
+ {
+ if (strstr(String(dispDev.DeviceName).ToCStr(), renderer->GetParams().MonitorName.ToCStr()))
+ {
+ renderer->FSDesktopX = monitor.rcMonitor.left;
+ renderer->FSDesktopY = monitor.rcMonitor.top;
+ return FALSE;
+ }
+ }
+ }
+
+ return TRUE;
+}
+
+
+void RenderDevice::UpdateMonitorOutputs()
+{
+ HRESULT hr;
+
+ bool deviceNameFound = false;
+
+ for(UINT OutputIndex = 0; ; OutputIndex++)
+ {
+ Ptr<IDXGIOutput> Output;
+ hr = Adapter->EnumOutputs(OutputIndex, &Output.GetRawRef());
+ if (hr == DXGI_ERROR_NOT_FOUND)
+ {
+ break;
+ }
+
+ DXGI_OUTPUT_DESC OutDesc;
+ Output->GetDesc(&OutDesc);
+
+ MONITORINFOEX monitor;
+ monitor.cbSize = sizeof(monitor);
+ if (::GetMonitorInfo(OutDesc.Monitor, &monitor) && monitor.szDevice[0])
+ {
+ DISPLAY_DEVICE dispDev;
+ memset(&dispDev, 0, sizeof(dispDev));
+ dispDev.cb = sizeof(dispDev);
+
+ if (::EnumDisplayDevices(monitor.szDevice, 0, &dispDev, 0))
+ {
+ if (strstr(String(dispDev.DeviceName).ToCStr(), Params.MonitorName.ToCStr()))
+ {
+ deviceNameFound = true;
+ FullscreenOutput = Output;
+ FSDesktopX = monitor.rcMonitor.left;
+ FSDesktopY = monitor.rcMonitor.top;
+ break;
+ }
+ }
+ }
+ }
+
+ if (!deviceNameFound && !Params.MonitorName.IsEmpty())
+ {
+ EnumDisplayMonitors(0, 0, MonitorEnumFunc, (LPARAM)this);
+ }
+}
+
+bool RenderDevice::RecreateSwapChain()
+{
+ DXGI_SWAP_CHAIN_DESC scDesc;
+ memset(&scDesc, 0, sizeof(scDesc));
+ scDesc.BufferCount = 1;
+ scDesc.BufferDesc.Width = WindowWidth;
+ scDesc.BufferDesc.Height = WindowHeight;
+ scDesc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
+ scDesc.BufferDesc.RefreshRate.Numerator = 60;
+ scDesc.BufferDesc.RefreshRate.Denominator = 1;
+ scDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
+ scDesc.OutputWindow = Window;
+ scDesc.SampleDesc.Count = Params.Multisample;
+ scDesc.SampleDesc.Quality = 0;
+ scDesc.Windowed = (Params.Fullscreen != Display_Fullscreen);
+ scDesc.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH;
+
+ if (SwapChain)
+ {
+ SwapChain->SetFullscreenState(FALSE, NULL);
+ SwapChain->Release();
+ SwapChain = NULL;
+ }
+
+ Ptr<IDXGISwapChain> newSC;
+ if (FAILED(DXGIFactory->CreateSwapChain(Device, &scDesc, &newSC.GetRawRef())))
+ return false;
+ SwapChain = newSC;
+
+ BackBuffer = NULL;
+ BackBufferRT = NULL;
+ HRESULT hr = SwapChain->GetBuffer(0, __uuidof(ID3D1xTexture2D), (void**)&BackBuffer.GetRawRef());
+ if (FAILED(hr))
+ return false;
+
+ hr = Device->CreateRenderTargetView(BackBuffer, NULL, &BackBufferRT.GetRawRef());
+ if (FAILED(hr))
+ return false;
+
+ Texture* depthBuffer = GetDepthBuffer(WindowWidth, WindowHeight, Params.Multisample);
+ CurDepthBuffer = depthBuffer;
+ if (CurRenderTarget == NULL)
+ {
+ Context->OMSetRenderTargets(1, &BackBufferRT.GetRawRef(), depthBuffer->TexDsv);
+ }
+ return true;
+}
+
+bool RenderDevice::SetParams(const RendererParams& newParams)
+{
+ String oldMonitor = Params.MonitorName;
+
+ Params = newParams;
+ if (newParams.MonitorName != oldMonitor)
+ {
+ UpdateMonitorOutputs();
+ }
+
+ // Cause this to be recreated with the new multisample mode.
+ pSceneColorTex = NULL;
+ return RecreateSwapChain();
+}
+
+
+bool RenderDevice::SetFullscreen(DisplayMode fullscreen)
+{
+ if (fullscreen == Params.Fullscreen)
+ return true;
+
+ HRESULT hr = SwapChain->SetFullscreenState(fullscreen, fullscreen ? FullscreenOutput : NULL);
+ if (FAILED(hr))
+ {
+ return false;
+ }
+
+ Params.Fullscreen = fullscreen;
+ return true;
+}
+
+void RenderDevice::SetRealViewport(const Viewport& vp)
+{
+ D3DViewport.Width = vp.w;
+ D3DViewport.Height = vp.h;
+ D3DViewport.MinDepth = 0;
+ D3DViewport.MaxDepth = 1;
+ D3DViewport.TopLeftX = vp.x;
+ D3DViewport.TopLeftY = vp.y;
+ Context->RSSetViewports(1, &D3DViewport);
+}
+
+static int GetDepthStateIndex(bool enable, bool write, RenderDevice::CompareFunc func)
+{
+ if (!enable)
+ return 0;
+ return 1 + int(func) * 2 + write;
+}
+
+void RenderDevice::SetDepthMode(bool enable, bool write, CompareFunc func)
+{
+ int index = GetDepthStateIndex(enable, write, func);
+ if (DepthStates[index])
+ {
+ CurDepthState = DepthStates[index];
+ Context->OMSetDepthStencilState(DepthStates[index], 0);
+ return;
+ }
+
+ D3D1x_(DEPTH_STENCIL_DESC) dss;
+ memset(&dss, 0, sizeof(dss));
+ dss.DepthEnable = enable;
+ switch(func)
+ {
+ case Compare_Always: dss.DepthFunc = D3D1x_(COMPARISON_ALWAYS); break;
+ case Compare_Less: dss.DepthFunc = D3D1x_(COMPARISON_LESS); break;
+ case Compare_Greater: dss.DepthFunc = D3D1x_(COMPARISON_GREATER); break;
+ default:
+ assert(0);
+ }
+ dss.DepthWriteMask = write ? D3D1x_(DEPTH_WRITE_MASK_ALL) : D3D1x_(DEPTH_WRITE_MASK_ZERO);
+ Device->CreateDepthStencilState(&dss, &DepthStates[index].GetRawRef());
+ Context->OMSetDepthStencilState(DepthStates[index], 0);
+ CurDepthState = DepthStates[index];
+}
+
+Texture* RenderDevice::GetDepthBuffer(int w, int h, int ms)
+{
+ for(unsigned i = 0; i < DepthBuffers.GetSize(); i++)
+ {
+ if (w == DepthBuffers[i]->Width && h == DepthBuffers[i]->Height &&
+ ms == DepthBuffers[i]->Samples)
+ return DepthBuffers[i];
+ }
+
+ Ptr<Texture> newDepth = *CreateTexture(Texture_Depth | Texture_RenderTarget | ms, w, h, NULL);
+ if (newDepth == NULL)
+ {
+ OVR_DEBUG_LOG(("Failed to get depth buffer."));
+ return NULL;
+ }
+
+ DepthBuffers.PushBack(newDepth);
+ return newDepth.GetPtr();
+}
+
+void RenderDevice::Clear(float r, float g, float b, float a, float depth)
+{
+ const float color[] = {r, g, b, a};
+
+ // Needed for each eye to do its own clear, since ClearRenderTargetView doesn't honor viewport.
+
+ // Save state that is affected by clearing this way
+ ID3D1xDepthStencilState* oldDepthState = CurDepthState;
+ StandardUniformData clearUniforms;
+
+ SetDepthMode(true, true, Compare_Always);
+
+ Context->IASetInputLayout(ModelVertexIL);
+ Context->GSSetShader(NULL);
+
+ ID3D1xShaderResourceView* sv[8] = {0, 0, 0, 0, 0, 0, 0, 0};
+ if (MaxTextureSet[Shader_Fragment])
+ {
+ Context->PSSetShaderResources(0, MaxTextureSet[Shader_Fragment], sv);
+ }
+
+ ID3D1xBuffer* vertexBuffer = QuadVertexBuffer->GetBuffer();
+ UINT vertexStride = sizeof(Vertex);
+ UINT vertexOffset = 0;
+ Context->IASetVertexBuffers(0, 1, &vertexBuffer, &vertexStride, &vertexOffset);
+
+ clearUniforms.View = Matrix4f(2, 0, 0, 0,
+ 0, 2, 0, 0,
+ 0, 0, 0, 0,
+ -1, -1, depth, 1);
+ UniformBuffers[Shader_Vertex]->Data(Buffer_Uniform, &clearUniforms, sizeof(clearUniforms));
+
+ ID3D1xBuffer* vertexConstants = UniformBuffers[Shader_Vertex]->GetBuffer();
+ Context->VSSetConstantBuffers(0, 1, &vertexConstants);
+ Context->IASetPrimitiveTopology(D3D1x_(PRIMITIVE_TOPOLOGY_TRIANGLESTRIP));
+ VertexShaders[VShader_MV]->Set(Prim_TriangleStrip);
+ PixelShaders[FShader_Solid]->Set(Prim_TriangleStrip);
+
+ UniformBuffers[Shader_Pixel]->Data(Buffer_Uniform, color, sizeof(color));
+ PixelShaders[FShader_Solid]->SetUniformBuffer(UniformBuffers[Shader_Pixel]);
+
+ // Clear Viewport
+ Context->OMSetBlendState(NULL, NULL, 0xffffffff);
+ Context->Draw(4, 0);
+
+ // reset
+ CurDepthState = oldDepthState;
+ Context->OMSetDepthStencilState(CurDepthState, 0);
+}
+
+// Buffers
+
+Buffer* RenderDevice::CreateBuffer()
+{
+ return new Buffer(this);
+}
+
+
+ID3D10Blob* RenderDevice::CompileShader(const char* profile, const char* src, const char* mainName)
+{
+ ID3D10Blob* shader;
+ ID3D10Blob* errors;
+ HRESULT hr = D3DCompile(src, strlen(src), NULL, NULL, NULL, mainName, profile,
+ 0, 0, &shader, &errors);
+ if (FAILED(hr))
+ {
+ OVR_DEBUG_LOG(("Compiling D3D shader for %s failed\n%s\n\n%s",
+ profile, src, errors->GetBufferPointer()));
+ OutputDebugStringA((char*)errors->GetBufferPointer());
+ return NULL;
+ }
+ if (errors)
+ {
+ errors->Release();
+ }
+ return shader;
+}
+
+void RenderDevice::SetCommonUniformBuffer(int i, RenderTiny::Buffer* buffer)
+{
+ CommonUniforms[i] = (Buffer*)buffer;
+
+ Context->PSSetConstantBuffers(1, 1, &CommonUniforms[1]->D3DBuffer.GetRawRef());
+ Context->VSSetConstantBuffers(1, 1, &CommonUniforms[1]->D3DBuffer.GetRawRef());
+}
+
+RenderTiny::Shader *RenderDevice::LoadBuiltinShader(ShaderStage stage, int shader)
+{
+ switch(stage)
+ {
+ case Shader_Vertex:
+ return VertexShaders[shader];
+ case Shader_Pixel:
+ return PixelShaders[shader];
+ default:
+ return NULL;
+ }
+}
+
+
+ID3D1xSamplerState* RenderDevice::GetSamplerState(int sm)
+{
+ if (SamplerStates[sm])
+ return SamplerStates[sm];
+
+ D3D1x_(SAMPLER_DESC) ss;
+ memset(&ss, 0, sizeof(ss));
+ if (sm & Sample_Clamp)
+ ss.AddressU = ss.AddressV = ss.AddressW = D3D1x_(TEXTURE_ADDRESS_CLAMP);
+ else if (sm & Sample_ClampBorder)
+ ss.AddressU = ss.AddressV = ss.AddressW = D3D1x_(TEXTURE_ADDRESS_BORDER);
+ else
+ ss.AddressU = ss.AddressV = ss.AddressW = D3D1x_(TEXTURE_ADDRESS_WRAP);
+
+ if (sm & Sample_Nearest)
+ {
+ ss.Filter = D3D1x_(FILTER_MIN_MAG_MIP_POINT);
+ }
+ else if (sm & Sample_Anisotropic)
+ {
+ ss.Filter = D3D1x_(FILTER_ANISOTROPIC);
+ ss.MaxAnisotropy = 8;
+ }
+ else
+ {
+ ss.Filter = D3D1x_(FILTER_MIN_MAG_MIP_LINEAR);
+ }
+ ss.MaxLOD = 15;
+ Device->CreateSamplerState(&ss, &SamplerStates[sm].GetRawRef());
+ return SamplerStates[sm];
+}
+
+
+void RenderDevice::SetTexture(RenderTiny::ShaderStage stage, int slot, const Texture* t)
+{
+ if (MaxTextureSet[stage] <= slot)
+ MaxTextureSet[stage] = slot + 1;
+
+ ID3D1xShaderResourceView* sv = t ? t->TexSv : NULL;
+ switch(stage)
+ {
+ case Shader_Fragment:
+ Context->PSSetShaderResources(slot, 1, &sv);
+ if (t)
+ {
+ Context->PSSetSamplers(slot, 1, &t->Sampler.GetRawRef());
+ }
+ break;
+
+ case Shader_Vertex:
+ Context->VSSetShaderResources(slot, 1, &sv);
+ break;
+ }
+}
+
+Texture* RenderDevice::CreateTexture(int format, int width, int height, const void* data, int mipcount)
+{
+ OVR_UNUSED(mipcount);
+
+ DXGI_FORMAT d3dformat;
+ int bpp;
+ switch(format & Texture_TypeMask)
+ {
+ case Texture_RGBA:
+ bpp = 4;
+ d3dformat = DXGI_FORMAT_R8G8B8A8_UNORM;
+ break;
+ case Texture_Depth:
+ bpp = 0;
+ d3dformat = DXGI_FORMAT_D32_FLOAT;
+ break;
+ default:
+ return NULL;
+ }
+
+ int samples = (format & Texture_SamplesMask);
+ if (samples < 1)
+ {
+ samples = 1;
+ }
+
+ Texture* NewTex = new Texture(this, format, width, height);
+ NewTex->Samples = samples;
+
+ D3D1x_(TEXTURE2D_DESC) dsDesc;
+ dsDesc.Width = width;
+ dsDesc.Height = height;
+ dsDesc.MipLevels = (format == (Texture_RGBA | Texture_GenMipmaps) && data) ? GetNumMipLevels(width, height) : 1;
+ dsDesc.ArraySize = 1;
+ dsDesc.Format = d3dformat;
+ dsDesc.SampleDesc.Count = samples;
+ dsDesc.SampleDesc.Quality = 0;
+ dsDesc.Usage = D3D1x_(USAGE_DEFAULT);
+ dsDesc.BindFlags = D3D1x_(BIND_SHADER_RESOURCE);
+ dsDesc.CPUAccessFlags = 0;
+ dsDesc.MiscFlags = 0;
+
+ if (format & Texture_RenderTarget)
+ {
+ if ((format & Texture_TypeMask) == Texture_Depth)
+ { // We don't use depth textures, and creating them in d3d10 requires different options.
+ dsDesc.BindFlags = D3D1x_(BIND_DEPTH_STENCIL);
+ }
+ else
+ {
+ dsDesc.BindFlags |= D3D1x_(BIND_RENDER_TARGET);
+ }
+ }
+
+ HRESULT hr = Device->CreateTexture2D(&dsDesc, NULL, &NewTex->Tex.GetRawRef());
+ if (FAILED(hr))
+ {
+ OVR_DEBUG_LOG_TEXT(("Failed to create 2D D3D texture."));
+ NewTex->Release();
+ return NULL;
+ }
+ if (dsDesc.BindFlags & D3D1x_(BIND_SHADER_RESOURCE))
+ {
+ Device->CreateShaderResourceView(NewTex->Tex, NULL, &NewTex->TexSv.GetRawRef());
+ }
+
+ if (data)
+ {
+ Context->UpdateSubresource(NewTex->Tex, 0, NULL, data, width * bpp, width * height * bpp);
+ if (format == (Texture_RGBA | Texture_GenMipmaps))
+ {
+ int srcw = width, srch = height;
+ int level = 0;
+ UByte* mipmaps = NULL;
+ do
+ {
+ level++;
+ int mipw = srcw >> 1;
+ if (mipw < 1)
+ {
+ mipw = 1;
+ }
+ int miph = srch >> 1;
+ if (miph < 1)
+ {
+ miph = 1;
+ }
+ if (mipmaps == NULL)
+ {
+ mipmaps = (UByte*)OVR_ALLOC(mipw * miph * 4);
+ }
+ FilterRgba2x2(level == 1 ? (const UByte*)data : mipmaps, srcw, srch, mipmaps);
+ Context->UpdateSubresource(NewTex->Tex, level, NULL, mipmaps, mipw * bpp, miph * bpp);
+ srcw = mipw;
+ srch = miph;
+ }
+ while(srcw > 1 || srch > 1);
+
+ if (mipmaps != NULL)
+ {
+ OVR_FREE(mipmaps);
+ }
+ }
+ }
+
+ if (format & Texture_RenderTarget)
+ {
+ if ((format & Texture_TypeMask) == Texture_Depth)
+ {
+ Device->CreateDepthStencilView(NewTex->Tex, NULL, &NewTex->TexDsv.GetRawRef());
+ }
+ else
+ {
+ Device->CreateRenderTargetView(NewTex->Tex, NULL, &NewTex->TexRtv.GetRawRef());
+ }
+ }
+
+ return NewTex;
+}
+
+
+// Rendering
+
+void RenderDevice::BeginRendering()
+{
+ Context->RSSetState(Rasterizer);
+}
+
+void RenderDevice::SetRenderTarget(RenderTiny::Texture* colorTex,
+ RenderTiny::Texture* depth, RenderTiny::Texture* stencil)
+{
+ OVR_UNUSED(stencil);
+
+ CurRenderTarget = (Texture*)colorTex;
+ if (colorTex == NULL)
+ {
+ Texture* newDepthBuffer = GetDepthBuffer(WindowWidth, WindowHeight, Params.Multisample);
+ if (newDepthBuffer == NULL)
+ {
+ OVR_DEBUG_LOG(("New depth buffer creation failed."));
+ }
+ if (newDepthBuffer != NULL)
+ {
+ CurDepthBuffer = GetDepthBuffer(WindowWidth, WindowHeight, Params.Multisample);
+ Context->OMSetRenderTargets(1, &BackBufferRT.GetRawRef(), CurDepthBuffer->TexDsv);
+ }
+ return;
+ }
+ if (depth == NULL)
+ {
+ depth = GetDepthBuffer(colorTex->GetWidth(), colorTex->GetHeight(), CurRenderTarget->Samples);
+ }
+
+ ID3D1xShaderResourceView* sv[8] = {0, 0, 0, 0, 0, 0, 0, 0};
+ if (MaxTextureSet[Shader_Fragment])
+ {
+ Context->PSSetShaderResources(0, MaxTextureSet[Shader_Fragment], sv);
+ }
+ memset(MaxTextureSet, 0, sizeof(MaxTextureSet));
+
+ CurDepthBuffer = (Texture*)depth;
+ Context->OMSetRenderTargets(1, &((Texture*)colorTex)->TexRtv.GetRawRef(), ((Texture*)depth)->TexDsv);
+}
+
+
+void RenderDevice::SetWorldUniforms(const Matrix4f& proj)
+{
+ StdUniforms.Proj = proj.Transposed();
+ // Shader constant buffers cannot be partially updated.
+}
+
+
+void RenderDevice::Render(const Matrix4f& matrix, Model* model)
+{
+ // Store data in buffers if not already
+ if (!model->VertexBuffer)
+ {
+ Ptr<Buffer> vb = *CreateBuffer();
+ vb->Data(Buffer_Vertex, &model->Vertices[0], model->Vertices.GetSize() * sizeof(Vertex));
+ model->VertexBuffer = vb;
+ }
+ if (!model->IndexBuffer)
+ {
+ Ptr<Buffer> ib = *CreateBuffer();
+ ib->Data(Buffer_Index, &model->Indices[0], model->Indices.GetSize() * 2);
+ model->IndexBuffer = ib;
+ }
+
+ Render(model->Fill ? model->Fill : DefaultFill,
+ model->VertexBuffer, model->IndexBuffer,
+ matrix, 0, (unsigned)model->Indices.GetSize(), model->GetPrimType());
+}
+
+void RenderDevice::Render(const ShaderFill* fill, RenderTiny::Buffer* vertices, RenderTiny::Buffer* indices,
+ const Matrix4f& matrix, int offset, int count, PrimitiveType rprim)
+{
+ Context->IASetInputLayout(ModelVertexIL);
+ if (indices)
+ {
+ Context->IASetIndexBuffer(((Buffer*)indices)->GetBuffer(), DXGI_FORMAT_R16_UINT, 0);
+ }
+
+ ID3D1xBuffer* vertexBuffer = ((Buffer*)vertices)->GetBuffer();
+ UINT vertexStride = sizeof(Vertex);
+ UINT vertexOffset = offset;
+ Context->IASetVertexBuffers(0, 1, &vertexBuffer, &vertexStride, &vertexOffset);
+
+ ShaderSet* shaders = ((ShaderFill*)fill)->GetShaders();
+
+ ShaderBase* vshader = ((ShaderBase*)shaders->GetShader(Shader_Vertex));
+ unsigned char* vertexData = vshader->UniformData;
+ if (vertexData)
+ {
+ StandardUniformData* stdUniforms = (StandardUniformData*) vertexData;
+ stdUniforms->View = matrix.Transposed();
+ stdUniforms->Proj = StdUniforms.Proj;
+ UniformBuffers[Shader_Vertex]->Data(Buffer_Uniform, vertexData, vshader->UniformsSize);
+ vshader->SetUniformBuffer(UniformBuffers[Shader_Vertex]);
+ }
+
+ for(int i = Shader_Vertex + 1; i < Shader_Count; i++)
+ if (shaders->GetShader(i))
+ {
+ ((ShaderBase*)shaders->GetShader(i))->UpdateBuffer(UniformBuffers[i]);
+ ((ShaderBase*)shaders->GetShader(i))->SetUniformBuffer(UniformBuffers[i]);
+ }
+
+ D3D1x_(PRIMITIVE_TOPOLOGY) prim;
+ switch(rprim)
+ {
+ case Prim_Triangles:
+ prim = D3D1x_(PRIMITIVE_TOPOLOGY_TRIANGLELIST);
+ break;
+ case Prim_Lines:
+ prim = D3D1x_(PRIMITIVE_TOPOLOGY_LINELIST);
+ break;
+ case Prim_TriangleStrip:
+ prim = D3D1x_(PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);
+ break;
+ default:
+ assert(0);
+ return;
+ }
+ Context->IASetPrimitiveTopology(prim);
+
+ fill->Set(rprim);
+
+ if (indices)
+ {
+ Context->DrawIndexed(count, 0, 0);
+ }
+ else
+ {
+ Context->Draw(count, 0);
+ }
+}
+
+
+void RenderDevice::Present()
+{
+ SwapChain->Present(0, 0);
+}
+
+void RenderDevice::ForceFlushGPU()
+{
+ D3D1x_QUERY_DESC queryDesc = { D3D1x_(QUERY_EVENT), 0 };
+ Ptr<ID3D1xQuery> query;
+ BOOL done = FALSE;
+
+ if (Device->CreateQuery(&queryDesc, &query.GetRawRef()) == S_OK)
+ {
+ // Begin() not used for EVENT query.
+ query->End();
+ // GetData will returns S_OK for both done == TRUE or FALSE.
+ // Exit on failure to avoid infinite loop.
+ do { }
+ while(!done && !FAILED(query->GetData(&done, sizeof(BOOL), 0)));
+ }
+}
+
+}}}
+
diff --git a/Samples/OculusRoomTiny/RenderTiny_D3D1X_Device.h b/Samples/OculusRoomTiny/RenderTiny_D3D1X_Device.h
index e608498..1438611 100644
--- a/Samples/OculusRoomTiny/RenderTiny_D3D1X_Device.h
+++ b/Samples/OculusRoomTiny/RenderTiny_D3D1X_Device.h
@@ -1,273 +1,273 @@
-/************************************************************************************
-
-Filename : RenderTiny_D3D1X_Device.h
-Content : RenderDevice implementation header for D3DX10.
-Created : September 10, 2012
-Authors : Andrew Reisse
-
-Copyright : Copyright 2012 Oculus VR, Inc. All Rights reserved.
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-
-************************************************************************************/
-
-#ifndef INC_RenderTiny_D3D1X_Device_h
-#define INC_RenderTiny_D3D1X_Device_h
-
-#include "Kernel/OVR_String.h"
-#include "Kernel/OVR_Array.h"
-
-#include "RenderTiny_Device.h"
-#include <Windows.h>
-
-#define _OVR_RENDERER_D3D10
-#include <d3d10.h>
-
-namespace OVR { namespace RenderTiny { namespace D3D10 {
-
-class RenderDevice;
-class Buffer;
-
-typedef ID3D10Device ID3D1xDevice;
-typedef ID3D10Device ID3D1xDeviceContext;
-typedef ID3D10RenderTargetView ID3D1xRenderTargetView;
-typedef ID3D10Texture2D ID3D1xTexture2D;
-typedef ID3D10ShaderResourceView ID3D1xShaderResourceView;
-typedef ID3D10DepthStencilView ID3D1xDepthStencilView;
-typedef ID3D10DepthStencilState ID3D1xDepthStencilState;
-typedef ID3D10InputLayout ID3D1xInputLayout;
-typedef ID3D10Buffer ID3D1xBuffer;
-typedef ID3D10VertexShader ID3D1xVertexShader;
-typedef ID3D10PixelShader ID3D1xPixelShader;
-typedef ID3D10GeometryShader ID3D1xGeometryShader;
-typedef ID3D10BlendState ID3D1xBlendState;
-typedef ID3D10RasterizerState ID3D1xRasterizerState;
-typedef ID3D10SamplerState ID3D1xSamplerState;
-typedef ID3D10Query ID3D1xQuery;
-typedef ID3D10Blob ID3D1xBlob;
-typedef D3D10_VIEWPORT D3D1x_VIEWPORT;
-typedef D3D10_QUERY_DESC D3D1x_QUERY_DESC;
-#define D3D1x_(x) D3D10_##x
-#define ID3D1x(x) ID3D10##x
-
-
-
-class ShaderBase : public RenderTiny::Shader
-{
-public:
- RenderDevice* Ren;
- unsigned char* UniformData;
- int UniformsSize;
-
- struct Uniform
- {
- String Name;
- int Offset, Size;
- };
- Array<Uniform> UniformInfo;
-
- ShaderBase(RenderDevice* r, ShaderStage stage);
- ~ShaderBase();
-
- void InitUniforms(ID3D10Blob* s);
- bool SetUniform(const char* name, int n, const float* v);
-
- void UpdateBuffer(Buffer* b);
-};
-
-template<RenderTiny::ShaderStage SStage, class D3DShaderType>
-class Shader : public ShaderBase
-{
-public:
- D3DShaderType* D3DShader;
-
- Shader(RenderDevice* r, D3DShaderType* s) : ShaderBase(r, SStage), D3DShader(s) {}
- Shader(RenderDevice* r, ID3D1xBlob* s) : ShaderBase(r, SStage)
- {
- Load(s);
- InitUniforms(s);
- }
- ~Shader()
- {
- if (D3DShader)
- D3DShader->Release();
- }
- bool Load(ID3D1xBlob* shader)
- {
- return Load(shader->GetBufferPointer(), shader->GetBufferSize());
- }
-
- // These functions have specializations.
- bool Load(void* shader, size_t size);
- void Set(PrimitiveType prim) const;
- void SetUniformBuffer(RenderTiny::Buffer* buffers, int i = 0);
-};
-
-typedef Shader<RenderTiny::Shader_Vertex, ID3D1xVertexShader> VertexShader;
-typedef Shader<RenderTiny::Shader_Fragment, ID3D1xPixelShader> PixelShader;
-
-
-class Buffer : public RenderTiny::Buffer
-{
-public:
- RenderDevice* Ren;
- Ptr<ID3D1xBuffer> D3DBuffer;
- size_t Size;
- int Use;
- bool Dynamic;
-
-public:
- Buffer(RenderDevice* r) : Ren(r), Size(0), Use(0) {}
- ~Buffer();
-
- ID3D1xBuffer* GetBuffer()
- {
- return D3DBuffer;
- }
-
- virtual size_t GetSize()
- {
- return Size;
- }
- virtual void* Map(size_t start, size_t size, int flags = 0);
- virtual bool Unmap(void *m);
- virtual bool Data(int use, const void* buffer, size_t size);
-};
-
-class Texture : public RenderTiny::Texture
-{
-public:
- RenderDevice* Ren;
- Ptr<ID3D1xTexture2D> Tex;
- Ptr<ID3D1xShaderResourceView> TexSv;
- Ptr<ID3D1xRenderTargetView> TexRtv;
- Ptr<ID3D1xDepthStencilView> TexDsv;
- mutable Ptr<ID3D1xSamplerState> Sampler;
- int Width, Height;
- int Samples;
-
- Texture(RenderDevice* r, int fmt, int w, int h);
- ~Texture();
-
- virtual int GetWidth() const
- {
- return Width;
- }
- virtual int GetHeight() const
- {
- return Height;
- }
- virtual int GetSamples() const
- {
- return Samples;
- }
-
- virtual void SetSampleMode(int sm);
-
- virtual void Set(int slot, RenderTiny::ShaderStage stage = RenderTiny::Shader_Fragment) const;
-};
-
-class RenderDevice : public RenderTiny::RenderDevice
-{
-public:
- Ptr<IDXGIFactory> DXGIFactory;
- HWND Window;
-
- Ptr<ID3D1xDevice> Device;
- Ptr<ID3D1xDeviceContext> Context;
- Ptr<IDXGISwapChain> SwapChain;
- Ptr<IDXGIAdapter> Adapter;
- Ptr<IDXGIOutput> FullscreenOutput;
- int FSDesktopX, FSDesktopY;
-
- Ptr<ID3D1xTexture2D> BackBuffer;
- Ptr<ID3D1xRenderTargetView> BackBufferRT;
- Ptr<Texture> CurRenderTarget;
- Ptr<Texture> CurDepthBuffer;
- Ptr<ID3D1xRasterizerState> Rasterizer;
- Ptr<ID3D1xBlendState> BlendState;
- D3D1x_VIEWPORT D3DViewport;
-
- Ptr<ID3D1xDepthStencilState> DepthStates[1 + 2 * Compare_Count];
- Ptr<ID3D1xDepthStencilState> CurDepthState;
- Ptr<ID3D1xInputLayout> ModelVertexIL;
-
- Ptr<ID3D1xSamplerState> SamplerStates[Sample_Count];
-
- struct StandardUniformData
- {
- Matrix4f Proj;
- Matrix4f View;
- } StdUniforms;
- Ptr<Buffer> UniformBuffers[Shader_Count];
- int MaxTextureSet[Shader_Count];
-
- Ptr<VertexShader> VertexShaders[VShader_Count];
- Ptr<PixelShader> PixelShaders[FShader_Count];
- Ptr<Buffer> CommonUniforms[8];
- Ptr<ShaderFill> DefaultFill;
-
- Ptr<Buffer> QuadVertexBuffer;
-
- Array<Ptr<Texture> > DepthBuffers;
-
-public:
- RenderDevice(const RendererParams& p, HWND window);
- ~RenderDevice();
-
- // Implement static initializer function to create this class.
- static RenderTiny::RenderDevice* CreateDevice(const RendererParams& rp, void* oswnd);
-
- void UpdateMonitorOutputs();
-
- virtual void SetRealViewport(const Viewport& vp);
- virtual bool SetParams(const RendererParams& newParams);
-
- virtual void Present();
- virtual void ForceFlushGPU();
-
- virtual bool SetFullscreen(DisplayMode fullscreen);
-
- virtual void Clear(float r = 0, float g = 0, float b = 0, float a = 1, float depth = 1);
-
- virtual Buffer* CreateBuffer();
- virtual Texture* CreateTexture(int format, int width, int height, const void* data, int mipcount=1);
-
- Texture* GetDepthBuffer(int w, int h, int ms);
-
- virtual void BeginRendering();
- virtual void SetRenderTarget(RenderTiny::Texture* color,
- RenderTiny::Texture* depth = NULL, RenderTiny::Texture* stencil = NULL);
- virtual void SetDepthMode(bool enable, bool write, CompareFunc func = Compare_Less);
- virtual void SetWorldUniforms(const Matrix4f& proj);
- virtual void SetCommonUniformBuffer(int i, RenderTiny::Buffer* buffer);
-
- virtual void Render(const Matrix4f& matrix, Model* model);
- virtual void Render(const ShaderFill* fill, RenderTiny::Buffer* vertices, RenderTiny::Buffer* indices,
- const Matrix4f& matrix, int offset, int count, PrimitiveType prim = Prim_Triangles);
-
- virtual ShaderFill *CreateSimpleFill() { return DefaultFill; }
-
- virtual RenderTiny::Shader *LoadBuiltinShader(ShaderStage stage, int shader);
-
- bool RecreateSwapChain();
- virtual ID3D10Blob* CompileShader(const char* profile, const char* src, const char* mainName = "main");
-
- ID3D1xSamplerState* GetSamplerState(int sm);
-
- void SetTexture(RenderTiny::ShaderStage stage, int slot, const Texture* t);
-};
-
-}}} // Render::D3D10
-
-#endif
+/************************************************************************************
+
+Filename : RenderTiny_D3D1X_Device.h
+Content : RenderDevice implementation header for D3DX10.
+Created : September 10, 2012
+Authors : Andrew Reisse
+
+Copyright : Copyright 2012 Oculus VR, Inc. All Rights reserved.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+************************************************************************************/
+
+#ifndef INC_RenderTiny_D3D1X_Device_h
+#define INC_RenderTiny_D3D1X_Device_h
+
+#include "Kernel/OVR_String.h"
+#include "Kernel/OVR_Array.h"
+
+#include "RenderTiny_Device.h"
+#include <Windows.h>
+
+#define _OVR_RENDERER_D3D10
+#include <d3d10.h>
+
+namespace OVR { namespace RenderTiny { namespace D3D10 {
+
+class RenderDevice;
+class Buffer;
+
+typedef ID3D10Device ID3D1xDevice;
+typedef ID3D10Device ID3D1xDeviceContext;
+typedef ID3D10RenderTargetView ID3D1xRenderTargetView;
+typedef ID3D10Texture2D ID3D1xTexture2D;
+typedef ID3D10ShaderResourceView ID3D1xShaderResourceView;
+typedef ID3D10DepthStencilView ID3D1xDepthStencilView;
+typedef ID3D10DepthStencilState ID3D1xDepthStencilState;
+typedef ID3D10InputLayout ID3D1xInputLayout;
+typedef ID3D10Buffer ID3D1xBuffer;
+typedef ID3D10VertexShader ID3D1xVertexShader;
+typedef ID3D10PixelShader ID3D1xPixelShader;
+typedef ID3D10GeometryShader ID3D1xGeometryShader;
+typedef ID3D10BlendState ID3D1xBlendState;
+typedef ID3D10RasterizerState ID3D1xRasterizerState;
+typedef ID3D10SamplerState ID3D1xSamplerState;
+typedef ID3D10Query ID3D1xQuery;
+typedef ID3D10Blob ID3D1xBlob;
+typedef D3D10_VIEWPORT D3D1x_VIEWPORT;
+typedef D3D10_QUERY_DESC D3D1x_QUERY_DESC;
+#define D3D1x_(x) D3D10_##x
+#define ID3D1x(x) ID3D10##x
+
+
+
+class ShaderBase : public RenderTiny::Shader
+{
+public:
+ RenderDevice* Ren;
+ unsigned char* UniformData;
+ int UniformsSize;
+
+ struct Uniform
+ {
+ String Name;
+ int Offset, Size;
+ };
+ Array<Uniform> UniformInfo;
+
+ ShaderBase(RenderDevice* r, ShaderStage stage);
+ ~ShaderBase();
+
+ void InitUniforms(ID3D10Blob* s);
+ bool SetUniform(const char* name, int n, const float* v);
+
+ void UpdateBuffer(Buffer* b);
+};
+
+template<RenderTiny::ShaderStage SStage, class D3DShaderType>
+class Shader : public ShaderBase
+{
+public:
+ D3DShaderType* D3DShader;
+
+ Shader(RenderDevice* r, D3DShaderType* s) : ShaderBase(r, SStage), D3DShader(s) {}
+ Shader(RenderDevice* r, ID3D1xBlob* s) : ShaderBase(r, SStage)
+ {
+ Load(s);
+ InitUniforms(s);
+ }
+ ~Shader()
+ {
+ if (D3DShader)
+ D3DShader->Release();
+ }
+ bool Load(ID3D1xBlob* shader)
+ {
+ return Load(shader->GetBufferPointer(), shader->GetBufferSize());
+ }
+
+ // These functions have specializations.
+ bool Load(void* shader, size_t size);
+ void Set(PrimitiveType prim) const;
+ void SetUniformBuffer(RenderTiny::Buffer* buffers, int i = 0);
+};
+
+typedef Shader<RenderTiny::Shader_Vertex, ID3D1xVertexShader> VertexShader;
+typedef Shader<RenderTiny::Shader_Fragment, ID3D1xPixelShader> PixelShader;
+
+
+class Buffer : public RenderTiny::Buffer
+{
+public:
+ RenderDevice* Ren;
+ Ptr<ID3D1xBuffer> D3DBuffer;
+ size_t Size;
+ int Use;
+ bool Dynamic;
+
+public:
+ Buffer(RenderDevice* r) : Ren(r), Size(0), Use(0) {}
+ ~Buffer();
+
+ ID3D1xBuffer* GetBuffer()
+ {
+ return D3DBuffer;
+ }
+
+ virtual size_t GetSize()
+ {
+ return Size;
+ }
+ virtual void* Map(size_t start, size_t size, int flags = 0);
+ virtual bool Unmap(void *m);
+ virtual bool Data(int use, const void* buffer, size_t size);
+};
+
+class Texture : public RenderTiny::Texture
+{
+public:
+ RenderDevice* Ren;
+ Ptr<ID3D1xTexture2D> Tex;
+ Ptr<ID3D1xShaderResourceView> TexSv;
+ Ptr<ID3D1xRenderTargetView> TexRtv;
+ Ptr<ID3D1xDepthStencilView> TexDsv;
+ mutable Ptr<ID3D1xSamplerState> Sampler;
+ int Width, Height;
+ int Samples;
+
+ Texture(RenderDevice* r, int fmt, int w, int h);
+ ~Texture();
+
+ virtual int GetWidth() const
+ {
+ return Width;
+ }
+ virtual int GetHeight() const
+ {
+ return Height;
+ }
+ virtual int GetSamples() const
+ {
+ return Samples;
+ }
+
+ virtual void SetSampleMode(int sm);
+
+ virtual void Set(int slot, RenderTiny::ShaderStage stage = RenderTiny::Shader_Fragment) const;
+};
+
+class RenderDevice : public RenderTiny::RenderDevice
+{
+public:
+ Ptr<IDXGIFactory> DXGIFactory;
+ HWND Window;
+
+ Ptr<ID3D1xDevice> Device;
+ Ptr<ID3D1xDeviceContext> Context;
+ Ptr<IDXGISwapChain> SwapChain;
+ Ptr<IDXGIAdapter> Adapter;
+ Ptr<IDXGIOutput> FullscreenOutput;
+ int FSDesktopX, FSDesktopY;
+
+ Ptr<ID3D1xTexture2D> BackBuffer;
+ Ptr<ID3D1xRenderTargetView> BackBufferRT;
+ Ptr<Texture> CurRenderTarget;
+ Ptr<Texture> CurDepthBuffer;
+ Ptr<ID3D1xRasterizerState> Rasterizer;
+ Ptr<ID3D1xBlendState> BlendState;
+ D3D1x_VIEWPORT D3DViewport;
+
+ Ptr<ID3D1xDepthStencilState> DepthStates[1 + 2 * Compare_Count];
+ Ptr<ID3D1xDepthStencilState> CurDepthState;
+ Ptr<ID3D1xInputLayout> ModelVertexIL;
+
+ Ptr<ID3D1xSamplerState> SamplerStates[Sample_Count];
+
+ struct StandardUniformData
+ {
+ Matrix4f Proj;
+ Matrix4f View;
+ } StdUniforms;
+ Ptr<Buffer> UniformBuffers[Shader_Count];
+ int MaxTextureSet[Shader_Count];
+
+ Ptr<VertexShader> VertexShaders[VShader_Count];
+ Ptr<PixelShader> PixelShaders[FShader_Count];
+ Ptr<Buffer> CommonUniforms[8];
+ Ptr<ShaderFill> DefaultFill;
+
+ Ptr<Buffer> QuadVertexBuffer;
+
+ Array<Ptr<Texture> > DepthBuffers;
+
+public:
+ RenderDevice(const RendererParams& p, HWND window);
+ ~RenderDevice();
+
+ // Implement static initializer function to create this class.
+ static RenderTiny::RenderDevice* CreateDevice(const RendererParams& rp, void* oswnd);
+
+ void UpdateMonitorOutputs();
+
+ virtual void SetRealViewport(const Viewport& vp);
+ virtual bool SetParams(const RendererParams& newParams);
+
+ virtual void Present();
+ virtual void ForceFlushGPU();
+
+ virtual bool SetFullscreen(DisplayMode fullscreen);
+
+ virtual void Clear(float r = 0, float g = 0, float b = 0, float a = 1, float depth = 1);
+
+ virtual Buffer* CreateBuffer();
+ virtual Texture* CreateTexture(int format, int width, int height, const void* data, int mipcount=1);
+
+ Texture* GetDepthBuffer(int w, int h, int ms);
+
+ virtual void BeginRendering();
+ virtual void SetRenderTarget(RenderTiny::Texture* color,
+ RenderTiny::Texture* depth = NULL, RenderTiny::Texture* stencil = NULL);
+ virtual void SetDepthMode(bool enable, bool write, CompareFunc func = Compare_Less);
+ virtual void SetWorldUniforms(const Matrix4f& proj);
+ virtual void SetCommonUniformBuffer(int i, RenderTiny::Buffer* buffer);
+
+ virtual void Render(const Matrix4f& matrix, Model* model);
+ virtual void Render(const ShaderFill* fill, RenderTiny::Buffer* vertices, RenderTiny::Buffer* indices,
+ const Matrix4f& matrix, int offset, int count, PrimitiveType prim = Prim_Triangles);
+
+ virtual ShaderFill *CreateSimpleFill() { return DefaultFill; }
+
+ virtual RenderTiny::Shader *LoadBuiltinShader(ShaderStage stage, int shader);
+
+ bool RecreateSwapChain();
+ virtual ID3D10Blob* CompileShader(const char* profile, const char* src, const char* mainName = "main");
+
+ ID3D1xSamplerState* GetSamplerState(int sm);
+
+ void SetTexture(RenderTiny::ShaderStage stage, int slot, const Texture* t);
+};
+
+}}} // Render::D3D10
+
+#endif
diff --git a/Samples/OculusRoomTiny/RenderTiny_Device.cpp b/Samples/OculusRoomTiny/RenderTiny_Device.cpp
index 1d6cdde..2c363c2 100644
--- a/Samples/OculusRoomTiny/RenderTiny_Device.cpp
+++ b/Samples/OculusRoomTiny/RenderTiny_Device.cpp
@@ -1,442 +1,442 @@
-/************************************************************************************
-
-Filename : RenderTiny_Device.cpp
-Content : Platform renderer for simple scene graph - implementation
-Created : September 6, 2012
-Authors : Andrew Reisse
-
-Copyright : Copyright 2012 Oculus VR, Inc. All Rights reserved.
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-
-************************************************************************************/
-
-#include "RenderTiny_Device.h"
-
-#include "Kernel/OVR_Log.h"
-
-namespace OVR { namespace RenderTiny {
-
-void Model::Render(const Matrix4f& ltw, RenderDevice* ren)
-{
- if (Visible)
- {
- Matrix4f m = ltw * GetMatrix();
- ren->Render(m, this);
- }
-}
-
-void Container::Render(const Matrix4f& ltw, RenderDevice* ren)
-{
- Matrix4f m = ltw * GetMatrix();
- for(unsigned i = 0; i < Nodes.GetSize(); i++)
- {
- Nodes[i]->Render(m, ren);
- }
-}
-
-void Scene::Render(RenderDevice* ren, const Matrix4f& view)
-{
- Lighting.Update(view, LightPos);
-
- ren->SetLighting(&Lighting);
-
- World.Render(view, ren);
-}
-
-
-
-UInt16 CubeIndices[] =
-{
- 0, 1, 3,
- 3, 1, 2,
-
- 5, 4, 6,
- 6, 4, 7,
-
- 8, 9, 11,
- 11, 9, 10,
-
- 13, 12, 14,
- 14, 12, 15,
-
- 16, 17, 19,
- 19, 17, 18,
-
- 21, 20, 22,
- 22, 20, 23
-};
-
-
-void Model::AddSolidColorBox(float x1, float y1, float z1,
- float x2, float y2, float z2,
- Color c)
-{
- float t;
-
- if(x1 > x2)
- {
- t = x1;
- x1 = x2;
- x2 = t;
- }
- if(y1 > y2)
- {
- t = y1;
- y1 = y2;
- y2 = t;
- }
- if(z1 > z2)
- {
- t = z1;
- z1 = z2;
- z2 = t;
- }
-
- // Cube vertices and their normals.
- Vector3f CubeVertices[][3] =
- {
- Vector3f(x1, y2, z1), Vector3f(z1, x1), Vector3f(0.0f, 1.0f, 0.0f),
- Vector3f(x2, y2, z1), Vector3f(z1, x2), Vector3f(0.0f, 1.0f, 0.0f),
- Vector3f(x2, y2, z2), Vector3f(z2, x2), Vector3f(0.0f, 1.0f, 0.0f),
- Vector3f(x1, y2, z2), Vector3f(z2, x1), Vector3f(0.0f, 1.0f, 0.0f),
-
- Vector3f(x1, y1, z1), Vector3f(z1, x1), Vector3f(0.0f, -1.0f, 0.0f),
- Vector3f(x2, y1, z1), Vector3f(z1, x2), Vector3f(0.0f, -1.0f, 0.0f),
- Vector3f(x2, y1, z2), Vector3f(z2, x2), Vector3f(0.0f, -1.0f, 0.0f),
- Vector3f(x1, y1, z2), Vector3f(z2, x1), Vector3f(0.0f, -1.0f, 0.0f),
-
- Vector3f(x1, y1, z2), Vector3f(z2, y1), Vector3f(-1.0f, 0.0f, 0.0f),
- Vector3f(x1, y1, z1), Vector3f(z1, y1), Vector3f(-1.0f, 0.0f, 0.0f),
- Vector3f(x1, y2, z1), Vector3f(z1, y2), Vector3f(-1.0f, 0.0f, 0.0f),
- Vector3f(x1, y2, z2), Vector3f(z2, y2), Vector3f(-1.0f, 0.0f, 0.0f),
-
- Vector3f(x2, y1, z2), Vector3f(z2, y1), Vector3f(1.0f, 0.0f, 0.0f),
- Vector3f(x2, y1, z1), Vector3f(z1, y1), Vector3f(1.0f, 0.0f, 0.0f),
- Vector3f(x2, y2, z1), Vector3f(z1, y2), Vector3f(1.0f, 0.0f, 0.0f),
- Vector3f(x2, y2, z2), Vector3f(z2, y2), Vector3f(1.0f, 0.0f, 0.0f),
-
- Vector3f(x1, y1, z1), Vector3f(x1, y1), Vector3f(0.0f, 0.0f, -1.0f),
- Vector3f(x2, y1, z1), Vector3f(x2, y1), Vector3f(0.0f, 0.0f, -1.0f),
- Vector3f(x2, y2, z1), Vector3f(x2, y2), Vector3f(0.0f, 0.0f, -1.0f),
- Vector3f(x1, y2, z1), Vector3f(x1, y2), Vector3f(0.0f, 0.0f, -1.0f),
-
- Vector3f(x1, y1, z2), Vector3f(x1, y1), Vector3f(0.0f, 0.0f, 1.0f),
- Vector3f(x2, y1, z2), Vector3f(x2, y1), Vector3f(0.0f, 0.0f, 1.0f),
- Vector3f(x2, y2, z2), Vector3f(x2, y2), Vector3f(0.0f, 0.0f, 1.0f),
- Vector3f(x1, y2, z2), Vector3f(x1, y2), Vector3f(0.0f, 0.0f, 1.0f)
- };
-
-
- UInt16 startIndex = GetNextVertexIndex();
-
- enum
- {
- CubeVertexCount = sizeof(CubeVertices) / sizeof(CubeVertices[0]),
- CubeIndexCount = sizeof(CubeIndices) / sizeof(CubeIndices[0])
- };
-
- for(int v = 0; v < CubeVertexCount; v++)
- {
- AddVertex(Vertex(CubeVertices[v][0], c, CubeVertices[v][1].x, CubeVertices[v][1].y, CubeVertices[v][2]));
- }
-
- // Renumber indices
- for(int i = 0; i < CubeIndexCount / 3; i++)
- {
- AddTriangle(CubeIndices[i * 3] + startIndex,
- CubeIndices[i * 3 + 1] + startIndex,
- CubeIndices[i * 3 + 2] + startIndex);
- }
-}
-
-
-//-------------------------------------------------------------------------------------
-
-
-void ShaderFill::Set(PrimitiveType prim) const
-{
- Shaders->Set(prim);
- for(int i = 0; i < 8; i++)
- {
- if(Textures[i])
- {
- Textures[i]->Set(i);
- }
- }
-}
-
-
-
-//-------------------------------------------------------------------------------------
-// ***** Rendering
-
-
-RenderDevice::RenderDevice()
- : CurPostProcess(PostProcess_None),
- SceneColorTexW(0), SceneColorTexH(0),
- SceneRenderScale(1),
- Distortion(1.0f, 0.18f, 0.115f),
- PostProcessShaderActive(PostProcessShader_DistortionAndChromAb)
-{
- PostProcessShaderRequested = PostProcessShaderActive;
-}
-
-ShaderFill* RenderDevice::CreateTextureFill(RenderTiny::Texture* t)
-{
- ShaderSet* shaders = CreateShaderSet();
- shaders->SetShader(LoadBuiltinShader(Shader_Vertex, VShader_MVP));
- shaders->SetShader(LoadBuiltinShader(Shader_Fragment, FShader_Texture));
- ShaderFill* f = new ShaderFill(*shaders);
- f->SetTexture(0, t);
- return f;
-}
-
-void RenderDevice::SetLighting(const LightingParams* lt)
-{
- if (!LightingBuffer)
- LightingBuffer = *CreateBuffer();
-
- LightingBuffer->Data(Buffer_Uniform, lt, sizeof(LightingParams));
- SetCommonUniformBuffer(1, LightingBuffer);
-}
-
-
-
-void RenderDevice::SetSceneRenderScale(float ss)
-{
- SceneRenderScale = ss;
- pSceneColorTex = NULL;
-}
-
-void RenderDevice::SetViewport(const Viewport& vp)
-{
- VP = vp;
-
- if (CurPostProcess == PostProcess_Distortion)
- {
- Viewport svp = vp;
- svp.w = (int)ceil(SceneRenderScale * vp.w);
- svp.h = (int)ceil(SceneRenderScale * vp.h);
- svp.x = (int)ceil(SceneRenderScale * vp.x);
- svp.y = (int)ceil(SceneRenderScale * vp.y);
- SetRealViewport(svp);
- }
- else
- {
- SetRealViewport(vp);
- }
-}
-
-
-bool RenderDevice::initPostProcessSupport(PostProcessType pptype)
-{
- if (pptype != PostProcess_Distortion)
- return true;
-
-
- if (PostProcessShaderRequested != PostProcessShaderActive)
- {
- pPostProcessShader.Clear();
- PostProcessShaderActive = PostProcessShaderRequested;
- }
-
- if (!pPostProcessShader)
- {
- Shader *vs = LoadBuiltinShader(Shader_Vertex, VShader_PostProcess);
-
- Shader *ppfs = NULL;
- if (PostProcessShaderActive == PostProcessShader_Distortion)
- {
- ppfs = LoadBuiltinShader(Shader_Fragment, FShader_PostProcess);
- }
- else if (PostProcessShaderActive == PostProcessShader_DistortionAndChromAb)
- {
- ppfs = LoadBuiltinShader(Shader_Fragment, FShader_PostProcessWithChromAb);
- }
- else
- OVR_ASSERT(false);
-
- pPostProcessShader = *CreateShaderSet();
- pPostProcessShader->SetShader(vs);
- pPostProcessShader->SetShader(ppfs);
- }
-
-
- int texw = (int)ceil(SceneRenderScale * WindowWidth),
- texh = (int)ceil(SceneRenderScale * WindowHeight);
-
- // If pSceneColorTex is already created and is of correct size, we are done.
- // It's important to check width/height in case window size changed.
- if (pSceneColorTex && (texw == SceneColorTexW) && (texh == SceneColorTexH))
- {
- return true;
- }
-
- pSceneColorTex = *CreateTexture(Texture_RGBA | Texture_RenderTarget | Params.Multisample,
- texw, texh, NULL);
- if (!pSceneColorTex)
- {
- return false;
- }
- SceneColorTexW = texw;
- SceneColorTexH = texh;
- pSceneColorTex->SetSampleMode(Sample_ClampBorder | Sample_Linear);
-
-
- if (!pFullScreenVertexBuffer)
- {
- pFullScreenVertexBuffer = *CreateBuffer();
- const RenderTiny::Vertex QuadVertices[] =
- {
- Vertex(Vector3f(0, 1, 0), Color(1, 1, 1, 1), 0, 0),
- Vertex(Vector3f(1, 1, 0), Color(1, 1, 1, 1), 1, 0),
- Vertex(Vector3f(0, 0, 0), Color(1, 1, 1, 1), 0, 1),
- Vertex(Vector3f(1, 0, 0), Color(1, 1, 1, 1), 1, 1)
- };
- pFullScreenVertexBuffer->Data(Buffer_Vertex, QuadVertices, sizeof(QuadVertices));
- }
- return true;
-}
-
-void RenderDevice::SetProjection(const Matrix4f& proj)
-{
- Proj = proj;
- SetWorldUniforms(proj);
-}
-
-void RenderDevice::BeginScene(PostProcessType pptype)
-{
- BeginRendering();
-
- if ((pptype != PostProcess_None) && initPostProcessSupport(pptype))
- {
- CurPostProcess = pptype;
- }
- else
- {
- CurPostProcess = PostProcess_None;
- }
-
- if (CurPostProcess == PostProcess_Distortion)
- {
- SetRenderTarget(pSceneColorTex);
- SetViewport(VP);
- }
- else
- {
- SetRenderTarget(0);
- }
-
- SetWorldUniforms(Proj);
-}
-
-void RenderDevice::FinishScene()
-{
- if (CurPostProcess == PostProcess_None)
- return;
-
- SetRenderTarget(0);
- SetRealViewport(VP);
- FinishScene1();
-
- CurPostProcess = PostProcess_None;
-}
-
-
-
-void RenderDevice::FinishScene1()
-{
- // Clear with black
- Clear(0.0f, 0.0f, 0.0f, 1.0f);
-
- float w = float(VP.w) / float(WindowWidth),
- h = float(VP.h) / float(WindowHeight),
- x = float(VP.x) / float(WindowWidth),
- y = float(VP.y) / float(WindowHeight);
-
- float as = float(VP.w) / float(VP.h);
-
- // We are using 1/4 of DistortionCenter offset value here, since it is
- // relative to [-1,1] range that gets mapped to [0, 0.5].
- pPostProcessShader->SetUniform2f("LensCenter",
- x + (w + Distortion.XCenterOffset * 0.5f)*0.5f, y + h*0.5f);
- pPostProcessShader->SetUniform2f("ScreenCenter", x + w*0.5f, y + h*0.5f);
-
- // MA: This is more correct but we would need higher-res texture vertically; we should adopt this
- // once we have asymmetric input texture scale.
- float scaleFactor = 1.0f / Distortion.Scale;
-
- pPostProcessShader->SetUniform2f("Scale", (w/2) * scaleFactor, (h/2) * scaleFactor * as);
- pPostProcessShader->SetUniform2f("ScaleIn", (2/w), (2/h) / as);
-
- pPostProcessShader->SetUniform4f("HmdWarpParam",
- Distortion.K[0], Distortion.K[1], Distortion.K[2], Distortion.K[3]);
-
- if (PostProcessShaderRequested == PostProcessShader_DistortionAndChromAb)
- {
- pPostProcessShader->SetUniform4f("ChromAbParam",
- Distortion.ChromaticAberration[0],
- Distortion.ChromaticAberration[1],
- Distortion.ChromaticAberration[2],
- Distortion.ChromaticAberration[3]);
- }
-
- Matrix4f texm(w, 0, 0, x,
- 0, h, 0, y,
- 0, 0, 0, 0,
- 0, 0, 0, 1);
- pPostProcessShader->SetUniform4x4f("Texm", texm);
-
- Matrix4f view(2, 0, 0, -1,
- 0, 2, 0, -1,
- 0, 0, 0, 0,
- 0, 0, 0, 1);
-
- ShaderFill fill(pPostProcessShader);
- fill.SetTexture(0, pSceneColorTex);
- Render(&fill, pFullScreenVertexBuffer, NULL, view, 0, 4, Prim_TriangleStrip);
-}
-
-
-int GetNumMipLevels(int w, int h)
-{
- int n = 1;
- while(w > 1 || h > 1)
- {
- w >>= 1;
- h >>= 1;
- n++;
- }
- return n;
-}
-
-void FilterRgba2x2(const UByte* src, int w, int h, UByte* dest)
-{
- for(int j = 0; j < (h & ~1); j += 2)
- {
- const UByte* psrc = src + (w * j * 4);
- UByte* pdest = dest + ((w >> 1) * (j >> 1) * 4);
-
- for(int i = 0; i < w >> 1; i++, psrc += 8, pdest += 4)
- {
- pdest[0] = (((int)psrc[0]) + psrc[4] + psrc[w * 4 + 0] + psrc[w * 4 + 4]) >> 2;
- pdest[1] = (((int)psrc[1]) + psrc[5] + psrc[w * 4 + 1] + psrc[w * 4 + 5]) >> 2;
- pdest[2] = (((int)psrc[2]) + psrc[6] + psrc[w * 4 + 2] + psrc[w * 4 + 6]) >> 2;
- pdest[3] = (((int)psrc[3]) + psrc[7] + psrc[w * 4 + 3] + psrc[w * 4 + 7]) >> 2;
- }
- }
-}
-
-
-}}
+/************************************************************************************
+
+Filename : RenderTiny_Device.cpp
+Content : Platform renderer for simple scene graph - implementation
+Created : September 6, 2012
+Authors : Andrew Reisse
+
+Copyright : Copyright 2012 Oculus VR, Inc. All Rights reserved.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+************************************************************************************/
+
+#include "RenderTiny_Device.h"
+
+#include "Kernel/OVR_Log.h"
+
+namespace OVR { namespace RenderTiny {
+
+void Model::Render(const Matrix4f& ltw, RenderDevice* ren)
+{
+ if (Visible)
+ {
+ Matrix4f m = ltw * GetMatrix();
+ ren->Render(m, this);
+ }
+}
+
+void Container::Render(const Matrix4f& ltw, RenderDevice* ren)
+{
+ Matrix4f m = ltw * GetMatrix();
+ for(unsigned i = 0; i < Nodes.GetSize(); i++)
+ {
+ Nodes[i]->Render(m, ren);
+ }
+}
+
+void Scene::Render(RenderDevice* ren, const Matrix4f& view)
+{
+ Lighting.Update(view, LightPos);
+
+ ren->SetLighting(&Lighting);
+
+ World.Render(view, ren);
+}
+
+
+
+UInt16 CubeIndices[] =
+{
+ 0, 1, 3,
+ 3, 1, 2,
+
+ 5, 4, 6,
+ 6, 4, 7,
+
+ 8, 9, 11,
+ 11, 9, 10,
+
+ 13, 12, 14,
+ 14, 12, 15,
+
+ 16, 17, 19,
+ 19, 17, 18,
+
+ 21, 20, 22,
+ 22, 20, 23
+};
+
+
+void Model::AddSolidColorBox(float x1, float y1, float z1,
+ float x2, float y2, float z2,
+ Color c)
+{
+ float t;
+
+ if(x1 > x2)
+ {
+ t = x1;
+ x1 = x2;
+ x2 = t;
+ }
+ if(y1 > y2)
+ {
+ t = y1;
+ y1 = y2;
+ y2 = t;
+ }
+ if(z1 > z2)
+ {
+ t = z1;
+ z1 = z2;
+ z2 = t;
+ }
+
+ // Cube vertices and their normals.
+ Vector3f CubeVertices[][3] =
+ {
+ Vector3f(x1, y2, z1), Vector3f(z1, x1), Vector3f(0.0f, 1.0f, 0.0f),
+ Vector3f(x2, y2, z1), Vector3f(z1, x2), Vector3f(0.0f, 1.0f, 0.0f),
+ Vector3f(x2, y2, z2), Vector3f(z2, x2), Vector3f(0.0f, 1.0f, 0.0f),
+ Vector3f(x1, y2, z2), Vector3f(z2, x1), Vector3f(0.0f, 1.0f, 0.0f),
+
+ Vector3f(x1, y1, z1), Vector3f(z1, x1), Vector3f(0.0f, -1.0f, 0.0f),
+ Vector3f(x2, y1, z1), Vector3f(z1, x2), Vector3f(0.0f, -1.0f, 0.0f),
+ Vector3f(x2, y1, z2), Vector3f(z2, x2), Vector3f(0.0f, -1.0f, 0.0f),
+ Vector3f(x1, y1, z2), Vector3f(z2, x1), Vector3f(0.0f, -1.0f, 0.0f),
+
+ Vector3f(x1, y1, z2), Vector3f(z2, y1), Vector3f(-1.0f, 0.0f, 0.0f),
+ Vector3f(x1, y1, z1), Vector3f(z1, y1), Vector3f(-1.0f, 0.0f, 0.0f),
+ Vector3f(x1, y2, z1), Vector3f(z1, y2), Vector3f(-1.0f, 0.0f, 0.0f),
+ Vector3f(x1, y2, z2), Vector3f(z2, y2), Vector3f(-1.0f, 0.0f, 0.0f),
+
+ Vector3f(x2, y1, z2), Vector3f(z2, y1), Vector3f(1.0f, 0.0f, 0.0f),
+ Vector3f(x2, y1, z1), Vector3f(z1, y1), Vector3f(1.0f, 0.0f, 0.0f),
+ Vector3f(x2, y2, z1), Vector3f(z1, y2), Vector3f(1.0f, 0.0f, 0.0f),
+ Vector3f(x2, y2, z2), Vector3f(z2, y2), Vector3f(1.0f, 0.0f, 0.0f),
+
+ Vector3f(x1, y1, z1), Vector3f(x1, y1), Vector3f(0.0f, 0.0f, -1.0f),
+ Vector3f(x2, y1, z1), Vector3f(x2, y1), Vector3f(0.0f, 0.0f, -1.0f),
+ Vector3f(x2, y2, z1), Vector3f(x2, y2), Vector3f(0.0f, 0.0f, -1.0f),
+ Vector3f(x1, y2, z1), Vector3f(x1, y2), Vector3f(0.0f, 0.0f, -1.0f),
+
+ Vector3f(x1, y1, z2), Vector3f(x1, y1), Vector3f(0.0f, 0.0f, 1.0f),
+ Vector3f(x2, y1, z2), Vector3f(x2, y1), Vector3f(0.0f, 0.0f, 1.0f),
+ Vector3f(x2, y2, z2), Vector3f(x2, y2), Vector3f(0.0f, 0.0f, 1.0f),
+ Vector3f(x1, y2, z2), Vector3f(x1, y2), Vector3f(0.0f, 0.0f, 1.0f)
+ };
+
+
+ UInt16 startIndex = GetNextVertexIndex();
+
+ enum
+ {
+ CubeVertexCount = sizeof(CubeVertices) / sizeof(CubeVertices[0]),
+ CubeIndexCount = sizeof(CubeIndices) / sizeof(CubeIndices[0])
+ };
+
+ for(int v = 0; v < CubeVertexCount; v++)
+ {
+ AddVertex(Vertex(CubeVertices[v][0], c, CubeVertices[v][1].x, CubeVertices[v][1].y, CubeVertices[v][2]));
+ }
+
+ // Renumber indices
+ for(int i = 0; i < CubeIndexCount / 3; i++)
+ {
+ AddTriangle(CubeIndices[i * 3] + startIndex,
+ CubeIndices[i * 3 + 1] + startIndex,
+ CubeIndices[i * 3 + 2] + startIndex);
+ }
+}
+
+
+//-------------------------------------------------------------------------------------
+
+
+void ShaderFill::Set(PrimitiveType prim) const
+{
+ Shaders->Set(prim);
+ for(int i = 0; i < 8; i++)
+ {
+ if(Textures[i])
+ {
+ Textures[i]->Set(i);
+ }
+ }
+}
+
+
+
+//-------------------------------------------------------------------------------------
+// ***** Rendering
+
+
+RenderDevice::RenderDevice()
+ : CurPostProcess(PostProcess_None),
+ SceneColorTexW(0), SceneColorTexH(0),
+ SceneRenderScale(1),
+ Distortion(1.0f, 0.18f, 0.115f),
+ PostProcessShaderActive(PostProcessShader_DistortionAndChromAb)
+{
+ PostProcessShaderRequested = PostProcessShaderActive;
+}
+
+ShaderFill* RenderDevice::CreateTextureFill(RenderTiny::Texture* t)
+{
+ ShaderSet* shaders = CreateShaderSet();
+ shaders->SetShader(LoadBuiltinShader(Shader_Vertex, VShader_MVP));
+ shaders->SetShader(LoadBuiltinShader(Shader_Fragment, FShader_Texture));
+ ShaderFill* f = new ShaderFill(*shaders);
+ f->SetTexture(0, t);
+ return f;
+}
+
+void RenderDevice::SetLighting(const LightingParams* lt)
+{
+ if (!LightingBuffer)
+ LightingBuffer = *CreateBuffer();
+
+ LightingBuffer->Data(Buffer_Uniform, lt, sizeof(LightingParams));
+ SetCommonUniformBuffer(1, LightingBuffer);
+}
+
+
+
+void RenderDevice::SetSceneRenderScale(float ss)
+{
+ SceneRenderScale = ss;
+ pSceneColorTex = NULL;
+}
+
+void RenderDevice::SetViewport(const Viewport& vp)
+{
+ VP = vp;
+
+ if (CurPostProcess == PostProcess_Distortion)
+ {
+ Viewport svp = vp;
+ svp.w = (int)ceil(SceneRenderScale * vp.w);
+ svp.h = (int)ceil(SceneRenderScale * vp.h);
+ svp.x = (int)ceil(SceneRenderScale * vp.x);
+ svp.y = (int)ceil(SceneRenderScale * vp.y);
+ SetRealViewport(svp);
+ }
+ else
+ {
+ SetRealViewport(vp);
+ }
+}
+
+
+bool RenderDevice::initPostProcessSupport(PostProcessType pptype)
+{
+ if (pptype != PostProcess_Distortion)
+ return true;
+
+
+ if (PostProcessShaderRequested != PostProcessShaderActive)
+ {
+ pPostProcessShader.Clear();
+ PostProcessShaderActive = PostProcessShaderRequested;
+ }
+
+ if (!pPostProcessShader)
+ {
+ Shader *vs = LoadBuiltinShader(Shader_Vertex, VShader_PostProcess);
+
+ Shader *ppfs = NULL;
+ if (PostProcessShaderActive == PostProcessShader_Distortion)
+ {
+ ppfs = LoadBuiltinShader(Shader_Fragment, FShader_PostProcess);
+ }
+ else if (PostProcessShaderActive == PostProcessShader_DistortionAndChromAb)
+ {
+ ppfs = LoadBuiltinShader(Shader_Fragment, FShader_PostProcessWithChromAb);
+ }
+ else
+ OVR_ASSERT(false);
+
+ pPostProcessShader = *CreateShaderSet();
+ pPostProcessShader->SetShader(vs);
+ pPostProcessShader->SetShader(ppfs);
+ }
+
+
+ int texw = (int)ceil(SceneRenderScale * WindowWidth),
+ texh = (int)ceil(SceneRenderScale * WindowHeight);
+
+ // If pSceneColorTex is already created and is of correct size, we are done.
+ // It's important to check width/height in case window size changed.
+ if (pSceneColorTex && (texw == SceneColorTexW) && (texh == SceneColorTexH))
+ {
+ return true;
+ }
+
+ pSceneColorTex = *CreateTexture(Texture_RGBA | Texture_RenderTarget | Params.Multisample,
+ texw, texh, NULL);
+ if (!pSceneColorTex)
+ {
+ return false;
+ }
+ SceneColorTexW = texw;
+ SceneColorTexH = texh;
+ pSceneColorTex->SetSampleMode(Sample_ClampBorder | Sample_Linear);
+
+
+ if (!pFullScreenVertexBuffer)
+ {
+ pFullScreenVertexBuffer = *CreateBuffer();
+ const RenderTiny::Vertex QuadVertices[] =
+ {
+ Vertex(Vector3f(0, 1, 0), Color(1, 1, 1, 1), 0, 0),
+ Vertex(Vector3f(1, 1, 0), Color(1, 1, 1, 1), 1, 0),
+ Vertex(Vector3f(0, 0, 0), Color(1, 1, 1, 1), 0, 1),
+ Vertex(Vector3f(1, 0, 0), Color(1, 1, 1, 1), 1, 1)
+ };
+ pFullScreenVertexBuffer->Data(Buffer_Vertex, QuadVertices, sizeof(QuadVertices));
+ }
+ return true;
+}
+
+void RenderDevice::SetProjection(const Matrix4f& proj)
+{
+ Proj = proj;
+ SetWorldUniforms(proj);
+}
+
+void RenderDevice::BeginScene(PostProcessType pptype)
+{
+ BeginRendering();
+
+ if ((pptype != PostProcess_None) && initPostProcessSupport(pptype))
+ {
+ CurPostProcess = pptype;
+ }
+ else
+ {
+ CurPostProcess = PostProcess_None;
+ }
+
+ if (CurPostProcess == PostProcess_Distortion)
+ {
+ SetRenderTarget(pSceneColorTex);
+ SetViewport(VP);
+ }
+ else
+ {
+ SetRenderTarget(0);
+ }
+
+ SetWorldUniforms(Proj);
+}
+
+void RenderDevice::FinishScene()
+{
+ if (CurPostProcess == PostProcess_None)
+ return;
+
+ SetRenderTarget(0);
+ SetRealViewport(VP);
+ FinishScene1();
+
+ CurPostProcess = PostProcess_None;
+}
+
+
+
+void RenderDevice::FinishScene1()
+{
+ // Clear with black
+ Clear(0.0f, 0.0f, 0.0f, 1.0f);
+
+ float w = float(VP.w) / float(WindowWidth),
+ h = float(VP.h) / float(WindowHeight),
+ x = float(VP.x) / float(WindowWidth),
+ y = float(VP.y) / float(WindowHeight);
+
+ float as = float(VP.w) / float(VP.h);
+
+ // We are using 1/4 of DistortionCenter offset value here, since it is
+ // relative to [-1,1] range that gets mapped to [0, 0.5].
+ pPostProcessShader->SetUniform2f("LensCenter",
+ x + (w + Distortion.XCenterOffset * 0.5f)*0.5f, y + h*0.5f);
+ pPostProcessShader->SetUniform2f("ScreenCenter", x + w*0.5f, y + h*0.5f);
+
+ // MA: This is more correct but we would need higher-res texture vertically; we should adopt this
+ // once we have asymmetric input texture scale.
+ float scaleFactor = 1.0f / Distortion.Scale;
+
+ pPostProcessShader->SetUniform2f("Scale", (w/2) * scaleFactor, (h/2) * scaleFactor * as);
+ pPostProcessShader->SetUniform2f("ScaleIn", (2/w), (2/h) / as);
+
+ pPostProcessShader->SetUniform4f("HmdWarpParam",
+ Distortion.K[0], Distortion.K[1], Distortion.K[2], Distortion.K[3]);
+
+ if (PostProcessShaderRequested == PostProcessShader_DistortionAndChromAb)
+ {
+ pPostProcessShader->SetUniform4f("ChromAbParam",
+ Distortion.ChromaticAberration[0],
+ Distortion.ChromaticAberration[1],
+ Distortion.ChromaticAberration[2],
+ Distortion.ChromaticAberration[3]);
+ }
+
+ Matrix4f texm(w, 0, 0, x,
+ 0, h, 0, y,
+ 0, 0, 0, 0,
+ 0, 0, 0, 1);
+ pPostProcessShader->SetUniform4x4f("Texm", texm);
+
+ Matrix4f view(2, 0, 0, -1,
+ 0, 2, 0, -1,
+ 0, 0, 0, 0,
+ 0, 0, 0, 1);
+
+ ShaderFill fill(pPostProcessShader);
+ fill.SetTexture(0, pSceneColorTex);
+ Render(&fill, pFullScreenVertexBuffer, NULL, view, 0, 4, Prim_TriangleStrip);
+}
+
+
+int GetNumMipLevels(int w, int h)
+{
+ int n = 1;
+ while(w > 1 || h > 1)
+ {
+ w >>= 1;
+ h >>= 1;
+ n++;
+ }
+ return n;
+}
+
+void FilterRgba2x2(const UByte* src, int w, int h, UByte* dest)
+{
+ for(int j = 0; j < (h & ~1); j += 2)
+ {
+ const UByte* psrc = src + (w * j * 4);
+ UByte* pdest = dest + ((w >> 1) * (j >> 1) * 4);
+
+ for(int i = 0; i < w >> 1; i++, psrc += 8, pdest += 4)
+ {
+ pdest[0] = (((int)psrc[0]) + psrc[4] + psrc[w * 4 + 0] + psrc[w * 4 + 4]) >> 2;
+ pdest[1] = (((int)psrc[1]) + psrc[5] + psrc[w * 4 + 1] + psrc[w * 4 + 5]) >> 2;
+ pdest[2] = (((int)psrc[2]) + psrc[6] + psrc[w * 4 + 2] + psrc[w * 4 + 6]) >> 2;
+ pdest[3] = (((int)psrc[3]) + psrc[7] + psrc[w * 4 + 3] + psrc[w * 4 + 7]) >> 2;
+ }
+ }
+}
+
+
+}}
diff --git a/Samples/OculusRoomTiny/RenderTiny_Device.h b/Samples/OculusRoomTiny/RenderTiny_Device.h
index 74ad7ec..878450d 100644
--- a/Samples/OculusRoomTiny/RenderTiny_Device.h
+++ b/Samples/OculusRoomTiny/RenderTiny_Device.h
@@ -1,724 +1,724 @@
-/************************************************************************************
-
-Filename : RenderTiny_Device.h
-Content : Minimal possible renderer for RoomTiny sample
-Created : September 6, 2012
-Authors : Andrew Reisse, Michael Antonov
-
-Copyright : Copyright 2012 Oculus VR, Inc. All Rights reserved.
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-
-************************************************************************************/
-
-#ifndef OVR_RenderTiny_Device_h
-#define OVR_RenderTiny_Device_h
-
-#include "Kernel/OVR_Math.h"
-#include "Kernel/OVR_Array.h"
-#include "Kernel/OVR_RefCount.h"
-#include "Kernel/OVR_String.h"
-#include "Kernel/OVR_File.h"
-#include "Kernel/OVR_Color.h"
-
-#include "Util/Util_Render_Stereo.h"
-
-namespace OVR { namespace RenderTiny {
-
-using namespace OVR::Util::Render;
-
-class RenderDevice;
-
-
-//-----------------------------------------------------------------------------------
-
-// Rendering primitive type used to render Model.
-enum PrimitiveType
-{
- Prim_Triangles,
- Prim_Lines,
- Prim_TriangleStrip,
- Prim_Unknown,
- Prim_Count
-};
-
-// Types of shaders taht can be stored together in a ShaderSet.
-enum ShaderStage
-{
- Shader_Vertex = 0,
- Shader_Fragment = 2,
- Shader_Pixel = 2,
- Shader_Count = 3,
-};
-
-// Built-in shader types; used by LoadBuiltinShader.
-enum BuiltinShaders
-{
- VShader_MV = 0,
- VShader_MVP = 1,
- VShader_PostProcess = 2,
- VShader_Count = 3,
-
- FShader_Solid = 0,
- FShader_Gouraud = 1,
- FShader_Texture = 2,
- FShader_PostProcess = 3,
- FShader_PostProcessWithChromAb = 4,
- FShader_LitGouraud = 5,
- FShader_LitTexture = 6,
- FShader_Count
-};
-
-
-enum MapFlags
-{
- Map_Discard = 1,
- Map_Read = 2, // do not use
- Map_Unsynchronized = 4, // like D3D11_MAP_NO_OVERWRITE
-};
-
-// Buffer types used for uploading geometry & constants.
-enum BufferUsage
-{
- Buffer_Unknown = 0,
- Buffer_Vertex = 1,
- Buffer_Index = 2,
- Buffer_Uniform = 4,
- Buffer_TypeMask = 0xff,
- Buffer_ReadOnly = 0x100, // Buffer must be created with Data().
-};
-
-enum TextureFormat
-{
- Texture_RGBA = 0x0100,
- Texture_Depth = 0x8000,
- Texture_TypeMask = 0xff00,
- Texture_SamplesMask = 0x00ff,
- Texture_RenderTarget = 0x10000,
- Texture_GenMipmaps = 0x20000,
-};
-
-// Texture sampling modes.
-enum SampleMode
-{
- Sample_Linear = 0,
- Sample_Nearest = 1,
- Sample_Anisotropic = 2,
- Sample_FilterMask = 3,
-
- Sample_Repeat = 0,
- Sample_Clamp = 4,
- Sample_ClampBorder = 8, // If unsupported Clamp is used instead.
- Sample_AddressMask =12,
-
- Sample_Count =13,
-};
-
-// A vector with a dummy w component for alignment in uniform buffers (and for float colors).
-// The w component is not used in any calculations.
-struct Vector4f : public Vector3f
-{
- float w;
-
- Vector4f() : w(1) {}
- Vector4f(const Vector3f& v) : Vector3f(v), w(1) {}
- Vector4f(float r, float g, float b, float a) : Vector3f(r,g,b), w(a) {}
-};
-
-
-// Base class for vertex and pixel shaders. Stored in ShaderSet.
-class Shader : public RefCountBase<Shader>
-{
- friend class ShaderSet;
-
-protected:
- ShaderStage Stage;
-
-public:
- Shader(ShaderStage s) : Stage(s) {}
- virtual ~Shader() {}
-
- ShaderStage GetStage() const { return Stage; }
-
- virtual void Set(PrimitiveType) const { }
- virtual void SetUniformBuffer(class Buffer* buffers, int i = 0) { OVR_UNUSED2(buffers, i); }
-
-protected:
- virtual bool SetUniform(const char* name, int n, const float* v) { OVR_UNUSED3(name, n, v); return false; }
-};
-
-
-// A group of shaders, one per stage.
-// A ShaderSet is applied to a RenderDevice for rendering with a given fill.
-class ShaderSet : public RefCountBase<ShaderSet>
-{
- protected:
- Ptr<Shader> Shaders[Shader_Count];
-
-public:
- ShaderSet() { }
- ~ShaderSet() { }
-
- virtual void SetShader(Shader *s)
- {
- Shaders[s->GetStage()] = s;
- }
- virtual void UnsetShader(int stage)
- {
- Shaders[stage] = NULL;
- }
- Shader* GetShader(int stage) { return Shaders[stage]; }
-
- virtual void Set(PrimitiveType prim) const
- {
- for (int i = 0; i < Shader_Count; i++)
- if (Shaders[i])
- Shaders[i]->Set(prim);
- }
-
- // Set a uniform (other than the standard matrices). It is undefined whether the
- // uniforms from one shader occupy the same space as those in other shaders
- // (unless a buffer is used, then each buffer is independent).
- virtual bool SetUniform(const char* name, int n, const float* v)
- {
- bool result = 0;
- for (int i = 0; i < Shader_Count; i++)
- if (Shaders[i])
- result |= Shaders[i]->SetUniform(name, n, v);
-
- return result;
- }
- bool SetUniform1f(const char* name, float x)
- {
- const float v[] = {x};
- return SetUniform(name, 1, v);
- }
- bool SetUniform2f(const char* name, float x, float y)
- {
- const float v[] = {x,y};
- return SetUniform(name, 2, v);
- }
- bool SetUniform4f(const char* name, float x, float y, float z, float w = 1)
- {
- const float v[] = {x,y,z,w};
- return SetUniform(name, 4, v);
- }
- bool SetUniformv(const char* name, const Vector3f& v)
- {
- const float a[] = {v.x,v.y,v.z,1};
- return SetUniform(name, 4, a);
- }
- bool SetUniform4fv(const char* name, int n, const Vector4f* v)
- {
- return SetUniform(name, 4*n, &v[0].x);
- }
- virtual bool SetUniform4x4f(const char* name, const Matrix4f& m)
- {
- Matrix4f mt = m.Transposed();
- return SetUniform(name, 16, &mt.M[0][0]);
- }
-};
-
-
-// Fill combines a ShaderSet (vertex, pixel) with textures, if any.
-// Every model has a fill.
-class ShaderFill : public RefCountBase<ShaderFill>
-{
- Ptr<ShaderSet> Shaders;
- Ptr<class Texture> Textures[8];
-
-public:
- ShaderFill(ShaderSet* sh) : Shaders(sh) { }
- ShaderFill(ShaderSet& sh) : Shaders(sh) { }
-
- ShaderSet* GetShaders() { return Shaders; }
-
- virtual void Set(PrimitiveType prim = Prim_Unknown) const;
- virtual void SetTexture(int i, class Texture* tex) { if (i < 8) Textures[i] = tex; }
-};
-
-
-// Buffer for vertex or index data. Some renderers require separate buffers, so that
-// is recommended. Some renderers cannot have high-performance buffers which are readable,
-// so reading in Map should not be relied on.
-//
-// Constraints on buffers, such as ReadOnly, are not enforced by the API but may result in
-// rendering-system dependent undesirable behavior, such as terrible performance or unreported failure.
-//
-// Use of a buffer inconsistent with usage is also not checked by the API, but it may result in bad
-// performance or even failure.
-//
-// Use the Data() function to set buffer data the first time, if possible (it may be faster).
-
-class Buffer : public RefCountBase<Buffer>
-{
-public:
- virtual ~Buffer() {}
-
- virtual size_t GetSize() = 0;
- virtual void* Map(size_t start, size_t size, int flags = 0) = 0;
- virtual bool Unmap(void *m) = 0;
-
- // Allocates a buffer, optionally filling it with data.
- virtual bool Data(int use, const void* buffer, size_t size) = 0;
-};
-
-class Texture : public RefCountBase<Texture>
-{
-public:
- virtual ~Texture() {}
-
- virtual int GetWidth() const = 0;
- virtual int GetHeight() const = 0;
- virtual int GetSamples() const { return 1; }
-
- virtual void SetSampleMode(int sm) = 0;
- virtual void Set(int slot, ShaderStage stage = Shader_Fragment) const = 0;
-};
-
-
-
-//-----------------------------------------------------------------------------------
-
-// Node is a base class for geometry in a Scene, it contains base position
-// and orientation data.
-// Model and Container both derive from it.
-//
-class Node : public RefCountBase<Node>
-{
- Vector3f Pos;
- Quatf Rot;
-
- mutable Matrix4f Mat;
- mutable bool MatCurrent;
-
-public:
- Node() : Pos(Vector3f(0)), MatCurrent(1) { }
- virtual ~Node() { }
-
- enum NodeType
- {
- Node_NonDisplay,
- Node_Container,
- Node_Model
- };
- virtual NodeType GetType() const { return Node_NonDisplay; }
-
- const Vector3f& GetPosition() const { return Pos; }
- const Quatf& GetOrientation() const { return Rot; }
- void SetPosition(Vector3f p) { Pos = p; MatCurrent = 0; }
- void SetOrientation(Quatf q) { Rot = q; MatCurrent = 0; }
-
- void Move(Vector3f p) { Pos += p; MatCurrent = 0; }
- void Rotate(Quatf q) { Rot = q * Rot; MatCurrent = 0; }
-
-
- // For testing only; causes Position an Orientation
- void SetMatrix(const Matrix4f& m)
- {
- MatCurrent = true;
- Mat = m;
- }
-
- const Matrix4f& GetMatrix() const
- {
- if (!MatCurrent)
- {
- Mat = Rot;
- Mat = Matrix4f::Translation(Pos) * Mat;
- MatCurrent = 1;
- }
- return Mat;
- }
-
- virtual void Render(const Matrix4f& ltw, RenderDevice* ren) { OVR_UNUSED2(ltw, ren); }
-};
-
-
-// Vertex type; same format is used for all shapes for simplicity.
-// Shapes are built by adding vertices to Model.
-struct Vertex
-{
- Vector3f Pos;
- Color C;
- float U, V;
- Vector3f Norm;
-
- Vertex (const Vector3f& p, const Color& c = Color(64,0,0,255),
- float u = 0, float v = 0, Vector3f n = Vector3f(1,0,0))
- : Pos(p), C(c), U(u), V(v), Norm(n)
- {}
- Vertex(float x, float y, float z, const Color& c = Color(64,0,0,255),
- float u = 0, float v = 0) : Pos(x,y,z), C(c), U(u), V(v)
- { }
-
- bool operator==(const Vertex& b) const
- {
- return Pos == b.Pos && C == b.C && U == b.U && V == b.V;
- }
-};
-
-// LightingParams are stored in a uniform buffer, don't change it without fixing all renderers
-// Scene contains a set of LightingParams that is uses for rendering.
-struct LightingParams
-{
- Vector4f Ambient;
- Vector4f LightPos[8];
- Vector4f LightColor[8];
- float LightCount;
- int Version;
-
- LightingParams() : LightCount(0), Version(0) {}
-
-
- void Update(const Matrix4f& view, const Vector4f* SceneLightPos)
- {
- Version++;
- for (int i = 0; i < LightCount; i++)
- {
- LightPos[i] = view.Transform(SceneLightPos[i]);
- }
- }
-
- void Set(ShaderSet* s) const
- {
- s->SetUniform4fv("Ambient", 1, &Ambient);
- s->SetUniform1f("LightCount", LightCount);
- s->SetUniform4fv("LightPos", (int)LightCount, LightPos);
- s->SetUniform4fv("LightColor", (int)LightCount, LightColor);
- }
-
-};
-
-//-----------------------------------------------------------------------------------
-
-// Model is a triangular mesh with a fill that can be added to scene.
-//
-class Model : public Node
-{
-public:
- Array<Vertex> Vertices;
- Array<UInt16> Indices;
- PrimitiveType Type;
- Ptr<ShaderFill> Fill;
- bool Visible;
-
- // Some renderers will create these if they didn't exist before rendering.
- // Currently they are not updated, so vertex data should not be changed after rendering.
- Ptr<Buffer> VertexBuffer;
- Ptr<Buffer> IndexBuffer;
-
- Model(PrimitiveType t = Prim_Triangles) : Type(t), Fill(NULL), Visible(true) { }
- ~Model() { }
-
- PrimitiveType GetPrimType() const { return Type; }
-
- void SetVisible(bool visible) { Visible = visible; }
- bool IsVisible() const { return Visible; }
-
-
- // Node implementation.
- virtual NodeType GetType() const { return Node_Model; }
- virtual void Render(const Matrix4f& ltw, RenderDevice* ren);
-
-
- // Returns the index next added vertex will have.
- UInt16 GetNextVertexIndex() const
- {
- return (UInt16)Vertices.GetSize();
- }
-
- UInt16 AddVertex(const Vertex& v)
- {
- assert(!VertexBuffer && !IndexBuffer);
- UInt16 index = (UInt16)Vertices.GetSize();
- Vertices.PushBack(v);
- return index;
- }
-
- void AddTriangle(UInt16 a, UInt16 b, UInt16 c)
- {
- Indices.PushBack(a);
- Indices.PushBack(b);
- Indices.PushBack(c);
- }
-
- // Uses texture coordinates for uniform world scaling (must use a repeat sampler).
- void AddSolidColorBox(float x1, float y1, float z1,
- float x2, float y2, float z2,
- Color c);
-};
-
-
-// Container stores a collection of rendering nodes (Models or other containers).
-class Container : public Node
-{
-public:
- Array<Ptr<Node> > Nodes;
-
- Container() { }
- ~Container() { }
-
- virtual NodeType GetType() const { return Node_Container; }
-
- virtual void Render(const Matrix4f& ltw, RenderDevice* ren);
-
- void Add(Node *n) { Nodes.PushBack(n); }
- void Clear() { Nodes.Clear(); }
-};
-
-
-// Scene combines a collection of model
-class Scene
-{
-public:
- Container World;
- Vector4f LightPos[8];
- LightingParams Lighting;
-
-public:
- void Render(RenderDevice* ren, const Matrix4f& view);
-
- void SetAmbient(Vector4f color)
- {
- Lighting.Ambient = color;
- }
-
- void AddLight(Vector3f pos, Vector4f color)
- {
- int n = (int)Lighting.LightCount;
- OVR_ASSERT(n < 8);
- LightPos[n] = pos;
- Lighting.LightColor[n] = color;
- Lighting.LightCount++;
- }
-
- void Clear()
- {
- World.Clear();
- Lighting.Ambient = Vector4f(0.0f, 0.0f, 0.0f, 0.0f);
- Lighting.LightCount = 0;
- }
- };
-
-
-//-----------------------------------------------------------------------------------
-
-// Post-processing type to apply to scene after rendering. PostProcess_Distortion
-// applied distortion as described by DistortionConfig.
-enum PostProcessType
-{
- PostProcess_None,
- PostProcess_Distortion
-};
-
-enum DisplayMode
-{
- Display_Window = 0,
- Display_Fullscreen = 1
-};
-
-
-// Rendering parameters used by RenderDevice::CreateDevice.
-struct RendererParams
-{
- int Multisample;
- int Fullscreen;
-
- // Windows - Monitor name for fullscreen mode.
- String MonitorName;
- // MacOS
- long DisplayId;
-
- RendererParams(int ms = 1) : Multisample(ms), Fullscreen(0) {}
-
- bool IsDisplaySet() const
- {
- return MonitorName.GetLength() || DisplayId;
- }
-};
-
-
-
-//-----------------------------------------------------------------------------------
-// ***** RenderDevice
-
-// Rendering device abstraction.
-// Provides platform-independent part of implementation, with platform-specific
-// part being in a separate derived class/file, such as D3D10::RenderDevice.
-//
-class RenderDevice : public RefCountBase<RenderDevice>
-{
-protected:
- int WindowWidth, WindowHeight;
- RendererParams Params;
- Viewport VP;
-
- Matrix4f Proj;
- Ptr<Buffer> pTextVertexBuffer;
-
- // For rendering with lens warping
- PostProcessType CurPostProcess;
- Ptr<Texture> pSceneColorTex; // Distortion render target, both eyes.
- int SceneColorTexW;
- int SceneColorTexH;
- Ptr<ShaderSet> pPostProcessShader;
- Ptr<Buffer> pFullScreenVertexBuffer;
- float SceneRenderScale;
- DistortionConfig Distortion;
-
- // For lighting on platforms with uniform buffers
- Ptr<Buffer> LightingBuffer;
-
- void FinishScene1();
-
-public:
- enum CompareFunc
- {
- Compare_Always = 0,
- Compare_Less = 1,
- Compare_Greater = 2,
- Compare_Count
- };
- RenderDevice();
- virtual ~RenderDevice() { Shutdown(); }
-
- // This static function is implemented in each derived class
- // to support a specific renderer type.
- //static RenderDevice* CreateDevice(const RendererParams& rp, void* oswnd);
-
-
- virtual void Init() {}
- virtual void Shutdown() {}
- virtual bool SetParams(const RendererParams&) { return 0; }
-
- const RendererParams& GetParams() const { return Params; }
-
-
- // StereoParams apply Viewport, Projection and Distortion simultaneously,
- // doing full configuration for one eye.
- void ApplyStereoParams(const StereoEyeParams& params)
- {
- SetViewport(params.VP);
- SetProjection(params.Projection);
- if (params.pDistortion)
- SetDistortionConfig(*params.pDistortion, params.Eye);
- }
-
- virtual void SetViewport(const Viewport& vp);
- void SetViewport(int x, int y, int w, int h) { SetViewport(Viewport(x,y,w,h)); }
-
- // PostProcess distortion
- void SetSceneRenderScale(float ss);
-
- void SetDistortionConfig(const DistortionConfig& config, StereoEye eye = StereoEye_Left)
- {
- Distortion = config;
- if (eye == StereoEye_Right)
- Distortion.XCenterOffset = -Distortion.XCenterOffset;
- }
-
- // Set viewport ignoring any adjustments used for the stereo mode.
- virtual void SetRealViewport(const Viewport& vp) = 0;
-
- virtual void Clear(float r = 0, float g = 0, float b = 0, float a = 1, float depth = 1) = 0;
-
- virtual bool IsFullscreen() const { return Params.Fullscreen != Display_Window; }
- virtual void Present() = 0;
- // Waits for rendering to complete; important for reducing latency.
- virtual void ForceFlushGPU() { }
-
- // Resources
- virtual Buffer* CreateBuffer() { return NULL; }
- virtual Texture* CreateTexture(int format, int width, int height, const void* data, int mipcount=1)
- { OVR_UNUSED5(format,width,height,data, mipcount); return NULL; }
-
-
- virtual ShaderSet* CreateShaderSet() { return new ShaderSet; }
- virtual Shader* LoadBuiltinShader(ShaderStage stage, int shader) = 0;
-
- // Rendering
-
- // Begin drawing directly to the currently selected render target, no post-processing.
- virtual void BeginRendering() {}
- // Begin drawing the primary scene. This will have post-processing applied (if enabled)
- // during FinishScene.
- virtual void BeginScene(PostProcessType pp = PostProcess_None);
- // Postprocess the scene and return to the screen render target.
- virtual void FinishScene();
-
- // Texture must have been created with Texture_RenderTarget. Use NULL for the default render target.
- // NULL depth buffer means use an internal, temporary one.
- virtual void SetRenderTarget(Texture* color, Texture* depth = NULL, Texture* stencil = NULL)
- { OVR_UNUSED3(color, depth, stencil); }
- virtual void SetDepthMode(bool enable, bool write, CompareFunc func = Compare_Less) = 0;
- virtual void SetProjection(const Matrix4f& proj);
- virtual void SetWorldUniforms(const Matrix4f& proj) = 0;
-
- // The data is not copied, it must remain valid until the end of the frame
- virtual void SetLighting(const LightingParams* light);
-
- // The index 0 is reserved for non-buffer uniforms, and so cannot be used with this function.
- virtual void SetCommonUniformBuffer(int i, Buffer* buffer) { OVR_UNUSED2(i, buffer); }
-
- virtual Matrix4f GetProjection() const { return Proj; }
-
- // This is a View matrix only, it will be combined with the projection matrix from SetProjection
- virtual void Render(const Matrix4f& matrix, Model* model) = 0;
- // offset is in bytes; indices can be null.
- virtual void Render(const ShaderFill* fill, Buffer* vertices, Buffer* indices,
- const Matrix4f& matrix, int offset, int count, PrimitiveType prim = Prim_Triangles) = 0;
-
- virtual ShaderFill *CreateSimpleFill() = 0;
- ShaderFill * CreateTextureFill(Texture* tex);
-
-
- // Don't call these directly, use App/Platform instead
- virtual bool SetFullscreen(DisplayMode fullscreen) { OVR_UNUSED(fullscreen); return false; }
-
-
- enum PostProcessShader
- {
- PostProcessShader_Distortion = 0,
- PostProcessShader_DistortionAndChromAb = 1,
- PostProcessShader_Count
- };
-
- PostProcessShader GetPostProcessShader()
- {
- return PostProcessShaderActive;
- }
-
- void SetPostProcessShader(PostProcessShader newShader)
- {
- PostProcessShaderRequested = newShader;
- }
-
-protected:
- // Stereo & post-processing
- virtual bool initPostProcessSupport(PostProcessType pptype);
-
-private:
- PostProcessShader PostProcessShaderRequested;
- PostProcessShader PostProcessShaderActive;
-};
-
-int GetNumMipLevels(int w, int h);
-
-// Filter an rgba image with a 2x2 box filter, for mipmaps.
-// Image size must be a power of 2.
-void FilterRgba2x2(const UByte* src, int w, int h, UByte* dest);
-
-}} // OVR::RenderTiny
-
-#endif
+/************************************************************************************
+
+Filename : RenderTiny_Device.h
+Content : Minimal possible renderer for RoomTiny sample
+Created : September 6, 2012
+Authors : Andrew Reisse, Michael Antonov
+
+Copyright : Copyright 2012 Oculus VR, Inc. All Rights reserved.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+************************************************************************************/
+
+#ifndef OVR_RenderTiny_Device_h
+#define OVR_RenderTiny_Device_h
+
+#include "Kernel/OVR_Math.h"
+#include "Kernel/OVR_Array.h"
+#include "Kernel/OVR_RefCount.h"
+#include "Kernel/OVR_String.h"
+#include "Kernel/OVR_File.h"
+#include "Kernel/OVR_Color.h"
+
+#include "Util/Util_Render_Stereo.h"
+
+namespace OVR { namespace RenderTiny {
+
+using namespace OVR::Util::Render;
+
+class RenderDevice;
+
+
+//-----------------------------------------------------------------------------------
+
+// Rendering primitive type used to render Model.
+enum PrimitiveType
+{
+ Prim_Triangles,
+ Prim_Lines,
+ Prim_TriangleStrip,
+ Prim_Unknown,
+ Prim_Count
+};
+
+// Types of shaders taht can be stored together in a ShaderSet.
+enum ShaderStage
+{
+ Shader_Vertex = 0,
+ Shader_Fragment = 2,
+ Shader_Pixel = 2,
+ Shader_Count = 3,
+};
+
+// Built-in shader types; used by LoadBuiltinShader.
+enum BuiltinShaders
+{
+ VShader_MV = 0,
+ VShader_MVP = 1,
+ VShader_PostProcess = 2,
+ VShader_Count = 3,
+
+ FShader_Solid = 0,
+ FShader_Gouraud = 1,
+ FShader_Texture = 2,
+ FShader_PostProcess = 3,
+ FShader_PostProcessWithChromAb = 4,
+ FShader_LitGouraud = 5,
+ FShader_LitTexture = 6,
+ FShader_Count
+};
+
+
+enum MapFlags
+{
+ Map_Discard = 1,
+ Map_Read = 2, // do not use
+ Map_Unsynchronized = 4, // like D3D11_MAP_NO_OVERWRITE
+};
+
+// Buffer types used for uploading geometry & constants.
+enum BufferUsage
+{
+ Buffer_Unknown = 0,
+ Buffer_Vertex = 1,
+ Buffer_Index = 2,
+ Buffer_Uniform = 4,
+ Buffer_TypeMask = 0xff,
+ Buffer_ReadOnly = 0x100, // Buffer must be created with Data().
+};
+
+enum TextureFormat
+{
+ Texture_RGBA = 0x0100,
+ Texture_Depth = 0x8000,
+ Texture_TypeMask = 0xff00,
+ Texture_SamplesMask = 0x00ff,
+ Texture_RenderTarget = 0x10000,
+ Texture_GenMipmaps = 0x20000,
+};
+
+// Texture sampling modes.
+enum SampleMode
+{
+ Sample_Linear = 0,
+ Sample_Nearest = 1,
+ Sample_Anisotropic = 2,
+ Sample_FilterMask = 3,
+
+ Sample_Repeat = 0,
+ Sample_Clamp = 4,
+ Sample_ClampBorder = 8, // If unsupported Clamp is used instead.
+ Sample_AddressMask =12,
+
+ Sample_Count =13,
+};
+
+// A vector with a dummy w component for alignment in uniform buffers (and for float colors).
+// The w component is not used in any calculations.
+struct Vector4f : public Vector3f
+{
+ float w;
+
+ Vector4f() : w(1) {}
+ Vector4f(const Vector3f& v) : Vector3f(v), w(1) {}
+ Vector4f(float r, float g, float b, float a) : Vector3f(r,g,b), w(a) {}
+};
+
+
+// Base class for vertex and pixel shaders. Stored in ShaderSet.
+class Shader : public RefCountBase<Shader>
+{
+ friend class ShaderSet;
+
+protected:
+ ShaderStage Stage;
+
+public:
+ Shader(ShaderStage s) : Stage(s) {}
+ virtual ~Shader() {}
+
+ ShaderStage GetStage() const { return Stage; }
+
+ virtual void Set(PrimitiveType) const { }
+ virtual void SetUniformBuffer(class Buffer* buffers, int i = 0) { OVR_UNUSED2(buffers, i); }
+
+protected:
+ virtual bool SetUniform(const char* name, int n, const float* v) { OVR_UNUSED3(name, n, v); return false; }
+};
+
+
+// A group of shaders, one per stage.
+// A ShaderSet is applied to a RenderDevice for rendering with a given fill.
+class ShaderSet : public RefCountBase<ShaderSet>
+{
+ protected:
+ Ptr<Shader> Shaders[Shader_Count];
+
+public:
+ ShaderSet() { }
+ ~ShaderSet() { }
+
+ virtual void SetShader(Shader *s)
+ {
+ Shaders[s->GetStage()] = s;
+ }
+ virtual void UnsetShader(int stage)
+ {
+ Shaders[stage] = NULL;
+ }
+ Shader* GetShader(int stage) { return Shaders[stage]; }
+
+ virtual void Set(PrimitiveType prim) const
+ {
+ for (int i = 0; i < Shader_Count; i++)
+ if (Shaders[i])
+ Shaders[i]->Set(prim);
+ }
+
+ // Set a uniform (other than the standard matrices). It is undefined whether the
+ // uniforms from one shader occupy the same space as those in other shaders
+ // (unless a buffer is used, then each buffer is independent).
+ virtual bool SetUniform(const char* name, int n, const float* v)
+ {
+ bool result = 0;
+ for (int i = 0; i < Shader_Count; i++)
+ if (Shaders[i])
+ result |= Shaders[i]->SetUniform(name, n, v);
+
+ return result;
+ }
+ bool SetUniform1f(const char* name, float x)
+ {
+ const float v[] = {x};
+ return SetUniform(name, 1, v);
+ }
+ bool SetUniform2f(const char* name, float x, float y)
+ {
+ const float v[] = {x,y};
+ return SetUniform(name, 2, v);
+ }
+ bool SetUniform4f(const char* name, float x, float y, float z, float w = 1)
+ {
+ const float v[] = {x,y,z,w};
+ return SetUniform(name, 4, v);
+ }
+ bool SetUniformv(const char* name, const Vector3f& v)
+ {
+ const float a[] = {v.x,v.y,v.z,1};
+ return SetUniform(name, 4, a);
+ }
+ bool SetUniform4fv(const char* name, int n, const Vector4f* v)
+ {
+ return SetUniform(name, 4*n, &v[0].x);
+ }
+ virtual bool SetUniform4x4f(const char* name, const Matrix4f& m)
+ {
+ Matrix4f mt = m.Transposed();
+ return SetUniform(name, 16, &mt.M[0][0]);
+ }
+};
+
+
+// Fill combines a ShaderSet (vertex, pixel) with textures, if any.
+// Every model has a fill.
+class ShaderFill : public RefCountBase<ShaderFill>
+{
+ Ptr<ShaderSet> Shaders;
+ Ptr<class Texture> Textures[8];
+
+public:
+ ShaderFill(ShaderSet* sh) : Shaders(sh) { }
+ ShaderFill(ShaderSet& sh) : Shaders(sh) { }
+
+ ShaderSet* GetShaders() { return Shaders; }
+
+ virtual void Set(PrimitiveType prim = Prim_Unknown) const;
+ virtual void SetTexture(int i, class Texture* tex) { if (i < 8) Textures[i] = tex; }
+};
+
+
+// Buffer for vertex or index data. Some renderers require separate buffers, so that
+// is recommended. Some renderers cannot have high-performance buffers which are readable,
+// so reading in Map should not be relied on.
+//
+// Constraints on buffers, such as ReadOnly, are not enforced by the API but may result in
+// rendering-system dependent undesirable behavior, such as terrible performance or unreported failure.
+//
+// Use of a buffer inconsistent with usage is also not checked by the API, but it may result in bad
+// performance or even failure.
+//
+// Use the Data() function to set buffer data the first time, if possible (it may be faster).
+
+class Buffer : public RefCountBase<Buffer>
+{
+public:
+ virtual ~Buffer() {}
+
+ virtual size_t GetSize() = 0;
+ virtual void* Map(size_t start, size_t size, int flags = 0) = 0;
+ virtual bool Unmap(void *m) = 0;
+
+ // Allocates a buffer, optionally filling it with data.
+ virtual bool Data(int use, const void* buffer, size_t size) = 0;
+};
+
+class Texture : public RefCountBase<Texture>
+{
+public:
+ virtual ~Texture() {}
+
+ virtual int GetWidth() const = 0;
+ virtual int GetHeight() const = 0;
+ virtual int GetSamples() const { return 1; }
+
+ virtual void SetSampleMode(int sm) = 0;
+ virtual void Set(int slot, ShaderStage stage = Shader_Fragment) const = 0;
+};
+
+
+
+//-----------------------------------------------------------------------------------
+
+// Node is a base class for geometry in a Scene, it contains base position
+// and orientation data.
+// Model and Container both derive from it.
+//
+class Node : public RefCountBase<Node>
+{
+ Vector3f Pos;
+ Quatf Rot;
+
+ mutable Matrix4f Mat;
+ mutable bool MatCurrent;
+
+public:
+ Node() : Pos(Vector3f(0)), MatCurrent(1) { }
+ virtual ~Node() { }
+
+ enum NodeType
+ {
+ Node_NonDisplay,
+ Node_Container,
+ Node_Model
+ };
+ virtual NodeType GetType() const { return Node_NonDisplay; }
+
+ const Vector3f& GetPosition() const { return Pos; }
+ const Quatf& GetOrientation() const { return Rot; }
+ void SetPosition(Vector3f p) { Pos = p; MatCurrent = 0; }
+ void SetOrientation(Quatf q) { Rot = q; MatCurrent = 0; }
+
+ void Move(Vector3f p) { Pos += p; MatCurrent = 0; }
+ void Rotate(Quatf q) { Rot = q * Rot; MatCurrent = 0; }
+
+
+ // For testing only; causes Position an Orientation
+ void SetMatrix(const Matrix4f& m)
+ {
+ MatCurrent = true;
+ Mat = m;
+ }
+
+ const Matrix4f& GetMatrix() const
+ {
+ if (!MatCurrent)
+ {
+ Mat = Rot;
+ Mat = Matrix4f::Translation(Pos) * Mat;
+ MatCurrent = 1;
+ }
+ return Mat;
+ }
+
+ virtual void Render(const Matrix4f& ltw, RenderDevice* ren) { OVR_UNUSED2(ltw, ren); }
+};
+
+
+// Vertex type; same format is used for all shapes for simplicity.
+// Shapes are built by adding vertices to Model.
+struct Vertex
+{
+ Vector3f Pos;
+ Color C;
+ float U, V;
+ Vector3f Norm;
+
+ Vertex (const Vector3f& p, const Color& c = Color(64,0,0,255),
+ float u = 0, float v = 0, Vector3f n = Vector3f(1,0,0))
+ : Pos(p), C(c), U(u), V(v), Norm(n)
+ {}
+ Vertex(float x, float y, float z, const Color& c = Color(64,0,0,255),
+ float u = 0, float v = 0) : Pos(x,y,z), C(c), U(u), V(v)
+ { }
+
+ bool operator==(const Vertex& b) const
+ {
+ return Pos == b.Pos && C == b.C && U == b.U && V == b.V;
+ }
+};
+
+// LightingParams are stored in a uniform buffer, don't change it without fixing all renderers
+// Scene contains a set of LightingParams that is uses for rendering.
+struct LightingParams
+{
+ Vector4f Ambient;
+ Vector4f LightPos[8];
+ Vector4f LightColor[8];
+ float LightCount;
+ int Version;
+
+ LightingParams() : LightCount(0), Version(0) {}
+
+
+ void Update(const Matrix4f& view, const Vector4f* SceneLightPos)
+ {
+ Version++;
+ for (int i = 0; i < LightCount; i++)
+ {
+ LightPos[i] = view.Transform(SceneLightPos[i]);
+ }
+ }
+
+ void Set(ShaderSet* s) const
+ {
+ s->SetUniform4fv("Ambient", 1, &Ambient);
+ s->SetUniform1f("LightCount", LightCount);
+ s->SetUniform4fv("LightPos", (int)LightCount, LightPos);
+ s->SetUniform4fv("LightColor", (int)LightCount, LightColor);
+ }
+
+};
+
+//-----------------------------------------------------------------------------------
+
+// Model is a triangular mesh with a fill that can be added to scene.
+//
+class Model : public Node
+{
+public:
+ Array<Vertex> Vertices;
+ Array<UInt16> Indices;
+ PrimitiveType Type;
+ Ptr<ShaderFill> Fill;
+ bool Visible;
+
+ // Some renderers will create these if they didn't exist before rendering.
+ // Currently they are not updated, so vertex data should not be changed after rendering.
+ Ptr<Buffer> VertexBuffer;
+ Ptr<Buffer> IndexBuffer;
+
+ Model(PrimitiveType t = Prim_Triangles) : Type(t), Fill(NULL), Visible(true) { }
+ ~Model() { }
+
+ PrimitiveType GetPrimType() const { return Type; }
+
+ void SetVisible(bool visible) { Visible = visible; }
+ bool IsVisible() const { return Visible; }
+
+
+ // Node implementation.
+ virtual NodeType GetType() const { return Node_Model; }
+ virtual void Render(const Matrix4f& ltw, RenderDevice* ren);
+
+
+ // Returns the index next added vertex will have.
+ UInt16 GetNextVertexIndex() const
+ {
+ return (UInt16)Vertices.GetSize();
+ }
+
+ UInt16 AddVertex(const Vertex& v)
+ {
+ assert(!VertexBuffer && !IndexBuffer);
+ UInt16 index = (UInt16)Vertices.GetSize();
+ Vertices.PushBack(v);
+ return index;
+ }
+
+ void AddTriangle(UInt16 a, UInt16 b, UInt16 c)
+ {
+ Indices.PushBack(a);
+ Indices.PushBack(b);
+ Indices.PushBack(c);
+ }
+
+ // Uses texture coordinates for uniform world scaling (must use a repeat sampler).
+ void AddSolidColorBox(float x1, float y1, float z1,
+ float x2, float y2, float z2,
+ Color c);
+};
+
+
+// Container stores a collection of rendering nodes (Models or other containers).
+class Container : public Node
+{
+public:
+ Array<Ptr<Node> > Nodes;
+
+ Container() { }
+ ~Container() { }
+
+ virtual NodeType GetType() const { return Node_Container; }
+
+ virtual void Render(const Matrix4f& ltw, RenderDevice* ren);
+
+ void Add(Node *n) { Nodes.PushBack(n); }
+ void Clear() { Nodes.Clear(); }
+};
+
+
+// Scene combines a collection of model
+class Scene
+{
+public:
+ Container World;
+ Vector4f LightPos[8];
+ LightingParams Lighting;
+
+public:
+ void Render(RenderDevice* ren, const Matrix4f& view);
+
+ void SetAmbient(Vector4f color)
+ {
+ Lighting.Ambient = color;
+ }
+
+ void AddLight(Vector3f pos, Vector4f color)
+ {
+ int n = (int)Lighting.LightCount;
+ OVR_ASSERT(n < 8);
+ LightPos[n] = pos;
+ Lighting.LightColor[n] = color;
+ Lighting.LightCount++;
+ }
+
+ void Clear()
+ {
+ World.Clear();
+ Lighting.Ambient = Vector4f(0.0f, 0.0f, 0.0f, 0.0f);
+ Lighting.LightCount = 0;
+ }
+ };
+
+
+//-----------------------------------------------------------------------------------
+
+// Post-processing type to apply to scene after rendering. PostProcess_Distortion
+// applied distortion as described by DistortionConfig.
+enum PostProcessType
+{
+ PostProcess_None,
+ PostProcess_Distortion
+};
+
+enum DisplayMode
+{
+ Display_Window = 0,
+ Display_Fullscreen = 1
+};
+
+
+// Rendering parameters used by RenderDevice::CreateDevice.
+struct RendererParams
+{
+ int Multisample;
+ int Fullscreen;
+
+ // Windows - Monitor name for fullscreen mode.
+ String MonitorName;
+ // MacOS
+ long DisplayId;
+
+ RendererParams(int ms = 1) : Multisample(ms), Fullscreen(0) {}
+
+ bool IsDisplaySet() const
+ {
+ return MonitorName.GetLength() || DisplayId;
+ }
+};
+
+
+
+//-----------------------------------------------------------------------------------
+// ***** RenderDevice
+
+// Rendering device abstraction.
+// Provides platform-independent part of implementation, with platform-specific
+// part being in a separate derived class/file, such as D3D10::RenderDevice.
+//
+class RenderDevice : public RefCountBase<RenderDevice>
+{
+protected:
+ int WindowWidth, WindowHeight;
+ RendererParams Params;
+ Viewport VP;
+
+ Matrix4f Proj;
+ Ptr<Buffer> pTextVertexBuffer;
+
+ // For rendering with lens warping
+ PostProcessType CurPostProcess;
+ Ptr<Texture> pSceneColorTex; // Distortion render target, both eyes.
+ int SceneColorTexW;
+ int SceneColorTexH;
+ Ptr<ShaderSet> pPostProcessShader;
+ Ptr<Buffer> pFullScreenVertexBuffer;
+ float SceneRenderScale;
+ DistortionConfig Distortion;
+
+ // For lighting on platforms with uniform buffers
+ Ptr<Buffer> LightingBuffer;
+
+ void FinishScene1();
+
+public:
+ enum CompareFunc
+ {
+ Compare_Always = 0,
+ Compare_Less = 1,
+ Compare_Greater = 2,
+ Compare_Count
+ };
+ RenderDevice();
+ virtual ~RenderDevice() { Shutdown(); }
+
+ // This static function is implemented in each derived class
+ // to support a specific renderer type.
+ //static RenderDevice* CreateDevice(const RendererParams& rp, void* oswnd);
+
+
+ virtual void Init() {}
+ virtual void Shutdown() {}
+ virtual bool SetParams(const RendererParams&) { return 0; }
+
+ const RendererParams& GetParams() const { return Params; }
+
+
+ // StereoParams apply Viewport, Projection and Distortion simultaneously,
+ // doing full configuration for one eye.
+ void ApplyStereoParams(const StereoEyeParams& params)
+ {
+ SetViewport(params.VP);
+ SetProjection(params.Projection);
+ if (params.pDistortion)
+ SetDistortionConfig(*params.pDistortion, params.Eye);
+ }
+
+ virtual void SetViewport(const Viewport& vp);
+ void SetViewport(int x, int y, int w, int h) { SetViewport(Viewport(x,y,w,h)); }
+
+ // PostProcess distortion
+ void SetSceneRenderScale(float ss);
+
+ void SetDistortionConfig(const DistortionConfig& config, StereoEye eye = StereoEye_Left)
+ {
+ Distortion = config;
+ if (eye == StereoEye_Right)
+ Distortion.XCenterOffset = -Distortion.XCenterOffset;
+ }
+
+ // Set viewport ignoring any adjustments used for the stereo mode.
+ virtual void SetRealViewport(const Viewport& vp) = 0;
+
+ virtual void Clear(float r = 0, float g = 0, float b = 0, float a = 1, float depth = 1) = 0;
+
+ virtual bool IsFullscreen() const { return Params.Fullscreen != Display_Window; }
+ virtual void Present() = 0;
+ // Waits for rendering to complete; important for reducing latency.
+ virtual void ForceFlushGPU() { }
+
+ // Resources
+ virtual Buffer* CreateBuffer() { return NULL; }
+ virtual Texture* CreateTexture(int format, int width, int height, const void* data, int mipcount=1)
+ { OVR_UNUSED5(format,width,height,data, mipcount); return NULL; }
+
+
+ virtual ShaderSet* CreateShaderSet() { return new ShaderSet; }
+ virtual Shader* LoadBuiltinShader(ShaderStage stage, int shader) = 0;
+
+ // Rendering
+
+ // Begin drawing directly to the currently selected render target, no post-processing.
+ virtual void BeginRendering() {}
+ // Begin drawing the primary scene. This will have post-processing applied (if enabled)
+ // during FinishScene.
+ virtual void BeginScene(PostProcessType pp = PostProcess_None);
+ // Postprocess the scene and return to the screen render target.
+ virtual void FinishScene();
+
+ // Texture must have been created with Texture_RenderTarget. Use NULL for the default render target.
+ // NULL depth buffer means use an internal, temporary one.
+ virtual void SetRenderTarget(Texture* color, Texture* depth = NULL, Texture* stencil = NULL)
+ { OVR_UNUSED3(color, depth, stencil); }
+ virtual void SetDepthMode(bool enable, bool write, CompareFunc func = Compare_Less) = 0;
+ virtual void SetProjection(const Matrix4f& proj);
+ virtual void SetWorldUniforms(const Matrix4f& proj) = 0;
+
+ // The data is not copied, it must remain valid until the end of the frame
+ virtual void SetLighting(const LightingParams* light);
+
+ // The index 0 is reserved for non-buffer uniforms, and so cannot be used with this function.
+ virtual void SetCommonUniformBuffer(int i, Buffer* buffer) { OVR_UNUSED2(i, buffer); }
+
+ virtual Matrix4f GetProjection() const { return Proj; }
+
+ // This is a View matrix only, it will be combined with the projection matrix from SetProjection
+ virtual void Render(const Matrix4f& matrix, Model* model) = 0;
+ // offset is in bytes; indices can be null.
+ virtual void Render(const ShaderFill* fill, Buffer* vertices, Buffer* indices,
+ const Matrix4f& matrix, int offset, int count, PrimitiveType prim = Prim_Triangles) = 0;
+
+ virtual ShaderFill *CreateSimpleFill() = 0;
+ ShaderFill * CreateTextureFill(Texture* tex);
+
+
+ // Don't call these directly, use App/Platform instead
+ virtual bool SetFullscreen(DisplayMode fullscreen) { OVR_UNUSED(fullscreen); return false; }
+
+
+ enum PostProcessShader
+ {
+ PostProcessShader_Distortion = 0,
+ PostProcessShader_DistortionAndChromAb = 1,
+ PostProcessShader_Count
+ };
+
+ PostProcessShader GetPostProcessShader()
+ {
+ return PostProcessShaderActive;
+ }
+
+ void SetPostProcessShader(PostProcessShader newShader)
+ {
+ PostProcessShaderRequested = newShader;
+ }
+
+protected:
+ // Stereo & post-processing
+ virtual bool initPostProcessSupport(PostProcessType pptype);
+
+private:
+ PostProcessShader PostProcessShaderRequested;
+ PostProcessShader PostProcessShaderActive;
+};
+
+int GetNumMipLevels(int w, int h);
+
+// Filter an rgba image with a 2x2 box filter, for mipmaps.
+// Image size must be a power of 2.
+void FilterRgba2x2(const UByte* src, int w, int h, UByte* dest);
+
+}} // OVR::RenderTiny
+
+#endif
diff --git a/Samples/OculusRoomTiny/RenderTiny_GL_Device.cpp b/Samples/OculusRoomTiny/RenderTiny_GL_Device.cpp
index 197c62a..07460c3 100644
--- a/Samples/OculusRoomTiny/RenderTiny_GL_Device.cpp
+++ b/Samples/OculusRoomTiny/RenderTiny_GL_Device.cpp
@@ -1,784 +1,784 @@
-/************************************************************************************
-
-Filename : RenderTiny_GL_Device.cpp
-Content : RenderDevice implementation for OpenGL (tiny version)
-Created : September 10, 2012
-Authors : Andrew Reisse, Artem Bolgar
-
-Copyright : Copyright 2012 Oculus VR, Inc. All Rights reserved.
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-
-************************************************************************************/
-
-#include "RenderTiny_GL_Device.h"
-#include "Kernel/OVR_Log.h"
-
-namespace OVR { namespace RenderTiny { namespace GL {
-
-
-
-static const char* StdVertexShaderSrc =
- "uniform mat4 Proj;\n"
- "uniform mat4 View;\n"
- "attribute vec4 Position;\n"
- "attribute vec4 Color;\n"
- "attribute vec2 TexCoord;\n"
- "attribute vec3 Normal;\n"
- "varying vec4 oColor;\n"
- "varying vec2 oTexCoord;\n"
- "varying vec3 oNormal;\n"
- "varying vec3 oVPos;\n"
- "void main()\n"
- "{\n"
- " gl_Position = Proj * (View * Position);\n"
- " oNormal = vec3(View * vec4(Normal,0));\n"
- " oVPos = vec3(View * Position);\n"
- " oTexCoord = TexCoord;\n"
- " oColor = Color;\n"
- "}\n";
-
-static const char* DirectVertexShaderSrc =
- "uniform mat4 View;\n"
- "attribute vec4 Position;\n"
- "attribute vec4 Color;\n"
- "attribute vec2 TexCoord;\n"
- "attribute vec3 Normal;\n"
- "varying vec4 oColor;\n"
- "varying vec2 oTexCoord;\n"
- "varying vec3 oNormal;\n"
- "void main()\n"
- "{\n"
- " gl_Position = View * Position;\n"
- " oTexCoord = TexCoord;\n"
- " oColor = Color;\n"
- " oNormal = vec3(View * vec4(Normal,0));\n"
- "}\n";
-
-static const char* SolidFragShaderSrc =
- "uniform vec4 Color;\n"
- "void main()\n"
- "{\n"
- " gl_FragColor = Color;\n"
- "}\n";
-
-static const char* GouraudFragShaderSrc =
- "varying vec4 oColor;\n"
- "void main()\n"
- "{\n"
- " gl_FragColor = oColor;\n"
- "}\n";
-
-static const char* TextureFragShaderSrc =
- "uniform sampler2D Texture0;\n"
- "varying vec4 oColor;\n"
- "varying vec2 oTexCoord;\n"
- "void main()\n"
- "{\n"
- " gl_FragColor = oColor * texture2D(Texture0, oTexCoord);\n"
- " if (gl_FragColor.a < 0.4)\n"
- " discard;\n"
- "}\n";
-
-#define LIGHTING_COMMON \
- "uniform vec3 Ambient;\n" \
- "uniform vec4 LightPos[8];\n" \
- "uniform vec4 LightColor[8];\n" \
- "uniform float LightCount;\n" \
- "varying vec4 oColor;\n" \
- "varying vec2 oTexCoord;\n" \
- "varying vec3 oNormal;\n" \
- "varying vec3 oVPos;\n" \
- "vec4 DoLight()\n" \
- "{\n" \
- " vec3 norm = normalize(oNormal);\n" \
- " vec3 light = Ambient;\n" \
- " for (int i = 0; i < int(LightCount); i++)\n" \
- " {\n" \
- " vec3 ltp = (LightPos[i].xyz - oVPos);\n" \
- " float ldist = length(ltp);\n" \
- " ltp = normalize(ltp);\n" \
- " light += clamp(LightColor[i].rgb * oColor.rgb * (dot(norm, ltp) / ldist), 0.0,1.0);\n" \
- " }\n" \
- " return vec4(light, oColor.a);\n" \
- "}\n"
-
-static const char* LitSolidFragShaderSrc =
- LIGHTING_COMMON
- "void main()\n"
- "{\n"
- " gl_FragColor = DoLight() * oColor;\n"
- "}\n";
-
-static const char* LitTextureFragShaderSrc =
- "uniform sampler2D Texture0;\n"
- LIGHTING_COMMON
- "void main()\n"
- "{\n"
- " gl_FragColor = DoLight() * texture2D(Texture0, oTexCoord);\n"
- "}\n";
-
-static const char* PostProcessVertexShaderSrc =
- "uniform mat4 View;\n"
- "uniform mat4 Texm;\n"
- "attribute vec4 Position;\n"
- "attribute vec2 TexCoord;\n"
- "varying vec2 oTexCoord;\n"
- "void main()\n"
- "{\n"
- " gl_Position = View * Position;\n"
- " oTexCoord = vec2(Texm * vec4(TexCoord,0,1));\n"
- " oTexCoord.y = 1.0-oTexCoord.y;\n"
- "}\n";
-
-static const char* PostProcessFragShaderSrc =
- "uniform vec2 LensCenter;\n"
- "uniform vec2 ScreenCenter;\n"
- "uniform vec2 Scale;\n"
- "uniform vec2 ScaleIn;\n"
- "uniform vec4 HmdWarpParam;\n"
- "uniform sampler2D Texture0;\n"
- "varying vec2 oTexCoord;\n"
- "\n"
- "vec2 HmdWarp(vec2 in01)\n"
- "{\n"
- " vec2 theta = (in01 - LensCenter) * ScaleIn;\n" // Scales to [-1, 1]
- " float rSq = theta.x * theta.x + theta.y * theta.y;\n"
- " vec2 theta1 = theta * (HmdWarpParam.x + HmdWarpParam.y * rSq + "
- " HmdWarpParam.z * rSq * rSq + HmdWarpParam.w * rSq * rSq * rSq);\n"
- " return LensCenter + Scale * theta1;\n"
- "}\n"
- "void main()\n"
- "{\n"
- " vec2 tc = HmdWarp(oTexCoord);\n"
- " if (!all(equal(clamp(tc, ScreenCenter-vec2(0.25,0.5), ScreenCenter+vec2(0.25,0.5)), tc)))\n"
- " gl_FragColor = vec4(0);\n"
- " else\n"
- " gl_FragColor = texture2D(Texture0, tc);\n"
- "}\n";
-
-// Shader with lens distortion and chromatic aberration correction.
-static const char* PostProcessFullFragShaderSrc =
- "uniform vec2 LensCenter;\n"
- "uniform vec2 ScreenCenter;\n"
- "uniform vec2 Scale;\n"
- "uniform vec2 ScaleIn;\n"
- "uniform vec4 HmdWarpParam;\n"
- "uniform vec4 ChromAbParam;\n"
- "uniform sampler2D Texture0;\n"
- "varying vec2 oTexCoord;\n"
- "\n"
- // Scales input texture coordinates for distortion.
- // ScaleIn maps texture coordinates to Scales to ([-1, 1]), although top/bottom will be
- // larger due to aspect ratio.
- "void main()\n"
- "{\n"
- " vec2 theta = (oTexCoord - LensCenter) * ScaleIn;\n" // Scales to [-1, 1]
- " float rSq= theta.x * theta.x + theta.y * theta.y;\n"
- " vec2 theta1 = theta * (HmdWarpParam.x + HmdWarpParam.y * rSq + "
- " HmdWarpParam.z * rSq * rSq + HmdWarpParam.w * rSq * rSq * rSq);\n"
- " \n"
- " // Detect whether blue texture coordinates are out of range since these will scaled out the furthest.\n"
- " vec2 thetaBlue = theta1 * (ChromAbParam.z + ChromAbParam.w * rSq);\n"
- " vec2 tcBlue = LensCenter + Scale * thetaBlue;\n"
- " if (!all(equal(clamp(tcBlue, ScreenCenter-vec2(0.25,0.5), ScreenCenter+vec2(0.25,0.5)), tcBlue)))\n"
- " {\n"
- " gl_FragColor = vec4(0);\n"
- " return;\n"
- " }\n"
- " \n"
- " // Now do blue texture lookup.\n"
- " float blue = texture2D(Texture0, tcBlue).b;\n"
- " \n"
- " // Do green lookup (no scaling).\n"
- " vec2 tcGreen = LensCenter + Scale * theta1;\n"
- " vec4 center = texture2D(Texture0, tcGreen);\n"
- " \n"
- " // Do red scale and lookup.\n"
- " vec2 thetaRed = theta1 * (ChromAbParam.x + ChromAbParam.y * rSq);\n"
- " vec2 tcRed = LensCenter + Scale * thetaRed;\n"
- " float red = texture2D(Texture0, tcRed).r;\n"
- " \n"
- " gl_FragColor = vec4(red, center.g, blue, 1);\n"
- "}\n";
-
-static const char* VShaderSrcs[VShader_Count] =
-{
- DirectVertexShaderSrc,
- StdVertexShaderSrc,
- PostProcessVertexShaderSrc
-};
-static const char* FShaderSrcs[FShader_Count] =
-{
- SolidFragShaderSrc,
- GouraudFragShaderSrc,
- TextureFragShaderSrc,
- PostProcessFragShaderSrc,
- PostProcessFullFragShaderSrc,
- LitSolidFragShaderSrc,
- LitTextureFragShaderSrc
-};
-
-
-
-RenderDevice::RenderDevice(const RendererParams& p)
-{
- for (int i = 0; i < VShader_Count; i++)
- VertexShaders[i] = *new Shader(this, Shader_Vertex, VShaderSrcs[i]);
-
- for (int i = 0; i < FShader_Count; i++)
- FragShaders[i] = *new Shader(this, Shader_Fragment, FShaderSrcs[i]);
-
- Ptr<ShaderSet> gouraudShaders = *new ShaderSet();
- gouraudShaders->SetShader(VertexShaders[VShader_MVP]);
- gouraudShaders->SetShader(FragShaders[FShader_Gouraud]);
- DefaultFill = *new ShaderFill(gouraudShaders);
-
- glGenFramebuffersEXT(1, &CurrentFbo);
-}
-
-Shader *RenderDevice::LoadBuiltinShader(ShaderStage stage, int shader)
-{
- switch (stage)
- {
- case Shader_Vertex: return VertexShaders[shader];
- case Shader_Fragment: return FragShaders[shader];
- default:
- return NULL;
- }
-}
-
-
-void RenderDevice::BeginRendering()
-{
- glEnable(GL_DEPTH_TEST);
- glEnable(GL_CULL_FACE);
- glFrontFace(GL_CW);
-
- glLineWidth(3.0f);
- glEnable(GL_LINE_SMOOTH);
- glEnable(GL_BLEND);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
-
- glMatrixMode(GL_MODELVIEW);
- glLoadIdentity();
-}
-
-void RenderDevice::SetDepthMode(bool enable, bool write, CompareFunc func)
-{
- if (enable)
- {
- glEnable(GL_DEPTH_TEST);
- glDepthMask(write);
- switch (func)
- {
- case Compare_Always: glDepthFunc(GL_ALWAYS); break;
- case Compare_Less: glDepthFunc(GL_LESS); break;
- case Compare_Greater: glDepthFunc(GL_GREATER); break;
- default: assert(0);
- }
- }
- else
- glDisable(GL_DEPTH_TEST);
-}
-
-void RenderDevice::SetRealViewport(const Viewport& vp)
-{
- int wh;
- if (CurRenderTarget)
- wh = CurRenderTarget->Height;
- else
- wh = WindowHeight;
- glViewport(vp.x, wh-vp.y-vp.h, vp.w, vp.h);
-
- glEnable(GL_SCISSOR_TEST);
- glScissor(vp.x, wh-vp.y-vp.h, vp.w, vp.h);
-}
-
-void RenderDevice::Clear(float r, float g, float b, float a, float depth)
-{
- glClearColor(r,g,b,a);
- glClearDepth(depth);
- glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
-}
-
-RBuffer* RenderDevice::GetDepthBuffer(int w, int h, int ms)
-{
- for (unsigned i = 0; i < DepthBuffers.GetSize(); i++)
- if (w == DepthBuffers[i]->Width && h == DepthBuffers[i]->Height)// && ms == DepthBuffers[i]->Samples)
- return DepthBuffers[i];
-
- //Ptr<Texture> newDepth = *CreateTexture(Texture_Depth|Texture_RenderTarget|ms, w, h, NULL);
- Ptr<RBuffer> newDepth = *new RBuffer(GL_DEPTH24_STENCIL8, w, h); // combined depth stencil
- DepthBuffers.PushBack(newDepth);
- return newDepth.GetPtr();
-}
-
-void RenderDevice::SetRenderTarget(RenderTiny::Texture* color, RenderTiny::Texture*, RenderTiny::Texture* stencil)
-{
- OVR_UNUSED(stencil);
-
- CurRenderTarget = (Texture*)color;
- if (color == NULL)
- {
- glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
- return;
- }
- //if (depth == NULL)
- RBuffer* depth = GetDepthBuffer(color->GetWidth(), color->GetHeight(), 0); //CurRenderTarget->Samples);
-
- glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, CurrentFbo);
- glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, ((Texture*)color)->TexId, 0);
- if (depth)
- //glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_2D, ((Texture*)depth)->TexId, 0);
- glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, ((RBuffer*)depth)->BufId);
- else
- glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, 0);
-
- GLenum status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
- if (status != GL_FRAMEBUFFER_COMPLETE_EXT)
- OVR_DEBUG_LOG(("framebuffer not complete: %x", status));
-}
-
-
-void RenderDevice::SetWorldUniforms(const Matrix4f& proj)
-{
- Proj = proj.Transposed();
-}
-
-void RenderDevice::SetTexture(RenderTiny::ShaderStage, int slot, const Texture* t)
-{
- glActiveTexture(GL_TEXTURE0 + slot);
- glBindTexture(GL_TEXTURE_2D, ((Texture*)t)->TexId);
- glActiveTexture(GL_TEXTURE0);
-}
-
-Buffer* RenderDevice::CreateBuffer()
-{
- return new Buffer(this);
-}
-
-void RenderDevice::Render(const Matrix4f& matrix, Model* model)
-{
- // Store data in buffers if not already
- if (!model->VertexBuffer)
- {
- Ptr<RenderTiny::Buffer> vb = *CreateBuffer();
- vb->Data(Buffer_Vertex, &model->Vertices[0], model->Vertices.GetSize() * sizeof(Vertex));
- model->VertexBuffer = vb;
- }
- if (!model->IndexBuffer)
- {
- Ptr<RenderTiny::Buffer> ib = *CreateBuffer();
- ib->Data(Buffer_Index, &model->Indices[0], model->Indices.GetSize() * 2);
- model->IndexBuffer = ib;
- }
-
- Render(model->Fill ? (const ShaderFill*)model->Fill : (const ShaderFill*)DefaultFill,
- model->VertexBuffer, model->IndexBuffer,
- matrix, 0, (int)model->Indices.GetSize(), model->GetPrimType());
-}
-
-void RenderDevice::Render(const ShaderFill* fill, RenderTiny::Buffer* vertices, RenderTiny::Buffer* indices,
- const Matrix4f& matrix, int offset, int count, PrimitiveType rprim)
-{
- ShaderSet* shaders = (ShaderSet*) ((ShaderFill*)fill)->GetShaders();
-
- GLenum prim;
- switch (rprim)
- {
- case Prim_Triangles:
- prim = GL_TRIANGLES;
- break;
- case Prim_Lines:
- prim = GL_LINES;
- break;
- case Prim_TriangleStrip:
- prim = GL_TRIANGLE_STRIP;
- break;
- default:
- assert(0);
- return;
- }
-
- fill->Set();
- if (shaders->ProjLoc >= 0)
- glUniformMatrix4fv(shaders->ProjLoc, 1, 0, &Proj.M[0][0]);
- if (shaders->ViewLoc >= 0)
- glUniformMatrix4fv(shaders->ViewLoc, 1, 0, &matrix.Transposed().M[0][0]);
-
- if (shaders->UsesLighting && Lighting->Version != shaders->LightingVer)
- {
- shaders->LightingVer = Lighting->Version;
- Lighting->Set(shaders);
- }
-
- glBindBuffer(GL_ARRAY_BUFFER, ((Buffer*)vertices)->GLBuffer);
- for (int i = 0; i < 4; i++)
- glEnableVertexAttribArray(i);
-
- glVertexAttribPointer(0, 3, GL_FLOAT, false, sizeof(Vertex), (char*)offset + offsetof(Vertex, Pos));
- glVertexAttribPointer(1, 4, GL_UNSIGNED_BYTE, true, sizeof(Vertex), (char*)offset + offsetof(Vertex, C));
- glVertexAttribPointer(2, 2, GL_FLOAT, false, sizeof(Vertex), (char*)offset + offsetof(Vertex, U));
- glVertexAttribPointer(3, 3, GL_FLOAT, false, sizeof(Vertex), (char*)offset + offsetof(Vertex, Norm));
-
- if (indices)
- {
- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ((Buffer*)indices)->GLBuffer);
- glDrawElements(prim, count, GL_UNSIGNED_SHORT, NULL);
- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
- }
- else
- {
- glDrawArrays(prim, 0, count);
- }
-
- for (int i = 0; i < 4; i++)
- glDisableVertexAttribArray(i);
-}
-
-void RenderDevice::SetLighting(const LightingParams* lt)
-{
- Lighting = lt;
-}
-
-Buffer::~Buffer()
-{
- if (GLBuffer)
- glDeleteBuffers(1, &GLBuffer);
-}
-
-bool Buffer::Data(int use, const void* buffer, size_t size)
-{
- switch (use & Buffer_TypeMask)
- {
- case Buffer_Index: Use = GL_ELEMENT_ARRAY_BUFFER; break;
- default: Use = GL_ARRAY_BUFFER; break;
- }
-
- if (!GLBuffer)
- glGenBuffers(1, &GLBuffer);
-
- int mode = GL_DYNAMIC_DRAW;
- if (use & Buffer_ReadOnly)
- mode = GL_STATIC_DRAW;
-
- glBindBuffer(Use, GLBuffer);
- glBufferData(Use, size, buffer, mode);
- glBindBuffer(Use, 0);
- return 1;
-}
-
-void* Buffer::Map(size_t start, size_t size, int flags)
-{
- int mode = GL_WRITE_ONLY;
- //if (flags & Map_Unsynchronized)
- // mode |= GL_MAP_UNSYNCHRONIZED;
-
- glBindBuffer(Use, GLBuffer);
- void* v = glMapBuffer(Use, mode);
- glBindBuffer(Use, 0);
- return v;
-}
-
-bool Buffer::Unmap(void*)
-{
- glBindBuffer(Use, GLBuffer);
- int r = glUnmapBuffer(Use);
- glBindBuffer(Use, 0);
- return r;
-}
-
-bool Shader::Compile(const char* src)
-{
- if (!GLShader)
- GLShader = glCreateShader(GLStage());
-
- glShaderSource(GLShader, 1, &src, 0);
- glCompileShader(GLShader);
- GLint r;
- glGetShaderiv(GLShader, GL_COMPILE_STATUS, &r);
- if (!r)
- {
- GLchar msg[1024];
- glGetShaderInfoLog(GLShader, sizeof(msg), 0, msg);
- if (msg[0])
- OVR_DEBUG_LOG(("Compiling shader\n%s\nfailed: %s\n", src, msg));
- if (!r)
- return 0;
- }
- return 1;
-}
-
-ShaderSet::ShaderSet()
-{
- Prog = glCreateProgram();
-}
-ShaderSet::~ShaderSet()
-{
- glDeleteProgram(Prog);
-}
-
-bool ShaderSet::Link()
-{
- glBindAttribLocation(Prog, 0, "Position");
- glBindAttribLocation(Prog, 1, "Color");
- glBindAttribLocation(Prog, 2, "TexCoord");
- glBindAttribLocation(Prog, 3, "Normal");
-
- glLinkProgram(Prog);
- GLint r;
- glGetProgramiv(Prog, GL_LINK_STATUS, &r);
- if (!r)
- {
- GLchar msg[1024];
- glGetProgramInfoLog(Prog, sizeof(msg), 0, msg);
- OVR_DEBUG_LOG(("Linking shaders failed: %s\n", msg));
- if (!r)
- return 0;
- }
- glUseProgram(Prog);
-
- UniformInfo.Clear();
- LightingVer = 0;
- UsesLighting = 0;
- GLuint i = 0;
- for(;; i++)
- {
- GLsizei namelen;
- GLint size = 0;
- GLenum type;
- GLchar name[32];
- glGetActiveUniform(Prog, i, sizeof(name), &namelen, &size, &type, name);
- if (size)
- {
- int l = glGetUniformLocation(Prog, name);
- char *np = name;
- while (*np)
- {
- if (*np == '[')
- *np = 0;
- np++;
- }
- Uniform u;
- u.Name = name;
- u.Location = l;
- u.Size = size;
- switch (type)
- {
- case GL_FLOAT: u.Type = 1; break;
- case GL_FLOAT_VEC2: u.Type = 2; break;
- case GL_FLOAT_VEC3: u.Type = 3; break;
- case GL_FLOAT_VEC4: u.Type = 4; break;
- case GL_FLOAT_MAT4: u.Type = 16; break;
- default:
- continue;
- }
- UniformInfo.PushBack(u);
- if (!strcmp(name, "LightCount"))
- UsesLighting = 1;
- }
- else
- break;
- }
-
- ProjLoc = glGetUniformLocation(Prog, "Proj");
- ViewLoc = glGetUniformLocation(Prog, "View");
- for (int i = 0; i < 8; i++)
- {
- char texv[32];
- sprintf(texv, "Texture%d", i);
- TexLoc[i] = glGetUniformLocation(Prog, texv);
- if (TexLoc[i] < 0)
- break;
-
- glUniform1i(TexLoc[i], i);
- }
- if (UsesLighting)
- OVR_ASSERT(ProjLoc >= 0 && ViewLoc >= 0);
- return 1;
-}
-
-void ShaderSet::Set(PrimitiveType) const
-{
- glUseProgram(Prog);
-}
-
-bool ShaderSet::SetUniform(const char* name, int n, const float* v)
-{
- for (int i = 0; i < UniformInfo.GetSize(); i++)
- if (!strcmp(UniformInfo[i].Name.ToCStr(), name))
- {
- OVR_ASSERT(UniformInfo[i].Location >= 0);
- glUseProgram(Prog);
- switch (UniformInfo[i].Type)
- {
- case 1: glUniform1fv(UniformInfo[i].Location, n, v); break;
- case 2: glUniform2fv(UniformInfo[i].Location, n/2, v); break;
- case 3: glUniform3fv(UniformInfo[i].Location, n/3, v); break;
- case 4: glUniform4fv(UniformInfo[i].Location, n/4, v); break;
- default: OVR_ASSERT(0);
- }
- return 1;
- }
-
- OVR_DEBUG_LOG(("Warning: uniform %s not present in selected shader", name));
- return 0;
-}
-
-bool ShaderSet::SetUniform4x4f(const char* name, const Matrix4f& m)
-{
- for (int i = 0; i < UniformInfo.GetSize(); i++)
- if (!strcmp(UniformInfo[i].Name.ToCStr(), name))
- {
- glUseProgram(Prog);
- glUniformMatrix4fv(UniformInfo[i].Location, 1, 1, &m.M[0][0]);
- return 1;
- }
-
- OVR_DEBUG_LOG(("Warning: uniform %s not present in selected shader", name));
- return 0;
-}
-
-Texture::Texture(RenderDevice* r, int w, int h) : Ren(r), Width(w), Height(h)
-{
- glGenTextures(1, &TexId);
-}
-
-Texture::~Texture()
-{
- if (TexId)
- glDeleteTextures(1, &TexId);
-}
-
-void Texture::Set(int slot, RenderTiny::ShaderStage stage) const
-{
- Ren->SetTexture(stage, slot, this);
-}
-
-void Texture::SetSampleMode(int sm)
-{
- glBindTexture(GL_TEXTURE_2D, TexId);
- switch (sm & Sample_FilterMask)
- {
- case Sample_Linear:
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 0);
- break;
-
- case Sample_Anisotropic:
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 8);
- break;
-
- case Sample_Nearest:
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 0);
- break;
- }
-
- switch (sm & Sample_AddressMask)
- {
- case Sample_Repeat:
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
- break;
-
- case Sample_Clamp:
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
- break;
-
- case Sample_ClampBorder:
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
- break;
- }
- glBindTexture(GL_TEXTURE_2D, 0);
-}
-
-Texture* RenderDevice::CreateTexture(int format, int width, int height, const void* data, int mipcount)
-{
- GLenum glformat, gltype = GL_UNSIGNED_BYTE;
- switch(format & Texture_TypeMask)
- {
- case Texture_RGBA: glformat = GL_RGBA; break;
- case Texture_Depth: glformat = GL_DEPTH; gltype = GL_DEPTH_COMPONENT; break;
- default:
- return NULL;
- }
- Texture* NewTex = new Texture(this, width, height);
- glBindTexture(GL_TEXTURE_2D, NewTex->TexId);
- glGetError();
-
- glTexImage2D(GL_TEXTURE_2D, 0, glformat, width, height, 0, glformat, gltype, data);
- OVR_ASSERT(!glGetError());
-
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
-
- if (format == (Texture_RGBA|Texture_GenMipmaps)) // not render target
- {
- int srcw = width, srch = height;
- int level = 0;
- UByte* mipmaps = NULL;
- do
- {
- level++;
- int mipw = srcw >> 1; if (mipw < 1) mipw = 1;
- int miph = srch >> 1; if (miph < 1) miph = 1;
- if (mipmaps == NULL)
- mipmaps = (UByte*)OVR_ALLOC(mipw * miph * 4);
- FilterRgba2x2(level == 1 ? (const UByte*)data : mipmaps, srcw, srch, mipmaps);
- glTexImage2D(GL_TEXTURE_2D, level, glformat, mipw, miph, 0, glformat, gltype, mipmaps);
- OVR_ASSERT(!glGetError());
- srcw = mipw;
- srch = miph;
- } while (srcw > 1 || srch > 1);
- if (mipmaps)
- OVR_FREE(mipmaps);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, level);
- OVR_ASSERT(!glGetError());
- }
- else
- {
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, mipcount-1);
- OVR_ASSERT(!glGetError());
- }
-
- OVR_ASSERT(!glGetError());
- glBindTexture(GL_TEXTURE_2D, 0);
- return NewTex;
-}
-
-RBuffer::RBuffer(GLenum format, GLint w, GLint h)
-{
- Width = w;
- Height = h;
- glGenRenderbuffersEXT(1, &BufId);
- glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, BufId);
- glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, format, w, h);
- glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0);
-}
-
-RBuffer::~RBuffer()
-{
- glDeleteRenderbuffersEXT(1, &BufId);
-}
-
-}}}
+/************************************************************************************
+
+Filename : RenderTiny_GL_Device.cpp
+Content : RenderDevice implementation for OpenGL (tiny version)
+Created : September 10, 2012
+Authors : Andrew Reisse, Artem Bolgar
+
+Copyright : Copyright 2012 Oculus VR, Inc. All Rights reserved.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+************************************************************************************/
+
+#include "RenderTiny_GL_Device.h"
+#include "Kernel/OVR_Log.h"
+
+namespace OVR { namespace RenderTiny { namespace GL {
+
+
+
+static const char* StdVertexShaderSrc =
+ "uniform mat4 Proj;\n"
+ "uniform mat4 View;\n"
+ "attribute vec4 Position;\n"
+ "attribute vec4 Color;\n"
+ "attribute vec2 TexCoord;\n"
+ "attribute vec3 Normal;\n"
+ "varying vec4 oColor;\n"
+ "varying vec2 oTexCoord;\n"
+ "varying vec3 oNormal;\n"
+ "varying vec3 oVPos;\n"
+ "void main()\n"
+ "{\n"
+ " gl_Position = Proj * (View * Position);\n"
+ " oNormal = vec3(View * vec4(Normal,0));\n"
+ " oVPos = vec3(View * Position);\n"
+ " oTexCoord = TexCoord;\n"
+ " oColor = Color;\n"
+ "}\n";
+
+static const char* DirectVertexShaderSrc =
+ "uniform mat4 View;\n"
+ "attribute vec4 Position;\n"
+ "attribute vec4 Color;\n"
+ "attribute vec2 TexCoord;\n"
+ "attribute vec3 Normal;\n"
+ "varying vec4 oColor;\n"
+ "varying vec2 oTexCoord;\n"
+ "varying vec3 oNormal;\n"
+ "void main()\n"
+ "{\n"
+ " gl_Position = View * Position;\n"
+ " oTexCoord = TexCoord;\n"
+ " oColor = Color;\n"
+ " oNormal = vec3(View * vec4(Normal,0));\n"
+ "}\n";
+
+static const char* SolidFragShaderSrc =
+ "uniform vec4 Color;\n"
+ "void main()\n"
+ "{\n"
+ " gl_FragColor = Color;\n"
+ "}\n";
+
+static const char* GouraudFragShaderSrc =
+ "varying vec4 oColor;\n"
+ "void main()\n"
+ "{\n"
+ " gl_FragColor = oColor;\n"
+ "}\n";
+
+static const char* TextureFragShaderSrc =
+ "uniform sampler2D Texture0;\n"
+ "varying vec4 oColor;\n"
+ "varying vec2 oTexCoord;\n"
+ "void main()\n"
+ "{\n"
+ " gl_FragColor = oColor * texture2D(Texture0, oTexCoord);\n"
+ " if (gl_FragColor.a < 0.4)\n"
+ " discard;\n"
+ "}\n";
+
+#define LIGHTING_COMMON \
+ "uniform vec3 Ambient;\n" \
+ "uniform vec4 LightPos[8];\n" \
+ "uniform vec4 LightColor[8];\n" \
+ "uniform float LightCount;\n" \
+ "varying vec4 oColor;\n" \
+ "varying vec2 oTexCoord;\n" \
+ "varying vec3 oNormal;\n" \
+ "varying vec3 oVPos;\n" \
+ "vec4 DoLight()\n" \
+ "{\n" \
+ " vec3 norm = normalize(oNormal);\n" \
+ " vec3 light = Ambient;\n" \
+ " for (int i = 0; i < int(LightCount); i++)\n" \
+ " {\n" \
+ " vec3 ltp = (LightPos[i].xyz - oVPos);\n" \
+ " float ldist = length(ltp);\n" \
+ " ltp = normalize(ltp);\n" \
+ " light += clamp(LightColor[i].rgb * oColor.rgb * (dot(norm, ltp) / ldist), 0.0,1.0);\n" \
+ " }\n" \
+ " return vec4(light, oColor.a);\n" \
+ "}\n"
+
+static const char* LitSolidFragShaderSrc =
+ LIGHTING_COMMON
+ "void main()\n"
+ "{\n"
+ " gl_FragColor = DoLight() * oColor;\n"
+ "}\n";
+
+static const char* LitTextureFragShaderSrc =
+ "uniform sampler2D Texture0;\n"
+ LIGHTING_COMMON
+ "void main()\n"
+ "{\n"
+ " gl_FragColor = DoLight() * texture2D(Texture0, oTexCoord);\n"
+ "}\n";
+
+static const char* PostProcessVertexShaderSrc =
+ "uniform mat4 View;\n"
+ "uniform mat4 Texm;\n"
+ "attribute vec4 Position;\n"
+ "attribute vec2 TexCoord;\n"
+ "varying vec2 oTexCoord;\n"
+ "void main()\n"
+ "{\n"
+ " gl_Position = View * Position;\n"
+ " oTexCoord = vec2(Texm * vec4(TexCoord,0,1));\n"
+ " oTexCoord.y = 1.0-oTexCoord.y;\n"
+ "}\n";
+
+static const char* PostProcessFragShaderSrc =
+ "uniform vec2 LensCenter;\n"
+ "uniform vec2 ScreenCenter;\n"
+ "uniform vec2 Scale;\n"
+ "uniform vec2 ScaleIn;\n"
+ "uniform vec4 HmdWarpParam;\n"
+ "uniform sampler2D Texture0;\n"
+ "varying vec2 oTexCoord;\n"
+ "\n"
+ "vec2 HmdWarp(vec2 in01)\n"
+ "{\n"
+ " vec2 theta = (in01 - LensCenter) * ScaleIn;\n" // Scales to [-1, 1]
+ " float rSq = theta.x * theta.x + theta.y * theta.y;\n"
+ " vec2 theta1 = theta * (HmdWarpParam.x + HmdWarpParam.y * rSq + "
+ " HmdWarpParam.z * rSq * rSq + HmdWarpParam.w * rSq * rSq * rSq);\n"
+ " return LensCenter + Scale * theta1;\n"
+ "}\n"
+ "void main()\n"
+ "{\n"
+ " vec2 tc = HmdWarp(oTexCoord);\n"
+ " if (!all(equal(clamp(tc, ScreenCenter-vec2(0.25,0.5), ScreenCenter+vec2(0.25,0.5)), tc)))\n"
+ " gl_FragColor = vec4(0);\n"
+ " else\n"
+ " gl_FragColor = texture2D(Texture0, tc);\n"
+ "}\n";
+
+// Shader with lens distortion and chromatic aberration correction.
+static const char* PostProcessFullFragShaderSrc =
+ "uniform vec2 LensCenter;\n"
+ "uniform vec2 ScreenCenter;\n"
+ "uniform vec2 Scale;\n"
+ "uniform vec2 ScaleIn;\n"
+ "uniform vec4 HmdWarpParam;\n"
+ "uniform vec4 ChromAbParam;\n"
+ "uniform sampler2D Texture0;\n"
+ "varying vec2 oTexCoord;\n"
+ "\n"
+ // Scales input texture coordinates for distortion.
+ // ScaleIn maps texture coordinates to Scales to ([-1, 1]), although top/bottom will be
+ // larger due to aspect ratio.
+ "void main()\n"
+ "{\n"
+ " vec2 theta = (oTexCoord - LensCenter) * ScaleIn;\n" // Scales to [-1, 1]
+ " float rSq= theta.x * theta.x + theta.y * theta.y;\n"
+ " vec2 theta1 = theta * (HmdWarpParam.x + HmdWarpParam.y * rSq + "
+ " HmdWarpParam.z * rSq * rSq + HmdWarpParam.w * rSq * rSq * rSq);\n"
+ " \n"
+ " // Detect whether blue texture coordinates are out of range since these will scaled out the furthest.\n"
+ " vec2 thetaBlue = theta1 * (ChromAbParam.z + ChromAbParam.w * rSq);\n"
+ " vec2 tcBlue = LensCenter + Scale * thetaBlue;\n"
+ " if (!all(equal(clamp(tcBlue, ScreenCenter-vec2(0.25,0.5), ScreenCenter+vec2(0.25,0.5)), tcBlue)))\n"
+ " {\n"
+ " gl_FragColor = vec4(0);\n"
+ " return;\n"
+ " }\n"
+ " \n"
+ " // Now do blue texture lookup.\n"
+ " float blue = texture2D(Texture0, tcBlue).b;\n"
+ " \n"
+ " // Do green lookup (no scaling).\n"
+ " vec2 tcGreen = LensCenter + Scale * theta1;\n"
+ " vec4 center = texture2D(Texture0, tcGreen);\n"
+ " \n"
+ " // Do red scale and lookup.\n"
+ " vec2 thetaRed = theta1 * (ChromAbParam.x + ChromAbParam.y * rSq);\n"
+ " vec2 tcRed = LensCenter + Scale * thetaRed;\n"
+ " float red = texture2D(Texture0, tcRed).r;\n"
+ " \n"
+ " gl_FragColor = vec4(red, center.g, blue, 1);\n"
+ "}\n";
+
+static const char* VShaderSrcs[VShader_Count] =
+{
+ DirectVertexShaderSrc,
+ StdVertexShaderSrc,
+ PostProcessVertexShaderSrc
+};
+static const char* FShaderSrcs[FShader_Count] =
+{
+ SolidFragShaderSrc,
+ GouraudFragShaderSrc,
+ TextureFragShaderSrc,
+ PostProcessFragShaderSrc,
+ PostProcessFullFragShaderSrc,
+ LitSolidFragShaderSrc,
+ LitTextureFragShaderSrc
+};
+
+
+
+RenderDevice::RenderDevice(const RendererParams& p)
+{
+ for (int i = 0; i < VShader_Count; i++)
+ VertexShaders[i] = *new Shader(this, Shader_Vertex, VShaderSrcs[i]);
+
+ for (int i = 0; i < FShader_Count; i++)
+ FragShaders[i] = *new Shader(this, Shader_Fragment, FShaderSrcs[i]);
+
+ Ptr<ShaderSet> gouraudShaders = *new ShaderSet();
+ gouraudShaders->SetShader(VertexShaders[VShader_MVP]);
+ gouraudShaders->SetShader(FragShaders[FShader_Gouraud]);
+ DefaultFill = *new ShaderFill(gouraudShaders);
+
+ glGenFramebuffersEXT(1, &CurrentFbo);
+}
+
+Shader *RenderDevice::LoadBuiltinShader(ShaderStage stage, int shader)
+{
+ switch (stage)
+ {
+ case Shader_Vertex: return VertexShaders[shader];
+ case Shader_Fragment: return FragShaders[shader];
+ default:
+ return NULL;
+ }
+}
+
+
+void RenderDevice::BeginRendering()
+{
+ glEnable(GL_DEPTH_TEST);
+ glEnable(GL_CULL_FACE);
+ glFrontFace(GL_CW);
+
+ glLineWidth(3.0f);
+ glEnable(GL_LINE_SMOOTH);
+ glEnable(GL_BLEND);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+
+ glMatrixMode(GL_MODELVIEW);
+ glLoadIdentity();
+}
+
+void RenderDevice::SetDepthMode(bool enable, bool write, CompareFunc func)
+{
+ if (enable)
+ {
+ glEnable(GL_DEPTH_TEST);
+ glDepthMask(write);
+ switch (func)
+ {
+ case Compare_Always: glDepthFunc(GL_ALWAYS); break;
+ case Compare_Less: glDepthFunc(GL_LESS); break;
+ case Compare_Greater: glDepthFunc(GL_GREATER); break;
+ default: assert(0);
+ }
+ }
+ else
+ glDisable(GL_DEPTH_TEST);
+}
+
+void RenderDevice::SetRealViewport(const Viewport& vp)
+{
+ int wh;
+ if (CurRenderTarget)
+ wh = CurRenderTarget->Height;
+ else
+ wh = WindowHeight;
+ glViewport(vp.x, wh-vp.y-vp.h, vp.w, vp.h);
+
+ glEnable(GL_SCISSOR_TEST);
+ glScissor(vp.x, wh-vp.y-vp.h, vp.w, vp.h);
+}
+
+void RenderDevice::Clear(float r, float g, float b, float a, float depth)
+{
+ glClearColor(r,g,b,a);
+ glClearDepth(depth);
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
+}
+
+RBuffer* RenderDevice::GetDepthBuffer(int w, int h, int ms)
+{
+ for (unsigned i = 0; i < DepthBuffers.GetSize(); i++)
+ if (w == DepthBuffers[i]->Width && h == DepthBuffers[i]->Height)// && ms == DepthBuffers[i]->Samples)
+ return DepthBuffers[i];
+
+ //Ptr<Texture> newDepth = *CreateTexture(Texture_Depth|Texture_RenderTarget|ms, w, h, NULL);
+ Ptr<RBuffer> newDepth = *new RBuffer(GL_DEPTH24_STENCIL8, w, h); // combined depth stencil
+ DepthBuffers.PushBack(newDepth);
+ return newDepth.GetPtr();
+}
+
+void RenderDevice::SetRenderTarget(RenderTiny::Texture* color, RenderTiny::Texture*, RenderTiny::Texture* stencil)
+{
+ OVR_UNUSED(stencil);
+
+ CurRenderTarget = (Texture*)color;
+ if (color == NULL)
+ {
+ glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
+ return;
+ }
+ //if (depth == NULL)
+ RBuffer* depth = GetDepthBuffer(color->GetWidth(), color->GetHeight(), 0); //CurRenderTarget->Samples);
+
+ glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, CurrentFbo);
+ glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, ((Texture*)color)->TexId, 0);
+ if (depth)
+ //glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_2D, ((Texture*)depth)->TexId, 0);
+ glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, ((RBuffer*)depth)->BufId);
+ else
+ glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, 0);
+
+ GLenum status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
+ if (status != GL_FRAMEBUFFER_COMPLETE_EXT)
+ OVR_DEBUG_LOG(("framebuffer not complete: %x", status));
+}
+
+
+void RenderDevice::SetWorldUniforms(const Matrix4f& proj)
+{
+ Proj = proj.Transposed();
+}
+
+void RenderDevice::SetTexture(RenderTiny::ShaderStage, int slot, const Texture* t)
+{
+ glActiveTexture(GL_TEXTURE0 + slot);
+ glBindTexture(GL_TEXTURE_2D, ((Texture*)t)->TexId);
+ glActiveTexture(GL_TEXTURE0);
+}
+
+Buffer* RenderDevice::CreateBuffer()
+{
+ return new Buffer(this);
+}
+
+void RenderDevice::Render(const Matrix4f& matrix, Model* model)
+{
+ // Store data in buffers if not already
+ if (!model->VertexBuffer)
+ {
+ Ptr<RenderTiny::Buffer> vb = *CreateBuffer();
+ vb->Data(Buffer_Vertex, &model->Vertices[0], model->Vertices.GetSize() * sizeof(Vertex));
+ model->VertexBuffer = vb;
+ }
+ if (!model->IndexBuffer)
+ {
+ Ptr<RenderTiny::Buffer> ib = *CreateBuffer();
+ ib->Data(Buffer_Index, &model->Indices[0], model->Indices.GetSize() * 2);
+ model->IndexBuffer = ib;
+ }
+
+ Render(model->Fill ? (const ShaderFill*)model->Fill : (const ShaderFill*)DefaultFill,
+ model->VertexBuffer, model->IndexBuffer,
+ matrix, 0, (int)model->Indices.GetSize(), model->GetPrimType());
+}
+
+void RenderDevice::Render(const ShaderFill* fill, RenderTiny::Buffer* vertices, RenderTiny::Buffer* indices,
+ const Matrix4f& matrix, int offset, int count, PrimitiveType rprim)
+{
+ ShaderSet* shaders = (ShaderSet*) ((ShaderFill*)fill)->GetShaders();
+
+ GLenum prim;
+ switch (rprim)
+ {
+ case Prim_Triangles:
+ prim = GL_TRIANGLES;
+ break;
+ case Prim_Lines:
+ prim = GL_LINES;
+ break;
+ case Prim_TriangleStrip:
+ prim = GL_TRIANGLE_STRIP;
+ break;
+ default:
+ assert(0);
+ return;
+ }
+
+ fill->Set();
+ if (shaders->ProjLoc >= 0)
+ glUniformMatrix4fv(shaders->ProjLoc, 1, 0, &Proj.M[0][0]);
+ if (shaders->ViewLoc >= 0)
+ glUniformMatrix4fv(shaders->ViewLoc, 1, 0, &matrix.Transposed().M[0][0]);
+
+ if (shaders->UsesLighting && Lighting->Version != shaders->LightingVer)
+ {
+ shaders->LightingVer = Lighting->Version;
+ Lighting->Set(shaders);
+ }
+
+ glBindBuffer(GL_ARRAY_BUFFER, ((Buffer*)vertices)->GLBuffer);
+ for (int i = 0; i < 4; i++)
+ glEnableVertexAttribArray(i);
+
+ glVertexAttribPointer(0, 3, GL_FLOAT, false, sizeof(Vertex), (char*)offset + offsetof(Vertex, Pos));
+ glVertexAttribPointer(1, 4, GL_UNSIGNED_BYTE, true, sizeof(Vertex), (char*)offset + offsetof(Vertex, C));
+ glVertexAttribPointer(2, 2, GL_FLOAT, false, sizeof(Vertex), (char*)offset + offsetof(Vertex, U));
+ glVertexAttribPointer(3, 3, GL_FLOAT, false, sizeof(Vertex), (char*)offset + offsetof(Vertex, Norm));
+
+ if (indices)
+ {
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ((Buffer*)indices)->GLBuffer);
+ glDrawElements(prim, count, GL_UNSIGNED_SHORT, NULL);
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
+ }
+ else
+ {
+ glDrawArrays(prim, 0, count);
+ }
+
+ for (int i = 0; i < 4; i++)
+ glDisableVertexAttribArray(i);
+}
+
+void RenderDevice::SetLighting(const LightingParams* lt)
+{
+ Lighting = lt;
+}
+
+Buffer::~Buffer()
+{
+ if (GLBuffer)
+ glDeleteBuffers(1, &GLBuffer);
+}
+
+bool Buffer::Data(int use, const void* buffer, size_t size)
+{
+ switch (use & Buffer_TypeMask)
+ {
+ case Buffer_Index: Use = GL_ELEMENT_ARRAY_BUFFER; break;
+ default: Use = GL_ARRAY_BUFFER; break;
+ }
+
+ if (!GLBuffer)
+ glGenBuffers(1, &GLBuffer);
+
+ int mode = GL_DYNAMIC_DRAW;
+ if (use & Buffer_ReadOnly)
+ mode = GL_STATIC_DRAW;
+
+ glBindBuffer(Use, GLBuffer);
+ glBufferData(Use, size, buffer, mode);
+ glBindBuffer(Use, 0);
+ return 1;
+}
+
+void* Buffer::Map(size_t start, size_t size, int flags)
+{
+ int mode = GL_WRITE_ONLY;
+ //if (flags & Map_Unsynchronized)
+ // mode |= GL_MAP_UNSYNCHRONIZED;
+
+ glBindBuffer(Use, GLBuffer);
+ void* v = glMapBuffer(Use, mode);
+ glBindBuffer(Use, 0);
+ return v;
+}
+
+bool Buffer::Unmap(void*)
+{
+ glBindBuffer(Use, GLBuffer);
+ int r = glUnmapBuffer(Use);
+ glBindBuffer(Use, 0);
+ return r;
+}
+
+bool Shader::Compile(const char* src)
+{
+ if (!GLShader)
+ GLShader = glCreateShader(GLStage());
+
+ glShaderSource(GLShader, 1, &src, 0);
+ glCompileShader(GLShader);
+ GLint r;
+ glGetShaderiv(GLShader, GL_COMPILE_STATUS, &r);
+ if (!r)
+ {
+ GLchar msg[1024];
+ glGetShaderInfoLog(GLShader, sizeof(msg), 0, msg);
+ if (msg[0])
+ OVR_DEBUG_LOG(("Compiling shader\n%s\nfailed: %s\n", src, msg));
+ if (!r)
+ return 0;
+ }
+ return 1;
+}
+
+ShaderSet::ShaderSet()
+{
+ Prog = glCreateProgram();
+}
+ShaderSet::~ShaderSet()
+{
+ glDeleteProgram(Prog);
+}
+
+bool ShaderSet::Link()
+{
+ glBindAttribLocation(Prog, 0, "Position");
+ glBindAttribLocation(Prog, 1, "Color");
+ glBindAttribLocation(Prog, 2, "TexCoord");
+ glBindAttribLocation(Prog, 3, "Normal");
+
+ glLinkProgram(Prog);
+ GLint r;
+ glGetProgramiv(Prog, GL_LINK_STATUS, &r);
+ if (!r)
+ {
+ GLchar msg[1024];
+ glGetProgramInfoLog(Prog, sizeof(msg), 0, msg);
+ OVR_DEBUG_LOG(("Linking shaders failed: %s\n", msg));
+ if (!r)
+ return 0;
+ }
+ glUseProgram(Prog);
+
+ UniformInfo.Clear();
+ LightingVer = 0;
+ UsesLighting = 0;
+ GLuint i = 0;
+ for(;; i++)
+ {
+ GLsizei namelen;
+ GLint size = 0;
+ GLenum type;
+ GLchar name[32];
+ glGetActiveUniform(Prog, i, sizeof(name), &namelen, &size, &type, name);
+ if (size)
+ {
+ int l = glGetUniformLocation(Prog, name);
+ char *np = name;
+ while (*np)
+ {
+ if (*np == '[')
+ *np = 0;
+ np++;
+ }
+ Uniform u;
+ u.Name = name;
+ u.Location = l;
+ u.Size = size;
+ switch (type)
+ {
+ case GL_FLOAT: u.Type = 1; break;
+ case GL_FLOAT_VEC2: u.Type = 2; break;
+ case GL_FLOAT_VEC3: u.Type = 3; break;
+ case GL_FLOAT_VEC4: u.Type = 4; break;
+ case GL_FLOAT_MAT4: u.Type = 16; break;
+ default:
+ continue;
+ }
+ UniformInfo.PushBack(u);
+ if (!strcmp(name, "LightCount"))
+ UsesLighting = 1;
+ }
+ else
+ break;
+ }
+
+ ProjLoc = glGetUniformLocation(Prog, "Proj");
+ ViewLoc = glGetUniformLocation(Prog, "View");
+ for (int i = 0; i < 8; i++)
+ {
+ char texv[32];
+ sprintf(texv, "Texture%d", i);
+ TexLoc[i] = glGetUniformLocation(Prog, texv);
+ if (TexLoc[i] < 0)
+ break;
+
+ glUniform1i(TexLoc[i], i);
+ }
+ if (UsesLighting)
+ OVR_ASSERT(ProjLoc >= 0 && ViewLoc >= 0);
+ return 1;
+}
+
+void ShaderSet::Set(PrimitiveType) const
+{
+ glUseProgram(Prog);
+}
+
+bool ShaderSet::SetUniform(const char* name, int n, const float* v)
+{
+ for (int i = 0; i < UniformInfo.GetSize(); i++)
+ if (!strcmp(UniformInfo[i].Name.ToCStr(), name))
+ {
+ OVR_ASSERT(UniformInfo[i].Location >= 0);
+ glUseProgram(Prog);
+ switch (UniformInfo[i].Type)
+ {
+ case 1: glUniform1fv(UniformInfo[i].Location, n, v); break;
+ case 2: glUniform2fv(UniformInfo[i].Location, n/2, v); break;
+ case 3: glUniform3fv(UniformInfo[i].Location, n/3, v); break;
+ case 4: glUniform4fv(UniformInfo[i].Location, n/4, v); break;
+ default: OVR_ASSERT(0);
+ }
+ return 1;
+ }
+
+ OVR_DEBUG_LOG(("Warning: uniform %s not present in selected shader", name));
+ return 0;
+}
+
+bool ShaderSet::SetUniform4x4f(const char* name, const Matrix4f& m)
+{
+ for (int i = 0; i < UniformInfo.GetSize(); i++)
+ if (!strcmp(UniformInfo[i].Name.ToCStr(), name))
+ {
+ glUseProgram(Prog);
+ glUniformMatrix4fv(UniformInfo[i].Location, 1, 1, &m.M[0][0]);
+ return 1;
+ }
+
+ OVR_DEBUG_LOG(("Warning: uniform %s not present in selected shader", name));
+ return 0;
+}
+
+Texture::Texture(RenderDevice* r, int w, int h) : Ren(r), Width(w), Height(h)
+{
+ glGenTextures(1, &TexId);
+}
+
+Texture::~Texture()
+{
+ if (TexId)
+ glDeleteTextures(1, &TexId);
+}
+
+void Texture::Set(int slot, RenderTiny::ShaderStage stage) const
+{
+ Ren->SetTexture(stage, slot, this);
+}
+
+void Texture::SetSampleMode(int sm)
+{
+ glBindTexture(GL_TEXTURE_2D, TexId);
+ switch (sm & Sample_FilterMask)
+ {
+ case Sample_Linear:
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 0);
+ break;
+
+ case Sample_Anisotropic:
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 8);
+ break;
+
+ case Sample_Nearest:
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 0);
+ break;
+ }
+
+ switch (sm & Sample_AddressMask)
+ {
+ case Sample_Repeat:
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
+ break;
+
+ case Sample_Clamp:
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+ break;
+
+ case Sample_ClampBorder:
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
+ break;
+ }
+ glBindTexture(GL_TEXTURE_2D, 0);
+}
+
+Texture* RenderDevice::CreateTexture(int format, int width, int height, const void* data, int mipcount)
+{
+ GLenum glformat, gltype = GL_UNSIGNED_BYTE;
+ switch(format & Texture_TypeMask)
+ {
+ case Texture_RGBA: glformat = GL_RGBA; break;
+ case Texture_Depth: glformat = GL_DEPTH; gltype = GL_DEPTH_COMPONENT; break;
+ default:
+ return NULL;
+ }
+ Texture* NewTex = new Texture(this, width, height);
+ glBindTexture(GL_TEXTURE_2D, NewTex->TexId);
+ glGetError();
+
+ glTexImage2D(GL_TEXTURE_2D, 0, glformat, width, height, 0, glformat, gltype, data);
+ OVR_ASSERT(!glGetError());
+
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+
+ if (format == (Texture_RGBA|Texture_GenMipmaps)) // not render target
+ {
+ int srcw = width, srch = height;
+ int level = 0;
+ UByte* mipmaps = NULL;
+ do
+ {
+ level++;
+ int mipw = srcw >> 1; if (mipw < 1) mipw = 1;
+ int miph = srch >> 1; if (miph < 1) miph = 1;
+ if (mipmaps == NULL)
+ mipmaps = (UByte*)OVR_ALLOC(mipw * miph * 4);
+ FilterRgba2x2(level == 1 ? (const UByte*)data : mipmaps, srcw, srch, mipmaps);
+ glTexImage2D(GL_TEXTURE_2D, level, glformat, mipw, miph, 0, glformat, gltype, mipmaps);
+ OVR_ASSERT(!glGetError());
+ srcw = mipw;
+ srch = miph;
+ } while (srcw > 1 || srch > 1);
+ if (mipmaps)
+ OVR_FREE(mipmaps);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, level);
+ OVR_ASSERT(!glGetError());
+ }
+ else
+ {
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, mipcount-1);
+ OVR_ASSERT(!glGetError());
+ }
+
+ OVR_ASSERT(!glGetError());
+ glBindTexture(GL_TEXTURE_2D, 0);
+ return NewTex;
+}
+
+RBuffer::RBuffer(GLenum format, GLint w, GLint h)
+{
+ Width = w;
+ Height = h;
+ glGenRenderbuffersEXT(1, &BufId);
+ glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, BufId);
+ glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, format, w, h);
+ glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0);
+}
+
+RBuffer::~RBuffer()
+{
+ glDeleteRenderbuffersEXT(1, &BufId);
+}
+
+}}}
diff --git a/Samples/OculusRoomTiny/RenderTiny_GL_Device.h b/Samples/OculusRoomTiny/RenderTiny_GL_Device.h
index feb504f..5d88180 100644
--- a/Samples/OculusRoomTiny/RenderTiny_GL_Device.h
+++ b/Samples/OculusRoomTiny/RenderTiny_GL_Device.h
@@ -1,228 +1,228 @@
-/************************************************************************************
-
-Filename : RenderTiny_GL_Device.h
-Content : RenderDevice implementation header for OpenGL (tiny version)
-Created : September 10, 2012
-Authors : Andrew Reisse, Artem Bolgar
-
-Copyright : Copyright 2012 Oculus VR, Inc. All Rights reserved.
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-
-************************************************************************************/
-
-#ifndef OVR_Render_GL_Device_h
-#define OVR_Render_GL_Device_h
-
-#include "RenderTiny_Device.h"
-
-#if defined(OVR_OS_WIN32)
-#include <Windows.h>
-#endif
-
-#if defined(OVR_OS_MAC)
-#include <OpenGL/gl.h>
-#include <OpenGL/glext.h>
-#else
-#define GL_GLEXT_PROTOTYPES
-#include <GL/gl.h>
-#include <GL/glext.h>
-#endif
-
-namespace OVR { namespace RenderTiny { namespace GL {
-
-class RenderDevice;
-
-class Buffer : public RenderTiny::Buffer
-{
-public:
- RenderDevice* Ren;
- size_t Size;
- GLenum Use;
- GLuint GLBuffer;
-
-public:
- Buffer(RenderDevice* r) : Ren(r), Size(0), Use(0), GLBuffer(0) {}
- ~Buffer();
-
- GLuint GetBuffer() { return GLBuffer; }
-
- virtual size_t GetSize() { return Size; }
- virtual void* Map(size_t start, size_t size, int flags = 0);
- virtual bool Unmap(void *m);
- virtual bool Data(int use, const void* buffer, size_t size);
-};
-
-class Texture : public RenderTiny::Texture
-{
-public:
- RenderDevice* Ren;
- GLuint TexId;
- int Width, Height;
-
- Texture(RenderDevice* r, int w, int h);
- ~Texture();
-
- virtual int GetWidth() const { return Width; }
- virtual int GetHeight() const { return Height; }
-
- virtual void SetSampleMode(int);
-
- virtual void Set(int slot, ShaderStage stage = Shader_Fragment) const;
-};
-
-class Shader : public RenderTiny::Shader
-{
-public:
- GLuint GLShader;
-
- Shader(RenderDevice*, ShaderStage st, GLuint s) : RenderTiny::Shader(st), GLShader(s) {}
- Shader(RenderDevice*, ShaderStage st, const char* src) : RenderTiny::Shader(st), GLShader(0)
- {
- Compile(src);
- }
- ~Shader()
- {
- if (GLShader)
- glDeleteShader(GLShader);
- }
- bool Compile(const char* src);
-
- GLenum GLStage() const
- {
- switch (Stage)
- {
- default: OVR_ASSERT(0); return GL_NONE;
- case Shader_Vertex: return GL_VERTEX_SHADER;
- case Shader_Fragment: return GL_FRAGMENT_SHADER;
- }
- }
-
- //void Set(PrimitiveType prim) const;
- //void SetUniformBuffer(Render::Buffer* buffers, int i = 0);
-};
-
-class ShaderSet : public RenderTiny::ShaderSet
-{
-public:
- GLuint Prog;
-
- struct Uniform
- {
- String Name;
- int Location, Size;
- int Type; // currently number of floats in vector
- };
- Array<Uniform> UniformInfo;
-
- int ProjLoc, ViewLoc;
- int TexLoc[8];
- bool UsesLighting;
- int LightingVer;
-
- ShaderSet();
- ~ShaderSet();
-
- virtual void SetShader(RenderTiny::Shader *s)
- {
- Shaders[s->GetStage()] = s;
- Shader* gls = (Shader*)s;
- glAttachShader(Prog, gls->GLShader);
- if (Shaders[Shader_Vertex] && Shaders[Shader_Fragment])
- Link();
- }
- virtual void UnsetShader(int stage)
- {
- Shader* gls = (Shader*)(RenderTiny::Shader*)Shaders[stage];
- if (gls)
- glDetachShader(Prog, gls->GLShader);
- Shaders[stage] = NULL;
- Link();
- }
-
- virtual void Set(PrimitiveType prim) const;
-
- // Set a uniform (other than the standard matrices). It is undefined whether the
- // uniforms from one shader occupy the same space as those in other shaders
- // (unless a buffer is used, then each buffer is independent).
- virtual bool SetUniform(const char* name, int n, const float* v);
- virtual bool SetUniform4x4f(const char* name, const Matrix4f& m);
-
- bool Link();
-};
-
- class RBuffer : public RefCountBase<RBuffer>
-{
- public:
- int Width, Height;
- GLuint BufId;
-
- RBuffer(GLenum format, GLint w, GLint h);
- ~RBuffer();
-};
-
-class RenderDevice : public RenderTiny::RenderDevice
-{
- Ptr<Shader> VertexShaders[VShader_Count];
- Ptr<Shader> FragShaders[FShader_Count];
-
- Ptr<ShaderFill> DefaultFill;
-
- Matrix4f Proj;
-
- Ptr<Texture> CurRenderTarget;
- Array<Ptr<RBuffer> > DepthBuffers;
- GLuint CurrentFbo;
-
- const LightingParams* Lighting;
-
-
-public:
- RenderDevice(const RendererParams& p);
-
- virtual void SetRealViewport(const Viewport& vp);
-
- //virtual void SetScissor(int x, int y, int w, int h);
-
- virtual void Clear(float r = 0, float g = 0, float b = 0, float a = 1, float depth = 1);
- virtual void Rect(float left, float top, float right, float bottom) { OVR_UNUSED4(left,top,right,bottom); }
-
- virtual void BeginRendering();
- virtual void SetDepthMode(bool enable, bool write, CompareFunc func = Compare_Less);
- virtual void SetWorldUniforms(const Matrix4f& proj);
-
- RBuffer* GetDepthBuffer(int w, int h, int ms);
-
- virtual void SetRenderTarget(RenderTiny::Texture* color,
- RenderTiny::Texture* depth = NULL, RenderTiny::Texture* stencil = NULL);
-
- virtual void SetLighting(const LightingParams* lt);
-
- virtual void Render(const Matrix4f& matrix, Model* model);
- virtual void Render(const ShaderFill* fill, RenderTiny::Buffer* vertices, RenderTiny::Buffer* indices,
- const Matrix4f& matrix, int offset, int count, PrimitiveType prim = Prim_Triangles);
-
- virtual Buffer* CreateBuffer();
- virtual Texture* CreateTexture(int format, int width, int height, const void* data, int mipcount=1);
- virtual ShaderSet* CreateShaderSet() { return new ShaderSet; }
-
- virtual ShaderFill *CreateSimpleFill() { return DefaultFill; }
-
- virtual Shader *LoadBuiltinShader(ShaderStage stage, int shader);
-
- void SetTexture(RenderTiny::ShaderStage, int slot, const Texture* t);
-};
-
-}}}
-
-#endif
+/************************************************************************************
+
+Filename : RenderTiny_GL_Device.h
+Content : RenderDevice implementation header for OpenGL (tiny version)
+Created : September 10, 2012
+Authors : Andrew Reisse, Artem Bolgar
+
+Copyright : Copyright 2012 Oculus VR, Inc. All Rights reserved.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+************************************************************************************/
+
+#ifndef OVR_Render_GL_Device_h
+#define OVR_Render_GL_Device_h
+
+#include "RenderTiny_Device.h"
+
+#if defined(OVR_OS_WIN32)
+#include <Windows.h>
+#endif
+
+#if defined(OVR_OS_MAC)
+#include <OpenGL/gl.h>
+#include <OpenGL/glext.h>
+#else
+#define GL_GLEXT_PROTOTYPES
+#include <GL/gl.h>
+#include <GL/glext.h>
+#endif
+
+namespace OVR { namespace RenderTiny { namespace GL {
+
+class RenderDevice;
+
+class Buffer : public RenderTiny::Buffer
+{
+public:
+ RenderDevice* Ren;
+ size_t Size;
+ GLenum Use;
+ GLuint GLBuffer;
+
+public:
+ Buffer(RenderDevice* r) : Ren(r), Size(0), Use(0), GLBuffer(0) {}
+ ~Buffer();
+
+ GLuint GetBuffer() { return GLBuffer; }
+
+ virtual size_t GetSize() { return Size; }
+ virtual void* Map(size_t start, size_t size, int flags = 0);
+ virtual bool Unmap(void *m);
+ virtual bool Data(int use, const void* buffer, size_t size);
+};
+
+class Texture : public RenderTiny::Texture
+{
+public:
+ RenderDevice* Ren;
+ GLuint TexId;
+ int Width, Height;
+
+ Texture(RenderDevice* r, int w, int h);
+ ~Texture();
+
+ virtual int GetWidth() const { return Width; }
+ virtual int GetHeight() const { return Height; }
+
+ virtual void SetSampleMode(int);
+
+ virtual void Set(int slot, ShaderStage stage = Shader_Fragment) const;
+};
+
+class Shader : public RenderTiny::Shader
+{
+public:
+ GLuint GLShader;
+
+ Shader(RenderDevice*, ShaderStage st, GLuint s) : RenderTiny::Shader(st), GLShader(s) {}
+ Shader(RenderDevice*, ShaderStage st, const char* src) : RenderTiny::Shader(st), GLShader(0)
+ {
+ Compile(src);
+ }
+ ~Shader()
+ {
+ if (GLShader)
+ glDeleteShader(GLShader);
+ }
+ bool Compile(const char* src);
+
+ GLenum GLStage() const
+ {
+ switch (Stage)
+ {
+ default: OVR_ASSERT(0); return GL_NONE;
+ case Shader_Vertex: return GL_VERTEX_SHADER;
+ case Shader_Fragment: return GL_FRAGMENT_SHADER;
+ }
+ }
+
+ //void Set(PrimitiveType prim) const;
+ //void SetUniformBuffer(Render::Buffer* buffers, int i = 0);
+};
+
+class ShaderSet : public RenderTiny::ShaderSet
+{
+public:
+ GLuint Prog;
+
+ struct Uniform
+ {
+ String Name;
+ int Location, Size;
+ int Type; // currently number of floats in vector
+ };
+ Array<Uniform> UniformInfo;
+
+ int ProjLoc, ViewLoc;
+ int TexLoc[8];
+ bool UsesLighting;
+ int LightingVer;
+
+ ShaderSet();
+ ~ShaderSet();
+
+ virtual void SetShader(RenderTiny::Shader *s)
+ {
+ Shaders[s->GetStage()] = s;
+ Shader* gls = (Shader*)s;
+ glAttachShader(Prog, gls->GLShader);
+ if (Shaders[Shader_Vertex] && Shaders[Shader_Fragment])
+ Link();
+ }
+ virtual void UnsetShader(int stage)
+ {
+ Shader* gls = (Shader*)(RenderTiny::Shader*)Shaders[stage];
+ if (gls)
+ glDetachShader(Prog, gls->GLShader);
+ Shaders[stage] = NULL;
+ Link();
+ }
+
+ virtual void Set(PrimitiveType prim) const;
+
+ // Set a uniform (other than the standard matrices). It is undefined whether the
+ // uniforms from one shader occupy the same space as those in other shaders
+ // (unless a buffer is used, then each buffer is independent).
+ virtual bool SetUniform(const char* name, int n, const float* v);
+ virtual bool SetUniform4x4f(const char* name, const Matrix4f& m);
+
+ bool Link();
+};
+
+ class RBuffer : public RefCountBase<RBuffer>
+{
+ public:
+ int Width, Height;
+ GLuint BufId;
+
+ RBuffer(GLenum format, GLint w, GLint h);
+ ~RBuffer();
+};
+
+class RenderDevice : public RenderTiny::RenderDevice
+{
+ Ptr<Shader> VertexShaders[VShader_Count];
+ Ptr<Shader> FragShaders[FShader_Count];
+
+ Ptr<ShaderFill> DefaultFill;
+
+ Matrix4f Proj;
+
+ Ptr<Texture> CurRenderTarget;
+ Array<Ptr<RBuffer> > DepthBuffers;
+ GLuint CurrentFbo;
+
+ const LightingParams* Lighting;
+
+
+public:
+ RenderDevice(const RendererParams& p);
+
+ virtual void SetRealViewport(const Viewport& vp);
+
+ //virtual void SetScissor(int x, int y, int w, int h);
+
+ virtual void Clear(float r = 0, float g = 0, float b = 0, float a = 1, float depth = 1);
+ virtual void Rect(float left, float top, float right, float bottom) { OVR_UNUSED4(left,top,right,bottom); }
+
+ virtual void BeginRendering();
+ virtual void SetDepthMode(bool enable, bool write, CompareFunc func = Compare_Less);
+ virtual void SetWorldUniforms(const Matrix4f& proj);
+
+ RBuffer* GetDepthBuffer(int w, int h, int ms);
+
+ virtual void SetRenderTarget(RenderTiny::Texture* color,
+ RenderTiny::Texture* depth = NULL, RenderTiny::Texture* stencil = NULL);
+
+ virtual void SetLighting(const LightingParams* lt);
+
+ virtual void Render(const Matrix4f& matrix, Model* model);
+ virtual void Render(const ShaderFill* fill, RenderTiny::Buffer* vertices, RenderTiny::Buffer* indices,
+ const Matrix4f& matrix, int offset, int count, PrimitiveType prim = Prim_Triangles);
+
+ virtual Buffer* CreateBuffer();
+ virtual Texture* CreateTexture(int format, int width, int height, const void* data, int mipcount=1);
+ virtual ShaderSet* CreateShaderSet() { return new ShaderSet; }
+
+ virtual ShaderFill *CreateSimpleFill() { return DefaultFill; }
+
+ virtual Shader *LoadBuiltinShader(ShaderStage stage, int shader);
+
+ void SetTexture(RenderTiny::ShaderStage, int slot, const Texture* t);
+};
+
+}}}
+
+#endif
diff --git a/Samples/OculusRoomTiny/Win32_OculusRoomTiny.cpp b/Samples/OculusRoomTiny/Win32_OculusRoomTiny.cpp
index 2e6dd3e..c27723f 100644
--- a/Samples/OculusRoomTiny/Win32_OculusRoomTiny.cpp
+++ b/Samples/OculusRoomTiny/Win32_OculusRoomTiny.cpp
@@ -1,712 +1,712 @@
-/************************************************************************************
-
-Filename : Win32_OculusRoomTiny.cpp
-Content : First-person view test application for Oculus Rift
-Created : October 4, 2012
-Authors : Michael Antonov, Andrew Reisse
-
-Copyright : Copyright 2012 Oculus, Inc. All Rights reserved.
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-
-*************************************************************************************/
-
-#include "Win32_OculusRoomTiny.h"
-#include "RenderTiny_D3D1X_Device.h"
-
-//-------------------------------------------------------------------------------------
-// ***** OculusRoomTiny Class
-
-// Static pApp simplifies routing the window function.
-OculusRoomTinyApp* OculusRoomTinyApp::pApp = 0;
-
-
-OculusRoomTinyApp::OculusRoomTinyApp(HINSTANCE hinst)
- : pRender(0),
- LastUpdate(0),
-
- // Win32
- hWnd(NULL),
- hInstance(hinst), Quit(0), MouseCaptured(true),
- hXInputModule(0), pXInputGetState(0),
-
- // Initial location
- EyePos(0.0f, 1.6f, -5.0f),
- EyeYaw(YawInitial), EyePitch(0), EyeRoll(0),
- LastSensorYaw(0),
- SConfig(),
- PostProcess(PostProcess_Distortion),
- ShiftDown(false),
- ControlDown(false)
-{
- pApp = this;
-
- Width = 1280;
- Height = 800;
-
- StartupTicks = OVR::Timer::GetTicks();
- LastPadPacketNo = 0;
-
- MoveForward = MoveBack = MoveLeft = MoveRight = 0;
- GamepadMove = Vector3f(0);
- GamepadRotate = Vector3f(0);
-}
-
-OculusRoomTinyApp::~OculusRoomTinyApp()
-{
- RemoveHandlerFromDevices();
- pSensor.Clear();
- pHMD.Clear();
- destroyWindow();
- pApp = 0;
-}
-
-
-int OculusRoomTinyApp::OnStartup(const char* args)
-{
- OVR_UNUSED(args);
-
-
- // *** Oculus HMD & Sensor Initialization
-
- // Create DeviceManager and first available HMDDevice from it.
- // Sensor object is created from the HMD, to ensure that it is on the
- // correct device.
-
- pManager = *DeviceManager::Create();
-
- // We'll handle it's messages in this case.
- pManager->SetMessageHandler(this);
-
-
- int detectionResult = IDCONTINUE;
- const char* detectionMessage;
-
- do
- {
- // Release Sensor/HMD in case this is a retry.
- pSensor.Clear();
- pHMD.Clear();
- RenderParams.MonitorName.Clear();
-
- pHMD = *pManager->EnumerateDevices<HMDDevice>().CreateDevice();
- if (pHMD)
- {
- pSensor = *pHMD->GetSensor();
-
- // This will initialize HMDInfo with information about configured IPD,
- // screen size and other variables needed for correct projection.
- // We pass HMD DisplayDeviceName into the renderer to select the
- // correct monitor in full-screen mode.
- if (pHMD->GetDeviceInfo(&HMDInfo))
- {
- RenderParams.MonitorName = HMDInfo.DisplayDeviceName;
- RenderParams.DisplayId = HMDInfo.DisplayId;
- SConfig.SetHMDInfo(HMDInfo);
- }
- }
- else
- {
- // If we didn't detect an HMD, try to create the sensor directly.
- // This is useful for debugging sensor interaction; it is not needed in
- // a shipping app.
- pSensor = *pManager->EnumerateDevices<SensorDevice>().CreateDevice();
- }
-
-
- // If there was a problem detecting the Rift, display appropriate message.
- detectionResult = IDCONTINUE;
-
- if (!pHMD && !pSensor)
- detectionMessage = "Oculus Rift not detected.";
- else if (!pHMD)
- detectionMessage = "Oculus Sensor detected; HMD Display not detected.";
- else if (!pSensor)
- detectionMessage = "Oculus HMD Display detected; Sensor not detected.";
- else if (HMDInfo.DisplayDeviceName[0] == '\0')
- detectionMessage = "Oculus Sensor detected; HMD display EDID not detected.";
- else
- detectionMessage = 0;
-
- if (detectionMessage)
- {
- String messageText(detectionMessage);
- messageText += "\n\n"
- "Press 'Try Again' to run retry detection.\n"
- "Press 'Continue' to run full-screen anyway.";
-
- detectionResult = ::MessageBoxA(0, messageText.ToCStr(), "Oculus Rift Detection",
- MB_CANCELTRYCONTINUE|MB_ICONWARNING);
-
- if (detectionResult == IDCANCEL)
- return 1;
- }
-
- } while (detectionResult != IDCONTINUE);
-
-
- if (HMDInfo.HResolution > 0)
- {
- Width = HMDInfo.HResolution;
- Height = HMDInfo.VResolution;
- }
-
-
- if (!setupWindow())
- return 1;
-
- if (pSensor)
- {
- // We need to attach sensor to SensorFusion object for it to receive
- // body frame messages and update orientation. SFusion.GetOrientation()
- // is used in OnIdle() to orient the view.
- SFusion.AttachToSensor(pSensor);
- SFusion.SetDelegateMessageHandler(this);
- SFusion.SetPredictionEnabled(true);
- }
-
-
- // *** Initialize Rendering
-
- // Enable multi-sampling by default.
- RenderParams.Multisample = 4;
- RenderParams.Fullscreen = true;
-
- // Setup Graphics.
- pRender = *RenderTiny::D3D10::RenderDevice::CreateDevice(RenderParams, (void*)hWnd);
- if (!pRender)
- return 1;
-
-
- // *** Configure Stereo settings.
-
- SConfig.SetFullViewport(Viewport(0,0, Width, Height));
- SConfig.SetStereoMode(Stereo_LeftRight_Multipass);
-
- // Configure proper Distortion Fit.
- // For 7" screen, fit to touch left side of the view, leaving a bit of invisible
- // screen on the top (saves on rendering cost).
- // For smaller screens (5.5"), fit to the top.
- if (HMDInfo.HScreenSize > 0.0f)
- {
- if (HMDInfo.HScreenSize > 0.140f) // 7"
- SConfig.SetDistortionFitPointVP(-1.0f, 0.0f);
- else
- SConfig.SetDistortionFitPointVP(0.0f, 1.0f);
- }
-
- pRender->SetSceneRenderScale(SConfig.GetDistortionScale());
-
- SConfig.Set2DAreaFov(DegreeToRad(85.0f));
-
-
- // *** Populate Room Scene
-
- // This creates lights and models.
- PopulateRoomScene(&Scene, pRender);
-
-
- LastUpdate = GetAppTime();
- return 0;
-}
-
-void OculusRoomTinyApp::OnMessage(const Message& msg)
-{
- if (msg.Type == Message_DeviceAdded && msg.pDevice == pManager)
- {
- LogText("DeviceManager reported device added.\n");
- }
- else if (msg.Type == Message_DeviceRemoved && msg.pDevice == pManager)
- {
- LogText("DeviceManager reported device removed.\n");
- }
- else if (msg.Type == Message_DeviceAdded && msg.pDevice == pSensor)
- {
- LogText("Sensor reported device added.\n");
- }
- else if (msg.Type == Message_DeviceRemoved && msg.pDevice == pSensor)
- {
- LogText("Sensor reported device removed.\n");
- }
-}
-
-
-void OculusRoomTinyApp::OnGamepad(float padLx, float padLy, float padRx, float padRy)
-{
- GamepadMove = Vector3f(padLx * padLx * (padLx > 0 ? 1 : -1),
- 0,
- padLy * padLy * (padLy > 0 ? -1 : 1));
- GamepadRotate = Vector3f(2 * padRx, -2 * padRy, 0);
-}
-
-void OculusRoomTinyApp::OnMouseMove(int x, int y, int modifiers)
-{
- OVR_UNUSED(modifiers);
-
- // Mouse motion here is always relative.
- int dx = x, dy = y;
- const float maxPitch = ((3.1415f/2)*0.98f);
-
- // Apply to rotation. Subtract for right body frame rotation,
- // since yaw rotation is positive CCW when looking down on XZ plane.
- EyeYaw -= (Sensitivity * dx)/ 360.0f;
-
- if (!pSensor)
- {
- EyePitch -= (Sensitivity * dy)/ 360.0f;
-
- if (EyePitch > maxPitch)
- EyePitch = maxPitch;
- if (EyePitch < -maxPitch)
- EyePitch = -maxPitch;
- }
-}
-
-void OculusRoomTinyApp::OnKey(unsigned vk, bool down)
-{
- switch (vk)
- {
- case 'Q':
- if (down && ControlDown)
- Quit = true;
- break;
- case VK_ESCAPE:
- if (!down)
- Quit = true;
- break;
-
- // Handle player movement keys.
- // We just update movement state here, while the actual translation is done in OnIdle()
- // based on time.
- case 'W': MoveForward = down ? (MoveForward | 1) : (MoveForward & ~1); break;
- case 'S': MoveBack = down ? (MoveBack | 1) : (MoveBack & ~1); break;
- case 'A': MoveLeft = down ? (MoveLeft | 1) : (MoveLeft & ~1); break;
- case 'D': MoveRight = down ? (MoveRight | 1) : (MoveRight & ~1); break;
- case VK_UP: MoveForward = down ? (MoveForward | 2) : (MoveForward & ~2); break;
- case VK_DOWN: MoveBack = down ? (MoveBack | 2) : (MoveBack & ~2); break;
-
- case 'R':
- SFusion.Reset();
- break;
-
- case 'P':
- if (down)
- {
- // Toggle chromatic aberration correction on/off.
- RenderDevice::PostProcessShader shader = pRender->GetPostProcessShader();
-
- if (shader == RenderDevice::PostProcessShader_Distortion)
- {
- pRender->SetPostProcessShader(RenderDevice::PostProcessShader_DistortionAndChromAb);
- }
- else if (shader == RenderDevice::PostProcessShader_DistortionAndChromAb)
- {
- pRender->SetPostProcessShader(RenderDevice::PostProcessShader_Distortion);
- }
- else
- OVR_ASSERT(false);
- }
- break;
-
- // Switch rendering modes/distortion.
- case VK_F1:
- SConfig.SetStereoMode(Stereo_None);
- PostProcess = PostProcess_None;
- break;
- case VK_F2:
- SConfig.SetStereoMode(Stereo_LeftRight_Multipass);
- PostProcess = PostProcess_None;
- break;
- case VK_F3:
- SConfig.SetStereoMode(Stereo_LeftRight_Multipass);
- PostProcess = PostProcess_Distortion;
- break;
-
- // Stereo IPD adjustments, in meter (default IPD is 64mm).
- case VK_OEM_PLUS:
- case VK_INSERT:
- if (down)
- SConfig.SetIPD(SConfig.GetIPD() + 0.0005f * (ShiftDown ? 5.0f : 1.0f));
- break;
- case VK_OEM_MINUS:
- case VK_DELETE:
- if (down)
- SConfig.SetIPD(SConfig.GetIPD() - 0.0005f * (ShiftDown ? 5.0f : 1.0f));
- break;
-
- // Holding down Shift key accelerates adjustment velocity.
- case VK_SHIFT:
- ShiftDown = down;
- break;
- case VK_CONTROL:
- ControlDown = down;
- break;
- }
-}
-
-
-void OculusRoomTinyApp::OnIdle()
-{
- double curtime = GetAppTime();
- float dt = float(curtime - LastUpdate);
- LastUpdate = curtime;
-
-
- // Handle Sensor motion.
- // We extract Yaw, Pitch, Roll instead of directly using the orientation
- // to allow "additional" yaw manipulation with mouse/controller.
- if (pSensor)
- {
- Quatf hmdOrient = SFusion.GetOrientation();
- float yaw = 0.0f;
-
- hmdOrient.GetEulerAngles<Axis_Y, Axis_X, Axis_Z>(&yaw, &EyePitch, &EyeRoll);
-
- EyeYaw += (yaw - LastSensorYaw);
- LastSensorYaw = yaw;
- }
-
-
- // Gamepad rotation.
- EyeYaw -= GamepadRotate.x * dt;
-
- if (!pSensor)
- {
- // Allow gamepad to look up/down, but only if there is no Rift sensor.
- EyePitch -= GamepadRotate.y * dt;
-
- const float maxPitch = ((3.1415f/2)*0.98f);
- if (EyePitch > maxPitch)
- EyePitch = maxPitch;
- if (EyePitch < -maxPitch)
- EyePitch = -maxPitch;
- }
-
- // Handle keyboard movement.
- // This translates EyePos based on Yaw vector direction and keys pressed.
- // Note that Pitch and Roll do not affect movement (they only affect view).
- if (MoveForward || MoveBack || MoveLeft || MoveRight)
- {
- Vector3f localMoveVector(0,0,0);
- Matrix4f yawRotate = Matrix4f::RotationY(EyeYaw);
-
- if (MoveForward)
- localMoveVector = ForwardVector;
- else if (MoveBack)
- localMoveVector = -ForwardVector;
-
- if (MoveRight)
- localMoveVector += RightVector;
- else if (MoveLeft)
- localMoveVector -= RightVector;
-
- // Normalize vector so we don't move faster diagonally.
- localMoveVector.Normalize();
- Vector3f orientationVector = yawRotate.Transform(localMoveVector);
- orientationVector *= MoveSpeed * dt * (ShiftDown ? 3.0f : 1.0f);
-
- EyePos += orientationVector;
- }
-
- else if (GamepadMove.LengthSq() > 0)
- {
- Matrix4f yawRotate = Matrix4f::RotationY(EyeYaw);
- Vector3f orientationVector = yawRotate.Transform(GamepadMove);
- orientationVector *= MoveSpeed * dt;
- EyePos += orientationVector;
- }
-
-
- // Rotate and position View Camera, using YawPitchRoll in BodyFrame coordinates.
- //
- Matrix4f rollPitchYaw = Matrix4f::RotationY(EyeYaw) * Matrix4f::RotationX(EyePitch) *
- Matrix4f::RotationZ(EyeRoll);
- Vector3f up = rollPitchYaw.Transform(UpVector);
- Vector3f forward = rollPitchYaw.Transform(ForwardVector);
-
-
- // Minimal head modelling.
- float headBaseToEyeHeight = 0.15f; // Vertical height of eye from base of head
- float headBaseToEyeProtrusion = 0.09f; // Distance forward of eye from base of head
-
- Vector3f eyeCenterInHeadFrame(0.0f, headBaseToEyeHeight, -headBaseToEyeProtrusion);
- Vector3f shiftedEyePos = EyePos + rollPitchYaw.Transform(eyeCenterInHeadFrame);
- shiftedEyePos.y -= eyeCenterInHeadFrame.y; // Bring the head back down to original height
-
- View = Matrix4f::LookAtRH(shiftedEyePos, shiftedEyePos + forward, up);
-
- // This is what transformation would be without head modeling.
- // View = Matrix4f::LookAtRH(EyePos, EyePos + forward, up);
-
- switch(SConfig.GetStereoMode())
- {
- case Stereo_None:
- Render(SConfig.GetEyeRenderParams(StereoEye_Center));
- break;
-
- case Stereo_LeftRight_Multipass:
- Render(SConfig.GetEyeRenderParams(StereoEye_Left));
- Render(SConfig.GetEyeRenderParams(StereoEye_Right));
- break;
- }
-
- pRender->Present();
- // Force GPU to flush the scene, resulting in the lowest possible latency.
- pRender->ForceFlushGPU();
-}
-
-
-// Render the scene for one eye.
-void OculusRoomTinyApp::Render(const StereoEyeParams& stereo)
-{
- pRender->BeginScene(PostProcess);
-
- // Apply Viewport/Projection for the eye.
- pRender->ApplyStereoParams(stereo);
- pRender->Clear();
- pRender->SetDepthMode(true, true);
-
- Scene.Render(pRender, stereo.ViewAdjust * View);
-
- pRender->FinishScene();
-}
-
-
-//-------------------------------------------------------------------------------------
-// ***** Win32-Specific Logic
-
-bool OculusRoomTinyApp::setupWindow()
-{
-
- WNDCLASS wc;
- memset(&wc, 0, sizeof(wc));
- wc.lpszClassName = L"OVRAppWindow";
- wc.style = CS_OWNDC;
- wc.lpfnWndProc = systemWindowProc;
- wc.cbWndExtra = sizeof(OculusRoomTinyApp*);
- RegisterClass(&wc);
-
-
- RECT winSize = { 0, 0, Width, Height };
- AdjustWindowRect(&winSize, WS_POPUP, false);
- hWnd = CreateWindowA("OVRAppWindow", "OculusRoomTiny", WS_POPUP|WS_VISIBLE,
- HMDInfo.DesktopX, HMDInfo.DesktopY,
- winSize.right-winSize.left, winSize.bottom-winSize.top,
- NULL, NULL, hInstance, (LPVOID)this);
-
-
- // Initialize Window center in screen coordinates
- POINT center = { Width / 2, Height / 2 };
- ::ClientToScreen(hWnd, &center);
- WindowCenter = center;
-
-
- return (hWnd != NULL);
-}
-
-void OculusRoomTinyApp::destroyWindow()
-{
- pRender.Clear();
-
- if (hWnd)
- {
- // Release window resources.
- ::DestroyWindow(hWnd);
- UnregisterClass(L"OVRAppWindow", hInstance);
- hWnd = 0;
- Width = Height = 0;
- }
-}
-
-
-LRESULT CALLBACK OculusRoomTinyApp::systemWindowProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp)
-{
- if (msg == WM_NCCREATE)
- pApp->hWnd = hwnd;
- return pApp->windowProc(msg, wp, lp);
-}
-
-void OculusRoomTinyApp::giveUsFocus(bool setFocus)
-{
- if (setFocus)
- {
- ::SetCursorPos(WindowCenter.x, WindowCenter.y);
-
- MouseCaptured = true;
- ::SetCapture(hWnd);
- ::ShowCursor(FALSE);
-
- }
- else
- {
- MouseCaptured = false;
- ::ReleaseCapture();
- ::ShowCursor(TRUE);
- }
-}
-
-LRESULT OculusRoomTinyApp::windowProc(UINT msg, WPARAM wp, LPARAM lp)
-{
- switch (msg)
- {
- case WM_MOUSEMOVE:
- {
- if (MouseCaptured)
- {
- // Convert mouse motion to be relative (report the offset and re-center).
- POINT newPos = { LOWORD(lp), HIWORD(lp) };
- ::ClientToScreen(hWnd, &newPos);
- if ((newPos.x == WindowCenter.x) && (newPos.y == WindowCenter.y))
- break;
- ::SetCursorPos(WindowCenter.x, WindowCenter.y);
-
- LONG dx = newPos.x - WindowCenter.x;
- LONG dy = newPos.y - WindowCenter.y;
- pApp->OnMouseMove(dx, dy, 0);
- }
- }
- break;
-
- case WM_MOVE:
- {
- RECT r;
- GetClientRect(hWnd, &r);
- WindowCenter.x = r.right/2;
- WindowCenter.y = r.bottom/2;
- ::ClientToScreen(hWnd, &WindowCenter);
- }
- break;
-
- case WM_KEYDOWN:
- OnKey((unsigned)wp, true);
- break;
- case WM_KEYUP:
- OnKey((unsigned)wp, false);
- break;
-
- case WM_SETFOCUS:
- giveUsFocus(true);
- break;
-
- case WM_KILLFOCUS:
- giveUsFocus(false);
- break;
-
- case WM_CREATE:
- // Hack to position mouse in fullscreen window shortly after startup.
- SetTimer(hWnd, 0, 100, NULL);
- break;
-
- case WM_TIMER:
- KillTimer(hWnd, 0);
- giveUsFocus(true);
- break;
-
- case WM_QUIT:
- case WM_CLOSE:
- Quit = true;
- return 0;
- }
-
- return DefWindowProc(hWnd, msg, wp, lp);
-}
-
-static inline float GamepadStick(short in)
-{
- float v;
- if (abs(in) < 9000)
- return 0;
- else if (in > 9000)
- v = (float) in - 9000;
- else
- v = (float) in + 9000;
- return v / (32767 - 9000);
-}
-
-static inline float GamepadTrigger(BYTE in)
-{
- return (in < 30) ? 0.0f : (float(in-30) / 225);
-}
-
-
-int OculusRoomTinyApp::Run()
-{
- // Loop processing messages until Quit flag is set,
- // rendering game scene inside of OnIdle().
-
- while (!Quit)
- {
- MSG msg;
- if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
- {
- TranslateMessage(&msg);
- DispatchMessage(&msg);
- }
- else
- {
- // Read game-pad.
- XINPUT_STATE xis;
-
- if (pXInputGetState && !pXInputGetState(0, &xis) &&
- (xis.dwPacketNumber != LastPadPacketNo))
- {
- OnGamepad(GamepadStick(xis.Gamepad.sThumbLX),
- GamepadStick(xis.Gamepad.sThumbLY),
- GamepadStick(xis.Gamepad.sThumbRX),
- GamepadStick(xis.Gamepad.sThumbRY));
- //pad.LT = GamepadTrigger(xis.Gamepad.bLeftTrigger);
- LastPadPacketNo = xis.dwPacketNumber;
- }
-
- pApp->OnIdle();
-
- // Keep sleeping when we're minimized.
- if (IsIconic(hWnd))
- Sleep(10);
- }
- }
-
- return 0;
-}
-
-
-//-------------------------------------------------------------------------------------
-// ***** Program Startup
-
-int WINAPI WinMain(HINSTANCE hinst, HINSTANCE, LPSTR inArgs, int)
-{
- int exitCode = 0;
-
- // Initializes LibOVR. This LogMask_All enables maximum logging.
- // Custom allocator can also be specified here.
- OVR::System::Init(OVR::Log::ConfigureDefaultLog(OVR::LogMask_All));
-
- // Scope to force application destructor before System::Destroy.
- {
- OculusRoomTinyApp app(hinst);
- //app.hInstance = hinst;
-
- exitCode = app.OnStartup(inArgs);
- if (!exitCode)
- {
- // Processes messages and calls OnIdle() to do rendering.
- exitCode = app.Run();
- }
- }
-
- // No OVR functions involving memory are allowed after this.
- OVR::System::Destroy();
-
- OVR_DEBUG_STATEMENT(_CrtDumpMemoryLeaks());
- return exitCode;
-}
+/************************************************************************************
+
+Filename : Win32_OculusRoomTiny.cpp
+Content : First-person view test application for Oculus Rift
+Created : October 4, 2012
+Authors : Michael Antonov, Andrew Reisse
+
+Copyright : Copyright 2012 Oculus, Inc. All Rights reserved.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+*************************************************************************************/
+
+#include "Win32_OculusRoomTiny.h"
+#include "RenderTiny_D3D1X_Device.h"
+
+//-------------------------------------------------------------------------------------
+// ***** OculusRoomTiny Class
+
+// Static pApp simplifies routing the window function.
+OculusRoomTinyApp* OculusRoomTinyApp::pApp = 0;
+
+
+OculusRoomTinyApp::OculusRoomTinyApp(HINSTANCE hinst)
+ : pRender(0),
+ LastUpdate(0),
+
+ // Win32
+ hWnd(NULL),
+ hInstance(hinst), Quit(0), MouseCaptured(true),
+ hXInputModule(0), pXInputGetState(0),
+
+ // Initial location
+ EyePos(0.0f, 1.6f, -5.0f),
+ EyeYaw(YawInitial), EyePitch(0), EyeRoll(0),
+ LastSensorYaw(0),
+ SConfig(),
+ PostProcess(PostProcess_Distortion),
+ ShiftDown(false),
+ ControlDown(false)
+{
+ pApp = this;
+
+ Width = 1280;
+ Height = 800;
+
+ StartupTicks = OVR::Timer::GetTicks();
+ LastPadPacketNo = 0;
+
+ MoveForward = MoveBack = MoveLeft = MoveRight = 0;
+ GamepadMove = Vector3f(0);
+ GamepadRotate = Vector3f(0);
+}
+
+OculusRoomTinyApp::~OculusRoomTinyApp()
+{
+ RemoveHandlerFromDevices();
+ pSensor.Clear();
+ pHMD.Clear();
+ destroyWindow();
+ pApp = 0;
+}
+
+
+int OculusRoomTinyApp::OnStartup(const char* args)
+{
+ OVR_UNUSED(args);
+
+
+ // *** Oculus HMD & Sensor Initialization
+
+ // Create DeviceManager and first available HMDDevice from it.
+ // Sensor object is created from the HMD, to ensure that it is on the
+ // correct device.
+
+ pManager = *DeviceManager::Create();
+
+ // We'll handle it's messages in this case.
+ pManager->SetMessageHandler(this);
+
+
+ int detectionResult = IDCONTINUE;
+ const char* detectionMessage;
+
+ do
+ {
+ // Release Sensor/HMD in case this is a retry.
+ pSensor.Clear();
+ pHMD.Clear();
+ RenderParams.MonitorName.Clear();
+
+ pHMD = *pManager->EnumerateDevices<HMDDevice>().CreateDevice();
+ if (pHMD)
+ {
+ pSensor = *pHMD->GetSensor();
+
+ // This will initialize HMDInfo with information about configured IPD,
+ // screen size and other variables needed for correct projection.
+ // We pass HMD DisplayDeviceName into the renderer to select the
+ // correct monitor in full-screen mode.
+ if (pHMD->GetDeviceInfo(&HMDInfo))
+ {
+ RenderParams.MonitorName = HMDInfo.DisplayDeviceName;
+ RenderParams.DisplayId = HMDInfo.DisplayId;
+ SConfig.SetHMDInfo(HMDInfo);
+ }
+ }
+ else
+ {
+ // If we didn't detect an HMD, try to create the sensor directly.
+ // This is useful for debugging sensor interaction; it is not needed in
+ // a shipping app.
+ pSensor = *pManager->EnumerateDevices<SensorDevice>().CreateDevice();
+ }
+
+
+ // If there was a problem detecting the Rift, display appropriate message.
+ detectionResult = IDCONTINUE;
+
+ if (!pHMD && !pSensor)
+ detectionMessage = "Oculus Rift not detected.";
+ else if (!pHMD)
+ detectionMessage = "Oculus Sensor detected; HMD Display not detected.";
+ else if (!pSensor)
+ detectionMessage = "Oculus HMD Display detected; Sensor not detected.";
+ else if (HMDInfo.DisplayDeviceName[0] == '\0')
+ detectionMessage = "Oculus Sensor detected; HMD display EDID not detected.";
+ else
+ detectionMessage = 0;
+
+ if (detectionMessage)
+ {
+ String messageText(detectionMessage);
+ messageText += "\n\n"
+ "Press 'Try Again' to run retry detection.\n"
+ "Press 'Continue' to run full-screen anyway.";
+
+ detectionResult = ::MessageBoxA(0, messageText.ToCStr(), "Oculus Rift Detection",
+ MB_CANCELTRYCONTINUE|MB_ICONWARNING);
+
+ if (detectionResult == IDCANCEL)
+ return 1;
+ }
+
+ } while (detectionResult != IDCONTINUE);
+
+
+ if (HMDInfo.HResolution > 0)
+ {
+ Width = HMDInfo.HResolution;
+ Height = HMDInfo.VResolution;
+ }
+
+
+ if (!setupWindow())
+ return 1;
+
+ if (pSensor)
+ {
+ // We need to attach sensor to SensorFusion object for it to receive
+ // body frame messages and update orientation. SFusion.GetOrientation()
+ // is used in OnIdle() to orient the view.
+ SFusion.AttachToSensor(pSensor);
+ SFusion.SetDelegateMessageHandler(this);
+ SFusion.SetPredictionEnabled(true);
+ }
+
+
+ // *** Initialize Rendering
+
+ // Enable multi-sampling by default.
+ RenderParams.Multisample = 4;
+ RenderParams.Fullscreen = true;
+
+ // Setup Graphics.
+ pRender = *RenderTiny::D3D10::RenderDevice::CreateDevice(RenderParams, (void*)hWnd);
+ if (!pRender)
+ return 1;
+
+
+ // *** Configure Stereo settings.
+
+ SConfig.SetFullViewport(Viewport(0,0, Width, Height));
+ SConfig.SetStereoMode(Stereo_LeftRight_Multipass);
+
+ // Configure proper Distortion Fit.
+ // For 7" screen, fit to touch left side of the view, leaving a bit of invisible
+ // screen on the top (saves on rendering cost).
+ // For smaller screens (5.5"), fit to the top.
+ if (HMDInfo.HScreenSize > 0.0f)
+ {
+ if (HMDInfo.HScreenSize > 0.140f) // 7"
+ SConfig.SetDistortionFitPointVP(-1.0f, 0.0f);
+ else
+ SConfig.SetDistortionFitPointVP(0.0f, 1.0f);
+ }
+
+ pRender->SetSceneRenderScale(SConfig.GetDistortionScale());
+
+ SConfig.Set2DAreaFov(DegreeToRad(85.0f));
+
+
+ // *** Populate Room Scene
+
+ // This creates lights and models.
+ PopulateRoomScene(&Scene, pRender);
+
+
+ LastUpdate = GetAppTime();
+ return 0;
+}
+
+void OculusRoomTinyApp::OnMessage(const Message& msg)
+{
+ if (msg.Type == Message_DeviceAdded && msg.pDevice == pManager)
+ {
+ LogText("DeviceManager reported device added.\n");
+ }
+ else if (msg.Type == Message_DeviceRemoved && msg.pDevice == pManager)
+ {
+ LogText("DeviceManager reported device removed.\n");
+ }
+ else if (msg.Type == Message_DeviceAdded && msg.pDevice == pSensor)
+ {
+ LogText("Sensor reported device added.\n");
+ }
+ else if (msg.Type == Message_DeviceRemoved && msg.pDevice == pSensor)
+ {
+ LogText("Sensor reported device removed.\n");
+ }
+}
+
+
+void OculusRoomTinyApp::OnGamepad(float padLx, float padLy, float padRx, float padRy)
+{
+ GamepadMove = Vector3f(padLx * padLx * (padLx > 0 ? 1 : -1),
+ 0,
+ padLy * padLy * (padLy > 0 ? -1 : 1));
+ GamepadRotate = Vector3f(2 * padRx, -2 * padRy, 0);
+}
+
+void OculusRoomTinyApp::OnMouseMove(int x, int y, int modifiers)
+{
+ OVR_UNUSED(modifiers);
+
+ // Mouse motion here is always relative.
+ int dx = x, dy = y;
+ const float maxPitch = ((3.1415f/2)*0.98f);
+
+ // Apply to rotation. Subtract for right body frame rotation,
+ // since yaw rotation is positive CCW when looking down on XZ plane.
+ EyeYaw -= (Sensitivity * dx)/ 360.0f;
+
+ if (!pSensor)
+ {
+ EyePitch -= (Sensitivity * dy)/ 360.0f;
+
+ if (EyePitch > maxPitch)
+ EyePitch = maxPitch;
+ if (EyePitch < -maxPitch)
+ EyePitch = -maxPitch;
+ }
+}
+
+void OculusRoomTinyApp::OnKey(unsigned vk, bool down)
+{
+ switch (vk)
+ {
+ case 'Q':
+ if (down && ControlDown)
+ Quit = true;
+ break;
+ case VK_ESCAPE:
+ if (!down)
+ Quit = true;
+ break;
+
+ // Handle player movement keys.
+ // We just update movement state here, while the actual translation is done in OnIdle()
+ // based on time.
+ case 'W': MoveForward = down ? (MoveForward | 1) : (MoveForward & ~1); break;
+ case 'S': MoveBack = down ? (MoveBack | 1) : (MoveBack & ~1); break;
+ case 'A': MoveLeft = down ? (MoveLeft | 1) : (MoveLeft & ~1); break;
+ case 'D': MoveRight = down ? (MoveRight | 1) : (MoveRight & ~1); break;
+ case VK_UP: MoveForward = down ? (MoveForward | 2) : (MoveForward & ~2); break;
+ case VK_DOWN: MoveBack = down ? (MoveBack | 2) : (MoveBack & ~2); break;
+
+ case 'R':
+ SFusion.Reset();
+ break;
+
+ case 'P':
+ if (down)
+ {
+ // Toggle chromatic aberration correction on/off.
+ RenderDevice::PostProcessShader shader = pRender->GetPostProcessShader();
+
+ if (shader == RenderDevice::PostProcessShader_Distortion)
+ {
+ pRender->SetPostProcessShader(RenderDevice::PostProcessShader_DistortionAndChromAb);
+ }
+ else if (shader == RenderDevice::PostProcessShader_DistortionAndChromAb)
+ {
+ pRender->SetPostProcessShader(RenderDevice::PostProcessShader_Distortion);
+ }
+ else
+ OVR_ASSERT(false);
+ }
+ break;
+
+ // Switch rendering modes/distortion.
+ case VK_F1:
+ SConfig.SetStereoMode(Stereo_None);
+ PostProcess = PostProcess_None;
+ break;
+ case VK_F2:
+ SConfig.SetStereoMode(Stereo_LeftRight_Multipass);
+ PostProcess = PostProcess_None;
+ break;
+ case VK_F3:
+ SConfig.SetStereoMode(Stereo_LeftRight_Multipass);
+ PostProcess = PostProcess_Distortion;
+ break;
+
+ // Stereo IPD adjustments, in meter (default IPD is 64mm).
+ case VK_OEM_PLUS:
+ case VK_INSERT:
+ if (down)
+ SConfig.SetIPD(SConfig.GetIPD() + 0.0005f * (ShiftDown ? 5.0f : 1.0f));
+ break;
+ case VK_OEM_MINUS:
+ case VK_DELETE:
+ if (down)
+ SConfig.SetIPD(SConfig.GetIPD() - 0.0005f * (ShiftDown ? 5.0f : 1.0f));
+ break;
+
+ // Holding down Shift key accelerates adjustment velocity.
+ case VK_SHIFT:
+ ShiftDown = down;
+ break;
+ case VK_CONTROL:
+ ControlDown = down;
+ break;
+ }
+}
+
+
+void OculusRoomTinyApp::OnIdle()
+{
+ double curtime = GetAppTime();
+ float dt = float(curtime - LastUpdate);
+ LastUpdate = curtime;
+
+
+ // Handle Sensor motion.
+ // We extract Yaw, Pitch, Roll instead of directly using the orientation
+ // to allow "additional" yaw manipulation with mouse/controller.
+ if (pSensor)
+ {
+ Quatf hmdOrient = SFusion.GetOrientation();
+ float yaw = 0.0f;
+
+ hmdOrient.GetEulerAngles<Axis_Y, Axis_X, Axis_Z>(&yaw, &EyePitch, &EyeRoll);
+
+ EyeYaw += (yaw - LastSensorYaw);
+ LastSensorYaw = yaw;
+ }
+
+
+ // Gamepad rotation.
+ EyeYaw -= GamepadRotate.x * dt;
+
+ if (!pSensor)
+ {
+ // Allow gamepad to look up/down, but only if there is no Rift sensor.
+ EyePitch -= GamepadRotate.y * dt;
+
+ const float maxPitch = ((3.1415f/2)*0.98f);
+ if (EyePitch > maxPitch)
+ EyePitch = maxPitch;
+ if (EyePitch < -maxPitch)
+ EyePitch = -maxPitch;
+ }
+
+ // Handle keyboard movement.
+ // This translates EyePos based on Yaw vector direction and keys pressed.
+ // Note that Pitch and Roll do not affect movement (they only affect view).
+ if (MoveForward || MoveBack || MoveLeft || MoveRight)
+ {
+ Vector3f localMoveVector(0,0,0);
+ Matrix4f yawRotate = Matrix4f::RotationY(EyeYaw);
+
+ if (MoveForward)
+ localMoveVector = ForwardVector;
+ else if (MoveBack)
+ localMoveVector = -ForwardVector;
+
+ if (MoveRight)
+ localMoveVector += RightVector;
+ else if (MoveLeft)
+ localMoveVector -= RightVector;
+
+ // Normalize vector so we don't move faster diagonally.
+ localMoveVector.Normalize();
+ Vector3f orientationVector = yawRotate.Transform(localMoveVector);
+ orientationVector *= MoveSpeed * dt * (ShiftDown ? 3.0f : 1.0f);
+
+ EyePos += orientationVector;
+ }
+
+ else if (GamepadMove.LengthSq() > 0)
+ {
+ Matrix4f yawRotate = Matrix4f::RotationY(EyeYaw);
+ Vector3f orientationVector = yawRotate.Transform(GamepadMove);
+ orientationVector *= MoveSpeed * dt;
+ EyePos += orientationVector;
+ }
+
+
+ // Rotate and position View Camera, using YawPitchRoll in BodyFrame coordinates.
+ //
+ Matrix4f rollPitchYaw = Matrix4f::RotationY(EyeYaw) * Matrix4f::RotationX(EyePitch) *
+ Matrix4f::RotationZ(EyeRoll);
+ Vector3f up = rollPitchYaw.Transform(UpVector);
+ Vector3f forward = rollPitchYaw.Transform(ForwardVector);
+
+
+ // Minimal head modelling.
+ float headBaseToEyeHeight = 0.15f; // Vertical height of eye from base of head
+ float headBaseToEyeProtrusion = 0.09f; // Distance forward of eye from base of head
+
+ Vector3f eyeCenterInHeadFrame(0.0f, headBaseToEyeHeight, -headBaseToEyeProtrusion);
+ Vector3f shiftedEyePos = EyePos + rollPitchYaw.Transform(eyeCenterInHeadFrame);
+ shiftedEyePos.y -= eyeCenterInHeadFrame.y; // Bring the head back down to original height
+
+ View = Matrix4f::LookAtRH(shiftedEyePos, shiftedEyePos + forward, up);
+
+ // This is what transformation would be without head modeling.
+ // View = Matrix4f::LookAtRH(EyePos, EyePos + forward, up);
+
+ switch(SConfig.GetStereoMode())
+ {
+ case Stereo_None:
+ Render(SConfig.GetEyeRenderParams(StereoEye_Center));
+ break;
+
+ case Stereo_LeftRight_Multipass:
+ Render(SConfig.GetEyeRenderParams(StereoEye_Left));
+ Render(SConfig.GetEyeRenderParams(StereoEye_Right));
+ break;
+ }
+
+ pRender->Present();
+ // Force GPU to flush the scene, resulting in the lowest possible latency.
+ pRender->ForceFlushGPU();
+}
+
+
+// Render the scene for one eye.
+void OculusRoomTinyApp::Render(const StereoEyeParams& stereo)
+{
+ pRender->BeginScene(PostProcess);
+
+ // Apply Viewport/Projection for the eye.
+ pRender->ApplyStereoParams(stereo);
+ pRender->Clear();
+ pRender->SetDepthMode(true, true);
+
+ Scene.Render(pRender, stereo.ViewAdjust * View);
+
+ pRender->FinishScene();
+}
+
+
+//-------------------------------------------------------------------------------------
+// ***** Win32-Specific Logic
+
+bool OculusRoomTinyApp::setupWindow()
+{
+
+ WNDCLASS wc;
+ memset(&wc, 0, sizeof(wc));
+ wc.lpszClassName = L"OVRAppWindow";
+ wc.style = CS_OWNDC;
+ wc.lpfnWndProc = systemWindowProc;
+ wc.cbWndExtra = sizeof(OculusRoomTinyApp*);
+ RegisterClass(&wc);
+
+
+ RECT winSize = { 0, 0, Width, Height };
+ AdjustWindowRect(&winSize, WS_POPUP, false);
+ hWnd = CreateWindowA("OVRAppWindow", "OculusRoomTiny", WS_POPUP|WS_VISIBLE,
+ HMDInfo.DesktopX, HMDInfo.DesktopY,
+ winSize.right-winSize.left, winSize.bottom-winSize.top,
+ NULL, NULL, hInstance, (LPVOID)this);
+
+
+ // Initialize Window center in screen coordinates
+ POINT center = { Width / 2, Height / 2 };
+ ::ClientToScreen(hWnd, &center);
+ WindowCenter = center;
+
+
+ return (hWnd != NULL);
+}
+
+void OculusRoomTinyApp::destroyWindow()
+{
+ pRender.Clear();
+
+ if (hWnd)
+ {
+ // Release window resources.
+ ::DestroyWindow(hWnd);
+ UnregisterClass(L"OVRAppWindow", hInstance);
+ hWnd = 0;
+ Width = Height = 0;
+ }
+}
+
+
+LRESULT CALLBACK OculusRoomTinyApp::systemWindowProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp)
+{
+ if (msg == WM_NCCREATE)
+ pApp->hWnd = hwnd;
+ return pApp->windowProc(msg, wp, lp);
+}
+
+void OculusRoomTinyApp::giveUsFocus(bool setFocus)
+{
+ if (setFocus)
+ {
+ ::SetCursorPos(WindowCenter.x, WindowCenter.y);
+
+ MouseCaptured = true;
+ ::SetCapture(hWnd);
+ ::ShowCursor(FALSE);
+
+ }
+ else
+ {
+ MouseCaptured = false;
+ ::ReleaseCapture();
+ ::ShowCursor(TRUE);
+ }
+}
+
+LRESULT OculusRoomTinyApp::windowProc(UINT msg, WPARAM wp, LPARAM lp)
+{
+ switch (msg)
+ {
+ case WM_MOUSEMOVE:
+ {
+ if (MouseCaptured)
+ {
+ // Convert mouse motion to be relative (report the offset and re-center).
+ POINT newPos = { LOWORD(lp), HIWORD(lp) };
+ ::ClientToScreen(hWnd, &newPos);
+ if ((newPos.x == WindowCenter.x) && (newPos.y == WindowCenter.y))
+ break;
+ ::SetCursorPos(WindowCenter.x, WindowCenter.y);
+
+ LONG dx = newPos.x - WindowCenter.x;
+ LONG dy = newPos.y - WindowCenter.y;
+ pApp->OnMouseMove(dx, dy, 0);
+ }
+ }
+ break;
+
+ case WM_MOVE:
+ {
+ RECT r;
+ GetClientRect(hWnd, &r);
+ WindowCenter.x = r.right/2;
+ WindowCenter.y = r.bottom/2;
+ ::ClientToScreen(hWnd, &WindowCenter);
+ }
+ break;
+
+ case WM_KEYDOWN:
+ OnKey((unsigned)wp, true);
+ break;
+ case WM_KEYUP:
+ OnKey((unsigned)wp, false);
+ break;
+
+ case WM_SETFOCUS:
+ giveUsFocus(true);
+ break;
+
+ case WM_KILLFOCUS:
+ giveUsFocus(false);
+ break;
+
+ case WM_CREATE:
+ // Hack to position mouse in fullscreen window shortly after startup.
+ SetTimer(hWnd, 0, 100, NULL);
+ break;
+
+ case WM_TIMER:
+ KillTimer(hWnd, 0);
+ giveUsFocus(true);
+ break;
+
+ case WM_QUIT:
+ case WM_CLOSE:
+ Quit = true;
+ return 0;
+ }
+
+ return DefWindowProc(hWnd, msg, wp, lp);
+}
+
+static inline float GamepadStick(short in)
+{
+ float v;
+ if (abs(in) < 9000)
+ return 0;
+ else if (in > 9000)
+ v = (float) in - 9000;
+ else
+ v = (float) in + 9000;
+ return v / (32767 - 9000);
+}
+
+static inline float GamepadTrigger(BYTE in)
+{
+ return (in < 30) ? 0.0f : (float(in-30) / 225);
+}
+
+
+int OculusRoomTinyApp::Run()
+{
+ // Loop processing messages until Quit flag is set,
+ // rendering game scene inside of OnIdle().
+
+ while (!Quit)
+ {
+ MSG msg;
+ if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
+ {
+ TranslateMessage(&msg);
+ DispatchMessage(&msg);
+ }
+ else
+ {
+ // Read game-pad.
+ XINPUT_STATE xis;
+
+ if (pXInputGetState && !pXInputGetState(0, &xis) &&
+ (xis.dwPacketNumber != LastPadPacketNo))
+ {
+ OnGamepad(GamepadStick(xis.Gamepad.sThumbLX),
+ GamepadStick(xis.Gamepad.sThumbLY),
+ GamepadStick(xis.Gamepad.sThumbRX),
+ GamepadStick(xis.Gamepad.sThumbRY));
+ //pad.LT = GamepadTrigger(xis.Gamepad.bLeftTrigger);
+ LastPadPacketNo = xis.dwPacketNumber;
+ }
+
+ pApp->OnIdle();
+
+ // Keep sleeping when we're minimized.
+ if (IsIconic(hWnd))
+ Sleep(10);
+ }
+ }
+
+ return 0;
+}
+
+
+//-------------------------------------------------------------------------------------
+// ***** Program Startup
+
+int WINAPI WinMain(HINSTANCE hinst, HINSTANCE, LPSTR inArgs, int)
+{
+ int exitCode = 0;
+
+ // Initializes LibOVR. This LogMask_All enables maximum logging.
+ // Custom allocator can also be specified here.
+ OVR::System::Init(OVR::Log::ConfigureDefaultLog(OVR::LogMask_All));
+
+ // Scope to force application destructor before System::Destroy.
+ {
+ OculusRoomTinyApp app(hinst);
+ //app.hInstance = hinst;
+
+ exitCode = app.OnStartup(inArgs);
+ if (!exitCode)
+ {
+ // Processes messages and calls OnIdle() to do rendering.
+ exitCode = app.Run();
+ }
+ }
+
+ // No OVR functions involving memory are allowed after this.
+ OVR::System::Destroy();
+
+ OVR_DEBUG_STATEMENT(_CrtDumpMemoryLeaks());
+ return exitCode;
+}
diff --git a/Samples/OculusRoomTiny/Win32_OculusRoomTiny.h b/Samples/OculusRoomTiny/Win32_OculusRoomTiny.h
index 5a0eedf..a86dd47 100644
--- a/Samples/OculusRoomTiny/Win32_OculusRoomTiny.h
+++ b/Samples/OculusRoomTiny/Win32_OculusRoomTiny.h
@@ -1,189 +1,189 @@
-/************************************************************************************
-
-Filename : OculusRoomTiny.h
-Content : Simplest possible first-person view test application for Oculus Rift
-Created : March 10, 2012
-Authors : Michael Antonov, Andrew Reisse
-
-Copyright : Copyright 2012 Oculus, Inc. All Rights reserved.
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-
-*************************************************************************************/
-#ifndef INC_OculusRoomTiny_h
-#define INC_OculusRoomTiny_h
-
-#include <Windows.h>
-#include <xinput.h>
-
-#include "OVR.h"
-#include "Util/Util_Render_Stereo.h"
-#include "../../LibOVR/Src/Kernel/OVR_Timer.h"
-#include "RenderTiny_D3D1X_Device.h"
-
-using namespace OVR;
-using namespace OVR::RenderTiny;
-
-
-//-------------------------------------------------------------------------------------
-// ***** OculusRoomTiny Description
-
-// This app renders a simple flat-shaded room allowing the user to move along the
-// floor and look around with an HMD, mouse, keyboard and gamepad.
-// By default, the application will start full-screen on Oculus Rift.
-//
-// The following keys work:
-//
-// 'W', 'S', 'A', 'D' - Move forward, back; strafe left/right.
-// F1 - No stereo, no distortion.
-// F2 - Stereo, no distortion.
-// F3 - Stereo and distortion.
-//
-
-// The world RHS coordinate system is defines as follows (as seen in perspective view):
-// Y - Up
-// Z - Back
-// X - Right
-const Vector3f UpVector(0.0f, 1.0f, 0.0f);
-const Vector3f ForwardVector(0.0f, 0.0f, -1.0f);
-const Vector3f RightVector(1.0f, 0.0f, 0.0f);
-
-// We start out looking in the positive Z (180 degree rotation).
-const float YawInitial = 3.141592f;
-const float Sensitivity = 1.0f;
-const float MoveSpeed = 3.0f; // m/s
-
-
-//-------------------------------------------------------------------------------------
-// ***** OculusRoomTiny Application class
-
-// An instance of this class is created on application startup (main/WinMain).
-//
-// It then works as follows:
-//
-// OnStartup - Window, graphics and HMD setup is done here.
-// This function will initialize OVR::DeviceManager and HMD,
-// creating SensorDevice and attaching it to SensorFusion.
-// This needs to be done before obtaining sensor data.
-//
-// OnIdle - Does per-frame processing, processing SensorFusion and
-// movement input and rendering the frame.
-
-class OculusRoomTinyApp : public MessageHandler
-{
-public:
- OculusRoomTinyApp(HINSTANCE hinst);
- ~OculusRoomTinyApp();
-
- // Initializes graphics, Rift input and creates world model.
- virtual int OnStartup(const char* args);
- // Called per frame to sample SensorFucion and render the world.
- virtual void OnIdle();
-
- // Installed for Oculus device messages. Optional.
- virtual void OnMessage(const Message& msg);
-
- // Handle input events for movement.
- virtual void OnGamepad(float padLx, float padLY, float padRx, float padRy);
- virtual void OnMouseMove(int x, int y, int modifiers);
- virtual void OnKey(unsigned vk, bool down);
-
- // Render the view for one eye.
- void Render(const StereoEyeParams& stereo);
-
- // Main application loop.
- int Run();
-
- // Return amount of time passed since application started in seconds.
- double GetAppTime() const
- {
- return (OVR::Timer::GetTicks() - StartupTicks) * (1.0 / (double)OVR::Timer::MksPerSecond);
- }
-
-
-protected:
-
- // Win32 window setup interface.
- LRESULT windowProc(UINT msg, WPARAM wp, LPARAM lp);
- bool setupWindow();
- void destroyWindow();
- // Win32 static function that delegates to WindowProc member function.
- static LRESULT CALLBACK systemWindowProc(HWND window, UINT msg, WPARAM wp, LPARAM lp);
-
- void giveUsFocus(bool setFocus);
-
- static OculusRoomTinyApp* pApp;
-
- // *** Rendering Variables
- Ptr<RenderDevice> pRender;
- RendererParams RenderParams;
- int Width, Height;
-
-
- // *** Win32 System Variables
- HWND hWnd;
- HINSTANCE hInstance;
- POINT WindowCenter; // In desktop coordinates
- bool Quit;
- bool MouseCaptured;
-
- // Dynamically ink to XInput to simplify projects.
- typedef DWORD (WINAPI *PFn_XInputGetState)(DWORD dwUserIndex, XINPUT_STATE* pState);
- PFn_XInputGetState pXInputGetState;
- HMODULE hXInputModule;
- UInt32 LastPadPacketNo;
-
-
- // *** Oculus HMD Variables
-
- Ptr<DeviceManager> pManager;
- Ptr<SensorDevice> pSensor;
- Ptr<HMDDevice> pHMD;
- SensorFusion SFusion;
- OVR::HMDInfo HMDInfo;
-
- // Last update seconds, used for move speed timing.
- double LastUpdate;
- UInt64 StartupTicks;
-
- // Position and look. The following apply:
- Vector3f EyePos;
- float EyeYaw; // Rotation around Y, CCW positive when looking at RHS (X,Z) plane.
- float EyePitch; // Pitch. If sensor is plugged in, only read from sensor.
- float EyeRoll; // Roll, only accessible from Sensor.
- float LastSensorYaw; // Stores previous Yaw value from to support computing delta.
-
- // Movement state; different bits may be set based on the state of keys.
- UByte MoveForward;
- UByte MoveBack;
- UByte MoveLeft;
- UByte MoveRight;
- Vector3f GamepadMove, GamepadRotate;
-
- Matrix4f View;
- RenderTiny::Scene Scene;
-
- // Stereo view parameters.
- StereoConfig SConfig;
- PostProcessType PostProcess;
-
- // Shift accelerates movement/adjustment velocity.
- bool ShiftDown;
- bool ControlDown;
-};
-
-// Adds sample models and lights to the argument scene.
-void PopulateRoomScene(Scene* scene, RenderDevice* render);
-
-
-#endif
+/************************************************************************************
+
+Filename : OculusRoomTiny.h
+Content : Simplest possible first-person view test application for Oculus Rift
+Created : March 10, 2012
+Authors : Michael Antonov, Andrew Reisse
+
+Copyright : Copyright 2012 Oculus, Inc. All Rights reserved.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+*************************************************************************************/
+#ifndef INC_OculusRoomTiny_h
+#define INC_OculusRoomTiny_h
+
+#include <Windows.h>
+#include <xinput.h>
+
+#include "OVR.h"
+#include "Util/Util_Render_Stereo.h"
+#include "../../LibOVR/Src/Kernel/OVR_Timer.h"
+#include "RenderTiny_D3D1X_Device.h"
+
+using namespace OVR;
+using namespace OVR::RenderTiny;
+
+
+//-------------------------------------------------------------------------------------
+// ***** OculusRoomTiny Description
+
+// This app renders a simple flat-shaded room allowing the user to move along the
+// floor and look around with an HMD, mouse, keyboard and gamepad.
+// By default, the application will start full-screen on Oculus Rift.
+//
+// The following keys work:
+//
+// 'W', 'S', 'A', 'D' - Move forward, back; strafe left/right.
+// F1 - No stereo, no distortion.
+// F2 - Stereo, no distortion.
+// F3 - Stereo and distortion.
+//
+
+// The world RHS coordinate system is defines as follows (as seen in perspective view):
+// Y - Up
+// Z - Back
+// X - Right
+const Vector3f UpVector(0.0f, 1.0f, 0.0f);
+const Vector3f ForwardVector(0.0f, 0.0f, -1.0f);
+const Vector3f RightVector(1.0f, 0.0f, 0.0f);
+
+// We start out looking in the positive Z (180 degree rotation).
+const float YawInitial = 3.141592f;
+const float Sensitivity = 1.0f;
+const float MoveSpeed = 3.0f; // m/s
+
+
+//-------------------------------------------------------------------------------------
+// ***** OculusRoomTiny Application class
+
+// An instance of this class is created on application startup (main/WinMain).
+//
+// It then works as follows:
+//
+// OnStartup - Window, graphics and HMD setup is done here.
+// This function will initialize OVR::DeviceManager and HMD,
+// creating SensorDevice and attaching it to SensorFusion.
+// This needs to be done before obtaining sensor data.
+//
+// OnIdle - Does per-frame processing, processing SensorFusion and
+// movement input and rendering the frame.
+
+class OculusRoomTinyApp : public MessageHandler
+{
+public:
+ OculusRoomTinyApp(HINSTANCE hinst);
+ ~OculusRoomTinyApp();
+
+ // Initializes graphics, Rift input and creates world model.
+ virtual int OnStartup(const char* args);
+ // Called per frame to sample SensorFucion and render the world.
+ virtual void OnIdle();
+
+ // Installed for Oculus device messages. Optional.
+ virtual void OnMessage(const Message& msg);
+
+ // Handle input events for movement.
+ virtual void OnGamepad(float padLx, float padLY, float padRx, float padRy);
+ virtual void OnMouseMove(int x, int y, int modifiers);
+ virtual void OnKey(unsigned vk, bool down);
+
+ // Render the view for one eye.
+ void Render(const StereoEyeParams& stereo);
+
+ // Main application loop.
+ int Run();
+
+ // Return amount of time passed since application started in seconds.
+ double GetAppTime() const
+ {
+ return (OVR::Timer::GetTicks() - StartupTicks) * (1.0 / (double)OVR::Timer::MksPerSecond);
+ }
+
+
+protected:
+
+ // Win32 window setup interface.
+ LRESULT windowProc(UINT msg, WPARAM wp, LPARAM lp);
+ bool setupWindow();
+ void destroyWindow();
+ // Win32 static function that delegates to WindowProc member function.
+ static LRESULT CALLBACK systemWindowProc(HWND window, UINT msg, WPARAM wp, LPARAM lp);
+
+ void giveUsFocus(bool setFocus);
+
+ static OculusRoomTinyApp* pApp;
+
+ // *** Rendering Variables
+ Ptr<RenderDevice> pRender;
+ RendererParams RenderParams;
+ int Width, Height;
+
+
+ // *** Win32 System Variables
+ HWND hWnd;
+ HINSTANCE hInstance;
+ POINT WindowCenter; // In desktop coordinates
+ bool Quit;
+ bool MouseCaptured;
+
+ // Dynamically ink to XInput to simplify projects.
+ typedef DWORD (WINAPI *PFn_XInputGetState)(DWORD dwUserIndex, XINPUT_STATE* pState);
+ PFn_XInputGetState pXInputGetState;
+ HMODULE hXInputModule;
+ UInt32 LastPadPacketNo;
+
+
+ // *** Oculus HMD Variables
+
+ Ptr<DeviceManager> pManager;
+ Ptr<SensorDevice> pSensor;
+ Ptr<HMDDevice> pHMD;
+ SensorFusion SFusion;
+ OVR::HMDInfo HMDInfo;
+
+ // Last update seconds, used for move speed timing.
+ double LastUpdate;
+ UInt64 StartupTicks;
+
+ // Position and look. The following apply:
+ Vector3f EyePos;
+ float EyeYaw; // Rotation around Y, CCW positive when looking at RHS (X,Z) plane.
+ float EyePitch; // Pitch. If sensor is plugged in, only read from sensor.
+ float EyeRoll; // Roll, only accessible from Sensor.
+ float LastSensorYaw; // Stores previous Yaw value from to support computing delta.
+
+ // Movement state; different bits may be set based on the state of keys.
+ UByte MoveForward;
+ UByte MoveBack;
+ UByte MoveLeft;
+ UByte MoveRight;
+ Vector3f GamepadMove, GamepadRotate;
+
+ Matrix4f View;
+ RenderTiny::Scene Scene;
+
+ // Stereo view parameters.
+ StereoConfig SConfig;
+ PostProcessType PostProcess;
+
+ // Shift accelerates movement/adjustment velocity.
+ bool ShiftDown;
+ bool ControlDown;
+};
+
+// Adds sample models and lights to the argument scene.
+void PopulateRoomScene(Scene* scene, RenderDevice* render);
+
+
+#endif