aboutsummaryrefslogtreecommitdiffstats
path: root/Samples/CommonSrc/Render/Render_GL_Device.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Samples/CommonSrc/Render/Render_GL_Device.cpp')
-rw-r--r--Samples/CommonSrc/Render/Render_GL_Device.cpp1704
1 files changed, 855 insertions, 849 deletions
diff --git a/Samples/CommonSrc/Render/Render_GL_Device.cpp b/Samples/CommonSrc/Render/Render_GL_Device.cpp
index d2ba42e..aaf1f0e 100644
--- a/Samples/CommonSrc/Render/Render_GL_Device.cpp
+++ b/Samples/CommonSrc/Render/Render_GL_Device.cpp
@@ -1,849 +1,855 @@
-/************************************************************************************
-
-Filename : Render_GL_Device.cpp
-Content : RenderDevice implementation for OpenGL
-Created : September 10, 2012
-Authors : Andrew Reisse
-
-Copyright : Copyright 2012 Oculus VR, Inc. All Rights reserved.
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-
-************************************************************************************/
-
-#include "../Render/Render_GL_Device.h"
-#include "Kernel/OVR_Log.h"
-
-namespace OVR { namespace Render { namespace GL {
-
-
-
-static const char* StdVertexShaderSrc =
- "uniform mat4 Proj;\n"
- "uniform mat4 View;\n"
- "attribute vec4 Position;\n"
- "attribute vec4 Color;\n"
- "attribute vec2 TexCoord;\n"
- "attribute vec2 TexCoord1;\n"
- "attribute vec3 Normal;\n"
- "varying vec4 oColor;\n"
- "varying vec2 oTexCoord;\n"
- "varying vec2 oTexCoord1;\n"
- "varying vec3 oNormal;\n"
- "varying vec3 oVPos;\n"
- "void main()\n"
- "{\n"
- " gl_Position = Proj * (View * Position);\n"
- " oNormal = vec3(View * vec4(Normal,0));\n"
- " oVPos = vec3(View * Position);\n"
- " oTexCoord = TexCoord;\n"
- " oTexCoord1 = TexCoord1;\n"
- " oColor = Color;\n"
- "}\n";
-
-static const char* DirectVertexShaderSrc =
- "uniform mat4 View;\n"
- "attribute vec4 Position;\n"
- "attribute vec4 Color;\n"
- "attribute vec2 TexCoord;\n"
- "attribute vec3 Normal;\n"
- "varying vec4 oColor;\n"
- "varying vec2 oTexCoord;\n"
- "varying vec3 oNormal;\n"
- "void main()\n"
- "{\n"
- " gl_Position = View * Position;\n"
- " oTexCoord = TexCoord;\n"
- " oColor = Color;\n"
- " oNormal = vec3(View * vec4(Normal,0));\n"
- "}\n";
-
-static const char* SolidFragShaderSrc =
- "uniform vec4 Color;\n"
- "void main()\n"
- "{\n"
- " gl_FragColor = Color;\n"
- "}\n";
-
-static const char* GouraudFragShaderSrc =
- "varying vec4 oColor;\n"
- "void main()\n"
- "{\n"
- " gl_FragColor = oColor;\n"
- "}\n";
-
-static const char* TextureFragShaderSrc =
- "uniform sampler2D Texture0;\n"
- "varying vec4 oColor;\n"
- "varying vec2 oTexCoord;\n"
- "void main()\n"
- "{\n"
- " gl_FragColor = oColor * texture2D(Texture0, oTexCoord);\n"
- " if (gl_FragColor.a < 0.4)\n"
- " discard;\n"
- "}\n";
-
-#define LIGHTING_COMMON \
- "uniform vec3 Ambient;\n" \
- "uniform vec4 LightPos[8];\n" \
- "uniform vec4 LightColor[8];\n" \
- "uniform float LightCount;\n" \
- "varying vec4 oColor;\n" \
- "varying vec2 oTexCoord;\n" \
- "varying vec3 oNormal;\n" \
- "varying vec3 oVPos;\n" \
- "vec4 DoLight()\n" \
- "{\n" \
- " vec3 norm = normalize(oNormal);\n" \
- " vec3 light = Ambient;\n" \
- " for (int i = 0; i < int(LightCount); i++)\n" \
- " {\n" \
- " vec3 ltp = (LightPos[i].xyz - oVPos);\n" \
- " float ldist = length(ltp);\n" \
- " ltp = normalize(ltp);\n" \
- " light += clamp(LightColor[i].rgb * oColor.rgb * (dot(norm, ltp) / ldist), 0.0,1.0);\n" \
- " }\n" \
- " return vec4(light, oColor.a);\n" \
- "}\n"
-
-static const char* LitSolidFragShaderSrc =
- LIGHTING_COMMON
- "void main()\n"
- "{\n"
- " gl_FragColor = DoLight() * oColor;\n"
- "}\n";
-
-static const char* LitTextureFragShaderSrc =
- "uniform sampler2D Texture0;\n"
- LIGHTING_COMMON
- "void main()\n"
- "{\n"
- " gl_FragColor = DoLight() * texture2D(Texture0, oTexCoord);\n"
- "}\n";
-
-static const char* AlphaTextureFragShaderSrc =
- "uniform sampler2D Texture0;\n"
- "varying vec4 oColor;\n"
- "varying vec2 oTexCoord;\n"
- "void main()\n"
- "{\n"
- " gl_FragColor = oColor * vec4(1,1,1,texture2D(Texture0, oTexCoord).a);\n"
- "}\n";
-
-static const char* MultiTextureFragShaderSrc =
- "uniform sampler2D Texture0;\n"
- "uniform sampler2D Texture1;\n"
- "varying vec4 oColor;\n"
- "varying vec2 oTexCoord;\n"
- "varying vec2 oTexCoord1;\n"
- "void main()\n"
- "{\n"
- " vec4 color1 = texture2D(Texture0, oTexCoord);\n"
- " vec4 color2 = texture2D(Texture1, oTexCoord1);\n"
- " color2.rgb = color2.rgb * mix(1.9, 1.2, clamp(length(color2.rgb),0.0,1.0));\n"
- " color2 = color1 * color2;\n"
- " if (color2.a <= 0.6)\n"
- " discard;\n"
- " gl_FragColor = color2;\n"
- "}\n";
-
-static const char* PostProcessVertexShaderSrc =
- "uniform mat4 View;\n"
- "uniform mat4 Texm;\n"
- "attribute vec4 Position;\n"
- "attribute vec2 TexCoord;\n"
- "varying vec2 oTexCoord;\n"
- "void main()\n"
- "{\n"
- " gl_Position = View * Position;\n"
- " oTexCoord = vec2(Texm * vec4(TexCoord,0,1));\n"
- " oTexCoord.y = 1.0-oTexCoord.y;\n"
- "}\n";
-
-static const char* PostProcessFragShaderSrc =
- "uniform vec2 LensCenter;\n"
- "uniform vec2 ScreenCenter;\n"
- "uniform vec2 Scale;\n"
- "uniform vec2 ScaleIn;\n"
- "uniform vec4 HmdWarpParam;\n"
- "uniform sampler2D Texture0;\n"
- "varying vec2 oTexCoord;\n"
- "\n"
- "vec2 HmdWarp(vec2 in01)\n"
- "{\n"
- " vec2 theta = (in01 - LensCenter) * ScaleIn;\n" // Scales to [-1, 1]
- " float rSq = theta.x * theta.x + theta.y * theta.y;\n"
- " vec2 theta1 = theta * (HmdWarpParam.x + HmdWarpParam.y * rSq + "
- " HmdWarpParam.z * rSq * rSq + HmdWarpParam.w * rSq * rSq * rSq);\n"
- " return LensCenter + Scale * theta1;\n"
- "}\n"
- "void main()\n"
- "{\n"
- " vec2 tc = HmdWarp(oTexCoord);\n"
- " if (!all(equal(clamp(tc, ScreenCenter-vec2(0.25,0.5), ScreenCenter+vec2(0.25,0.5)), tc)))\n"
- " gl_FragColor = vec4(0);\n"
- " else\n"
- " gl_FragColor = texture2D(Texture0, tc);\n"
- "}\n";
-
-// Shader with lens distortion and chromatic aberration correction.
-static const char* PostProcessFullFragShaderSrc =
- "uniform vec2 LensCenter;\n"
- "uniform vec2 ScreenCenter;\n"
- "uniform vec2 Scale;\n"
- "uniform vec2 ScaleIn;\n"
- "uniform vec4 HmdWarpParam;\n"
- "uniform vec4 ChromAbParam;\n"
- "uniform sampler2D Texture0;\n"
- "varying vec2 oTexCoord;\n"
- "\n"
- // Scales input texture coordinates for distortion.
- // ScaleIn maps texture coordinates to Scales to ([-1, 1]), although top/bottom will be
- // larger due to aspect ratio.
- "void main()\n"
- "{\n"
- " vec2 theta = (oTexCoord - LensCenter) * ScaleIn;\n" // Scales to [-1, 1]
- " float rSq= theta.x * theta.x + theta.y * theta.y;\n"
- " vec2 theta1 = theta * (HmdWarpParam.x + HmdWarpParam.y * rSq + "
- " HmdWarpParam.z * rSq * rSq + HmdWarpParam.w * rSq * rSq * rSq);\n"
- " \n"
- " // Detect whether blue texture coordinates are out of range since these will scaled out the furthest.\n"
- " vec2 thetaBlue = theta1 * (ChromAbParam.z + ChromAbParam.w * rSq);\n"
- " vec2 tcBlue = LensCenter + Scale * thetaBlue;\n"
- " if (!all(equal(clamp(tcBlue, ScreenCenter-vec2(0.25,0.5), ScreenCenter+vec2(0.25,0.5)), tcBlue)))\n"
- " {\n"
- " gl_FragColor = vec4(0);\n"
- " return;\n"
- " }\n"
- " \n"
- " // Now do blue texture lookup.\n"
- " float blue = texture2D(Texture0, tcBlue).b;\n"
- " \n"
- " // Do green lookup (no scaling).\n"
- " vec2 tcGreen = LensCenter + Scale * theta1;\n"
- " vec4 center = texture2D(Texture0, tcGreen);\n"
- " \n"
- " // Do red scale and lookup.\n"
- " vec2 thetaRed = theta1 * (ChromAbParam.x + ChromAbParam.y * rSq);\n"
- " vec2 tcRed = LensCenter + Scale * thetaRed;\n"
- " float red = texture2D(Texture0, tcRed).r;\n"
- " \n"
- " gl_FragColor = vec4(red, center.g, blue, center.a);\n"
- "}\n";
-
-static const char* VShaderSrcs[VShader_Count] =
-{
- DirectVertexShaderSrc,
- StdVertexShaderSrc,
- PostProcessVertexShaderSrc
-};
-static const char* FShaderSrcs[FShader_Count] =
-{
- SolidFragShaderSrc,
- GouraudFragShaderSrc,
- TextureFragShaderSrc,
- AlphaTextureFragShaderSrc,
- PostProcessFragShaderSrc,
- PostProcessFullFragShaderSrc,
- LitSolidFragShaderSrc,
- LitTextureFragShaderSrc,
- MultiTextureFragShaderSrc
-};
-
-
-
-RenderDevice::RenderDevice(const RendererParams& p)
-{
- for (int i = 0; i < VShader_Count; i++)
- VertexShaders[i] = *new Shader(this, Shader_Vertex, VShaderSrcs[i]);
-
- for (int i = 0; i < FShader_Count; i++)
- FragShaders[i] = *new Shader(this, Shader_Fragment, FShaderSrcs[i]);
-
- Ptr<ShaderSet> gouraudShaders = *new ShaderSet();
- gouraudShaders->SetShader(VertexShaders[VShader_MVP]);
- gouraudShaders->SetShader(FragShaders[FShader_Gouraud]);
- DefaultFill = *new ShaderFill(gouraudShaders);
-
- glGenFramebuffersEXT(1, &CurrentFbo);
-}
-
-Shader *RenderDevice::LoadBuiltinShader(ShaderStage stage, int shader)
-{
- switch (stage)
- {
- case Shader_Vertex: return VertexShaders[shader];
- case Shader_Fragment: return FragShaders[shader];
- default:
- return NULL;
- }
-}
-
-
-void RenderDevice::BeginRendering()
-{
- glEnable(GL_DEPTH_TEST);
- glEnable(GL_CULL_FACE);
- glFrontFace(GL_CW);
-
- glLineWidth(3.0f);
- glEnable(GL_LINE_SMOOTH);
- glEnable(GL_BLEND);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
-
- glMatrixMode(GL_MODELVIEW);
- glLoadIdentity();
-}
-
-void RenderDevice::SetDepthMode(bool enable, bool write, CompareFunc func)
-{
- if (enable)
- {
- glEnable(GL_DEPTH_TEST);
- glDepthMask(write);
- switch (func)
- {
- case Compare_Always: glDepthFunc(GL_ALWAYS); break;
- case Compare_Less: glDepthFunc(GL_LESS); break;
- case Compare_Greater: glDepthFunc(GL_GREATER); break;
- default: assert(0);
- }
- }
- else
- glDisable(GL_DEPTH_TEST);
-}
-
-void RenderDevice::SetRealViewport(const Viewport& vp)
-{
- int wh;
- if (CurRenderTarget)
- wh = CurRenderTarget->Height;
- else
- wh = WindowHeight;
- glViewport(vp.x, wh-vp.y-vp.h, vp.w, vp.h);
-
- glEnable(GL_SCISSOR_TEST);
- glScissor(vp.x, wh-vp.y-vp.h, vp.w, vp.h);
-}
-
-void RenderDevice::Clear(float r, float g, float b, float a, float depth)
-{
- glClearColor(r,g,b,a);
- glClearDepth(depth);
- glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
-}
-
-RBuffer* RenderDevice::GetDepthBuffer(int w, int h, int ms)
-{
- for (unsigned i = 0; i < DepthBuffers.GetSize(); i++)
- if (w == DepthBuffers[i]->Width && h == DepthBuffers[i]->Height)// && ms == DepthBuffers[i]->Samples)
- return DepthBuffers[i];
-
- //Ptr<Texture> newDepth = *CreateTexture(Texture_Depth|Texture_RenderTarget|ms, w, h, NULL);
- Ptr<RBuffer> newDepth = *new RBuffer(GL_DEPTH24_STENCIL8, w, h); // combined depth stencil
- DepthBuffers.PushBack(newDepth);
- return newDepth.GetPtr();
-}
-
-void RenderDevice::SetRenderTarget(Render::Texture* color, Render::Texture*, Render::Texture* stencil)
-{
- OVR_UNUSED(stencil);
-
- CurRenderTarget = (Texture*)color;
- if (color == NULL)
- {
- glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
- return;
- }
- //if (depth == NULL)
- RBuffer* depth = GetDepthBuffer(color->GetWidth(), color->GetHeight(), 0); //CurRenderTarget->Samples);
-
- glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, CurrentFbo);
- glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, ((Texture*)color)->TexId, 0);
- if (depth)
- //glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_2D, ((Texture*)depth)->TexId, 0);
- glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, ((RBuffer*)depth)->BufId);
- else
- glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, 0);
-
- GLenum status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
- if (status != GL_FRAMEBUFFER_COMPLETE_EXT)
- OVR_DEBUG_LOG(("framebuffer not complete: %x", status));
-}
-
-
-void RenderDevice::SetWorldUniforms(const Matrix4f& proj)
-{
- Proj = proj.Transposed();
-}
-
-void RenderDevice::SetTexture(Render::ShaderStage, int slot, const Texture* t)
-{
- glActiveTexture(GL_TEXTURE0 + slot);
- glBindTexture(GL_TEXTURE_2D, ((Texture*)t)->TexId);
- glActiveTexture(GL_TEXTURE0);
-}
-
-Buffer* RenderDevice::CreateBuffer()
-{
- return new Buffer(this);
-}
-
-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
- if (!model->VertexBuffer)
- {
- Ptr<Render::Buffer> vb = *CreateBuffer();
- vb->Data(Buffer_Vertex, &model->Vertices[0], model->Vertices.GetSize() * sizeof(Vertex));
- model->VertexBuffer = vb;
- }
- if (!model->IndexBuffer)
- {
- Ptr<Render::Buffer> ib = *CreateBuffer();
- ib->Data(Buffer_Index, &model->Indices[0], model->Indices.GetSize() * 2);
- model->IndexBuffer = ib;
- }
-
- Render(model->Fill ? (const Fill*)model->Fill : (const Fill*)DefaultFill,
- model->VertexBuffer, model->IndexBuffer,
- matrix, 0, (int)model->Indices.GetSize(), model->GetPrimType());
-}
-
-void RenderDevice::Render(const Fill* fill, Render::Buffer* vertices, Render::Buffer* indices,
- const Matrix4f& matrix, int offset, int count, PrimitiveType rprim)
-{
- ShaderSet* shaders = (ShaderSet*) ((ShaderFill*)fill)->GetShaders();
-
- GLenum prim;
- switch (rprim)
- {
- case Prim_Triangles:
- prim = GL_TRIANGLES;
- break;
- case Prim_Lines:
- prim = GL_LINES;
- break;
- case Prim_TriangleStrip:
- prim = GL_TRIANGLE_STRIP;
- break;
- default:
- assert(0);
- return;
- }
-
- fill->Set();
- if (shaders->ProjLoc >= 0)
- glUniformMatrix4fv(shaders->ProjLoc, 1, 0, &Proj.M[0][0]);
- if (shaders->ViewLoc >= 0)
- glUniformMatrix4fv(shaders->ViewLoc, 1, 0, &matrix.Transposed().M[0][0]);
-
- if (shaders->UsesLighting && Lighting->Version != shaders->LightingVer)
- {
- shaders->LightingVer = Lighting->Version;
- Lighting->Set(shaders);
- }
-
- glBindBuffer(GL_ARRAY_BUFFER, ((Buffer*)vertices)->GLBuffer);
- for (int i = 0; i < 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));
-
- if (indices)
- {
- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ((Buffer*)indices)->GLBuffer);
- glDrawElements(prim, count, GL_UNSIGNED_SHORT, NULL);
- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
- }
- else
- {
- glDrawArrays(prim, 0, count);
- }
-
- for (int i = 0; i < 5; i++)
- glDisableVertexAttribArray(i);
-}
-
-void RenderDevice::RenderWithAlpha(const Fill* fill, Render::Buffer* vertices, Render::Buffer* indices,
- const Matrix4f& matrix, int offset, int count, PrimitiveType rprim)
-{
- //glEnable(GL_BLEND);
- Render(fill, vertices, indices, matrix, offset, count, rprim);
- //glDisable(GL_BLEND);
-}
-
-void RenderDevice::SetLighting(const LightingParams* lt)
-{
- Lighting = lt;
-}
-
-Buffer::~Buffer()
-{
- if (GLBuffer)
- glDeleteBuffers(1, &GLBuffer);
-}
-
-bool Buffer::Data(int use, const void* buffer, size_t size)
-{
- switch (use & Buffer_TypeMask)
- {
- case Buffer_Index: Use = GL_ELEMENT_ARRAY_BUFFER; break;
- default: Use = GL_ARRAY_BUFFER; break;
- }
-
- if (!GLBuffer)
- glGenBuffers(1, &GLBuffer);
-
- int mode = GL_DYNAMIC_DRAW;
- if (use & Buffer_ReadOnly)
- mode = GL_STATIC_DRAW;
-
- glBindBuffer(Use, GLBuffer);
- glBufferData(Use, size, buffer, mode);
- glBindBuffer(Use, 0);
- return 1;
-}
-
-void* Buffer::Map(size_t start, size_t size, int flags)
-{
- int mode = GL_WRITE_ONLY;
- //if (flags & Map_Unsynchronized)
- // mode |= GL_MAP_UNSYNCHRONIZED;
-
- glBindBuffer(Use, GLBuffer);
- void* v = glMapBuffer(Use, mode);
- glBindBuffer(Use, 0);
- return v;
-}
-
-bool Buffer::Unmap(void*)
-{
- glBindBuffer(Use, GLBuffer);
- int r = glUnmapBuffer(Use);
- glBindBuffer(Use, 0);
- return r;
-}
-
-bool Shader::Compile(const char* src)
-{
- if (!GLShader)
- GLShader = glCreateShader(GLStage());
-
- glShaderSource(GLShader, 1, &src, 0);
- glCompileShader(GLShader);
- GLint r;
- glGetShaderiv(GLShader, GL_COMPILE_STATUS, &r);
- if (!r)
- {
- GLchar msg[1024];
- glGetShaderInfoLog(GLShader, sizeof(msg), 0, msg);
- if (msg[0])
- OVR_DEBUG_LOG(("Compiling shader\n%s\nfailed: %s\n", src, msg));
- if (!r)
- return 0;
- }
- return 1;
-}
-
-ShaderSet::ShaderSet()
-{
- Prog = glCreateProgram();
-}
-ShaderSet::~ShaderSet()
-{
- glDeleteProgram(Prog);
-}
-
-bool ShaderSet::Link()
-{
- glBindAttribLocation(Prog, 0, "Position");
- glBindAttribLocation(Prog, 1, "Color");
- glBindAttribLocation(Prog, 2, "TexCoord");
- glBindAttribLocation(Prog, 3, "TexCoord1");
- glBindAttribLocation(Prog, 4, "Normal");
-
- glLinkProgram(Prog);
- GLint r;
- glGetProgramiv(Prog, GL_LINK_STATUS, &r);
- if (!r)
- {
- GLchar msg[1024];
- glGetProgramInfoLog(Prog, sizeof(msg), 0, msg);
- OVR_DEBUG_LOG(("Linking shaders failed: %s\n", msg));
- if (!r)
- return 0;
- }
- glUseProgram(Prog);
-
- UniformInfo.Clear();
- LightingVer = 0;
- UsesLighting = 0;
- GLuint i = 0;
- for(;; i++)
- {
- GLsizei namelen;
- GLint size = 0;
- GLenum type;
- GLchar name[32];
- glGetActiveUniform(Prog, i, sizeof(name), &namelen, &size, &type, name);
- if (size)
- {
- int l = glGetUniformLocation(Prog, name);
- char *np = name;
- while (*np)
- {
- if (*np == '[')
- *np = 0;
- np++;
- }
- Uniform u;
- u.Name = name;
- u.Location = l;
- u.Size = size;
- switch (type)
- {
- case GL_FLOAT: u.Type = 1; break;
- case GL_FLOAT_VEC2: u.Type = 2; break;
- case GL_FLOAT_VEC3: u.Type = 3; break;
- case GL_FLOAT_VEC4: u.Type = 4; break;
- case GL_FLOAT_MAT4: u.Type = 16; break;
- default:
- continue;
- }
- UniformInfo.PushBack(u);
- if (!strcmp(name, "LightCount"))
- UsesLighting = 1;
- }
- else
- break;
- }
-
- ProjLoc = glGetUniformLocation(Prog, "Proj");
- ViewLoc = glGetUniformLocation(Prog, "View");
- for (int i = 0; i < 8; i++)
- {
- char texv[32];
- sprintf(texv, "Texture%d", i);
- TexLoc[i] = glGetUniformLocation(Prog, texv);
- if (TexLoc[i] < 0)
- break;
-
- glUniform1i(TexLoc[i], i);
- }
- if (UsesLighting)
- OVR_ASSERT(ProjLoc >= 0 && ViewLoc >= 0);
- return 1;
-}
-
-void ShaderSet::Set(PrimitiveType) const
-{
- glUseProgram(Prog);
-}
-
-bool ShaderSet::SetUniform(const char* name, int n, const float* v)
-{
- for (int i = 0; i < UniformInfo.GetSize(); i++)
- if (!strcmp(UniformInfo[i].Name.ToCStr(), name))
- {
- OVR_ASSERT(UniformInfo[i].Location >= 0);
- glUseProgram(Prog);
- switch (UniformInfo[i].Type)
- {
- case 1: glUniform1fv(UniformInfo[i].Location, n, v); break;
- case 2: glUniform2fv(UniformInfo[i].Location, n/2, v); break;
- case 3: glUniform3fv(UniformInfo[i].Location, n/3, v); break;
- case 4: glUniform4fv(UniformInfo[i].Location, n/4, v); break;
- default: OVR_ASSERT(0);
- }
- return 1;
- }
-
- OVR_DEBUG_LOG(("Warning: uniform %s not present in selected shader", name));
- return 0;
-}
-
-bool ShaderSet::SetUniform4x4f(const char* name, const Matrix4f& m)
-{
- for (int i = 0; i < UniformInfo.GetSize(); i++)
- if (!strcmp(UniformInfo[i].Name.ToCStr(), name))
- {
- glUseProgram(Prog);
- glUniformMatrix4fv(UniformInfo[i].Location, 1, 1, &m.M[0][0]);
- return 1;
- }
-
- OVR_DEBUG_LOG(("Warning: uniform %s not present in selected shader", name));
- return 0;
-}
-
-Texture::Texture(RenderDevice* r, int w, int h) : Ren(r), Width(w), Height(h)
-{
- glGenTextures(1, &TexId);
-}
-
-Texture::~Texture()
-{
- if (TexId)
- glDeleteTextures(1, &TexId);
-}
-
-void Texture::Set(int slot, Render::ShaderStage stage) const
-{
- Ren->SetTexture(stage, slot, this);
-}
-
-void Texture::SetSampleMode(int sm)
-{
- glBindTexture(GL_TEXTURE_2D, TexId);
- switch (sm & Sample_FilterMask)
- {
- case Sample_Linear:
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 0);
- break;
-
- case Sample_Anisotropic:
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 8);
- break;
-
- case Sample_Nearest:
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 0);
- break;
- }
-
- switch (sm & Sample_AddressMask)
- {
- case Sample_Repeat:
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
- break;
-
- case Sample_Clamp:
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
- break;
-
- case Sample_ClampBorder:
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
- break;
- }
- glBindTexture(GL_TEXTURE_2D, 0);
-}
-
-Texture* RenderDevice::CreateTexture(int format, int width, int height, const void* data, int mipcount)
-{
- GLenum glformat, gltype = GL_UNSIGNED_BYTE;
- switch(format & Texture_TypeMask)
- {
- case Texture_RGBA: glformat = GL_RGBA; break;
- case Texture_R: glformat = GL_ALPHA; break;
- case Texture_Depth: glformat = GL_DEPTH; gltype = GL_DEPTH_COMPONENT; 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;
- default:
- return NULL;
- }
- Texture* NewTex = new Texture(this, width, height);
- glBindTexture(GL_TEXTURE_2D, NewTex->TexId);
- glGetError();
-
- if (format & Texture_Compressed)
- {
- const unsigned char* level = (const unsigned char*)data;
- int w = width, h = height;
- for (int i = 0; i < mipcount; i++)
- {
- int mipsize = GetTextureSize(format, w, h);
- glCompressedTexImage2D(GL_TEXTURE_2D, i, glformat, w, h, 0, mipsize, level);
-
- level += mipsize;
- w >>= 1;
- h >>= 1;
- if (w < 1) w = 1;
- if (h < 1) h = 1;
- }
- }
- else
- glTexImage2D(GL_TEXTURE_2D, 0, glformat, width, height, 0, glformat, gltype, data);
-
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
-
- if (format == (Texture_RGBA|Texture_GenMipmaps)) // not render target
- {
- int srcw = width, srch = height;
- int level = 0;
- UByte* mipmaps = NULL;
- do
- {
- level++;
- int mipw = srcw >> 1; if (mipw < 1) mipw = 1;
- int miph = srch >> 1; if (miph < 1) miph = 1;
- if (mipmaps == NULL)
- mipmaps = (UByte*)OVR_ALLOC(mipw * miph * 4);
- FilterRgba2x2(level == 1 ? (const UByte*)data : mipmaps, srcw, srch, mipmaps);
- glTexImage2D(GL_TEXTURE_2D, level, glformat, mipw, miph, 0, glformat, gltype, mipmaps);
- srcw = mipw;
- srch = miph;
- } while (srcw > 1 || srch > 1);
- if (mipmaps)
- OVR_FREE(mipmaps);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, level);
- }
- else
- {
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, mipcount-1);
- }
-
- OVR_ASSERT(!glGetError());
- glBindTexture(GL_TEXTURE_2D, 0);
- return NewTex;
-}
-
-RBuffer::RBuffer(GLenum format, GLint w, GLint h)
-{
- Width = w;
- Height = h;
- glGenRenderbuffersEXT(1, &BufId);
- glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, BufId);
- glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, format, w, h);
- glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0);
-}
-
-RBuffer::~RBuffer()
-{
- glDeleteRenderbuffersEXT(1, &BufId);
-}
-
-}}}
+/************************************************************************************
+
+Filename : Render_GL_Device.cpp
+Content : RenderDevice implementation for OpenGL
+Created : September 10, 2012
+Authors : Andrew Reisse
+
+Copyright : Copyright 2012 Oculus VR, Inc. All Rights reserved.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+************************************************************************************/
+
+#include "../Render/Render_GL_Device.h"
+#include "Kernel/OVR_Log.h"
+
+namespace OVR { namespace Render { namespace GL {
+
+
+
+static const char* StdVertexShaderSrc =
+ "uniform mat4 Proj;\n"
+ "uniform mat4 View;\n"
+ "attribute vec4 Position;\n"
+ "attribute vec4 Color;\n"
+ "attribute vec2 TexCoord;\n"
+ "attribute vec2 TexCoord1;\n"
+ "attribute vec3 Normal;\n"
+ "varying vec4 oColor;\n"
+ "varying vec2 oTexCoord;\n"
+ "varying vec2 oTexCoord1;\n"
+ "varying vec3 oNormal;\n"
+ "varying vec3 oVPos;\n"
+ "void main()\n"
+ "{\n"
+ " gl_Position = Proj * (View * Position);\n"
+ " oNormal = vec3(View * vec4(Normal,0));\n"
+ " oVPos = vec3(View * Position);\n"
+ " oTexCoord = TexCoord;\n"
+ " oTexCoord1 = TexCoord1;\n"
+ " oColor = Color;\n"
+ "}\n";
+
+static const char* DirectVertexShaderSrc =
+ "uniform mat4 View;\n"
+ "attribute vec4 Position;\n"
+ "attribute vec4 Color;\n"
+ "attribute vec2 TexCoord;\n"
+ "attribute vec3 Normal;\n"
+ "varying vec4 oColor;\n"
+ "varying vec2 oTexCoord;\n"
+ "varying vec3 oNormal;\n"
+ "void main()\n"
+ "{\n"
+ " gl_Position = View * Position;\n"
+ " oTexCoord = TexCoord;\n"
+ " oColor = Color;\n"
+ " oNormal = vec3(View * vec4(Normal,0));\n"
+ "}\n";
+
+static const char* SolidFragShaderSrc =
+ "uniform vec4 Color;\n"
+ "void main()\n"
+ "{\n"
+ " gl_FragColor = Color;\n"
+ "}\n";
+
+static const char* GouraudFragShaderSrc =
+ "varying vec4 oColor;\n"
+ "void main()\n"
+ "{\n"
+ " gl_FragColor = oColor;\n"
+ "}\n";
+
+static const char* TextureFragShaderSrc =
+ "uniform sampler2D Texture0;\n"
+ "varying vec4 oColor;\n"
+ "varying vec2 oTexCoord;\n"
+ "void main()\n"
+ "{\n"
+ " gl_FragColor = oColor * texture2D(Texture0, oTexCoord);\n"
+ " if (gl_FragColor.a < 0.4)\n"
+ " discard;\n"
+ "}\n";
+
+#define LIGHTING_COMMON \
+ "uniform vec3 Ambient;\n" \
+ "uniform vec4 LightPos[8];\n" \
+ "uniform vec4 LightColor[8];\n" \
+ "uniform float LightCount;\n" \
+ "varying vec4 oColor;\n" \
+ "varying vec2 oTexCoord;\n" \
+ "varying vec3 oNormal;\n" \
+ "varying vec3 oVPos;\n" \
+ "vec4 DoLight()\n" \
+ "{\n" \
+ " vec3 norm = normalize(oNormal);\n" \
+ " vec3 light = Ambient;\n" \
+ " for (int i = 0; i < int(LightCount); i++)\n" \
+ " {\n" \
+ " vec3 ltp = (LightPos[i].xyz - oVPos);\n" \
+ " float ldist = length(ltp);\n" \
+ " ltp = normalize(ltp);\n" \
+ " light += clamp(LightColor[i].rgb * oColor.rgb * (dot(norm, ltp) / ldist), 0.0,1.0);\n" \
+ " }\n" \
+ " return vec4(light, oColor.a);\n" \
+ "}\n"
+
+static const char* LitSolidFragShaderSrc =
+ LIGHTING_COMMON
+ "void main()\n"
+ "{\n"
+ " gl_FragColor = DoLight() * oColor;\n"
+ "}\n";
+
+static const char* LitTextureFragShaderSrc =
+ "uniform sampler2D Texture0;\n"
+ LIGHTING_COMMON
+ "void main()\n"
+ "{\n"
+ " gl_FragColor = DoLight() * texture2D(Texture0, oTexCoord);\n"
+ "}\n";
+
+static const char* AlphaTextureFragShaderSrc =
+ "uniform sampler2D Texture0;\n"
+ "varying vec4 oColor;\n"
+ "varying vec2 oTexCoord;\n"
+ "void main()\n"
+ "{\n"
+ " gl_FragColor = oColor * vec4(1,1,1,texture2D(Texture0, oTexCoord).a);\n"
+ "}\n";
+
+static const char* MultiTextureFragShaderSrc =
+ "uniform sampler2D Texture0;\n"
+ "uniform sampler2D Texture1;\n"
+ "varying vec4 oColor;\n"
+ "varying vec2 oTexCoord;\n"
+ "varying vec2 oTexCoord1;\n"
+ "void main()\n"
+ "{\n"
+ " vec4 color1 = texture2D(Texture0, oTexCoord);\n"
+ " vec4 color2 = texture2D(Texture1, oTexCoord1);\n"
+ " color2.rgb = color2.rgb * mix(1.9, 1.2, clamp(length(color2.rgb),0.0,1.0));\n"
+ " color2 = color1 * color2;\n"
+ " if (color2.a <= 0.6)\n"
+ " discard;\n"
+ " gl_FragColor = color2;\n"
+ "}\n";
+
+static const char* PostProcessVertexShaderSrc =
+ "uniform mat4 View;\n"
+ "uniform mat4 Texm;\n"
+ "attribute vec4 Position;\n"
+ "attribute vec2 TexCoord;\n"
+ "varying vec2 oTexCoord;\n"
+ "void main()\n"
+ "{\n"
+ " gl_Position = View * Position;\n"
+ " oTexCoord = vec2(Texm * vec4(TexCoord,0,1));\n"
+ " oTexCoord.y = 1.0-oTexCoord.y;\n"
+ "}\n";
+
+static const char* PostProcessFragShaderSrc =
+ "uniform vec2 LensCenter;\n"
+ "uniform vec2 ScreenCenter;\n"
+ "uniform vec2 Scale;\n"
+ "uniform vec2 ScaleIn;\n"
+ "uniform vec4 HmdWarpParam;\n"
+ "uniform sampler2D Texture0;\n"
+ "varying vec2 oTexCoord;\n"
+ "\n"
+ "vec2 HmdWarp(vec2 in01)\n"
+ "{\n"
+ " vec2 theta = (in01 - LensCenter) * ScaleIn;\n" // Scales to [-1, 1]
+ " float rSq = theta.x * theta.x + theta.y * theta.y;\n"
+ " vec2 theta1 = theta * (HmdWarpParam.x + HmdWarpParam.y * rSq + "
+ " HmdWarpParam.z * rSq * rSq + HmdWarpParam.w * rSq * rSq * rSq);\n"
+ " return LensCenter + Scale * theta1;\n"
+ "}\n"
+ "void main()\n"
+ "{\n"
+ " vec2 tc = HmdWarp(oTexCoord);\n"
+ " if (!all(equal(clamp(tc, ScreenCenter-vec2(0.25,0.5), ScreenCenter+vec2(0.25,0.5)), tc)))\n"
+ " gl_FragColor = vec4(0);\n"
+ " else\n"
+ " gl_FragColor = texture2D(Texture0, tc);\n"
+ "}\n";
+
+// Shader with lens distortion and chromatic aberration correction.
+static const char* PostProcessFullFragShaderSrc =
+ "uniform vec2 LensCenter;\n"
+ "uniform vec2 ScreenCenter;\n"
+ "uniform vec2 Scale;\n"
+ "uniform vec2 ScaleIn;\n"
+ "uniform vec4 HmdWarpParam;\n"
+ "uniform vec4 ChromAbParam;\n"
+ "uniform sampler2D Texture0;\n"
+ "varying vec2 oTexCoord;\n"
+ "\n"
+ // Scales input texture coordinates for distortion.
+ // ScaleIn maps texture coordinates to Scales to ([-1, 1]), although top/bottom will be
+ // larger due to aspect ratio.
+ "void main()\n"
+ "{\n"
+ " vec2 theta = (oTexCoord - LensCenter) * ScaleIn;\n" // Scales to [-1, 1]
+ " float rSq= theta.x * theta.x + theta.y * theta.y;\n"
+ " vec2 theta1 = theta * (HmdWarpParam.x + HmdWarpParam.y * rSq + "
+ " HmdWarpParam.z * rSq * rSq + HmdWarpParam.w * rSq * rSq * rSq);\n"
+ " \n"
+ " // Detect whether blue texture coordinates are out of range since these will scaled out the furthest.\n"
+ " vec2 thetaBlue = theta1 * (ChromAbParam.z + ChromAbParam.w * rSq);\n"
+ " vec2 tcBlue = LensCenter + Scale * thetaBlue;\n"
+ " if (!all(equal(clamp(tcBlue, ScreenCenter-vec2(0.25,0.5), ScreenCenter+vec2(0.25,0.5)), tcBlue)))\n"
+ " {\n"
+ " gl_FragColor = vec4(0);\n"
+ " return;\n"
+ " }\n"
+ " \n"
+ " // Now do blue texture lookup.\n"
+ " float blue = texture2D(Texture0, tcBlue).b;\n"
+ " \n"
+ " // Do green lookup (no scaling).\n"
+ " vec2 tcGreen = LensCenter + Scale * theta1;\n"
+ " vec4 center = texture2D(Texture0, tcGreen);\n"
+ " \n"
+ " // Do red scale and lookup.\n"
+ " vec2 thetaRed = theta1 * (ChromAbParam.x + ChromAbParam.y * rSq);\n"
+ " vec2 tcRed = LensCenter + Scale * thetaRed;\n"
+ " float red = texture2D(Texture0, tcRed).r;\n"
+ " \n"
+ " gl_FragColor = vec4(red, center.g, blue, center.a);\n"
+ "}\n";
+
+static const char* VShaderSrcs[VShader_Count] =
+{
+ DirectVertexShaderSrc,
+ StdVertexShaderSrc,
+ PostProcessVertexShaderSrc
+};
+static const char* FShaderSrcs[FShader_Count] =
+{
+ SolidFragShaderSrc,
+ GouraudFragShaderSrc,
+ TextureFragShaderSrc,
+ AlphaTextureFragShaderSrc,
+ PostProcessFragShaderSrc,
+ PostProcessFullFragShaderSrc,
+ LitSolidFragShaderSrc,
+ LitTextureFragShaderSrc,
+ MultiTextureFragShaderSrc
+};
+
+
+
+RenderDevice::RenderDevice(const RendererParams& p)
+{
+ for (int i = 0; i < VShader_Count; i++)
+ VertexShaders[i] = *new Shader(this, Shader_Vertex, VShaderSrcs[i]);
+
+ for (int i = 0; i < FShader_Count; i++)
+ FragShaders[i] = *new Shader(this, Shader_Fragment, FShaderSrcs[i]);
+
+ Ptr<ShaderSet> gouraudShaders = *new ShaderSet();
+ gouraudShaders->SetShader(VertexShaders[VShader_MVP]);
+ gouraudShaders->SetShader(FragShaders[FShader_Gouraud]);
+ DefaultFill = *new ShaderFill(gouraudShaders);
+
+ glGenFramebuffersEXT(1, &CurrentFbo);
+}
+
+Shader *RenderDevice::LoadBuiltinShader(ShaderStage stage, int shader)
+{
+ switch (stage)
+ {
+ case Shader_Vertex: return VertexShaders[shader];
+ case Shader_Fragment: return FragShaders[shader];
+ default:
+ return NULL;
+ }
+}
+
+
+void RenderDevice::BeginRendering()
+{
+ glEnable(GL_DEPTH_TEST);
+ glEnable(GL_CULL_FACE);
+ glFrontFace(GL_CW);
+
+ glLineWidth(3.0f);
+ glEnable(GL_LINE_SMOOTH);
+ glEnable(GL_BLEND);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+
+ glMatrixMode(GL_MODELVIEW);
+ glLoadIdentity();
+}
+
+void RenderDevice::SetDepthMode(bool enable, bool write, CompareFunc func)
+{
+ if (enable)
+ {
+ glEnable(GL_DEPTH_TEST);
+ glDepthMask(write);
+ switch (func)
+ {
+ case Compare_Always: glDepthFunc(GL_ALWAYS); break;
+ case Compare_Less: glDepthFunc(GL_LESS); break;
+ case Compare_Greater: glDepthFunc(GL_GREATER); break;
+ default: assert(0);
+ }
+ }
+ else
+ glDisable(GL_DEPTH_TEST);
+}
+
+void RenderDevice::SetRealViewport(const Viewport& vp)
+{
+ int wh;
+ if (CurRenderTarget)
+ wh = CurRenderTarget->Height;
+ else
+ wh = WindowHeight;
+ glViewport(vp.x, wh-vp.y-vp.h, vp.w, vp.h);
+
+ glEnable(GL_SCISSOR_TEST);
+ glScissor(vp.x, wh-vp.y-vp.h, vp.w, vp.h);
+}
+
+void RenderDevice::Clear(float r, float g, float b, float a, float depth)
+{
+ glClearColor(r,g,b,a);
+ glClearDepth(depth);
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
+}
+
+RBuffer* RenderDevice::GetDepthBuffer(int w, int h, int ms)
+{
+ for (unsigned i = 0; i < DepthBuffers.GetSize(); i++)
+ if (w == DepthBuffers[i]->Width && h == DepthBuffers[i]->Height)// && ms == DepthBuffers[i]->Samples)
+ return DepthBuffers[i];
+
+ //Ptr<Texture> newDepth = *CreateTexture(Texture_Depth|Texture_RenderTarget|ms, w, h, NULL);
+ Ptr<RBuffer> newDepth = *new RBuffer(GL_DEPTH24_STENCIL8, w, h); // combined depth stencil
+ DepthBuffers.PushBack(newDepth);
+ return newDepth.GetPtr();
+}
+
+void RenderDevice::SetRenderTarget(Render::Texture* color, Render::Texture*, Render::Texture* stencil)
+{
+ OVR_UNUSED(stencil);
+
+ CurRenderTarget = (Texture*)color;
+ if (color == NULL)
+ {
+ glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
+ return;
+ }
+ //if (depth == NULL)
+ RBuffer* depth = GetDepthBuffer(color->GetWidth(), color->GetHeight(), 0); //CurRenderTarget->Samples);
+
+ glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, CurrentFbo);
+ glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, ((Texture*)color)->TexId, 0);
+ if (depth)
+ //glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_2D, ((Texture*)depth)->TexId, 0);
+ glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, ((RBuffer*)depth)->BufId);
+ else
+ glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, 0);
+
+ GLenum status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
+ if (status != GL_FRAMEBUFFER_COMPLETE_EXT)
+ OVR_DEBUG_LOG(("framebuffer not complete: %x", status));
+}
+
+
+void RenderDevice::SetWorldUniforms(const Matrix4f& proj)
+{
+ Proj = proj.Transposed();
+}
+
+void RenderDevice::SetTexture(Render::ShaderStage, int slot, const Texture* t)
+{
+ glActiveTexture(GL_TEXTURE0 + slot);
+ glBindTexture(GL_TEXTURE_2D, ((Texture*)t)->TexId);
+ glActiveTexture(GL_TEXTURE0);
+}
+
+Buffer* RenderDevice::CreateBuffer()
+{
+ return new Buffer(this);
+}
+
+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
+ if (!model->VertexBuffer)
+ {
+ Ptr<Render::Buffer> vb = *CreateBuffer();
+ vb->Data(Buffer_Vertex, &model->Vertices[0], model->Vertices.GetSize() * sizeof(Vertex));
+ model->VertexBuffer = vb;
+ }
+ if (!model->IndexBuffer)
+ {
+ Ptr<Render::Buffer> ib = *CreateBuffer();
+ ib->Data(Buffer_Index, &model->Indices[0], model->Indices.GetSize() * 2);
+ model->IndexBuffer = ib;
+ }
+
+ Render(model->Fill ? (const Fill*)model->Fill : (const Fill*)DefaultFill,
+ model->VertexBuffer, model->IndexBuffer,
+ matrix, 0, (int)model->Indices.GetSize(), model->GetPrimType());
+}
+
+void RenderDevice::Render(const Fill* fill, Render::Buffer* vertices, Render::Buffer* indices,
+ const Matrix4f& matrix, int offset, int count, PrimitiveType rprim)
+{
+ ShaderSet* shaders = (ShaderSet*) ((ShaderFill*)fill)->GetShaders();
+
+ GLenum prim;
+ switch (rprim)
+ {
+ case Prim_Triangles:
+ prim = GL_TRIANGLES;
+ break;
+ case Prim_Lines:
+ prim = GL_LINES;
+ break;
+ case Prim_TriangleStrip:
+ prim = GL_TRIANGLE_STRIP;
+ break;
+ default:
+ assert(0);
+ return;
+ }
+
+ fill->Set();
+ if (shaders->ProjLoc >= 0)
+ glUniformMatrix4fv(shaders->ProjLoc, 1, 0, &Proj.M[0][0]);
+ if (shaders->ViewLoc >= 0)
+ glUniformMatrix4fv(shaders->ViewLoc, 1, 0, &matrix.Transposed().M[0][0]);
+
+ if (shaders->UsesLighting && Lighting->Version != shaders->LightingVer)
+ {
+ shaders->LightingVer = Lighting->Version;
+ Lighting->Set(shaders);
+ }
+
+ glBindBuffer(GL_ARRAY_BUFFER, ((Buffer*)vertices)->GLBuffer);
+ for (int i = 0; i < 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));
+
+ if (indices)
+ {
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ((Buffer*)indices)->GLBuffer);
+ glDrawElements(prim, count, GL_UNSIGNED_SHORT, NULL);
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
+ }
+ else
+ {
+ glDrawArrays(prim, 0, count);
+ }
+
+ for (int i = 0; i < 5; i++)
+ glDisableVertexAttribArray(i);
+}
+
+void RenderDevice::RenderWithAlpha(const Fill* fill, Render::Buffer* vertices, Render::Buffer* indices,
+ const Matrix4f& matrix, int offset, int count, PrimitiveType rprim)
+{
+ //glEnable(GL_BLEND);
+ Render(fill, vertices, indices, matrix, offset, count, rprim);
+ //glDisable(GL_BLEND);
+}
+
+void RenderDevice::SetLighting(const LightingParams* lt)
+{
+ Lighting = lt;
+}
+
+Buffer::~Buffer()
+{
+ if (GLBuffer)
+ glDeleteBuffers(1, &GLBuffer);
+}
+
+bool Buffer::Data(int use, const void* buffer, size_t size)
+{
+ switch (use & Buffer_TypeMask)
+ {
+ case Buffer_Index: Use = GL_ELEMENT_ARRAY_BUFFER; break;
+ default: Use = GL_ARRAY_BUFFER; break;
+ }
+
+ if (!GLBuffer)
+ glGenBuffers(1, &GLBuffer);
+
+ int mode = GL_DYNAMIC_DRAW;
+ if (use & Buffer_ReadOnly)
+ mode = GL_STATIC_DRAW;
+
+ glBindBuffer(Use, GLBuffer);
+ glBufferData(Use, size, buffer, mode);
+ glBindBuffer(Use, 0);
+ return 1;
+}
+
+void* Buffer::Map(size_t start, size_t size, int flags)
+{
+ int mode = GL_WRITE_ONLY;
+ //if (flags & Map_Unsynchronized)
+ // mode |= GL_MAP_UNSYNCHRONIZED;
+
+ glBindBuffer(Use, GLBuffer);
+ void* v = glMapBuffer(Use, mode);
+ glBindBuffer(Use, 0);
+ return v;
+}
+
+bool Buffer::Unmap(void*)
+{
+ glBindBuffer(Use, GLBuffer);
+ int r = glUnmapBuffer(Use);
+ glBindBuffer(Use, 0);
+ return r;
+}
+
+bool Shader::Compile(const char* src)
+{
+ if (!GLShader)
+ GLShader = glCreateShader(GLStage());
+
+ glShaderSource(GLShader, 1, &src, 0);
+ glCompileShader(GLShader);
+ GLint r;
+ glGetShaderiv(GLShader, GL_COMPILE_STATUS, &r);
+ if (!r)
+ {
+ GLchar msg[1024];
+ glGetShaderInfoLog(GLShader, sizeof(msg), 0, msg);
+ if (msg[0])
+ OVR_DEBUG_LOG(("Compiling shader\n%s\nfailed: %s\n", src, msg));
+ if (!r)
+ return 0;
+ }
+ return 1;
+}
+
+ShaderSet::ShaderSet()
+{
+ Prog = glCreateProgram();
+}
+ShaderSet::~ShaderSet()
+{
+ glDeleteProgram(Prog);
+}
+
+bool ShaderSet::Link()
+{
+ glBindAttribLocation(Prog, 0, "Position");
+ glBindAttribLocation(Prog, 1, "Color");
+ glBindAttribLocation(Prog, 2, "TexCoord");
+ glBindAttribLocation(Prog, 3, "TexCoord1");
+ glBindAttribLocation(Prog, 4, "Normal");
+
+ glLinkProgram(Prog);
+ GLint r;
+ glGetProgramiv(Prog, GL_LINK_STATUS, &r);
+ if (!r)
+ {
+ GLchar msg[1024];
+ glGetProgramInfoLog(Prog, sizeof(msg), 0, msg);
+ OVR_DEBUG_LOG(("Linking shaders failed: %s\n", msg));
+ if (!r)
+ return 0;
+ }
+ glUseProgram(Prog);
+
+ UniformInfo.Clear();
+ LightingVer = 0;
+ UsesLighting = 0;
+ GLuint i = 0;
+ for(;; i++)
+ {
+ GLsizei namelen;
+ GLint size = 0;
+ GLenum type;
+ GLchar name[32];
+ glGetActiveUniform(Prog, i, sizeof(name), &namelen, &size, &type, name);
+ if (size)
+ {
+ int l = glGetUniformLocation(Prog, name);
+ char *np = name;
+ while (*np)
+ {
+ if (*np == '[')
+ *np = 0;
+ np++;
+ }
+ Uniform u;
+ u.Name = name;
+ u.Location = l;
+ u.Size = size;
+ switch (type)
+ {
+ case GL_FLOAT: u.Type = 1; break;
+ case GL_FLOAT_VEC2: u.Type = 2; break;
+ case GL_FLOAT_VEC3: u.Type = 3; break;
+ case GL_FLOAT_VEC4: u.Type = 4; break;
+ case GL_FLOAT_MAT4: u.Type = 16; break;
+ default:
+ continue;
+ }
+ UniformInfo.PushBack(u);
+ if (!strcmp(name, "LightCount"))
+ UsesLighting = 1;
+ }
+ else
+ break;
+ }
+
+ ProjLoc = glGetUniformLocation(Prog, "Proj");
+ ViewLoc = glGetUniformLocation(Prog, "View");
+ for (int i = 0; i < 8; i++)
+ {
+ char texv[32];
+ sprintf(texv, "Texture%d", i);
+ TexLoc[i] = glGetUniformLocation(Prog, texv);
+ if (TexLoc[i] < 0)
+ break;
+
+ glUniform1i(TexLoc[i], i);
+ }
+ if (UsesLighting)
+ OVR_ASSERT(ProjLoc >= 0 && ViewLoc >= 0);
+ return 1;
+}
+
+void ShaderSet::Set(PrimitiveType) const
+{
+ glUseProgram(Prog);
+}
+
+bool ShaderSet::SetUniform(const char* name, int n, const float* v)
+{
+ for (int i = 0; i < UniformInfo.GetSize(); i++)
+ if (!strcmp(UniformInfo[i].Name.ToCStr(), name))
+ {
+ OVR_ASSERT(UniformInfo[i].Location >= 0);
+ glUseProgram(Prog);
+ switch (UniformInfo[i].Type)
+ {
+ case 1: glUniform1fv(UniformInfo[i].Location, n, v); break;
+ case 2: glUniform2fv(UniformInfo[i].Location, n/2, v); break;
+ case 3: glUniform3fv(UniformInfo[i].Location, n/3, v); break;
+ case 4: glUniform4fv(UniformInfo[i].Location, n/4, v); break;
+ default: OVR_ASSERT(0);
+ }
+ return 1;
+ }
+
+ OVR_DEBUG_LOG(("Warning: uniform %s not present in selected shader", name));
+ return 0;
+}
+
+bool ShaderSet::SetUniform4x4f(const char* name, const Matrix4f& m)
+{
+ for (int i = 0; i < UniformInfo.GetSize(); i++)
+ if (!strcmp(UniformInfo[i].Name.ToCStr(), name))
+ {
+ glUseProgram(Prog);
+ glUniformMatrix4fv(UniformInfo[i].Location, 1, 1, &m.M[0][0]);
+ return 1;
+ }
+
+ OVR_DEBUG_LOG(("Warning: uniform %s not present in selected shader", name));
+ return 0;
+}
+
+Texture::Texture(RenderDevice* r, int w, int h) : Ren(r), Width(w), Height(h)
+{
+ glGenTextures(1, &TexId);
+}
+
+Texture::~Texture()
+{
+ if (TexId)
+ glDeleteTextures(1, &TexId);
+}
+
+void Texture::Set(int slot, Render::ShaderStage stage) const
+{
+ Ren->SetTexture(stage, slot, this);
+}
+
+void Texture::SetSampleMode(int sm)
+{
+ glBindTexture(GL_TEXTURE_2D, TexId);
+ switch (sm & Sample_FilterMask)
+ {
+ case Sample_Linear:
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 0);
+ break;
+
+ case Sample_Anisotropic:
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 8);
+ break;
+
+ case Sample_Nearest:
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 0);
+ break;
+ }
+
+ switch (sm & Sample_AddressMask)
+ {
+ case Sample_Repeat:
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
+ break;
+
+ case Sample_Clamp:
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+ break;
+
+ case Sample_ClampBorder:
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
+ break;
+ }
+ glBindTexture(GL_TEXTURE_2D, 0);
+}
+
+Texture* RenderDevice::CreateTexture(int format, int width, int height, const void* data, int mipcount)
+{
+ GLenum glformat, gltype = GL_UNSIGNED_BYTE;
+ switch(format & Texture_TypeMask)
+ {
+ case Texture_RGBA: glformat = GL_RGBA; break;
+ case Texture_R: glformat = GL_ALPHA; break;
+ case Texture_Depth: glformat = GL_DEPTH; gltype = GL_DEPTH_COMPONENT; 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;
+ default:
+ return NULL;
+ }
+ Texture* NewTex = new Texture(this, width, height);
+ glBindTexture(GL_TEXTURE_2D, NewTex->TexId);
+ glGetError();
+
+ if (format & Texture_Compressed)
+ {
+ const unsigned char* level = (const unsigned char*)data;
+ int w = width, h = height;
+ for (int i = 0; i < mipcount; i++)
+ {
+ int mipsize = GetTextureSize(format, w, h);
+ glCompressedTexImage2D(GL_TEXTURE_2D, i, glformat, w, h, 0, mipsize, level);
+
+ level += mipsize;
+ w >>= 1;
+ h >>= 1;
+ if (w < 1) w = 1;
+ if (h < 1) h = 1;
+ }
+ }
+ else
+ glTexImage2D(GL_TEXTURE_2D, 0, glformat, width, height, 0, glformat, gltype, data);
+
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+
+ if (format == (Texture_RGBA|Texture_GenMipmaps)) // not render target
+ {
+ int srcw = width, srch = height;
+ int level = 0;
+ UByte* mipmaps = NULL;
+ do
+ {
+ level++;
+ int mipw = srcw >> 1; if (mipw < 1) mipw = 1;
+ int miph = srch >> 1; if (miph < 1) miph = 1;
+ if (mipmaps == NULL)
+ mipmaps = (UByte*)OVR_ALLOC(mipw * miph * 4);
+ FilterRgba2x2(level == 1 ? (const UByte*)data : mipmaps, srcw, srch, mipmaps);
+ glTexImage2D(GL_TEXTURE_2D, level, glformat, mipw, miph, 0, glformat, gltype, mipmaps);
+ srcw = mipw;
+ srch = miph;
+ } while (srcw > 1 || srch > 1);
+ if (mipmaps)
+ OVR_FREE(mipmaps);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, level);
+ }
+ else
+ {
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, mipcount-1);
+ }
+
+ OVR_ASSERT(!glGetError());
+ glBindTexture(GL_TEXTURE_2D, 0);
+ return NewTex;
+}
+
+bool RenderDevice::SetFullscreen(DisplayMode fullscreen)
+{
+ Params.Fullscreen = fullscreen;
+ return true;
+}
+
+RBuffer::RBuffer(GLenum format, GLint w, GLint h)
+{
+ Width = w;
+ Height = h;
+ glGenRenderbuffersEXT(1, &BufId);
+ glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, BufId);
+ glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, format, w, h);
+ glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0);
+}
+
+RBuffer::~RBuffer()
+{
+ glDeleteRenderbuffersEXT(1, &BufId);
+}
+
+}}}