Interior mapping from a single texture

Started by angros47, July 24, 2024, 00:01:22

Previous topic - Next topic

angros47

I found this interesting article about interior mapping: https://andrewgotow.com/2018/09/09/interior-mapping-part-2/

Here is a shader to achieve the same in OpenB3D:

Vertex:
#version 100

precision highp float;

attribute vec3 vert_pos;
attribute vec3 vert_norm;
attribute vec2 vert_uv;

uniform mat4 world;
uniform mat4 view;
uniform mat4 projection;
uniform highp mat4 LightMatrix;

varying vec2 frag_uv;
varying vec3 varyingNormal;
varying vec3 lightDirection;
varying vec3 viewDirection;

void main(void)
{
 gl_Position =  projection * view * world * vec4(vert_pos, 1.0);
 vec3 vertexWorld = vec3(view * world * vec4(vert_pos, 1.0));

 varyingNormal = normalize((view * world * vec4( vert_norm, 0.0 ) ).xyz);

 highp vec4 lightdir = LightMatrix*vec4(0.0, 0.0, 1.0,0.0);
 lightDirection = normalize(vec3(view*lightdir));
 viewDirection = vertexWorld;

 
 frag_uv = vert_uv;
}


Fragment:
#version 100
#extension GL_OES_standard_derivatives : enable
precision highp float;

uniform sampler2D interior;

uniform ivec2 roomTiles;
uniform vec2 depthRemap;
uniform float scale;
uniform float seed;

varying vec2 frag_uv;
varying vec3 varyingNormal;
varying vec3 lightDirection;
varying vec3 viewDirection;




mat3 cotangent_frame(vec3 N, vec3 p, vec2 uv)
{
 /* get edge vectors of the pixel triangle */
 vec3 dp1 = dFdx( p );
 vec3 dp2 = dFdy( p );
 vec2 duv1 = dFdx( uv );
 vec2 duv2 = dFdy( uv );

 /* solve the linear system */
 vec3 dp2perp = cross( dp2, N );
 vec3 dp1perp = cross( N, dp1 );
 vec3 T = dp2perp * duv1.x + dp1perp * duv2.x;
 vec3 B = dp2perp * duv1.y + dp1perp * duv2.y;

 /* construct a scale-invariant frame */
 float invmax = inversesqrt( max( dot(T,T), dot(B,B) ) );
 return mat3( T * invmax, B * invmax, N );
}

highp mat3 transpose(in highp mat3 inMatrix)
{
 highp vec3 i0 = inMatrix
;
 highp vec3 i1 = inMatrix[1];
 highp vec3 i2 = inMatrix[2];

 highp mat3 outMatrix = mat3(
 vec3(i0.x, i1.x, i2.x),
 vec3(i0.y, i1.y, i2.y),
 vec3(i0.z, i1.z, i2.z)
 );
 return outMatrix;
}



void main(void)
{

 mat3 TBN = cotangent_frame(varyingNormal ,  viewDirection, frag_uv );
 vec3 view_dir = transpose(TBN) * viewDirection;

 vec2 _Rooms = vec2(float(roomTiles.x), float(roomTiles.y));

 vec2 roomUV = fract(frag_uv);
 vec2 roomIndexUV = floor(frag_uv);
 vec2 co = roomIndexUV.x + roomIndexUV.y * (roomIndexUV.x + vec2(1));
 vec2 rand2 = fract(sin(co * (vec2(12.9898,78.233))+vec2(seed*0.74352, seed*16.2456)) * (43758.5453));

 // randomize the room
 vec2 n = floor(rand2 * _Rooms.xy);
 roomIndexUV += n;



 float farFrac=texture2D(interior, (roomIndexUV + 0.5) / _Rooms).a;

 float depthScale = mix(depthRemap.y, depthRemap.x, farFrac);
 

 // raytrace box from view dir
 vec3 pos = vec3(roomUV * vec2(2) - vec2(1), -1.);
 view_dir.z *= -depthScale;
 vec3 id = 1.0 / view_dir;
 vec3 k = abs(id) - pos * id;
 float kMin = min(min(k.x, k.y), k.z);
 pos += kMin * view_dir;

 // 0.0 - 1.0 room depth
 float interp = pos.z * 0.5 + 0.5;

 // account for perspective in room textures
 // assumes camera with an fov of 53.13 degrees (atan(0.5))
 float realZ = clamp(interp, 0.0, 1.0) / depthScale + 1.0;
 interp = 1.0 - (1.0 / realZ);
 interp *= depthScale + 1.0;

 // iterpolate from wall back to near wall
 vec2 interiorUV = pos.xy * mix(1.0, farFrac*scale, interp);
 interiorUV = interiorUV * 0.5 + 0.5;

 gl_FragColor = texture2D(interior, (roomIndexUV + interiorUV)/_Rooms);


}