c – 双抛物面阴影映射
我使用的是OpenGL 4.0,GLSL 4.0,不是GLEW或类似的,不是GLU或类似的,不是GLUT或类似的.也使用OpenCL或CUDA,但它们不涉及这种情况.
我一直试图解决我的问题几周没有成功,现在我希望有双抛物面阴影映射经验的人可以给我建议.让我们直接解决问题并检查一些图片(图片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): "swap.z=sign(swap.z)*swap.z;n" //almost dark picture,wrong way 我们再次看同一个场景,但现在我们使用完全不同的正统代码行(图3和代码3): "swap.z=-(teDistance-n)/(f-n);n" //lightning is mainly working but no shadows,should be the right way 最后,我们看一下代码行计算的场景,它在我们最近看到的例子中(几乎)完美地工作(图4和代码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)故意制作阴影痤疮图案的图片: 在这一点上,我需要说,我在两台独立的Windows 7.1笔记本电脑上运行程序,一台配备nVIDIA GeForce GT 525M,另一台配备AMD Radeon R6.结果是一样的.编译器是Visual Studio 2010.在我看来,这是一个纯粹的OpenGL相关问题. 为了解决这个问题,我写了一个单独的小测试程序,最后得到了阴影贴图.据我所知,测试程序的工作方式与制作图片1-5的程序非常相似,但没有优化,并且许多矩阵乘法已经从主机移动到着色器.测试程序源的相关部分如下.着色器优先: static const char *vertex1= "#version 400 coren" "layout (location=1) in vec3 vertexLocation;n" "out vec3 vPosition;n" "void main() {n" "vPosition=vertexLocation;n" "} "; static const char *tessIn1= "#version 400 coren" "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" "} "; static const char* tessOut1= "#version 400 coren" "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" "} "; static const char* geometry1= "#version 400 coren" "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" "} "; static const char* fragment1= "#version 400 coren" "in float gDistance;n" "out vec2 fragmentVari;n" "void main() {n" "fragmentVari=vec2(gDistance,gDistance*gDistance);n" "} "; const char *vertex2= "#version 400 coren" "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" "} "; const char *fragment2= "#version 400 coren" "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" "} "; const char *vertexLight= "#version 400 coren" "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" "} "; const char *fragmentLight= "#version 400 coren" "out vec4 fragmentColor;n" "void main() {n" "fragmentColor=vec4(1.0,1.0);n" "} "; 这是显示功能: void TForm1::display() { GLuint loc1,loc2,loc3,loc4,loc5,loc6; float swap[16]; float normal[16]={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); glDepthMask(GL_TRUE); glDepthRange(0,1); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glViewport(0,textureDim.x,textureDim.y); glPatchParameteri(GL_PATCH_VERTICES,3); loc1=glGetUniformLocation(shaderT1,"model "); loc2=glGetUniformLocation(shaderT1,"lightOrientation "); loc3=glGetUniformLocation(shaderT1,"view "); 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,swap); glUniformMatrix4fv(loc3,view); glBindVertexArray(VAO[1]); glDrawArrays(GL_PATCHES,3); glUniformMatrix4fv(loc1,identity); glUniformMatrix4fv(loc2,view); glBindVertexArray(VAO[0]); glDrawArrays(GL_PATCHES,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); 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,512,512); loc1=glGetUniformLocation(shaderT2,"model "); loc2=glGetUniformLocation(shaderT2,"view "); loc3=glGetUniformLocation(shaderT2,"normal "); loc4=glGetUniformLocation(shaderT2,"colour "); loc5=glGetUniformLocation(shaderT2,"projection "); loc6=glGetUniformLocation(shaderT2,"lightOrientation "); //render a rectangle where the shadow is drawn onto glUniformMatrix4fv(loc1,view); matrixMultiply4D(swap,view,identity); inverseMatrix4D(swap,swap); transpose4D(normal,normal); glUniform4fv(loc4,red); glUniformMatrix4fv(loc5,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,swap); glBindVertexArray(VAO[0]); glDrawArrays(GL_TRIANGLES,6); //render the triangle which makes a shadow glUniformMatrix4fv(loc1,triangleMatrix); inverseMatrix4D(swap,swap); transpose4D(normal,yellow); glUniformMatrix4fv(loc5,swap); glBindVertexArray(VAO[1]); glDrawArrays(GL_TRIANGLES,3); } //finally render a white triangle which represents a location of the light { glUseProgram(shaderT3); glBindFramebuffer(GL_FRAMEBUFFER,1); glViewport(0,512); loc1=glGetUniformLocation(shaderT3,"view "); loc2=glGetUniformLocation(shaderT3,"projection "); loc3=glGetUniformLocation(shaderT3,"lightOrientation "); glUniformMatrix4fv(loc1,view); glUniformMatrix4fv(loc2,projection); glUniformMatrix4fv(loc3,lightMatrix); glBindVertexArray(VAO[2]); glDrawArrays(GL_TRIANGLES,3); } glFinish(); //rotate a light on it's orbit matrixMultiply4D(lightMatrix,rotationMatrix,lightMatrix); } 我拍了四部电影代表上面的测试程序和代码行1-4.下面是用代码1完成的电影1: Movie_1 电影2代码2: Movie_2 电影3代码3: Movie_3 电影4代码4: Movie_4 你可以看到Movie 4是唯一一个阴影贴图工作的地方(两个半球之间的边界区域没有阴影,但我可以忍受.但是,如果有人知道如何修复它,我会很高兴如果你告诉我).但它不适用于主项目!我希望你能给我一些关于可能出错的建议,我应该检查或给你你的双抛物面阴影映射代码样本…… 解决方法
好吧,回答自己……
我发现了我的错误:在渲染阴影贴图时,我还渲染了代表光线的白球.它掩盖了一切,这就是一个词是黑暗的原因…… 现在我的主要项目是我的测试项目,但是半球之间仍然存在令人讨厌的细线.有谁知道我能为此做些什么? (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |