From 07d0f4d0bbf3477ac6a9584f726e8ec6ab285707 Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Mon, 14 Apr 2014 21:25:09 -0700 Subject: Adding windows 0.3.1 SDK --- Samples/OculusRoomTiny/OSX_OculusRoomTiny.h | 223 --- Samples/OculusRoomTiny/OSX_OculusRoomTiny.mm | 861 ----------- Samples/OculusRoomTiny/OSX_OculusRoomTiny2.h | 223 +++ Samples/OculusRoomTiny/OculusRoomModel.cpp | 8 +- Samples/OculusRoomTiny/OculusRoomTiny.rc | Bin 144 -> 0 bytes Samples/OculusRoomTiny/OculusRoomTiny2.rc | Bin 0 -> 144 bytes .../OculusRoomTiny/OculusRoomTiny_Msvc2010.vcxproj | 187 --- .../OculusRoomTiny_Msvc2010.vcxproj.filters | 17 - .../Projects/Win/VS2010/OculusRoomTiny.vcxproj | 189 +++ .../Win/VS2010/OculusRoomTiny.vcxproj.filters | 26 + .../Projects/Win/VS2012/OculusRoomTiny.vcxproj | 197 +++ .../Win/VS2012/OculusRoomTiny.vcxproj.filters | 26 + .../Projects/Win/VS2013/OculusRoomTiny.vcxproj | 208 +++ .../Win/VS2013/OculusRoomTiny.vcxproj.filters | 29 + Samples/OculusRoomTiny/RenderTiny_D3D11_Device.cpp | 1556 ++++++++++++++++++++ Samples/OculusRoomTiny/RenderTiny_D3D11_Device.h | 824 +++++++++++ Samples/OculusRoomTiny/RenderTiny_D3D1X_Device.cpp | 1311 ----------------- Samples/OculusRoomTiny/RenderTiny_D3D1X_Device.h | 273 ---- Samples/OculusRoomTiny/RenderTiny_Device.cpp | 442 ------ Samples/OculusRoomTiny/RenderTiny_Device.h | 724 --------- Samples/OculusRoomTiny/RenderTiny_GL_Device.cpp | 784 ---------- Samples/OculusRoomTiny/RenderTiny_GL_Device.h | 228 --- Samples/OculusRoomTiny/Win32_DistortionMesh.cpp | 244 +++ Samples/OculusRoomTiny/Win32_OculusRoomTiny.cpp | 876 +++-------- Samples/OculusRoomTiny/Win32_OculusRoomTiny.h | 189 --- .../OculusRoomTiny/Win32_OculusRoomTiny_Util.cpp | 254 ++++ 26 files changed, 4005 insertions(+), 5894 deletions(-) delete mode 100644 Samples/OculusRoomTiny/OSX_OculusRoomTiny.h delete mode 100644 Samples/OculusRoomTiny/OSX_OculusRoomTiny.mm create mode 100644 Samples/OculusRoomTiny/OSX_OculusRoomTiny2.h delete mode 100644 Samples/OculusRoomTiny/OculusRoomTiny.rc create mode 100644 Samples/OculusRoomTiny/OculusRoomTiny2.rc delete mode 100644 Samples/OculusRoomTiny/OculusRoomTiny_Msvc2010.vcxproj delete mode 100644 Samples/OculusRoomTiny/OculusRoomTiny_Msvc2010.vcxproj.filters create mode 100644 Samples/OculusRoomTiny/Projects/Win/VS2010/OculusRoomTiny.vcxproj create mode 100644 Samples/OculusRoomTiny/Projects/Win/VS2010/OculusRoomTiny.vcxproj.filters create mode 100644 Samples/OculusRoomTiny/Projects/Win/VS2012/OculusRoomTiny.vcxproj create mode 100644 Samples/OculusRoomTiny/Projects/Win/VS2012/OculusRoomTiny.vcxproj.filters create mode 100644 Samples/OculusRoomTiny/Projects/Win/VS2013/OculusRoomTiny.vcxproj create mode 100644 Samples/OculusRoomTiny/Projects/Win/VS2013/OculusRoomTiny.vcxproj.filters create mode 100644 Samples/OculusRoomTiny/RenderTiny_D3D11_Device.cpp create mode 100644 Samples/OculusRoomTiny/RenderTiny_D3D11_Device.h delete mode 100644 Samples/OculusRoomTiny/RenderTiny_D3D1X_Device.cpp delete mode 100644 Samples/OculusRoomTiny/RenderTiny_D3D1X_Device.h delete mode 100644 Samples/OculusRoomTiny/RenderTiny_Device.cpp delete mode 100644 Samples/OculusRoomTiny/RenderTiny_Device.h delete mode 100644 Samples/OculusRoomTiny/RenderTiny_GL_Device.cpp delete mode 100644 Samples/OculusRoomTiny/RenderTiny_GL_Device.h create mode 100644 Samples/OculusRoomTiny/Win32_DistortionMesh.cpp delete mode 100644 Samples/OculusRoomTiny/Win32_OculusRoomTiny.h create mode 100644 Samples/OculusRoomTiny/Win32_OculusRoomTiny_Util.cpp (limited to 'Samples/OculusRoomTiny') diff --git a/Samples/OculusRoomTiny/OSX_OculusRoomTiny.h b/Samples/OculusRoomTiny/OSX_OculusRoomTiny.h deleted file mode 100644 index 280fda5..0000000 --- a/Samples/OculusRoomTiny/OSX_OculusRoomTiny.h +++ /dev/null @@ -1,223 +0,0 @@ -/************************************************************************************ - - 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 - -#import -#import - - -#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 - -//@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 pRender; - RendererParams RenderParams; - int Width, Height; - - bool Quit; - - // *** Oculus HMD Variables - - Ptr pManager; - Ptr pSensor; - Ptr 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 deleted file mode 100644 index 7c5d81f..0000000 --- a/Samples/OculusRoomTiny/OSX_OculusRoomTiny.mm +++ /dev/null @@ -1,861 +0,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().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().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(&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/OSX_OculusRoomTiny2.h b/Samples/OculusRoomTiny/OSX_OculusRoomTiny2.h new file mode 100644 index 0000000..ff5ad5e --- /dev/null +++ b/Samples/OculusRoomTiny/OSX_OculusRoomTiny2.h @@ -0,0 +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 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_OSX_OculusRoomTiny_h +#define INC_OSX_OculusRoomTiny_h + +#import + +#import +#import + + +#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 + +//@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 pRender; + RendererParams RenderParams; + int Width, Height; + + bool Quit; + + // *** Oculus HMD Variables + + Ptr pManager; + Ptr pSensor; + Ptr 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/OculusRoomModel.cpp b/Samples/OculusRoomTiny/OculusRoomModel.cpp index e12751a..f425be0 100644 --- a/Samples/OculusRoomTiny/OculusRoomModel.cpp +++ b/Samples/OculusRoomTiny/OculusRoomModel.cpp @@ -4,7 +4,7 @@ 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. +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. @@ -20,11 +20,7 @@ limitations under the License. *************************************************************************************/ -#include "RenderTiny_Device.h" - -using namespace OVR; -using namespace OVR::RenderTiny; - +#include "RenderTiny_D3D11_Device.h" //------------------------------------------------------------------------------------- // ***** Room Model diff --git a/Samples/OculusRoomTiny/OculusRoomTiny.rc b/Samples/OculusRoomTiny/OculusRoomTiny.rc deleted file mode 100644 index 49a6a5a..0000000 Binary files a/Samples/OculusRoomTiny/OculusRoomTiny.rc and /dev/null differ diff --git a/Samples/OculusRoomTiny/OculusRoomTiny2.rc b/Samples/OculusRoomTiny/OculusRoomTiny2.rc new file mode 100644 index 0000000..49a6a5a Binary files /dev/null and b/Samples/OculusRoomTiny/OculusRoomTiny2.rc differ diff --git a/Samples/OculusRoomTiny/OculusRoomTiny_Msvc2010.vcxproj b/Samples/OculusRoomTiny/OculusRoomTiny_Msvc2010.vcxproj deleted file mode 100644 index 4bc37a8..0000000 --- a/Samples/OculusRoomTiny/OculusRoomTiny_Msvc2010.vcxproj +++ /dev/null @@ -1,187 +0,0 @@ - - - - - Debug - Win32 - - - Debug - x64 - - - Release - Win32 - - - Release - x64 - - - - {80523489-2881-4F64-8C3B-FAF88B60ABCD} - Win32Proj - OculusRoomTiny - OculusRoomTiny - - - - Application - true - Unicode - - - Application - true - Unicode - - - Application - false - true - Unicode - - - Application - false - true - Unicode - - - - - - - - - - - - - - - - - - - true - $(Configuration)\Obj\ - $(ProjectDir)$(Configuration)\ - - - true - $(Configuration)\Obj\ - $(ProjectDir)$(Configuration)\ - - - false - $(Configuration)\Obj\ - $(ProjectDir)$(Configuration)\ - - - false - $(Configuration)\Obj\ - $(ProjectDir)$(Configuration)\ - - - - - - Level4 - Disabled - OVR_BUILD_DEBUG;WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions) - ../../LibOVR/Include;../../LibOVR/Src;../../3rdParty/glext;$(DXSDK_DIR)/Include;%(AdditionalIncludeDirectories) - OldStyle - true - false - - - Windows - true - 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) - ../../LibOVR/Lib/Win32;$(DXSDK_DIR)/Lib/x86;%(AdditionalLibraryDirectories) - - - - - - - Level4 - Disabled - OVR_BUILD_DEBUG;WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions) - ../../LibOVR/Include;../../LibOVR/Src;../../3rdParty/glext;$(DXSDK_DIR)/Include;%(AdditionalIncludeDirectories) - OldStyle - true - false - - - Windows - true - 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) - ../../LibOVR/Lib/x64;$(DXSDK_DIR)/Lib/x64;%(AdditionalLibraryDirectories) - - - - - Level4 - - - MaxSpeed - true - true - WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions) - ../../LibOVR/Include;../../LibOVR/Src;../../3rdParty/glext;$(DXSDK_DIR)/Include;%(AdditionalIncludeDirectories) - MultiThreaded - true - OldStyle - - - Windows - false - true - true - ../../LibOVR/Lib/Win32;$(DXSDK_DIR)/Lib/x86;%(AdditionalLibraryDirectories) - 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) - - - - - Level4 - - - MaxSpeed - true - true - WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions) - ../../LibOVR/Include;../../LibOVR/Src;../../3rdParty/glext;$(DXSDK_DIR)/Include;%(AdditionalIncludeDirectories) - MultiThreaded - true - OldStyle - - - Windows - true - true - true - ../../LibOVR/Lib/x64;$(DXSDK_DIR)/Lib/x64;%(AdditionalLibraryDirectories) - 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) - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/Samples/OculusRoomTiny/OculusRoomTiny_Msvc2010.vcxproj.filters b/Samples/OculusRoomTiny/OculusRoomTiny_Msvc2010.vcxproj.filters deleted file mode 100644 index 3c09bd5..0000000 --- a/Samples/OculusRoomTiny/OculusRoomTiny_Msvc2010.vcxproj.filters +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/Samples/OculusRoomTiny/Projects/Win/VS2010/OculusRoomTiny.vcxproj b/Samples/OculusRoomTiny/Projects/Win/VS2010/OculusRoomTiny.vcxproj new file mode 100644 index 0000000..d6bb3e7 --- /dev/null +++ b/Samples/OculusRoomTiny/Projects/Win/VS2010/OculusRoomTiny.vcxproj @@ -0,0 +1,189 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + {6C6ECAC4-DB5C-4301-8371-9C7CC8C623C2} + Win32Proj + OculusRoomTiny + OculusRoomTiny + + + + Application + true + Unicode + + + Application + true + Unicode + + + Application + false + true + Unicode + + + Application + false + true + Unicode + + + + + + + + + + + + + + + + + + + true + $(ProjectDir)../../../Obj/Win/VS2010/$(Configuration)/$(PlatformName)/ + $(ProjectDir)../../../Bin/Win/VS2010/$(Configuration)/$(PlatformName)/ + OculusRoomTiny + + + true + $(ProjectDir)../../../Obj/Win/VS2010/$(Configuration)/$(PlatformName)/ + $(ProjectDir)../../../Bin/Win/VS2010/$(Configuration)/$(PlatformName)/ + OculusRoomTiny + + + false + $(ProjectDir)../../../Obj/Win/VS2010/$(Configuration)/$(PlatformName)/ + $(ProjectDir)../../../Bin/Win/VS2010/$(Configuration)/$(PlatformName)/ + OculusRoomTiny + + + false + $(ProjectDir)../../../Obj/Win/VS2010/$(Configuration)/$(PlatformName)/ + $(ProjectDir)../../../Bin/Win/VS2010/$(Configuration)/$(PlatformName)/ + OculusRoomTiny + + + + + + Level4 + Disabled + OVR_BUILD_DEBUG;WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions) + ../../../../../LibOVR/Include;../../../../../LibOVR/Src;$(DXSDK_DIR)/Include;%(AdditionalIncludeDirectories) + OldStyle + true + false + MultiThreadedDebug + + + Windows + true + opengl32.lib;libovrd.lib;d3dx11.lib;dxgi.lib;dxguid.lib;d3d10.lib;d3d11.lib;d3dcompiler.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) + ../../../../../LibOVR/Lib/$(Platform)/VS2010/;$(DXSDK_DIR)/Lib/x86;%(AdditionalLibraryDirectories) + + + + + + + Level4 + Disabled + OVR_BUILD_DEBUG;WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions) + ../../../../../LibOVR/Include;../../../../../LibOVR/Src;$(DXSDK_DIR)/Include;%(AdditionalIncludeDirectories) + OldStyle + true + false + MultiThreadedDebug + + + Windows + true + opengl32.lib;libovr64d.lib;dxgi.lib;dxguid.lib;d3d10.lib;d3d11.lib;d3dcompiler.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) + ../../../../../LibOVR/Lib/$(Platform)/VS2010/;$(DXSDK_DIR)/Lib/x64;%(AdditionalLibraryDirectories) + + + + + Level4 + + + MaxSpeed + true + true + WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions) + ../../../../../LibOVR/Include;../../../../../LibOVR/Src;$(DXSDK_DIR)/Include;%(AdditionalIncludeDirectories) + MultiThreaded + true + OldStyle + + + Windows + false + true + true + ../../../../../LibOVR/Lib/$(Platform)/VS2010/;$(DXSDK_DIR)/Lib/x86;%(AdditionalLibraryDirectories) + opengl32.lib;libovr.lib;dxguid.lib;dxgi.lib;d3dx11.lib;d3d10.lib;d3d11.lib;d3dcompiler.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) + + + + + Level4 + + + MaxSpeed + true + true + WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions) + ../../../../../LibOVR/Include;../../../../../LibOVR/Src;$(DXSDK_DIR)/Include;%(AdditionalIncludeDirectories) + MultiThreaded + true + OldStyle + + + Windows + true + true + true + ../../../../../LibOVR/Lib/$(Platform)/VS2010/;$(DXSDK_DIR)/Lib/x64;../../../../../3rdParty/Point Grey Research/FlyCapture2/lib64;%(AdditionalLibraryDirectories) + opengl32.lib;libovr64.lib;dxgi.lib;dxguid.lib;d3d10.lib;d3d11.lib;d3dcompiler.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) + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Samples/OculusRoomTiny/Projects/Win/VS2010/OculusRoomTiny.vcxproj.filters b/Samples/OculusRoomTiny/Projects/Win/VS2010/OculusRoomTiny.vcxproj.filters new file mode 100644 index 0000000..8c02afc --- /dev/null +++ b/Samples/OculusRoomTiny/Projects/Win/VS2010/OculusRoomTiny.vcxproj.filters @@ -0,0 +1,26 @@ + + + + + Util + + + Util + + + Util + + + + + + + Util + + + + + {0750679b-ec1e-44c8-a78b-05d9e58a3588} + + + \ No newline at end of file diff --git a/Samples/OculusRoomTiny/Projects/Win/VS2012/OculusRoomTiny.vcxproj b/Samples/OculusRoomTiny/Projects/Win/VS2012/OculusRoomTiny.vcxproj new file mode 100644 index 0000000..b547f70 --- /dev/null +++ b/Samples/OculusRoomTiny/Projects/Win/VS2012/OculusRoomTiny.vcxproj @@ -0,0 +1,197 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + {5736727A-FEB0-49C0-B63A-36BF0FEB4FF3} + Win32Proj + OculusRoomTiny + OculusRoomTiny + + + + Application + true + Unicode + v110 + + + Application + true + Unicode + v110 + + + Application + false + true + Unicode + v110 + + + Application + false + true + Unicode + v110 + + + + + + + + + + + + + + + + + + + true + $(ProjectDir)../../../Obj/Win/VS2012/$(Configuration)/$(PlatformName)/ + $(ProjectDir)../../../Bin/Win/VS2012/$(Configuration)/$(PlatformName)/ + OculusRookTiny + + + true + $(ProjectDir)../../../Obj/Win/VS2012/$(Configuration)/$(PlatformName)/ + $(ProjectDir)../../../Bin/Win/VS2012/$(Configuration)/$(PlatformName)/ + OculusRookTiny + + + false + $(ProjectDir)../../../Obj/Win/VS2012/$(Configuration)/$(PlatformName)/ + $(ProjectDir)../../../Bin/Win/VS2012/$(Configuration)/$(PlatformName)/ + OculusRookTiny + + + false + $(ProjectDir)../../../Obj/Win/VS2012/$(Configuration)/$(PlatformName)/ + $(ProjectDir)../../../Bin/Win/VS2012/$(Configuration)/$(PlatformName)/ + OculusRookTiny + + + + + + Level4 + Disabled + OVR_BUILD_DEBUG;WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions) + ../../../../../LibOVR/Include;../../../../../3rdParty/glext;../../../../../LibOVR/Src;%(AdditionalIncludeDirectories) + OldStyle + true + false + MultiThreadedDebug + + + Windows + true + opengl32.lib;libovrd.lib;dxgi.lib;dxguid.lib;d3d10.lib;d3d11.lib;d3dcompiler.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) + ../../../../../LibOVR/Lib/$(PlatformName)/VS2012/;%(AdditionalLibraryDirectories) + + + + + + + Level4 + Disabled + OVR_BUILD_DEBUG;WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions) + ../../../../../LibOVR/Include;../../../../../3rdParty/glext;../../../../../LibOVR/Src;%(AdditionalIncludeDirectories) + OldStyle + true + false + MultiThreadedDebug + + + Windows + true + opengl32.lib;libovr64d.lib;dxgi.lib;dxguid.lib;d3d10.lib;d3d11.lib;d3dcompiler.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) + ../../../../../LibOVR/Lib/$(PlatformName)/VS2012/;%(AdditionalLibraryDirectories) + + + + + Level4 + + + MaxSpeed + true + true + WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions) + ../../../../../LibOVR/Include;../../../../../3rdParty/glext;../../../../../LibOVR/Src;%(AdditionalIncludeDirectories) + MultiThreaded + true + OldStyle + false + /d2Zi+ %(AdditionalOptions) + + + Windows + false + true + true + ../../../../../LibOVR/Lib/$(PlatformName)/VS2012/;%(AdditionalLibraryDirectories) + opengl32.lib;libovr.lib;dxguid.lib;dxgi.lib;d3d10.lib;d3d11.lib;d3dcompiler.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) + + + + + Level4 + + + MaxSpeed + true + true + WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions) + ../../../../../LibOVR/Include;../../../../../3rdParty/glext;../../../../../LibOVR/Src;%(AdditionalIncludeDirectories) + MultiThreaded + true + OldStyle + false + /d2Zi+ %(AdditionalOptions) + + + Windows + true + true + true + ../../../../../LibOVR/Lib/$(PlatformName)/VS2012/;%(AdditionalLibraryDirectories) + opengl32.lib;libovr64.lib;dxgi.lib;dxguid.lib;d3d10.lib;d3d11.lib;d3dcompiler.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) + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Samples/OculusRoomTiny/Projects/Win/VS2012/OculusRoomTiny.vcxproj.filters b/Samples/OculusRoomTiny/Projects/Win/VS2012/OculusRoomTiny.vcxproj.filters new file mode 100644 index 0000000..0847db0 --- /dev/null +++ b/Samples/OculusRoomTiny/Projects/Win/VS2012/OculusRoomTiny.vcxproj.filters @@ -0,0 +1,26 @@ + + + + + + + Util + + + Util + + + Util + + + + + {0750679b-ec1e-44c8-a78b-05d9e58a3588} + + + + + Util + + + \ No newline at end of file diff --git a/Samples/OculusRoomTiny/Projects/Win/VS2013/OculusRoomTiny.vcxproj b/Samples/OculusRoomTiny/Projects/Win/VS2013/OculusRoomTiny.vcxproj new file mode 100644 index 0000000..e09a883 --- /dev/null +++ b/Samples/OculusRoomTiny/Projects/Win/VS2013/OculusRoomTiny.vcxproj @@ -0,0 +1,208 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + {394FF596-A90B-4C95-888B-B743834ED15B} + Win32Proj + OculusRoomTiny + OculusRoomTiny + + + + Application + true + Unicode + v120 + + + Application + true + Unicode + v120 + + + Application + false + true + Unicode + v120 + + + Application + false + true + Unicode + v120 + + + + + + + + + + + + + + + + + + + true + $(ProjectDir)../../../Obj/Win/VS2013/$(Configuration)/$(PlatformName)/ + $(ProjectDir)../../../Bin/Win/VS2013/$(Configuration)/$(PlatformName)/ + $(VC_IncludePath);$(WindowsSDK_IncludePath); + $(VC_LibraryPath_x86);$(WindowsSDK_LibraryPath_x86); + OculusRoomTiny + + + true + $(ProjectDir)../../../Obj/Win/VS2013/$(Configuration)/$(PlatformName)/ + $(ProjectDir)../../../Bin/Win/VS2013/$(Configuration)/$(PlatformName)/ + $(VC_IncludePath);$(WindowsSDK_IncludePath); + $(VC_LibraryPath_x64);$(WindowsSDK_LibraryPath_x64); + OculusRoomTiny + + + false + $(ProjectDir)../../../Obj/Win/VS2013/$(Configuration)/$(PlatformName)/ + $(ProjectDir)../../../Bin/Win/VS2013/$(Configuration)/$(PlatformName)/ + $(VC_IncludePath);$(WindowsSDK_IncludePath); + $(VC_LibraryPath_x86);$(WindowsSDK_LibraryPath_x86); + OculusRoomTiny + + + false + $(ProjectDir)../../../Obj/Win/VS2013/$(Configuration)/$(PlatformName)/ + $(ProjectDir)../../../Bin/Win/VS2013/$(Configuration)/$(PlatformName)/ + $(VC_IncludePath);$(WindowsSDK_IncludePath); + $(VC_LibraryPath_x64);$(WindowsSDK_LibraryPath_x64); + OculusRoomTiny + + + + + + Level4 + Disabled + OVR_BUILD_DEBUG;WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions) + ../../../../../LibOVR/Include;../../../../../LibOVR/Src;%(AdditionalIncludeDirectories) + OldStyle + true + false + MultiThreadedDebug + + + Windows + true + opengl32.lib;libovrd.lib;dxgi.lib;dxguid.lib;d3d10.lib;d3d11.lib;d3dcompiler.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) + ../../../../../LibOVR/Lib/Win32/VS2013/;%(AdditionalLibraryDirectories) + + + + + + + Level4 + Disabled + OVR_BUILD_DEBUG;_WIN64;_DEBUG;_WINDOWS;%(PreprocessorDefinitions) + ../../../../../LibOVR/Include;../../../../../LibOVR/Src;%(AdditionalIncludeDirectories) + OldStyle + true + false + MultiThreadedDebug + + + Windows + true + opengl32.lib;libovr64d.lib;dxgi.lib;dxguid.lib;d3d10.lib;d3d11.lib;d3dcompiler.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) + ../../../../../LibOVR/Lib/x64/VS2013/;%(AdditionalLibraryDirectories) + + + + + Level4 + + + MaxSpeed + true + true + WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions) + ../../../../../LibOVR/Include;../../../../../LibOVR/Src;%(AdditionalIncludeDirectories) + MultiThreaded + true + OldStyle + false + /d2Zi+ %(AdditionalOptions) + + + Windows + false + true + true + ../../../../../LibOVR/Lib/Win32/VS2013/;%(AdditionalLibraryDirectories) + opengl32.lib;libovr.lib;dxguid.lib;dxgi.lib;d3d10.lib;d3d11.lib;d3dcompiler.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) + + + + + Level4 + + + MaxSpeed + true + true + _WIN64;NDEBUG;_WINDOWS;%(PreprocessorDefinitions) + ../../../../../LibOVR/Include;../../../../../LibOVR/Src;%(AdditionalIncludeDirectories) + MultiThreaded + true + OldStyle + false + /d2Zi+ %(AdditionalOptions) + + + Windows + true + true + true + ../../../../../LibOVR/Lib/x64/VS2013/;%(AdditionalLibraryDirectories) + opengl32.lib;libovr64.lib;dxguid.lib;dxgi.lib;d3d10.lib;d3d11.lib;d3dcompiler.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) + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Samples/OculusRoomTiny/Projects/Win/VS2013/OculusRoomTiny.vcxproj.filters b/Samples/OculusRoomTiny/Projects/Win/VS2013/OculusRoomTiny.vcxproj.filters new file mode 100644 index 0000000..6df3291 --- /dev/null +++ b/Samples/OculusRoomTiny/Projects/Win/VS2013/OculusRoomTiny.vcxproj.filters @@ -0,0 +1,29 @@ + + + + + + + Util + + + Util + + + Util + + + + + + + + {aa2ef577-a403-4088-a39c-0a87a96151a9} + + + + + Util + + + \ No newline at end of file diff --git a/Samples/OculusRoomTiny/RenderTiny_D3D11_Device.cpp b/Samples/OculusRoomTiny/RenderTiny_D3D11_Device.cpp new file mode 100644 index 0000000..964c81c --- /dev/null +++ b/Samples/OculusRoomTiny/RenderTiny_D3D11_Device.cpp @@ -0,0 +1,1556 @@ +/************************************************************************************ + +Filename : RenderTiny_D3D11.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 "RenderTiny_D3D11_Device.h" +#include "Kernel/OVR_Log.h" +#include + + + + +namespace OVR { namespace RenderTiny { + + +//------------------------------------------------------------------------------------- +// Vertex format +static D3D11_INPUT_ELEMENT_DESC ModelVertexDesc[] = +{ + {"Position", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, offsetof(Vertex, Pos), D3D11_INPUT_PER_VERTEX_DATA, 0}, + {"Color", 0, DXGI_FORMAT_R8G8B8A8_UNORM, 0, offsetof(Vertex, C), D3D11_INPUT_PER_VERTEX_DATA, 0}, + {"TexCoord", 0, DXGI_FORMAT_R32G32_FLOAT, 0, offsetof(Vertex, U), D3D11_INPUT_PER_VERTEX_DATA, 0}, + {"Normal", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, offsetof(Vertex, Norm), D3D11_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"; + + +static const char* VShaderSrcs[VShader_Count] = +{ + DirectVertexShaderSrc, + StdVertexShaderSrc + +}; +static const char* FShaderSrcs[FShader_Count] = +{ + SolidPixelShaderSrc, + GouraudPixelShaderSrc, + TexturePixelShaderSrc, + LitSolidPixelShaderSrc, + LitTexturePixelShaderSrc +}; + + +//------------------------------------------------------------------------------------- +// ***** 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; + } + + D3D11_BUFFER_DESC desc; + memset(&desc, 0, sizeof(desc)); + if (use & Buffer_ReadOnly) + { + desc.Usage = D3D11_USAGE_IMMUTABLE; + desc.CPUAccessFlags = 0; + } + else + { + desc.Usage = D3D11_USAGE_DYNAMIC; + desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + Dynamic = 1; + } + + switch(use & Buffer_TypeMask) + { + case Buffer_Vertex: desc.BindFlags = D3D11_BIND_VERTEX_BUFFER; break; + case Buffer_Index: desc.BindFlags = D3D11_BIND_INDEX_BUFFER; break; + case Buffer_Uniform: + desc.BindFlags = D3D11_BIND_CONSTANT_BUFFER; + size += ((size + 15) & ~15) - size; + break; + } + + desc.ByteWidth = (unsigned)size; + + D3D11_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); + + D3D11_MAP mapFlags = D3D11_MAP_WRITE; + if (flags & Map_Discard) + mapFlags = D3D11_MAP_WRITE_DISCARD; + if (flags & Map_Unsynchronized) + mapFlags = D3D11_MAP_WRITE_NO_OVERWRITE; + + D3D11_MAPPED_SUBRESOURCE map; + if (SUCCEEDED(Ren->Context->Map(D3DBuffer, 0, mapFlags, 0, &map))) + return ((char*)map.pData) + start; + else + return NULL; +} + +bool Buffer::Unmap(void *m) +{ + OVR_UNUSED(m); + + Ren->Context->Unmap(D3DBuffer, 0); + return true; +} + + +//------------------------------------------------------------------------------------- +// Shaders + +template<> bool Shader::Load(void* shader, size_t size) +{ + return SUCCEEDED(Ren->Device->CreateVertexShader(shader, size, NULL, &D3DShader)); +} +template<> bool Shader::Load(void* shader, size_t size) +{ + return SUCCEEDED(Ren->Device->CreatePixelShader(shader, size, NULL, &D3DShader)); +} + +template<> void Shader::Set(PrimitiveType) const +{ + Ren->Context->VSSetShader(D3DShader, NULL, 0); +} +template<> void Shader::Set(PrimitiveType) const +{ + Ren->Context->PSSetShader(D3DShader, NULL, 0); +} + +template<> void Shader::SetUniformBuffer(Buffer* buffer, int i) +{ + Ren->Context->VSSetConstantBuffers(i, 1, &((Buffer*)buffer)->D3DBuffer.GetRawRef()); +} +template<> void Shader::SetUniformBuffer(Buffer* buffer, int i) +{ + Ren->Context->PSSetConstantBuffers(i, 1, &((Buffer*)buffer)->D3DBuffer.GetRawRef()); +} + + +//------------------------------------------------------------------------------------- +// ***** Shader Base + +ShaderBase::ShaderBase(RenderDevice* r, ShaderStage stage) + : Stage(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; +} + +bool ShaderBase::SetUniformBool(const char* name, int n, const bool* v) +{ + OVR_UNUSED(n); + + for(unsigned i = 0; i < UniformInfo.GetSize(); i++) + { + if (!strcmp(UniformInfo[i].Name.ToCStr(), name)) + { + memcpy(UniformData + UniformInfo[i].Offset, v, UniformInfo[i].Size); + return 1; + } + } + return 0; +} + +void ShaderBase::InitUniforms(ID3D10Blob* s) +{ + InitUniforms(s->GetBufferPointer(), s->GetBufferSize()); +} + +void ShaderBase::InitUniforms(void* s, size_t size) +{ + ID3D11ShaderReflection* ref = NULL; + D3DReflect(s, size, IID_ID3D11ShaderReflection, (void**) &ref); + ID3D11ShaderReflectionConstantBuffer* buf = ref->GetConstantBufferByIndex(0); + D3D11_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++) + { + ID3D11ShaderReflectionVariable* var = buf->GetVariableByIndex(i); + if (var) + { + D3D11_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, ShaderStage stage) const +{ + Ren->SetTexture(stage, slot, this); +} + +void Texture::SetSampleMode(int sm) +{ + Sampler = Ren->GetSamplerState(sm); +} + + +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); + } + } +} + + +//------------------------------------------------------------------------------------- +// ***** 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; + //int flags = D3D11_CREATE_DEVICE_DEBUG; + + hr = D3D11CreateDevice(Adapter, Adapter ? D3D_DRIVER_TYPE_UNKNOWN : D3D_DRIVER_TYPE_HARDWARE, + NULL, flags, NULL, 0, D3D11_SDK_VERSION, + &Device.GetRawRef(), NULL, &Context.GetRawRef()); + + if (FAILED(hr)) + return; + + if (!RecreateSwapChain()) + return; + + if (Params.Fullscreen) + SwapChain->SetFullscreenState(1, FullscreenOutput); + + initShadersAndStates(); +} + + +RenderDevice::RenderDevice(const SlaveRendererParams& p) +{ + WindowWidth = p.RTSize.w; + WindowHeight = p.RTSize.h; + Params.Multisample = p.Multisample; + Window = 0; + + Context = p.pDeviceContext; + Device = p.pDevice; // IN D3D11 this is different + + BackBufferRT = p.pBackBufferRT; + + initShadersAndStates(); +} + +// Constructor helper +void RenderDevice::initShadersAndStates() +{ + 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(); + ID3D11InputLayout** objRef = &ModelVertexIL.GetRawRef(); + + HRESULT validate = Device->CreateInputLayout(ModelVertexDesc, sizeof(ModelVertexDesc)/sizeof(D3D11_INPUT_ELEMENT_DESC), + buffer, bufferSize, objRef); + OVR_UNUSED(validate); + + Ptr gouraudShaders = *new ShaderSet(); + gouraudShaders->SetShader(VertexShaders[VShader_MVP]); + gouraudShaders->SetShader(PixelShaders[FShader_Gouraud]); + DefaultFill = *new ShaderFill(gouraudShaders); + + D3D11_BLEND_DESC bm; + memset(&bm, 0, sizeof(bm)); + bm.RenderTarget[0].BlendEnable = true; + bm.RenderTarget[0].BlendOp = bm.RenderTarget[0].BlendOpAlpha = D3D11_BLEND_OP_ADD; + bm.RenderTarget[0].SrcBlend = bm.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_SRC_ALPHA; + bm.RenderTarget[0].DestBlend = bm.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_INV_SRC_ALPHA; + bm.RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL; + Device->CreateBlendState(&bm, &BlendState.GetRawRef()); + + D3D11_RASTERIZER_DESC rs; + memset(&rs, 0, sizeof(rs)); + rs.AntialiasedLineEnable = true; + rs.CullMode = D3D11_CULL_BACK; + rs.DepthClipEnable = true; + rs.FillMode = D3D11_FILL_SOLID; + Device->CreateRasterizerState(&rs, &Rasterizer.GetRawRef()); + + QuadVertexBuffer = *CreateBuffer(); + const 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); +} + +void RenderDevice::InitShaders( const char * vertex_shader, const char * pixel_shader, ShaderSet ** pShaders, ID3D11InputLayout ** pVertexIL, + D3D11_INPUT_ELEMENT_DESC * DistortionMeshVertexDesc, int num_elements) +{ + ID3D10Blob* vsData = CompileShader("vs_4_0", vertex_shader); + + Ptr vtxShader = *new VertexShader(this, vsData); + + ID3D11InputLayout** objRef = pVertexIL; + + HRESULT validate = Device->CreateInputLayout( + DistortionMeshVertexDesc, num_elements, + vsData->GetBufferPointer(), vsData->GetBufferSize(), objRef); + if(FAILED(validate)) OVR_ASSERT(false); + + (*pShaders) = CreateShaderSet(); + (*pShaders)->SetShader(vtxShader); + + ID3D10Blob *pShader = CompileShader("ps_4_0", pixel_shader); + Ptr ps = *new PixelShader(this, pShader); + + (*pShaders)->SetShader(ps); +} + + + +RenderDevice::~RenderDevice() +{ + if (SwapChain && Params.Fullscreen) + { + SwapChain->SetFullscreenState(false, NULL); + } +} + + + +// Implement static initializer function to create this class. +RenderDevice* RenderDevice::CreateDevice(const RendererParams& rp, void* oswnd) +{ + RenderDevice* p = new RenderDevice(rp, (HWND)oswnd); + if (p) + { + if (!p->Device) + { + p->Release(); + p = 0; + } + } + return p; +} + +RenderDevice* RenderDevice::CreateSlaveDevice(const SlaveRendererParams& srp) +{ + return new RenderDevice(srp); +} + + +// 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 D3D11 (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 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 = 0; + 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 newSC; + if (FAILED(DXGIFactory->CreateSwapChain(Device, &scDesc, &newSC.GetRawRef()))) + return false; + SwapChain = newSC; + + BackBuffer = NULL; + BackBufferRT = NULL; + HRESULT hr = SwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (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(); + } + + 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::SetViewport(const Recti& vp) +{ + D3DViewport.Width = (float)vp.w; + D3DViewport.Height = (float)vp.h; + D3DViewport.MinDepth = 0; + D3DViewport.MaxDepth = 1; + D3DViewport.TopLeftX = (float)vp.x; + D3DViewport.TopLeftY = (float)vp.y; + Context->RSSetViewports(1, &D3DViewport); +} + +void RenderDevice::SetFullViewport() +{ + D3DViewport.Width = (float)WindowWidth; + D3DViewport.Height = (float)WindowHeight; + D3DViewport.MinDepth = 0; + D3DViewport.MaxDepth = 1; + D3DViewport.TopLeftX = 0; + D3DViewport.TopLeftY = 0; + 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; + } + + D3D11_DEPTH_STENCIL_DESC dss; + memset(&dss, 0, sizeof(dss)); + dss.DepthEnable = enable; + switch(func) + { + case Compare_Always: dss.DepthFunc = D3D11_COMPARISON_ALWAYS; break; + case Compare_Less: dss.DepthFunc = D3D11_COMPARISON_LESS; break; + case Compare_Greater: dss.DepthFunc = D3D11_COMPARISON_GREATER; break; + default: + OVR_ASSERT(0); + } + dss.DepthWriteMask = write ? D3D11_DEPTH_WRITE_MASK_ALL : D3D11_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 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 + ID3D11DepthStencilState* oldDepthState = CurDepthState; + StandardUniformData clearUniforms; + + SetDepthMode(true, true, Compare_Always); + + Context->IASetInputLayout(ModelVertexIL); + Context->GSSetShader(NULL, NULL, 0); + + ID3D11ShaderResourceView* sv[8] = {0, 0, 0, 0, 0, 0, 0, 0}; + if (MaxTextureSet[Shader_Fragment]) + { + Context->PSSetShaderResources(0, MaxTextureSet[Shader_Fragment], sv); + } + + ID3D11Buffer* 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)); + + ID3D11Buffer* vertexConstants = UniformBuffers[Shader_Vertex]->GetBuffer(); + Context->VSSetConstantBuffers(0, 1, &vertexConstants); + Context->IASetPrimitiveTopology(D3D11_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, Buffer* buffer) +{ + CommonUniforms[i] = (Buffer*)buffer; + + Context->PSSetConstantBuffers(1, 1, &CommonUniforms[1]->D3DBuffer.GetRawRef()); + Context->VSSetConstantBuffers(1, 1, &CommonUniforms[1]->D3DBuffer.GetRawRef()); +} + +ShaderBase *RenderDevice::LoadBuiltinShader(ShaderStage stage, int shader) +{ + switch(stage) + { + case Shader_Vertex: + return VertexShaders[shader]; + case Shader_Pixel: + return PixelShaders[shader]; + default: + return NULL; + } +} + + +ID3D11SamplerState* RenderDevice::GetSamplerState(int sm) +{ + if (SamplerStates[sm]) + return SamplerStates[sm]; + + D3D11_SAMPLER_DESC ss; + memset(&ss, 0, sizeof(ss)); + if (sm & Sample_Clamp) + ss.AddressU = ss.AddressV = ss.AddressW = D3D11_TEXTURE_ADDRESS_CLAMP; + else if (sm & Sample_ClampBorder) + ss.AddressU = ss.AddressV = ss.AddressW = D3D11_TEXTURE_ADDRESS_BORDER; + else + ss.AddressU = ss.AddressV = ss.AddressW = D3D11_TEXTURE_ADDRESS_WRAP; + + if (sm & Sample_Nearest) + { + ss.Filter = D3D11_FILTER_MIN_MAG_MIP_POINT; + } + else if (sm & Sample_Anisotropic) + { + ss.Filter = D3D11_FILTER_ANISOTROPIC; + ss.MaxAnisotropy = 8; + } + else + { + ss.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR; + } + ss.MaxLOD = 15; + Device->CreateSamplerState(&ss, &SamplerStates[sm].GetRawRef()); + return SamplerStates[sm]; +} + + +void RenderDevice::SetTexture(ShaderStage stage, int slot, const Texture* t) +{ + if (MaxTextureSet[stage] <= slot) + MaxTextureSet[stage] = slot + 1; + + ID3D11ShaderResourceView* 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; + } +} + +// Placeholder texture to come in externally in slave rendering mode +Texture* RenderDevice::CreatePlaceholderTexture(int format) +{ + Texture* newTex = new Texture(this, format, 0, 0); + newTex->Samples = 1; + + return newTex; +} + + +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; + + D3D11_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 = D3D11_USAGE_DEFAULT; + dsDesc.BindFlags = D3D11_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 = D3D11_BIND_DEPTH_STENCIL; + } + else + { + dsDesc.BindFlags |= D3D11_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 & D3D11_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; +} + +ShaderFill* RenderDevice::CreateTextureFill(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; +} + +// Rendering + +void RenderDevice::BeginRendering() +{ + Context->RSSetState(Rasterizer); +} + +void RenderDevice::SetLighting(const LightingParams* lt) +{ + if (!LightingBuffer) + LightingBuffer = *CreateBuffer(); + + LightingBuffer->Data(Buffer_Uniform, lt, sizeof(LightingParams)); + SetCommonUniformBuffer(1, LightingBuffer); +} + +void RenderDevice::SetProjection(const Matrix4f& proj) +{ + Proj = proj; + SetWorldUniforms(proj); +} + +void RenderDevice::BeginScene() +{ + BeginRendering(); + SetViewport(VP); + SetWorldUniforms(Proj); +} + +void RenderDevice::FinishScene() +{ + SetRenderTarget(0); +} + +void RenderDevice::SetRenderTarget(Texture* colorTex, + Texture* depth, + 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); + } + + ID3D11ShaderResourceView* 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& view, Model* model) +{ + // Store data in buffers if not already + if (!model->VertexBuffer) + { + Ptr vb = *CreateBuffer(); + vb->Data(Buffer_Vertex, &model->Vertices[0], model->Vertices.GetSize() * sizeof(Vertex)); + model->VertexBuffer = vb; + } + if (!model->IndexBuffer) + { + Ptr 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, + view, 0, (unsigned)model->Indices.GetSize(), model->GetPrimType()); +} + + +//Cut down one for ORT for simplicity +void RenderDevice::Render(const ShaderFill* fill, Buffer* vertices, Buffer* indices) +{ + Render(fill, vertices, indices, Matrix4f(), 0, (int)vertices->GetSize(), Prim_Triangles, false); +} + + +void RenderDevice::Render(const ShaderFill* fill, Buffer* vertices, Buffer* indices, + const Matrix4f& matrix, int offset, int count, PrimitiveType rprim, bool updateUniformData) +{ + + if(((ShaderFill*)fill)->GetInputLayout() != NULL) + Context->IASetInputLayout((ID3D11InputLayout*)((ShaderFill*)fill)->GetInputLayout()); + else + Context->IASetInputLayout(ModelVertexIL); + + if (indices) + { + Context->IASetIndexBuffer(((Buffer*)indices)->GetBuffer(), DXGI_FORMAT_R16_UINT, 0); + } + + ID3D11Buffer* 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) + { + // TODO: some VSes don't start with StandardUniformData! + if ( updateUniformData ) + { + 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]); + } + + D3D11_PRIMITIVE_TOPOLOGY prim; + switch(rprim) + { + case Prim_Triangles: + prim = D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST; + break; + case Prim_Lines: + prim = D3D11_PRIMITIVE_TOPOLOGY_LINELIST; + break; + case Prim_TriangleStrip: + prim = D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP; + break; + default: + OVR_ASSERT(0); + return; + } + Context->IASetPrimitiveTopology(prim); + + fill->Set(rprim); + + if (indices) + { + Context->DrawIndexed(count, 0, 0); + } + else + { + Context->Draw(count, 0); + } +} + + +void RenderDevice::Present(bool vsyncEnabled) +{ + SwapChain->Present(vsyncEnabled ? 1 : 0, 0); +} + +void RenderDevice::WaitUntilGpuIdle() +{ + // Flush and Stall CPU while waiting for GPU to complete rendering all of the queued draw calls + D3D11_QUERY_DESC queryDesc = { D3D11_QUERY_EVENT, 0 }; + Ptr query; + BOOL done = FALSE; + + if (Device->CreateQuery(&queryDesc, &query.GetRawRef()) == S_OK) + { + Context->End(query); + do { } + while(!done && !FAILED(Context->GetData(query, &done, sizeof(BOOL), 0))); + } +} + + +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_D3D11_Device.h b/Samples/OculusRoomTiny/RenderTiny_D3D11_Device.h new file mode 100644 index 0000000..f4ec71a --- /dev/null +++ b/Samples/OculusRoomTiny/RenderTiny_D3D11_Device.h @@ -0,0 +1,824 @@ +/************************************************************************************ + +Filename : RenderTiny_D3D11_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_D3D11_Device_h +#define INC_RenderTiny_D3D11_Device_h + +#include "Kernel/OVR_Math.h" +#include "Kernel/OVR_Array.h" +#include "Kernel/OVR_String.h" +#include "Kernel/OVR_Color.h" +#include + +namespace OVR { namespace RenderTiny { + + +class RenderDevice; +class Buffer; + + +//----------------------------------------------------------------------------------- + +// 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_Count = 2, + + FShader_Solid = 0, + FShader_Gouraud = 1, + FShader_Texture = 2, + FShader_LitGouraud = 3, + FShader_LitTexture = 4, + 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, +}; + + +// Base class for vertex and pixel shaders. Stored in ShaderSet. +class ShaderBase : public RefCountBase +{ + friend class ShaderSet; + +protected: + ShaderStage Stage; + +public: + RenderDevice* Ren; + unsigned char* UniformData; + int UniformsSize; + + enum VarType + { + VARTYPE_FLOAT, + VARTYPE_INT, + VARTYPE_BOOL, + }; + + struct Uniform + { + String Name; + VarType Type; + int Offset, Size; + }; + Array UniformInfo; + + ShaderBase(RenderDevice* r, ShaderStage stage); + ShaderBase(ShaderStage s) : Stage(s) {} + + ~ShaderBase(); + + ShaderStage GetStage() const { return Stage; } + + virtual void Set(PrimitiveType) const { } + virtual void SetUniformBuffer(class Buffer* buffers, int i = 0) { OVR_UNUSED2(buffers, i); } + + void InitUniforms(ID3D10Blob* s); + void InitUniforms(void* s, size_t sizeS); + virtual bool SetUniform(const char* name, int n, const float* v); + virtual bool SetUniformBool(const char* name, int n, const bool* v); + + void UpdateBuffer(Buffer* b); +}; + +template +class Shader : public ShaderBase +{ +public: + D3DShaderType* D3DShader; + + Shader(RenderDevice* r, D3DShaderType* s) : ShaderBase(r, SStage), D3DShader(s) {} + Shader(RenderDevice* r, ID3D10Blob* s) : ShaderBase(r, SStage) + { + Load(s); + InitUniforms(s); + } + Shader(RenderDevice* r, void* s, size_t size) : ShaderBase(r, SStage) + { + Load(s, size); + InitUniforms(s, size); + } + ~Shader() + { + if (D3DShader) + D3DShader->Release(); + } + bool Load(ID3D10Blob* 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(Buffer* buffers, int i = 0); +}; + +typedef Shader VertexShader; +typedef Shader PixelShader; + + +// A group of shaders, one per stage. +// A ShaderSet is applied to a RenderDevice for rendering with a given fill. +class ShaderSet : public RefCountBase +{ +protected: + Ptr Shaders[Shader_Count]; + +public: + ShaderSet() { } + ~ShaderSet() { } + + virtual void SetShader(ShaderBase *s) + { + Shaders[s->GetStage()] = s; + } + virtual void UnsetShader(int stage) + { + Shaders[stage] = NULL; + } + ShaderBase* 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 SetUniform3f(const char* name, float x, float y, float z) + { + const float v[] = {x,y,z}; + return SetUniform(name, 3, 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 +{ + Ptr Shaders; + Ptr Textures[8]; + void* InputLayout; // HACK this should be abstracted + +public: + ShaderFill(ShaderSet* sh) : Shaders(sh) { InputLayout = NULL; } + ShaderFill(ShaderSet& sh) : Shaders(sh) { InputLayout = NULL; } + + ShaderSet* GetShaders() { return Shaders; } + + + void* GetInputLayout() { return InputLayout; } + + virtual void Set(PrimitiveType prim = Prim_Unknown) const; + virtual void SetTexture(int i, class Texture* tex) { if (i < 8) Textures[i] = tex; } + void SetInputLayout(void* newIL) { InputLayout = (void*)newIL; } +}; + +// 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 +{ +public: + RenderDevice* Ren; + Ptr D3DBuffer; + size_t Size; + int Use; + bool Dynamic; + +public: + Buffer(RenderDevice* r) : Ren(r), Size(0), Use(0) {} + virtual ~Buffer() {} + + ID3D11Buffer* 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); + // Allocates a buffer, optionally filling it with data. + virtual bool Data(int use, const void* buffer, size_t size); +}; + +class Texture : public RefCountBase +{ +public: + RenderDevice* Ren; + Ptr Tex; + Ptr TexSv; + Ptr TexRtv; + Ptr TexDsv; + mutable Ptr Sampler; + int Width, Height; + int Samples; + + Texture(RenderDevice* r, int fmt, int w, int h); + virtual ~Texture(); + + virtual int GetWidth() const { return Width; } + virtual int GetHeight() const { return Height; } + virtual int GetSamples() const { return Samples; } + + virtual void SetSampleMode(int sm); + + // Updates texture to point to specified resources + // - used for slave rendering. + void UpdatePlaceholderTexture(ID3D11Texture2D* texture, ID3D11ShaderResourceView* psrv) + { + Tex = texture; + TexSv = psrv; + TexRtv.Clear(); + TexDsv.Clear(); + + D3D11_TEXTURE2D_DESC desc; + texture->GetDesc(&desc); + Width = desc.Width; + Height= desc.Height; + } + + + virtual void Set(int slot, ShaderStage stage = Shader_Fragment) const; +}; + + +//----------------------------------------------------------------------------------- + +// 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 +{ + 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 = Matrix4f(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 Vertices; + Array Indices; + PrimitiveType Type; + Ptr 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 VertexBuffer; + Ptr 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) + { + OVR_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 > 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 NewOverrideBase +{ +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; + } +}; + + +//----------------------------------------------------------------------------------- + +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; + } +}; + +class RenderDevice : public RefCountBase +{ + + +protected: + int WindowWidth, WindowHeight; + RendererParams Params; + Recti VP; + + Matrix4f Proj; + Ptr pTextVertexBuffer; + + // For lighting on platforms with uniform buffers + Ptr LightingBuffer; + +public: + enum CompareFunc + { + Compare_Always = 0, + Compare_Less = 1, + Compare_Greater = 2, + Compare_Count + }; + + Ptr DXGIFactory; + HWND Window; + + Ptr Device; + Ptr Context; + Ptr SwapChain; + Ptr Adapter; + Ptr FullscreenOutput; + int FSDesktopX, FSDesktopY; + + Ptr BackBuffer; + Ptr BackBufferRT; + Ptr CurRenderTarget; + Ptr CurDepthBuffer; + Ptr Rasterizer; + Ptr BlendState; + D3D11_VIEWPORT D3DViewport; + + Ptr DepthStates[1 + 2 * Compare_Count]; + Ptr CurDepthState; + Ptr ModelVertexIL; + + Ptr SamplerStates[Sample_Count]; + + struct StandardUniformData + { + Matrix4f Proj; + Matrix4f View; + } StdUniforms; + Ptr UniformBuffers[Shader_Count]; + int MaxTextureSet[Shader_Count]; + + Ptr VertexShaders[VShader_Count]; + Ptr PixelShaders[FShader_Count]; + Ptr CommonUniforms[8]; + Ptr DefaultFill; + + Ptr QuadVertexBuffer; + + Array > DepthBuffers; + +public: + + // Slave parameters are used to create a renderer that uses an externally + // specified device. + struct SlaveRendererParams + { + ID3D11Device* pDevice; + ID3D11DeviceContext* pDeviceContext; + ID3D11RenderTargetView* pBackBufferRT; + Sizei RTSize; + int Multisample; + }; + + RenderDevice(); + RenderDevice(const RendererParams& p, HWND window); + RenderDevice(const SlaveRendererParams& p); + virtual ~RenderDevice(); + + // Implement static initializer function to create this class. + // Creates a new rendering device + static RenderDevice* CreateDevice(const RendererParams& rp, void* oswnd); + + // Creates a "slave" renderer existing device. + static RenderDevice* CreateSlaveDevice(const SlaveRendererParams& srp); + + + + // Constructor helper + void initShadersAndStates(); + void InitShaders( const char * vertex_shader, const char * pixel_shader, ShaderSet ** pShaders, ID3D11InputLayout ** pVertexIL, + D3D11_INPUT_ELEMENT_DESC * DistortionMeshVertexDesc, int num_elements); + + + + void UpdateMonitorOutputs(); + + void SetViewport(int x, int y, int w, int h) { SetViewport(Recti(x,y,w,h)); } + // Set viewport ignoring any adjustments used for the stereo mode. + virtual void SetViewport(const Recti& vp); + virtual void SetFullViewport(); + + virtual bool SetParams(const RendererParams& newParams); + const RendererParams& GetParams() const { return Params; } + + virtual void Present(bool vsyncEnabled); + + // Waits for rendering to complete; important for reducing latency. + virtual void WaitUntilGpuIdle(); + + // Don't call these directly, use App/Platform instead + virtual bool SetFullscreen(DisplayMode fullscreen); + + virtual void Clear(float r = 0, float g = 0, float b = 0, float a = 1, float depth = 1); + + // Resources + virtual Buffer* CreateBuffer(); + virtual Texture* CreateTexture(int format, int width, int height, const void* data, int mipcount=1); + + // Placeholder texture to come in externally + virtual Texture* CreatePlaceholderTexture(int format); + + virtual ShaderSet* CreateShaderSet() { return new ShaderSet; } + + Texture* GetDepthBuffer(int w, int h, int ms); + + // Begin drawing directly to the currently selected render target, no post-processing. + virtual void BeginRendering(); + + // Begin drawing the primary scene, starting up whatever post-processing may be needed. + virtual void BeginScene(); + 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); + + virtual void SetDepthMode(bool enable, bool write, CompareFunc func = Compare_Less); + virtual void SetProjection(const Matrix4f& proj); + virtual void SetWorldUniforms(const Matrix4f& proj); + // The index 0 is reserved for non-buffer uniforms, and so cannot be used with this function. + virtual void SetCommonUniformBuffer(int i, Buffer* buffer); + // The data is not copied, it must remain valid until the end of the frame + virtual void SetLighting(const LightingParams* light); + + 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& view, Model* model); + virtual void Render(const ShaderFill* fill, Buffer* vertices, Buffer* indices); + virtual void Render(const ShaderFill* fill, Buffer* vertices, Buffer* indices, + const Matrix4f& matrix, int offset, int count, PrimitiveType prim = Prim_Triangles, bool updateUniformData = true); + + virtual ShaderFill *CreateSimpleFill() { return DefaultFill; } + ShaderFill * CreateTextureFill(Texture* tex); + + virtual ShaderBase *LoadBuiltinShader(ShaderStage stage, int shader); + + bool RecreateSwapChain(); + virtual ID3D10Blob* CompileShader(const char* profile, const char* src, const char* mainName = "main"); + + ID3D11SamplerState* GetSamplerState(int sm); + + void SetTexture(ShaderStage stage, int slot, const Texture* t); +}; + +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); + +}} + + +//Anything including this file, uses these +using namespace OVR; +using namespace OVR::RenderTiny; + + +#endif diff --git a/Samples/OculusRoomTiny/RenderTiny_D3D1X_Device.cpp b/Samples/OculusRoomTiny/RenderTiny_D3D1X_Device.cpp deleted file mode 100644 index a1a567a..0000000 --- a/Samples/OculusRoomTiny/RenderTiny_D3D1X_Device.cpp +++ /dev/null @@ -1,1311 +0,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 - -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::Load(void* shader, size_t size) -{ - return SUCCEEDED(Ren->Device->CreateVertexShader(shader, size, &D3DShader)); -} -template<> bool Shader::Load(void* shader, size_t size) -{ - return SUCCEEDED(Ren->Device->CreatePixelShader(shader, size, &D3DShader)); -} - -template<> void Shader::Set(PrimitiveType) const -{ - Ren->Context->VSSetShader(D3DShader); -} -template<> void Shader::Set(PrimitiveType) const -{ - Ren->Context->PSSetShader(D3DShader); -} - -template<> void Shader::SetUniformBuffer(RenderTiny::Buffer* buffer, int i) -{ - Ren->Context->VSSetConstantBuffers(i, 1, &((Buffer*)buffer)->D3DBuffer.GetRawRef()); -} -template<> void Shader::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 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 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 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 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 vb = *CreateBuffer(); - vb->Data(Buffer_Vertex, &model->Vertices[0], model->Vertices.GetSize() * sizeof(Vertex)); - model->VertexBuffer = vb; - } - if (!model->IndexBuffer) - { - Ptr 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 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 deleted file mode 100644 index 1438611..0000000 --- a/Samples/OculusRoomTiny/RenderTiny_D3D1X_Device.h +++ /dev/null @@ -1,273 +0,0 @@ -/************************************************************************************ - -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 - -#define _OVR_RENDERER_D3D10 -#include - -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 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 -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 VertexShader; -typedef Shader PixelShader; - - -class Buffer : public RenderTiny::Buffer -{ -public: - RenderDevice* Ren; - Ptr 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 Tex; - Ptr TexSv; - Ptr TexRtv; - Ptr TexDsv; - mutable Ptr 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 DXGIFactory; - HWND Window; - - Ptr Device; - Ptr Context; - Ptr SwapChain; - Ptr Adapter; - Ptr FullscreenOutput; - int FSDesktopX, FSDesktopY; - - Ptr BackBuffer; - Ptr BackBufferRT; - Ptr CurRenderTarget; - Ptr CurDepthBuffer; - Ptr Rasterizer; - Ptr BlendState; - D3D1x_VIEWPORT D3DViewport; - - Ptr DepthStates[1 + 2 * Compare_Count]; - Ptr CurDepthState; - Ptr ModelVertexIL; - - Ptr SamplerStates[Sample_Count]; - - struct StandardUniformData - { - Matrix4f Proj; - Matrix4f View; - } StdUniforms; - Ptr UniformBuffers[Shader_Count]; - int MaxTextureSet[Shader_Count]; - - Ptr VertexShaders[VShader_Count]; - Ptr PixelShaders[FShader_Count]; - Ptr CommonUniforms[8]; - Ptr DefaultFill; - - Ptr QuadVertexBuffer; - - Array > 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 deleted file mode 100644 index 2c363c2..0000000 --- a/Samples/OculusRoomTiny/RenderTiny_Device.cpp +++ /dev/null @@ -1,442 +0,0 @@ -/************************************************************************************ - -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 deleted file mode 100644 index 878450d..0000000 --- a/Samples/OculusRoomTiny/RenderTiny_Device.h +++ /dev/null @@ -1,724 +0,0 @@ -/************************************************************************************ - -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 -{ - 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 -{ - protected: - Ptr 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 -{ - Ptr Shaders; - Ptr 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 -{ -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 -{ -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 -{ - 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 Vertices; - Array Indices; - PrimitiveType Type; - Ptr 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 VertexBuffer; - Ptr 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 > 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 -{ -protected: - int WindowWidth, WindowHeight; - RendererParams Params; - Viewport VP; - - Matrix4f Proj; - Ptr pTextVertexBuffer; - - // For rendering with lens warping - PostProcessType CurPostProcess; - Ptr pSceneColorTex; // Distortion render target, both eyes. - int SceneColorTexW; - int SceneColorTexH; - Ptr pPostProcessShader; - Ptr pFullScreenVertexBuffer; - float SceneRenderScale; - DistortionConfig Distortion; - - // For lighting on platforms with uniform buffers - Ptr 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 deleted file mode 100644 index 07460c3..0000000 --- a/Samples/OculusRoomTiny/RenderTiny_GL_Device.cpp +++ /dev/null @@ -1,784 +0,0 @@ -/************************************************************************************ - -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 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 newDepth = *CreateTexture(Texture_Depth|Texture_RenderTarget|ms, w, h, NULL); - Ptr 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 vb = *CreateBuffer(); - vb->Data(Buffer_Vertex, &model->Vertices[0], model->Vertices.GetSize() * sizeof(Vertex)); - model->VertexBuffer = vb; - } - if (!model->IndexBuffer) - { - Ptr 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 deleted file mode 100644 index 5d88180..0000000 --- a/Samples/OculusRoomTiny/RenderTiny_GL_Device.h +++ /dev/null @@ -1,228 +0,0 @@ -/************************************************************************************ - -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 -#endif - -#if defined(OVR_OS_MAC) -#include -#include -#else -#define GL_GLEXT_PROTOTYPES -#include -#include -#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 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 -{ - public: - int Width, Height; - GLuint BufId; - - RBuffer(GLenum format, GLint w, GLint h); - ~RBuffer(); -}; - -class RenderDevice : public RenderTiny::RenderDevice -{ - Ptr VertexShaders[VShader_Count]; - Ptr FragShaders[FShader_Count]; - - Ptr DefaultFill; - - Matrix4f Proj; - - Ptr CurRenderTarget; - Array > 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_DistortionMesh.cpp b/Samples/OculusRoomTiny/Win32_DistortionMesh.cpp new file mode 100644 index 0000000..3356467 --- /dev/null +++ b/Samples/OculusRoomTiny/Win32_DistortionMesh.cpp @@ -0,0 +1,244 @@ +/************************************************************************************ + +Filename : Win32_DistortionMesh.cpp +Content : Manual creation and rendering of a distortion mesh +Created : March 5, 2014 +Authors : Tom Heath, Volga Aksoy +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. +*************************************************************************************/ + +//----------------------------------------------------------------------------------- +// If we decide to do our own rendering, then we need to make sure that +// we are creating the distortion mesh manually using the data provided by the LibOVR SDK + +#include "OVR_CAPI.h" +#include "RenderTiny_D3D11_Device.h" + +//----------------------------------------------------------------------------------- + +// Contains render data required to render the distortion mesh with the proper shaders +// NOTE: For *demostration purposes*, the C-style functions in Win32_OculusRoomTiny.cpp +// actually render the distortion mesh, while this struct only stores the data in a logical group +struct DistortionRenderData +{ + ShaderSet * Shaders; + ID3D11InputLayout * VertexIL; + Vector2f UVScaleOffset[2][2]; + Ptr MeshVBs[2]; + Ptr MeshIBs[2]; +} DistortionData; + +//Format for mesh and shaders +struct DistortionVertex +{ + Vector2f Pos; + Vector2f TexR; + Vector2f TexG; + Vector2f TexB; + Color Col; +}; +static D3D11_INPUT_ELEMENT_DESC DistortionMeshVertexDesc[] = +{ + {"Position", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0}, + {"TexCoord", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 8, D3D11_INPUT_PER_VERTEX_DATA, 0}, + {"TexCoord", 1, DXGI_FORMAT_R32G32_FLOAT, 0, 16, D3D11_INPUT_PER_VERTEX_DATA, 0}, + {"TexCoord", 2, DXGI_FORMAT_R32G32_FLOAT, 0, 24, D3D11_INPUT_PER_VERTEX_DATA, 0}, + {"Color", 0, DXGI_FORMAT_R8G8B8A8_UNORM, 0, 32, D3D11_INPUT_PER_VERTEX_DATA, 0}, +}; + + + +void DistortionMeshInit(unsigned distortionCaps, ovrHmd HMD, + ovrEyeRenderDesc eyeRenderDesc[2], RenderDevice* pRender) +{ + //Generate distortion mesh for each eye + for ( int eyeNum = 0; eyeNum < 2; eyeNum++ ) + { + // Allocate & generate distortion mesh vertices. + ovrDistortionMesh meshData; + ovrHmd_CreateDistortionMesh(HMD, eyeRenderDesc[eyeNum].Desc, distortionCaps, + (ovrVector2f* ) DistortionData.UVScaleOffset[eyeNum], + &meshData); + + // Now parse the vertex data and create a render ready vertex buffer from it + DistortionVertex * pVBVerts = (DistortionVertex*)OVR_ALLOC( + sizeof(DistortionVertex) * meshData.VertexCount ); + DistortionVertex * v = pVBVerts; + ovrDistortionVertex * ov = meshData.pVertexData; + for ( unsigned vertNum = 0; vertNum < meshData.VertexCount; vertNum++ ) + { + v->Pos.x = ov->Pos.x; + v->Pos.y = ov->Pos.y; + v->TexR = (*(Vector2f*)&ov->TexR); + v->TexG = (*(Vector2f*)&ov->TexG); + v->TexB = (*(Vector2f*)&ov->TexB); + v->Col.R = v->Col.G = v->Col.B = (OVR::UByte)( ov->VignetteFactor * 255.99f ); + v->Col.A = (OVR::UByte)( ov->TimeWarpFactor * 255.99f ); + v++; ov++; + } + //Register this mesh with the renderer + DistortionData.MeshVBs[eyeNum] = *pRender->CreateBuffer(); + DistortionData.MeshVBs[eyeNum]->Data ( Buffer_Vertex, pVBVerts, + sizeof(DistortionVertex) * meshData.VertexCount ); + DistortionData.MeshIBs[eyeNum] = *pRender->CreateBuffer(); + DistortionData.MeshIBs[eyeNum]->Data ( Buffer_Index, meshData.pIndexData, + sizeof(unsigned short) * meshData.IndexCount ); + + OVR_FREE ( pVBVerts ); + ovrHmd_DestroyDistortionMesh( &meshData ); + } + + // Pixel shader for the mesh + //------------------------------------------------------------------------------------------- + const char* pixelShader = + "Texture2D Texture : register(t0); \n" + "SamplerState Linear : register(s0); \n" + + "float4 main(in float4 oPosition : SV_Position, in float4 oColor : COLOR, \n" + " in float2 oTexCoord0 : TEXCOORD0, in float2 oTexCoord1 : TEXCOORD1, \n" + " in float2 oTexCoord2 : TEXCOORD2) : SV_Target \n" + "{ \n" + // 3 samples for fixing chromatic aberrations + " float ResultR = Texture.Sample(Linear, oTexCoord0.xy).r; \n" + " float ResultG = Texture.Sample(Linear, oTexCoord1.xy).g; \n" + " float ResultB = Texture.Sample(Linear, oTexCoord2.xy).b; \n" + " return float4(ResultR * oColor.r, ResultG * oColor.g, ResultB * oColor.b, 1.0); \n" + "}"; + + + // Choose the vertex shader, according to if you have timewarp enabled + if (distortionCaps & ovrDistortion_TimeWarp) + { // TIMEWARP + //-------------------------------------------------------------------------------------------- + const char* vertexShader = + "float2 EyeToSourceUVScale; \n" + "float2 EyeToSourceUVOffset; \n" + "float4x4 EyeRotationStart; \n" + "float4x4 EyeRotationEnd; \n" + "float2 TimewarpTexCoord(float2 TexCoord, float4x4 rotMat) \n" + "{ \n" + // Vertex inputs are in TanEyeAngle space for the R,G,B channels (i.e. after chromatic + // aberration and distortion). These are now "real world" vectors in direction (x,y,1) + // relative to the eye of the HMD. Apply the 3x3 timewarp rotation to these vectors. + " float3 transformed = float3( mul ( rotMat, float4(TexCoord.xy, 1, 1) ).xyz); \n" + // Project them back onto the Z=1 plane of the rendered images. + " float2 flattened = (transformed.xy / transformed.z); \n" + // Scale them into ([0,0.5],[0,1]) or ([0.5,0],[0,1]) UV lookup space (depending on eye) + " return(EyeToSourceUVScale * flattened + EyeToSourceUVOffset); \n" + "} \n" + "void main(in float2 Position : POSITION, in float4 Color : COLOR0, \n" + " in float2 TexCoord0 : TEXCOORD0, in float2 TexCoord1 : TEXCOORD1, \n" + " in float2 TexCoord2 : TEXCOORD2, \n" + " out float4 oPosition : SV_Position, out float4 oColor : COLOR, \n" + " out float2 oTexCoord0 : TEXCOORD0, out float2 oTexCoord1 : TEXCOORD1, \n" + " out float2 oTexCoord2 : TEXCOORD2) \n" + "{ \n" + " float timewarpLerpFactor = Color.a; \n" + " float4x4 lerpedEyeRot = lerp(EyeRotationStart, EyeRotationEnd, timewarpLerpFactor);\n" + " oTexCoord0 = TimewarpTexCoord(TexCoord0,lerpedEyeRot); \n" + " oTexCoord1 = TimewarpTexCoord(TexCoord1,lerpedEyeRot); \n" + " oTexCoord2 = TimewarpTexCoord(TexCoord2,lerpedEyeRot); \n" + " oPosition = float4(Position.xy, 0.5, 1.0); \n" + " oColor = Color.r; /*For vignette fade*/ \n" + "}"; + + pRender->InitShaders(vertexShader, pixelShader, &DistortionData.Shaders, + &DistortionData.VertexIL,DistortionMeshVertexDesc,5); + } + else + { + //------------------------------------------------------------------------------------------- + const char* vertexShader = + "float2 EyeToSourceUVScale; \n" + "float2 EyeToSourceUVOffset; \n" + "void main(in float2 Position : POSITION, in float4 Color : COLOR0, \n" + " in float2 TexCoord0 : TEXCOORD0, in float2 TexCoord1 : TEXCOORD1, \n" + " in float2 TexCoord2 : TEXCOORD2, \n" + " out float4 oPosition : SV_Position, out float4 oColor : COLOR, \n" + " out float2 oTexCoord0 : TEXCOORD0, out float2 oTexCoord1 : TEXCOORD1, \n" + " out float2 oTexCoord2 : TEXCOORD2) \n" + "{ \n" + // Scale them into ([0,0.5],[0,1]) or ([0.5,0],[0,1]) UV lookup space (depending on eye) + " oTexCoord0 = EyeToSourceUVScale * TexCoord0 + EyeToSourceUVOffset; \n" + " oTexCoord1 = EyeToSourceUVScale * TexCoord1 + EyeToSourceUVOffset; \n" + " oTexCoord2 = EyeToSourceUVScale * TexCoord2 + EyeToSourceUVOffset; \n" + " oPosition = float4(Position.xy, 0.5, 1.0); \n" + " oColor = Color.r; /*For vignette fade*/ \n" + "}"; + + pRender->InitShaders(vertexShader, pixelShader, &DistortionData.Shaders, + &DistortionData.VertexIL,DistortionMeshVertexDesc,5); + } +} + + +void DistortionMeshRender(unsigned distortionCaps, ovrHmd HMD, + double timwarpTimePoint, ovrPosef eyeRenderPoses[2], + RenderDevice* pRender, Texture* pRendertargetTexture) +{ + if (distortionCaps & ovrDistortion_TimeWarp) + { // TIMEWARP + // Wait till time-warp to reduce latency. + ovr_WaitTillTime(timwarpTimePoint); + } + + // Clear screen + pRender->SetRenderTarget(NULL); + pRender->SetFullViewport(); + pRender->Clear(0.0f, 0.0f, 0.0f, 0.0f); + + // Setup shader + ShaderFill distortionShaderFill(DistortionData.Shaders); + distortionShaderFill.SetTexture(0, pRendertargetTexture); + distortionShaderFill.SetInputLayout(DistortionData.VertexIL); + + for(int eyeNum = 0; eyeNum < 2; eyeNum++) + { + // Setup shader constants + DistortionData.Shaders->SetUniform2f("EyeToSourceUVScale", + DistortionData.UVScaleOffset[eyeNum][0].x, DistortionData.UVScaleOffset[eyeNum][0].y); + DistortionData.Shaders->SetUniform2f("EyeToSourceUVOffset", + DistortionData.UVScaleOffset[eyeNum][1].x, DistortionData.UVScaleOffset[eyeNum][1].y); + + if (distortionCaps & ovrDistortion_TimeWarp) + { // TIMEWARP - Additional shader constants required + ovrMatrix4f timeWarpMatrices[2]; + ovrHmd_GetEyeTimewarpMatrices(HMD, (ovrEyeType)eyeNum, eyeRenderPoses[eyeNum], timeWarpMatrices); + DistortionData.Shaders->SetUniform4x4f("EyeRotationStart", Matrix4f(timeWarpMatrices[0])); + DistortionData.Shaders->SetUniform4x4f("EyeRotationEnd", Matrix4f(timeWarpMatrices[1])); + } + // Perform distortion + pRender->Render(&distortionShaderFill, + DistortionData.MeshVBs[eyeNum], DistortionData.MeshIBs[eyeNum]); + } + + pRender->SetRenderTarget(NULL); +} + + +void DistortionMeshRelease(void) +{ + for(int eyeNum = 0; eyeNum < 2; eyeNum++) + { + DistortionData.MeshVBs[eyeNum].Clear(); + DistortionData.MeshIBs[eyeNum].Clear(); + } + if (DistortionData.Shaders) + { + DistortionData.Shaders->UnsetShader(Shader_Vertex); + DistortionData.Shaders->UnsetShader(Shader_Pixel); + } +} + diff --git a/Samples/OculusRoomTiny/Win32_OculusRoomTiny.cpp b/Samples/OculusRoomTiny/Win32_OculusRoomTiny.cpp index c27723f..5300537 100644 --- a/Samples/OculusRoomTiny/Win32_OculusRoomTiny.cpp +++ b/Samples/OculusRoomTiny/Win32_OculusRoomTiny.cpp @@ -1,6 +1,6 @@ /************************************************************************************ -Filename : Win32_OculusRoomTiny.cpp +Filename : Win32_OculusRoomTiny2.cpp Content : First-person view test application for Oculus Rift Created : October 4, 2012 Authors : Michael Antonov, Andrew Reisse @@ -18,695 +18,273 @@ 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; +// This app renders a simple flat-shaded room allowing the user to move along the +// floor and look around with an HMD and mouse/keyboard. +// The following keys work: +// 'W', 'S', 'A', 'D', 'F' - Move forward, back; strafe left/right, toggle freeze in timewarp. +// The world right handed coordinate system is defined as Y -> Up, Z -> Back, X -> Right + +//Include the OculusVR SDK +#include "OVR_CAPI.h" + +// ***** Choices and settings + +// Whether the SDK performs rendering/distortion, or the app. +//#define SDK_RENDER 1 + +const unsigned DistortionCaps = ovrDistortion_Chromatic | ovrDistortion_TimeWarp; +const bool VSyncEnabled = true; +const bool FullScreen = true; + +// Include Non-SDK supporting Utilities from other files +#include "RenderTiny_D3D11_Device.h" + +RenderDevice * Util_InitWindowAndGraphics (Recti vp, int fullscreen, int multiSampleCount); +void Util_ReleaseWindowAndGraphics (RenderDevice* pRender); +bool Util_RespondToControls (float & EyeYaw, Vector3f & EyePos, + float deltaTime, Quatf PoseOrientation); +void PopulateRoomScene (Scene* scene, RenderDevice* render); + +//Structures for the application +ovrHmd HMD; +ovrHmdDesc HMDDesc; +ovrEyeRenderDesc EyeRenderDesc[2]; +RenderDevice* pRender; +Texture* pRendertargetTexture; +Scene* pRoomScene; + +// Specifics for whether the SDK or the app is doing the distortion. +#if SDK_RENDER + #define OVR_D3D_VERSION 11 + #include "OVR_CAPI_D3D.h" + ovrD3D11Texture EyeTexture[2]; +#else + void DistortionMeshInit (unsigned distortionCaps, ovrHmd HMD, + ovrEyeRenderDesc eyeRenderDesc[2], RenderDevice * pRender); + void DistortionMeshRender(unsigned distortionCaps, ovrHmd HMD, + double timwarpTimePoint, ovrPosef eyeRenderPoses[2], + RenderDevice * pRender, Texture* pRendertargetTexture); +#endif - 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) +int Init() { - 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; + // Initializes LibOVR. + ovr_Initialize(); - do + HMD = ovrHmd_Create(0); + if (!HMD) { - // Release Sensor/HMD in case this is a retry. - pSensor.Clear(); - pHMD.Clear(); - RenderParams.MonitorName.Clear(); - - pHMD = *pManager->EnumerateDevices().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().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; + MessageBoxA(NULL,"Oculus Rift not detected.","", MB_OK); + return(1); } - - - 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); - } - + //Get more details about the HMD + ovrHmd_GetDesc(HMD, &HMDDesc); + if (HMDDesc.DisplayDeviceName[0] == '\0') + MessageBoxA(NULL,"Rift detected, display not enabled.","", MB_OK); + + //Setup Window and Graphics + const int backBufferMultisample = 1; + pRender = Util_InitWindowAndGraphics(Recti(HMDDesc.WindowsPos, HMDDesc.Resolution), + FullScreen, backBufferMultisample); + if (!pRender) return 1; + + //Configure Stereo settings. + Sizei recommenedTex0Size = ovrHmd_GetFovTextureSize(HMD, ovrEye_Left, HMDDesc.DefaultEyeFov[0], 1.0f); + Sizei recommenedTex1Size = ovrHmd_GetFovTextureSize(HMD, ovrEye_Right, HMDDesc.DefaultEyeFov[1], 1.0f); + Sizei RenderTargetSize; + RenderTargetSize.w = recommenedTex0Size.w + recommenedTex1Size.w; + RenderTargetSize.h = max ( recommenedTex0Size.h, recommenedTex1Size.h ); + + const int eyeRenderMultisample = 1; + pRendertargetTexture = pRender->CreateTexture(Texture_RGBA | Texture_RenderTarget | + eyeRenderMultisample, + RenderTargetSize.w, RenderTargetSize.h, NULL); + // The actual RT size may be different due to HW limits. + RenderTargetSize.w = pRendertargetTexture->GetWidth(); + RenderTargetSize.h = pRendertargetTexture->GetHeight(); + + // Initialize eye rendering information for ovrHmd_Configure. + // The viewport sizes are re-computed in case RenderTargetSize changed due to HW limitations. + ovrEyeDesc eyes[2]; + eyes[0].Eye = ovrEye_Left; + eyes[1].Eye = ovrEye_Right; + eyes[0].Fov = HMDDesc.DefaultEyeFov[0]; + eyes[1].Fov = HMDDesc.DefaultEyeFov[1]; + eyes[0].TextureSize = RenderTargetSize; + eyes[1].TextureSize = RenderTargetSize; + eyes[0].RenderViewport.Pos = Vector2i(0,0); + eyes[0].RenderViewport.Size = Sizei(RenderTargetSize.w / 2, RenderTargetSize.h); + eyes[1].RenderViewport.Pos = Vector2i((RenderTargetSize.w + 1) / 2, 0); + eyes[1].RenderViewport.Size = eyes[0].RenderViewport.Size; + +#if SDK_RENDER + // Query D3D texture data. + Texture* rtt = (Texture*)pRendertargetTexture; + EyeTexture[0].D3D11.Header.API = ovrRenderAPI_D3D11; + EyeTexture[0].D3D11.Header.TextureSize = RenderTargetSize; + EyeTexture[0].D3D11.Header.RenderViewport = eyes[0].RenderViewport; + EyeTexture[0].D3D11.pTexture = rtt->Tex.GetPtr(); + EyeTexture[0].D3D11.pSRView = rtt->TexSv.GetPtr(); + + // Right eye uses the same texture, but different rendering viewport. + EyeTexture[1] = EyeTexture[0]; + EyeTexture[1].D3D11.Header.RenderViewport = eyes[1].RenderViewport; + + // Configure d3d11. + RenderDevice* render = (RenderDevice*)pRender; + ovrD3D11Config d3d11cfg; + d3d11cfg.D3D11.Header.API = ovrRenderAPI_D3D11; + d3d11cfg.D3D11.Header.RTSize = Sizei(HMDDesc.Resolution.w, HMDDesc.Resolution.h); + d3d11cfg.D3D11.Header.Multisample = backBufferMultisample; + d3d11cfg.D3D11.pDevice = render->Device; + d3d11cfg.D3D11.pDeviceContext = render->Context; + d3d11cfg.D3D11.pBackBufferRT = render->BackBufferRT; + d3d11cfg.D3D11.pSwapChain = render->SwapChain; + + if (!ovrHmd_ConfigureRendering(HMD, &d3d11cfg.Config, + (VSyncEnabled ? 0 : ovrHmdCap_NoVSync), DistortionCaps, + eyes, EyeRenderDesc)) return(1); +#else // !SDK_RENDER + EyeRenderDesc[0] = ovrHmd_GetRenderDesc(HMD, eyes[0]); + EyeRenderDesc[1] = ovrHmd_GetRenderDesc(HMD, eyes[1]); - // *** 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); - } + // Create our own distortion mesh and shaders + DistortionMeshInit(DistortionCaps, HMD, EyeRenderDesc, pRender); +#endif - pRender->SetSceneRenderScale(SConfig.GetDistortionScale()); - - SConfig.Set2DAreaFov(DegreeToRad(85.0f)); - - - // *** Populate Room Scene + // Start the sensor which informs of the Rift's pose and motion + ovrHmd_StartSensor(HMD, ovrHmdCap_Orientation | + ovrHmdCap_YawCorrection | + ovrHmdCap_Position | + ovrHmdCap_LowPersistence | + ovrHmdCap_LatencyTest, 0); // This creates lights and models. - PopulateRoomScene(&Scene, pRender); + pRoomScene = new Scene; + PopulateRoomScene(pRoomScene, 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() +void ProcessAndRender() { - 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(&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); +#if SDK_RENDER + ovrFrameTiming frameTiming = ovrHmd_BeginFrame(HMD, 0); +#else + ovrFrameTiming frameTiming = ovrHmd_BeginFrameTiming(HMD, 0); +#endif - EyePos += orientationVector; - } - - else if (GamepadMove.LengthSq() > 0) - { - Matrix4f yawRotate = Matrix4f::RotationY(EyeYaw); - Vector3f orientationVector = yawRotate.Transform(GamepadMove); - orientationVector *= MoveSpeed * dt; - EyePos += orientationVector; - } + //Adjust eye position and rotation from controls, maintaining y position from HMD. + static Vector3f EyePos(0.0f, 1.6f, -5.0f); + static float EyeYaw(3.141592f); + Posef movePose = ovrHmd_GetSensorState(HMD, frameTiming.ScanoutMidpointSeconds).Predicted.Pose; + ovrPosef eyeRenderPose[2]; - // 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); + EyePos.y = ovrHmd_GetFloat(HMD, OVR_KEY_EYE_HEIGHT, EyePos.y); + bool freezeEyeRender = Util_RespondToControls(EyeYaw, EyePos, + frameTiming.DeltaSeconds, movePose.Orientation); + pRender->BeginScene(); - // 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()) + //Render the two undistorted eye views into their render buffers. + if (!freezeEyeRender) // freeze to debug, especially for time warp { - 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->SetRenderTarget ( pRendertargetTexture ); + pRender->SetViewport (Recti(0,0, pRendertargetTexture->GetWidth(), + pRendertargetTexture->GetHeight() )); + pRender->Clear(); + for (int eyeIndex = 0; eyeIndex < ovrEye_Count; eyeIndex++) + { + ovrEyeType eye = HMDDesc.EyeRenderOrder[eyeIndex]; +#if SDK_RENDER + eyeRenderPose[eye] = ovrHmd_BeginEyeRender(HMD, eye); +#else + eyeRenderPose[eye] = ovrHmd_GetEyePose(HMD, eye); +#endif + + // Get view matrix + Matrix4f rollPitchYaw = Matrix4f::RotationY(EyeYaw); + Matrix4f finalRollPitchYaw = rollPitchYaw * Matrix4f(eyeRenderPose[eye].Orientation); + Vector3f finalUp = finalRollPitchYaw.Transform(Vector3f(0,1,0)); + Vector3f finalForward = finalRollPitchYaw.Transform(Vector3f(0,0,-1)); + Vector3f shiftedEyePos = EyePos + rollPitchYaw.Transform(eyeRenderPose[eye].Position); + + Matrix4f view = Matrix4f::LookAtRH(shiftedEyePos, + shiftedEyePos + finalForward, finalUp); + + Matrix4f proj = ovrMatrix4f_Projection(EyeRenderDesc[eye].Desc.Fov, 0.01f, 10000.0f, true); + + pRender->SetViewport(EyeRenderDesc[eye].Desc.RenderViewport.Pos.x, + EyeRenderDesc[eye].Desc.RenderViewport.Pos.y, + EyeRenderDesc[eye].Desc.RenderViewport.Size.w, + EyeRenderDesc[eye].Desc.RenderViewport.Size.h); + pRender->SetProjection(proj); + pRender->SetDepthMode(true, true); + pRoomScene->Render(pRender, Matrix4f::Translation(EyeRenderDesc[eye].ViewAdjust) * view); + + #if SDK_RENDER + ovrHmd_EndEyeRender(HMD, eye, eyeRenderPose[eye], &EyeTexture[eye].Texture); + #endif + } } - - 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); + // Now render the distorted view and finish. +#if SDK_RENDER + // Let OVR do distortion rendering, Present and flush/sync + ovrHmd_EndFrame(HMD); + +#else + DistortionMeshRender(DistortionCaps, HMD, frameTiming.TimewarpPointSeconds, + eyeRenderPose, pRender, pRendertargetTexture); + pRender->Present( VSyncEnabled ); + pRender->WaitUntilGpuIdle(); //for lowest latency + ovrHmd_EndFrameTiming(HMD); +#endif } -void OculusRoomTinyApp::destroyWindow() +/* +void RenderFramePseudoCode() { - 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); +ovrFrame hmdFrameState = ovrHmd_BeginFrame(hmd); - } - else - { - MouseCaptured = false; - ::ReleaseCapture(); - ::ShowCursor(TRUE); - } -} - -LRESULT OculusRoomTinyApp::windowProc(UINT msg, WPARAM wp, LPARAM lp) +for (int eyeIndex = 0; eyeIndex < ovrEye_Count; eyeIndex++) { - 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); -} + ovrEyeType eye = HMDDesc.EyeRenderOrder[eyeIndex]; + ovrPosef eyeRenderPose = ovrHmd_BeginEyeRender(hmd, eye); -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); -} + RenderGameView(RenderViewports[eye], eyeRenderPose); -static inline float GamepadTrigger(BYTE in) -{ - return (in < 30) ? 0.0f : (float(in-30) / 225); + ovrHmd_EndEyeRender(hmd, eye, &EyeTexture[eye].Texture); } - -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; +// Let OVR do distortion rendering, Present and Flush+Sync. +ovrHmd_EndFrame(hmd); } - +*/ //------------------------------------------------------------------------------------- -// ***** Program Startup - -int WINAPI WinMain(HINSTANCE hinst, HINSTANCE, LPSTR inArgs, int) +void Release(void) { - 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. + pRendertargetTexture->Release(); + pRendertargetTexture = 0; + ovrHmd_Destroy(HMD); + Util_ReleaseWindowAndGraphics(pRender); + pRender = 0; + if (pRoomScene) { - OculusRoomTinyApp app(hinst); - //app.hInstance = hinst; - - exitCode = app.OnStartup(inArgs); - if (!exitCode) - { - // Processes messages and calls OnIdle() to do rendering. - exitCode = app.Run(); - } - } - + delete pRoomScene; + pRoomScene = 0; + } // No OVR functions involving memory are allowed after this. - OVR::System::Destroy(); - - OVR_DEBUG_STATEMENT(_CrtDumpMemoryLeaks()); - return exitCode; + ovr_Shutdown(); } + diff --git a/Samples/OculusRoomTiny/Win32_OculusRoomTiny.h b/Samples/OculusRoomTiny/Win32_OculusRoomTiny.h deleted file mode 100644 index a86dd47..0000000 --- a/Samples/OculusRoomTiny/Win32_OculusRoomTiny.h +++ /dev/null @@ -1,189 +0,0 @@ -/************************************************************************************ - -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 -#include - -#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 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 pManager; - Ptr pSensor; - Ptr 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 diff --git a/Samples/OculusRoomTiny/Win32_OculusRoomTiny_Util.cpp b/Samples/OculusRoomTiny/Win32_OculusRoomTiny_Util.cpp new file mode 100644 index 0000000..ab0f252 --- /dev/null +++ b/Samples/OculusRoomTiny/Win32_OculusRoomTiny_Util.cpp @@ -0,0 +1,254 @@ +/************************************************************************************ + +Filename : Win32_OculusRoomTiny_Util.cpp +Content : Win32 system interface & app/graphics initialization ligic +Created : October 4, 2012 + +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 "RenderTiny_D3D11_Device.h" + +// Win32 System Variables +HWND hWnd = NULL; +HINSTANCE hInstance; +POINT WindowCenter; + +// User inputs +bool Quit = 0; +UByte MoveForward = 0, + MoveBack = 0, + MoveLeft = 0, + MoveRight = 0; + +bool ShiftDown = false, + ControlDown = false; + +// Freezes the scene during timewarp rendering. +bool FreezeEyeRender = false; + +float AdditionalYawFromMouse = 0; + +// Movement speed, in m/s applied during keyboard motion. +const float MoveSpeed = 3.0f; + +// Functions from Win32_OculusRoomTiny.cpp and DistortionMesh.cpp +int Init(); +void ProcessAndRender(); +void Release(); +void DistortionMeshRelease(void); + + +//------------------------------------------------------------------------------------- + +void OnKey(unsigned vk, bool down) +{ + switch (vk) + { + case 'Q': if (down && ControlDown) Quit = true; break; + case VK_ESCAPE: if (!down) Quit = true; break; + + 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 'F': FreezeEyeRender = !down ? !FreezeEyeRender : FreezeEyeRender; break; + + case VK_SHIFT: ShiftDown = down; break; + case VK_CONTROL:ControlDown = down; break; + } +} + +void OnMouseMove(int x) +{ + const float Sensitivity = 1.0f; + AdditionalYawFromMouse -= (Sensitivity * x)/ 360.0f; +} + +bool Util_RespondToControls(float & EyeYaw, Vector3f & EyePos, + float deltaTime, Quatf PoseOrientation) +{ + #if 0//Optional debug output + char debugString[1000]; + sprintf_s(debugString,"Pos = (%0.2f, %0.2f, %0.2f)\n",EyePos.x,EyePos.y,EyePos.z); + OutputDebugStringA(debugString); + #endif + + //Mouse rotation + EyeYaw += AdditionalYawFromMouse; + AdditionalYawFromMouse = 0; + + //Get HeadYaw + float HeadPitch, HeadRoll, HeadYaw; + PoseOrientation.GetEulerAngles(&HeadYaw,&HeadPitch, &HeadRoll); + + //Move on Eye pos from controls + Vector3f localMoveVector(0,0,0); + Matrix4f yawRotate = Matrix4f::RotationY(EyeYaw + HeadYaw); + + if (MoveForward) localMoveVector += Vector3f(0,0,-1); + if (MoveBack) localMoveVector += Vector3f(0,0,+1); + if (MoveRight) localMoveVector += Vector3f(1,0,0); + if (MoveLeft) localMoveVector += Vector3f(-1,0,0); + + Vector3f orientationVector = yawRotate.Transform(localMoveVector); + + orientationVector *= MoveSpeed * deltaTime * (ShiftDown ? 3.0f : 1.0f); + EyePos += orientationVector; + + //Some rudimentary limitation of movement, so not to go through walls + const float minDistanceToWall = 0.30f; + EyePos.x = max(EyePos.x,-10.0f + minDistanceToWall); + EyePos.x = min(EyePos.x, 10.0f - minDistanceToWall); + EyePos.z = max(EyePos.z,-20.0f + minDistanceToWall); + + //Return if need to freeze or not + return(FreezeEyeRender); +} + + +LRESULT CALLBACK systemWindowProc(HWND arg_hwnd, UINT msg, WPARAM wp, LPARAM lp) +{ + switch (msg) + { + case(WM_NCCREATE): hWnd = arg_hwnd; break; + + case WM_MOUSEMOVE: { + // 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); + OnMouseMove(newPos.x - WindowCenter.x); + 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_CREATE: SetTimer(hWnd, 0, 100, NULL); break; + case WM_TIMER: KillTimer(hWnd, 0); + + case WM_SETFOCUS: + SetCursorPos(WindowCenter.x, WindowCenter.y); + SetCapture(hWnd); + ShowCursor(FALSE); + break; + case WM_KILLFOCUS: + ReleaseCapture(); + ShowCursor(TRUE); + break; + + case WM_QUIT: + case WM_CLOSE: Quit = true; + return 0; + } + + return DefWindowProc(hWnd, msg, wp, lp); +} + + +RenderDevice* Util_InitWindowAndGraphics(Recti vp, int fullscreen, int multiSampleCount) +{ + // Window + WNDCLASS wc; + memset(&wc, 0, sizeof(wc)); + wc.lpszClassName = L"OVRAppWindow"; + wc.style = CS_OWNDC; + wc.lpfnWndProc = systemWindowProc; + wc.cbWndExtra = NULL; + RegisterClass(&wc); + + RECT winSize = { 0, 0, vp.w, vp.h }; + AdjustWindowRect(&winSize, WS_POPUP, false); + hWnd = CreateWindowA("OVRAppWindow", "OculusRoomTiny", WS_POPUP |WS_VISIBLE, + vp.x, vp.y, + winSize.right-winSize.left, winSize.bottom-winSize.top, + NULL, NULL, hInstance, NULL); + + POINT center = { vp.w / 2, vp.h / 2 }; + ::ClientToScreen(hWnd, ¢er); + WindowCenter = center; + + if (!hWnd) return(NULL); + + // Graphics + RendererParams renderParams; + renderParams.Multisample = multiSampleCount; + renderParams.Fullscreen = fullscreen; + return (RenderDevice::CreateDevice(renderParams, (void*)hWnd)); +} + + +void Util_ReleaseWindowAndGraphics(RenderDevice * prender) +{ + if (prender) + prender->Release(); + + DistortionMeshRelease(); + + if (hWnd) + { + // Release window resources. + ::DestroyWindow(hWnd); + UnregisterClass(L"OVRAppWindow", hInstance); + } +} + + +//------------------------------------------------------------------------------------- +// ***** Program Startup +// +int WINAPI WinMain(HINSTANCE hinst, HINSTANCE, LPSTR , int) +{ + hInstance = hinst; + + if (!Init()) + { + // Processes messages and calls OnIdle() to do rendering. + while (!Quit) + { + MSG msg; + if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) + { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + else + { + ProcessAndRender(); + + // Keep sleeping when we're minimized. + if (IsIconic(hWnd)) Sleep(10); + } + } + } + Release(); + OVR_DEBUG_STATEMENT(_CrtDumpMemoryLeaks()); + return (0); +} + -- cgit v1.2.3