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


oculus_sdk
Author(s):
autogenerated on Fri Aug 28 2015 11:53:11