2016-12-20 102 views
4

我使用的是OpenGL 4.0,GLSL 4.0,而不是GLEW或类似的,不是GLU或类似的,不是GLUT或类似的。 OpenCL或CUDA也被使用,但它们不涉及这种情况。双抛物面阴影贴图

我一直在试图解决我的问题几周没有成功,现在我希望有双抛物面阴影贴图经验的人可以给我建议。让我们直奔问题和检查一些照片(图1):

Picture_1

图片1包含了一些彩色箭头我需要解释一下。红色箭头显示我们应该看到的唯一正确的阴影。其他箭头表示阴影错误:黄色箭头显示由镶嵌引起的斑点,也许是蓝色箭头,但是它们的位置在前/后半球的边界上。绿色箭头指向不存在的锯齿图案(最近我们看到的例子中没有)。现在,它注意到,上面的图片是计算用下面的代码行是很重要的(代码1):

"swap.z=-sign(swap.z)*swap.z;\n" //mostly right results in the main project, but wrong way 

这行代码位于GLSL着色器程序,它是四位候选人我一直的一个在拍摄照片的主项目中尝试没有取得成功。但是,我们将会看到,代码4在单独的测试程序中工作。代码1实际上是完全错误的做DPSM的方法,但它是我主要项目获得阴影的唯一方式。接下来我们来看看同样的场景计算略有不同,但仍然是错误的代码行(图2和代码2):

Picture_2

"swap.z=sign(swap.z)*swap.z;\n" //almost dark picture, wrong way 

我们再次看到同样的场景,但现在我们使用完全不同的,正统代码线(图3和码3):

Picture_3

"swap.z=-(teDistance-n)/(f-n);\n" //lightning is mainly working but no shadows, should be the right way 

最后,我们看通过代码所计算的场景其中工程(几乎)完美的例子线,我们看到最近(图4和码4):

Picture_4

"swap.z=(teDistance-n)/(f-n);\n" //almost dark picture, doesn't work in the main project, but works in the test program, right way 

如果有人怀疑上面的图片中看到的文物是由于所谓的“阴影粉刺现象“,不,我认为他们不是。下面是一个有阴影痤疮模式我故意设置SHADOW_EPSILON = 0.000005f和关闭模糊制成(图5)图片:

Picture_5

在这一点上我必须说,我已经在两个运行程序独立的Windows 7.1笔记本电脑,其中一款采用nVIDIA GeForce GT 525M和另一款AMD Radeon R6。结果是相同的。编译器是Visual Studio 2010.在我看来,这是一个纯OpenGL相关的问题。

为了解决这个问题,我编写了一个单独的小测试程序,最后得到了阴影贴图的工作。据我所知,测试程序与制作图片1-5的程序几乎完全相同,但没有进行优化,并且一些矩阵乘法已从主机移动到着色器。测试程序源的相关部分如下。着色器第一:

static const char *vertex1= 
"#version 400 core\n" 

"layout (location=1) in vec3 vertexLocation;\n" 

"out vec3 vPosition;\n" 

"void main() {\n" 
    "vPosition=vertexLocation;\n" 
"}\0"; 




static const char *tessIn1= 
"#version 400 core\n" 

"layout (vertices=3) out;\n" 

"in vec3 vPosition[];\n" 
"out vec3 tcPosition[];\n" 

"void main() {\n" 
    "tcPosition[gl_InvocationID]=vPosition[gl_InvocationID];\n" 
    "if (gl_InvocationID==0) {\n" 

     "gl_TessLevelOuter[0]=max(distance(vPosition[1], vPosition[2]), 1.0);\n" 
     "gl_TessLevelOuter[1]=max(distance(vPosition[2], vPosition[0]), 1.0);\n" 
     "gl_TessLevelOuter[2]=max(distance(vPosition[0], vPosition[1]), 1.0);\n" 
     "gl_TessLevelInner[0]=max(0.33*(gl_TessLevelOuter[0]+gl_TessLevelOuter[1]+gl_TessLevelOuter[2]), 1.0);\n" 

    "}\n" 
"}\0"; 


static const char* tessOut1= 
"#version 400 core\n" 

"layout(triangles, equal_spacing, ccw) in;\n" 

"uniform mat4 model;\n" 
"uniform mat4 view;\n" 
"uniform mat4 lightOrientation;\n" 

"in vec3 tcPosition[];\n" 
"out float teDistance;\n" 
"out float teClip;\n" 

"const float n=0.5;\n" 
"const float f=20000.0;\n" 

"void main() {\n" 

    "vec3 accum=vec3(0.0);\n" 
    "accum=accum+gl_TessCoord.x*tcPosition[0];\n" 
    "accum=accum+gl_TessCoord.y*tcPosition[1];\n" 
    "accum=accum+gl_TessCoord.z*tcPosition[2];\n" 

// Transform position to the paraboloid's view space 
    "vec4 swap=lightOrientation*model*vec4(accum, 1.0);\n" 

//store the distance and other variables 
    "teDistance=abs(swap.z);\n" 
    "teClip=swap.z;\n" 

//calculate and set X and Y coordinates 
    "swap.xyz=normalize(swap.xyz);\n" 
    "if (swap.z<=0.0) {\n" 
     "swap.xy=swap.xy/(1.0-swap.z);\n" 
    "} else {\n" 
     "swap.xy=swap.xy/(1.0+swap.z);\n" 
    "}\n" 

//calculate and set Z and W coordinates 
// "swap.z=-sign(swap.z)*swap.z;\n" //Wrong way 
// "swap.z=sign(swap.z)*swap.z;\n" //Wrong way 
// "swap.z=-(teDistance-n)/(f-n);\n"  //Wrong way 
    "swap.z=(teDistance-n)/(f-n);\n"  //Right way 
    "swap.w=1.0;\n" 

    "gl_Position=swap;\n" 
"}\0"; 


static const char* geometry1= 
"#version 400 core\n" 

"layout(triangles) in;\n" 
"layout(triangle_strip, max_vertices=3) out;\n" 

"in float teDistance[];\n" 
"in float teClip[];\n" 
"out float gDistance;\n" 

"void main() {\n" 
    "for (int i=0; i<3; i++) {\n" 
     "gDistance=teDistance[i];\n" 
     "if (teClip[i]<=0.0) {\n" 
      "gl_Layer=0;\n" 
     "} else {\n" 
      "gl_Layer=1;\n" 
     "}\n" 
     "gl_Position=gl_in[i].gl_Position;\n" 
     "EmitVertex();\n" 
    "}\n" 
    "EndPrimitive();\n" 
"}\0"; 


static const char* fragment1= 
"#version 400 core\n" 

"in float gDistance;\n" 

"out vec2 fragmentVari;\n" 

"void main() {\n" 

    "fragmentVari=vec2(gDistance, gDistance*gDistance);\n" 

"}\0"; 


const char *vertex2= 
"#version 400 core\n" 

"layout (location=1) in vec3 vertexPosition;\n" 
"layout (location=2) in vec2 vertexTexCoord;\n" 
"layout (location=3) in vec3 vertexNormal;\n" 

"const float n=0.5;\n" 
"const float f=20000.0;\n" 

"uniform vec4 colour;\n" 
"uniform mat4 model;\n" 
"uniform mat4 view;\n" 
"uniform mat4 normal;\n" 
"uniform mat4 projection;\n" 
"uniform mat4 lightOrientation;\n" 

"out vec2 texKoord;\n" 
"out vec3 pointNormal;\n" 
"out vec3 point;\n" 
"out vec4 color;\n" 
"out vec4 vOriginPoint;\n" 

"void main() {\n" 
    "texKoord=vertexTexCoord;\n" 
    "pointNormal=normalize(vec3(normal*vec4(vertexNormal, 1.0)));\n" 
    "point=vec3(model*vec4(vertexPosition, 1.0));\n" 
    "color=colour;\n" 
    "vOriginPoint=vec4(vertexPosition, 1.0);\n" 
    "gl_Position=projection*view*model*vec4(vertexPosition, 1.0);\n" 
"}\0"; 


const char *fragment2= 
"#version 400 core\n" 

"uniform sampler2DArray tex1;\n" 

"uniform vec4 colour;\n" 
"uniform mat4 model;\n" 
"uniform mat4 view;\n" 
"uniform mat4 normal;\n" 
"uniform mat4 projection;\n" 
"uniform mat4 lightOrientation;\n" 

"in vec2 texKoord;\n" 
"in vec3 pointNormal;\n" 
"in vec3 point;\n" 
"in vec4 color;\n" 
"in vec4 vOriginPoint;\n" 
"out vec4 fragmentColor;\n" 

"const float SHADOW_EPSILON = 0.05f;\n" 
"const vec3 Ka=vec3(0.05, 0.05, 0.05);\n" //Ambient reflectivity 
"const vec3 Kd=vec3(1.0, 1.0, 1.0);\n" //Diffuse reflectivity 
"const float At=0.4;\n"     //Light attenuation 

"vec3 ads(in vec3 position, in vec3 normal) {\n" 
    "vec3 l=vec3(lightOrientation*model*vOriginPoint);\n" 
    "vec3 s=normalize(l - position);\n" 
    "vec3 intensity=vec3(0.5, 0.5, 0.5)*10.0;\n" 
    "float attenuation=1.0/(1.0+At*max(length(l), 1.0));\n" 
    "intensity=intensity*attenuation*Kd*abs(dot(s, normal));\n" 
    "return intensity;\n" 
"}\n" 

"float drawShadow() {\n" 
    "vec3 texKoord;\n" 
    "vec4 textureDepth;\n" 

    "vec4 originPoint=vec4(lightOrientation*model*vOriginPoint);\n" 
    "float distance=abs(originPoint.z);\n" 
    "vec3 normalized=normalize(originPoint.xyz);\n" 

    "if (normalized.z<=0.0) {\n" 
     "texKoord.xy=normalized.xy/(1.0-normalized.z);\n" 
     "texKoord.xy=0.5*texKoord.xy+0.5;\n" 
     "texKoord.z=0.0;\n" 
     "textureDepth=texture(tex1, texKoord);\n" 
    "} else {\n" 
     "texKoord.xy=normalized.xy/(1.0+normalized.z);\n" 
     "texKoord.xy=0.5*texKoord.xy+0.5;\n" 
     "texKoord.z=1.0;\n" 
     "textureDepth=texture(tex1, texKoord);\n" 
    "}\n" 

    "if (textureDepth.x+SHADOW_EPSILON>=distance) {\n" 
     "return 1.0;\n" 
    "} else {\n" 
     "return 0.0;\n" 
    "}\n" 
"}\n" 

"void main() {\n" 
    "vec4 lightning=vec4(Ka, 1.0);\n" 
    "swap2=swap2*drawShadow();\n" 
    "lightning=lightning+swap2;\n" 
    "fragmentColor=color*lightning;\n" 
"}\0"; 


const char *vertexLight= 
"#version 400 core\n" 

"layout (location=1) in vec3 vertexPosition;\n" 

"uniform mat4 view;\n" 
"uniform mat4 projection;\n" 
"uniform mat4 lightOrientation;\n" 

"void main() {\n" 
    "gl_Position=projection*view*lightOrientation*vec4(vertexPosition, 1.0);\n" 
"}\0"; 


const char *fragmentLight= 
"#version 400 core\n" 

"out vec4 fragmentColor;\n" 

"void main() {\n" 
    "fragmentColor=vec4(1.0, 1.0, 1.0, 1.0);\n" 
"}\0"; 

这里是显示功能:

void TForm1::display() 
{ 
    GLuint loc1, loc2, loc3, loc4, loc5, loc6; 
    float swap[16]; 
    float normal[16]={0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0}; 

//first we render a shadow map 
    { 
     glUseProgram(shaderT1); 
     glBindFramebuffer(GL_FRAMEBUFFER, frameBuffer[0]); 
     glClearColor(20000.0f, 0.0f, 0.0f, 0.0f); 
     glDepthMask(GL_TRUE); 
     glDepthRange(0, 1); 
     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 
     glViewport(0, 0, textureDim.x, textureDim.y); 
     glPatchParameteri(GL_PATCH_VERTICES, 3); 
     loc1=glGetUniformLocation(shaderT1, "model\0"); 
     loc2=glGetUniformLocation(shaderT1, "lightOrientation\0"); 
     loc3=glGetUniformLocation(shaderT1, "view\0"); 
     swap[0]=1.0; swap[1]=0.0; swap[2]=0.0; swap[3]=0.0; 
     swap[4]=0.0; swap[5]=1.0; swap[6]=0.0; swap[7]=0.0; 
     swap[8]=0.0; swap[9]=0.0; swap[10]=1.0; swap[11]=0.0; 
     swap[12]=-lightMatrix[12]; swap[13]=-lightMatrix[13]; swap[14]=-lightMatrix[14]; swap[15]=1.0; 
     glUniformMatrix4fv(loc1, 1, GL_FALSE, triangleMatrix); 
     glUniformMatrix4fv(loc2, 1, GL_FALSE, swap); 
     glUniformMatrix4fv(loc3, 1, GL_FALSE, view); 
     glBindVertexArray(VAO[1]); 
     glDrawArrays(GL_PATCHES, 0, 3); 
     glUniformMatrix4fv(loc1, 1, GL_FALSE, identity); 
     glUniformMatrix4fv(loc2, 1, GL_FALSE, swap); 
     glUniformMatrix4fv(loc3, 1, GL_FALSE, view); 
     glBindVertexArray(VAO[0]); 
     glDrawArrays(GL_PATCHES, 0, 6); 
    } 

//then we render the world and make use of that rendered shadow map 
    { 
     glUseProgram(shaderT2); 
     glBindFramebuffer(GL_FRAMEBUFFER, 0); 
     glDepthMask(GL_TRUE); 
     glDepthRange(0, 1); 
     glClearColor(0.0f, 1.0f, 0.0f, 0.0f); 
     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 
     glUniform1i(glGetUniformLocation(shaderT2, "tex1"), 1); 
     glActiveTexture(GL_TEXTURE0+1); 
     glBindTexture(GL_TEXTURE_2D_ARRAY, texID[0]); 
     glViewport(0, 0, 512, 512); 
     loc1=glGetUniformLocation(shaderT2, "model\0"); 
     loc2=glGetUniformLocation(shaderT2, "view\0"); 
     loc3=glGetUniformLocation(shaderT2, "normal\0"); 
     loc4=glGetUniformLocation(shaderT2, "colour\0"); 
     loc5=glGetUniformLocation(shaderT2, "projection\0"); 
     loc6=glGetUniformLocation(shaderT2, "lightOrientation\0"); 

//render a rectangle where the shadow is drawn onto 
     glUniformMatrix4fv(loc1, 1, GL_FALSE, identity); 
     glUniformMatrix4fv(loc2, 1, GL_FALSE, view); 
     matrixMultiply4D(swap, view, identity); 
     inverseMatrix4D(swap, swap); 
     transpose4D(normal, swap); 
     glUniformMatrix4fv(loc3, 1, GL_FALSE, normal); 
     glUniform4fv(loc4, 1, red); 
     glUniformMatrix4fv(loc5, 1, GL_FALSE, projection); 
     swap[0]=1.0; swap[1]=0.0; swap[2]=0.0; swap[3]=0.0; 
     swap[4]=0.0; swap[5]=1.0; swap[6]=0.0; swap[7]=0.0; 
     swap[8]=0.0; swap[9]=0.0; swap[10]=1.0; swap[11]=0.0; 
     swap[12]=-lightMatrix[12]; swap[13]=-lightMatrix[13]; swap[14]=-lightMatrix[14]; swap[15]=1.0; 
     glUniformMatrix4fv(loc6, 1, GL_FALSE, swap); 
     glBindVertexArray(VAO[0]); 
     glDrawArrays(GL_TRIANGLES, 0, 6); 

//render the triangle which makes a shadow 
     glUniformMatrix4fv(loc1, 1, GL_FALSE, triangleMatrix); 
     glUniformMatrix4fv(loc2, 1, GL_FALSE, view); 
     matrixMultiply4D(swap, view, triangleMatrix); 
     inverseMatrix4D(swap, swap); 
     transpose4D(normal, swap); 
     glUniformMatrix4fv(loc3, 1, GL_FALSE, normal); 
     glUniform4fv(loc4, 1, yellow); 
     glUniformMatrix4fv(loc5, 1, GL_FALSE, projection); 
     swap[0]=1.0; swap[1]=0.0; swap[2]=0.0; swap[3]=0.0; 
     swap[4]=0.0; swap[5]=1.0; swap[6]=0.0; swap[7]=0.0; 
     swap[8]=0.0; swap[9]=0.0; swap[10]=1.0; swap[11]=0.0; 
     swap[12]=-lightMatrix[12]; swap[13]=-lightMatrix[13]; swap[14]=-lightMatrix[14]; swap[15]=1.0; 
     glUniformMatrix4fv(loc6, 1, GL_FALSE, swap); 
     glBindVertexArray(VAO[1]); 
     glDrawArrays(GL_TRIANGLES, 0, 3); 
    } 

//finally render a white triangle which represents a location of the light 
    { 
     glUseProgram(shaderT3); 
     glBindFramebuffer(GL_FRAMEBUFFER, 0); 
     glDepthMask(GL_TRUE); 
     glDepthRange(0, 1); 
     glViewport(0, 0, 512, 512); 
     loc1=glGetUniformLocation(shaderT3, "view\0"); 
     loc2=glGetUniformLocation(shaderT3, "projection\0"); 
     loc3=glGetUniformLocation(shaderT3, "lightOrientation\0"); 
     glUniformMatrix4fv(loc1, 1, GL_FALSE, view); 
     glUniformMatrix4fv(loc2, 1, GL_FALSE, projection); 
     glUniformMatrix4fv(loc3, 1, GL_FALSE, lightMatrix); 
     glBindVertexArray(VAO[2]); 
     glDrawArrays(GL_TRIANGLES, 0, 3); 
    } 

    glFinish(); 

//rotate a light on it's orbit 
    matrixMultiply4D(lightMatrix, rotationMatrix, lightMatrix); 

} 

我已表示测试程序和代码线的上方1-4 4部电影。下面是电影1进行与代码1:

Movie_1

电影2与代码2:

Movie_2

电影3与代码3:

Movie_3

电影4代码4:

Movie_4

你可以看到电影4是唯一一个影子映射工作的地方(两个半球之间的边界区没有阴影,但我可以忍受。但是,如果有人知道如何解决它,如果你告诉我,我会很高兴)。但它在主项目中不起作用!我希望你能给我什么可能是错的建议,我应该怎么检查或给我你的工作的双抛物面阴影映射代码样本...

回答

0

好,回答我自己......

我发现我的bug:在渲染阴影贴图时,我也渲染了代表光线的白色球。它遮住了一切,这就是原因,字是黑暗的...

现在我的主要项目作为我的测试项目,但仍然存在半球之间令人讨厌的细线。有人知道我能做些什么吗?

+0

我遇到了同样的问题,我想我在两个抛物面之间的边界处出现了“接缝”线。请参阅:https://stackoverflow.com/questions/44118994/dual-paraboloid-shadow-texture-edge-seams这就是你所得到的? –