From ffc91631e7fccb464f8f9fab535fcd360674dc92 Mon Sep 17 00:00:00 2001 From: kaetemi Date: Mon, 1 Jul 2013 23:23:54 +0200 Subject: [PATCH] Create stereo render target, see #43 --- code/nel/include/nel/3d/stereo_display.h | 4 +- code/nel/include/nel/3d/stereo_ovr.h | 13 +++- code/nel/src/3d/CMakeLists.txt | 1 + code/nel/src/3d/stereo_ovr.cpp | 90 ++++++++++++++++++++++-- code/nel/src/3d/stereo_ovr_fp.cpp | 82 +++++++++++++++++++++ 5 files changed, 180 insertions(+), 10 deletions(-) create mode 100644 code/nel/src/3d/stereo_ovr_fp.cpp diff --git a/code/nel/include/nel/3d/stereo_display.h b/code/nel/include/nel/3d/stereo_display.h index ad75ad934..2f6592b60 100644 --- a/code/nel/include/nel/3d/stereo_display.h +++ b/code/nel/include/nel/3d/stereo_display.h @@ -92,7 +92,7 @@ public: virtual ~IStereoDisplay(); /// Sets driver and generates necessary render targets - virtual void setDriver(NL3D::UDriver &driver) = 0; + virtual void setDriver(NL3D::UDriver *driver) = 0; /// Gets the required screen resolution for this device virtual void getScreenResolution(uint &width, uint &height) = 0; @@ -124,7 +124,7 @@ public: /// Returns non-NULL if a new render target was set virtual UTexture *beginRenderTarget(bool set) = 0; /// Returns true if a render target was fully drawn - virtual bool endRenderTarget(bool render) = 0; + virtual bool endRenderTarget(bool unset) = 0; static const char *getLibraryName(CStereoDeviceInfo::TStereoDeviceLibrary library); static void listDevices(std::vector &devicesOut); diff --git a/code/nel/include/nel/3d/stereo_ovr.h b/code/nel/include/nel/3d/stereo_ovr.h index 3fff84ffb..f25ef10e0 100644 --- a/code/nel/include/nel/3d/stereo_ovr.h +++ b/code/nel/include/nel/3d/stereo_ovr.h @@ -49,14 +49,18 @@ // NeL includes #include +#include // Project includes #include #include #include +#include namespace NL3D { +class ITexture; +class CTextureUser; class CStereoOVRDevicePtr; class CStereoOVRDeviceHandle; @@ -75,7 +79,7 @@ public: virtual ~CStereoOVR(); /// Sets driver and generates necessary render targets - virtual void setDriver(NL3D::UDriver &driver); + virtual void setDriver(NL3D::UDriver *driver); /// Gets the required screen resolution for this device virtual void getScreenResolution(uint &width, uint &height); @@ -107,7 +111,7 @@ public: /// Returns non-NULL if a new render target was set, always NULL if not using render targets virtual UTexture *beginRenderTarget(bool set); /// Returns true if a render target was fully drawn, always false if not using render targets - virtual bool endRenderTarget(bool render); + virtual bool endRenderTarget(bool unset); /// Get the HMD orientation @@ -138,6 +142,11 @@ private: CMatrix m_CameraMatrix[NL_STEREO_MAX_USER_CAMERAS]; mutable bool m_OrientationCached; mutable NLMISC::CQuat m_OrientationCache; + UDriver *m_Driver; + NLMISC::CSmartPtr m_BarrelTex; + NL3D::CTextureUser *m_BarrelTexU; + NL3D::UMaterial m_BarrelMat; + NLMISC::CQuadUV m_BarrelQuad; }; /* class CStereoOVR */ diff --git a/code/nel/src/3d/CMakeLists.txt b/code/nel/src/3d/CMakeLists.txt index ec07b28b8..da0288561 100644 --- a/code/nel/src/3d/CMakeLists.txt +++ b/code/nel/src/3d/CMakeLists.txt @@ -692,6 +692,7 @@ SOURCE_GROUP(Stereo FILES stereo_hmd.cpp ../../include/nel/3d/stereo_hmd.h stereo_ovr.cpp + stereo_ovr_fp.cpp ../../include/nel/3d/stereo_ovr.h) NL_TARGET_LIB(nel3d ${HEADERS} ${SRC}) diff --git a/code/nel/src/3d/stereo_ovr.cpp b/code/nel/src/3d/stereo_ovr.cpp index a4b92b39e..8eb8e1f9b 100644 --- a/code/nel/src/3d/stereo_ovr.cpp +++ b/code/nel/src/3d/stereo_ovr.cpp @@ -53,6 +53,12 @@ // NeL includes // #include #include +#include +#include +#include +#include +#include +#include // Project includes @@ -61,6 +67,8 @@ using namespace std; namespace NL3D { +extern const char *g_StereoOVR_arbfp1; + namespace { class CStereoOVRLog : public OVR::Log @@ -155,7 +163,7 @@ public: OVR::HMDInfo HMDInfo; }; -CStereoOVR::CStereoOVR(const CStereoOVRDeviceHandle *handle) : m_Stage(0), m_SubStage(0), m_OrientationCached(false) +CStereoOVR::CStereoOVR(const CStereoOVRDeviceHandle *handle) : m_Stage(0), m_SubStage(0), m_OrientationCached(false), m_BarrelTexU(NULL) { ++s_DeviceCounter; m_DevicePtr = new CStereoOVRDevicePtr(); @@ -194,6 +202,17 @@ CStereoOVR::CStereoOVR(const CStereoOVRDeviceHandle *handle) : m_Stage(0), m_Sub CStereoOVR::~CStereoOVR() { + if (!m_BarrelMat.empty()) + { + m_BarrelMat.getObjectPtr()->setTexture(0, NULL); + m_Driver->deleteMaterial(m_BarrelMat); + } + delete m_BarrelTexU; + m_BarrelTexU = NULL; + m_BarrelTex = NULL; // CSmartPtr + + m_Driver = NULL; + if (m_DevicePtr->SensorDevice) m_DevicePtr->SensorDevice->Release(); m_DevicePtr->SensorDevice.Clear(); @@ -206,9 +225,51 @@ CStereoOVR::~CStereoOVR() --s_DeviceCounter; } -void CStereoOVR::setDriver(NL3D::UDriver &driver) +void CStereoOVR::setDriver(NL3D::UDriver *driver) { - // ... + m_Driver = driver; + // Do not allow weird stuff. + uint32 width, height; + driver->getWindowSize(width, height); + nlassert(width == m_DevicePtr->HMDInfo.HResolution); + nlassert(height == m_DevicePtr->HMDInfo.VResolution); + + NL3D::IDriver *drvInternal = (static_cast(driver))->getDriver(); + + m_BarrelTex = new CTextureBloom(); // lol bloom + m_BarrelTex->setReleasable(false); + m_BarrelTex->resize(width, height); + m_BarrelTex->setFilterMode(ITexture::Linear, ITexture::LinearMipMapOff); + m_BarrelTex->setWrapS(ITexture::Clamp); + m_BarrelTex->setWrapT(ITexture::Clamp); + m_BarrelTex->setRenderTarget(true); + drvInternal->setupTexture(*m_BarrelTex); + m_BarrelTexU = new CTextureUser(m_BarrelTex); + + m_BarrelMat = m_Driver->createMaterial(); + NL3D::CMaterial *barrelMat = m_BarrelMat.getObjectPtr(); + m_BarrelMat.initUnlit(); + m_BarrelMat.setColor(CRGBA::White); + m_BarrelMat.setBlend (false); + m_BarrelMat.setAlphaTest (false); + barrelMat->setBlendFunc(CMaterial::one, CMaterial::zero); + barrelMat->setZWrite(false); + barrelMat->setZFunc(CMaterial::always); + barrelMat->setDoubleSided(true); + barrelMat->setTexture(0, m_BarrelTex); + + m_BarrelQuad.V0 = CVector(0.f, 0.f, 0.5f); + m_BarrelQuad.V1 = CVector(1.f, 0.f, 0.5f); + m_BarrelQuad.V2 = CVector(1.f, 1.f, 0.5f); + m_BarrelQuad.V3 = CVector(0.f, 1.f, 0.5f); + + float newU = drvInternal->isTextureRectangle(m_BarrelTex) ? (float)width : 1.f; + float newV = drvInternal->isTextureRectangle(m_BarrelTex) ? (float)height : 1.f; + + m_BarrelQuad.Uv0 = CUV(0.f, 0.f); + m_BarrelQuad.Uv1 = CUV(newU, 0.f); + m_BarrelQuad.Uv2 = CUV(newU, newV); + m_BarrelQuad.Uv3 = CUV(0.f, newV); } void CStereoOVR::getScreenResolution(uint &width, uint &height) @@ -391,15 +452,32 @@ bool CStereoOVR::wantInterface2D() UTexture *CStereoOVR::beginRenderTarget(bool set) { // render target always set before driver clear - nlassert(m_SubStage == 1); + // nlassert(m_SubStage <= 1); + if (m_Stage == 1) + { + if (set) + { + (static_cast(m_Driver))->setRenderTarget(*m_BarrelTexU, 0, 0, 0, 0); + } + return m_BarrelTexU; + } return NULL; } /// Returns true if a render target was fully drawn -bool CStereoOVR::endRenderTarget( bool render) +bool CStereoOVR::endRenderTarget(bool unset) { // after rendering of course - nlassert(m_SubStage > 1); + // nlassert(m_SubStage > 1); + if (m_Stage == 4) + { + if (unset) + { + CTextureUser cu; + (static_cast(m_Driver))->setRenderTarget(cu); + } + return true; + } return false; } diff --git a/code/nel/src/3d/stereo_ovr_fp.cpp b/code/nel/src/3d/stereo_ovr_fp.cpp new file mode 100644 index 000000000..eaa80f14c --- /dev/null +++ b/code/nel/src/3d/stereo_ovr_fp.cpp @@ -0,0 +1,82 @@ +/************************************************************************************ + +Filename : stereo_ovf_fp.cpp +Content : Barrel fragment program compiled to a blob of assembly +Created : July 01, 2013 + +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. + +************************************************************************************/ + +namespace NL3D { +const char *g_StereoOVR_arbfp1 = + "!!ARBfp1.0\n" + //# cgc version 3.1.0013, build date Apr 18 2012 + //# command line args: -profile arbfp1 + //# source file: pp_oculus_vr.cg + //#vendor NVIDIA Corporation + //#version 3.1.0.13 + //#profile arbfp1 + //#program pp_oculus_vr + //#semantic pp_oculus_vr.cLensCenter + //#semantic pp_oculus_vr.cScreenCenter + //#semantic pp_oculus_vr.cScale + //#semantic pp_oculus_vr.cScaleIn + //#semantic pp_oculus_vr.cHmdWarpParam + //#semantic pp_oculus_vr.cTex0 : TEX0 + //#var float2 texCoord : $vin.TEXCOORD0 : TEX0 : 0 : 1 + //#var float2 cLensCenter : : c[0] : 1 : 1 + //#var float2 cScreenCenter : : c[1] : 2 : 1 + //#var float2 cScale : : c[2] : 3 : 1 + //#var float2 cScaleIn : : c[3] : 4 : 1 + //#var float4 cHmdWarpParam : : c[4] : 5 : 1 + //#var sampler2D cTex0 : TEX0 : texunit 0 : 6 : 1 + //#var float4 oCol : $vout.COLOR : COL : 7 : 1 + //#const c[5] = 0.25 0.5 0 1 + "PARAM c[6] = { program.local[0..4],\n" + " { 0.25, 0.5, 0, 1 } };\n" + "TEMP R0;\n" + "TEMP R1;\n" + "ADD R0.xy, fragment.texcoord[0], -c[0];\n" + "MUL R0.xy, R0, c[3];\n" + "MUL R0.z, R0.y, R0.y;\n" + "MAD R0.z, R0.x, R0.x, R0;\n" + "MUL R0.w, R0.z, c[4];\n" + "MUL R0.w, R0, R0.z;\n" + "MAD R1.y, R0.z, c[4], c[4].x;\n" + "MUL R1.x, R0.z, c[4].z;\n" + "MAD R1.x, R0.z, R1, R1.y;\n" + "MAD R0.z, R0.w, R0, R1.x;\n" + "MUL R0.xy, R0, R0.z;\n" + "MOV R0.zw, c[5].xyxy;\n" + "ADD R1.xy, R0.zwzw, c[1];\n" + "MUL R0.xy, R0, c[2];\n" + "ADD R0.xy, R0, c[0];\n" + "MIN R1.xy, R1, R0;\n" + "ADD R0.zw, -R0, c[1].xyxy;\n" + "MAX R0.zw, R0, R1.xyxy;\n" + "ADD R0.zw, R0, -R0.xyxy;\n" + "ABS R0.zw, R0;\n" + "CMP R0.zw, -R0, c[5].z, c[5].w;\n" + "MUL R0.z, R0, R0.w;\n" + "ABS R0.z, R0;\n" + "CMP R0.z, -R0, c[5], c[5].w;\n" + "ABS R1.x, R0.z;\n" + "TEX R0, R0, texture[0], 2D;\n" + "CMP R1.x, -R1, c[5].z, c[5].w;\n" + "CMP result.color, -R1.x, R0, c[5].z;\n" + "END\n"; + //# 28 instructions, 2 R-regs +} \ No newline at end of file