OSG: GLSL Shader работает на AMD, но не на NVIDIA

В настоящее время я работаю над проектом OSG для своего исследования и написал шейдер CelShading (наряду с простым шейдером Fog). Сначала я рендерил с CelShader вместе с буфером глубины в Texture, а затем использую fogShader. Все отлично работает на моем AMD Radeon HD 7950 и на моем Intel HD4400 (хотя это медленно на последнем), оба работают под управлением Windows. Однако в Linux, работающем на Quadro 600, шейдер компилируется без ошибок, но все равно ошибается, свет тускнеет, и из-за отсутствия некоторых световых пятен кажется, что не все источники света в сцене используются. Весь мультяшный эффект тоже пропал. Я подтвердил, что шейдер работает на другом AMD, ATI Mobility HD3400.

Но на других NVIDIA, таких как GTX 670 или 660 TI или 560 TI (это временные окна), шейдер не работает. Сначала это было полностью испорчено из-за неоднородного потока, но после того, как я исправил это, это все еще не работает.

У меня есть эта проблема в течение нескольких дней, и она вызывает у меня головную боль. Я не знаю, что мне не хватает, почему он работает на простом Intel HD 4400, но не на высокопроизводительных картах NVIDIA? Как ни странно, fogShader отлично работает на всех системах и дает мне хороший туман, который я хочу. У кого-нибудь есть идея? Униформа установлена ​​для toonTex, но texture0 не установлена, потому что модель отображена в ультрафиолетовом свете с помощью blender, но текстуры, кажется, работают очень хорошо (посмотрите на Pony на экранах). Я предполагаю, что 0 используется в качестве макета для texture0, что, насколько я знаю, совершенно правильно. Вот видео, показывающее шейдер на GTX 660 TI. Кажется, что-то работает, если есть только один свет, но это не так, как должно выглядеть, на Radeon HD 7950 это так (игнорируйте черную рамку, проблема с скриншотами).

Свет ясен по-другому.

РЕДАКТИРОВАТЬ: Только что сделал еще один тест: на Intel HD 4400 и Windows, он работает. Но та же самая система под управлением Linux показывает только много белого с некоторыми контурами, но без текстур вообще. Есть какие-нибудь предложения? Источники для шейдеров здесь:

celShader.vert

#version 120
varying vec3 normalModelView;
varying vec4 vertexModelView;
uniform bool zAnimation;
uniform float osg_FrameTime;
void main()
{   
    normalModelView = gl_NormalMatrix * gl_Normal;
    vertexModelView = gl_ModelViewMatrix * gl_Vertex;
    gl_TexCoord[0] = gl_MultiTexCoord0;

    vec4 vertexPos = gl_Vertex;
    if(zAnimation){//
        vertexPos.z = sin(5.0*vertexPos.z + osg_FrameTime)*0.25;//+ vertexPos.z;    
    }
    gl_Position = gl_ModelViewProjectionMatrix * vertexPos;     

}

celShader.frag

#version 120 
#define NUM_LIGHTS 5
uniform sampler2D texture0;
uniform sampler2D toonTex;
uniform float osg_FrameTime;
uniform bool tex;
varying vec3 normalModelView;
varying vec4 vertexModelView;

vec4 calculateLightFromLightSource(int lightIndex, bool front){
    vec3 lightDir;
    vec3 eye = normalize(-vertexModelView.xyz);
    vec4 curLightPos = gl_LightSource[lightIndex].position;
    //curLightPos.z = sin(10*osg_FrameTime)*4+curLightPos.z;
    lightDir = normalize(curLightPos.xyz - vertexModelView.xyz);

    float dist = distance( gl_LightSource[lightIndex].position, vertexModelView );
    float attenuation =  1.0 / (gl_LightSource[lightIndex].constantAttenuation
                 + gl_LightSource[lightIndex].linearAttenuation * dist 
                 + gl_LightSource[lightIndex].quadraticAttenuation * dist * dist);

    float z = length(vertexModelView);
    vec4 color;
    vec3 n = normalize(normalModelView);
    vec3 nBack = normalize(-normalModelView);
    float intensity = dot(n,lightDir); //NdotL, Lambert
    float intensityBack = dot(nBack,lightDir); //NdotL, Lambert
    //-Phong Modell
    vec3 reflected = normalize(reflect( -lightDir, n));
    float specular = pow(max(dot(reflected, eye), 0.0), gl_FrontMaterial.shininess);
    vec3 reflectedBack = normalize(reflect( -lightDir, nBack));
    float specularBack = pow(max(dot(reflectedBack, eye), 0.0), gl_BackMaterial.shininess);
    //Toon-Shading
    //2D Toon http://www.cs.rpi.edu/~cutler/classes/advancedgraphics/S12/final_projects/hutchins_kim.pdf        
    vec4 toonColor = texture2D(toonTex,vec2(intensity,specular));
    vec4 toonColorBack = texture2D(toonTex,vec2(intensityBack,specularBack));
    if(front){  
        color += gl_FrontMaterial.ambient * gl_LightSource[lightIndex].ambient[lightIndex];
        if(intensity > 0.0){
            color += gl_FrontMaterial.diffuse * gl_LightSource[lightIndex].diffuse * intensity * attenuation ;
            color += gl_FrontMaterial.specular * gl_LightSource[lightIndex].specular * specular *attenuation ;
        }
        return color  * toonColor;
    } else {//back  
        color += gl_BackMaterial.ambient * gl_LightSource[lightIndex].ambient[lightIndex];
        if(intensity > 0.0){
            color += gl_BackMaterial.diffuse * gl_LightSource[lightIndex].diffuse * intensityBack * attenuation ;
            color += gl_BackMaterial.specular * gl_LightSource[lightIndex].specular * specularBack *attenuation ;
        }
        return color  * toonColorBack;
    }   
}

void main(void) {
    vec4 color = vec4(0.0);
    bool front = true;
    //non-uniform-flow error correction
    //see more here: http://www.opengl.org/wiki/GLSL_Sampler#Non-uniform_flow_control
    //and here: http://gamedev.stackexchange.com/questions/32543/glsl-if-else-statement-unexpected-behaviour
    vec4 texColor = texture2D(texture0,gl_TexCoord[0].xy);
    if(!gl_FrontFacing)
        front = false;
    for(int i = 0; i< NUM_LIGHTS; i++){
        color += calculateLightFromLightSource(i,front);
        }
    if(tex) 
        gl_FragColor =color * texColor;
    else
        gl_FragColor = color;
  }

fogShader.vert

#version 120
varying vec4 vertexModelView;
void main()
{   
  gl_Position = ftransform();       
  vertexModelView = gl_ModelViewMatrix * gl_Vertex;
  gl_TexCoord[0] = gl_MultiTexCoord0;
}

fogShader.frag

varying vec4 vertexModelView;
uniform sampler2D texture0;
uniform sampler2D deepth;
uniform vec3 fogColor;
uniform float zNear;
uniform float zFar;

float linearDepth(float z){
    return (2.0 * (zNear+zFar)) / ((zFar + zNear) - z * (zFar - zNear));// -1.0;    
}

void main(void){
    //Literature
    //http://www.ozone3d.net/tutorials/glsl_fog/p04.php and depth_of_field example OSG Cookbook
    vec2 deepthPoint = gl_TexCoord[0].xy;
    float z = texture2D(deepth, deepthPoint).x;
    //fogFactor = (end - z) / (end - start)
    z = linearDepth(z); 
        float fogFactor = (4000*4-z) / (4000*4 - 30*4);
    fogFactor = clamp(fogFactor, 0.0, 1.0);

    vec4 texColor = texture2D(texture0,gl_TexCoord[0].xy);

    gl_FragColor = mix(vec4(fogColor,1.0), texColor,fogFactor);

}

ProgramLinking

 osg::ref_ptr<osg::Shader> toonFrag = osgDB::readShaderFile("../Shader/celShader.frag");
 osg::ref_ptr<osg::Shader> toonVert = osgDB::readShaderFile("../Shader/" +  _vertSource);
 osg::ref_ptr<osg::Program> celShadingProgram = new osg::Program;
 celShadingProgram->addShader(toonFrag);
 celShadingProgram->addShader(toonVert);

 osg::ref_ptr<osg::Texture2D> toonTex = new osg::Texture2D;
 toonTex->setImage(osgDB::readImageFile("../BlenderFiles/Texturen/toons/" + _toonTex));
 toonTex->setFilter(osg::Texture::MIN_FILTER, osg::Texture::NEAREST);
 toonTex->setFilter(osg::Texture::MAG_FILTER, osg::Texture::NEAREST);

 osg::ref_ptr<osg::StateSet> ss = new osg::StateSet;




 ss->setTextureAttributeAndModes(1, toonTex, osg::StateAttribute::OVERRIDE | osg::StateAttribute::ON);
 ss->addUniform(new osg::Uniform("toonTex", 1));
 ss->setAttributeAndModes(celShadingProgram, osg::StateAttribute::OVERRIDE | osg::StateAttribute::ON);

                    //TODO NEEED?
 ss->setTextureMode(1, GL_TEXTURE_1D, osg::StateAttribute::OVERRIDE | osg::StateAttribute::OFF);


 ss->addUniform(new osg::Uniform("tex", true));
 ss->addUniform(new osg::Uniform("zAnimation", false));

1 ответ

Решение

Хорошо, я наконец нашел ошибку. Начиная с нулевой версии моего шейдера произошла неисправная линия, которую я пропускал целую неделю (и я удивлен, что мой драйвер AMD не дал мне ошибку, это было просто неправильно! РЕДАКТИРОВАТЬ: совсем не так, см. Комментарий ниже!). Эти две строки были разбиты:

 color += gl_FrontMaterial.ambient * gl_LightSource[lightIndex].ambient[lightIndex];
 color += gl_BackMaterial.ambient * gl_LightSource[lightIndex].ambient[lightIndex];

эмбиент конечно не массив....

Другие вопросы по тегам