Hi all, I’m working on a project that runs on both PC and Android tablet at present. So far, I’ve found it great that I can basically use much of the same code, including the shaders. Now, I have some shadow shaders
#version 100 // version number that will ensure shader works with OpenGL ES 2.0.
#extension GL_EXT_shadow_samplers : enable // make sure sampler2DShadow is available if possible.
uniform sampler2DShadow s_shadowTex;
// if it was available, I use the OpenGL ES 2.0 projection function (mostly for mobile (android)).
mediump float shadow = shadow2DProjEXT(s_shadowTex, v_shadowCoord);
// Otherwise I use the standard shadow2DProj function.
mediump float shadow = shadow2DProj(s_shadowTex, v_shadowCoord).z;
Generally this approach has worked. That is, until I ran the software on my older laptop. The shader doesn’t output any errors or warnings, but doesn’t actually output any fragments: it acts though GL_EXT_shadow_samplers is defined, but so long as I remove a call to shadow2DProjEXT, it works (although I don’t get to use my shadow-texture that way). I’m a little confused. I quite like error messages but the shader seems to compile without error, it just doesn’t actually run.
You may be curious as to how I know that the shader fails with shadow2DProjEXT, even though there is no error provided. Simply, I tried setting the fragment to pure red:
gl_FragColor.rgb = vec3(1,0,0);
and the fragments continued to be rendered black. If I then removed the call to shadow2DProjEXT, the fragments were rendered red. The only difference was the call to shadow2DProjEXT (I had removed the term returned from this function from any later calculations, btw).
Further, the extension certainly seems to be available. If I omit
#extension GL_EXT_shadow_samplers : enable
then I am given the error:
error C7531: global function shadow2DProjEXT requires “#extension GL_EXT_shadow_samplers : enable” before use
This is most frustrating… I have of course discovered that if I set the version directive to 120, then I can simply use shadow2DProj, and works fine, but I then fear (without having tested) that this version number will cause my shader to not be compiled on ES 2.0 devices (or w, just some of them!).
I’m assuming this is a driver error? I’m totally up to date with my drivers though. Would really prefer just having single shaders that cover all target hardware.
What you’re doing to get access to the shadow sampler and lookup function looks correct to me (for OpenGL ES 2.0 SL).
Though it sounds like you are trying to compile the same shader source under an OpenGL implementation on your laptop, not an OpenGL ES implementation or emulator. That seems to be the cause of your problems.
OpenGL’s shading language (GLSL) is very similar but still different from OpenGL ES’s shading language. For example, there is no EXT_shadow_samplers in GLSL nor version 1.00 in OpenGL’s shading language. Take a look here to confirm that.
I’d suggest you use a GLES emulator on the PC (examples: ImgTech’s PVRVFrame in the PowerVR SDK, ANGLE, Mesa3D’s, Qualcomm’s, or GLES profile support in the native OpenGL drivers, if supported). Then you can use the same source and in most cases still get GPU hardware acceleration support on PCs. The exception being Mesa3D which is a software emulation. Re GLES profile support in the native OpenGL drivers, look for the presence of GLX_EXT_create_context_es_profile (Linux) or WGL_EXT_create_context_es_profile (Windows) in the supported GL extensions for your driver. For a usage example, see pg 33 here.
Alternatively, have separate shader source for GL-SL and GLES-SL, either statically or via dynamic constructed (e.g. to get the #version, #extension, and possibly some header #defines right for GLES vs. GL).
Here’s hoping Vulkan spreads quickly, along with EGL support on the desktop. This’ll help get rid of the cross-GPU portability gotchas like this between mobile and desktop.