diff options
author | Brad Davis <[email protected]> | 2014-04-14 21:25:09 -0700 |
---|---|---|
committer | Brad Davis <[email protected]> | 2014-04-14 21:25:09 -0700 |
commit | 07d0f4d0bbf3477ac6a9584f726e8ec6ab285707 (patch) | |
tree | 1854d0c690eff32e77b137567c88a52d56d8b660 /Samples/CommonSrc/Render | |
parent | f28388ff2af14b56ef2d973b2f4f9da021716d4c (diff) |
Adding windows 0.3.1 SDK
Diffstat (limited to 'Samples/CommonSrc/Render')
-rw-r--r-- | Samples/CommonSrc/Render/Render_D3D1X_Device.cpp | 710 | ||||
-rw-r--r-- | Samples/CommonSrc/Render/Render_D3D1X_Device.h | 41 | ||||
-rw-r--r-- | Samples/CommonSrc/Render/Render_Device.cpp | 2306 | ||||
-rw-r--r-- | Samples/CommonSrc/Render/Render_Device.h | 326 | ||||
-rw-r--r-- | Samples/CommonSrc/Render/Render_GL_Device.cpp | 639 | ||||
-rw-r--r-- | Samples/CommonSrc/Render/Render_GL_Device.h | 113 | ||||
-rw-r--r-- | Samples/CommonSrc/Render/Render_GL_Win32_Device.cpp | 248 | ||||
-rw-r--r-- | Samples/CommonSrc/Render/Render_GL_Win32_Device.h | 24 | ||||
-rw-r--r-- | Samples/CommonSrc/Render/Render_LoadTextureDDS.cpp | 6 | ||||
-rw-r--r-- | Samples/CommonSrc/Render/Render_XmlSceneLoader.cpp | 13 | ||||
-rw-r--r-- | Samples/CommonSrc/Render/Render_XmlSceneLoader.h | 2 |
11 files changed, 2950 insertions, 1478 deletions
diff --git a/Samples/CommonSrc/Render/Render_D3D1X_Device.cpp b/Samples/CommonSrc/Render/Render_D3D1X_Device.cpp index 6408e08..d7c606f 100644 --- a/Samples/CommonSrc/Render/Render_D3D1X_Device.cpp +++ b/Samples/CommonSrc/Render/Render_D3D1X_Device.cpp @@ -21,13 +21,20 @@ limitations under the License. ************************************************************************************/ +#define GPU_PROFILING 0 + #include "Kernel/OVR_Log.h" #include "Kernel/OVR_Std.h" #include "Render_D3D1X_Device.h" +#include "Util/Util_ImageWindow.h" + +#include "OVR_CAPI_D3D.h" #include <d3dcompiler.h> +#include <d3d9.h> // for GPU markers + #if (OVR_D3D_VERSION == 10) namespace OVR { namespace Render { namespace D3D10 { #else @@ -43,7 +50,6 @@ static D3D1x_(INPUT_ELEMENT_DESC) ModelVertexDesc[] = {"Normal", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, offsetof(Vertex, Norm), D3D1x_(INPUT_PER_VERTEX_DATA), 0}, }; - static const char* StdVertexShaderSrc = "float4x4 Proj;\n" "float4x4 View;\n" @@ -135,13 +141,18 @@ static const char* MultiTexturePixelShaderSrc = "{\n" "float4 color1;\n" "float4 color2;\n" - " color1 = Texture[0].Sample(Linear, ov.TexCoord);\n" + " color1 = Texture[0].Sample(Linear, ov.TexCoord);\n" + // go to linear space colors (assume gamma 2.0 for speed) + " color1.rgb *= color1.rgb;\n" " color2 = Texture[1].Sample(Linear, ov.TexCoord1);\n" + // go to linear space colors (assume gamma 2.0 for speed) + " color2.rgb *= color2.rgb;\n" " color2.rgb = color2.rgb * lerp(1.2, 1.9, saturate(length(color2.rgb)));\n" " color2 = color1 * color2;\n" " if (color2.a <= 0.4)\n" " discard;\n" - " return color2;\n" + // go to back to gamma space space colors (assume gamma 2.0 for speed) + " return float4(sqrt(color2.rgb), color2.a);\n" "}\n"; #define LIGHTING_COMMON \ @@ -201,7 +212,9 @@ static const char* AlphaTexturePixelShaderSrc = "};\n" "float4 main(in Varyings ov) : SV_Target\n" "{\n" - " return ov.Color * float4(1,1,1,Texture.Sample(Linear, ov.TexCoord).r);\n" + " float4 finalColor = ov.Color;\n" + " finalColor.a *= Texture.Sample(Linear, ov.TexCoord).r;\n" + " return finalColor;\n" "}\n"; @@ -211,97 +224,294 @@ 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, in float2 TexCoord1 : TEXCOORD1,\n" - " out float4 oPosition : SV_Position, out float4 oColor : COLOR, out float2 oTexCoord : TEXCOORD0)\n" + " out float4 oPosition : SV_Position, 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 = + +// 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" + "float3 DistortionClearColor;\n" + "float EdgeFadeScale;\n" + "float2 EyeToSourceUVScale;\n" + "float2 EyeToSourceUVOffset;\n" + "float2 EyeToSourceNDCScale;\n" + "float2 EyeToSourceNDCOffset;\n" + "float2 TanEyeAngleScale;\n" + "float2 TanEyeAngleOffset;\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. - "float2 HmdWarp(float2 in01)\n" + "float4 main(in float4 oPosition : SV_Position,\n" + " in float2 oTexCoord : TEXCOORD0) : SV_Target\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" + // Input oTexCoord is [-1,1] across the half of the screen used for a single eye. + " float2 TanEyeAngleDistorted = oTexCoord * TanEyeAngleScale + TanEyeAngleOffset;\n" // Scales to tan(thetaX),tan(thetaY), but still distorted (i.e. only the center is correct) + " float RadiusSq = TanEyeAngleDistorted.x * TanEyeAngleDistorted.x + TanEyeAngleDistorted.y * TanEyeAngleDistorted.y;\n" + " float Distort = rcp ( 1.0 + RadiusSq * ( HmdWarpParam.y + RadiusSq * ( HmdWarpParam.z + RadiusSq * ( HmdWarpParam.w ) ) ) );\n" + " float DistortR = Distort * ( ChromAbParam.x + RadiusSq * ChromAbParam.y );\n" + " float DistortG = Distort;\n" + " float DistortB = Distort * ( ChromAbParam.z + RadiusSq * ChromAbParam.w );\n" + " float2 TanEyeAngleR = DistortR * TanEyeAngleDistorted;\n" + " float2 TanEyeAngleG = DistortG * TanEyeAngleDistorted;\n" + " float2 TanEyeAngleB = DistortB * TanEyeAngleDistorted;\n" + + // These are now in "TanEyeAngle" space. + // The vectors (TanEyeAngleRGB.x, TanEyeAngleRGB.y, 1.0) are real-world vectors pointing from the eye to where the components of the pixel appear to be. + // If you had a raytracer, you could just use them directly. + + // Scale them into ([0,0.5],[0,1]) or ([0.5,0],[0,1]) UV lookup space (depending on eye) + " float2 SourceCoordR = TanEyeAngleR * EyeToSourceUVScale + EyeToSourceUVOffset;\n" + " float2 SourceCoordG = TanEyeAngleG * EyeToSourceUVScale + EyeToSourceUVOffset;\n" + " float2 SourceCoordB = TanEyeAngleB * EyeToSourceUVScale + EyeToSourceUVOffset;\n" + + // Find the distance to the nearest edge. + " float2 NDCCoord = TanEyeAngleG * EyeToSourceNDCScale + EyeToSourceNDCOffset;\n" + " float EdgeFadeIn = EdgeFadeScale * ( 1.0 - max ( abs ( NDCCoord.x ), abs ( NDCCoord.y ) ) );\n" + " if ( EdgeFadeIn < 0.0 )\n" + " {\n" + " return float4(DistortionClearColor.r, DistortionClearColor.g, DistortionClearColor.b, 1.0);\n" + " }\n" + " EdgeFadeIn = saturate ( EdgeFadeIn );\n" + + // Actually do the lookups. + " float ResultR = Texture.Sample(Linear, SourceCoordR).r;\n" + " float ResultG = Texture.Sample(Linear, SourceCoordG).g;\n" + " float ResultB = Texture.Sample(Linear, SourceCoordB).b;\n" + + " return float4(ResultR * EdgeFadeIn, ResultG * EdgeFadeIn, ResultB * EdgeFadeIn, 1.0);\n" + "}\n"; + +//---------------------------------------------------------------------------- + +// A vertex format used for mesh-based distortion. +/* +struct DistortionVertex +{ + Vector2f Pos; + Vector2f TexR; + Vector2f TexG; + Vector2f TexB; + Color Col; +}; +*/ +static D3D1x_(INPUT_ELEMENT_DESC) DistortionVertexDesc[] = +{ + {"Position", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D1x_(INPUT_PER_VERTEX_DATA), 0}, + {"TexCoord", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 8, D3D1x_(INPUT_PER_VERTEX_DATA), 0}, + {"TexCoord", 1, DXGI_FORMAT_R32G32_FLOAT, 0, 8+8, D3D1x_(INPUT_PER_VERTEX_DATA), 0}, + {"TexCoord", 2, DXGI_FORMAT_R32G32_FLOAT, 0, 8+8+8, D3D1x_(INPUT_PER_VERTEX_DATA), 0}, + {"Color", 0, DXGI_FORMAT_R8G8B8A8_UNORM, 0, 8+8+8+8, D3D1x_(INPUT_PER_VERTEX_DATA), 0}, +}; + + +//---------------------------------------------------------------------------- +// Simple distortion shader that does three texture reads. +// Used for mesh-based distortion without timewarp. + +static const char* PostProcessMeshVertexShaderSrc = + "float2 EyeToSourceUVScale;\n" + "float2 EyeToSourceUVOffset;\n" + "void main(in float2 Position : POSITION, in float4 Color : COLOR0, in float2 TexCoord0 : TEXCOORD0, in float2 TexCoord1 : TEXCOORD1, in float2 TexCoord2 : TEXCOORD2,\n" + " out float4 oPosition : SV_Position, out float4 oColor : COLOR, out float2 oTexCoord0 : TEXCOORD0, out float2 oTexCoord1 : TEXCOORD1, out float2 oTexCoord2 : TEXCOORD2)\n" + "{\n" + " oPosition.x = Position.x;\n" + " oPosition.y = Position.y;\n" + " oPosition.z = 0.5;\n" + " oPosition.w = 1.0;\n" + // Vertex inputs are in TanEyeAngle space for the R,G,B channels (i.e. after chromatic aberration and distortion). + // Scale them into the correct [0-1],[0-1] UV lookup space (depending on eye) + " oTexCoord0 = TexCoord0 * EyeToSourceUVScale + EyeToSourceUVOffset;\n" + " oTexCoord1 = TexCoord1 * EyeToSourceUVScale + EyeToSourceUVOffset;\n" + " oTexCoord2 = TexCoord2 * EyeToSourceUVScale + EyeToSourceUVOffset;\n" + " oColor = Color;\n" // Used for vignette fade. + "}\n"; + +static const char* PostProcessMeshPixelShaderSrc = + "Texture2D Texture : register(t0);\n" + "SamplerState Linear : register(s0);\n" + "\n" "float4 main(in float4 oPosition : SV_Position, in float4 oColor : COLOR,\n" - " in float2 oTexCoord : TEXCOORD0) : SV_Target\n" + " in float2 oTexCoord0 : TEXCOORD0, in float2 oTexCoord1 : TEXCOORD1, in float2 oTexCoord2 : TEXCOORD2) : 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" + " float ResultR = Texture.Sample(Linear, oTexCoord0).r;\n" + " float ResultG = Texture.Sample(Linear, oTexCoord1).g;\n" + " float ResultB = Texture.Sample(Linear, oTexCoord2).b;\n" + " return float4(ResultR * oColor.r, ResultG * oColor.g, ResultB * oColor.b, 1.0);\n" "}\n"; -// Shader with lens distortion and chromatic aberration correction. -static const char* PostProcessPixelShaderWithChromAbSrc = + +//---------------------------------------------------------------------------- +// Pixel shader is very simple - does three texture reads. +// Vertex shader does all the hard work. +// Used for mesh-based distortion with timewarp. + +static const char* PostProcessMeshTimewarpVertexShaderSrc = + "float2 EyeToSourceUVScale;\n" + "float2 EyeToSourceUVOffset;\n" + "float3x3 EyeRotationStart;\n" + "float3x3 EyeRotationEnd;\n" + "void main(in float2 Position : POSITION, in float4 Color : COLOR0, in float2 TexCoord0 : TEXCOORD0, in float2 TexCoord1 : TEXCOORD1, in float2 TexCoord2 : TEXCOORD2,\n" + " out float4 oPosition : SV_Position, out float4 oColor : COLOR, out float2 oTexCoord0 : TEXCOORD0, out float2 oTexCoord1 : TEXCOORD1, out float2 oTexCoord2 : TEXCOORD2)\n" + "{\n" + " oPosition.x = Position.x;\n" + " oPosition.y = Position.y;\n" + " oPosition.z = 0.5;\n" + " oPosition.w = 1.0;\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. + " float3 TanEyeAngleR = float3 ( TexCoord0.x, TexCoord0.y, 1.0 );\n" + " float3 TanEyeAngleG = float3 ( TexCoord1.x, TexCoord1.y, 1.0 );\n" + " float3 TanEyeAngleB = float3 ( TexCoord2.x, TexCoord2.y, 1.0 );\n" + + // Accurate time warp lerp vs. faster +#if 1 + // Apply the two 3x3 timewarp rotations to these vectors. + " float3 TransformedRStart = mul ( TanEyeAngleR, EyeRotationStart );\n" + " float3 TransformedGStart = mul ( TanEyeAngleG, EyeRotationStart );\n" + " float3 TransformedBStart = mul ( TanEyeAngleB, EyeRotationStart );\n" + " float3 TransformedREnd = mul ( TanEyeAngleR, EyeRotationEnd );\n" + " float3 TransformedGEnd = mul ( TanEyeAngleG, EyeRotationEnd );\n" + " float3 TransformedBEnd = mul ( TanEyeAngleB, EyeRotationEnd );\n" + // And blend between them. + " float3 TransformedR = lerp ( TransformedRStart, TransformedREnd, Color.a );\n" + " float3 TransformedG = lerp ( TransformedGStart, TransformedGEnd, Color.a );\n" + " float3 TransformedB = lerp ( TransformedBStart, TransformedBEnd, Color.a );\n" +#else + " float3x3 EyeRotation = lerp ( EyeRotationStart, EyeRotationEnd, Color.a );\n" + " float3 TransformedR = mul ( TanEyeAngleR, EyeRotation );\n" + " float3 TransformedG = mul ( TanEyeAngleG, EyeRotation );\n" + " float3 TransformedB = mul ( TanEyeAngleB, EyeRotation );\n" +#endif + + // Project them back onto the Z=1 plane of the rendered images. + " float RecipZR = rcp ( TransformedR.z );\n" + " float RecipZG = rcp ( TransformedG.z );\n" + " float RecipZB = rcp ( TransformedB.z );\n" + " float2 FlattenedR = float2 ( TransformedR.x * RecipZR, TransformedR.y * RecipZR );\n" + " float2 FlattenedG = float2 ( TransformedG.x * RecipZG, TransformedG.y * RecipZG );\n" + " float2 FlattenedB = float2 ( TransformedB.x * RecipZB, TransformedB.y * RecipZB );\n" + + // These are now still in TanEyeAngle space. + // Scale them into the correct [0-1],[0-1] UV lookup space (depending on eye) + " float2 SrcCoordR = FlattenedR * EyeToSourceUVScale + EyeToSourceUVOffset;\n" + " float2 SrcCoordG = FlattenedG * EyeToSourceUVScale + EyeToSourceUVOffset;\n" + " float2 SrcCoordB = FlattenedB * EyeToSourceUVScale + EyeToSourceUVOffset;\n" + " oTexCoord0 = SrcCoordR;\n" + " oTexCoord1 = SrcCoordG;\n" + " oTexCoord2 = SrcCoordB;\n" + " oColor = Color.r;\n" // Used for vignette fade. + "}\n"; + +static const char* PostProcessMeshTimewarpPixelShaderSrc = "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" + "float4 main(in float4 oPosition : SV_Position, in float4 oColor : COLOR,\n" + " in float2 oTexCoord0 : TEXCOORD0, in float2 oTexCoord1 : TEXCOORD1, in float2 oTexCoord2 : TEXCOORD2) : SV_Target\n" + "{\n" + " float ResultR = Texture.Sample(Linear, oTexCoord0).r;\n" + " float ResultG = Texture.Sample(Linear, oTexCoord1).g;\n" + " float ResultB = Texture.Sample(Linear, oTexCoord2).b;\n" + " return float4(ResultR * oColor.r, ResultG * oColor.g, ResultB * oColor.b, 1.0);\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. +//---------------------------------------------------------------------------- +// Pixel shader is very simple - does three texture reads. +// Vertex shader does all the hard work. +// Used for mesh-based distortion with positional timewarp. + +static const char* PostProcessMeshPositionalTimewarpVertexShaderSrc = + "Texture2DMS<float,4> DepthTexture : register(t0);\n" + // Padding because we are uploading "standard uniform buffer" constants + "float4x4 Padding1;\n" + "float4x4 Padding2;\n" + "float2 EyeToSourceUVScale;\n" + "float2 EyeToSourceUVOffset;\n" + "float2 DepthProjector;\n" + "float2 DepthDimSize;\n" + "float4x4 EyeRotationStart;\n" + "float4x4 EyeRotationEnd;\n" + + "float4 PositionFromDepth(float2 inTexCoord)\n" + "{\n" + " float2 eyeToSourceTexCoord = inTexCoord * EyeToSourceUVScale + EyeToSourceUVOffset;\n" + " float depth = DepthTexture.Load(int2(eyeToSourceTexCoord * DepthDimSize), 0).x;\n" + " float linearDepth = DepthProjector.y / (depth - DepthProjector.x);\n" + " float4 retVal = float4(inTexCoord, 1, 1);\n" + " retVal.xyz *= linearDepth;\n" + " return retVal;\n" + "}\n" + + "float2 TimewarpTexCoordToWarpedPos(float2 inTexCoord, 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 4x4 timewarp rotation to these vectors. + " float4 inputPos = PositionFromDepth(inTexCoord);\n" + " float3 transformed = float3( mul ( rotMat, inputPos ).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) + " float2 noDepthUV = flattened * EyeToSourceUVScale + EyeToSourceUVOffset;\n" + //" float depth = DepthTexture.SampleLevel(Linear, noDepthUV, 0).r;\n" + " return noDepthUV.xy;\n" + "}\n" + + "void main( in float2 Position : POSITION, in float4 Color : COLOR0, in float2 TexCoord0 : TEXCOORD0,\n" + " in float2 TexCoord1 : TEXCOORD1, in float2 TexCoord2 : TEXCOORD2,\n" + " out float4 oPosition : SV_Position, out float4 oColor : COLOR,\n" + " out float2 oTexCoord0 : TEXCOORD0, out float2 oTexCoord1 : TEXCOORD1, out float2 oTexCoord2 : TEXCOORD2)\n" + "{\n" + " oPosition.x = Position.x;\n" + " oPosition.y = Position.y;\n" + " oPosition.z = 0.5;\n" + " oPosition.w = 1.0;\n" + + " float timewarpLerpFactor = Color.a;\n" + " float4x4 lerpedEyeRot = lerp(EyeRotationStart, EyeRotationEnd, timewarpLerpFactor);\n" + //" float4x4 lerpedEyeRot = EyeRotationStart;\n" + + // warped positions are a bit more involved, hence a separate function + " oTexCoord0 = TimewarpTexCoordToWarpedPos(TexCoord0, lerpedEyeRot);\n" + " oTexCoord1 = TimewarpTexCoordToWarpedPos(TexCoord1, lerpedEyeRot);\n" + " oTexCoord2 = TimewarpTexCoordToWarpedPos(TexCoord2, lerpedEyeRot);\n" + + " oColor = Color.r; // Used for vignette fade.\n" + "}\n"; + +static const char* PostProcessMeshPositionalTimewarpPixelShaderSrc = + "Texture2D Texture : register(t0);\n" + "SamplerState Linear : register(s0);\n" + "float2 DepthDimSize;\n" + "\n" "float4 main(in float4 oPosition : SV_Position, in float4 oColor : COLOR,\n" - " in float2 oTexCoord : TEXCOORD0) : SV_Target\n" + " in float2 oTexCoord0 : TEXCOORD0, in float2 oTexCoord1 : TEXCOORD1, in float2 oTexCoord2 : TEXCOORD2) : 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" - " float4 greenColor = Texture.Sample(Linear, tcGreen);\n" - " float green = greenColor.g;\n" - " float alpha = greenColor.a;\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, alpha);\n" + " float3 result;\n" + " result.r = Texture.Sample(Linear, oTexCoord0).r;\n" + " result.g = Texture.Sample(Linear, oTexCoord1).g;\n" + " result.b = Texture.Sample(Linear, oTexCoord2).b;\n" + " return float4(result * oColor, 1.0);\n" "}\n"; +//---------------------------------------------------------------------------- static const char* VShaderSrcs[VShader_Count] = { DirectVertexShaderSrc, StdVertexShaderSrc, - PostProcessVertexShaderSrc + PostProcessVertexShaderSrc, + PostProcessMeshVertexShaderSrc, + PostProcessMeshTimewarpVertexShaderSrc, + PostProcessMeshPositionalTimewarpVertexShaderSrc }; static const char* FShaderSrcs[FShader_Count] = { @@ -309,11 +519,13 @@ static const char* FShaderSrcs[FShader_Count] = GouraudPixelShaderSrc, TexturePixelShaderSrc, AlphaTexturePixelShaderSrc, - PostProcessPixelShaderSrc, PostProcessPixelShaderWithChromAbSrc, LitSolidPixelShaderSrc, LitTexturePixelShaderSrc, - MultiTexturePixelShaderSrc + MultiTexturePixelShaderSrc, + PostProcessMeshPixelShaderSrc, + PostProcessMeshTimewarpPixelShaderSrc, + PostProcessMeshPositionalTimewarpPixelShaderSrc }; RenderDevice::RenderDevice(const RendererParams& p, HWND window) @@ -322,8 +534,8 @@ RenderDevice::RenderDevice(const RendererParams& p, HWND window) GetClientRect(window, &rc); UINT width = rc.right - rc.left; UINT height = rc.bottom - rc.top; - WindowWidth = width; - WindowHeight = height; + ::OVR::Render::RenderDevice::SetWindowSize(width, height); + Window = window; Params = p; @@ -359,17 +571,18 @@ RenderDevice::RenderDevice(const RendererParams& p, HWND window) UpdateMonitorOutputs(); } - int flags = 0; + int flags = D3D10_CREATE_DEVICE_BGRA_SUPPORT; //0; #if (OVR_D3D_VERSION == 10) - hr = D3D10CreateDevice(Adapter, D3D10_DRIVER_TYPE_HARDWARE, NULL, flags, D3D1x_(SDK_VERSION), + hr = D3D10CreateDevice1(Adapter, D3D10_DRIVER_TYPE_HARDWARE, NULL, flags, D3D10_FEATURE_LEVEL_10_1, D3D10_1_SDK_VERSION, &Device.GetRawRef()); Context = Device; Context->AddRef(); #else //11 + D3D_FEATURE_LEVEL featureLevel; // TODO: Limit certain features based on D3D feature level hr = D3D11CreateDevice(Adapter, Adapter ? D3D_DRIVER_TYPE_UNKNOWN : D3D_DRIVER_TYPE_HARDWARE, NULL, flags, NULL, 0, D3D1x_(SDK_VERSION), - &Device.GetRawRef(), NULL, &Context.GetRawRef()); + &Device.GetRawRef(), &featureLevel, &Context.GetRawRef()); #endif if (FAILED(hr)) return; @@ -387,25 +600,43 @@ RenderDevice::RenderDevice(const RendererParams& p, HWND window) MaxTextureSet[i] = 0; } - ID3D10Blob* vsData = CompileShader("vs_4_0", DirectVertexShaderSrc); + ID3D10Blob* vsData = CompileShader("vs_4_1", 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])); + OVR_ASSERT ( VShaderSrcs[i] != NULL ); // You forgot a shader! + ID3D10Blob *pShader = CompileShader("vs_4_1", VShaderSrcs[i]); + VertexShaders[i] = NULL; + if ( pShader != NULL ) + { + VertexShaders[i] = *new VertexShader(this, pShader); + } } for(int i = 0; i < FShader_Count; i++) { - PixelShaders[i] = *new PixelShader(this, CompileShader("ps_4_0", FShaderSrcs[i])); + OVR_ASSERT ( FShaderSrcs[i] != NULL ); // You forgot a shader! + ID3D10Blob *pShader = CompileShader("ps_4_1", FShaderSrcs[i]); + PixelShaders[i] = NULL; + if ( pShader != NULL ) + { + PixelShaders[i] = *new PixelShader(this, pShader); + } } SPInt bufferSize = vsData->GetBufferSize(); const void* buffer = vsData->GetBufferPointer(); ID3D1xInputLayout** objRef = &ModelVertexIL.GetRawRef(); - - HRESULT validate = Device->CreateInputLayout(ModelVertexDesc, 5, buffer, bufferSize, objRef); + HRESULT validate = Device->CreateInputLayout(ModelVertexDesc, sizeof(ModelVertexDesc)/sizeof(ModelVertexDesc[0]), buffer, bufferSize, objRef); OVR_UNUSED(validate); + ID3D10Blob* vsData2 = CompileShader("vs_4_1", PostProcessMeshVertexShaderSrc); + SPInt bufferSize2 = vsData2->GetBufferSize(); + const void* buffer2 = vsData2->GetBufferPointer(); + ID3D1xInputLayout** objRef2 = &DistortionVertexIL.GetRawRef(); + HRESULT validate2 = Device->CreateInputLayout(DistortionVertexDesc, sizeof(DistortionVertexDesc)/sizeof(DistortionVertexDesc[0]), buffer2, bufferSize2, objRef2); + OVR_UNUSED(validate2); + Ptr<ShaderSet> gouraudShaders = *new ShaderSet(); gouraudShaders->SetShader(VertexShaders[VShader_MVP]); gouraudShaders->SetShader(PixelShaders[FShader_Gouraud]); @@ -433,7 +664,7 @@ RenderDevice::RenderDevice(const RendererParams& p, HWND window) D3D1x_(RASTERIZER_DESC) rs; memset(&rs, 0, sizeof(rs)); - rs.AntialiasedLineEnable = true; + rs.AntialiasedLineEnable = false; // You can't just turn this on - it needs alpha modes etc setting up and doesn't work with Z buffers. rs.CullMode = D3D1x_(CULL_BACK); // rs.CullMode = D3D1x_(CULL_NONE); rs.DepthClipEnable = true; @@ -568,10 +799,11 @@ bool RenderDevice::RecreateSwapChain() DXGI_SWAP_CHAIN_DESC scDesc; memset(&scDesc, 0, sizeof(scDesc)); scDesc.BufferCount = 1; - scDesc.BufferDesc.Width = WindowWidth; + scDesc.BufferDesc.Width = WindowWidth; scDesc.BufferDesc.Height = WindowHeight; scDesc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; - scDesc.BufferDesc.RefreshRate.Numerator = 60; + // Use default refresh rate; switching rate on CC prototype can cause screen lockup. + scDesc.BufferDesc.RefreshRate.Numerator = 0; scDesc.BufferDesc.RefreshRate.Denominator = 1; scDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; scDesc.OutputWindow = Window; @@ -621,18 +853,60 @@ bool RenderDevice::SetParams(const RendererParams& newParams) UpdateMonitorOutputs(true); } - // Cause this to be recreated with the new multisample mode. - pSceneColorTex = NULL; return RecreateSwapChain(); } + +ovrRenderAPIConfig RenderDevice::Get_ovrRenderAPIConfig() const +{ +#if (OVR_D3D_VERSION == 10) + static ovrD3D10Config cfg; + cfg.D3D10.Header.API = ovrRenderAPI_D3D10; + cfg.D3D10.Header.RTSize = Sizei(WindowWidth, WindowHeight); + cfg.D3D10.Header.Multisample = Params.Multisample; + cfg.D3D10.pDevice = Device; + cfg.D3D10.pBackBufferRT = BackBufferRT; + cfg.D3D10.pSwapChain = SwapChain; +#else + static ovrD3D11Config cfg; + cfg.D3D11.Header.API = ovrRenderAPI_D3D11; + cfg.D3D11.Header.RTSize = Sizei(WindowWidth, WindowHeight); + cfg.D3D11.Header.Multisample = Params.Multisample; + cfg.D3D11.pDevice = Device; + cfg.D3D11.pDeviceContext = Context; + cfg.D3D11.pBackBufferRT = BackBufferRT; + cfg.D3D11.pSwapChain = SwapChain; +#endif + return cfg.Config; +} + +ovrTexture Texture::Get_ovrTexture() +{ + ovrTexture tex; + + OVR::Sizei newRTSize(Width, Height); + +#if (OVR_D3D_VERSION == 10) + ovrD3D10TextureData* texData = (ovrD3D10TextureData*)&tex; + texData->Header.API = ovrRenderAPI_D3D10; +#else + ovrD3D11TextureData* texData = (ovrD3D11TextureData*)&tex; + texData->Header.API = ovrRenderAPI_D3D11; +#endif + texData->Header.TextureSize = newRTSize; + texData->Header.RenderViewport = Recti(newRTSize); + texData->pTexture = Tex; + texData->pSRView = TexSv; + + return tex; +} void RenderDevice::SetWindowSize(int w, int h) { if (w == WindowWidth && h == WindowHeight) return; - WindowWidth = w; - WindowHeight = h; + ::OVR::Render::RenderDevice::SetWindowSize(w, h); + Context->OMSetRenderTargets(0, NULL, NULL); BackBuffer = NULL; BackBufferRT = NULL; @@ -698,32 +972,24 @@ bool RenderDevice::SetFullscreen(DisplayMode fullscreen) return true; } -void RenderDevice::SetMultipleViewports(int n, const Viewport* vps) +void RenderDevice::SetViewport(const Recti& vp) { - if (n > 2) - { - n = 2; - } - for(int i = 0; i < n; i++) - { #if (OVR_D3D_VERSION == 10) - Viewports[i].Width = vps[i].w; - Viewports[i].Height = vps[i].h; - Viewports[i].MinDepth = 0; - Viewports[i].MaxDepth = 1; - Viewports[i].TopLeftX = vps[i].x; - Viewports[i].TopLeftY = vps[i].y; + D3DViewport.Width = vp.w; + D3DViewport.Height = vp.h; + D3DViewport.MinDepth = 0; + D3DViewport.MaxDepth = 1; + D3DViewport.TopLeftX = vp.x; + D3DViewport.TopLeftY = vp.y; #else - Viewports[i].Width = (float)vps[i].w; - Viewports[i].Height = (float)vps[i].h; - Viewports[i].MinDepth = 0; - Viewports[i].MaxDepth = 1; - Viewports[i].TopLeftX = (float)vps[i].x; - Viewports[i].TopLeftY = (float)vps[i].y; + 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; #endif - } - NumViewports = n; - Context->RSSetViewports(n, Viewports); + Context->RSSetViewports(1,&D3DViewport); } static int GetDepthStateIndex(bool enable, bool write, RenderDevice::CompareFunc func) @@ -754,7 +1020,7 @@ void RenderDevice::SetDepthMode(bool enable, bool write, CompareFunc func) case Compare_Less: dss.DepthFunc = D3D1x_(COMPARISON_LESS); break; case Compare_Greater: dss.DepthFunc = D3D1x_(COMPARISON_GREATER); break; default: - assert(0); + OVR_ASSERT(0); } dss.DepthWriteMask = write ? D3D1x_(DEPTH_WRITE_MASK_ALL) : D3D1x_(DEPTH_WRITE_MASK_ZERO); Device->CreateDepthStencilState(&dss, &DepthStates[index].GetRawRef()); @@ -782,70 +1048,27 @@ Texture* RenderDevice::GetDepthBuffer(int w, int h, int ms) return newDepth.GetPtr(); } -void RenderDevice::Clear(float r, float g, float b, float a, float depth) +void RenderDevice::Clear(float r /*= 0*/, float g /*= 0*/, float b /*= 0*/, float a /*= 1*/, + float depth /*= 1*/, + bool clearColor /*= true*/, bool clearDepth /*= true*/) { - const float color[] = {r, g, b, a}; - - // save state that is affected by clearing this way - ID3D1xDepthStencilState* oldDepthState = CurDepthState; - StandardUniformData clearUniforms; - - SetDepthMode(true, true, Compare_Always); - - Context->IASetInputLayout(ModelVertexIL); -#if (OVR_D3D_VERSION == 10) - Context->GSSetShader(NULL); -#else - Context->GSSetShader(NULL, NULL, 0); -#endif - //Shader<Shader_Geometry,ID3D1xGeometryShader> NullGS(this,(ID3D1xGeometryShader*)NULL); - //NullGS.Set(Prim_TriangleStrip); - - 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]); - - if (NumViewports > 1) + if ( clearColor ) { - for(int i = 0; i < NumViewports; i++) + const float color[] = {r, g, b, a}; + if ( CurRenderTarget == NULL ) + { + Context->ClearRenderTargetView ( BackBufferRT.GetRawRef(), color ); + } + else { - Context->RSSetViewports(1, &Viewports[i]); - Context->OMSetBlendState(NULL, NULL, 0xffffffff); - Context->Draw(4, 0); + Context->ClearRenderTargetView ( CurRenderTarget->TexRtv, color ); } - Context->RSSetViewports(NumViewports, Viewports); } - else + + if ( clearDepth ) { - Context->OMSetBlendState(NULL, NULL, 0xffffffff); - Context->Draw(4, 0); + Context->ClearDepthStencilView ( CurDepthBuffer->TexDsv, D3D10_CLEAR_DEPTH | D3D10_CLEAR_STENCIL, depth, 0 ); } - - // reset - CurDepthState = oldDepthState; - Context->OMSetDepthStencilState(CurDepthState, 0); } // Buffers @@ -1280,6 +1503,11 @@ Texture::Texture(RenderDevice* ren, int fmt, int w, int h) : Ren(ren), Tex(NULL) Sampler = Ren->GetSamplerState(0); } +void* Texture::GetInternalImplementation() +{ + return Tex; +} + Texture::~Texture() { } @@ -1312,6 +1540,10 @@ void RenderDevice::SetTexture(Render::ShaderStage stage, int slot, const Texture case Shader_Vertex: Context->VSSetShaderResources(slot, 1, &sv); + if (t) + { + Context->VSSetSamplers(slot, 1, &t->Sampler.GetRawRef()); + } break; } } @@ -1501,10 +1733,22 @@ Texture* RenderDevice::CreateTexture(int format, int width, int height, const vo } else { + int samples = (format & Texture_SamplesMask); + if (samples < 1) + { + samples = 1; + } + + bool createDepthSrv = (format & Texture_SampleDepth) > 0; + DXGI_FORMAT d3dformat; int bpp; switch(format & Texture_TypeMask) { + case Texture_BGRA: + bpp = 4; + d3dformat = DXGI_FORMAT_B8G8R8A8_UNORM; + break; case Texture_RGBA: bpp = 4; d3dformat = DXGI_FORMAT_R8G8B8A8_UNORM; @@ -1513,30 +1757,28 @@ Texture* RenderDevice::CreateTexture(int format, int width, int height, const vo bpp = 1; d3dformat = DXGI_FORMAT_R8_UNORM; break; + case Texture_A: + bpp = 1; + d3dformat = DXGI_FORMAT_A8_UNORM; + break; case Texture_Depth: bpp = 0; - d3dformat = DXGI_FORMAT_D32_FLOAT; + d3dformat = createDepthSrv ? DXGI_FORMAT_R32_TYPELESS : 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.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.Count = samples; dsDesc.SampleDesc.Quality = 0; dsDesc.Usage = D3D1x_(USAGE_DEFAULT); dsDesc.BindFlags = D3D1x_(BIND_SHADER_RESOURCE); @@ -1546,9 +1788,8 @@ Texture* RenderDevice::CreateTexture(int format, int width, int height, const vo 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); + dsDesc.BindFlags = createDepthSrv ? (dsDesc.BindFlags | D3D1x_(BIND_DEPTH_STENCIL)) : D3D1x_(BIND_DEPTH_STENCIL); } else { @@ -1565,7 +1806,19 @@ Texture* RenderDevice::CreateTexture(int format, int width, int height, const vo } if (dsDesc.BindFlags & D3D1x_(BIND_SHADER_RESOURCE)) { - Device->CreateShaderResourceView(NewTex->Tex, NULL, &NewTex->TexSv.GetRawRef()); + if((dsDesc.BindFlags & D3D1x_(BIND_DEPTH_STENCIL)) > 0 && createDepthSrv) + { + D3D1x_(SHADER_RESOURCE_VIEW_DESC) depthSrv; + depthSrv.Format = DXGI_FORMAT_R32_FLOAT; + depthSrv.ViewDimension = samples > 1 ? D3D1x_(SRV_DIMENSION_TEXTURE2DMS) : D3D1x_(SRV_DIMENSION_TEXTURE2D); + depthSrv.Texture2D.MostDetailedMip = 0; + depthSrv.Texture2D.MipLevels = dsDesc.MipLevels; + Device->CreateShaderResourceView(NewTex->Tex, &depthSrv, &NewTex->TexSv.GetRawRef()); + } + else + { + Device->CreateShaderResourceView(NewTex->Tex, NULL, &NewTex->TexSv.GetRawRef()); + } } if (data) @@ -1611,7 +1864,12 @@ Texture* RenderDevice::CreateTexture(int format, int width, int height, const vo { if ((format & Texture_TypeMask) == Texture_Depth) { - Device->CreateDepthStencilView(NewTex->Tex, NULL, &NewTex->TexDsv.GetRawRef()); + D3D1x_(DEPTH_STENCIL_VIEW_DESC) depthDsv; + ZeroMemory(&depthDsv, sizeof(depthDsv)); + depthDsv.Format = DXGI_FORMAT_D32_FLOAT; + depthDsv.ViewDimension = samples > 1 ? D3D1x_(DSV_DIMENSION_TEXTURE2DMS) : D3D1x_(DSV_DIMENSION_TEXTURE2D); + depthDsv.Texture2D.MipSlice = 0; + Device->CreateDepthStencilView(NewTex->Tex, createDepthSrv ? &depthDsv : NULL, &NewTex->TexDsv.GetRawRef()); } else { @@ -1703,38 +1961,54 @@ void RenderDevice::RenderWithAlpha( const Fill* fill, Render::Buffer* vertices, } void RenderDevice::Render(const Fill* fill, Render::Buffer* vertices, Render::Buffer* indices, - const Matrix4f& matrix, int offset, int count, PrimitiveType rprim) + const Matrix4f& matrix, int offset, int count, PrimitiveType rprim, bool useDistortionVertex/* = false*/) { - Context->IASetInputLayout(ModelVertexIL); + ID3D1xBuffer* vertexBuffer = ((Buffer*)vertices)->GetBuffer(); + UINT vertexOffset = offset; + UINT vertexStride = sizeof(Vertex); + if ( useDistortionVertex ) + { + Context->IASetInputLayout(DistortionVertexIL); + vertexStride = sizeof(DistortionVertex); + } + else + { + Context->IASetInputLayout(ModelVertexIL); + vertexStride = sizeof(Vertex); + } + Context->IASetVertexBuffers(0, 1, &vertexBuffer, &vertexStride, &vertexOffset); + 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) + if ( vertexData != NULL ) { - StandardUniformData* stdUniforms = (StandardUniformData*) vertexData; - stdUniforms->View = matrix.Transposed(); - stdUniforms->Proj = StdUniforms.Proj; + // TODO: some VSes don't start with StandardUniformData! + if ( vshader->UniformsSize >= sizeof(StandardUniformData) ) + { + 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) @@ -1749,7 +2023,7 @@ void RenderDevice::Render(const Fill* fill, Render::Buffer* vertices, Render::Bu prim = D3D1x_(PRIMITIVE_TOPOLOGY_TRIANGLESTRIP); break; default: - assert(0); + OVR_ASSERT(0); return; } Context->IASetPrimitiveTopology(prim); @@ -1782,20 +2056,40 @@ UPInt RenderDevice::QueryGPUMemorySize() } -void RenderDevice::Present() +void RenderDevice::Present ( bool withVsync ) { - SwapChain->Present(0, 0); + if( OVR::Util::ImageWindow::GlobalWindow() ) + { + OVR::Util::ImageWindow::GlobalWindow()->Process(); + } + + if ( withVsync ) + { + SwapChain->Present(1, 0); + } + else + { + // Immediate present + SwapChain->Present(0, 0); + } } -void RenderDevice::ForceFlushGPU() +void RenderDevice::WaitUntilGpuIdle() { +#if 0 + // If enabling this option and using an NVIDIA GPU, + // then make sure your "max pre-rendered frames" is set to 1 under the NVIDIA GPU settings. + + // Flush GPU data and don't stall CPU waiting for GPU to complete + Context->Flush(); +#else + // Flush and Stall CPU while waiting for GPU to complete rendering all of the queued draw calls D3D1x_QUERY_DESC queryDesc = { D3D1x_(QUERY_EVENT), 0 }; Ptr<ID3D1xQuery> query; BOOL done = FALSE; if (Device->CreateQuery(&queryDesc, &query.GetRawRef()) == S_OK) { - #if (OVR_D3D_VERSION == 10) // Begin() not used for EVENT query. query->End(); @@ -1808,10 +2102,10 @@ void RenderDevice::ForceFlushGPU() do { } while(!done && !FAILED(Context->GetData(query, &done, sizeof(BOOL), 0))); #endif - } -} +#endif +} void RenderDevice::FillRect(float left, float top, float right, float bottom, Color c) { @@ -1841,5 +2135,27 @@ void RenderDevice::RenderImage(float left, float top, float right, float bottom, Context->OMSetBlendState(NULL, NULL, 0xffffffff); } +void RenderDevice::BeginGpuEvent(const char* markerText, UInt32 markerColor) +{ +#if GPU_PROFILING + WCHAR wStr[255]; + size_t newStrLen = 0; + mbstowcs_s(&newStrLen, wStr, markerText, 255); + LPCWSTR pwStr = wStr; + + D3DPERF_BeginEvent(markerColor, pwStr); +#else + OVR_UNUSED(markerText); + OVR_UNUSED(markerColor); +#endif +} + +void RenderDevice::EndGpuEvent() +{ +#if GPU_PROFILING + D3DPERF_EndEvent(); +#endif +} + }}} diff --git a/Samples/CommonSrc/Render/Render_D3D1X_Device.h b/Samples/CommonSrc/Render/Render_D3D1X_Device.h index b615e2b..e06bcda 100644 --- a/Samples/CommonSrc/Render/Render_D3D1X_Device.h +++ b/Samples/CommonSrc/Render/Render_D3D1X_Device.h @@ -42,7 +42,7 @@ limitations under the License. #if (OVR_D3D_VERSION == 10) #define _OVR_RENDERER_D3D10 -#include <d3d10.h> +#include <d3d10_1.h> namespace OVR { namespace Render { namespace D3D10 { @@ -64,8 +64,8 @@ class RenderDevice; #endif #if (OVR_D3D_VERSION == 10) -typedef ID3D10Device ID3D1xDevice; -typedef ID3D10Device ID3D1xDeviceContext; +typedef ID3D10Device1 ID3D1xDevice; +typedef ID3D10Device1 ID3D1xDeviceContext; typedef ID3D10RenderTargetView ID3D1xRenderTargetView; typedef ID3D10Texture2D ID3D1xTexture2D; typedef ID3D10ShaderResourceView ID3D1xShaderResourceView; @@ -73,6 +73,7 @@ typedef ID3D10DepthStencilView ID3D1xDepthStencilView; typedef ID3D10DepthStencilState ID3D1xDepthStencilState; typedef ID3D10InputLayout ID3D1xInputLayout; typedef ID3D10Buffer ID3D1xBuffer; +typedef ID3D10Resource ID3D1xResource; typedef ID3D10VertexShader ID3D1xVertexShader; typedef ID3D10PixelShader ID3D1xPixelShader; typedef ID3D10GeometryShader ID3D1xGeometryShader; @@ -96,6 +97,7 @@ typedef ID3D11DepthStencilView ID3D1xDepthStencilView; typedef ID3D11DepthStencilState ID3D1xDepthStencilState; typedef ID3D11InputLayout ID3D1xInputLayout; typedef ID3D11Buffer ID3D1xBuffer; +typedef ID3D11Resource ID3D1xResource; typedef ID3D10Blob ID3D1xBlob; typedef ID3D11VertexShader ID3D1xVertexShader; typedef ID3D11PixelShader ID3D1xPixelShader; @@ -201,11 +203,12 @@ public: class Texture : public Render::Texture { public: - RenderDevice* Ren; + RenderDevice* Ren; Ptr<ID3D1xTexture2D> Tex; Ptr<ID3D1xShaderResourceView> TexSv; Ptr<ID3D1xRenderTargetView> TexRtv; Ptr<ID3D1xDepthStencilView> TexDsv; + Ptr<ID3D1xTexture2D> TexStaging; mutable Ptr<ID3D1xSamplerState> Sampler; int Width, Height; int Samples; @@ -229,6 +232,11 @@ public: virtual void SetSampleMode(int sm); virtual void Set(int slot, Render::ShaderStage stage = Render::Shader_Fragment) const; + + virtual ovrTexture Get_ovrTexture(); + + virtual void* GetInternalImplementation(); + }; class RenderDevice : public Render::RenderDevice @@ -251,12 +259,12 @@ public: Ptr<Texture> CurDepthBuffer; Ptr<ID3D1xRasterizerState> Rasterizer; Ptr<ID3D1xBlendState> BlendState; - int NumViewports; - D3D1x_VIEWPORT Viewports[2]; + D3D1x_VIEWPORT D3DViewport; Ptr<ID3D1xDepthStencilState> DepthStates[1 + 2 * Compare_Count]; Ptr<ID3D1xDepthStencilState> CurDepthState; Ptr<ID3D1xInputLayout> ModelVertexIL; + Ptr<ID3D1xInputLayout> DistortionVertexIL; Ptr<ID3D1xSamplerState> SamplerStates[Sample_Count]; @@ -292,18 +300,22 @@ public: // and it should be recreated. void UpdateMonitorOutputs(bool needRecreate = false); - virtual void SetMultipleViewports(int n, const Viewport* vps); + virtual void SetViewport(const Recti& vp); virtual void SetWindowSize(int w, int h); virtual bool SetParams(const RendererParams& newParams); - //virtual void SetScissor(int x, int y, int w, int h); - virtual void Present(); - virtual void ForceFlushGPU(); + // Returns details needed by CAPI distortion rendering. + virtual ovrRenderAPIConfig Get_ovrRenderAPIConfig() const; + + virtual void Present ( bool withVsync ); + virtual void WaitUntilGpuIdle(); virtual bool SetFullscreen(DisplayMode fullscreen); virtual UPInt QueryGPUMemorySize(); - virtual void Clear(float r = 0, float g = 0, float b = 0, float a = 1, float depth = 1); + virtual void Clear(float r = 0, float g = 0, float b = 0, float a = 1, + float depth = 1, + bool clearColor = true, bool clearDepth = true); virtual void Rect(float left, float top, float right, float bottom) { OVR_UNUSED4(left, top, right, bottom); @@ -331,7 +343,6 @@ public: ExtraShaders = s; } - // Overrident to apply proper blend state. virtual void FillRect(float left, float top, float right, float bottom, Color c); virtual void FillGradientRect(float left, float top, float right, float bottom, Color col_top, Color col_btm); @@ -340,7 +351,7 @@ public: virtual void Render(const Matrix4f& matrix, Model* model); virtual void Render(const Fill* fill, Render::Buffer* vertices, Render::Buffer* indices, - const Matrix4f& matrix, int offset, int count, PrimitiveType prim = Prim_Triangles); + const Matrix4f& matrix, int offset, int count, PrimitiveType prim = Prim_Triangles, bool useDistortionVertex = false); virtual void RenderWithAlpha( const Fill* fill, Render::Buffer* vertices, Render::Buffer* indices, const Matrix4f& matrix, int offset, int count, PrimitiveType prim = Prim_Triangles); @@ -355,6 +366,10 @@ public: ID3D1xSamplerState* GetSamplerState(int sm); void SetTexture(Render::ShaderStage stage, int slot, const Texture* t); + + // GPU Profiling + virtual void BeginGpuEvent(const char* markerText, UInt32 markerColor); + virtual void EndGpuEvent(); }; }}} diff --git a/Samples/CommonSrc/Render/Render_Device.cpp b/Samples/CommonSrc/Render/Render_Device.cpp index d0f3228..e917fb0 100644 --- a/Samples/CommonSrc/Render/Render_Device.cpp +++ b/Samples/CommonSrc/Render/Render_Device.cpp @@ -25,107 +25,112 @@ limitations under the License. #include "../Render/Render_Font.h" #include "Kernel/OVR_Log.h" +#include "Util/Util_Render_Stereo.h" +using namespace OVR::Util::Render; namespace OVR { namespace Render { -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); - } -} - -Matrix4f SceneView::GetViewMatrix() const -{ - Matrix4f view = Matrix4f(GetOrientation().Conj()) * Matrix4f::Translation(GetPosition()); - return view; -} - -void LightingParams::Update(const Matrix4f& view, const Vector4f* SceneLightPos) -{ - Version++; - for (int i = 0; i < LightCount; i++) - { - LightPos[i] = view.Transform(SceneLightPos[i]); - } -} - -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 -}; - -// Colors are specified for planes perpendicular to the axis -// For example, "xColor" is the color of the y-z plane -Model* Model::CreateAxisFaceColorBox(float x1, float x2, Color xcolor, - float y1, float y2, Color ycolor, - float z1, float z2, Color zcolor) -{ - 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; - } - - Model* box = new Model(); - - UInt16 startIndex = 0; - // Cube - startIndex = - box->AddVertex(Vector3f(x1, y2, z1), ycolor); + void Model::Render(const Matrix4f& ltw, RenderDevice* ren) + { + if(Visible) + { + AutoGpuProf prof(ren, "Model_Render"); + 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); + } + } + + Matrix4f SceneView::GetViewMatrix() const + { + Matrix4f view = Matrix4f(GetOrientation().Conj()) * Matrix4f::Translation(GetPosition()); + return view; + } + + void LightingParams::Update(const Matrix4f& view, const Vector3f* SceneLightPos) + { + Version++; + for (int i = 0; i < LightCount; i++) + { + LightPos[i] = view.Transform(SceneLightPos[i]); + } + } + + void Scene::Render(RenderDevice* ren, const Matrix4f& view) + { + AutoGpuProf prof(ren, "Scene_Render"); + + 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 + }; + + // Colors are specified for planes perpendicular to the axis + // For example, "xColor" is the color of the y-z plane + Model* Model::CreateAxisFaceColorBox(float x1, float x2, Color xcolor, + float y1, float y2, Color ycolor, + float z1, float z2, Color zcolor) + { + 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; + } + + Model* box = new Model(); + + UInt16 startIndex = 0; + // Cube + startIndex = + box->AddVertex(Vector3f(x1, y2, z1), ycolor); box->AddVertex(Vector3f(x2, y2, z1), ycolor); box->AddVertex(Vector3f(x2, y2, z2), ycolor); box->AddVertex(Vector3f(x1, y2, z2), ycolor); @@ -156,960 +161,1233 @@ Model* Model::CreateAxisFaceColorBox(float x1, float x2, Color xcolor, box->AddVertex(Vector3f(x1, y2, z2), zcolor); - enum - { - // CubeVertexCount = sizeof(CubeVertices)/sizeof(CubeVertices[0]), - CubeIndexCount = sizeof(CubeIndices) / sizeof(CubeIndices[0]) - }; - - // Renumber indices - for(int i = 0; i < CubeIndexCount / 3; i++) - { - box->AddTriangle(CubeIndices[i * 3] + startIndex, - CubeIndices[i * 3 + 1] + startIndex, - CubeIndices[i * 3 + 2] + startIndex); - } - - return box; -} - -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); - } -} - - - -Model* Model::CreateBox(Color c, Vector3f origin, Vector3f size) -{ - Model *box = new Model(); - Vector3f s = size * 0.5f; - - box->AddVertex(-s.x, s.y, -s.z, c, 0, 1, 0, 0, -1); - box->AddVertex(s.x, s.y, -s.z, c, 1, 1, 0, 0, -1); - box->AddVertex(s.x, -s.y, -s.z, c, 1, 0, 0, 0, -1); - box->AddVertex(-s.x, -s.y, -s.z, c, 0, 0, 0, 0, -1); - box->AddTriangle(2, 1, 0); - box->AddTriangle(0, 3, 2); - - box->AddVertex(s.x, s.y, s.z, c, 1, 1, 0, 0, 1); - box->AddVertex(-s.x, s.y, s.z, c, 0, 1, 0, 0, 1); - box->AddVertex(-s.x, -s.y, s.z, c, 0, 0, 0, 0, 1); - box->AddVertex(s.x, -s.y, s.z, c, 1, 0, 0, 0, 1); - box->AddTriangle(6, 5, 4); - box->AddTriangle(4, 7, 6); - - box->AddVertex(-s.x, s.y, -s.z, c, 1, 0, -1, 0, 0); - box->AddVertex(-s.x, s.y, s.z, c, 1, 1, -1, 0, 0); - box->AddVertex(-s.x, -s.y, s.z, c, 0, 1, -1, 0, 0); - box->AddVertex(-s.x, -s.y, -s.z, c, 0, 0, -1, 0, 0); - box->AddTriangle(10, 11, 8); - box->AddTriangle(8, 9, 10); - - box->AddVertex(s.x, s.y, -s.z, c, 1, 0, 1, 0, 0); - box->AddVertex(s.x, -s.y, -s.z, c, 0, 0, 1, 0, 0); - box->AddVertex(s.x, -s.y, s.z, c, 0, 1, 1, 0, 0); - box->AddVertex(s.x, s.y, s.z, c, 1, 1, 1, 0, 0); - box->AddTriangle(14, 15, 12); - box->AddTriangle(12, 13, 14); - - box->AddVertex(-s.x, -s.y, s.z, c, 0, 1, 0, -1, 0); - box->AddVertex(s.x, -s.y, s.z, c, 1, 1, 0, -1, 0); - box->AddVertex(s.x, -s.y, -s.z, c, 1, 0, 0, -1, 0); - box->AddVertex(-s.x, -s.y, -s.z, c, 0, 0, 0, -1, 0); - box->AddTriangle(18, 19, 16); - box->AddTriangle(16, 17, 18); - - box->AddVertex(-s.x, s.y, -s.z, c, 0, 0, 0, 1, 0); - box->AddVertex(s.x, s.y, -s.z, c, 1, 0, 0, 1, 0); - box->AddVertex(s.x, s.y, s.z, c, 1, 1, 0, 1, 0); - box->AddVertex(-s.x, s.y, s.z, c, 0, 1, 0, 1, 0); - box->AddTriangle(20, 21, 22); - box->AddTriangle(22, 23, 20); - - box->SetPosition(origin); - return box; -} - -// Triangulation of a cylinder centered at the origin -Model* Model::CreateCylinder(Color color, Vector3f origin, float height, float radius, int sides) -{ - Model *cyl = new Model(); - float halfht = height * 0.5f; - for(UInt16 i = 0; i < sides; i++) - { - float x = cosf(Math<float>::TwoPi * i / float(sides)); - float y = sinf(Math<float>::TwoPi * i / float(sides)); - - cyl->AddVertex(radius * x, radius * y, halfht, color, x + 1, y, 0, 0, 1); - cyl->AddVertex(radius * x, radius * y, -1.0f*halfht, color, x, y, 0, 0, -1); - - UInt16 j = 0; - if(i < sides - 1) - { - j = i + 1; - cyl->AddTriangle(0, i * 4 + 4, i * 4); - cyl->AddTriangle(1, i * 4 + 1, i * 4 + 5); - } - - float nx = cosf(Math<float>::Pi * (0.5f + 2.0f * i / float(sides))); - float ny = sinf(Math<float>::Pi * (0.5f + 2.0f * i / float(sides))); - cyl->AddVertex(radius * x, radius * y, halfht, color, x + 1, y, nx, ny, 0); - cyl->AddVertex(radius * x, radius * y, -1.0f*halfht, color, x, y, nx, ny, 0); - - cyl->AddTriangle(i * 4 + 2, j * 4 + 2, i * 4 + 3); - cyl->AddTriangle(i * 4 + 3, j * 4 + 2, j * 4 + 3); - } - cyl->SetPosition(origin); - return cyl; -}; - -//Triangulation of a cone centered at the origin -Model* Model::CreateCone(Color color, Vector3f origin, float height, float radius, int sides) -{ - Model *cone = new Model(); - float halfht = height * 0.5f; - cone->AddVertex(0.0f, 0.0f, -1.0f*halfht, color, 0, 0, 0, 0, -1); - - for(UInt16 i = 0; i < sides; i++) - { - float x = cosf(Math<float>::TwoPi * i / float(sides)); - float y = sinf(Math<float>::TwoPi * i / float(sides)); - - cone->AddVertex(radius * x, radius * y, -1.0f*halfht, color, 0, 0, 0, 0, -1); - - UInt16 j = 1; - if(i < sides - 1) - { - j = i + 1; - } - - float next_x = cosf(Math<float>::TwoPi * j / float(sides)); - float next_y = sinf(Math<float>::TwoPi * j / float(sides)); - - Vector3f normal = Vector3f(x, y, -halfht).Cross(Vector3f(next_x, next_y, -halfht)); - - cone->AddVertex(0.0f, 0.0f, halfht, color, 1, 0, normal.x, normal.y, normal.z); - cone->AddVertex(radius * x, radius * y, -1.0f*halfht, color, 0, 0, normal.x, normal.y, normal.z); - - cone->AddTriangle(0, 3*i + 1, 3*j + 1); - cone->AddTriangle(3*i + 2, 3*j + 3, 3*i + 3); - } - cone->SetPosition(origin); - return cone; -}; - -//Triangulation of a sphere centered at the origin -Model* Model::CreateSphere(Color color, Vector3f origin, float radius, int sides) -{ - Model *sphere = new Model(); - UInt16 usides = (UInt16) sides; - UInt16 halfsides = usides/2; - - for(UInt16 k = 0; k < halfsides; k++) { - - float z = cosf(Math<float>::Pi * k / float(halfsides)); - float z_r = sinf(Math<float>::Pi * k / float(halfsides)); // the radius of the cross circle with coordinate z - - if (k == 0) - { // add north and south poles - sphere->AddVertex(0.0f, 0.0f, radius, color, 0, 0, 0, 0, 1); - sphere->AddVertex(0.0f, 0.0f, -radius, color, 1, 1, 0, 0, -1); - } - else - { - for(UInt16 i = 0; i < sides; i++) - { - float x = cosf(Math<float>::TwoPi * i / float(sides)) * z_r; - float y = sinf(Math<float>::TwoPi * i / float(sides)) * z_r; - - UInt16 j = 0; - if(i < sides - 1) - { - j = i + 1; - } - - sphere->AddVertex(radius * x, radius * y, radius * z, color, 0, 1, x, y, z); - - UInt16 indi = 2 + (k -1)*usides + i; - UInt16 indj = 2 + (k -1)*usides + j; - if (k == 1) // NorthPole - sphere->AddTriangle(0, j + 2, i + 2); - else if (k == halfsides - 1) //SouthPole - { - sphere->AddTriangle(1, indi, indj); - sphere->AddTriangle(indi, indi - usides, indj); - sphere->AddTriangle(indi - usides, indj - usides, indj); - } - else - { - sphere->AddTriangle(indi, indi - usides, indj); - sphere->AddTriangle(indi - usides, indj - usides, indj); - } - } - } // end else - } - sphere->SetPosition(origin); - return sphere; -}; - -Model* Model::CreateGrid(Vector3f origin, Vector3f stepx, Vector3f stepy, - int halfx, int halfy, int nmajor, Color minor, Color major) -{ - Model* grid = new Model(Prim_Lines); - float halfxf = (float)halfx; - float halfyf = (float)halfy; - - for(int jn = 0; jn <= halfy; jn++) - { - float j = (float)jn; - - grid->AddLine(grid->AddVertex((stepx * -halfxf) + (stepy * j), (jn % nmajor) ? minor : major, 0, 0.5f), - grid->AddVertex((stepx * halfxf) + (stepy * j), (jn % nmajor) ? minor : major, 1, 0.5f)); - - if(j) - grid->AddLine(grid->AddVertex((stepx * -halfxf) + (stepy * -j), (jn % nmajor) ? minor : major, 0, 0.5f), - grid->AddVertex((stepx * halfxf) + (stepy * -j), (jn % nmajor) ? minor : major, 1, 0.5f)); - } - - for(int in = 0; in <= halfx; in++) - { - float i = (float)in; - - grid->AddLine(grid->AddVertex((stepx * i) + (stepy * -halfyf), (in % nmajor) ? minor : major, 0, 0.5f), - grid->AddVertex((stepx * i) + (stepy * halfyf), (in % nmajor) ? minor : major, 1, 0.5f)); - - if(i) - grid->AddLine(grid->AddVertex((stepx * -i) + (stepy * -halfyf), (in % nmajor) ? minor : major, 0, 0.5f), - grid->AddVertex((stepx * -i) + (stepy * halfyf), (in % nmajor) ? minor : major, 1, 0.5f)); - } - - grid->SetPosition(origin); - return grid; -} - - -//------------------------------------------------------------------------------------- - - -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), - DistortionClearColor(0, 0, 0), - PostProcessShaderActive(PostProcessShader_DistortionAndChromAb), - TotalTextureMemoryUsage(0) -{ - PostProcessShaderRequested = PostProcessShaderActive; -} - -Fill* RenderDevice::CreateTextureFill(Render::Texture* t, bool useAlpha) -{ - ShaderSet* shaders = CreateShaderSet(); - shaders->SetShader(LoadBuiltinShader(Shader_Vertex, VShader_MVP)); - shaders->SetShader(LoadBuiltinShader(Shader_Fragment, useAlpha ? FShader_AlphaTexture : FShader_Texture)); - Fill* f = new ShaderFill(*shaders); - f->SetTexture(0, t); - return f; -} - -void LightingParams::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); -} - -void RenderDevice::SetLighting(const LightingParams* lt) -{ - if (!LightingBuffer) - LightingBuffer = *CreateBuffer(); - - LightingBuffer->Data(Buffer_Uniform, lt, sizeof(LightingParams)); - SetCommonUniformBuffer(1, LightingBuffer); -} - -float RenderDevice::MeasureText(const Font* font, const char* str, float size, float* strsize) -{ - UPInt length = strlen(str); - float w = 0; - float xp = 0; - float yp = 0; - - for (UPInt i = 0; i < length; i++) - { - if(str[i] == '\n') - { - yp += font->lineheight; - if(xp > w) - { - w = xp; - } - xp = 0; - continue; - } - - // Tab followed by a numbers sets position to specified offset. - if(str[i] == '\t') - { - char *p = 0; - float tabPixels = (float)OVR_strtoq(str + i + 1, &p, 10); - i += p - (str + i + 1); - xp = tabPixels; - } - else - { - const Font::Char* ch = &font->chars[str[i]]; - xp += ch->advance; - } - } - - if(xp > w) - { - w = xp; - } - - if(strsize) - { - strsize[0] = (size / font->lineheight) * w; - strsize[1] = (size / font->lineheight) * (yp + font->lineheight); - } - return (size / font->lineheight) * w; -} - -void RenderDevice::RenderText(const Font* font, const char* str, - float x, float y, float size, Color c) -{ - if(!pTextVertexBuffer) - { - pTextVertexBuffer = *CreateBuffer(); - if(!pTextVertexBuffer) - { - return; - } - } - - if(!font->fill) - { - font->fill = CreateTextureFill(Ptr<Texture>( - *CreateTexture(Texture_R, font->twidth, font->theight, font->tex)), true); - } - - UPInt length = strlen(str); - - pTextVertexBuffer->Data(Buffer_Vertex, NULL, length * 6 * sizeof(Vertex)); - Vertex* vertices = (Vertex*)pTextVertexBuffer->Map(0, length * 6 * sizeof(Vertex), Map_Discard); - if(!vertices) - { - return; - } + enum + { + // CubeVertexCount = sizeof(CubeVertices)/sizeof(CubeVertices[0]), + CubeIndexCount = sizeof(CubeIndices) / sizeof(CubeIndices[0]) + }; + + // Renumber indices + for(int i = 0; i < CubeIndexCount / 3; i++) + { + box->AddTriangle(CubeIndices[i * 3] + startIndex, + CubeIndices[i * 3 + 1] + startIndex, + CubeIndices[i * 3 + 2] + startIndex); + } + + return box; + } + + 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); + } + } + + // Adds box at specified location to current vertices. + void Model::AddBox(Color c, Vector3f origin, Vector3f size) + { + Vector3f s = size * 0.5f; + Vector3f o = origin; + UInt16 i = GetNextVertexIndex(); + + AddVertex(-s.x + o.x, s.y + o.y, -s.z + o.z, c, 0, 1, 0, 0, -1); + AddVertex(s.x + o.x, s.y + o.y, -s.z + o.z, c, 1, 1, 0, 0, -1); + AddVertex(s.x + o.x, -s.y + o.y, -s.z + o.z, c, 1, 0, 0, 0, -1); + AddVertex(-s.x + o.x, -s.y + o.y, -s.z + o.z, c, 0, 0, 0, 0, -1); + AddTriangle(2 + i, 1 + i, 0 + i); + AddTriangle(0 + i, 3 + i, 2 + i); + + AddVertex(s.x + o.x, s.y + o.y, s.z + o.z, c, 1, 1, 0, 0, 1); + AddVertex(-s.x+ o.x, s.y + o.y, s.z + o.z, c, 0, 1, 0, 0, 1); + AddVertex(-s.x+ o.x, -s.y + o.y, s.z + o.z, c, 0, 0, 0, 0, 1); + AddVertex(s.x + o.x, -s.y + o.y, s.z + o.z, c, 1, 0, 0, 0, 1); + AddTriangle(6 + i, 5 + i, 4 + i); + AddTriangle(4 + i, 7 + i, 6 + i); + + AddVertex(-s.x + o.x, s.y + o.y, -s.z + o.z, c, 1, 0, -1, 0, 0); + AddVertex(-s.x + o.x, s.y + o.y, s.z + o.z, c, 1, 1, -1, 0, 0); + AddVertex(-s.x + o.x, -s.y + o.y, s.z + o.z, c, 0, 1, -1, 0, 0); + AddVertex(-s.x + o.x, -s.y + o.y, -s.z + o.z, c, 0, 0, -1, 0, 0); + AddTriangle(10 + i, 11 + i, 8 + i); + AddTriangle(8 + i, 9 + i, 10 + i); + + AddVertex(s.x + o.x, s.y + o.y, -s.z + o.z, c, 1, 0, 1, 0, 0); + AddVertex(s.x + o.x, -s.y + o.y, -s.z + o.z, c, 0, 0, 1, 0, 0); + AddVertex(s.x + o.x, -s.y + o.y, s.z + o.z, c, 0, 1, 1, 0, 0); + AddVertex(s.x + o.x, s.y + o.y, s.z + o.z, c, 1, 1, 1, 0, 0); + AddTriangle(14 + i, 15 + i, 12 + i); + AddTriangle(12 + i, 13 + i, 14 + i); + + AddVertex(-s.x+ o.x, -s.y + o.y, s.z + o.z, c, 0, 1, 0, -1, 0); + AddVertex(s.x + o.x, -s.y + o.y, s.z + o.z, c, 1, 1, 0, -1, 0); + AddVertex(s.x + o.x, -s.y + o.y, -s.z + o.z, c, 1, 0, 0, -1, 0); + AddVertex(-s.x+ o.x, -s.y + o.y, -s.z + o.z, c, 0, 0, 0, -1, 0); + AddTriangle(18 + i, 19 + i, 16 + i); + AddTriangle(16 + i, 17 + i, 18 + i); + + AddVertex(-s.x + o.x, s.y + o.y, -s.z + o.z, c, 0, 0, 0, 1, 0); + AddVertex(s.x + o.x, s.y + o.y, -s.z + o.z, c, 1, 0, 0, 1, 0); + AddVertex(s.x + o.x, s.y + o.y, s.z + o.z, c, 1, 1, 0, 1, 0); + AddVertex(-s.x + o.x, s.y + o.y, s.z + o.z, c, 0, 1, 0, 1, 0); + AddTriangle(20 + i, 21 + i, 22 + i); + AddTriangle(22 + i, 23 + i, 20 + i); + } + + + Model* Model::CreateBox(Color c, Vector3f origin, Vector3f size) + { + Model *box = new Model(); + box->AddBox(c, Vector3f(0), size); + box->SetPosition(origin); + return box; + } + + // Triangulation of a cylinder centered at the origin + Model* Model::CreateCylinder(Color color, Vector3f origin, float height, float radius, int sides) + { + Model *cyl = new Model(); + float halfht = height * 0.5f; + for(UInt16 i = 0; i < sides; i++) + { + float x = cosf(Math<float>::TwoPi * i / float(sides)); + float y = sinf(Math<float>::TwoPi * i / float(sides)); + + cyl->AddVertex(radius * x, radius * y, halfht, color, x + 1, y, 0, 0, 1); + cyl->AddVertex(radius * x, radius * y, -1.0f*halfht, color, x, y, 0, 0, -1); + + UInt16 j = 0; + if(i < sides - 1) + { + j = i + 1; + cyl->AddTriangle(0, i * 4 + 4, i * 4); + cyl->AddTriangle(1, i * 4 + 1, i * 4 + 5); + } + + float nx = cosf(Math<float>::Pi * (0.5f + 2.0f * i / float(sides))); + float ny = sinf(Math<float>::Pi * (0.5f + 2.0f * i / float(sides))); + cyl->AddVertex(radius * x, radius * y, halfht, color, x + 1, y, nx, ny, 0); + cyl->AddVertex(radius * x, radius * y, -1.0f*halfht, color, x, y, nx, ny, 0); + + cyl->AddTriangle(i * 4 + 2, j * 4 + 2, i * 4 + 3); + cyl->AddTriangle(i * 4 + 3, j * 4 + 2, j * 4 + 3); + } + cyl->SetPosition(origin); + return cyl; + }; + + //Triangulation of a cone centered at the origin + Model* Model::CreateCone(Color color, Vector3f origin, float height, float radius, int sides) + { + Model *cone = new Model(); + float halfht = height * 0.5f; + cone->AddVertex(0.0f, 0.0f, -1.0f*halfht, color, 0, 0, 0, 0, -1); + + for(UInt16 i = 0; i < sides; i++) + { + float x = cosf(Math<float>::TwoPi * i / float(sides)); + float y = sinf(Math<float>::TwoPi * i / float(sides)); + + cone->AddVertex(radius * x, radius * y, -1.0f*halfht, color, 0, 0, 0, 0, -1); + + UInt16 j = 1; + if(i < sides - 1) + { + j = i + 1; + } + + float next_x = cosf(Math<float>::TwoPi * j / float(sides)); + float next_y = sinf(Math<float>::TwoPi * j / float(sides)); + + Vector3f normal = Vector3f(x, y, -halfht).Cross(Vector3f(next_x, next_y, -halfht)); + + cone->AddVertex(0.0f, 0.0f, halfht, color, 1, 0, normal.x, normal.y, normal.z); + cone->AddVertex(radius * x, radius * y, -1.0f*halfht, color, 0, 0, normal.x, normal.y, normal.z); + + cone->AddTriangle(0, 3*i + 1, 3*j + 1); + cone->AddTriangle(3*i + 2, 3*j + 3, 3*i + 3); + } + cone->SetPosition(origin); + return cone; + }; + + //Triangulation of a sphere centered at the origin + Model* Model::CreateSphere(Color color, Vector3f origin, float radius, int sides) + { + Model *sphere = new Model(); + UInt16 usides = (UInt16) sides; + UInt16 halfsides = usides/2; + + for(UInt16 k = 0; k < halfsides; k++) { + + float z = cosf(Math<float>::Pi * k / float(halfsides)); + float z_r = sinf(Math<float>::Pi * k / float(halfsides)); // the radius of the cross circle with coordinate z + + if (k == 0) + { // add north and south poles + sphere->AddVertex(0.0f, 0.0f, radius, color, 0, 0, 0, 0, 1); + sphere->AddVertex(0.0f, 0.0f, -radius, color, 1, 1, 0, 0, -1); + } + else + { + for(UInt16 i = 0; i < sides; i++) + { + float x = cosf(Math<float>::TwoPi * i / float(sides)) * z_r; + float y = sinf(Math<float>::TwoPi * i / float(sides)) * z_r; - Matrix4f m = Matrix4f(size / font->lineheight, 0, 0, 0, - 0, size / font->lineheight, 0, 0, - 0, 0, 0, 0, - x, y, 0, 1).Transposed(); + UInt16 j = 0; + if(i < sides - 1) + { + j = i + 1; + } - float xp = 0, yp = (float)font->ascent; - int ivertex = 0; + sphere->AddVertex(radius * x, radius * y, radius * z, color, 0, 1, x, y, z); - for (UPInt i = 0; i < length; i++) - { - if(str[i] == '\n') - { - yp += font->lineheight; - xp = 0; - continue; - } - // Tab followed by a numbers sets position to specified offset. - if(str[i] == '\t') - { - char *p = 0; - float tabPixels = (float)OVR_strtoq(str + i + 1, &p, 10); - i += p - (str + i + 1); - xp = tabPixels; - continue; - } - - const Font::Char* ch = &font->chars[str[i]]; - Vertex* chv = &vertices[ivertex]; - for(int j = 0; j < 6; j++) - { - chv[j].C = c; - } - float x = xp + ch->x; - float y = yp - ch->y; - float cx = font->twidth * (ch->u2 - ch->u1); - float cy = font->theight * (ch->v2 - ch->v1); - chv[0] = Vertex(Vector3f(x, y, 0), c, ch->u1, ch->v1); - chv[1] = Vertex(Vector3f(x + cx, y, 0), c, ch->u2, ch->v1); - chv[2] = Vertex(Vector3f(x + cx, cy + y, 0), c, ch->u2, ch->v2); - chv[3] = Vertex(Vector3f(x, y, 0), c, ch->u1, ch->v1); - chv[4] = Vertex(Vector3f(x + cx, cy + y, 0), c, ch->u2, ch->v2); - chv[5] = Vertex(Vector3f(x, y + cy, 0), c, ch->u1, ch->v2); - ivertex += 6; - - xp += ch->advance; - } - - pTextVertexBuffer->Unmap(vertices); + UInt16 indi = 2 + (k -1)*usides + i; + UInt16 indj = 2 + (k -1)*usides + j; + if (k == 1) // NorthPole + sphere->AddTriangle(0, j + 2, i + 2); + else if (k == halfsides - 1) //SouthPole + { + sphere->AddTriangle(1, indi, indj); + sphere->AddTriangle(indi, indi - usides, indj); + sphere->AddTriangle(indi - usides, indj - usides, indj); + } + else + { + sphere->AddTriangle(indi, indi - usides, indj); + sphere->AddTriangle(indi - usides, indj - usides, indj); + } + } + } // end else + } + sphere->SetPosition(origin); + return sphere; + }; - Render(font->fill, pTextVertexBuffer, NULL, m, 0, ivertex, Prim_Triangles); -} + Model* Model::CreateGrid(Vector3f origin, Vector3f stepx, Vector3f stepy, + int halfx, int halfy, int nmajor, Color minor, Color major) + { + Model* grid = new Model(Prim_Lines); + float halfxf = (float)halfx; + float halfyf = (float)halfy; -void RenderDevice::FillRect(float left, float top, float right, float bottom, Color c) -{ - if(!pTextVertexBuffer) - { - pTextVertexBuffer = *CreateBuffer(); - if(!pTextVertexBuffer) - { - return; - } - } + for(int jn = 0; jn <= halfy; jn++) + { + float j = (float)jn; - // Get!! - Fill* fill = CreateSimpleFill(); + grid->AddLine(grid->AddVertex((stepx * -halfxf) + (stepy * j), (jn % nmajor) ? minor : major, 0, 0.5f), + grid->AddVertex((stepx * halfxf) + (stepy * j), (jn % nmajor) ? minor : major, 1, 0.5f)); - pTextVertexBuffer->Data(Buffer_Vertex, NULL, 6 * sizeof(Vertex)); - Vertex* vertices = (Vertex*)pTextVertexBuffer->Map(0, 6 * sizeof(Vertex), Map_Discard); - if(!vertices) - { - return; - } + if(j) + grid->AddLine(grid->AddVertex((stepx * -halfxf) + (stepy * -j), (jn % nmajor) ? minor : major, 0, 0.5f), + grid->AddVertex((stepx * halfxf) + (stepy * -j), (jn % nmajor) ? minor : major, 1, 0.5f)); + } - vertices[0] = Vertex(Vector3f(left, top, 0.0f), c); - vertices[1] = Vertex(Vector3f(right, top, 0), c); - vertices[2] = Vertex(Vector3f(left, bottom, 0), c); - vertices[3] = Vertex(Vector3f(left, bottom, 0), c); - vertices[4] = Vertex(Vector3f(right, top, 0), c); - vertices[5] = Vertex(Vector3f(right, bottom, 0), c); + for(int in = 0; in <= halfx; in++) + { + float i = (float)in; - pTextVertexBuffer->Unmap(vertices); + grid->AddLine(grid->AddVertex((stepx * i) + (stepy * -halfyf), (in % nmajor) ? minor : major, 0, 0.5f), + grid->AddVertex((stepx * i) + (stepy * halfyf), (in % nmajor) ? minor : major, 1, 0.5f)); - Render(fill, pTextVertexBuffer, NULL, Matrix4f(), 0, 6, Prim_Triangles); -} + if(i) + grid->AddLine(grid->AddVertex((stepx * -i) + (stepy * -halfyf), (in % nmajor) ? minor : major, 0, 0.5f), + grid->AddVertex((stepx * -i) + (stepy * halfyf), (in % nmajor) ? minor : major, 1, 0.5f)); + } -void RenderDevice::FillGradientRect(float left, float top, float right, float bottom, Color col_top, Color col_btm) -{ - if(!pTextVertexBuffer) - { - pTextVertexBuffer = *CreateBuffer(); - if(!pTextVertexBuffer) - { - return; - } - } + grid->SetPosition(origin); + return grid; + } - // Get!! - Fill* fill = CreateSimpleFill(); - pTextVertexBuffer->Data(Buffer_Vertex, NULL, 6 * sizeof(Vertex)); - Vertex* vertices = (Vertex*)pTextVertexBuffer->Map(0, 6 * sizeof(Vertex), Map_Discard); - if(!vertices) - { - return; - } + //------------------------------------------------------------------------------------- - vertices[0] = Vertex(Vector3f(left, top, 0.0f), col_top); - vertices[1] = Vertex(Vector3f(right, top, 0), col_top); - vertices[2] = Vertex(Vector3f(left, bottom, 0), col_btm); - vertices[3] = Vertex(Vector3f(left, bottom, 0), col_btm); - vertices[4] = Vertex(Vector3f(right, top, 0), col_top); - vertices[5] = Vertex(Vector3f(right, bottom, 0), col_btm); - - pTextVertexBuffer->Unmap(vertices); - - Render(fill, pTextVertexBuffer, NULL, Matrix4f(), 0, 6, Prim_Triangles); -} - -void RenderDevice::RenderImage(float left, - float top, - float right, - float bottom, - ShaderFill* image, - unsigned char alpha) -{ - /* - if(!pTextVertexBuffer) - { - pTextVertexBuffer = *CreateBuffer(); - if(!pTextVertexBuffer) - { - return; - } - } - pTextVertexBuffer->Data(Buffer_Vertex, NULL, 6 * sizeof(Vertex)); - Vertex* vertices = (Vertex*)pTextVertexBuffer->Map(0, 6 * sizeof(Vertex), Map_Discard); - if(!vertices) - { - return; - } + void ShaderFill::Set(PrimitiveType prim) const + { + Shaders->Set(prim); - vertices[0] = Vertex(Vector3f(left, top, 0.0f), Color(255, 255, 255, 255)); - vertices[1] = Vertex(Vector3f(right, top, 0), Color(255, 255, 255, 255)); - vertices[2] = Vertex(Vector3f(left, bottom, 0), Color(255, 255, 255, 255)); - vertices[3] = Vertex(Vector3f(left, bottom, 0), Color(255, 255, 255, 255)); - vertices[4] = Vertex(Vector3f(right, top, 0), Color(255, 255, 255, 255)); - vertices[5] = Vertex(Vector3f(right, bottom, 0), Color(255, 255, 255, 255)); - - pTextVertexBuffer->Unmap(vertices); - - Render(image, pTextVertexBuffer, NULL, Matrix4f(), 0, 6, Prim_Triangles); - */ - - Color c = Color(255, 255, 255, alpha); - Ptr<Model> m = *new Model(Prim_Triangles); - m->AddVertex(left, bottom, 0.0f, c, 0.0f, 0.0f); - m->AddVertex(right, bottom, 0.0f, c, 1.0f, 0.0f); - m->AddVertex(right, top, 0.0f, c, 1.0f, 1.0f); - m->AddVertex(left, top, 0.0f, c, 0.0f, 1.0f); - m->AddTriangle(2,1,0); - m->AddTriangle(0,3,2); - m->Fill = image; - - Render(Matrix4f(), m); -} - -/* -void RenderDevice::GetStereoViewports(const Viewport& in, Viewport* out) const -{ - out[0] = out[1] = in; - if (StereoBufferMode == Stereo_SplitH) - { - out[0].w = out[1].w = in.w / 2; - out[1].x += WindowWidth / 2; - } -} -*/ + for(int i = 0; i < 8 && VtxTextures[i] != NULL; ++i) + VtxTextures[i]->Set(i, Shader_Vertex); -void RenderDevice::SetSceneRenderScale(float ss) -{ - SceneRenderScale = ss; - pSceneColorTex = NULL; -} + for (int i = 0; i < 8 && Textures[i] != NULL; ++i) + Textures[i]->Set(i); + } -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); - } -} + //------------------------------------------------------------------------------------- + // ***** Rendering -bool RenderDevice::initPostProcessSupport(PostProcessType pptype) -{ - if(pptype != PostProcess_Distortion) - { - return true; - } + RenderDevice::RenderDevice() + : DistortionClearColor(0, 0, 0), + TotalTextureMemoryUsage(0), + FadeOutBorderFraction(0) + { + // Ensure these are different, so that the first time it's run, things actually get initialized. + PostProcessShaderActive = PostProcessShader_Count; + PostProcessShaderRequested = PostProcessShader_DistortionAndChromAb; + } - if (PostProcessShaderRequested != PostProcessShaderActive) + void RenderDevice::Shutdown() { + // This runs before the subclass's Shutdown(), where the context, etc, may be deleted. + pTextVertexBuffer.Clear(); 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 Render::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)); + pFullScreenVertexBuffer.Clear(); + pDistortionMeshVertexBuffer[0].Clear(); + pDistortionMeshVertexBuffer[1].Clear(); + pDistortionMeshIndexBuffer[0].Clear(); + pDistortionMeshIndexBuffer[1].Clear(); + LightingBuffer.Clear(); } - 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); - SetExtraShaders(NULL); -} - -void RenderDevice::FinishScene() -{ - SetExtraShaders(0); - if(CurPostProcess == PostProcess_None) - { - return; - } - - SetRenderTarget(0); - SetRealViewport(VP); - FinishScene1(); - - CurPostProcess = PostProcess_None; -} - + Fill* RenderDevice::CreateTextureFill(Render::Texture* t, bool useAlpha) + { + ShaderSet* shaders = CreateShaderSet(); + shaders->SetShader(LoadBuiltinShader(Shader_Vertex, VShader_MVP)); + shaders->SetShader(LoadBuiltinShader(Shader_Fragment, useAlpha ? FShader_AlphaTexture : FShader_Texture)); + Fill* f = new ShaderFill(*shaders); + f->SetTexture(0, t); + return f; + } + + void LightingParams::Set(ShaderSet* s) const + { + s->SetUniform4fvArray("Ambient", 1, &Ambient); + s->SetUniform1f("LightCount", LightCount); + s->SetUniform4fvArray("LightPos", (int)LightCount, LightPos); + s->SetUniform4fvArray("LightColor", (int)LightCount, LightColor); + } + + void RenderDevice::SetLighting(const LightingParams* lt) + { + if (!LightingBuffer) + LightingBuffer = *CreateBuffer(); + + LightingBuffer->Data(Buffer_Uniform, lt, sizeof(LightingParams)); + SetCommonUniformBuffer(1, LightingBuffer); + } + + float RenderDevice::MeasureText(const Font* font, const char* str, float size, float strsize[2], + const UPInt charRange[2], Vector2f charRangeRect[2]) + { + UPInt length = strlen(str); + float w = 0; + float xp = 0; + float yp = 0; + + for (UPInt i = 0; i < length; i++) + { + if (str[i] == '\n') + { + yp += font->lineheight; + if(xp > w) + { + w = xp; + } + xp = 0; + continue; + } + + // Record top-left charRange rectangle coordinate. + if (charRange && charRangeRect && (i == charRange[0])) + charRangeRect[0] = Vector2f(xp, yp); + + // Tab followed by a numbers sets position to specified offset. + if (str[i] == '\t') + { + char *p = 0; + float tabPixels = (float)OVR_strtoq(str + i + 1, &p, 10); + i += p - (str + i + 1); + xp = tabPixels; + } + else + { + const Font::Char* ch = &font->chars[str[i]]; + xp += ch->advance; + } + + // End of character range. + // Store 'xp' after advance, yp will advance later. + if (charRange && charRangeRect && (i == charRange[1])) + charRangeRect[1] = Vector2f(xp, yp); + } + + if (xp > w) + { + w = xp; + } + + float scale = (size / font->lineheight); + + if (strsize) + { + strsize[0] = scale * w; + strsize[1] = scale * (yp + font->lineheight); + } + + if (charRange && charRangeRect) + { + // Selection rectangle ends in teh bottom. + charRangeRect[1].y += font->lineheight; + charRangeRect[0] *= scale; + charRangeRect[1] *= scale; + } + + return (size / font->lineheight) * w; + } + + + + + + void RenderDevice::RenderText(const Font* font, const char* str, + float x, float y, float size, Color c) + { + if(!pTextVertexBuffer) + { + pTextVertexBuffer = *CreateBuffer(); + if(!pTextVertexBuffer) + { + return; + } + } + + if(!font->fill) + { + font->fill = CreateTextureFill(Ptr<Texture>( + *CreateTexture(Texture_R, font->twidth, font->theight, font->tex)), true); + } + + UPInt length = strlen(str); + + pTextVertexBuffer->Data(Buffer_Vertex, NULL, length * 6 * sizeof(Vertex)); + Vertex* vertices = (Vertex*)pTextVertexBuffer->Map(0, length * 6 * sizeof(Vertex), Map_Discard); + if(!vertices) + { + return; + } + + Matrix4f m = Matrix4f(size / font->lineheight, 0, 0, 0, + 0, size / font->lineheight, 0, 0, + 0, 0, 0, 0, + x, y, 0, 1).Transposed(); + + float xp = 0, yp = (float)font->ascent; + int ivertex = 0; + + for (UPInt i = 0; i < length; i++) + { + if(str[i] == '\n') + { + yp += font->lineheight; + xp = 0; + continue; + } + // Tab followed by a numbers sets position to specified offset. + if(str[i] == '\t') + { + char *p = 0; + float tabPixels = (float)OVR_strtoq(str + i + 1, &p, 10); + i += p - (str + i + 1); + xp = tabPixels; + continue; + } + + const Font::Char* ch = &font->chars[str[i]]; + Vertex* chv = &vertices[ivertex]; + for(int j = 0; j < 6; j++) + { + chv[j].C = c; + } + float x = xp + ch->x; + float y = yp - ch->y; + float cx = font->twidth * (ch->u2 - ch->u1); + float cy = font->theight * (ch->v2 - ch->v1); + chv[0] = Vertex(Vector3f(x, y, 0), c, ch->u1, ch->v1); + chv[1] = Vertex(Vector3f(x + cx, y, 0), c, ch->u2, ch->v1); + chv[2] = Vertex(Vector3f(x + cx, cy + y, 0), c, ch->u2, ch->v2); + chv[3] = Vertex(Vector3f(x, y, 0), c, ch->u1, ch->v1); + chv[4] = Vertex(Vector3f(x + cx, cy + y, 0), c, ch->u2, ch->v2); + chv[5] = Vertex(Vector3f(x, y + cy, 0), c, ch->u1, ch->v2); + ivertex += 6; + + xp += ch->advance; + } + + pTextVertexBuffer->Unmap(vertices); + + Render(font->fill, pTextVertexBuffer, NULL, m, 0, ivertex, Prim_Triangles); + } + + void RenderDevice::FillRect(float left, float top, float right, float bottom, Color c) + { + if(!pTextVertexBuffer) + { + pTextVertexBuffer = *CreateBuffer(); + if(!pTextVertexBuffer) + { + return; + } + } + + // Get!! + Fill* fill = CreateSimpleFill(); + + pTextVertexBuffer->Data(Buffer_Vertex, NULL, 6 * sizeof(Vertex)); + Vertex* vertices = (Vertex*)pTextVertexBuffer->Map(0, 6 * sizeof(Vertex), Map_Discard); + if(!vertices) + { + return; + } + + vertices[0] = Vertex(Vector3f(left, top, 0.0f), c); + vertices[1] = Vertex(Vector3f(right, top, 0.0f), c); + vertices[2] = Vertex(Vector3f(left, bottom, 0.0f), c); + vertices[3] = Vertex(Vector3f(left, bottom, 0.0f), c); + vertices[4] = Vertex(Vector3f(right, top, 0.0f), c); + vertices[5] = Vertex(Vector3f(right, bottom, 0.0f), c); + + pTextVertexBuffer->Unmap(vertices); + + Render(fill, pTextVertexBuffer, NULL, Matrix4f(), 0, 6, Prim_Triangles); + } + + + + void RenderDevice::FillGradientRect(float left, float top, float right, float bottom, Color col_top, Color col_btm) + { + if(!pTextVertexBuffer) + { + pTextVertexBuffer = *CreateBuffer(); + if(!pTextVertexBuffer) + { + return; + } + } + + // Get!! + Fill* fill = CreateSimpleFill(); + + pTextVertexBuffer->Data(Buffer_Vertex, NULL, 6 * sizeof(Vertex)); + Vertex* vertices = (Vertex*)pTextVertexBuffer->Map(0, 6 * sizeof(Vertex), Map_Discard); + if(!vertices) + { + return; + } + + vertices[0] = Vertex(Vector3f(left, top, 0.0f), col_top); + vertices[1] = Vertex(Vector3f(right, top, 0.0f), col_top); + vertices[2] = Vertex(Vector3f(left, bottom, 0.0f), col_btm); + vertices[3] = Vertex(Vector3f(left, bottom, 0.0f), col_btm); + vertices[4] = Vertex(Vector3f(right, top, 0.0f), col_top); + vertices[5] = Vertex(Vector3f(right, bottom, 0.0f), col_btm); + + pTextVertexBuffer->Unmap(vertices); + + Render(fill, pTextVertexBuffer, NULL, Matrix4f(), 0, 6, Prim_Triangles); + } + + + void RenderDevice::FillTexturedRect(float left, float top, float right, float bottom, float ul, float vt, float ur, float vb, Color c, Ptr<Texture> tex) + { + if(!pTextVertexBuffer) + { + pTextVertexBuffer = *CreateBuffer(); + if(!pTextVertexBuffer) + { + return; + } + } + + static Fill *fill = NULL; + if ( fill == NULL ) + { + fill = CreateTextureFill(tex, false); + } + fill->SetTexture ( 0, tex ); + + pTextVertexBuffer->Data(Buffer_Vertex, NULL, 6 * sizeof(Vertex)); + Vertex* vertices = (Vertex*)pTextVertexBuffer->Map(0, 6 * sizeof(Vertex), Map_Discard); + if(!vertices) + { + return; + } + + vertices[0] = Vertex(Vector3f(left, top, 0.0f), c, ul, vt); + vertices[1] = Vertex(Vector3f(right, top, 0.0f), c, ur, vt); + vertices[2] = Vertex(Vector3f(left, bottom, 0.0f), c, ul, vb); + vertices[3] = Vertex(Vector3f(left, bottom, 0.0f), c, ul, vb); + vertices[4] = Vertex(Vector3f(right, top, 0.0f), c, ur, vt); + vertices[5] = Vertex(Vector3f(right, bottom, 0.0f), c, ur, vb); + + pTextVertexBuffer->Unmap(vertices); + + Render(fill, pTextVertexBuffer, NULL, Matrix4f(), 0, 6, Prim_Triangles); + } + + + void RenderDevice::RenderLines ( int NumLines, Color c, float *x, float *y, float *z /*= NULL*/ ) + { + OVR_ASSERT ( x != NULL ); + OVR_ASSERT ( y != NULL ); + // z can be NULL for 2D stuff. + + if(!pTextVertexBuffer) + { + pTextVertexBuffer = *CreateBuffer(); + if(!pTextVertexBuffer) + { + return; + } + } + + // Get!! + Fill* fill = CreateSimpleFill(); + + int NumVerts = NumLines * 2; + + pTextVertexBuffer->Data(Buffer_Vertex, NULL, NumVerts * sizeof(Vertex)); + Vertex* vertices = (Vertex*)pTextVertexBuffer->Map(0, NumVerts * sizeof(Vertex), Map_Discard); + if(!vertices) + { + return; + } + + if ( z != NULL ) + { + for ( int VertNum = 0; VertNum < NumVerts; VertNum++ ) + { + vertices[VertNum] = Vertex(Vector3f(x[VertNum], y[VertNum], z[VertNum]), c); + } + } + else + { + for ( int VertNum = 0; VertNum < NumVerts; VertNum++ ) + { + vertices[VertNum] = Vertex(Vector3f(x[VertNum], y[VertNum], 1.0f), c); + } + } + + pTextVertexBuffer->Unmap(vertices); + + Render(fill, pTextVertexBuffer, NULL, Matrix4f(), 0, NumVerts, Prim_Lines); + } + + + + void RenderDevice::RenderImage(float left, + float top, + float right, + float bottom, + ShaderFill* image, + unsigned char alpha) + { + Color c = Color(255, 255, 255, alpha); + Ptr<Model> m = *new Model(Prim_Triangles); + m->AddVertex(left, bottom, 0.0f, c, 0.0f, 0.0f); + m->AddVertex(right, bottom, 0.0f, c, 1.0f, 0.0f); + m->AddVertex(right, top, 0.0f, c, 1.0f, 1.0f); + m->AddVertex(left, top, 0.0f, c, 0.0f, 1.0f); + m->AddTriangle(2,1,0); + m->AddTriangle(0,3,2); + m->Fill = image; + + Render(Matrix4f(), m); + } + + bool RenderDevice::initPostProcessSupport(PostProcessType pptype) + { + if(pptype == PostProcess_None) + { + return true; + } + + + if (PostProcessShaderRequested != PostProcessShaderActive) + { + pPostProcessShader.Clear(); + PostProcessShaderActive = PostProcessShaderRequested; + } + + if (!pPostProcessShader) + { + Shader *vs = NULL; + Shader *ppfs = NULL; + + if (PostProcessShaderActive == PostProcessShader_DistortionAndChromAb) + { + ppfs = LoadBuiltinShader(Shader_Fragment, FShader_PostProcessWithChromAb); + vs = LoadBuiltinShader(Shader_Vertex, VShader_PostProcess); + } + else if (PostProcessShaderActive == PostProcessShader_MeshDistortionAndChromAb) + { + ppfs = LoadBuiltinShader(Shader_Fragment, FShader_PostProcessMeshWithChromAb); + vs = LoadBuiltinShader(Shader_Vertex, VShader_PostProcessMesh); + } + else if (PostProcessShaderActive == PostProcessShader_MeshDistortionAndChromAbTimewarp) + { + ppfs = LoadBuiltinShader(Shader_Fragment, FShader_PostProcessMeshWithChromAbTimewarp); + vs = LoadBuiltinShader(Shader_Vertex, VShader_PostProcessMeshTimewarp); + } + else if (PostProcessShaderActive == PostProcessShader_MeshDistortionAndChromAbPositionalTimewarp) + { + ppfs = LoadBuiltinShader(Shader_Fragment, FShader_PostProcessMeshWithChromAbPositionalTimewarp); + vs = LoadBuiltinShader(Shader_Vertex, VShader_PostProcessMeshPositionalTimewarp); + } + else + { + OVR_ASSERT(false); + } + OVR_ASSERT(ppfs); // Means the shader failed to compile - look in the debug spew. + OVR_ASSERT(vs); + + pPostProcessShader = *CreateShaderSet(); + pPostProcessShader->SetShader(vs); + pPostProcessShader->SetShader(ppfs); + } + + + if(!pFullScreenVertexBuffer) + { + pFullScreenVertexBuffer = *CreateBuffer(); + const Render::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(); + initPostProcessSupport(pptype); + SetViewport(VP); + SetWorldUniforms(Proj); + SetExtraShaders(NULL); + } + + void RenderDevice::FinishScene() + { + SetExtraShaders(0); + SetRenderTarget(0); + } + + + + void RenderDevice::PrecalculatePostProcess(PostProcessType pptype, + const StereoEyeParams &stereoParamsLeft, const StereoEyeParams &stereoParamsRight, + const HmdRenderInfo &hmdRenderInfo ) + { + PostProcessingType = pptype; + + if ( ( pptype == PostProcess_MeshDistortion ) || + ( pptype == PostProcess_MeshDistortionTimewarp ) || + ( pptype == PostProcess_MeshDistortionPositionalTimewarp ) ) + { + for ( int eyeNum = 0; eyeNum < 2; eyeNum++ ) + { + const StereoEyeParams &stereoParams = ( eyeNum == 0 ) ? stereoParamsLeft : stereoParamsRight; + + // Get the mesh data. + int numVerts = 0; + int numTris = 0; + DistortionMeshVertexData *pRawVerts = NULL; + UInt16 *pIndices = NULL; + DistortionMeshCreate ( &pRawVerts, &pIndices, &numVerts, &numTris, stereoParams, hmdRenderInfo ); + int numIndices = numTris * 3; + + // Convert to final vertex data. + DistortionVertex *pVerts = (DistortionVertex*)OVR_ALLOC ( sizeof(DistortionVertex) * numVerts ); + DistortionVertex *pCurVert = pVerts; + DistortionMeshVertexData *pCurRawVert = pRawVerts; + for ( int vertNum = 0; vertNum < numVerts; vertNum++ ) + { + pCurVert->Pos.x = pCurRawVert->ScreenPosNDC.x; + pCurVert->Pos.y = pCurRawVert->ScreenPosNDC.y; + pCurVert->TexR = pCurRawVert->TanEyeAnglesR; + pCurVert->TexG = pCurRawVert->TanEyeAnglesG; + pCurVert->TexB = pCurRawVert->TanEyeAnglesB; + // Convert [0.0f,1.0f] to [0,255] + pCurVert->Col.R = (OVR::UByte)( floorf ( pCurRawVert->Shade * 255.999f ) ); + pCurVert->Col.G = pCurVert->Col.R; + pCurVert->Col.B = pCurVert->Col.R; + pCurVert->Col.A = (OVR::UByte)( floorf ( pCurRawVert->TimewarpLerp * 255.999f ) ); + pCurRawVert++; + pCurVert++; + } -void RenderDevice::FinishScene1() -{ - float r, g, b, a; - DistortionClearColor.GetRGBA(&r, &g, &b, &a); - Clear(r, g, b, a); - - 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]); - } + DistortionMeshNumTris[eyeNum] = numTris; + pDistortionMeshVertexBuffer[eyeNum] = *CreateBuffer(); + pDistortionMeshVertexBuffer[eyeNum]->Data ( Buffer_Vertex, pVerts, sizeof(DistortionVertex) * numVerts ); + pDistortionMeshIndexBuffer[eyeNum] = *CreateBuffer(); + pDistortionMeshIndexBuffer[eyeNum]->Data ( Buffer_Index, pIndices, ( sizeof(UInt16) * numIndices ) ); + + DistortionMeshDestroy ( pRawVerts, pIndices ); + OVR_FREE ( pVerts ); + } + } + else + { + // ...no setup needed for other distortion types. + } + } + + + void RenderDevice::ApplyPostProcess(Matrix4f const &matNowFromWorldStart, Matrix4f const &matNowFromWorldEnd, + Matrix4f const &matRenderFromWorldLeft, Matrix4f const &matRenderFromWorldRight, + StereoEyeParams const &stereoParamsLeft, StereoEyeParams const &stereoParamsRight, + Ptr<Texture> pSourceTextureLeftOrOnly, + Ptr<Texture> pSourceTextureRight, + Ptr<Texture> pSourceTextureLeftOrOnlyDepth, + Ptr<Texture> pSourceTextureRightDepth) + { + SetExtraShaders(0); + + if ( PostProcessingType == PostProcess_MeshDistortion ) + { + Recti vp ( 0, 0, WindowWidth, WindowHeight ); + SetViewport(vp); + float r, g, b, a; + DistortionClearColor.GetRGBA(&r, &g, &b, &a); + Clear(r, g, b, a); + + Matrix4f dummy; + ShaderFill fill(pPostProcessShader); + + fill.SetTexture ( 0, pSourceTextureLeftOrOnly ); + pPostProcessShader->SetUniform2f("EyeToSourceUVScale", stereoParamsLeft.EyeToSourceUV.Scale.x, stereoParamsLeft.EyeToSourceUV.Scale.y ); + pPostProcessShader->SetUniform2f("EyeToSourceUVOffset", stereoParamsLeft.EyeToSourceUV.Offset.x, stereoParamsLeft.EyeToSourceUV.Offset.y ); + Render(&fill, pDistortionMeshVertexBuffer[0], pDistortionMeshIndexBuffer[0], dummy, 0, DistortionMeshNumTris[0] * 3, Prim_Triangles, true); + + if ( pSourceTextureRight != NULL ) + { + fill.SetTexture ( 0, pSourceTextureRight ); + } + pPostProcessShader->SetUniform2f("EyeToSourceUVScale", stereoParamsRight.EyeToSourceUV.Scale.x, stereoParamsRight.EyeToSourceUV.Scale.y ); + pPostProcessShader->SetUniform2f("EyeToSourceUVOffset", stereoParamsRight.EyeToSourceUV.Offset.x, stereoParamsRight.EyeToSourceUV.Offset.y ); + Render(&fill, pDistortionMeshVertexBuffer[1], pDistortionMeshIndexBuffer[1], dummy, 0, DistortionMeshNumTris[1] * 3, Prim_Triangles, true); + } + else if ( PostProcessingType == PostProcess_MeshDistortionTimewarp ) + { + Recti vp ( 0, 0, WindowWidth, WindowHeight ); + SetViewport(vp); + float r, g, b, a; + DistortionClearColor.GetRGBA(&r, &g, &b, &a); + Clear(r, g, b, a); + + ShaderFill fill(pPostProcessShader); + fill.SetTexture ( 0, pSourceTextureLeftOrOnly ); + + for ( int eyeNum = 0; eyeNum < 2; eyeNum++ ) + { + Matrix4f const &matRenderFromWorld = ( eyeNum == 0 ) ? matRenderFromWorldLeft : matRenderFromWorldRight; + const StereoEyeParams &stereoParams = ( eyeNum == 0 ) ? stereoParamsLeft : stereoParamsRight; + + Matrix4f matRenderFromNowStart = TimewarpComputePoseDelta ( matRenderFromWorld, matNowFromWorldStart ); + Matrix4f matRenderFromNowEnd = TimewarpComputePoseDelta ( matRenderFromWorld, matNowFromWorldEnd ); + + pPostProcessShader->SetUniform2f("EyeToSourceUVScale", stereoParams.EyeToSourceUV.Scale.x, stereoParams.EyeToSourceUV.Scale.y ); + pPostProcessShader->SetUniform2f("EyeToSourceUVOffset", stereoParams.EyeToSourceUV.Offset.x, stereoParams.EyeToSourceUV.Offset.y ); + pPostProcessShader->SetUniform3x3f("EyeRotationStart", matRenderFromNowStart); + pPostProcessShader->SetUniform3x3f("EyeRotationEnd", matRenderFromNowEnd); + + Matrix4f dummy; + if ( ( pSourceTextureRight != NULL ) && ( eyeNum == 1 ) ) + { + fill.SetTexture ( 0, pSourceTextureRight ); + } + Render(&fill, pDistortionMeshVertexBuffer[eyeNum], pDistortionMeshIndexBuffer[eyeNum], dummy, 0, DistortionMeshNumTris[eyeNum] * 3, Prim_Triangles, true); + } + } + else if ( PostProcessingType == PostProcess_MeshDistortionPositionalTimewarp ) + { + Recti vp( 0, 0, WindowWidth, WindowHeight ); + SetViewport(vp); + float r, g, b, a; + DistortionClearColor.GetRGBA(&r, &g, &b, &a); + Clear(r, g, b, a); + + ShaderFill fill(pPostProcessShader); + fill.SetTexture ( 0, pSourceTextureLeftOrOnly ); + fill.SetTexture ( 0, pSourceTextureLeftOrOnlyDepth, Shader_Vertex ); + + for ( int eyeNum = 0; eyeNum < 2; eyeNum++ ) + { + Matrix4f const &matRenderFromWorld = ( eyeNum == 0 ) ? matRenderFromWorldLeft : matRenderFromWorldRight; + const StereoEyeParams &stereoParams = ( eyeNum == 0 ) ? stereoParamsLeft : stereoParamsRight; + + Matrix4f matRenderFromNowStart = TimewarpComputePoseDelta ( matRenderFromWorld, matNowFromWorldStart ); + Matrix4f matRenderFromNowEnd = TimewarpComputePoseDelta ( matRenderFromWorld, matNowFromWorldEnd ); + + pPostProcessShader->SetUniform2f("EyeToSourceUVScale", stereoParams.EyeToSourceUV.Scale.x, stereoParams.EyeToSourceUV.Scale.y ); + pPostProcessShader->SetUniform2f("EyeToSourceUVOffset", stereoParams.EyeToSourceUV.Offset.x, stereoParams.EyeToSourceUV.Offset.y ); + + // DepthProjector values can also be calculated as: + // float DepthProjectorX = FarClip / (FarClip - NearClip); + // float DepthProjectorY = (-FarClip * NearClip) / (FarClip - NearClip); + pPostProcessShader->SetUniform2f("DepthProjector", -stereoParams.RenderedProjection.M[2][2], stereoParams.RenderedProjection.M[2][3]); + pPostProcessShader->SetUniform2f("DepthDimSize", (float)pSourceTextureLeftOrOnlyDepth->GetWidth(), (float)pSourceTextureLeftOrOnlyDepth->GetHeight()); + pPostProcessShader->SetUniform4x4f("EyeRotationStart", matRenderFromNowStart); + pPostProcessShader->SetUniform4x4f("EyeRotationEnd", matRenderFromNowEnd); + + + Matrix4f dummy; + if ( ( pSourceTextureRight != NULL ) && ( eyeNum == 1 ) ) + { + OVR_ASSERT(pSourceTextureRightDepth != NULL); + fill.SetTexture ( 0, pSourceTextureRight ); + fill.SetTexture ( 0, pSourceTextureRightDepth, Shader_Vertex ); + } - 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); - RenderWithAlpha(&fill, pFullScreenVertexBuffer, NULL, view, 0, 4, Prim_TriangleStrip); -} - -bool CollisionModel::TestPoint(const Vector3f& p) const -{ - for(unsigned i = 0; i < Planes.GetSize(); i++) - if(Planes[i].TestSide(p) > 0) - { - return 0; - } - - return 1; -} - -bool CollisionModel::TestRay(const Vector3f& origin, const Vector3f& norm, float& len, Planef* ph) const -{ - if(TestPoint(origin)) - { - len = 0; - *ph = Planes[0]; - return true; - } - Vector3f fullMove = origin + norm * len; + Render(&fill, pDistortionMeshVertexBuffer[eyeNum], pDistortionMeshIndexBuffer[eyeNum], dummy, 0, DistortionMeshNumTris[eyeNum] * 3, Prim_Triangles, true); + } + } + else + { + if ( PostProcessingType == PostProcess_PixelDistortion ) + { + float r, g, b, a; + DistortionClearColor.GetRGBA(&r, &g, &b, &a); + Clear(r, g, b, a); + + for ( int eyeNum = 0; eyeNum < 2; eyeNum++ ) + { + const StereoEyeParams &stereoParams = ( eyeNum == 0 ) ? stereoParamsLeft : stereoParamsRight; + + // Always use the half-FB viewport, not the "current scene" VP which may be totally different. + SetViewport(stereoParams.DistortionViewport); + + // TODO: precalc a bunch of things to make the shader faster. + // Note that the shader currently doesn't use Distortion.K[0], it hardwires it to 1.0. + pPostProcessShader->SetUniform4f("HmdWarpParam", + 1.0f, + stereoParams.Distortion.Lens.K[1], + stereoParams.Distortion.Lens.K[2], + stereoParams.Distortion.Lens.K[3]); + // We now only support one distortion type for shaders. + OVR_ASSERT ( stereoParams.Distortion.Lens.Eqn == Distortion_RecipPoly4 ); + + pPostProcessShader->SetUniform3f("DistortionClearColor", + DistortionClearColor.R, + DistortionClearColor.G, + DistortionClearColor.B ); + + // These are stored as deltas off the "main" distortion coefficients, but + // in the shader we use them as absolute values. + pPostProcessShader->SetUniform4f("ChromAbParam", + stereoParams.Distortion.Lens.ChromaticAberration[0] + 1.0f, + stereoParams.Distortion.Lens.ChromaticAberration[1], + stereoParams.Distortion.Lens.ChromaticAberration[2] + 1.0f, + stereoParams.Distortion.Lens.ChromaticAberration[3]); + + // From [-1,1] space (for a single eye), offset by LensCenter, scaled to TanEyeAngle space. + // Done this way so that the shader can do a multiply-add, rather than a subtract-then-multiply. + Vector2f localTanEyeAngleOffset = -stereoParams.Distortion.LensCenter.EntrywiseMultiply(stereoParams.Distortion.TanEyeAngleScale); + pPostProcessShader->SetUniform2f("TanEyeAngleScale", stereoParams.Distortion.TanEyeAngleScale.x, + stereoParams.Distortion.TanEyeAngleScale.y); + pPostProcessShader->SetUniform2f("TanEyeAngleOffset", localTanEyeAngleOffset.x, localTanEyeAngleOffset.y); + + // From TanEyeAngle space to the source the app rendered the standard projective scene to. + pPostProcessShader->SetUniform2f("EyeToSourceUVScale", stereoParams.EyeToSourceUV.Scale.x, stereoParams.EyeToSourceUV.Scale.y ); + pPostProcessShader->SetUniform2f("EyeToSourceUVOffset", stereoParams.EyeToSourceUV.Offset.x, stereoParams.EyeToSourceUV.Offset.y ); + pPostProcessShader->SetUniform2f("EyeToSourceNDCScale", stereoParams.EyeToSourceNDC.Scale.x, stereoParams.EyeToSourceNDC.Scale.y ); + pPostProcessShader->SetUniform2f("EyeToSourceNDCOffset", stereoParams.EyeToSourceNDC.Offset.x, stereoParams.EyeToSourceNDC.Offset.y ); + + // Fade out towards the last bit of the edge, rather than having a sharp edge that attracts the eye. + pPostProcessShader->SetUniform1f("EdgeFadeScale", 1.0f / FadeOutBorderFraction ); + + // Vertex texture coordinates are (0,0) to (1,1). This moves them to (-1,-1),(1,1) + Matrix4f texm(2, 0, 0, -1, + 0, 2, 0, -1, + 0, 0, 0, 0, + 0, 0, 0, 1); + pPostProcessShader->SetUniform4x4f("Texm", texm); + + // Input vertices are (0,0) to (1,1). This moves them to (-1,-1),(1,1), i.e. filling the viewport (which will be set to the correct half of the screen). + Matrix4f view(2, 0, 0, -1, + 0, 2, 0, -1, + 0, 0, 0, 0, + 0, 0, 0, 1); + ShaderFill fill(pPostProcessShader); + + if ( ( pSourceTextureRight != NULL ) && ( eyeNum == 1 ) ) + { + fill.SetTexture ( 0, pSourceTextureRight ); + } + else + { + fill.SetTexture ( 0, pSourceTextureLeftOrOnly ); + } + Render(&fill, pFullScreenVertexBuffer, NULL, view, 0, 4, Prim_TriangleStrip); + } + } + else if ( PostProcessingType == PostProcess_NoDistortion ) + { + // Just splat the thing on the framebuffer with no distortion. + Clear ( 0.0f, 0.4f, 0.0f, 1.0f, 1.0f ); + // 1:1 mapping to screen pixels. + Matrix4f ortho; + ortho.SetIdentity(); + ortho.M[0][0] = 1.0f; + ortho.M[0][3] = 0.0f; + ortho.M[1][1] = -1.0f; + ortho.M[1][3] = 0.0f; + ortho.M[2][2] = 0; + SetProjection(ortho); + int rtWidth = pSourceTextureLeftOrOnly->GetWidth(); + int rtHeight = pSourceTextureLeftOrOnly->GetHeight(); + + for ( int eyeNum = 0; eyeNum < 2; eyeNum++ ) + { + const StereoEyeParams &stereoParams = ( eyeNum == 0 ) ? stereoParamsLeft : stereoParamsRight; + SetViewport ( stereoParams.DistortionViewport ); - int crossing = -1; - float cdot1 = 0, cdot2 = 0; + Ptr<Texture> pTex; + if ( ( pSourceTextureRight != NULL ) && ( eyeNum == 1 ) ) + { + pTex = pSourceTextureRight; + } + else + { + pTex = pSourceTextureLeftOrOnly; + } - for(unsigned i = 0; i < Planes.GetSize(); ++i) - { - float dot2 = Planes[i].TestSide(fullMove); - if(dot2 > 0) - { - return false; - } - float dot1 = Planes[i].TestSide(origin); - if(dot1 > 0) - { - if(dot2 <= 0) - { - //assert(crossing==-1); - if(crossing == -1) - { - crossing = i; - cdot2 = dot2; - cdot1 = dot1; + float ul = (float)( stereoParams.RenderedViewport.x ) / (float)rtWidth; + float ur = (float)( stereoParams.RenderedViewport.x + stereoParams.RenderedViewport.w ) / (float)rtWidth; + float vt = (float)( stereoParams.RenderedViewport.y ) / (float)rtHeight; + float vb = (float)( stereoParams.RenderedViewport.y + stereoParams.RenderedViewport.h ) / (float)rtHeight; + FillTexturedRect ( + -1.0f, -1.0f, 1.0f, 1.0f, + ul, vt, ur, vb, + Color(255,255,255,255), pTex ); } - else + } + else + { + OVR_ASSERT ( !"Unknown distortion type" ); + } + } + } + + bool CollisionModel::TestPoint(const Vector3f& p) const + { + for(unsigned i = 0; i < Planes.GetSize(); i++) + if(Planes[i].TestSide(p) > 0) + { + return 0; + } + + return 1; + } + + bool CollisionModel::TestRay(const Vector3f& origin, const Vector3f& norm, float& len, Planef* ph) const + { + if(TestPoint(origin)) + { + len = 0; + *ph = Planes[0]; + return true; + } + Vector3f fullMove = origin + norm * len; + + int crossing = -1; + float cdot1 = 0, cdot2 = 0; + + for(unsigned i = 0; i < Planes.GetSize(); ++i) + { + float dot2 = Planes[i].TestSide(fullMove); + if(dot2 > 0) + { + return false; + } + float dot1 = Planes[i].TestSide(origin); + if(dot1 > 0) + { + if(dot2 <= 0) { - if(dot2 > cdot2) + //OVR_ASSERT(crossing==-1); + if(crossing == -1) { crossing = i; cdot2 = dot2; cdot1 = dot1; } + else + { + if(dot2 > cdot2) + { + crossing = i; + cdot2 = dot2; + cdot1 = dot1; + } + } } - } - } - } - - if(crossing < 0) - { - return false; - } - - assert(TestPoint(origin + norm * len)); - - len = len * cdot1 / (cdot1 - cdot2) - 0.05f; - if(len < 0) - { - len = 0; - } - float tp = Planes[crossing].TestSide(origin + norm * len); - OVR_ASSERT(fabsf(tp) < 0.05f + Mathf::Tolerance); - OVR_UNUSED(tp); - - if(ph) - { - *ph = Planes[crossing]; - } - return true; -} - -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; - } - } -} - -int GetTextureSize(int format, int w, int h) -{ - switch (format & Texture_TypeMask) - { - case Texture_R: return w*h; - case Texture_RGBA: return w*h*4; - case Texture_DXT1: { - int bw = (w+3)/4, bh = (h+3)/4; - return bw * bh * 8; - } - case Texture_DXT3: - case Texture_DXT5: { - int bw = (w+3)/4, bh = (h+3)/4; - return bw * bh * 16; - } - - default: - OVR_ASSERT(0); - } - return 0; -} + } + } + + if(crossing < 0) + { + return false; + } + + OVR_ASSERT(TestPoint(origin + norm * len)); + + len = len * cdot1 / (cdot1 - cdot2) - 0.05f; + if(len < 0) + { + len = 0; + } + float tp = Planes[crossing].TestSide(origin + norm * len); + OVR_ASSERT(fabsf(tp) < 0.05f + Mathf::Tolerance); + OVR_UNUSED(tp); + + if(ph) + { + *ph = Planes[crossing]; + } + return true; + } + + 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; + } + } + } + + int GetTextureSize(int format, int w, int h) + { + switch (format & Texture_TypeMask) + { + case Texture_R: return w*h; + case Texture_RGBA: return w*h*4; + case Texture_DXT1: { + int bw = (w+3)/4, bh = (h+3)/4; + return bw * bh * 8; + } + case Texture_DXT3: + case Texture_DXT5: { + int bw = (w+3)/4, bh = (h+3)/4; + return bw * bh * 16; + } + + default: + OVR_ASSERT(0); + } + return 0; + } }} diff --git a/Samples/CommonSrc/Render/Render_Device.h b/Samples/CommonSrc/Render/Render_Device.h index 028f282..f8a6dff 100644 --- a/Samples/CommonSrc/Render/Render_Device.h +++ b/Samples/CommonSrc/Render/Render_Device.h @@ -28,24 +28,31 @@ limitations under the License. #include "Kernel/OVR_RefCount.h" #include "Kernel/OVR_String.h" #include "Kernel/OVR_File.h" +#include "OVR_CAPI.h" -#include "Util/Util_Render_Stereo.h" +#include "OVR_Stereo.h" namespace OVR { namespace Render { -using namespace OVR::Util::Render; - class RenderDevice; struct Font; //----------------------------------------------------------------------------------- +enum ShaderStage +{ + Shader_Vertex = 0, + Shader_Geometry = 1, + Shader_Fragment = 2, + Shader_Pixel = 2, + Shader_Count = 3, +}; + enum PrimitiveType { Prim_Triangles, Prim_Lines, Prim_TriangleStrip, - Prim_Points, Prim_Unknown, Prim_Count }; @@ -64,36 +71,32 @@ public: virtual void Set(PrimitiveType prim = Prim_Unknown) const = 0; virtual void Unset() const {} - virtual void SetTexture(int i, class Texture* tex) { OVR_UNUSED2(i,tex); } - virtual Texture* GetTexture(int i) { OVR_UNUSED(i); return 0; } -}; - -enum ShaderStage -{ - Shader_Vertex = 0, - Shader_Geometry = 1, - Shader_Fragment = 2, - Shader_Pixel = 2, - Shader_Count = 3, + virtual void SetTexture(int i, class Texture* tex, ShaderStage stage = Shader_Pixel) { OVR_UNUSED3(i,tex,stage); } + virtual Texture* GetTexture(int i, ShaderStage stage = Shader_Pixel) { OVR_UNUSED2(i,stage); return 0; } }; enum BuiltinShaders { - VShader_MV = 0, - VShader_MVP = 1, - VShader_PostProcess = 2, - VShader_Count = 3, - - FShader_Solid = 0, - FShader_Gouraud = 1, - FShader_Texture = 2, - FShader_AlphaTexture = 3, - FShader_PostProcess = 4, - FShader_PostProcessWithChromAb = 5, - FShader_LitGouraud = 6, - FShader_LitTexture = 7, - FShader_MultiTexture = 8, - FShader_Count = 9, + VShader_MV = 0, + VShader_MVP , + VShader_PostProcess , + VShader_PostProcessMesh , + VShader_PostProcessMeshTimewarp , + VShader_PostProcessMeshPositionalTimewarp , + VShader_Count , + + FShader_Solid = 0, + FShader_Gouraud , + FShader_Texture , + FShader_AlphaTexture , + FShader_PostProcessWithChromAb , + FShader_LitGouraud , + FShader_LitTexture , + FShader_MultiTexture , + FShader_PostProcessMeshWithChromAb , + FShader_PostProcessMeshWithChromAbTimewarp , + FShader_PostProcessMeshWithChromAbPositionalTimewarp , + FShader_Count , }; @@ -119,6 +122,8 @@ enum TextureFormat { Texture_RGBA = 0x100, Texture_R = 0x200, + Texture_A = 0x400, + Texture_BGRA = 0x800, Texture_DXT1 = 0x1100, Texture_DXT3 = 0x1200, Texture_DXT5 = 0x1300, @@ -126,8 +131,9 @@ enum TextureFormat Texture_TypeMask = 0xff00, Texture_Compressed = 0x1000, Texture_SamplesMask = 0x00ff, - Texture_RenderTarget = 0x10000, - Texture_GenMipmaps = 0x20000, + Texture_RenderTarget = 0x10000, + Texture_SampleDepth = 0x20000, + Texture_GenMipmaps = 0x40000, }; enum SampleMode @@ -145,16 +151,14 @@ enum SampleMode 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 +struct Color4f { - float w; + float r, g, b, a; - 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) {} + Color4f() : r(0), g(0), b(0), a(1) {} + Color4f(const Vector3f& v) : r(v.x), g(v.y), b(v.z), a(1) {} + Color4f(float ir, float ig, float ib, float ia) : r(ir), g(ig), b(ib), a(ia) {} }; @@ -231,24 +235,34 @@ public: 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) + bool SetUniform4fv(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) + bool SetUniform4fvArray(const char* name, int n, const Color4f* v) { - return SetUniform(name, 4*n, &v[0].x); + return SetUniform(name, 4*n, &v[0].r); } virtual bool SetUniform4x4f(const char* name, const Matrix4f& m) { return SetUniform(name, 16, &m.M[0][0]); } + virtual bool SetUniform3x3f(const char* name, const Matrix4f& m) + { + // float3x3 is actually stored the same way as float4x3, with the last items ignored by the code. + return SetUniform(name, 12, &m.M[0][0]); + } }; class ShaderSetMatrixTranspose : public ShaderSet @@ -265,6 +279,7 @@ class ShaderFill : public Fill { Ptr<ShaderSet> Shaders; Ptr<Texture> Textures[8]; + Ptr<Texture> VtxTextures[8]; public: ShaderFill(ShaderSet* sh) : Shaders(sh) { } @@ -272,8 +287,28 @@ public: void Set(PrimitiveType prim) const; ShaderSet* GetShaders() { return Shaders; } - virtual void SetTexture(int i, class Texture* tex) { if (i < 8) Textures[i] = tex; } - virtual Texture* GetTexture(int i) { if (i < 8) return Textures[i]; else return 0; } + virtual void SetTexture(int i, class Texture* tex, ShaderStage stage = Shader_Pixel) + { + if (i < 8) + { + if(stage == Shader_Pixel) Textures[i] = tex; + else if(stage == Shader_Vertex) VtxTextures[i] = tex; + else OVR_ASSERT(false); + } + } + virtual Texture* GetTexture(int i, ShaderStage stage = Shader_Pixel) + { + if (i < 8) + { + if(stage == Shader_Pixel) return Textures[i]; + else if(stage == Shader_Vertex) return VtxTextures[i]; + else OVR_ASSERT(false); return 0; + } + else + { + return 0; + } + } }; /* Buffer for vertex or index data. Some renderers require separate buffers, so that @@ -313,6 +348,10 @@ public: virtual void SetSampleMode(int sm) = 0; virtual void Set(int slot, ShaderStage stage = Shader_Fragment) const = 0; + + virtual ovrTexture Get_ovrTexture() = 0; + + virtual void* GetInternalImplementation() { return NULL; }; }; @@ -379,7 +418,7 @@ public: { if (!MatCurrent) { - Mat = Rot; + Mat = Matrix4f(Rot); Mat = Matrix4f::Translation(Pos) * Mat; MatCurrent = 1; } @@ -413,18 +452,27 @@ struct Vertex } }; +struct DistortionVertex +{ + Vector2f Pos; + Vector2f TexR; + Vector2f TexG; + Vector2f TexB; + Color Col; +}; + // this is stored in a uniform buffer, don't change it without fixing all renderers struct LightingParams { - Vector4f Ambient; - Vector4f LightPos[8]; - Vector4f LightColor[8]; + Color4f Ambient; + Color4f LightPos[8]; // Not actually colours, but we need the extra element of padding. + Color4f LightColor[8]; float LightCount; int Version; LightingParams() : LightCount(0), Version(0) {} - void Update(const Matrix4f& view, const Vector4f* SceneLightPos); + void Update(const Matrix4f& view, const Vector3f* SceneLightPos); void Set(ShaderSet* s) const; }; @@ -472,10 +520,12 @@ public: UInt16 AddVertex(const Vertex& v) { - assert(!VertexBuffer && !IndexBuffer); - UInt16 index = (UInt16)Vertices.GetSize(); - Vertices.PushBack(v); - return index; + OVR_ASSERT(!VertexBuffer && !IndexBuffer); + UPInt size = Vertices.GetSize(); + OVR_ASSERT(size <= USHRT_MAX); // We only use a short to store vert indices. + UInt16 index = (UInt16) size; + Vertices.PushBack(v); + return index; } UInt16 AddVertex(const Vector3f& v, const Color& c, float u_ = 0, float v_ = 0) { @@ -528,6 +578,9 @@ public: float z1, float z2, Color zcolor); + // Adds box at specified location to current vertices. + void AddBox(Color c, Vector3f origin, Vector3f size); + // Uses texture coordinates for exactly covering each surface once. static Model* CreateBox(Color c, Vector3f origin, Vector3f size); @@ -575,18 +628,18 @@ class Scene { public: Container World; - Vector4f LightPos[8]; + Vector3f LightPos[8]; LightingParams Lighting; Array<Ptr<Model> > Models; public: void Render(RenderDevice* ren, const Matrix4f& view); - void SetAmbient(Vector4f color) + void SetAmbient(Color4f color) { Lighting.Ambient = color; } - void AddLight(Vector3f pos, Vector4f color) + void AddLight(Vector3f pos, Color4f color) { int n = (int)Lighting.LightCount; OVR_ASSERT(n < 8); @@ -599,7 +652,7 @@ public: { World.Clear(); Models.Clear(); - Lighting.Ambient = Vector4f(0.0f, 0.0f, 0.0f, 0.0f); + Lighting.Ambient = Color4f(0.0f, 0.0f, 0.0f, 0.0f); Lighting.LightCount = 0; } @@ -624,11 +677,15 @@ enum RenderCaps }; // Post-processing type to apply to scene after rendering. PostProcess_Distortion -// applied distortion as described by DistortionConfig. +// applied distortion as described by DistortionRenderDesc. enum PostProcessType { PostProcess_None, - PostProcess_Distortion + PostProcess_PixelDistortion, + PostProcess_MeshDistortion, + PostProcess_MeshDistortionTimewarp, + PostProcess_MeshDistortionPositionalTimewarp, + PostProcess_NoDistortion, }; enum DisplayMode @@ -688,29 +745,27 @@ class RenderDevice : public RefCountBase<RenderDevice> protected: int WindowWidth, WindowHeight; RendererParams Params; - Viewport VP; + Recti VP; Matrix4f Proj; Ptr<Buffer> pTextVertexBuffer; - // For rendering with lens warping - PostProcessType CurPostProcess; - Ptr<Texture> pSceneColorTex; - int SceneColorTexW; - int SceneColorTexH; + PostProcessType PostProcessingType; + Ptr<ShaderSet> pPostProcessShader; Ptr<Buffer> pFullScreenVertexBuffer; - float SceneRenderScale; - DistortionConfig Distortion; Color DistortionClearColor; - UPInt TotalTextureMemoryUsage; + UPInt TotalTextureMemoryUsage; + float FadeOutBorderFraction; + + int DistortionMeshNumTris[2]; + Ptr<Buffer> pDistortionMeshVertexBuffer[2]; + Ptr<Buffer> pDistortionMeshIndexBuffer[2]; // For lighting on platforms with uniform buffers Ptr<Buffer> LightingBuffer; - void FinishScene1(); - public: enum CompareFunc { @@ -728,41 +783,43 @@ public: virtual void Init() {} - virtual void Shutdown() {} + virtual void Shutdown(); virtual bool SetParams(const RendererParams&) { return 0; } const RendererParams& GetParams() const { return Params; } - + // Returns details needed by CAPI distortion rendering. + virtual ovrRenderAPIConfig Get_ovrRenderAPIConfig() const = 0; + // 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); + SetViewport(params.RenderedViewport); + SetProjection(params.RenderedProjection); } + void ApplyStereoParams(const Recti& vp, const Matrix4f& projection) + { + SetViewport(vp); + SetProjection(projection); + } // Apply "orthographic" stereo parameters used for rendering 2D HUD overlays. - void ApplyStereoParams2D(const StereoEyeParams& params) + void ApplyStereoParams2D(StereoEyeParams const ¶ms, Matrix4f const &ortho) { - SetViewport(params.VP); - SetProjection(params.OrthoProjection); - if (params.pDistortion) - SetDistortionConfig(*params.pDistortion, params.Eye); + SetViewport(params.RenderedViewport); + SetProjection(ortho); } + - virtual void SetViewport(const Viewport& vp); - void SetViewport(int x, int y, int w, int h) { SetViewport(Viewport(x,y,w,h)); } - //virtual void SetScissor(int x, int y, int w, int h) = 0; - // Set viewport ignoring any adjustments used for the stereo mode. - virtual void SetRealViewport(const Viewport& vp) { SetMultipleViewports(1, &vp); } - virtual void SetMultipleViewports(int n, const Viewport* vps) { OVR_UNUSED2(n, vps); } + virtual void SetViewport(const Recti& vp) = 0; + void SetViewport(int x, int y, int w, int h) { SetViewport(Recti(x,y,w,h)); } - virtual void Clear(float r = 0, float g = 0, float b = 0, float a = 1, float depth = 1) = 0; + virtual void Clear(float r = 0, float g = 0, float b = 0, float a = 1, + float depth = 1, + bool clearColor = true, bool clearDepth = true) = 0; virtual void Rect(float left, float top, float right, float bottom) = 0; inline void Clear(const Color &c, float depth = 1) @@ -773,9 +830,9 @@ public: } virtual bool IsFullscreen() const { return Params.Fullscreen != Display_Window; } - virtual void Present() = 0; + virtual void Present ( bool withVsync ) = 0; // Waits for rendering to complete; important for reducing latency. - virtual void ForceFlushGPU() { } + virtual void WaitUntilGpuIdle() { } // Resources virtual Buffer* CreateBuffer() { return NULL; } @@ -789,12 +846,24 @@ public: // 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); //StereoDisplay disp = Stereo_Center); - // Postprocess the scene and return to the screen render target. + // Begin drawing the primary scene, starting up whatever post-processing may be needed. + virtual void BeginScene(PostProcessType pp = PostProcess_None); + // Call when any of the stereo options change, so precalculation can happen. + virtual void PrecalculatePostProcess(PostProcessType pptype, + const StereoEyeParams &stereoParamsLeft, const StereoEyeParams &stereoParamsRight, + const HmdRenderInfo &hmdRenderInfo ); + // Perform postprocessing + virtual void ApplyPostProcess(Matrix4f const &matNowFromWorldStart, Matrix4f const &matNowFromWorldEnd, + Matrix4f const &matRenderFromWorldLeft, Matrix4f const &matRenderFromWorldRight, + StereoEyeParams const &stereoParamsLeft, StereoEyeParams const &stereoParamsRight, + Ptr<Texture> pSourceTextureLeftOrOnly, + Ptr<Texture> pSourceTextureRight, + Ptr<Texture> pSourceTextureLeftOrOnlyDepth, + Ptr<Texture> pSourceTextureRightDepth); + // Finish scene. virtual void FinishScene(); // Texture must have been created with Texture_RenderTarget. Use NULL for the default render target. @@ -818,31 +887,25 @@ public: virtual void Render(const Matrix4f& matrix, Model* model) = 0; // offset is in bytes; indices can be null. virtual void Render(const Fill* fill, Buffer* vertices, Buffer* indices, - const Matrix4f& matrix, int offset, int count, PrimitiveType prim = Prim_Triangles) = 0; + const Matrix4f& matrix, int offset, int count, PrimitiveType prim = Prim_Triangles, bool useDistortionVertex = false) = 0; virtual void RenderWithAlpha(const Fill* fill, Render::Buffer* vertices, Render::Buffer* indices, const Matrix4f& matrix, int offset, int count, PrimitiveType prim = Prim_Triangles) = 0; // Returns width of text in same units as drawing. If strsize is not null, stores width and height. - float MeasureText(const Font* font, const char* str, float size, float* strsize = NULL); + // Can optionally return char-range selection rectangle. + float MeasureText(const Font* font, const char* str, float size, float strsize[2] = NULL, + const UPInt charRange[2] = 0, Vector2f charRangeRect[2] = 0); virtual void RenderText(const Font* font, const char* str, float x, float y, float size, Color c); virtual void FillRect(float left, float top, float right, float bottom, Color c); + virtual void RenderLines ( int NumLines, Color c, float *x, float *y, float *z = NULL ); + virtual void FillTexturedRect(float left, float top, float right, float bottom, float ul, float vt, float ur, float vb, Color c, Ptr<Texture> tex); virtual void FillGradientRect(float left, float top, float right, float bottom, Color col_top, Color col_btm); virtual void RenderImage(float left, float top, float right, float bottom, ShaderFill* image, unsigned char alpha=255); virtual Fill *CreateSimpleFill(int flags = Fill::F_Solid) = 0; Fill * CreateTextureFill(Texture* tex, bool useAlpha = false); - // 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; - } - // Sets the color that is applied around distortion. void SetDistortionClearColor(Color clearColor) { @@ -851,7 +914,12 @@ public: // Don't call these directly, use App/Platform instead virtual bool SetFullscreen(DisplayMode fullscreen) { OVR_UNUSED(fullscreen); return false; } - virtual void SetWindowSize(int w, int h) { WindowWidth = w; WindowHeight = h; } + virtual void SetWindowSize(int w, int h) + { + WindowWidth = w; + WindowHeight = h; + VP = Recti( 0, 0, WindowWidth, WindowHeight ); + } UPInt GetTotalTextureMemoryUsage() const { @@ -860,8 +928,10 @@ public: enum PostProcessShader { - PostProcessShader_Distortion = 0, - PostProcessShader_DistortionAndChromAb = 1, + PostProcessShader_DistortionAndChromAb = 0, + PostProcessShader_MeshDistortionAndChromAb, + PostProcessShader_MeshDistortionAndChromAbTimewarp, + PostProcessShader_MeshDistortionAndChromAbPositionalTimewarp, PostProcessShader_Count }; @@ -875,6 +945,16 @@ public: PostProcessShaderRequested = newShader; } + void SetFadeOutBorderFraction ( float newVal ) + { + FadeOutBorderFraction = newVal; + } + + // GPU Profiling + // using (void) to avoid "unused param" warnings + virtual void BeginGpuEvent(const char* markerText, UInt32 markerColor) { (void)markerText; (void)markerColor; } + virtual void EndGpuEvent() { } + protected: // Stereo & post-processing virtual bool initPostProcessSupport(PostProcessType pptype); @@ -887,6 +967,34 @@ private: PostProcessShader PostProcessShaderActive; }; +//----------------------------------------------------------------------------------- +// GPU profile marker helper to encapsulate a given scope block +class AutoGpuProf +{ +public: + AutoGpuProf(RenderDevice* device, const char* markerText, UInt32 color) + : mDevice(device) + { device->BeginGpuEvent(markerText, color); } + + // Generates random color if one is not provided + AutoGpuProf(RenderDevice* device, const char* markerText) + : mDevice(device) + { + UInt32 color = ((rand() & 0xFF) << 24) + + ((rand() & 0xFF) << 16) + + ((rand() & 0xFF) << 8) + + (rand() & 0xFF); + device->BeginGpuEvent(markerText, color); + } + + ~AutoGpuProf() { mDevice->EndGpuEvent(); } + +private: + RenderDevice* mDevice; + AutoGpuProf() { }; +}; +//----------------------------------------------------------------------------------- + int GetNumMipLevels(int w, int h); int GetTextureSize(int format, int w, int h); diff --git a/Samples/CommonSrc/Render/Render_GL_Device.cpp b/Samples/CommonSrc/Render/Render_GL_Device.cpp index aaf1f0e..4b3ddec 100644 --- a/Samples/CommonSrc/Render/Render_GL_Device.cpp +++ b/Samples/CommonSrc/Render/Render_GL_Device.cpp @@ -23,9 +23,122 @@ limitations under the License. #include "../Render/Render_GL_Device.h" #include "Kernel/OVR_Log.h" +#include "OVR_CAPI_GL.h" namespace OVR { namespace Render { namespace GL { +// GL Hooks for PC. +#if defined(OVR_OS_WIN32) + +PFNWGLGETSWAPINTERVALEXTPROC wglGetSwapIntervalEXT; +PFNWGLSWAPINTERVALEXTPROC wglSwapIntervalEXT; +PFNGLGENFRAMEBUFFERSEXTPROC glGenFramebuffersEXT; +PFNGLDELETEFRAMEBUFFERSEXTPROC glDeleteFramebuffersEXT; +PFNGLDELETESHADERPROC glDeleteShader; +PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC glCheckFramebufferStatusEXT; +PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC glFramebufferRenderbufferEXT; +PFNGLFRAMEBUFFERTEXTURE2DEXTPROC glFramebufferTexture2DEXT; +PFNGLBINDFRAMEBUFFEREXTPROC glBindFramebufferEXT; +PFNGLACTIVETEXTUREPROC glActiveTexture; +PFNGLDISABLEVERTEXATTRIBARRAYPROC glDisableVertexAttribArray; +PFNGLVERTEXATTRIBPOINTERPROC glVertexAttribPointer; +PFNGLENABLEVERTEXATTRIBARRAYPROC glEnableVertexAttribArray; +PFNGLBINDBUFFERPROC glBindBuffer; +PFNGLUNIFORMMATRIX3FVPROC glUniformMatrix3fv; +PFNGLUNIFORMMATRIX4FVPROC glUniformMatrix4fv; +PFNGLDELETEBUFFERSPROC glDeleteBuffers; +PFNGLBUFFERDATAPROC glBufferData; +PFNGLGENBUFFERSPROC glGenBuffers; +PFNGLMAPBUFFERPROC glMapBuffer; +PFNGLUNMAPBUFFERPROC glUnmapBuffer; +PFNGLGETSHADERINFOLOGPROC glGetShaderInfoLog; +PFNGLGETSHADERIVPROC glGetShaderiv; +PFNGLCOMPILESHADERPROC glCompileShader; +PFNGLSHADERSOURCEPROC glShaderSource; +PFNGLCREATESHADERPROC glCreateShader; +PFNGLCREATEPROGRAMPROC glCreateProgram; +PFNGLATTACHSHADERPROC glAttachShader; +PFNGLDETACHSHADERPROC glDetachShader; +PFNGLDELETEPROGRAMPROC glDeleteProgram; +PFNGLUNIFORM1IPROC glUniform1i; +PFNGLGETUNIFORMLOCATIONPROC glGetUniformLocation; +PFNGLGETACTIVEUNIFORMPROC glGetActiveUniform; +PFNGLUSEPROGRAMPROC glUseProgram; +PFNGLGETPROGRAMINFOLOGPROC glGetProgramInfoLog; +PFNGLGETPROGRAMIVPROC glGetProgramiv; +PFNGLLINKPROGRAMPROC glLinkProgram; +PFNGLBINDATTRIBLOCATIONPROC glBindAttribLocation; +PFNGLUNIFORM4FVPROC glUniform4fv; +PFNGLUNIFORM3FVPROC glUniform3fv; +PFNGLUNIFORM2FVPROC glUniform2fv; +PFNGLUNIFORM1FVPROC glUniform1fv; +PFNGLCOMPRESSEDTEXIMAGE2DPROC glCompressedTexImage2D; +PFNGLRENDERBUFFERSTORAGEEXTPROC glRenderbufferStorageEXT; +PFNGLBINDRENDERBUFFEREXTPROC glBindRenderbufferEXT; +PFNGLGENRENDERBUFFERSEXTPROC glGenRenderbuffersEXT; +PFNGLDELETERENDERBUFFERSEXTPROC glDeleteRenderbuffersEXT; + +PFNGLGENVERTEXARRAYSPROC glGenVertexArrays; + +void InitGLExtensions() +{ + if (glGenFramebuffersEXT) + return; + + + wglGetSwapIntervalEXT = (PFNWGLGETSWAPINTERVALEXTPROC) wglGetProcAddress("wglGetSwapIntervalEXT"); + wglSwapIntervalEXT = (PFNWGLSWAPINTERVALEXTPROC) wglGetProcAddress("wglSwapIntervalEXT"); + glGenFramebuffersEXT = (PFNGLGENFRAMEBUFFERSEXTPROC) wglGetProcAddress("glGenFramebuffersEXT"); + glDeleteFramebuffersEXT = (PFNGLDELETEFRAMEBUFFERSEXTPROC) wglGetProcAddress("glDeleteFramebuffersEXT"); + glDeleteShader = (PFNGLDELETESHADERPROC) wglGetProcAddress("glDeleteShader"); + glCheckFramebufferStatusEXT = (PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC) wglGetProcAddress("glCheckFramebufferStatusEXT"); + glFramebufferRenderbufferEXT = (PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC) wglGetProcAddress("glFramebufferRenderbufferEXT"); + glFramebufferTexture2DEXT = (PFNGLFRAMEBUFFERTEXTURE2DEXTPROC) wglGetProcAddress("glFramebufferTexture2DEXT"); + glBindFramebufferEXT = (PFNGLBINDFRAMEBUFFEREXTPROC) wglGetProcAddress("glBindFramebufferEXT"); + glActiveTexture = (PFNGLACTIVETEXTUREPROC) wglGetProcAddress("glActiveTexture"); + glDisableVertexAttribArray = (PFNGLDISABLEVERTEXATTRIBARRAYPROC) wglGetProcAddress("glDisableVertexAttribArray"); + glVertexAttribPointer = (PFNGLVERTEXATTRIBPOINTERPROC) wglGetProcAddress("glVertexAttribPointer"); + glEnableVertexAttribArray = (PFNGLENABLEVERTEXATTRIBARRAYPROC) wglGetProcAddress("glEnableVertexAttribArray"); + glBindBuffer = (PFNGLBINDBUFFERPROC) wglGetProcAddress("glBindBuffer"); + glUniformMatrix3fv = (PFNGLUNIFORMMATRIX3FVPROC) wglGetProcAddress("glUniformMatrix3fv"); + glUniformMatrix4fv = (PFNGLUNIFORMMATRIX4FVPROC) wglGetProcAddress("glUniformMatrix4fv"); + glDeleteBuffers = (PFNGLDELETEBUFFERSPROC) wglGetProcAddress("glDeleteBuffers"); + glBufferData = (PFNGLBUFFERDATAPROC) wglGetProcAddress("glBufferData"); + glGenBuffers = (PFNGLGENBUFFERSPROC) wglGetProcAddress("glGenBuffers"); + glMapBuffer = (PFNGLMAPBUFFERPROC) wglGetProcAddress("glMapBuffer"); + glUnmapBuffer = (PFNGLUNMAPBUFFERPROC) wglGetProcAddress("glUnmapBuffer"); + glGetShaderInfoLog = (PFNGLGETSHADERINFOLOGPROC) wglGetProcAddress("glGetShaderInfoLog"); + glGetShaderiv = (PFNGLGETSHADERIVPROC) wglGetProcAddress("glGetShaderiv"); + glCompileShader = (PFNGLCOMPILESHADERPROC) wglGetProcAddress("glCompileShader"); + glShaderSource = (PFNGLSHADERSOURCEPROC) wglGetProcAddress("glShaderSource"); + glCreateShader = (PFNGLCREATESHADERPROC) wglGetProcAddress("glCreateShader"); + glCreateProgram = (PFNGLCREATEPROGRAMPROC) wglGetProcAddress("glCreateProgram"); + glAttachShader = (PFNGLATTACHSHADERPROC) wglGetProcAddress("glAttachShader"); + glDetachShader = (PFNGLDETACHSHADERPROC) wglGetProcAddress("glDetachShader"); + glDeleteProgram = (PFNGLDELETEPROGRAMPROC) wglGetProcAddress("glDeleteProgram"); + glUniform1i = (PFNGLUNIFORM1IPROC) wglGetProcAddress("glUniform1i"); + glGetUniformLocation = (PFNGLGETUNIFORMLOCATIONPROC) wglGetProcAddress("glGetUniformLocation"); + glGetActiveUniform = (PFNGLGETACTIVEUNIFORMPROC) wglGetProcAddress("glGetActiveUniform"); + glUseProgram = (PFNGLUSEPROGRAMPROC) wglGetProcAddress("glUseProgram"); + glGetProgramInfoLog = (PFNGLGETPROGRAMINFOLOGPROC) wglGetProcAddress("glGetProgramInfoLog"); + glGetProgramiv = (PFNGLGETPROGRAMIVPROC) wglGetProcAddress("glGetProgramiv"); + glLinkProgram = (PFNGLLINKPROGRAMPROC) wglGetProcAddress("glLinkProgram"); + glBindAttribLocation = (PFNGLBINDATTRIBLOCATIONPROC) wglGetProcAddress("glBindAttribLocation"); + glUniform4fv = (PFNGLUNIFORM4FVPROC) wglGetProcAddress("glUniform4fv"); + glUniform3fv = (PFNGLUNIFORM3FVPROC) wglGetProcAddress("glUniform3fv"); + glUniform2fv = (PFNGLUNIFORM2FVPROC) wglGetProcAddress("glUniform2fv"); + glUniform1fv = (PFNGLUNIFORM1FVPROC) wglGetProcAddress("glUniform1fv"); + glCompressedTexImage2D = (PFNGLCOMPRESSEDTEXIMAGE2DPROC) wglGetProcAddress("glCompressedTexImage2D"); + glRenderbufferStorageEXT = (PFNGLRENDERBUFFERSTORAGEEXTPROC) wglGetProcAddress("glRenderbufferStorageEXT"); + glBindRenderbufferEXT = (PFNGLBINDRENDERBUFFEREXTPROC) wglGetProcAddress("glBindRenderbufferEXT"); + glGenRenderbuffersEXT = (PFNGLGENRENDERBUFFERSEXTPROC) wglGetProcAddress("glGenRenderbuffersEXT"); + glDeleteRenderbuffersEXT = (PFNGLDELETERENDERBUFFERSEXTPROC) wglGetProcAddress("glDeleteRenderbuffersEXT"); + + + glGenVertexArrays = (PFNGLGENVERTEXARRAYSPROC) wglGetProcAddress("glGenVertexArrays"); +} + +#endif static const char* StdVertexShaderSrc = @@ -157,6 +270,53 @@ static const char* MultiTextureFragShaderSrc = " gl_FragColor = color2;\n" "}\n"; +static const char* PostProcessMeshFragShaderSrc = + "uniform sampler2D Texture;\n" + "varying vec4 oColor;\n" + "varying vec2 oTexCoord0;\n" + "varying vec2 oTexCoord1;\n" + "varying vec2 oTexCoord2;\n" + "\n" + "void main()\n" + "{\n" + " float ResultR = texture2D(Texture, oTexCoord0).r;\n" + " float ResultG = texture2D(Texture, oTexCoord1).g;\n" + " float ResultB = texture2D(Texture, oTexCoord2).b;\n" + " gl_FragColor = vec4(ResultR * oColor.r, ResultG * oColor.g, ResultB * oColor.b, 1.0);\n" + "}\n"; + +static const char* PostProcessMeshTimewarpFragShaderSrc = + "uniform sampler2D Texture;\n" + "varying vec4 oColor;\n" + "varying vec2 oTexCoord0;\n" + "varying vec2 oTexCoord1;\n" + "varying vec2 oTexCoord2;\n" + "\n" + "void main()\n" + "{\n" + " float ResultR = texture2D(Texture, oTexCoord0).r;\n" + " float ResultG = texture2D(Texture, oTexCoord1).g;\n" + " float ResultB = texture2D(Texture, oTexCoord2).b;\n" + " gl_FragColor = vec4(ResultR * oColor.r, ResultG * oColor.g, ResultB * oColor.b, 1.0);\n" + "}\n"; + +static const char* PostProcessMeshPositionalTimewarpFragShaderSrc = + "uniform sampler2D Texture0;\n" + "uniform sampler2D Texture1;\n" + "varying vec4 oColor;\n" + "varying vec2 oTexCoord0;\n" + "varying vec2 oTexCoord1;\n" + "varying vec2 oTexCoord2;\n" + "\n" + "void main()\n" + "{\n" + " gl_FragColor.r = oColor.r * texture2D(Texture1, oTexCoord0).r;\n" + " gl_FragColor.g = oColor.g * texture2D(Texture1, oTexCoord1).g;\n" + " gl_FragColor.b = oColor.b * texture2D(Texture1, oTexCoord2).b;\n" + " gl_FragColor.a = 1.0;\n" + "}\n"; + + static const char* PostProcessVertexShaderSrc = "uniform mat4 View;\n" "uniform mat4 Texm;\n" @@ -167,85 +327,275 @@ static const char* PostProcessVertexShaderSrc = "{\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* PostProcessMeshVertexShaderSrc = + "uniform vec2 EyeToSourceUVScale;\n" + "uniform vec2 EyeToSourceUVOffset;\n" + + "attribute vec2 Position;\n" + "attribute vec4 Color;\n" + "attribute vec2 TexCoord0;\n" + "attribute vec2 TexCoord1;\n" + "attribute vec2 TexCoord2;\n" + + "varying vec4 oColor;\n" + "varying vec2 oTexCoord0;\n" + "varying vec2 oTexCoord1;\n" + "varying vec2 oTexCoord2;\n" + + "void main()\n" + "{\n" + " gl_Position.x = Position.x;\n" + " gl_Position.y = Position.y;\n" + " gl_Position.z = 0.5;\n" + " gl_Position.w = 1.0;\n" + // Vertex inputs are in TanEyeAngle space for the R,G,B channels (i.e. after chromatic aberration and distortion). + // Scale them into the correct [0-1],[0-1] UV lookup space (depending on eye) + " oTexCoord0 = TexCoord0 * EyeToSourceUVScale + EyeToSourceUVOffset;\n" + " oTexCoord0.y = 1-oTexCoord0.y;\n" + " oTexCoord1 = TexCoord1 * EyeToSourceUVScale + EyeToSourceUVOffset;\n" + " oTexCoord1.y = 1-oTexCoord1.y;\n" + " oTexCoord2 = TexCoord2 * EyeToSourceUVScale + EyeToSourceUVOffset;\n" + " oTexCoord2.y = 1-oTexCoord2.y;\n" + " oColor = Color;\n" // Used for vignette fade. + "}\n"; + +static const char* PostProcessMeshTimewarpVertexShaderSrc = + "uniform vec2 EyeToSourceUVScale;\n" + "uniform vec2 EyeToSourceUVOffset;\n" + "uniform mat4 EyeRotationStart;\n" + "uniform mat4 EyeRotationEnd;\n" + + "attribute vec2 Position;\n" + "attribute vec4 Color;\n" + "attribute vec2 TexCoord0;\n" + "attribute vec2 TexCoord1;\n" + "attribute vec2 TexCoord2;\n" + + "varying vec4 oColor;\n" + "varying vec2 oTexCoord0;\n" + "varying vec2 oTexCoord1;\n" + "varying vec2 oTexCoord2;\n" + + "void main()\n" + "{\n" + " gl_Position.x = Position.x;\n" + " gl_Position.y = Position.y;\n" + " gl_Position.z = 0.0;\n" + " gl_Position.w = 1.0;\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. + " vec3 TanEyeAngleR = vec3 ( TexCoord0.x, TexCoord0.y, 1.0 );\n" + " vec3 TanEyeAngleG = vec3 ( TexCoord1.x, TexCoord1.y, 1.0 );\n" + " vec3 TanEyeAngleB = vec3 ( TexCoord2.x, TexCoord2.y, 1.0 );\n" + + // Accurate time warp lerp vs. faster +#if 1 + // Apply the two 3x3 timewarp rotations to these vectors. + " vec3 TransformedRStart = (EyeRotationStart * vec4(TanEyeAngleR, 0)).xyz;\n" + " vec3 TransformedGStart = (EyeRotationStart * vec4(TanEyeAngleG, 0)).xyz;\n" + " vec3 TransformedBStart = (EyeRotationStart * vec4(TanEyeAngleB, 0)).xyz;\n" + " vec3 TransformedREnd = (EyeRotationEnd * vec4(TanEyeAngleR, 0)).xyz;\n" + " vec3 TransformedGEnd = (EyeRotationEnd * vec4(TanEyeAngleG, 0)).xyz;\n" + " vec3 TransformedBEnd = (EyeRotationEnd * vec4(TanEyeAngleB, 0)).xyz;\n" + // And blend between them. + " vec3 TransformedR = mix ( TransformedRStart, TransformedREnd, Color.a );\n" + " vec3 TransformedG = mix ( TransformedGStart, TransformedGEnd, Color.a );\n" + " vec3 TransformedB = mix ( TransformedBStart, TransformedBEnd, Color.a );\n" +#else + " mat3 EyeRotation = mix ( EyeRotationStart, EyeRotationEnd, Color.a );\n" + " vec3 TransformedR = EyeRotation * TanEyeAngleR;\n" + " vec3 TransformedG = EyeRotation * TanEyeAngleG;\n" + " vec3 TransformedB = EyeRotation * TanEyeAngleB;\n" +#endif + + // Project them back onto the Z=1 plane of the rendered images. + " float RecipZR = 1.0 / TransformedR.z;\n" + " float RecipZG = 1.0 / TransformedG.z;\n" + " float RecipZB = 1.0 / TransformedB.z;\n" + " vec2 FlattenedR = vec2 ( TransformedR.x * RecipZR, TransformedR.y * RecipZR );\n" + " vec2 FlattenedG = vec2 ( TransformedG.x * RecipZG, TransformedG.y * RecipZG );\n" + " vec2 FlattenedB = vec2 ( TransformedB.x * RecipZB, TransformedB.y * RecipZB );\n" + + // These are now still in TanEyeAngle space. + // Scale them into the correct [0-1],[0-1] UV lookup space (depending on eye) + " vec2 SrcCoordR = FlattenedR * EyeToSourceUVScale + EyeToSourceUVOffset;\n" + " vec2 SrcCoordG = FlattenedG * EyeToSourceUVScale + EyeToSourceUVOffset;\n" + " vec2 SrcCoordB = FlattenedB * EyeToSourceUVScale + EyeToSourceUVOffset;\n" + " oTexCoord0 = SrcCoordR;\n" + " oTexCoord0.y = 1-oTexCoord0.y;\n" + " oTexCoord1 = SrcCoordG;\n" + " oTexCoord1.y = 1-oTexCoord1.y;\n" + " oTexCoord2 = SrcCoordB;\n" + " oTexCoord2.y = 1-oTexCoord2.y;\n" + " oColor = Color.r;\n" // Used for vignette fade. + "}\n"; + +static const char* PostProcessMeshPositionalTimewarpVertexShaderSrc = + "#version 150\n" + "uniform sampler2D Texture0;\n" + "uniform vec2 EyeToSourceUVScale;\n" + "uniform vec2 EyeToSourceUVOffset;\n" + "uniform vec2 DepthProjector;\n" + "uniform vec2 DepthDimSize;\n" + "uniform mat4 EyeRotationStart;\n" + "uniform mat4 EyeRotationEnd;\n" + + "in vec2 Position;\n" + "in vec4 Color;\n" + "in vec2 TexCoord0;\n" + "in vec2 TexCoord1;\n" + "in vec2 TexCoord2;\n" + + "out vec4 oColor;\n" + "out vec2 oTexCoord0;\n" + "out vec2 oTexCoord1;\n" + "out vec2 oTexCoord2;\n" + + "vec4 PositionFromDepth(vec2 inTexCoord)\n" + "{\n" + " vec2 eyeToSourceTexCoord = inTexCoord * EyeToSourceUVScale + EyeToSourceUVOffset;\n" + " eyeToSourceTexCoord.y = 1 - eyeToSourceTexCoord.y;\n" + " float depth = texelFetch(Texture0, ivec2(eyeToSourceTexCoord * DepthDimSize), 0).x;\n" + " float linearDepth = DepthProjector.y / (depth - DepthProjector.x);\n" + " vec4 retVal = vec4(inTexCoord, 1, 1);\n" + " retVal.xyz *= linearDepth;\n" + " return retVal;\n" + "}\n" + + "vec2 TimewarpTexCoordToWarpedPos(vec2 inTexCoord, float a)\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 4x4 timewarp rotation to these vectors. + " vec4 inputPos = PositionFromDepth(inTexCoord);\n" + " vec3 transformed = mix ( EyeRotationStart * inputPos, EyeRotationEnd * inputPos, a ).xyz;\n" + // Project them back onto the Z=1 plane of the rendered images. + " vec2 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) + " vec2 noDepthUV = flattened * EyeToSourceUVScale + EyeToSourceUVOffset;\n" + //" float depth = texture2DLod(Texture0, noDepthUV, 0).r;\n" + " return noDepthUV.xy;\n" + "}\n" + + "void main()\n" + "{\n" + " gl_Position.x = Position.x;\n" + " gl_Position.y = Position.y;\n" + " gl_Position.z = 0.0;\n" + " gl_Position.w = 1.0;\n" + + // warped positions are a bit more involved, hence a separate function + " oTexCoord0 = TimewarpTexCoordToWarpedPos(TexCoord0, Color.a);\n" + " oTexCoord0.y = 1-oTexCoord0.y;\n" + " oTexCoord1 = TimewarpTexCoordToWarpedPos(TexCoord1, Color.a);\n" + " oTexCoord1.y = 1-oTexCoord1.y;\n" + " oTexCoord2 = TimewarpTexCoordToWarpedPos(TexCoord2, Color.a);\n" + " oTexCoord2.y = 1-oTexCoord2.y;\n" + + " oColor = vec4(Color.r); // Used for vignette fade.\n" "}\n"; static const char* PostProcessFragShaderSrc = "uniform vec2 LensCenter;\n" "uniform vec2 ScreenCenter;\n" - "uniform vec2 Scale;\n" - "uniform vec2 ScaleIn;\n" + "uniform vec2 EyeToSourceUVScale;\n" + "uniform vec2 EyeToSourceNDCScale;\n" "uniform vec4 HmdWarpParam;\n" - "uniform sampler2D Texture0;\n" + "uniform sampler2D Texture1;\n" + "varying vec2 oTexCoord;\n" - "\n" + "vec2 HmdWarp(vec2 in01)\n" "{\n" - " vec2 theta = (in01 - LensCenter) * ScaleIn;\n" // Scales to [-1, 1] + " vec2 theta = (in01 - LensCenter) * EyeToSourceNDCScale;\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" + " return LensCenter + EyeToSourceUVScale * 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" + " gl_FragColor = texture2D(Texture1, 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" +static const char* PostProcessFragShaderWithChromAbSrc = + "uniform sampler2D Texture;\n" + "uniform vec3 DistortionClearColor;\n" + "uniform float EdgeFadeScale;\n" + "uniform vec2 EyeToSourceUVScale;\n" + "uniform vec2 EyeToSourceUVOffset;\n" + "uniform vec2 EyeToSourceNDCScale;\n" + "uniform vec2 EyeToSourceNDCOffset;\n" + "uniform vec2 TanEyeAngleScale;\n" + "uniform vec2 TanEyeAngleOffset;\n" "uniform vec4 HmdWarpParam;\n" "uniform vec4 ChromAbParam;\n" - "uniform sampler2D Texture0;\n" + + "varying vec4 oPosition;\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" + + "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" + // Input oTexCoord is [-1,1] across the half of the screen used for a single eye. + " vec2 TanEyeAngleDistorted = oTexCoord * TanEyeAngleScale + TanEyeAngleOffset;\n" // Scales to tan(thetaX),tan(thetaY), but still distorted (i.e. only the center is correct) + " float RadiusSq = TanEyeAngleDistorted.x * TanEyeAngleDistorted.x + TanEyeAngleDistorted.y * TanEyeAngleDistorted.y;\n" + " float Distort = 1.0 / ( 1.0 + RadiusSq * ( HmdWarpParam.y + RadiusSq * ( HmdWarpParam.z + RadiusSq * ( HmdWarpParam.w ) ) ) );\n" + " float DistortR = Distort * ( ChromAbParam.x + RadiusSq * ChromAbParam.y );\n" + " float DistortG = Distort;\n" + " float DistortB = Distort * ( ChromAbParam.z + RadiusSq * ChromAbParam.w );\n" + " vec2 TanEyeAngleR = DistortR * TanEyeAngleDistorted;\n" + " vec2 TanEyeAngleG = DistortG * TanEyeAngleDistorted;\n" + " vec2 TanEyeAngleB = DistortB * TanEyeAngleDistorted;\n" + + // These are now in "TanEyeAngle" space. + // The vectors (TanEyeAngleRGB.x, TanEyeAngleRGB.y, 1.0) are real-world vectors pointing from the eye to where the components of the pixel appear to be. + // If you had a raytracer, you could just use them directly. + + // Scale them into ([0,0.5],[0,1]) or ([0.5,0],[0,1]) UV lookup space (depending on eye) + " vec2 SourceCoordR = TanEyeAngleR * EyeToSourceUVScale + EyeToSourceUVOffset;\n" + " SourceCoordR.y = 1 - SourceCoordR.y;\n" + " vec2 SourceCoordG = TanEyeAngleG * EyeToSourceUVScale + EyeToSourceUVOffset;\n" + " SourceCoordG.y = 1 - SourceCoordG.y;\n" + " vec2 SourceCoordB = TanEyeAngleB * EyeToSourceUVScale + EyeToSourceUVOffset;\n" + " SourceCoordB.y = 1 - SourceCoordB.y;\n" + + // Find the distance to the nearest edge. + " vec2 NDCCoord = TanEyeAngleG * EyeToSourceNDCScale + EyeToSourceNDCOffset;\n" + " float EdgeFadeIn = clamp ( EdgeFadeScale, 0, 1e5 ) * ( 1.0 - max ( abs ( NDCCoord.x ), abs ( NDCCoord.y ) ) );\n" + " if ( EdgeFadeIn < 0.0 )\n" " {\n" - " gl_FragColor = vec4(0);\n" - " return;\n" + " gl_FragColor = vec4(DistortionClearColor.r, DistortionClearColor.g, DistortionClearColor.b, 1.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, center.a);\n" + " EdgeFadeIn = clamp ( EdgeFadeIn, 0.0, 1.0 );\n" + + // Actually do the lookups. + " float ResultR = texture2D(Texture, SourceCoordR).r;\n" + " float ResultG = texture2D(Texture, SourceCoordG).g;\n" + " float ResultB = texture2D(Texture, SourceCoordB).b;\n" + + " gl_FragColor = vec4(ResultR * EdgeFadeIn, ResultG * EdgeFadeIn, ResultB * EdgeFadeIn, 1.0);\n" "}\n"; + + static const char* VShaderSrcs[VShader_Count] = { DirectVertexShaderSrc, StdVertexShaderSrc, - PostProcessVertexShaderSrc + PostProcessVertexShaderSrc, + PostProcessMeshVertexShaderSrc, + PostProcessMeshTimewarpVertexShaderSrc, + PostProcessMeshPositionalTimewarpVertexShaderSrc }; static const char* FShaderSrcs[FShader_Count] = { @@ -253,16 +603,17 @@ static const char* FShaderSrcs[FShader_Count] = GouraudFragShaderSrc, TextureFragShaderSrc, AlphaTextureFragShaderSrc, - PostProcessFragShaderSrc, - PostProcessFullFragShaderSrc, + PostProcessFragShaderWithChromAbSrc, LitSolidFragShaderSrc, LitTextureFragShaderSrc, - MultiTextureFragShaderSrc + MultiTextureFragShaderSrc, + PostProcessMeshFragShaderSrc, + PostProcessMeshTimewarpFragShaderSrc, + PostProcessMeshPositionalTimewarpFragShaderSrc }; - -RenderDevice::RenderDevice(const RendererParams& p) +RenderDevice::RenderDevice(const RendererParams&) { for (int i = 0; i < VShader_Count; i++) VertexShaders[i] = *new Shader(this, Shader_Vertex, VShaderSrcs[i]); @@ -278,6 +629,37 @@ RenderDevice::RenderDevice(const RendererParams& p) glGenFramebuffersEXT(1, &CurrentFbo); } +RenderDevice::~RenderDevice() +{ + Shutdown(); +} + +void RenderDevice::Shutdown() +{ + // Release any other resources first. + OVR::Render::RenderDevice::Shutdown(); + + // This runs before the subclass's Shutdown(), where the context, etc, may be deleted. + + glDeleteFramebuffersEXT(1, &CurrentFbo); + + for (int i = 0; i < VShader_Count; ++i) + VertexShaders[i].Clear(); + + for (int i = 0; i < FShader_Count; ++i) + FragShaders[i].Clear(); + + DefaultFill.Clear(); + DepthBuffers.Clear(); +} + + +void RenderDevice::FillTexturedRect(float left, float top, float right, float bottom, float ul, float vt, float ur, float vb, Color c, Ptr<OVR::Render::Texture> tex) +{ + Render::RenderDevice::FillTexturedRect(left, top, right, bottom, ul, vb, ur, vt, c, tex); +} + + Shader *RenderDevice::LoadBuiltinShader(ShaderStage stage, int shader) { switch (stage) @@ -323,7 +705,7 @@ void RenderDevice::SetDepthMode(bool enable, bool write, CompareFunc func) glDisable(GL_DEPTH_TEST); } -void RenderDevice::SetRealViewport(const Viewport& vp) +void RenderDevice::SetViewport(const Recti& vp) { int wh; if (CurRenderTarget) @@ -332,30 +714,38 @@ void RenderDevice::SetRealViewport(const Viewport& vp) 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); + //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) +void RenderDevice::WaitUntilGpuIdle() { - glClearColor(r,g,b,a); - glClearDepth(depth); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); + glFlush(); + glFinish(); } -RBuffer* RenderDevice::GetDepthBuffer(int w, int h, int ms) +void RenderDevice::Clear(float r, float g, float b, float a, float depth, bool clearColor /*= true*/, bool clearDepth /*= true*/) +{ + glClearColor(r,g,b,a); + glClearDepth(depth); + glClear( + ( clearColor ? ( GL_COLOR_BUFFER_BIT ) : 0 ) | + ( clearDepth ? ( GL_DEPTH_BUFFER_BIT ) : 0 ) + ); +} + +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) + if (w == DepthBuffers[i]->Width && h == DepthBuffers[i]->Height && ms == DepthBuffers[i]->GetSamples()) return DepthBuffers[i]; - //Ptr<Texture> newDepth = *CreateTexture(Texture_Depth|Texture_RenderTarget|ms, w, h, NULL); - Ptr<RBuffer> newDepth = *new RBuffer(GL_DEPTH24_STENCIL8, w, h); // combined depth stencil + Ptr<Texture> newDepth = *CreateTexture(Texture_Depth|Texture_RenderTarget|ms, w, h, NULL); DepthBuffers.PushBack(newDepth); return newDepth.GetPtr(); } -void RenderDevice::SetRenderTarget(Render::Texture* color, Render::Texture*, Render::Texture* stencil) +void RenderDevice::SetRenderTarget(Render::Texture* color, Render::Texture* depth, Render::Texture* stencil) { OVR_UNUSED(stencil); @@ -365,14 +755,14 @@ void RenderDevice::SetRenderTarget(Render::Texture* color, Render::Texture*, Ren glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); return; } - //if (depth == NULL) - RBuffer* depth = GetDepthBuffer(color->GetWidth(), color->GetHeight(), 0); //CurRenderTarget->Samples); + + if (depth == NULL) + depth = GetDepthBuffer(color->GetWidth(), color->GetHeight(), CurRenderTarget->GetSamples()); 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); + glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_2D, ((Texture*)depth)->TexId, 0); else glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, 0); @@ -404,8 +794,7 @@ Fill* RenderDevice::CreateSimpleFill(int flags) OVR_UNUSED(flags); return DefaultFill; } - - + void RenderDevice::Render(const Matrix4f& matrix, Model* model) { // Store data in buffers if not already @@ -428,7 +817,7 @@ void RenderDevice::Render(const Matrix4f& matrix, Model* model) } void RenderDevice::Render(const Fill* fill, Render::Buffer* vertices, Render::Buffer* indices, - const Matrix4f& matrix, int offset, int count, PrimitiveType rprim) + const Matrix4f& matrix, int offset, int count, PrimitiveType rprim, bool useDistortionVertex/* = false*/) { ShaderSet* shaders = (ShaderSet*) ((ShaderFill*)fill)->GetShaders(); @@ -461,15 +850,26 @@ void RenderDevice::Render(const Fill* fill, Render::Buffer* vertices, Render::Bu Lighting->Set(shaders); } - glBindBuffer(GL_ARRAY_BUFFER, ((Buffer*)vertices)->GLBuffer); - for (int i = 0; i < 5; 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, 2, GL_FLOAT, false, sizeof(Vertex), (char*)offset + offsetof(Vertex, U2)); - glVertexAttribPointer(4, 3, GL_FLOAT, false, sizeof(Vertex), (char*)offset + offsetof(Vertex, Norm)); + glBindBuffer(GL_ARRAY_BUFFER, ((Buffer*)vertices)->GLBuffer); + for (int i = 0; i < 5; i++) + glEnableVertexAttribArray(i); + + if (useDistortionVertex) + { + glVertexAttribPointer(0, 2, GL_FLOAT, false, sizeof(DistortionVertex), (char*)offset + offsetof(DistortionVertex, Pos)); + glVertexAttribPointer(1, 4, GL_UNSIGNED_BYTE, true, sizeof(DistortionVertex), (char*)offset + offsetof(DistortionVertex, Col)); + glVertexAttribPointer(2, 2, GL_FLOAT, false, sizeof(DistortionVertex), (char*)offset + offsetof(DistortionVertex, TexR)); + glVertexAttribPointer(3, 2, GL_FLOAT, false, sizeof(DistortionVertex), (char*)offset + offsetof(DistortionVertex, TexG)); + glVertexAttribPointer(4, 2, GL_FLOAT, false, sizeof(DistortionVertex), (char*)offset + offsetof(DistortionVertex, TexB)); + } + else + { + 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, 2, GL_FLOAT, false, sizeof(Vertex), (char*)offset + offsetof(Vertex, U2)); + glVertexAttribPointer(4, 3, GL_FLOAT, false, sizeof(Vertex), (char*)offset + offsetof(Vertex, Norm)); + } if (indices) { @@ -482,8 +882,8 @@ void RenderDevice::Render(const Fill* fill, Render::Buffer* vertices, Render::Bu glDrawArrays(prim, 0, count); } - for (int i = 0; i < 5; i++) - glDisableVertexAttribArray(i); + for (int i = 0; i < 5; i++) + glDisableVertexAttribArray(i); } void RenderDevice::RenderWithAlpha(const Fill* fill, Render::Buffer* vertices, Render::Buffer* indices, @@ -526,7 +926,7 @@ bool Buffer::Data(int use, const void* buffer, size_t size) return 1; } -void* Buffer::Map(size_t start, size_t size, int flags) +void* Buffer::Map(size_t, size_t, int) { int mode = GL_WRITE_ONLY; //if (flags & Map_Unsynchronized) @@ -543,7 +943,13 @@ bool Buffer::Unmap(void*) glBindBuffer(Use, GLBuffer); int r = glUnmapBuffer(Use); glBindBuffer(Use, 0); - return r; + return r != 0; +} + +Shader::~Shader() +{ + if (GLShader) + glDeleteShader(GLShader); } bool Shader::Compile(const char* src) @@ -576,6 +982,24 @@ ShaderSet::~ShaderSet() glDeleteProgram(Prog); } +void ShaderSet::SetShader(Render::Shader *s) +{ + Shaders[s->GetStage()] = s; + Shader* gls = (Shader*)s; + glAttachShader(Prog, gls->GLShader); + if (Shaders[Shader_Vertex] && Shaders[Shader_Fragment]) + Link(); +} + +void ShaderSet::UnsetShader(int stage) +{ + Shader* gls = (Shader*)(Render::Shader*)Shaders[stage]; + if (gls) + glDetachShader(Prog, gls->GLShader); + Shaders[stage] = NULL; + Link(); +} + bool ShaderSet::Link() { glBindAttribLocation(Prog, 0, "Position"); @@ -600,14 +1024,19 @@ bool ShaderSet::Link() UniformInfo.Clear(); LightingVer = 0; UsesLighting = 0; - GLuint i = 0; - for(;; i++) + + GLint uniformCount = 0; + glGetProgramiv(Prog, GL_ACTIVE_UNIFORMS, &uniformCount); + OVR_ASSERT(uniformCount >= 0); + + for(GLuint i = 0; i < (GLuint)uniformCount; 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); @@ -628,6 +1057,7 @@ bool ShaderSet::Link() 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_MAT3: u.Type = 12; break; case GL_FLOAT_MAT4: u.Type = 16; break; default: continue; @@ -645,7 +1075,7 @@ bool ShaderSet::Link() for (int i = 0; i < 8; i++) { char texv[32]; - sprintf(texv, "Texture%d", i); + OVR_sprintf(texv, 10, "Texture%d", i); TexLoc[i] = glGetUniformLocation(Prog, texv); if (TexLoc[i] < 0) break; @@ -664,7 +1094,7 @@ void ShaderSet::Set(PrimitiveType) const bool ShaderSet::SetUniform(const char* name, int n, const float* v) { - for (int i = 0; i < UniformInfo.GetSize(); i++) + for (unsigned int i = 0; i < UniformInfo.GetSize(); i++) if (!strcmp(UniformInfo[i].Name.ToCStr(), name)) { OVR_ASSERT(UniformInfo[i].Location >= 0); @@ -675,6 +1105,8 @@ bool ShaderSet::SetUniform(const char* name, int n, const float* v) 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; + case 12: glUniformMatrix3fv(UniformInfo[i].Location, 1, 1, v); break; + case 16: glUniformMatrix4fv(UniformInfo[i].Location, 1, 1, v); break; default: OVR_ASSERT(0); } return 1; @@ -686,7 +1118,7 @@ bool ShaderSet::SetUniform(const char* name, int n, const float* v) bool ShaderSet::SetUniform4x4f(const char* name, const Matrix4f& m) { - for (int i = 0; i < UniformInfo.GetSize(); i++) + for (unsigned int i = 0; i < UniformInfo.GetSize(); i++) if (!strcmp(UniformInfo[i].Name.ToCStr(), name)) { glUseProgram(Prog); @@ -722,7 +1154,7 @@ void Texture::SetSampleMode(int sm) 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); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 1); break; case Sample_Anisotropic: @@ -734,7 +1166,7 @@ void Texture::SetSampleMode(int sm) 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); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 1); break; } @@ -758,6 +1190,20 @@ void Texture::SetSampleMode(int sm) glBindTexture(GL_TEXTURE_2D, 0); } +ovrTexture Texture::Get_ovrTexture() +{ + ovrTexture tex; + OVR::Sizei newRTSize(Width, Height); + + ovrGLTextureData* texData = (ovrGLTextureData*)&tex; + texData->Header.API = ovrRenderAPI_OpenGL; + texData->Header.TextureSize = newRTSize; + texData->Header.RenderViewport = Recti(newRTSize); + texData->TexId = TexId; + + return tex; +} + Texture* RenderDevice::CreateTexture(int format, int width, int height, const void* data, int mipcount) { GLenum glformat, gltype = GL_UNSIGNED_BYTE; @@ -765,7 +1211,7 @@ Texture* RenderDevice::CreateTexture(int format, int width, int height, const vo { case Texture_RGBA: glformat = GL_RGBA; break; case Texture_R: glformat = GL_ALPHA; break; - case Texture_Depth: glformat = GL_DEPTH; gltype = GL_DEPTH_COMPONENT; break; + case Texture_Depth: glformat = GL_DEPTH_COMPONENT32F; gltype = GL_FLOAT; break; case Texture_DXT1: glformat = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT; break; case Texture_DXT3: glformat = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT; break; case Texture_DXT5: glformat = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT; break; @@ -774,7 +1220,7 @@ Texture* RenderDevice::CreateTexture(int format, int width, int height, const vo } Texture* NewTex = new Texture(this, width, height); glBindTexture(GL_TEXTURE_2D, NewTex->TexId); - glGetError(); + OVR_ASSERT(!glGetError()); if (format & Texture_Compressed) { @@ -792,6 +1238,8 @@ Texture* RenderDevice::CreateTexture(int format, int width, int height, const vo if (h < 1) h = 1; } } + else if (format & Texture_Depth) + glTexImage2D(GL_TEXTURE_2D, 0, glformat, width, height, 0, GL_DEPTH_COMPONENT, gltype, data); else glTexImage2D(GL_TEXTURE_2D, 0, glformat, width, height, 0, glformat, gltype, data); @@ -831,12 +1279,6 @@ Texture* RenderDevice::CreateTexture(int format, int width, int height, const vo return NewTex; } -bool RenderDevice::SetFullscreen(DisplayMode fullscreen) -{ - Params.Fullscreen = fullscreen; - return true; -} - RBuffer::RBuffer(GLenum format, GLint w, GLint h) { Width = w; @@ -849,7 +1291,8 @@ RBuffer::RBuffer(GLenum format, GLint w, GLint h) RBuffer::~RBuffer() { - glDeleteRenderbuffersEXT(1, &BufId); + if (BufId) + glDeleteRenderbuffersEXT(1, &BufId); } }}} diff --git a/Samples/CommonSrc/Render/Render_GL_Device.h b/Samples/CommonSrc/Render/Render_GL_Device.h index 88eaff4..5d97eef 100644 --- a/Samples/CommonSrc/Render/Render_GL_Device.h +++ b/Samples/CommonSrc/Render/Render_GL_Device.h @@ -34,13 +34,76 @@ limitations under the License. #include <OpenGL/gl.h> #include <OpenGL/glext.h> #else +#ifndef GL_GLEXT_PROTOTYPES #define GL_GLEXT_PROTOTYPES +#endif #include <GL/gl.h> #include <GL/glext.h> +#if defined(OVR_OS_WIN32) +#include <GL/wglext.h> +#endif #endif namespace OVR { namespace Render { namespace GL { +// GL extension Hooks for PC. +#if defined(OVR_OS_WIN32) + +extern PFNWGLGETSWAPINTERVALEXTPROC wglGetSwapIntervalEXT; +extern PFNWGLSWAPINTERVALEXTPROC wglSwapIntervalEXT; +extern PFNGLGENFRAMEBUFFERSEXTPROC glGenFramebuffersEXT; +extern PFNGLDELETEFRAMEBUFFERSEXTPROC glDeleteFramebuffersEXT; +extern PFNGLDELETESHADERPROC glDeleteShader; +extern PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC glCheckFramebufferStatusEXT; +extern PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC glFramebufferRenderbufferEXT; +extern PFNGLFRAMEBUFFERTEXTURE2DEXTPROC glFramebufferTexture2DEXT; +extern PFNGLBINDFRAMEBUFFEREXTPROC glBindFramebufferEXT; +extern PFNGLACTIVETEXTUREPROC glActiveTexture; +extern PFNGLDISABLEVERTEXATTRIBARRAYPROC glDisableVertexAttribArray; +extern PFNGLVERTEXATTRIBPOINTERPROC glVertexAttribPointer; +extern PFNGLENABLEVERTEXATTRIBARRAYPROC glEnableVertexAttribArray; +extern PFNGLBINDBUFFERPROC glBindBuffer; +extern PFNGLUNIFORMMATRIX4FVPROC glUniformMatrix4fv; +extern PFNGLDELETEBUFFERSPROC glDeleteBuffers; +extern PFNGLBUFFERDATAPROC glBufferData; +extern PFNGLGENBUFFERSPROC glGenBuffers; +extern PFNGLMAPBUFFERPROC glMapBuffer; +extern PFNGLUNMAPBUFFERPROC glUnmapBuffer; +extern PFNGLGETSHADERINFOLOGPROC glGetShaderInfoLog; +extern PFNGLGETSHADERIVPROC glGetShaderiv; +extern PFNGLCOMPILESHADERPROC glCompileShader; +extern PFNGLSHADERSOURCEPROC glShaderSource; +extern PFNGLCREATESHADERPROC glCreateShader; +extern PFNGLCREATEPROGRAMPROC glCreateProgram; +extern PFNGLATTACHSHADERPROC glAttachShader; +extern PFNGLDETACHSHADERPROC glDetachShader; +extern PFNGLDELETEPROGRAMPROC glDeleteProgram; +extern PFNGLUNIFORM1IPROC glUniform1i; +extern PFNGLGETUNIFORMLOCATIONPROC glGetUniformLocation; +extern PFNGLGETACTIVEUNIFORMPROC glGetActiveUniform; +extern PFNGLUSEPROGRAMPROC glUseProgram; +extern PFNGLGETPROGRAMINFOLOGPROC glGetProgramInfoLog; +extern PFNGLGETPROGRAMIVPROC glGetProgramiv; +extern PFNGLLINKPROGRAMPROC glLinkProgram; +extern PFNGLBINDATTRIBLOCATIONPROC glBindAttribLocation; +extern PFNGLUNIFORM4FVPROC glUniform4fv; +extern PFNGLUNIFORM3FVPROC glUniform3fv; +extern PFNGLUNIFORM2FVPROC glUniform2fv; +extern PFNGLUNIFORM1FVPROC glUniform1fv; +extern PFNGLCOMPRESSEDTEXIMAGE2DPROC glCompressedTexImage2D; +extern PFNGLRENDERBUFFERSTORAGEEXTPROC glRenderbufferStorageEXT; +extern PFNGLBINDRENDERBUFFEREXTPROC glBindRenderbufferEXT; +extern PFNGLGENRENDERBUFFERSEXTPROC glGenRenderbuffersEXT; +extern PFNGLDELETERENDERBUFFERSEXTPROC glDeleteRenderbuffersEXT; + +// For testing +extern PFNGLGENVERTEXARRAYSPROC glGenVertexArrays; + +extern void InitGLExtensions(); + +#endif + + class RenderDevice; class Buffer : public Render::Buffer @@ -77,6 +140,7 @@ public: virtual int GetHeight() const { return Height; } virtual void SetSampleMode(int); + virtual ovrTexture Get_ovrTexture(); virtual void Set(int slot, ShaderStage stage = Shader_Fragment) const; }; @@ -91,11 +155,8 @@ public: { Compile(src); } - ~Shader() - { - if (GLShader) - glDeleteShader(GLShader); - } + + ~Shader(); bool Compile(const char* src); GLenum GLStage() const @@ -133,22 +194,8 @@ public: ShaderSet(); ~ShaderSet(); - virtual void SetShader(Render::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*)(Render::Shader*)Shaders[stage]; - if (gls) - glDetachShader(Prog, gls->GLShader); - Shaders[stage] = NULL; - Link(); - } + virtual void SetShader(Render::Shader *s); + virtual void UnsetShader(int stage); virtual void Set(PrimitiveType prim) const; @@ -161,7 +208,7 @@ public: bool Link(); }; - class RBuffer : public RefCountBase<RBuffer> +class RBuffer : public RefCountBase<RBuffer> { public: int Width, Height; @@ -180,28 +227,38 @@ class RenderDevice : public Render::RenderDevice Matrix4f Proj; +protected: Ptr<Texture> CurRenderTarget; - Array<Ptr<RBuffer> > DepthBuffers; + Array<Ptr<Texture> > DepthBuffers; GLuint CurrentFbo; const LightingParams* Lighting; public: RenderDevice(const RendererParams& p); + virtual ~RenderDevice(); - virtual void SetRealViewport(const Viewport& vp); + virtual void Shutdown(); + + virtual void FillTexturedRect(float left, float top, float right, float bottom, float ul, float vt, float ur, float vb, Color c, Ptr<OVR::Render::Texture> tex); + + virtual void SetViewport(const Recti& vp); //virtual void SetScissor(int x, int y, int w, int h); + + virtual void WaitUntilGpuIdle(); - virtual void Clear(float r = 0, float g = 0, float b = 0, float a = 1, float depth = 1); + virtual void Clear(float r = 0, float g = 0, float b = 0, float a = 1, float depth = 1, + bool clearColor = true, bool clearDepth = true); 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); + Texture* GetDepthBuffer(int w, int h, int ms); + virtual void Present (bool withVsync){OVR_UNUSED(withVsync);}; virtual void SetRenderTarget(Render::Texture* color, Render::Texture* depth = NULL, Render::Texture* stencil = NULL); @@ -209,7 +266,7 @@ public: virtual void Render(const Matrix4f& matrix, Model* model); virtual void Render(const Fill* fill, Render::Buffer* vertices, Render::Buffer* indices, - const Matrix4f& matrix, int offset, int count, PrimitiveType prim = Prim_Triangles); + const Matrix4f& matrix, int offset, int count, PrimitiveType prim = Prim_Triangles, bool useDistortionVertex = false); virtual void RenderWithAlpha(const Fill* fill, Render::Buffer* vertices, Render::Buffer* indices, const Matrix4f& matrix, int offset, int count, PrimitiveType prim = Prim_Triangles); @@ -222,8 +279,6 @@ public: virtual Shader *LoadBuiltinShader(ShaderStage stage, int shader); void SetTexture(Render::ShaderStage, int slot, const Texture* t); - - virtual bool SetFullscreen(DisplayMode fullscreen); }; }}} diff --git a/Samples/CommonSrc/Render/Render_GL_Win32_Device.cpp b/Samples/CommonSrc/Render/Render_GL_Win32_Device.cpp index 4f22a50..1065c98 100644 --- a/Samples/CommonSrc/Render/Render_GL_Win32_Device.cpp +++ b/Samples/CommonSrc/Render/Render_GL_Win32_Device.cpp @@ -3,7 +3,7 @@ Filename : Render_GL_Win32 Device.cpp Content : Win32 OpenGL Device implementation Created : September 10, 2012 -Authors : Andrew Reisse, Michael Antonov +Authors : Andrew Reisse, Michael Antonov, David Borel Copyright : Copyright 2012 Oculus VR, Inc. All Rights reserved. @@ -22,16 +22,46 @@ limitations under the License. ************************************************************************************/ #include "Render_GL_Win32_Device.h" +#include "OVR_CAPI_GL.h" + +#include <dwmapi.h> namespace OVR { namespace Render { namespace GL { namespace Win32 { +typedef HRESULT (__stdcall *PFNDWMENABLECOMPOSITIONPROC) (UINT); + +#pragma warning(disable : 4995) +PFNDWMENABLECOMPOSITIONPROC DwmEnableComposition; + // ***** GL::Win32::RenderDevice + +RenderDevice::RenderDevice(const Render::RendererParams& p, HWND win, HDC dc, HGLRC gl) + : GL::RenderDevice(p) + , Window(win) + , WglContext(gl) + , GdiDc(dc) + , PreFullscreen(0, 0, 0, 0) + , HMonitor(0) + , FSDesktop(0, 0, 0, 0) +{ + OVR_UNUSED(p); +} // Implement static initializer function to create this class. -Render::RenderDevice* RenderDevice::CreateDevice(const RendererParams&, void* oswnd) +Render::RenderDevice* RenderDevice::CreateDevice(const RendererParams& rp, void* oswnd) { HWND hwnd = (HWND)oswnd; + + if (!DwmEnableComposition) + { + HINSTANCE hInst = LoadLibrary( L"dwmapi.dll" ); + OVR_ASSERT(hInst); + DwmEnableComposition = (PFNDWMENABLECOMPOSITIONPROC)GetProcAddress( hInst, "DwmEnableComposition" ); + OVR_ASSERT(DwmEnableComposition); + } + + DwmEnableComposition(DWM_EC_DISABLECOMPOSITION); PIXELFORMATDESCRIPTOR pfd; memset(&pfd, 0, sizeof(pfd)); @@ -63,18 +93,40 @@ Render::RenderDevice* RenderDevice::CreateDevice(const RendererParams&, void* os return NULL; } - // return new RenderDevice(rp, hwnd, dc, context); - return 0; + InitGLExtensions(); + + return new RenderDevice(rp, hwnd, dc, context); } +ovrRenderAPIConfig RenderDevice::Get_ovrRenderAPIConfig() const +{ + static ovrGLConfig cfg; + cfg.OGL.Header.API = ovrRenderAPI_OpenGL; + cfg.OGL.Header.RTSize = Sizei(WindowWidth, WindowHeight); + cfg.OGL.Header.Multisample = Params.Multisample; + cfg.OGL.WglContext = WglContext; + cfg.OGL.Window = Window; + cfg.OGL.GdiDc = GdiDc; -void RenderDevice::Present() + return cfg.Config; +} + +void RenderDevice::Present(bool useVsync) { - SwapBuffers(GdiDc); + BOOL success; + int swapInterval = (useVsync) ? 1 : 0; + if (wglGetSwapIntervalEXT() != swapInterval) + wglSwapIntervalEXT(swapInterval); + + success = SwapBuffers(GdiDc); + OVR_ASSERT(success); } void RenderDevice::Shutdown() { + //Release any remaining GL resources. + GL::RenderDevice::Shutdown(); + if (WglContext) { wglMakeCurrent(NULL,NULL); @@ -86,5 +138,189 @@ void RenderDevice::Shutdown() } } +bool RenderDevice::SetParams(const RendererParams& newParams) +{ + Params = newParams; + //TODO: Apply changes now. + return true; +} + +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().Display.MonitorName.ToCStr())) + { + renderer->HMonitor = hMonitor; + renderer->FSDesktop.x = monitor.rcMonitor.left; + renderer->FSDesktop.y = monitor.rcMonitor.top; + renderer->FSDesktop.w = monitor.rcMonitor.right - monitor.rcMonitor.left; + renderer->FSDesktop.h = monitor.rcMonitor.bottom - monitor.rcMonitor.top; + return FALSE; + } + } + } + + return TRUE; +} + +bool RenderDevice::SetFullscreen(DisplayMode fullscreen) +{ + if (fullscreen == Params.Fullscreen) + { + return true; + } + + if (Params.Fullscreen == Display_FakeFullscreen) + { + SetWindowLong(Window, GWL_STYLE, WS_OVERLAPPEDWINDOW | WS_VISIBLE | WS_CLIPSIBLINGS); + SetWindowPos(Window, HWND_NOTOPMOST, PreFullscreen.x, PreFullscreen.y, + PreFullscreen.w, PreFullscreen.h, SWP_NOZORDER | SWP_NOACTIVATE | SWP_FRAMECHANGED); + } + else if (Params.Fullscreen == Display_Fullscreen) + { + { + // Find out the name of the device this window + // is on (this is for multi-monitor setups) + HMONITOR hMonitor = MonitorFromWindow(Window, MONITOR_DEFAULTTOPRIMARY); + MONITORINFOEX monInfo; + memset(&monInfo, 0, sizeof(MONITORINFOEX)); + monInfo.cbSize = sizeof(MONITORINFOEX); + GetMonitorInfo(hMonitor, &monInfo); + + // Restore the display resolution + ChangeDisplaySettingsEx(monInfo.szDevice, NULL, NULL, 0, NULL); + //ChangeDisplaySettings(NULL, 0); + } + { + // Restore the window styles + DWORD style = (DWORD)GetWindowLongPtr(Window, GWL_STYLE); + DWORD exstyle = (DWORD)GetWindowLongPtr(Window, GWL_EXSTYLE); + SetWindowLongPtr(Window, GWL_STYLE, style | WS_OVERLAPPEDWINDOW); + SetWindowLongPtr(Window, GWL_EXSTYLE, exstyle & (~(WS_EX_APPWINDOW | WS_EX_TOPMOST))); + + MONITORINFOEX monInfo; + memset(&monInfo, 0, sizeof(MONITORINFOEX)); + monInfo.cbSize = sizeof(MONITORINFOEX); + GetMonitorInfo(HMonitor, &monInfo); + + // Restore the window size/position + SetWindowPos(Window, NULL, PreFullscreen.x, PreFullscreen.y, PreFullscreen.w, PreFullscreen.h, + SWP_NOACTIVATE | SWP_NOCOPYBITS | SWP_NOOWNERZORDER | SWP_NOREPOSITION | SWP_NOZORDER); + } + } + + + if (!Params.Display.MonitorName.IsEmpty()) + { + EnumDisplayMonitors(0, 0, MonitorEnumFunc, (LPARAM)this); + } + + if (fullscreen == Display_FakeFullscreen) + { + // Get WINDOWPLACEMENT before changing style to get OVERLAPPED coordinates, + // which we will restore. + WINDOWPLACEMENT wp; + wp.length = sizeof(wp); + GetWindowPlacement(Window, &wp); + PreFullscreen.w = wp.rcNormalPosition.right - wp.rcNormalPosition.left; + PreFullscreen.h = wp.rcNormalPosition.bottom - wp.rcNormalPosition.top; + PreFullscreen.x = wp.rcNormalPosition.left; + PreFullscreen.y = wp.rcNormalPosition.top; + // Warning: SetWindowLong sends message computed based on old size (incorrect). + // A proper work-around would be to mask that message out during window frame change in Platform. + SetWindowLong(Window, GWL_STYLE, WS_OVERLAPPED | WS_VISIBLE | WS_CLIPSIBLINGS); + SetWindowPos(Window, NULL, FSDesktop.x, FSDesktop.y, 0, 0, SWP_NOSIZE | SWP_NOACTIVATE | SWP_FRAMECHANGED); + + // Relocate cursor into the window to avoid losing focus on first click. + POINT oldCursor; + if (GetCursorPos(&oldCursor) && + ((oldCursor.x < FSDesktop.x) || (oldCursor.x > (FSDesktop.x + PreFullscreen.w)) || + (oldCursor.y < FSDesktop.y) || (oldCursor.x > (FSDesktop.y + PreFullscreen.h)))) + { + // TBD: FullScreen window logic should really be in platform; it causes world rotation + // in relative mouse mode. + ::SetCursorPos(FSDesktop.x, FSDesktop.y); + } + } + else if (fullscreen == Display_Fullscreen) + { + // Find out the name of the device this window + // is on (this is for multi-monitor setups) + MONITORINFOEX monInfo; + memset(&monInfo, 0, sizeof(MONITORINFOEX)); + monInfo.cbSize = sizeof(MONITORINFOEX); + GetMonitorInfo(HMonitor, &monInfo); + + // Find the requested device mode + DEVMODE dmode; + bool foundMode = false; + memset(&dmode, 0, sizeof(DEVMODE)); + dmode.dmSize = sizeof(DEVMODE); + Recti vp = VP; + for(int i=0 ; EnumDisplaySettings(monInfo.szDevice, i, &dmode); ++i) + { + foundMode = (dmode.dmPelsWidth==(DWORD)vp.w) && + (dmode.dmPelsHeight==(DWORD)vp.h) && + (dmode.dmBitsPerPel==(DWORD)32); + if (foundMode) + break; + } + if(!foundMode) + return false; + + dmode.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT; + + // Save the current window position/size + RECT rect; + GetWindowRect(Window, &rect); + PreFullscreen.x = rect.left; + PreFullscreen.y = rect.top; + PreFullscreen.w = rect.right - rect.left; + PreFullscreen.h = rect.bottom - rect.top; + + // Save the window style and set it for fullscreen mode + DWORD style = (DWORD)GetWindowLongPtr(Window, GWL_STYLE); + DWORD exstyle = (DWORD)GetWindowLongPtr(Window, GWL_EXSTYLE); + SetWindowLongPtr(Window, GWL_STYLE, style & (~WS_OVERLAPPEDWINDOW)); + SetWindowLongPtr(Window, GWL_EXSTYLE, exstyle | WS_EX_APPWINDOW | WS_EX_TOPMOST); + + // Attempt to change the resolution + LONG ret = ChangeDisplaySettingsEx(monInfo.szDevice, &dmode, NULL, CDS_FULLSCREEN, NULL); + //LONG ret = ChangeDisplaySettings(&dmode, CDS_FULLSCREEN); + + // If it failed, clean up and return. + if (ret != DISP_CHANGE_SUCCESSFUL) + { + SetWindowLongPtr(Window, GWL_STYLE, style); + SetWindowLongPtr(Window, GWL_EXSTYLE, exstyle); + return false; + } + + // We need to call GetMonitorInfo() again becase + // details may have changed with the resolution + GetMonitorInfo(HMonitor, &monInfo); + + // Set the window's size and position so + // that it covers the entire screen + SetWindowPos(Window, HWND_TOPMOST, monInfo.rcMonitor.left, monInfo.rcMonitor.top, vp.w, vp.h, + SWP_SHOWWINDOW | SWP_NOZORDER | SWP_FRAMECHANGED); + } + + Params.Fullscreen = fullscreen; + return true; +} + }}}} diff --git a/Samples/CommonSrc/Render/Render_GL_Win32_Device.h b/Samples/CommonSrc/Render/Render_GL_Win32_Device.h index f63b1d0..de81a80 100644 --- a/Samples/CommonSrc/Render/Render_GL_Win32_Device.h +++ b/Samples/CommonSrc/Render/Render_GL_Win32_Device.h @@ -3,7 +3,7 @@ Filename : Render_GL_Win32 Device.h Content : Win32 OpenGL Device implementation header Created : September 10, 2012 -Authors : Andrew Reisse, Michael Antonov +Authors : Andrew Reisse, Michael Antonov, David Borel Copyright : Copyright 2012 Oculus VR, Inc. All Rights reserved. @@ -38,19 +38,29 @@ namespace OVR { namespace Render { namespace GL { namespace Win32 { // Win32-Specific GL Render Device, used to create OpenGL under Windows. class RenderDevice : public GL::RenderDevice { - HWND Window; - HGLRC WglContext; - HDC GdiDc; + friend BOOL CALLBACK MonitorEnumFunc(HMONITOR hMonitor, HDC, LPRECT, LPARAM dwData); + + HWND Window; + HGLRC WglContext; + HDC GdiDc; + Recti PreFullscreen; + Recti FSDesktop; + HMONITOR HMonitor; public: - RenderDevice(const Render::RendererParams& p, HWND win, HDC dc, HGLRC gl) - : GL::RenderDevice(p), Window(win), WglContext(gl), GdiDc(dc) { OVR_UNUSED(p); } + RenderDevice(const Render::RendererParams& p, HWND win, HDC dc, HGLRC gl); + virtual ~RenderDevice() { Shutdown(); } // Implement static initializer function to create this class. static Render::RenderDevice* CreateDevice(const RendererParams& rp, void* oswnd); + + virtual ovrRenderAPIConfig Get_ovrRenderAPIConfig() const; virtual void Shutdown(); - virtual void Present(); + virtual void Present(bool withVsync); + bool SetParams(const RendererParams& newParams); + + virtual bool SetFullscreen(DisplayMode fullscreen); }; diff --git a/Samples/CommonSrc/Render/Render_LoadTextureDDS.cpp b/Samples/CommonSrc/Render/Render_LoadTextureDDS.cpp index b2b4b31..5bbdb21 100644 --- a/Samples/CommonSrc/Render/Render_LoadTextureDDS.cpp +++ b/Samples/CommonSrc/Render/Render_LoadTextureDDS.cpp @@ -5,7 +5,7 @@ Content : A DDS file loader for cross-platform compressed texture support. Created : March 5, 2013 Authors : Peter Hoff, Dan Goodman, Bryan Croteau -Copyright : Copyright 2013 Oculus VR, Inc. All Rights reserved. +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. @@ -75,10 +75,10 @@ Texture* LoadTextureDDS(RenderDevice* ren, File* f) f->Read((unsigned char*)(&header), sizeof(header)); - int width = header.Width; + int width = header.Width; int height = header.Height; - int format = 0; + int format = Texture_RGBA; UInt32 mipCount = header.MipMapCount; if(mipCount <= 0) diff --git a/Samples/CommonSrc/Render/Render_XmlSceneLoader.cpp b/Samples/CommonSrc/Render/Render_XmlSceneLoader.cpp index b2b1ac1..5f31250 100644 --- a/Samples/CommonSrc/Render/Render_XmlSceneLoader.cpp +++ b/Samples/CommonSrc/Render/Render_XmlSceneLoader.cpp @@ -5,7 +5,7 @@ Content : Imports and exports XML files - implementation Created : January 21, 2013 Authors : Robotic Arm Software - Peter Hoff, Dan Goodman, Bryan Croteau -Copyright : Copyright 2013 Oculus VR, Inc. All Rights reserved. +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. @@ -121,6 +121,7 @@ bool XmlHandler::ReadFile(const char* fileName, OVR::Render::RenderDevice* pRend OVR_DEBUG_LOG_TEXT(("%i models remaining...", modelCount - i)); } Models.PushBack(*new Model(Prim_Triangles)); + const char* name = pXmlModel->Attribute("name"); bool isCollisionModel = false; pXmlModel->QueryBoolAttribute("isCollisionModel", &isCollisionModel); Models[i]->IsCollisionModel = isCollisionModel; @@ -129,6 +130,8 @@ bool XmlHandler::ReadFile(const char* fileName, OVR::Render::RenderDevice* pRend Models[i]->Visible = false; } + bool tree_c = (strcmp(name, "tree_C") == 0) || (strcmp(name, "Object03") == 0); + //read the vertices OVR::Array<Vector3f> *vertices = new OVR::Array<Vector3f>(); ParseVectorString(pXmlModel->FirstChildElement("vertices")->FirstChild()-> @@ -137,6 +140,11 @@ bool XmlHandler::ReadFile(const char* fileName, OVR::Render::RenderDevice* pRend for (unsigned int vertexIndex = 0; vertexIndex < vertices->GetSize(); ++vertexIndex) { vertices->At(vertexIndex).x *= -1.0f; + + if (tree_c) + { // Move the terrace tree closer to the house + vertices->At(vertexIndex).z += 0.5; + } } //read the normals @@ -237,6 +245,7 @@ bool XmlHandler::ReadFile(const char* fileName, OVR::Render::RenderDevice* pRend // Read the vertex indices for the triangles const char* indexStr = pXmlModel->FirstChildElement("indices")-> FirstChild()->ToText()->Value(); + UPInt stringLength = strlen(indexStr); for(UPInt j = 0; j < stringLength; ) @@ -306,6 +315,8 @@ bool XmlHandler::ReadFile(const char* fileName, OVR::Render::RenderDevice* pRend float D; pXmlPlane->QueryFloatAttribute("d", &D); D -= 0.5f; + if (i == 26) + D += 0.5f; // tighten the terrace collision so player can move right up to rail Planef p(norm.z, norm.y, norm.x * -1.0f, D); cm->Add(p); pXmlPlane = pXmlPlane->NextSiblingElement("plane"); diff --git a/Samples/CommonSrc/Render/Render_XmlSceneLoader.h b/Samples/CommonSrc/Render/Render_XmlSceneLoader.h index 694fc2e..7dff174 100644 --- a/Samples/CommonSrc/Render/Render_XmlSceneLoader.h +++ b/Samples/CommonSrc/Render/Render_XmlSceneLoader.h @@ -5,7 +5,7 @@ Content : Imports and exports XML files Created : January 21, 2013 Authors : Robotic Arm Software - Peter Hoff, Dan Goodman, Bryan Croteau -Copyright : Copyright 2013 Oculus VR, Inc. All Rights reserved. +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. |