Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Interior Mapping shader self shadowing

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;  

}
like image 554
shaderology Avatar asked Mar 18 '14 07:03

shaderology


Video Answer


1 Answers

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.

like image 145
lcmylin Avatar answered Oct 04 '22 05:10

lcmylin