这里有一个关于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;
}
答案 0 :(得分:0)
您是否将着色器选择模式与着色器一起使用?如果是这样,这可能是您的问题:选择模式可能会触发回退到软件实现;我知道在GPU上没有选择模式的OpenGL实现。由于这个代码路径很少被使用,因此它很可能是错误的。特别是如果与着色器一起使用,必须在GPU上进行仿真。如果着色器JIT编译器发出错误代码,您将会崩溃。
最重要的是,选择模式已从全新的OpenGL版本中删除。您应该使用单通道整数颜色缓冲附件渲染到Framebuffer对象,而不是选择模式(容易出错且速度慢)。每个对象都以不同的“索引”颜色呈现。通过回读索引图像,您可以根据像素值进行选择。这实际上可以与选择投影矩阵组合,以将片段生成限制为视图体积的一小部分。