60
votes

I'm tinkering with Joost van Dongen's Interior mapping shader and I'm trying to implement self-shadowing. Still I couldn't quite figure out what coordinates shadow casting light vectors need to be in. You can see somewhat working demo at here I've attached the light position with an offset to the camera position just to see whats happening but obviously it doesn't look right either. Shader code is below. Look for SHADOWS DEV in fragment shader. Vectors in question are: shad_E and shad_I.

vertex shader:

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 );
}

fragment shader:

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: [email protected]
    // 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;  

}
1
Can you add some screenshots of what kind of errors you are seeing? Also what platform are you running on? Also try to reduce the problem. It is just a box/ray check. Try to make it work with rendering/raycasting a box with a fullscreen quad.starmole
What's a picture of the render so far?AdrianGW
You might want to share more of the code on jsfiddle or something so people could play with it. This is VERY specific to this particular paper/algorithm. It's not something people can look at and go "oh yeah, just do a cross there, and flip the y", So you either have to wait for someone who had implemented this, or share more so other people can take a stab at it. I.E. even a screen shot might give insight into where the problem lies,pailhead

1 Answers

3
votes

Based on my very limited understanding of what you're trying to implement, it seems you would need to take the location of the intersection between the eye vector and the interior plane it hits, then trace it back to the light.

To trace back to the light, you would first have to check if the interior plane intersected by the eye vector is back-facing from the light's perspective, which would make it in shadow. If it's front-facing then you have to ray cast from within the room to the light and check for an intersection with any of the other interior planes.