OpenGl选择和着色器(用于照明)在某些GPU上崩溃(主要是ati)

时间:2012-11-29 19:53:38

标签: opengl 3d glsl

这里有一个关于opengl选择和着色器的问题。

我们正在使用着色器进行phong照明。着色器工作得很好。但是,如果我们使用我们的opengl选择与我们的着色器结合使用应用程序崩溃。这种组合在5台以上的计算机上运行良好(Geforce gtx 460 SE,Ati Mobility Radeon HD 5850,Intel Graphic 4000等......)。但由于一些不明原因,我们崩溃了这些错误:

#
# A fatal error has been detected by the Java Runtime Environment:
#
#  EXCEPTION_ACCESS_VIOLATION (0xc0000005) at pc=0x000000000cde9cc3, pid=2888, tid=3940
#
# JRE version: 7.0_07-b10
# Java VM: Java HotSpot(TM) 64-Bit Server VM (23.3-b01 mixed mode windows-amd64 compressed oops)
# Problematic frame:
# C  [ig4icd64.dll+0x6d9cc3]  ShCompile+0x17b3b3
#
# Failed to write core dump. Minidumps are not enabled by default on client versions of Windows
#
# An error report file with more information is saved as:
# C:\Projet2\Exe\hs_err_pid2888.log
#
# If you would like to submit a bug report, please visit:
#   http://bugreport.sun.com/bugreport/crash.jsp
# The crash happened outside the Java Virtual Machine in native code.
# See problematic frame for where to report the bug.
#

看起来编译不起作用。在工作的计算机上,我们没有编译错误(使用glGetShaderInfoLog)。

同样的事情发生在AMD Radeon HD 6970M上,但错误与atixxxx.dll有关。

这是我们的opengl选择:

GLint viewport[4];
glSelectBuffer(BUFSIZE,selectBuf);
glRenderMode(GL_SELECT);

glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();

glGetIntegerv(GL_VIEWPORT,viewport);
gluPickMatrix(x,viewport[3]-y, 5,5,viewport);

FacadeModele::obtenirInstance()->obtenirVue()->obtenirProjection()->appliquer();

glMatrixMode(GL_MODELVIEW);
glInitNames();

glLoadIdentity();
FacadeModele::obtenirInstance()->obtenirVue()->obtenirCamera().positionner();

arbre->afficher();
int hits;

// restorer la matrice originale
glMatrixMode(GL_PROJECTION);
glPopMatrix();
glMatrixMode(GL_MODELVIEW);
glFlush();

// retourner au mode de rendering normal
hits = glRenderMode(GL_RENDER);

if (hits > 0)
    processHits(hits,selectBuf);

我们的顶点着色器:

varying vec3 normal, lightDir1, lightDir2, lightDir3, eyeVec;
void main()
{
// calculer la normale qui sera interpolée pour le nuanceur de fragment
normal = gl_NormalMatrix * gl_Normal;

// calculer la position du sommet dans l'espace de la caméra ("eye-coordinate position")
vec3 ecPosition = vec3( gl_ModelViewMatrix * gl_Vertex );

// vecteur de la direction de la lumière
lightDir1 = vec3( gl_LightSource[0].position.xyz - ecPosition );
lightDir2 = vec3( gl_LightSource[1].position.xyz - ecPosition );
lightDir3 = vec3( gl_LightSource[2].position.xyz - ecPosition );

eyeVec = -ecPosition; // vecteur qui pointe vers le (0,0,0), c'est-à-dire vers l'oeil
gl_FrontColor = gl_Color;
// transformation standard du sommet (ModelView et Projection)
gl_Position = ftransform();
}

我们的片段着色器:

varying vec3 normal, lightDir1, lightDir2, lightDir3, eyeVec;
float maxCutoff = 0.9;

void main(void)
{
    vec4 couleur = ( ( gl_FrontLightModelProduct.sceneColor * gl_FrontMaterial.ambient ) +
                    ( gl_LightSource[0].ambient * gl_FrontMaterial.ambient ) +
                    ( gl_LightSource[1].ambient * gl_FrontMaterial.ambient ) 
                );
    // vecteur normal
    vec3 N = normalize( normal );
    // direction de la lumière
    vec3 L = normalize( lightDir1 );
    // produit scalaire pour le calcul de la réflexion diffuse
    float NdotL = dot( N, L );

    vec3 D = normalize(gl_LightSource[0].spotDirection);
    float LdotD = dot(-L,D);
    float attenuation = (LdotD - maxCutoff)/(gl_LightSource[0].spotCosCutoff-maxCutoff)  ;

    // calcul de l'éclairage seulement si le produit scalaire est positif
    if ( NdotL > 0.0 )
    {
        // calcul de la composante diffuse
        if(attenuation > 0.0)
            couleur += gl_LightSource[0].diffuse * gl_FrontMaterial.diffuse * NdotL*attenuation;

        // calcul de la composante spéculaire
        vec3 E = normalize( eyeVec );
        vec3 R = -reflect( L, N ); // réflexion de L par rapport à N
        // produit scalaire pour la réflexion spéculaire
        float NdotHV = max( dot( R, E ), 0.0 );
        couleur += gl_LightSource[0].specular * gl_FrontMaterial.specular * pow( NdotHV, gl_FrontMaterial.shininess )*attenuation;
    }

    // vecteur normal
    vec3 N2 = normalize( normal );
    // direction de la lumière
    vec3 L2 = normalize( lightDir2 );
    // produit scalaire pour le calcul de la réflexion diffuse
    float NdotL2 = dot( N2, L2 );

    vec3 D2 = normalize(gl_LightSource[1].spotDirection);
    float LdotD2 = dot(-L2,D2);
    float attenuation2 = (LdotD2 - maxCutoff)/(gl_LightSource[1].spotCosCutoff-maxCutoff)  ;

    // calcul de l'éclairage seulement si le produit scalaire est positif
    if ( NdotL2 > 0.0 )
    {
        // calcul de la composante diffuse
        if(attenuation2 > 0.0)
            couleur += gl_LightSource[1].diffuse * gl_FrontMaterial.diffuse * NdotL2*attenuation2;

        // calcul de la composante spéculaire
        vec3 E2 = normalize( eyeVec );
        vec3 R2 = -reflect( L2, N2 ); // réflexion de L par rapport à N
        // produit scalaire pour la réflexion spéculaire
        float NdotHV2 = max( dot( R2, E2 ), 0.0 );
    }

    // vecteur normal
    vec3 N3 = normalize( normal );
    // direction de la lumière
    vec3 L3 = normalize( lightDir3 );
    // produit scalaire pour le calcul de la réflexion diffuse
    float NdotL3 = dot( N3, L3 );

    vec3 D3 = normalize(gl_LightSource[2].spotDirection);
    float LdotD3 = dot(-L3,D3);
    float attenuation3 = (LdotD3 - maxCutoff)/(gl_LightSource[2].spotCosCutoff-maxCutoff)  ;

    // calcul de l'éclairage seulement si le produit scalaire est positif
    if ( NdotL3 > 0.0 )
    {
        // calcul de la composante diffuse
        if(attenuation3 > 0.0)
            couleur += gl_LightSource[2].diffuse * gl_FrontMaterial.diffuse * NdotL3*attenuation3;

        // calcul de la composante spéculaire
        vec3 E3 = normalize( eyeVec );
        vec3 R3 = -reflect( L3, N3 ); // réflexion de L par rapport à N
        // produit scalaire pour la réflexion spéculaire
        float NdotHV3 = max( dot( R3, E3 ), 0.0 );
    }

    couleur *= gl_Color;
    gl_FragColor = couleur;
}

1 个答案:

答案 0 :(得分:0)

您是否将着色器选择模式与着色器一起使用?如果是这样,这可能是您的问题:选择模式可能会触发回退到软件实现;我知道在GPU上没有选择模式的OpenGL实现。由于这个代码路径很少被使用,因此它很可能是错误的。特别是如果与着色器一起使用,必须在GPU上进行仿真。如果着色器JIT编译器发出错误代码,您将会崩溃。

最重要的是,选择模式已从全新的OpenGL版本中删除。您应该使用单通道整数颜色缓冲附件渲染到Framebuffer对象,而不是选择模式(容易出错且速度慢)。每个对象都以不同的“索引”颜色呈现。通过回读索引图像,您可以根据像素值进行选择。这实际上可以与选择投影矩阵组合,以将片段生成限制为视图体积的一小部分。