jjzjj

c++ - 双抛物面阴影贴图

coder 2024-02-25 原文

我使用的是 OpenGL 4.0、GLSL 4.0,不是 GLEW 或类似软件,不是 GLU 或类似软件,不是 GLUT 或类似软件。 OpenCL 或 CUDA 也被使用,但它们不在本例中。

几周来我一直在尝试解决我的问题,但没有成功,现在我希望有双抛物面阴影贴图经验的人能给我建议。让我们直接进入问题并检查一些图片(图片 1):

图 1 包含一些我需要解释的彩色箭头。红色箭头显示了我们应该看到的唯一正确的阴影。其他箭头表示阴影错误:黄色箭头表示由镶嵌造成的 Blob ,蓝色箭头可能也是,但它们的位置在前半球/后半球的边界上。绿色箭头指向不应该存在的锯齿图案(在我们最近看到的示例中不存在)。现在请务必注意,上面的图片是使用以下代码行(代码 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 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。下面是用代码 1 完成的电影 1:

Movie_1

带有代码 2 的电影 2:

Movie_2

带有代码 3 的电影 3:

Movie_3

带有代码 4 的电影 4:

Movie_4

你可以看到电影 4 是唯一一个阴影映射有效的电影(两个半球之间的边界区域没有阴影,但我可以接受。但是,如果有人知道如何修复它,我'如果你告诉我,我会很高兴)。但它在主项目中不起作用!我希望你能给我一些建议,告诉我可能出了什么问题,我应该检查什么,或者给我你的工作双抛物面阴影映射代码示例......

最佳答案

好吧,我自己回答...

我发现了我的错误:在渲染阴影贴图时,我还渲染了代表光的白球。它遮挡了一切,这就是单词变暗的原因......

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

关于c++ - 双抛物面阴影贴图,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41246783/

有关c++ - 双抛物面阴影贴图的更多相关文章

  1. ruby-on-rails - 如何优雅地重启 thin + nginx? - 2

    我的瘦服务器配置了nginx,我的ROR应用程序正在它们上运行。在我发布代码更新时运行thinrestart会给我的应用程序带来一些停机时间。我试图弄清楚如何优雅地重启正在运行的Thin实例,但找不到好的解决方案。有没有人能做到这一点? 最佳答案 #Restartjustthethinserverdescribedbythatconfigsudothin-C/etc/thin/mysite.ymlrestartNginx将继续运行并代理请求。如果您将Nginx设置为使用多个上游服务器,例如server{listen80;server

  2. ruby - 使用 `+=` 和 `send` 方法 - 2

    如何将send与+=一起使用?a=20;a.send"+=",10undefinedmethod`+='for20:Fixnuma=20;a+=10=>30 最佳答案 恐怕你不能。+=不是方法,而是语法糖。参见http://www.ruby-doc.org/docs/ProgrammingRuby/html/tut_expressions.html它说Incommonwithmanyotherlanguages,Rubyhasasyntacticshortcut:a=a+2maybewrittenasa+=2.你能做的最好的事情是:

  3. ruby - 如何计算 Liquid 中的变量 +1 - 2

    我对如何计算通过{%assignvar=0%}赋值的变量加一完全感到困惑。这应该是最简单的任务。到目前为止,这是我尝试过的:{%assignamount=0%}{%forvariantinproduct.variants%}{%assignamount=amount+1%}{%endfor%}Amount:{{amount}}结果总是0。也许我忽略了一些明显的东西。也许有更好的方法。我想要存档的只是获取运行的迭代次数。 最佳答案 因为{{incrementamount}}将输出您的变量值并且不会影响{%assign%}定义的变量,我

  4. arrays - Ruby 数组 += vs 推送 - 2

    我有一个数组数组,想将元素附加到子数组。+=做我想做的,但我想了解为什么push不做。我期望的行为(并与+=一起工作):b=Array.new(3,[])b[0]+=["apple"]b[1]+=["orange"]b[2]+=["frog"]b=>[["苹果"],["橙子"],["Frog"]]通过推送,我将推送的元素附加到每个子数组(为什么?):a=Array.new(3,[])a[0].push("apple")a[1].push("orange")a[2].push("frog")a=>[[“苹果”、“橙子”、“Frog”]、[“苹果”、“橙子”、“Frog”]、[“苹果”、“

  5. += 的 Ruby 方法 - 2

    有没有办法让Ruby能够做这样的事情?classPlane@moved=0@x=0defx+=(v)#thisiserror@x+=v@moved+=1enddefto_s"moved#{@moved}times,currentxis#{@x}"endendplane=Plane.newplane.x+=5plane.x+=10putsplane.to_s#moved2times,currentxis15 最佳答案 您不能在Ruby中覆盖复合赋值运算符。任务在内部处理。您应该覆盖+,而不是+=。plane.a+=b与plane.a=

  6. ruby - Sinatra + Heroku + Datamapper 使用 dm-sqlite-adapter 部署问题 - 2

    出于某种原因,heroku尝试要求dm-sqlite-adapter,即使它应该在这里使用Postgres。请注意,这发生在我打开任何URL时-而不是在gitpush本身期间。我构建了一个默认的Facebook应用程序。gem文件:source:gemcuttergem"foreman"gem"sinatra"gem"mogli"gem"json"gem"httparty"gem"thin"gem"data_mapper"gem"heroku"group:productiondogem"pg"gem"dm-postgres-adapter"endgroup:development,:t

  7. ruby - Ruby 中字符串运算符 + 和 << 的区别 - 2

    我是Ruby和这个网站的新手。下面两个函数是不同的,一个在函数外修改变量,一个不修改。defm1(x)x我想确保我理解正确-当调用m1时,对str的引用被复制并传递给将其视为x的函数。运算符当调用m2时,对str的引用被复制并传递给将其视为x的函数。运算符+创建一个新字符串,赋值x=x+"4"只是将x重定向到新字符串,而原始str变量保持不变。对吧?谢谢 最佳答案 String#+::str+other_str→new_strConcatenation—ReturnsanewStringcontainingother_strconc

  8. ruby - rails 3.2.2(或 3.2.1)+ Postgresql 9.1.3 + Ubuntu 11.10 连接错误 - 2

    我正在使用PostgreSQL9.1.3(x86_64-pc-linux-gnu上的PostgreSQL9.1.3,由gcc-4.6.real(Ubuntu/Linaro4.6.1-9ubuntu3)4.6.1,64位编译)和在ubuntu11.10上运行3.2.2或3.2.1。现在,我可以使用以下命令连接PostgreSQLsupostgres输入密码我可以看到postgres=#我将以下详细信息放在我的config/database.yml中并执行“railsdb”,它工作正常。开发:adapter:postgresqlencoding:utf8reconnect:falsedat

  9. ruby - 在 Ruby + Chef 中检查现有目录失败 - 2

    这是我在ChefRecipe中的一blockRuby:#ifdatadirdoesn'texist,moveoverthedefaultoneif!File.exist?("/vol/postgres/data")execute"mv/var/lib/postgresql/9.1/main/vol/postgres/data"end结果是:Executingmv/var/lib/postgresql/9.1/main/vol/postgres/datamv:inter-devicemovefailed:`/var/lib/postgresql/9.1/main'to`/vol/post

  10. ruby-on-rails - 使用 Pow 作为服务器在 RubyMine 中调试 - Ruby 2.1.1 + Rails 4 - 2

    我已经开始使用RubyMine6。我正在处理Rails4、Ruby2.1.1项目。我无法找到如何使用Pow作为服务器调试到RubyMine。你能给我指明正确的方向吗? 最佳答案 我能够使用远程调试从RubyMine进行调试。我正在使用RubyMine6、Rails3、Ruby2.1.1。首先创建一个.powenv文件并添加:exportRUBY_DEBUG_PORT=1234exportPOW_WORKERS=1将以下gem添加到您的Gemfile:gem'ruby-debug-ide'gem'debase'创建一个新的初始化器st

随机推荐