diff options
Diffstat (limited to 'Samples/OculusRoomTiny')
-rw-r--r-- | Samples/OculusRoomTiny/OSX_OculusRoomTiny.h | 446 | ||||
-rw-r--r-- | Samples/OculusRoomTiny/OSX_OculusRoomTiny.mm | 1722 | ||||
-rw-r--r-- | Samples/OculusRoomTiny/OculusRoomModel.cpp | 520 | ||||
-rw-r--r-- | Samples/OculusRoomTiny/OculusRoomTiny_Msvc2010.vcxproj | 372 | ||||
-rw-r--r-- | Samples/OculusRoomTiny/OculusRoomTiny_Msvc2010.vcxproj.filters | 32 | ||||
-rw-r--r-- | Samples/OculusRoomTiny/RenderTiny_D3D1X_Device.cpp | 2622 | ||||
-rw-r--r-- | Samples/OculusRoomTiny/RenderTiny_D3D1X_Device.h | 546 | ||||
-rw-r--r-- | Samples/OculusRoomTiny/RenderTiny_Device.cpp | 884 | ||||
-rw-r--r-- | Samples/OculusRoomTiny/RenderTiny_Device.h | 1448 | ||||
-rw-r--r-- | Samples/OculusRoomTiny/RenderTiny_GL_Device.cpp | 1568 | ||||
-rw-r--r-- | Samples/OculusRoomTiny/RenderTiny_GL_Device.h | 456 | ||||
-rw-r--r-- | Samples/OculusRoomTiny/Win32_OculusRoomTiny.cpp | 1424 | ||||
-rw-r--r-- | Samples/OculusRoomTiny/Win32_OculusRoomTiny.h | 378 |
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, ¢er);
- 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, ¢er); + 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 |