内部映射着色器自阴影

60

我正在尝试改进Joost van Dongen的内部映射着色器,并尝试实现自阴影。但我还没弄清楚投射阴影光矢量所需的坐标。你可以在这里看到效果有点好的演示。

为了观察情况我将光位置与摄像机位置相比加了一个偏移量,但显然这样看起来也不对。

着色器代码如下。在片段着色器中查找 SHADOWS DEV。涉及的向量是:shad_Eshad_I

顶点着色器:

varying vec3 oP; // surface position in object space
varying vec3 oE; // position of the eye in object space
varying vec3 oI; // incident ray direction in object space

varying vec3 shad_E; // shadow light position
varying vec3 shad_I; // shadow direction

uniform vec3 lightPosition;

void main() {

    // inverse veiw matrix
    mat4 modelViewMatrixInverse = InverseMatrix( modelViewMatrix );

    // surface position in object space
    oP = position;

    // position of the eye in object space
    oE = modelViewMatrixInverse[3].xyz;

    // incident ray direction in object space
    oI = oP - oE; 

     // link the light position to camera for testing
     // need to find a way for world space directional light to work
    shad_E = oE - lightPosition;

     // light vector
    shad_I = oP - shad_E;

    gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
}

片元着色器:

varying vec3 oP; // surface position in object space
varying vec3 oE; // position of the eye in object space
varying vec3 oI; // incident ray direction in object space

varying vec3 shad_E; // shadow light position
varying vec3 shad_I; // shadow direction

uniform vec3 wallFreq;

uniform float wallsBias;

uniform vec3 wallCeilingColor;
uniform vec3 wallFloorColor;
uniform vec3 wallXYColor;
uniform vec3 wallZYColor;

float checker(vec2 uv, float checkSize) {
  float fmodResult = mod( floor(checkSize * uv.x) + floor(checkSize * uv.y), 2.0);

  if (fmodResult < 1.0) {
    return 1.0;
  } else {
    return 0.85;
  }
}

void main() {

    // INTERIOR MAPPING by Joost van Dongen
    // http://interiormapping.oogst3d.net/
    // email: joost@ronimo-games.com
    // Twitter: @JoostDevBlog

    vec3 wallFrequencies = wallFreq / 2.0 - wallsBias;

    //calculate wall locations
    vec3 walls = ( floor( oP * wallFrequencies) + step( vec3( 0.0 ), oI )) / wallFrequencies;

    //how much of the ray is needed to get from the oE to each of the walls
    vec3 rayFractions = ( walls - oE) / oI;

    //texture-coordinates of intersections
    vec2 intersectionXY = (oE + rayFractions.z * oI).xy;
    vec2 intersectionXZ = (oE + rayFractions.y * oI).xz;
    vec2 intersectionZY = (oE + rayFractions.x * oI).zy;

    //use the intersection as the texture coordinates for the ceiling
    vec3 ceilingColour = wallCeilingColor * checker( intersectionXZ, 2.0 );
    vec3 floorColour = wallFloorColor * checker( intersectionXZ, 2.0 );
    vec3 verticalColour = mix(floorColour, ceilingColour, step(0.0, oI.y));
    vec3 wallXYColour = wallXYColor * checker( intersectionXY, 2.0 );
    vec3 wallZYColour = wallZYColor * checker( intersectionZY, 2.0 );

    // SHADOWS DEV // SHADOWS DEV // SHADOWS DEV // SHADOWS DEV //

    vec3 shad_P = oP;  // just surface position in object space
    vec3 shad_walls = ( floor( shad_P * wallFrequencies) + step( vec3( 0.0 ), shad_I )) / wallFrequencies;
    vec3 shad_rayFr = ( shad_walls - shad_E ) / shad_I;

    // Cast shadow from ceiling planes (intersectionXZ)

    wallZYColour *= mix( 0.3, 1.0, step( shad_rayFr.x, shad_rayFr.y ));
    verticalColour *= mix( 0.3, 1.0, step( rayFractions.y, shad_rayFr.y ));
    wallXYColour *= mix( 0.3, 1.0, step( shad_rayFr.z, shad_rayFr.y ));

    // SHADOWS DEV // SHADOWS DEV // SHADOWS DEV // SHADOWS DEV //

    // intersect walls
    float xVSz = step(rayFractions.x, rayFractions.z);
    vec3 interiorColour = mix(wallXYColour, wallZYColour, xVSz);
    float rayFraction_xVSz = mix(rayFractions.z, rayFractions.x, xVSz);
    float xzVSy = step(rayFraction_xVSz, rayFractions.y);

    interiorColour = mix(verticalColour, interiorColour, xzVSy);

    gl_FragColor.xyz = interiorColour;  

}

6
您能否提供一些您看到的错误类型的截图?您使用的是哪个平台?尝试简化问题,只需进行一个框/光线检查。尝试使用全屏四边形渲染/射线投射来使其正常工作。 - starmole
到目前为止,渲染的图片是什么样子? - AdrianGW
1
你可能想在jsfiddle或其他地方分享更多的代码,这样人们就可以与之互动。这非常特定于这篇论文/算法。这不是人们可以看一眼就说“哦,只需在那里交叉,然后翻转y”,所以你要么等待已经实现过这个的人,要么分享更多信息,让其他人也能尝试。例如,即使是屏幕截图也可能揭示问题所在。 - pailhead
1个回答

3

根据我对你试图实现的内容的非常有限的理解,似乎你需要找到视线向量和其穿过的内部平面相交的位置,然后跟踪回到光源。

要跟踪回到光源,首先必须检查从光源角度看,由视线向量穿过的内部平面是否是背向的,这将使其处于阴影中。如果是正面的,则必须从房间内部射线投射到光源并检查是否与任何其他内部平面相交。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接