00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
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"
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
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
00211
00212
00213 "void main()\n"
00214 "{\n"
00215 " vec2 theta = (oTexCoord - LensCenter) * ScaleIn;\n"
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)
00350 return DepthBuffers[i];
00351
00352
00353 Ptr<RBuffer> newDepth = *new RBuffer(GL_DEPTH24_STENCIL8, w, h);
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
00369 RBuffer* depth = GetDepthBuffer(color->GetWidth(), color->GetHeight(), 0);
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
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
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
00493 Render(fill, vertices, indices, matrix, offset, count, rprim);
00494
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
00533
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))
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 }}}