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/Render_Device.cpp | |
parent | f28388ff2af14b56ef2d973b2f4f9da021716d4c (diff) |
Adding windows 0.3.1 SDK
Diffstat (limited to 'Samples/CommonSrc/Render/Render_Device.cpp')
-rw-r--r-- | Samples/CommonSrc/Render/Render_Device.cpp | 2306 |
1 files changed, 1292 insertions, 1014 deletions
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; + } }} |