Я работаю над кроссплатформенным рендерером для Windows и iOS. Для примера приложения я написал шейдер, который без проблем работал на обеих платформах (версия шейдера «#версия 120» в Windows и «#версия 100» в iOS).
Далее я добавил еще два источника света и на iOS начали происходить странные вещи. Я несколько раз переделывал свой код, но он так и не показал ожидаемого результата (факел рендерится с помощью шейдера только с одним источником света, поэтому на iOS он выглядит нормально).
(1) Иногда всё было одного цвета:
(2) А иногда это выглядело просто ужасно в любом случае:
В Windows это выглядит так, как я ожидал:
Кто-нибудь знает, почему мой шейдер делает это на iOS?
Это мой фрагментный шейдер для (2):
//Light
uniform mediump float numLights;
//L0
uniform mediump vec4 lightPosition_0;
uniform mediump vec3 lightColor_0;
uniform mediump float lightIntensity_0;
uniform mediump float lightAttenuation_0;
//L1
/*same as for light 0 */
//L2
/*same as for light 0 */
uniform mediump vec3 ambientColor;
uniform mediump vec3 Ka;
uniform mediump vec3 Kd;
uniform mediump vec3 Ks;
uniform sampler2D NormalMap;
uniform sampler2D DiffuseMap;
uniform sampler2D SpecularMap;
varying highp vec4 texCoordVarying;
varying highp vec4 posWorldSpace; // pos in View Space
varying highp vec3 tangentSurface2light_0;
varying highp vec3 tangentSurface2light_1;
varying highp vec3 tangentSurface2light_2;
void main()
{
//normal based on normal map
highp vec3 normalNormalMap = normalize(texture2D(NormalMap, texCoordVarying.st).xyz *2.0 - 1.0);
//ambient light
highp vec3 ambient = clamp(ambientColor + Ka, 0.0, 1.0);
//diffuse light
highp vec3 diffuse;
// light 0
if(numLights >= 1.0)
{
//light intensity based on distance from light to object
highp float distance = distance(posWorldSpace, lightPosition_0);
highp float intensityBasedOnDist = lightIntensity_0/(lightAttenuation_0*distance*distance);
intensityBasedOnDist = clamp(intensityBasedOnDist, 0.0, 1.0);
//light intensity based on angle between normal and light vector
highp float intensity = max(dot(normalNormalMap,tangentSurface2light_0), 0.0) ;
intensity = clamp(intensity, 0.0, 1.0);
//diffuse light
diffuse += lightColor_0 * intensity * intensityBasedOnDist;
}
// light 1
if(numLights >= 2.0)
{
/*same as for light 0 */
}
// light 2
if(numLights >= 3.0)
{
/*same as for light 0 */
}
diffuse = diffuse * Kd * texture2D(DiffuseMap, texCoordVarying.st).xyz;
gl_FragColor = vec4(clamp(ambient + diffuse, 0.0, 1.0), 1.0);
}
Я сделал много вещей highp или mediump. Когда я делал все на высоте, иногда это выглядело почти правильно, но теперь даже этот трюк, похоже, уже не помогает...