Render_GL_Device.cpp
Go to the documentation of this file.
00001 /************************************************************************************
00002 
00003 Filename    :   Render_GL_Device.cpp
00004 Content     :   RenderDevice implementation for OpenGL
00005 Created     :   September 10, 2012
00006 Authors     :   Andrew Reisse
00007 
00008 Copyright   :   Copyright 2012 Oculus VR, Inc. All Rights reserved.
00009 
00010 Licensed under the Apache License, Version 2.0 (the "License");
00011 you may not use this file except in compliance with the License.
00012 You may obtain a copy of the License at
00013 
00014 http://www.apache.org/licenses/LICENSE-2.0
00015 
00016 Unless required by applicable law or agreed to in writing, software
00017 distributed under the License is distributed on an "AS IS" BASIS,
00018 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00019 See the License for the specific language governing permissions and
00020 limitations under the License.
00021 
00022 ************************************************************************************/
00023 
00024 #include "../Render/Render_GL_Device.h"
00025 #include "Kernel/OVR_Log.h"
00026 
00027 namespace OVR { namespace Render { namespace GL {
00028 
00029 
00030 
00031 static const char* StdVertexShaderSrc =
00032     "uniform mat4 Proj;\n"
00033     "uniform mat4 View;\n"
00034     "attribute vec4 Position;\n"
00035     "attribute vec4 Color;\n"
00036     "attribute vec2 TexCoord;\n"
00037     "attribute vec2 TexCoord1;\n"
00038     "attribute vec3 Normal;\n"
00039     "varying  vec4 oColor;\n"
00040     "varying  vec2 oTexCoord;\n"
00041     "varying  vec2 oTexCoord1;\n"
00042     "varying  vec3 oNormal;\n"
00043     "varying  vec3 oVPos;\n"
00044     "void main()\n"
00045     "{\n"
00046     "   gl_Position = Proj * (View * Position);\n"
00047     "   oNormal = vec3(View * vec4(Normal,0));\n"
00048     "   oVPos = vec3(View * Position);\n"
00049     "   oTexCoord = TexCoord;\n"
00050     "   oTexCoord1 = TexCoord1;\n"
00051     "   oColor = Color;\n"
00052     "}\n";
00053 
00054 static const char* DirectVertexShaderSrc =
00055     "uniform mat4 View;\n"
00056     "attribute vec4 Position;\n"
00057     "attribute vec4 Color;\n"
00058     "attribute vec2 TexCoord;\n"
00059     "attribute vec3 Normal;\n"
00060     "varying  vec4 oColor;\n"
00061     "varying  vec2 oTexCoord;\n"
00062     "varying  vec3 oNormal;\n"
00063     "void main()\n"
00064     "{\n"
00065     "   gl_Position = View * Position;\n"
00066     "   oTexCoord = TexCoord;\n"
00067     "   oColor = Color;\n"
00068     "   oNormal = vec3(View * vec4(Normal,0));\n"
00069     "}\n";
00070 
00071 static const char* SolidFragShaderSrc =
00072     "uniform vec4 Color;\n"
00073     "void main()\n"
00074     "{\n"
00075     "   gl_FragColor = Color;\n"
00076     "}\n";
00077 
00078 static const char* GouraudFragShaderSrc =
00079     "varying vec4 oColor;\n"
00080     "void main()\n"
00081     "{\n"
00082     "   gl_FragColor = oColor;\n"
00083     "}\n";
00084 
00085 static const char* TextureFragShaderSrc =
00086     "uniform sampler2D Texture0;\n"
00087     "varying vec4 oColor;\n"
00088     "varying vec2 oTexCoord;\n"
00089     "void main()\n"
00090     "{\n"
00091     "   gl_FragColor = oColor * texture2D(Texture0, oTexCoord);\n"
00092     "   if (gl_FragColor.a < 0.4)\n"
00093     "       discard;\n"
00094     "}\n";
00095 
00096 #define LIGHTING_COMMON                                                 \
00097     "uniform   vec3 Ambient;\n"                                               \
00098     "uniform   vec4 LightPos[8];\n"                                           \
00099     "uniform   vec4 LightColor[8];\n"                                         \
00100     "uniform   float LightCount;\n"                                          \
00101     "varying   vec4 oColor;\n"                                                  \
00102     "varying   vec2 oTexCoord;\n"                                               \
00103     "varying   vec3 oNormal;\n"                                                 \
00104     "varying   vec3 oVPos;\n"                                                   \
00105     "vec4 DoLight()\n"                                        \
00106     "{\n"                                                               \
00107     "   vec3 norm = normalize(oNormal);\n"                             \
00108     "   vec3 light = Ambient;\n"                                        \
00109     "   for (int i = 0; i < int(LightCount); i++)\n"                \
00110     "   {\n"                                                            \
00111     "       vec3 ltp = (LightPos[i].xyz - oVPos);\n"              \
00112     "       float  ldist = length(ltp);\n"                             \
00113     "       ltp = normalize(ltp);\n"                             \
00114     "       light += clamp(LightColor[i].rgb * oColor.rgb * (dot(norm, ltp) / ldist), 0.0,1.0);\n" \
00115     "   }\n"                                                            \
00116     "   return vec4(light, oColor.a);\n"                               \
00117     "}\n"
00118 
00119 static const char* LitSolidFragShaderSrc =
00120     LIGHTING_COMMON
00121     "void main()\n"
00122     "{\n"
00123     "   gl_FragColor = DoLight() * oColor;\n"
00124     "}\n";
00125 
00126 static const char* LitTextureFragShaderSrc =
00127     "uniform sampler2D Texture0;\n"
00128     LIGHTING_COMMON
00129     "void main()\n"
00130     "{\n"
00131     "   gl_FragColor = DoLight() * texture2D(Texture0, oTexCoord);\n"
00132     "}\n";
00133 
00134 static const char* AlphaTextureFragShaderSrc =
00135     "uniform sampler2D Texture0;\n"
00136     "varying vec4 oColor;\n"
00137     "varying vec2 oTexCoord;\n"
00138     "void main()\n"
00139     "{\n"
00140     "   gl_FragColor = oColor * vec4(1,1,1,texture2D(Texture0, oTexCoord).a);\n"
00141     "}\n";
00142 
00143 static const char* MultiTextureFragShaderSrc =
00144     "uniform sampler2D Texture0;\n"
00145     "uniform sampler2D Texture1;\n"
00146     "varying vec4 oColor;\n"
00147     "varying vec2 oTexCoord;\n"
00148     "varying vec2 oTexCoord1;\n"
00149     "void main()\n"
00150     "{\n"
00151         "       vec4 color1 = texture2D(Texture0, oTexCoord);\n"
00152         "       vec4 color2 = texture2D(Texture1, oTexCoord1);\n"
00153         "       color2.rgb = color2.rgb * mix(1.9, 1.2, clamp(length(color2.rgb),0.0,1.0));\n"
00154         "       color2 = color1 * color2;\n"
00155         "   if (color2.a <= 0.6)\n"
00156         "               discard;\n"
00157         "       gl_FragColor = color2;\n"
00158     "}\n";
00159 
00160 static const char* PostProcessVertexShaderSrc =
00161     "uniform mat4 View;\n"
00162     "uniform mat4 Texm;\n"
00163     "attribute vec4 Position;\n"
00164     "attribute vec2 TexCoord;\n"
00165     "varying  vec2 oTexCoord;\n"
00166     "void main()\n"
00167     "{\n"
00168     "   gl_Position = View * Position;\n"
00169     "   oTexCoord = vec2(Texm * vec4(TexCoord,0,1));\n"
00170     "   oTexCoord.y = 1.0-oTexCoord.y;\n"
00171     "}\n";
00172 
00173 static const char* PostProcessFragShaderSrc =
00174     "uniform vec2 LensCenter;\n"
00175     "uniform vec2 ScreenCenter;\n"
00176     "uniform vec2 Scale;\n"
00177     "uniform vec2 ScaleIn;\n"
00178     "uniform vec4 HmdWarpParam;\n"
00179     "uniform sampler2D Texture0;\n"
00180     "varying vec2 oTexCoord;\n"
00181     "\n"
00182     "vec2 HmdWarp(vec2 in01)\n"
00183     "{\n"
00184     "   vec2  theta = (in01 - LensCenter) * ScaleIn;\n" // Scales to [-1, 1]
00185     "   float rSq = theta.x * theta.x + theta.y * theta.y;\n"
00186     "   vec2  theta1 = theta * (HmdWarpParam.x + HmdWarpParam.y * rSq + "
00187     "                           HmdWarpParam.z * rSq * rSq + HmdWarpParam.w * rSq * rSq * rSq);\n"
00188     "   return LensCenter + Scale * theta1;\n"
00189     "}\n"
00190     "void main()\n"
00191     "{\n"
00192     "   vec2 tc = HmdWarp(oTexCoord);\n"
00193     "   if (!all(equal(clamp(tc, ScreenCenter-vec2(0.25,0.5), ScreenCenter+vec2(0.25,0.5)), tc)))\n"
00194     "       gl_FragColor = vec4(0);\n"
00195     "   else\n"
00196     "       gl_FragColor = texture2D(Texture0, tc);\n"
00197     "}\n";
00198 
00199 // Shader with lens distortion and chromatic aberration correction.
00200 static const char* PostProcessFullFragShaderSrc =
00201     "uniform vec2 LensCenter;\n"
00202     "uniform vec2 ScreenCenter;\n"
00203     "uniform vec2 Scale;\n"
00204     "uniform vec2 ScaleIn;\n"
00205     "uniform vec4 HmdWarpParam;\n"
00206     "uniform vec4 ChromAbParam;\n"
00207     "uniform sampler2D Texture0;\n"
00208     "varying vec2 oTexCoord;\n"
00209     "\n"
00210     // Scales input texture coordinates for distortion.
00211     // ScaleIn maps texture coordinates to Scales to ([-1, 1]), although top/bottom will be
00212     // larger due to aspect ratio.
00213     "void main()\n"
00214     "{\n"
00215     "   vec2  theta = (oTexCoord - LensCenter) * ScaleIn;\n" // Scales to [-1, 1]
00216     "   float rSq= theta.x * theta.x + theta.y * theta.y;\n"
00217     "   vec2  theta1 = theta * (HmdWarpParam.x + HmdWarpParam.y * rSq + "
00218     "                  HmdWarpParam.z * rSq * rSq + HmdWarpParam.w * rSq * rSq * rSq);\n"
00219     "   \n"
00220     "   // Detect whether blue texture coordinates are out of range since these will scaled out the furthest.\n"
00221     "   vec2 thetaBlue = theta1 * (ChromAbParam.z + ChromAbParam.w * rSq);\n"
00222     "   vec2 tcBlue = LensCenter + Scale * thetaBlue;\n"
00223     "   if (!all(equal(clamp(tcBlue, ScreenCenter-vec2(0.25,0.5), ScreenCenter+vec2(0.25,0.5)), tcBlue)))\n"
00224     "   {\n"
00225     "       gl_FragColor = vec4(0);\n"
00226     "       return;\n"
00227     "   }\n"
00228     "   \n"
00229     "   // Now do blue texture lookup.\n"
00230     "   float blue = texture2D(Texture0, tcBlue).b;\n"
00231     "   \n"
00232     "   // Do green lookup (no scaling).\n"
00233     "   vec2  tcGreen = LensCenter + Scale * theta1;\n"
00234     "   vec4  center = texture2D(Texture0, tcGreen);\n"
00235     "   \n"
00236     "   // Do red scale and lookup.\n"
00237     "   vec2  thetaRed = theta1 * (ChromAbParam.x + ChromAbParam.y * rSq);\n"
00238     "   vec2  tcRed = LensCenter + Scale * thetaRed;\n"
00239     "   float red = texture2D(Texture0, tcRed).r;\n"
00240     "   \n"
00241     "   gl_FragColor = vec4(red, center.g, blue, center.a);\n"
00242     "}\n";
00243 
00244 static const char* VShaderSrcs[VShader_Count] =
00245 {
00246     DirectVertexShaderSrc,
00247     StdVertexShaderSrc,
00248     PostProcessVertexShaderSrc
00249 };
00250 static const char* FShaderSrcs[FShader_Count] =
00251 {
00252     SolidFragShaderSrc,
00253     GouraudFragShaderSrc,
00254     TextureFragShaderSrc,
00255     AlphaTextureFragShaderSrc,
00256     PostProcessFragShaderSrc,
00257     PostProcessFullFragShaderSrc,
00258     LitSolidFragShaderSrc,
00259     LitTextureFragShaderSrc,
00260     MultiTextureFragShaderSrc
00261 };
00262 
00263 
00264 
00265 RenderDevice::RenderDevice(const RendererParams& p)
00266 {
00267     for (int i = 0; i < VShader_Count; i++)
00268         VertexShaders[i] = *new Shader(this, Shader_Vertex, VShaderSrcs[i]);
00269 
00270     for (int i = 0; i < FShader_Count; i++)
00271         FragShaders[i] = *new Shader(this, Shader_Fragment, FShaderSrcs[i]);
00272 
00273     Ptr<ShaderSet> gouraudShaders = *new ShaderSet();
00274     gouraudShaders->SetShader(VertexShaders[VShader_MVP]);
00275     gouraudShaders->SetShader(FragShaders[FShader_Gouraud]);
00276     DefaultFill = *new ShaderFill(gouraudShaders);
00277 
00278     glGenFramebuffersEXT(1, &CurrentFbo);
00279 }
00280 
00281 Shader *RenderDevice::LoadBuiltinShader(ShaderStage stage, int shader)
00282 {
00283     switch (stage)
00284     {
00285     case Shader_Vertex: return VertexShaders[shader];
00286     case Shader_Fragment: return FragShaders[shader];
00287     default:
00288         return NULL;
00289     }
00290 }
00291 
00292 
00293 void RenderDevice::BeginRendering()
00294 {
00295     glEnable(GL_DEPTH_TEST);
00296     glEnable(GL_CULL_FACE);
00297     glFrontFace(GL_CW);
00298 
00299     glLineWidth(3.0f);
00300     glEnable(GL_LINE_SMOOTH);
00301     glEnable(GL_BLEND);
00302     glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
00303 
00304     glMatrixMode(GL_MODELVIEW);
00305     glLoadIdentity();
00306 }
00307 
00308 void RenderDevice::SetDepthMode(bool enable, bool write, CompareFunc func)
00309 {
00310     if (enable)
00311     {
00312         glEnable(GL_DEPTH_TEST);
00313         glDepthMask(write);
00314         switch (func)
00315         {
00316         case Compare_Always:  glDepthFunc(GL_ALWAYS); break;
00317         case Compare_Less:    glDepthFunc(GL_LESS); break;
00318         case Compare_Greater: glDepthFunc(GL_GREATER); break;
00319         default: assert(0);
00320         }
00321     }
00322     else
00323         glDisable(GL_DEPTH_TEST);
00324 }
00325 
00326 void RenderDevice::SetRealViewport(const Viewport& vp)
00327 {
00328     int wh;
00329     if (CurRenderTarget)
00330         wh = CurRenderTarget->Height;
00331     else
00332         wh = WindowHeight;
00333     glViewport(vp.x, wh-vp.y-vp.h, vp.w, vp.h);
00334 
00335     glEnable(GL_SCISSOR_TEST);
00336     glScissor(vp.x, wh-vp.y-vp.h, vp.w, vp.h);
00337 }
00338 
00339 void RenderDevice::Clear(float r, float g, float b, float a, float depth)
00340 {
00341     glClearColor(r,g,b,a);
00342     glClearDepth(depth);
00343     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
00344 }
00345 
00346 RBuffer* RenderDevice::GetDepthBuffer(int w, int h, int ms)
00347 {
00348     for (unsigned i = 0; i < DepthBuffers.GetSize(); i++)
00349         if (w == DepthBuffers[i]->Width && h == DepthBuffers[i]->Height)// && ms == DepthBuffers[i]->Samples)
00350             return DepthBuffers[i];
00351 
00352     //Ptr<Texture> newDepth = *CreateTexture(Texture_Depth|Texture_RenderTarget|ms, w, h, NULL);
00353     Ptr<RBuffer> newDepth = *new RBuffer(GL_DEPTH24_STENCIL8, w, h); // combined depth stencil
00354     DepthBuffers.PushBack(newDepth);
00355     return newDepth.GetPtr();
00356 }
00357 
00358 void RenderDevice::SetRenderTarget(Render::Texture* color, Render::Texture*, Render::Texture* stencil)
00359 {
00360     OVR_UNUSED(stencil);
00361 
00362     CurRenderTarget = (Texture*)color;
00363     if (color == NULL)
00364     {
00365         glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
00366         return;
00367     }
00368     //if (depth == NULL)
00369     RBuffer* depth = GetDepthBuffer(color->GetWidth(), color->GetHeight(), 0); //CurRenderTarget->Samples);
00370 
00371     glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, CurrentFbo);
00372     glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, ((Texture*)color)->TexId, 0);
00373     if (depth)
00374         //glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_2D, ((Texture*)depth)->TexId, 0);
00375         glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, ((RBuffer*)depth)->BufId);
00376     else
00377         glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, 0);
00378 
00379     GLenum status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
00380     if (status != GL_FRAMEBUFFER_COMPLETE_EXT)
00381         OVR_DEBUG_LOG(("framebuffer not complete: %x", status));
00382 }
00383 
00384 
00385 void RenderDevice::SetWorldUniforms(const Matrix4f& proj)
00386 {
00387     Proj = proj.Transposed();
00388 }
00389 
00390 void RenderDevice::SetTexture(Render::ShaderStage, int slot, const Texture* t)
00391 {
00392     glActiveTexture(GL_TEXTURE0 + slot);
00393     glBindTexture(GL_TEXTURE_2D, ((Texture*)t)->TexId);
00394     glActiveTexture(GL_TEXTURE0);
00395 }
00396 
00397 Buffer* RenderDevice::CreateBuffer()
00398 {
00399     return new Buffer(this);
00400 }
00401 
00402 Fill* RenderDevice::CreateSimpleFill(int flags)
00403 {
00404     OVR_UNUSED(flags);
00405     return DefaultFill;
00406 }
00407 
00408 
00409 void RenderDevice::Render(const Matrix4f& matrix, Model* model)
00410 {
00411     // Store data in buffers if not already
00412     if (!model->VertexBuffer)
00413     {
00414         Ptr<Render::Buffer> vb = *CreateBuffer();
00415         vb->Data(Buffer_Vertex, &model->Vertices[0], model->Vertices.GetSize() * sizeof(Vertex));
00416         model->VertexBuffer = vb;
00417     }
00418     if (!model->IndexBuffer)
00419     {
00420         Ptr<Render::Buffer> ib = *CreateBuffer();
00421         ib->Data(Buffer_Index, &model->Indices[0], model->Indices.GetSize() * 2);
00422         model->IndexBuffer = ib;
00423     }
00424 
00425     Render(model->Fill ? (const Fill*)model->Fill : (const Fill*)DefaultFill,
00426            model->VertexBuffer, model->IndexBuffer,
00427            matrix, 0, (int)model->Indices.GetSize(), model->GetPrimType());
00428 }
00429 
00430 void RenderDevice::Render(const Fill* fill, Render::Buffer* vertices, Render::Buffer* indices,
00431                       const Matrix4f& matrix, int offset, int count, PrimitiveType rprim)
00432 {
00433     ShaderSet* shaders = (ShaderSet*) ((ShaderFill*)fill)->GetShaders();
00434 
00435     GLenum prim;
00436     switch (rprim)
00437     {
00438     case Prim_Triangles:
00439         prim = GL_TRIANGLES;
00440         break;
00441     case Prim_Lines:
00442         prim = GL_LINES;
00443         break;
00444     case Prim_TriangleStrip:
00445         prim = GL_TRIANGLE_STRIP;
00446         break;
00447     default:
00448         assert(0);
00449         return;
00450     }
00451 
00452     fill->Set();
00453     if (shaders->ProjLoc >= 0)
00454         glUniformMatrix4fv(shaders->ProjLoc, 1, 0, &Proj.M[0][0]);
00455     if (shaders->ViewLoc >= 0)
00456         glUniformMatrix4fv(shaders->ViewLoc, 1, 0, &matrix.Transposed().M[0][0]);
00457 
00458     if (shaders->UsesLighting && Lighting->Version != shaders->LightingVer)
00459     {
00460         shaders->LightingVer = Lighting->Version;
00461         Lighting->Set(shaders);
00462     }
00463 
00464     glBindBuffer(GL_ARRAY_BUFFER, ((Buffer*)vertices)->GLBuffer);
00465     for (int i = 0; i < 5; i++)
00466         glEnableVertexAttribArray(i);
00467 
00468     glVertexAttribPointer(0, 3, GL_FLOAT, false, sizeof(Vertex), (char*)offset + offsetof(Vertex, Pos));
00469     glVertexAttribPointer(1, 4, GL_UNSIGNED_BYTE, true, sizeof(Vertex), (char*)offset + offsetof(Vertex, C));
00470     glVertexAttribPointer(2, 2, GL_FLOAT, false, sizeof(Vertex), (char*)offset + offsetof(Vertex, U));
00471     glVertexAttribPointer(3, 2, GL_FLOAT, false, sizeof(Vertex), (char*)offset + offsetof(Vertex, U2));
00472     glVertexAttribPointer(4, 3, GL_FLOAT, false, sizeof(Vertex), (char*)offset + offsetof(Vertex, Norm));
00473 
00474     if (indices)
00475     {
00476         glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ((Buffer*)indices)->GLBuffer);
00477         glDrawElements(prim, count, GL_UNSIGNED_SHORT, NULL);
00478         glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
00479     }
00480     else
00481     {
00482         glDrawArrays(prim, 0, count);
00483     }
00484 
00485     for (int i = 0; i < 5; i++)
00486         glDisableVertexAttribArray(i);
00487 }
00488 
00489 void RenderDevice::RenderWithAlpha(const Fill* fill, Render::Buffer* vertices, Render::Buffer* indices,
00490                                    const Matrix4f& matrix, int offset, int count, PrimitiveType rprim)
00491 {
00492     //glEnable(GL_BLEND);
00493     Render(fill, vertices, indices, matrix, offset, count, rprim);
00494     //glDisable(GL_BLEND);
00495 }
00496 
00497 void RenderDevice::SetLighting(const LightingParams* lt)
00498 {
00499     Lighting = lt;
00500 }
00501 
00502 Buffer::~Buffer()
00503 {
00504     if (GLBuffer)
00505         glDeleteBuffers(1, &GLBuffer);
00506 }
00507 
00508 bool Buffer::Data(int use, const void* buffer, size_t size)
00509 {
00510     switch (use & Buffer_TypeMask)
00511     {
00512     case Buffer_Index:     Use = GL_ELEMENT_ARRAY_BUFFER; break;
00513     default:               Use = GL_ARRAY_BUFFER; break;
00514     }
00515 
00516     if (!GLBuffer)
00517         glGenBuffers(1, &GLBuffer);
00518 
00519     int mode = GL_DYNAMIC_DRAW;
00520     if (use & Buffer_ReadOnly)
00521         mode = GL_STATIC_DRAW;
00522 
00523     glBindBuffer(Use, GLBuffer);
00524     glBufferData(Use, size, buffer, mode);
00525     glBindBuffer(Use, 0);
00526     return 1;
00527 }
00528 
00529 void* Buffer::Map(size_t start, size_t size, int flags)
00530 {
00531     int mode = GL_WRITE_ONLY;
00532     //if (flags & Map_Unsynchronized)
00533     //    mode |= GL_MAP_UNSYNCHRONIZED;
00534     
00535     glBindBuffer(Use, GLBuffer);
00536     void* v = glMapBuffer(Use, mode);
00537     glBindBuffer(Use, 0);
00538     return v;
00539 }
00540 
00541 bool Buffer::Unmap(void*)
00542 {
00543     glBindBuffer(Use, GLBuffer);
00544     int r = glUnmapBuffer(Use);
00545     glBindBuffer(Use, 0);
00546     return r;
00547 }
00548 
00549 bool Shader::Compile(const char* src)
00550 {
00551     if (!GLShader)
00552         GLShader = glCreateShader(GLStage());
00553 
00554     glShaderSource(GLShader, 1, &src, 0);
00555     glCompileShader(GLShader);
00556     GLint r;
00557     glGetShaderiv(GLShader, GL_COMPILE_STATUS, &r);
00558     if (!r)
00559     {
00560         GLchar msg[1024];
00561         glGetShaderInfoLog(GLShader, sizeof(msg), 0, msg);
00562         if (msg[0])
00563             OVR_DEBUG_LOG(("Compiling shader\n%s\nfailed: %s\n", src, msg));
00564         if (!r)
00565             return 0;
00566     }
00567     return 1;
00568 }
00569 
00570 ShaderSet::ShaderSet()
00571 {
00572     Prog = glCreateProgram();
00573 }
00574 ShaderSet::~ShaderSet()
00575 {
00576     glDeleteProgram(Prog);
00577 }
00578 
00579 bool ShaderSet::Link()
00580 {
00581     glBindAttribLocation(Prog, 0, "Position");
00582     glBindAttribLocation(Prog, 1, "Color");
00583     glBindAttribLocation(Prog, 2, "TexCoord");
00584     glBindAttribLocation(Prog, 3, "TexCoord1");
00585     glBindAttribLocation(Prog, 4, "Normal");
00586 
00587     glLinkProgram(Prog);
00588     GLint r;
00589     glGetProgramiv(Prog, GL_LINK_STATUS, &r);
00590     if (!r)
00591     {
00592         GLchar msg[1024];
00593         glGetProgramInfoLog(Prog, sizeof(msg), 0, msg);
00594         OVR_DEBUG_LOG(("Linking shaders failed: %s\n", msg));
00595         if (!r)
00596             return 0;
00597     }
00598     glUseProgram(Prog);
00599 
00600     UniformInfo.Clear();
00601     LightingVer = 0;
00602     UsesLighting = 0;
00603     GLuint i = 0;
00604     for(;; i++)
00605     {
00606         GLsizei namelen;
00607         GLint size = 0;
00608         GLenum type;
00609         GLchar name[32];
00610         glGetActiveUniform(Prog, i, sizeof(name), &namelen, &size, &type, name);
00611         if (size)
00612         {
00613             int l = glGetUniformLocation(Prog, name);
00614             char *np = name;
00615             while (*np)
00616             {
00617                 if (*np == '[')
00618                     *np = 0;
00619                 np++;
00620             }
00621             Uniform u;
00622             u.Name = name;
00623             u.Location = l;
00624             u.Size = size;
00625             switch (type)
00626             {
00627             case GL_FLOAT:      u.Type = 1; break;
00628             case GL_FLOAT_VEC2: u.Type = 2; break;
00629             case GL_FLOAT_VEC3: u.Type = 3; break;
00630             case GL_FLOAT_VEC4: u.Type = 4; break;
00631             case GL_FLOAT_MAT4: u.Type = 16; break;
00632             default:
00633                 continue;
00634             }
00635             UniformInfo.PushBack(u);
00636             if (!strcmp(name, "LightCount"))
00637                 UsesLighting = 1;
00638         }
00639         else
00640             break;
00641     }
00642 
00643     ProjLoc = glGetUniformLocation(Prog, "Proj");
00644     ViewLoc = glGetUniformLocation(Prog, "View");
00645     for (int i = 0; i < 8; i++)
00646     {
00647         char texv[32];
00648         sprintf(texv, "Texture%d", i);
00649         TexLoc[i] = glGetUniformLocation(Prog, texv);
00650         if (TexLoc[i] < 0)
00651             break;
00652 
00653         glUniform1i(TexLoc[i], i);
00654     }
00655     if (UsesLighting)
00656         OVR_ASSERT(ProjLoc >= 0 && ViewLoc >= 0);
00657     return 1;
00658 }
00659 
00660 void ShaderSet::Set(PrimitiveType) const
00661 {
00662     glUseProgram(Prog);
00663 }
00664 
00665 bool ShaderSet::SetUniform(const char* name, int n, const float* v)
00666 {
00667     for (int i = 0; i < UniformInfo.GetSize(); i++)
00668         if (!strcmp(UniformInfo[i].Name.ToCStr(), name))
00669         {
00670             OVR_ASSERT(UniformInfo[i].Location >= 0);
00671             glUseProgram(Prog);
00672             switch (UniformInfo[i].Type)
00673             {
00674             case 1:   glUniform1fv(UniformInfo[i].Location, n, v); break;
00675             case 2:   glUniform2fv(UniformInfo[i].Location, n/2, v); break;
00676             case 3:   glUniform3fv(UniformInfo[i].Location, n/3, v); break;
00677             case 4:   glUniform4fv(UniformInfo[i].Location, n/4, v); break;
00678             default: OVR_ASSERT(0);
00679             }
00680             return 1;
00681         }
00682 
00683     OVR_DEBUG_LOG(("Warning: uniform %s not present in selected shader", name));
00684     return 0;
00685 }
00686 
00687 bool ShaderSet::SetUniform4x4f(const char* name, const Matrix4f& m)
00688 {
00689     for (int i = 0; i < UniformInfo.GetSize(); i++)
00690         if (!strcmp(UniformInfo[i].Name.ToCStr(), name))
00691         {
00692             glUseProgram(Prog);
00693             glUniformMatrix4fv(UniformInfo[i].Location, 1, 1, &m.M[0][0]);
00694             return 1;
00695         }
00696 
00697     OVR_DEBUG_LOG(("Warning: uniform %s not present in selected shader", name));
00698     return 0;
00699 }
00700 
00701 Texture::Texture(RenderDevice* r, int w, int h) : Ren(r), Width(w), Height(h)
00702 {
00703     glGenTextures(1, &TexId);
00704 }
00705 
00706 Texture::~Texture()
00707 {
00708     if (TexId)
00709         glDeleteTextures(1, &TexId);
00710 }
00711 
00712 void Texture::Set(int slot, Render::ShaderStage stage) const
00713 {
00714     Ren->SetTexture(stage, slot, this);
00715 }
00716 
00717 void Texture::SetSampleMode(int sm)
00718 {
00719     glBindTexture(GL_TEXTURE_2D, TexId);
00720     switch (sm & Sample_FilterMask)
00721     {
00722     case Sample_Linear:
00723         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
00724         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
00725         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 0);
00726         break;
00727 
00728     case Sample_Anisotropic:
00729         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
00730         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
00731         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 8);
00732         break;
00733 
00734     case Sample_Nearest:
00735         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
00736         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
00737         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 0);
00738         break;
00739     }
00740 
00741     switch (sm & Sample_AddressMask)
00742     {
00743     case Sample_Repeat:
00744         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
00745         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
00746         break;
00747 
00748     case Sample_Clamp:
00749         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
00750         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
00751         break;
00752 
00753     case Sample_ClampBorder:
00754         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
00755         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
00756         break;
00757     }
00758     glBindTexture(GL_TEXTURE_2D, 0);
00759 }
00760 
00761 Texture* RenderDevice::CreateTexture(int format, int width, int height, const void* data, int mipcount)
00762 {
00763     GLenum   glformat, gltype = GL_UNSIGNED_BYTE;
00764     switch(format & Texture_TypeMask)
00765     {
00766     case Texture_RGBA:  glformat = GL_RGBA; break;
00767     case Texture_R:     glformat = GL_ALPHA; break;
00768     case Texture_Depth: glformat = GL_DEPTH; gltype = GL_DEPTH_COMPONENT; break;
00769     case Texture_DXT1:  glformat = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT; break;
00770     case Texture_DXT3:  glformat = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT; break;
00771     case Texture_DXT5:  glformat = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT; break;
00772     default:
00773         return NULL;
00774     }
00775     Texture* NewTex = new Texture(this, width, height);
00776     glBindTexture(GL_TEXTURE_2D, NewTex->TexId);
00777     glGetError();
00778     
00779     if (format & Texture_Compressed)
00780     {
00781         const unsigned char* level = (const unsigned char*)data;
00782         int w = width, h = height;
00783         for (int i = 0; i < mipcount; i++)
00784         {
00785             int mipsize = GetTextureSize(format, w, h);
00786             glCompressedTexImage2D(GL_TEXTURE_2D, i, glformat, w, h, 0, mipsize, level);
00787 
00788             level += mipsize;
00789             w >>= 1;
00790             h >>= 1;
00791             if (w < 1) w = 1;
00792             if (h < 1) h = 1;
00793         }
00794     }
00795     else
00796         glTexImage2D(GL_TEXTURE_2D, 0, glformat, width, height, 0, glformat, gltype, data);
00797 
00798     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
00799     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
00800     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
00801     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
00802 
00803     if (format == (Texture_RGBA|Texture_GenMipmaps)) // not render target
00804     {
00805         int srcw = width, srch = height;
00806         int level = 0;
00807         UByte* mipmaps = NULL;
00808         do
00809         {
00810             level++;
00811             int mipw = srcw >> 1; if (mipw < 1) mipw = 1;
00812             int miph = srch >> 1; if (miph < 1) miph = 1;
00813             if (mipmaps == NULL)
00814                 mipmaps = (UByte*)OVR_ALLOC(mipw * miph * 4);
00815             FilterRgba2x2(level == 1 ? (const UByte*)data : mipmaps, srcw, srch, mipmaps);
00816             glTexImage2D(GL_TEXTURE_2D, level, glformat, mipw, miph, 0, glformat, gltype, mipmaps);
00817             srcw = mipw;
00818             srch = miph;
00819         } while (srcw > 1 || srch > 1);
00820         if (mipmaps)
00821             OVR_FREE(mipmaps);
00822         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, level);
00823     }
00824     else
00825     {
00826         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, mipcount-1);
00827     }
00828 
00829     OVR_ASSERT(!glGetError());
00830     glBindTexture(GL_TEXTURE_2D, 0);
00831     return NewTex;
00832 }
00833 
00834 bool RenderDevice::SetFullscreen(DisplayMode fullscreen)
00835 {
00836     Params.Fullscreen = fullscreen;
00837     return true;
00838 }
00839 
00840 RBuffer::RBuffer(GLenum format, GLint w, GLint h)
00841 {
00842     Width = w;
00843     Height = h;
00844     glGenRenderbuffersEXT(1, &BufId);
00845     glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, BufId);
00846     glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, format, w, h);
00847     glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0);
00848 }
00849 
00850 RBuffer::~RBuffer()
00851 {
00852     glDeleteRenderbuffersEXT(1, &BufId);
00853 }
00854 
00855 }}}


oculus_sdk
Author(s):
autogenerated on Mon Oct 6 2014 03:01:19