Change to specular maps?


Ok I figured I’d make a new thread for this as it really has my head boggled…
I did a test using Spearmint (modified version of ioquake3) since I can’t find any previous versions of ioquake3, and noticed that version 0.3 was when this “change” was introduced, although it doesn’t seem to be documented at all.

This is Spearmint v0.2:

This is Spearmint v0.3:

As you can see, v0.2 looks correct, but whatever has been changed in v0.3 and onwards, has completely messed up specular maps. It almost looks like the engine isnt even treating them as specular maps. It’s simply overlaying them on top of the map textures…


For reference, Spearmint 0.2 is based on ioquake3 Oct 16, 2015 and Spearmint 0.3 is based on ioquake3 May 9, 2016. The full list of ioquake3 changes is here.


Any idea what change could have caused this?


You could try other values for r_glossType (default is 1) which controls how specular texture alpha channel is used in calculations. However the exact original method is not available. r_glossType 0=gloss, 1=smoothness, 2=roughness, 3=shininess. There is other changes that affect specular but it’s hard to pick out behavior changes vs reorganized code.


Looking over the changelog, it might be that between 0.2 and 0.3, any image loaded as a diffuse/color map that has a matching image with a _s suffix (e.g. blue.png and blue_s.png) will automatically load the _s image as a specular map.

Also, r_pbr was implemented, which completely changes the layout of the specular maps, though it shouldn’t default to on.


Thanks for the replies. I’ve since noticed that this version of the engine seems to be completely ignoring my specular maps and instead seems to be generating its own specular maps (presumably from the map textures themselves) I discovered this by completely deleting the .mtr from the pk3 and then seeing that the map looked exactly the same.

Edit: After further investigation, I’ve discovered that simply renaming the .mtr to the same as the .shader, seems to fix alot of the map textures (they were previously 2 different filenames, which worked fine in previous versions of ioquake)


So I’ve done some more testing today and come to the realisation that the current OpenGL2 renderer must be broken, or some things must have been seriously overlooked.

Quick rundown of a few things I’ve noticed are messed up:

When r_ForceSun is enabled, real time model shadows are shown. This causes the players shadow to render over the 1st person weapon models, thus completely hiding the specular maps. Standing in “sunlight” and looking directly up moves the shadow away and shows the specular maps again.

Specular maps don’t seem to show any shininess anymore. Not much more I can say on that. Rolling back to an earlier OpenGL2 build from 2015, instantly correct this issue. See pics below.

To get the specular maps on my weapon models to look even somewhat close to how they used to, I have to completely invert them in photoshop. It almost seems like white areas of the specular map look darker ingame, than black areas…

Whatever the case, I’m just gonna stick with this older build of OpenGL2 until this issues are fixed, or someone explains how specular maps actually work now.

Here’s an example of the difference. Only thing I’ve changed is the version of the OpenGL2 renderer:

Older version from 2015:

Latest version:

As you can see, there is a massive difference in the shininess of the gun and the ammo box, and also the map textures in general just look slightly more defined with the old version.


Can you please post your cfg renderer settings? What cvars did you modify? Default cvars? etc.,etc.
Just because I can’t reproduce your issue atm.
Yes, a lot of things have changed, and yes, shadows are still ‘broken’, but all in all the renderer should still look nice. So don’t give up! Here are my settings:

seta r_gamma “1”
seta r_swapInterval “1”
seta r_textureMode “GL_LINEAR_MIPMAP_LINEAR”
seta r_finish “1”
seta r_dlightBacks “1”
seta r_dynamiclight “1”
seta r_drawSun “1”
seta r_fastsky “0”
seta r_ignoreGLErrors “1”
seta r_stereoSeparation “64”
seta r_zproj “64”
seta r_flares “1”
seta r_lodbias “0”
seta r_lodCurveError “250”
seta r_ignoreDstAlpha “1”
seta r_shadowCascadeZBias “0”
seta r_shadowCascadeZFar “4096”
seta r_shadowCascadeZNear “2”
seta r_shadowMapSize “4096”
seta r_shadowBlur “1”
seta r_shadowFilter “1”
seta r_sunShadows “1”
seta r_sunlightMode “2”
seta r_drawSunRays “1”
seta r_genNormalMaps “0”
seta r_imageUpsampleType “1”
seta r_imageUpsampleMaxSize “1024”
seta r_imageUpsample “0”
seta r_mergeLightmaps “1”
seta r_pshadowDist “128”
seta r_dlightMode “2”
seta r_glossType “1”
seta r_baseGloss “0.3”
seta r_baseSpecular “0.04”
seta r_baseParallax “0.05”
seta r_baseNormalY “1.0”
seta r_baseNormalX “1.0”
seta r_pbr “0”
seta r_cubemapSize “64”
seta r_cubeMapping “1”
seta r_parallaxMapping “1”
seta r_deluxeMapping “1”
seta r_specularMapping “1”
seta r_normalMapping “1”
seta r_ssao “0”
seta r_depthPrepass “1”
seta r_autoExposure “1”
seta r_toneMap “1”
seta r_postProcess “1”
seta r_floatLightmap “1”
seta r_hdr “1”
seta r_greyscale “0”
seta r_stereoEnabled “0”
seta r_subdivisions “2”
seta r_vertexLight “0”
seta r_simpleMipMaps “1”
seta r_customheight “1024”
seta r_customwidth “1600”
seta r_noborder “0”
seta r_fullscreen “1”
seta r_mode “-2”
seta r_ignorehwgamma “0”
seta r_overBrightBits “0”
seta r_ext_multisample “4”
seta r_depthbits “24”
seta r_stencilbits “8”
seta r_colorbits “32”
seta r_texturebits “32”
seta r_detailtextures “1”
seta r_roundImagesDown “1”
seta r_picmip “0”
seta r_ext_max_anisotropy “16”
seta r_ext_texture_filter_anisotropic “1”
seta r_ext_direct_state_access “1”
seta r_arb_vertex_array_object “1”
seta r_arb_seamless_cube_map “1”
seta r_ext_framebuffer_multisample “8”
seta r_ext_texture_float “1”
seta r_ext_framebuffer_object “1”
seta r_ext_texture_env_add “1”
seta r_ext_compiled_vertex_array “1”
seta r_ext_multitexture “1”
seta r_ext_compressed_textures “0”
seta r_allowExtensions “1”

BTW: Glad you are here again! Do you plan to do more cool stuff for ioquake3’s renderer2 again, or even for Spearmint?


Well, the plan was to get back into mapping, but this new version of the renderer has put a monkey wrench it that. I just can’t get it to look right/as good as the old version.

I’ve tried all kinds of cvars, but the difference between the 2 versions is just as apparent with a clean cfg.

I can send you the pk3 with my custom models/materials if you want to take a look?


I think it would be better to post your shader here, so more intelligent people than me can have a look at your work. Maybe I’m wrong, but on your first screenshots the railgun looks okay even with Spearmint v0.3, the shotgun on the other hand look really ugly with Spearmint v0.3 (latest screenshot). So are all models are affected? Eventually some shader/mtr. stages are ‘wrong’ now. The quake3 shaders are okay (model head on the HUD)?
Can you post all shader/mtr. stages for the shotgun skin ‘officially’, here at the forums?

Ah, and you really use the very latest ioquake3 code? Zturtleman made some changes to the code concerning specular maps:


Just compiled the latest ioquake3 code and tested, and unfortunately, it looks exactly the same (minus sound, which just doesn’t work for some reason…) Here’s the mtr entry for the shotgun. This is the same code that worked perfectly fine in the old opengl2 renderer:

		map models/weapons2/shotgun/shotgun.tga
		rgbGen lightingDiffuse
            stage normalmap
            map models/weapons2/shotgun/shotgun_n.png
            normalScale 1 1
            parallaxDepth 0.05
            stage specularmap
            map models/weapons2/shotgun/shotgun_s.png
            specularReflectance 0.5
            specularExponent 16


Okay, I tested the shader you posted here.
I can confirm the issue, the specular map really looks ugly. It seems there is nothing we can do as far as the assets are concerned (shader/texture) etc. I used the shader from above, created my own testing textures (specular and normalmap texture). I tried different texture Format (.dds, .png, .tga, .jpg) - no difference.
Than I tried to manipulate the shader (sorting order, different lightmap stages etc.) - no difference.

All in all you really found a serious bug!
Best to open a new issue on ioquake3’s issue tracker and hope the author of the code will maintain the renderer and can fix the issue. If this won’t happen, we can compile the renderer to the specific commit where the bug was introduced (lot of work though).

Weird, to me it seems as if the normalmaps are also ‘broken’, at least it seems they aren’t lit at all (I will inspect this more…)

Here is the ioquake3 issue tracker:
And here is the screenshot that confirms your issue:

Sorry, that I couldn’t help so far, I’ll have a look at the rendering code, though I have no rendering experience.
Probably its really the best solution to stick to an older version, until this bug is fixed!



Yeah I figured as much. I’ll stick to the old version of the renderer and i’ll open an issue on the tracker (when I work out how, lol)
Thanks for looking into it though. I’m extremely surprised nobody noticed this before now. I literally just came back after not touching Quake 3 for 3 years, loaded up the latest ioquake3 with my custom pk3’s and the difference just slapped me right in the face. I was looking at it, thinking… what the hell has happened here… lol. I knew something major had been changed because my map textures were completely screwed up. Took me 2 days to workout what was causing that…

Anyway, glad to know I’ve helped in some way. Even if the solution is to just implement the “old” method of rendering normal/spec maps into the new version of the renderer, that would be fine imo!