Jump to content
The Dark Mod Forums

revelator

Development Role
  • Posts

    1177
  • Joined

  • Last visited

  • Days Won

    21

Everything posted by revelator

  1. final version /* ==================== CopyDepthbuffer ==================== */ void idImage::CopyDepthbuffer(int x, int y, int imageWidth, int imageHeight, bool useOversizedBuffer) { this->Bind(); // if the size isn't a power of 2, the image must be increased in size int potWidth, potHeight; IMAGE_ROUND_POWER2(imageWidth, potWidth); IMAGE_ROUND_POWER2(imageHeight, potHeight); GetDownsize(imageWidth, imageHeight); GetDownsize(potWidth, potHeight); // Ensure we are reading from the back buffer: (might be GL_NONE revelator) glReadBuffer(GL_BACK); // only resize if the current dimensions can't hold it at all, // otherwise subview renderings could thrash this if ((useOversizedBuffer && (uploadWidth < potWidth || uploadHeight < potHeight)) || (!useOversizedBuffer && (uploadWidth != potWidth || uploadHeight != potHeight))) { uploadWidth = potWidth; uploadHeight = potHeight; // This bit runs once only at map start, because it tests whether the image is too small to hold the screen. // It resizes the texture to a power of two that can hold the screen, // and then subsequent captures to the texture put the depth component into the RGB channels: (steveL) glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT24_ARB, potWidth, potHeight, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, NULL); glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, x, y, imageWidth, imageHeight); } else { // otherwise, just subimage upload it so that drivers can tell we are going to be changing // it and don't try and do a texture compression or some other silliness. glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, x, y, imageWidth, imageHeight); } glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); backEnd.c_copyDepthBuffer++; } if i understood correctly that is
  2. Ill be damned thats some cool work there steve gratz. Heh seems the fraze old dogs have a harder time learning new tricks fits, i would newer had picked up on ASM shaders that fast iiimposible. Atleast i was on the right track with the depth copy so i can pat myself on the back also .
  3. Have to agree with steve there, coding in the renderer ranges from trivial to sometimes painfull but gamecode is pure torture. I once replaced the entire VM in quake with bengt jardrups and spent the next 3 years mining out bugs because of incompatibilities with my engine port urgh, . The renderer took me about a months work before it was as i wanted it, getting the game logic going finally worked after a lot of work but its something im not keen on experiencing again.
  4. ah crazy eddies gui, yeah good alternative for a gui, like lua support. i Remeber it was used in some mmorpg game and it had in game configurable menus like world of warcraft.
  5. http://glampert.blogspot.dk/2014/01/visualizing-depth-buffer.html found some usefull info here, looks like we have to read the backbuffer ? which left me with a wtf moment, cause someone told me not to read from that. also it seems really simple compared to my massive function. Also a test shader on that site sadly its in GLSL so not directly useable with vanilla. btw this part // otherwise, just subimage upload it so that drivers can tell we are going to be changing // it and don't try and do a texture compression or some other silliness, still need to create it as depth buffer image though. glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT24_ARB, potWidth, potHeight, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, NULL); remove it again, it causes the engine to run to a crawl. And same here, newer found a lot of good info about ASM shaders :S
  6. void idImage::CopyDepthbuffer(int x, int y, int imageWidth, int imageHeight, bool useOversizedBuffer) { this->Bind(); // if the size isn't a power of 2, the image must be increased in size int potWidth, potHeight; IMAGE_ROUND_POWER2(imageWidth, potWidth); IMAGE_ROUND_POWER2(imageHeight, potHeight); GetDownsize(imageWidth, imageHeight); GetDownsize(potWidth, potHeight); // Instruct openGL that we won't bind a color texture (depth images are greyscale). glReadBuffer(GL_NONE); // only resize if the current dimensions can't hold it at all, // otherwise subview renderings could thrash this if ((useOversizedBuffer && (uploadWidth < potWidth || uploadHeight < potHeight)) || (!useOversizedBuffer && (uploadWidth != potWidth || uploadHeight != potHeight))) { uploadWidth = potWidth; uploadHeight = potHeight; if (potWidth == imageWidth && potHeight == imageHeight) { glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, x, y, imageWidth, imageHeight, NULL); } else { glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT24_ARB, potWidth, potHeight, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, NULL); glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, x, y, imageWidth, imageHeight); } } else { // otherwise, just subimage upload it so that drivers can tell we are going to be changing // it and don't try and do a texture compression or some other silliness, still need to create it as depth buffer image though. glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT24_ARB, potWidth, potHeight, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, NULL); glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, x, y, imageWidth, imageHeight); } glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); backEnd.c_copyDepthBuffer++; } try this one out, i removed the fix for bilerp seams (not needed and might have broken it) and changed the depth component to GL_DEPTH_COMPONENT24_ARB (better). the extra glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT24_ARB, potWidth, potHeight, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, NULL); is a test cause im not sure just copying the depthbuffer data is enough (or does the driver know its a depthimage when not specified ?).
  7. Nice work steve yeah im also still beating my head around the depthbuffer, i wish sikkpin was around as he has more experience with that part. My depthbuffer code might also be of use to him and he could probably iron out any bugs i might be responsible for heh. Im going to have a look at FBO's and see if i can find a not to messy way of working them into vanillas code, should help a bit with the above.
  8. Hmm wouldnt call the old gui a cpu hog its an xml parser they are by design pretty light on resources. There are other more deserving targets for that claim like old OpenGL 1.4 calls (there are quite a lot in vanilla) or lack of a multithreaded renderer . I can respect that you find vanilla archaic and would rather force others to use the newer engine but take into account the work these devs have put into darkmod, it might be hard for them to totally scrap everything they created so far and starting over. On the positive account we might end up with some nice improvements to vanilla even if it takes some time. Its also a good learning experience .
  9. draw_exp was an experimental renderer it was disabled in vanilla but theres some interresting stuff in there like shadow maps instead of shadow volumes, bloom, and other stuff. the shadowmap code was rather nasty in some places (used the non portable windows gl wgl) and is probably the reason why they ditched it. Looking around i found evidence that most use FBO's for depthbuffer operations but id prefer not to go down that path, since it would mean rewriting large parts of the image libraries. It might be worth it though but id rather not be the one to do it :S i have tons of work ahead allready.
  10. static void R_CreateShadowBufferImage( idImage *image ) { byte *data = (byte *)Mem_Alloc( lightBufferSize*lightBufferSize ); memset( data, 0, lightBufferSize*lightBufferSize ); image->GenerateImage( (byte *)data, 4, 4, TF_LINEAR, false, TR_CLAMP_TO_BORDER, TD_HIGH_QUALITY ); // now reset it to a shadow depth image GL_CheckErrors(); image->uploadWidth = image->uploadHeight = lightBufferSize; qglTexImage2D( GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT24_ARB, lightBufferSize, lightBufferSize, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, data ); qglTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE_ARB, GL_COMPARE_R_TO_TEXTURE ); // qglTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE_ARB, GL_NONE ); qglTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC_ARB, GL_LEQUAL ); // explicit zero depth border float color[4]; color[0] = color[1] = color[2] = color[3] = 0; qglTexParameterfv( GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, color ); GL_CheckErrors(); Mem_Free( data ); } lightBufferSize is const int 1024. In retrospect this function uses dynamic allocation on a const so could probably get away with using an array instead on data, eg data[1024][1024]; and skip the Mem_Alloc / Mem_Free completely. Should not even be nessesary to image->uploadWidth = image->uploadHeight = lightBufferSize; as we are not using the function to render a texture but rather write it out. So an R_WriteTGA at the end instead hmm ???.
  11. Had a look at draw_exp.cpp and the funtion for making depthbuffer images for the shadows seems to be something to take into account. Found the editor but might get a newer version from here https://www.opengl.org/sdk/tools/ShaderDesigner/ mines over a year old. Also supports exporting to 3dsmax
  12. Hmm and as for exporting the depthmap textures, might have to write some code for that, maybe take hints from the SaveTga function ? maybe we can use it without even writing a new function, ill see what i can do.
  13. Hmm found this while searching but im not sure its for windows. http://forum.unity3d.com/threads/shader-forge-a-visual-node-based-shader-editor.191595/ I do have a GLSL editor though, no not rendermonkey ill see if i can dig it up on my overfilled harddrives.
  14. Not related but i finally completed work on my new Msys2 based compiler suite for MinGW64. Might be nice for those people here switching between coding for linux and windows to use some known posix tools 64 bit Msys2 based version here https://sourceforge.net/projects/cbadvanced/files/CB%20Msys2%20version/x64/installer/ 32 bit Msys based version here https://sourceforge.net/projects/cbadvanced/files/CB%20Msys2%20version/x86/installer/ Msys2 is based on Cygwin like the old one but this one is synced to to the latest Cygwin version, the difference is that this creates pure windows code without relying on the Posix dll like Cygwin eg. (cygwin1.dll) The msys2 version is named Msys-2.0.dll though. The suites are packed with lots of tools and support libraries like boost and intel threading building blocks, besides a ton of image libraries GTK and QT OpenAL several other Sound libraries and decoders / encoders and the latest gcc and binutils versions 4.9.1 and 2.24. My gcc builds also default to linking statically with the gcc runtimes but if prefered you can still link to the dll versions. If you want to link to the dynamic versions be aware that this gcc is patched to allow throwing exceptions from the static libraries so if thats you'r reason its not needed . The installers autopatch QT to the path they are installed in so QT works right out of the box. I also included the basic postgresql console tools and a batch file for creating the default database. Just type postgresql in the windows shell tab or cygstart postgresql in the Msys2 shell, and it will initialize and start the default database. For more advanced work its easier to get the free pgadmin III frontend. The batch files for the compilers can be modified by removing the rem on 2 lines to support native windows symlinks and or use qtcreators gdb frontend for debugging. Theres a modified CodeBlocks IDE included that supports my compilers, it needs updating (made it some years ago) but it works fine most of the time. Hope someone finds them usefull
  15. Nice one that gets rid of the hack in sikkmod then, instead of doing a pushback on it in the game dll, me like .
  16. Probably the best place for this would be precompiled.h as its global to all the source ?. Heh even BFG reinterprets the float values but atleast it uses a more modern way IEEE-754. I toyed a bit with it changing vanillas FLT_EPSILON to DBL_EPSILON so far it works fine but im not sure its correct for all cases.
  17. Yikes thats ancient seems there was a bit confusion about this though but atleast we now have confirmation from a trusted source . C++ crankyness (shudder) glad im not the poor soul who had to fix that good job though.
  18. Brian Harris (BFG source maintainer) just comfirmed it, this texgen was newer used and is safe to remove. So i guess case closed .
  19. Indeed probably a lot of stuff that can be removed outright, not sure it will do anything speedwise as they are not used at all but it makes the source a lot easier to read
  20. I think it was an early try on refraction the heathaze shader works better though and is a combine shader so its easier to use.
  21. Digging deeper i found out that arbFP_glasswarp.txt arbVP_glasswarp.txt seem to have been the old shaders used for refraction but that functionality was moved to heathaze.vfp. If the engine uses the arb2 backend only you can do // a single file can have both a vertex program and a fragment program static progDef_t progs[MAX_GLPROGS] = { { GL_VERTEX_PROGRAM_ARB, VPROG_TEST, "test.vfp" }, { GL_FRAGMENT_PROGRAM_ARB, FPROG_TEST, "test.vfp" }, { GL_VERTEX_PROGRAM_ARB, VPROG_INTERACTION, "interaction.vfp" }, { GL_FRAGMENT_PROGRAM_ARB, FPROG_INTERACTION, "interaction.vfp" }, { GL_VERTEX_PROGRAM_ARB, VPROG_BUMPY_ENVIRONMENT, "bumpyEnvironment.vfp" }, { GL_FRAGMENT_PROGRAM_ARB, FPROG_BUMPY_ENVIRONMENT, "bumpyEnvironment.vfp" }, { GL_VERTEX_PROGRAM_ARB, VPROG_AMBIENT, "ambientLight.vfp" }, { GL_FRAGMENT_PROGRAM_ARB, FPROG_AMBIENT, "ambientLight.vfp" }, { GL_VERTEX_PROGRAM_ARB, VPROG_STENCIL_SHADOW, "shadow.vp" }, //{ GL_VERTEX_PROGRAM_ARB, VPROG_R200_INTERACTION, "R200_interaction.vp" }, //{ GL_VERTEX_PROGRAM_ARB, VPROG_NV20_BUMP_AND_LIGHT, "nv20_bumpAndLight.vp" }, //{ GL_VERTEX_PROGRAM_ARB, VPROG_NV20_DIFFUSE_COLOR, "nv20_diffuseColor.vp" }, //{ GL_VERTEX_PROGRAM_ARB, VPROG_NV20_SPECULAR_COLOR, "nv20_specularColor.vp" }, //{ GL_VERTEX_PROGRAM_ARB, VPROG_NV20_DIFFUSE_AND_SPECULAR_COLOR, "nv20_diffuseAndSpecularColor.vp" }, { GL_VERTEX_PROGRAM_ARB, VPROG_ENVIRONMENT, "environment.vfp" }, { GL_FRAGMENT_PROGRAM_ARB, FPROG_ENVIRONMENT, "environment.vfp" }, //{ GL_VERTEX_PROGRAM_ARB, VPROG_GLASSWARP, "arbVP_glasswarp.vp" }, //{ GL_FRAGMENT_PROGRAM_ARB, FPROG_GLASSWARP, "arbFP_glasswarp.fp" }, // additional programs can be dynamically specified in materials }; those shader programs are not used anymore it seems, so far i had no adverse effects doing this. the heathaze shader is loaded via the materials same as other effects, only a few like skybox and reflection depend on calling from draw_common.cpp and those only because they need some support code from there. I removed all the now defunct shaders for the other backends + glasswarp and vanilla still works just fine
  22. Ok confirmed. this -> if (pStage->texture.texgen == TG_GLASSWARP) { // As far as I can tell, this is never used, confirmed revelator. glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, FPROG_GLASSWARP); glEnable(GL_FRAGMENT_PROGRAM_ARB); GL_SelectTexture(2); globalImages->scratchImage->Bind(); GL_SelectTexture(1); globalImages->scratchImage2->Bind(); RB_SetStageTexGen(surf); GL_SelectTexture(0); } is newer used :S the shaders are there but are not called anywhere in vanillas materials. checked by disabling the code and using the warning from BFG, it newer triggers in any of the maps. Not to say that the effect might be crap it might look cool even, someone better make a test map with a material shader using this so we can check it out . Mayhap the thing took to big of a toll on gfx at the time, vanilla was rather hard on gfx cards from back then so maybe they removed the interaction from the materials. edit: After some searching up and down the net i found out that its a refraction shader for windows, and it did work at some point but not in the last patch. It was also disabled in Q4 but should apperently have looked quite nice when it was still working. Sadly i cannot find any hints as to why it was disabled.
  23. As far as i can see only a few of the effects in draw_common.cpp are used if you leave out the older backends that might have used it, pretty much only the code for skies and and maybe one other. I just tried removing the code for glasswarp in revelation and it has no effect what so ever on heathaze hmm. So yeah it looks like those effects have been moved to the shaders. Might indeed be activated by a keyword in the materials, not sure which ill take a look later today.
  24. Tbh. i dont think the glasswarp shader ever had anything to do with heathaze, as far as i could see from vanilla it seems to have been an effect that did exactly what the name implied namely warping glass windows etc. The effects in draw_common seem to have been an unhealthy mixup of old code some of which was newer used (Q3 leftover maybe). Rather confusing so mistakes here are probably common. And yes i played it .
  25. Heh im glad i make you smile but static void RB_PrepareStageTexturing( const shaderStage_t *pStage, const drawSurf_t *surf ) { float useTexGenParm[4] = { 0.0f, 0.0f, 0.0f, 0.0f }; // set the texture matrix if needed RB_LoadShaderTextureMatrix( surf->shaderRegisters, &pStage->texture ); // texgens if( pStage->texture.texgen == TG_REFLECT_CUBE ) { // see if there is also a bump map specified const shaderStage_t *bumpStage = surf->material->GetBumpStage(); if( bumpStage != NULL ) { // per-pixel reflection mapping with bump mapping GL_SelectTexture( 1 ); bumpStage->texture.image->Bind(); GL_SelectTexture( 0 ); RENDERLOG_PRINTF( "TexGen: TG_REFLECT_CUBE: Bumpy Environment\n" ); if( surf->jointCache ) { renderProgManager.BindShader_BumpyEnvironmentSkinned(); } else { renderProgManager.BindShader_BumpyEnvironment(); } } else { RENDERLOG_PRINTF( "TexGen: TG_REFLECT_CUBE: Environment\n" ); if( surf->jointCache ) { renderProgManager.BindShader_EnvironmentSkinned(); } else { renderProgManager.BindShader_Environment(); } } } else if( pStage->texture.texgen == TG_SKYBOX_CUBE ) { renderProgManager.BindShader_SkyBox(); } else if( pStage->texture.texgen == TG_WOBBLESKY_CUBE ) { const int *parms = surf->material->GetTexGenRegisters(); float wobbleDegrees = surf->shaderRegisters[ parms[0] ] * ( idMath::PI / 180.0f ); float wobbleSpeed = surf->shaderRegisters[ parms[1] ] * ( 2.0f * idMath::PI / 60.0f ); float rotateSpeed = surf->shaderRegisters[ parms[2] ] * ( 2.0f * idMath::PI / 60.0f ); idVec3 axis[3]; { // very ad-hoc "wobble" transform float s, c; idMath::SinCos( wobbleSpeed * backEnd.viewDef->renderView.time[0] * 0.001f, s, c ); float ws, wc; idMath::SinCos( wobbleDegrees, ws, wc ); axis[2][0] = ws * c; axis[2][1] = ws * s; axis[2][2] = wc; axis[1][0] = -s * s * ws; axis[1][2] = -s * ws * ws; axis[1][1] = idMath::Sqrt( idMath::Fabs( 1.0f - ( axis[1][0] * axis[1][0] + axis[1][2] * axis[1][2] ) ) ); // make the second vector exactly perpendicular to the first axis[1] -= ( axis[2] * axis[1] ) * axis[2]; axis[1].Normalize(); // construct the third with a cross axis[0].Cross( axis[1], axis[2] ); } // add the rotate float rs, rc; idMath::SinCos( rotateSpeed * backEnd.viewDef->renderView.time[0] * 0.001f, rs, rc ); float transform[12]; transform[0 * 4 + 0] = axis[0][0] * rc + axis[1][0] * rs; transform[0 * 4 + 1] = axis[0][1] * rc + axis[1][1] * rs; transform[0 * 4 + 2] = axis[0][2] * rc + axis[1][2] * rs; transform[0 * 4 + 3] = 0.0f; transform[1 * 4 + 0] = axis[1][0] * rc - axis[0][0] * rs; transform[1 * 4 + 1] = axis[1][1] * rc - axis[0][1] * rs; transform[1 * 4 + 2] = axis[1][2] * rc - axis[0][2] * rs; transform[1 * 4 + 3] = 0.0f; transform[2 * 4 + 0] = axis[2][0]; transform[2 * 4 + 1] = axis[2][1]; transform[2 * 4 + 2] = axis[2][2]; transform[2 * 4 + 3] = 0.0f; SetVertexParms( RENDERPARM_WOBBLESKY_X, transform, 3 ); renderProgManager.BindShader_WobbleSky(); } else if( ( pStage->texture.texgen == TG_SCREEN ) || ( pStage->texture.texgen == TG_SCREEN2 ) ) { useTexGenParm[0] = 1.0f; useTexGenParm[1] = 1.0f; useTexGenParm[2] = 1.0f; useTexGenParm[3] = 1.0f; float mat[16]; R_MatrixMultiply( surf->space->modelViewMatrix, backEnd.viewDef->projectionMatrix, mat ); RENDERLOG_PRINTF( "TexGen : %s\n", ( pStage->texture.texgen == TG_SCREEN ) ? "TG_SCREEN" : "TG_SCREEN2" ); renderLog.Indent(); float plane[4]; plane[0] = mat[0 * 4 + 0]; plane[1] = mat[1 * 4 + 0]; plane[2] = mat[2 * 4 + 0]; plane[3] = mat[3 * 4 + 0]; SetVertexParm( RENDERPARM_TEXGEN_0_S, plane ); RENDERLOG_PRINTF( "TEXGEN_S = %4.3f, %4.3f, %4.3f, %4.3f\n", plane[0], plane[1], plane[2], plane[3] ); plane[0] = mat[0 * 4 + 1]; plane[1] = mat[1 * 4 + 1]; plane[2] = mat[2 * 4 + 1]; plane[3] = mat[3 * 4 + 1]; SetVertexParm( RENDERPARM_TEXGEN_0_T, plane ); RENDERLOG_PRINTF( "TEXGEN_T = %4.3f, %4.3f, %4.3f, %4.3f\n", plane[0], plane[1], plane[2], plane[3] ); plane[0] = mat[0 * 4 + 3]; plane[1] = mat[1 * 4 + 3]; plane[2] = mat[2 * 4 + 3]; plane[3] = mat[3 * 4 + 3]; SetVertexParm( RENDERPARM_TEXGEN_0_Q, plane ); RENDERLOG_PRINTF( "TEXGEN_Q = %4.3f, %4.3f, %4.3f, %4.3f\n", plane[0], plane[1], plane[2], plane[3] ); renderLog.Outdent(); } else if( pStage->texture.texgen == TG_DIFFUSE_CUBE ) { // As far as I can tell, this is never used idLib::Warning( "Using Diffuse Cube! Please contact Brian!" ); } else if( pStage->texture.texgen == TG_GLASSWARP ) { // As far as I can tell, this is never used idLib::Warning( "Using GlassWarp! Please contact Brian!" ); } SetVertexParm( RENDERPARM_TEXGEN_0_ENABLED, useTexGenParm ); } was not stephen but brian my memory might be more rotten than cheese -> still glasswarp is not used in BFG atleast not in what goes for vanillas draw_common.cpp. In BFG the file is called tr_backend_draw.cpp sorry for the confusion. note -> // As far as I can tell, this is never used idLib::Warning( "Using Diffuse Cube! Please contact Brian!" ); and // As far as I can tell, this is never used idLib::Warning( "Using GlassWarp! Please contact Brian!" );
×
×
  • Create New...