0

我在这里遇到了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;
}
4

1 回答 1

0

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

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

于 2012-11-29T20:53:36.767 回答