vec3 localToWorld( vec3 _VERTEX, mat4 _MODEL_MATRIX ) { return ( _MODEL_MATRIX * vec4( _VERTEX, 1.0 ) ).xyz; } vec3 localToWorldDirection( vec3 _VERTEX, mat4 _MODEL_MATRIX ) { mat4 mw = _MODEL_MATRIX; mw[ 3 ][ 0 ] = 0.0; mw[ 3 ][ 1 ] = 0.0; mw[ 3 ][ 2 ] = 0.0; mw[ 3 ][ 3 ] = 1.0; return ( mw * vec4( _VERTEX, 1.0 ) ).xyz; } vec3 worldToLocal( vec3 _VERTEX, mat4 _MODEL_MATRIX ) { return ( inverse( _MODEL_MATRIX ) * vec4( _VERTEX, 1.0 ) ).xyz; } vec3 extractScale( mat3 _MODEL_NORMAL_MATRIX ) { mat3 m = _MODEL_NORMAL_MATRIX; float x = length( vec3( m[ 0 ][ 0 ], m[ 1 ][ 0 ], m[ 2 ][ 0 ] ) ); float y = length( vec3( m[ 0 ][ 1 ], m[ 1 ][ 1 ], m[ 2 ][ 1 ] ) ); float z = length( vec3( m[ 0 ][ 2 ], m[ 1 ][ 2 ], m[ 2 ][ 2 ] ) ); return vec3( x, y, z ); } vec2 tilingOffset( vec2 uv, vec4 tilingOffset ) { uv *= tilingOffset.xy; uv += tilingOffset.zw; return uv; } vec2 tilingOffsetRepeat( vec2 uv, vec4 tilingOffset ) { uv *= tilingOffset.xy; uv += tilingOffset.zw; return mod( uv, vec2(1,1) ); } vec3 billboardWorldOffset( vec2 _UV, mat4 _INV_VIEW_MATRIX, mat4 _MODEL_MATRIX ) { vec2 mappedUV = mix( vec2(-1,1), vec2( 1, -1 ), _UV ); vec4 offset = vec4( mappedUV.x, mappedUV.y, 0, 0 ); offset = _INV_VIEW_MATRIX * offset; mat4 mw = _MODEL_MATRIX; mw[ 3 ][ 0 ] = 0.0; mw[ 3 ][ 1 ] = 0.0; mw[ 3 ][ 2 ] = 0.0; vec3 worldOffset = worldToLocal( offset.xyz, mw ); worldOffset = normalize( worldOffset ); return worldOffset; } vec2 rotate_v2( vec2 uv, float angle ) { float s = sin( angle ); float c = cos( angle ); float x = uv.x; float y = uv.y; uv.x = c * x - s * y; uv.y = s * x + c * y; return uv; } vec2 rotateAround_v2( vec2 uv, float angle, vec2 pivot ) { uv -= pivot; uv = rotate_v2( uv, angle ); uv += pivot; return uv; } vec2 rotateAroundTexture_v2( vec2 uv, float angle, vec2 pivot, vec2 textureSize ) { vec2 p = uv; float aspect = textureSize.x / textureSize.y; float cosA = cos( angle ); float sinA = sin( angle ); mat2 rotMat = mat2( vec2( cosA, -sinA ), vec2( sinA, cosA ) ); rotMat = mat2( vec2( cosA, -sinA ), vec2( sinA, cosA ) ); p -= pivot; p.y *= 1.0 / aspect; p *= rotMat; p.y *= aspect; p += pivot; return p; } vec3 cameraWorldPosition( mat4 _INV_VIEW_MATRIX ) { return (_INV_VIEW_MATRIX * vec4(vec3(0.0), 1.0)).xyz; } vec3 cameraWorldForward( mat4 _INV_VIEW_MATRIX ) { vec3 pos = cameraWorldPosition( _INV_VIEW_MATRIX ); return normalize( (_INV_VIEW_MATRIX * vec4( vec3(0.0,0.0,1.0), 1.0)).xyz - pos ); } mat3 identity_m3() { return mat3( vec3( 1, 0, 0 ), vec3( 0, 1, 0 ), vec3( 0, 0, 1 ) ); } mat3 translate_m3( vec2 translation ) { return mat3( vec3( 1, 0, translation.x ), vec3( 0, 1, translation.y ), vec3( 0, 0, 1 ) ); } mat3 scale_m3( vec2 scale ) { return mat3( vec3( scale.x, 0, 0 ), vec3( 0, scale.y, 0 ), vec3( 0, 0, 1 ) ); } mat3 scalePivot_m3( vec2 scale, vec2 pivot ) { return translate_m3( -pivot ) * scale_m3( scale ) * translate_m3( pivot ); } mat3 rotate_m3( float radiansAngle ) { float c = cos( radiansAngle ); float s = sin( radiansAngle ); return mat3( vec3( c, -s, 0 ), vec3( s, c, 0 ), vec3( 0, 0, 1 ) ); } mat3 rotatePivot_m3( float radiansAngle, vec2 pivot ) { return translate_m3( -pivot ) * rotate_m3( radiansAngle ) * translate_m3( pivot ); } mat3 rotatePivotAspect_m3( float radiansAngle, vec2 pivot, float aspect ) { return translate_m3( -pivot ) * scale_m3( vec2( 1, 1.0/aspect ) ) * rotate_m3( radiansAngle ) * scale_m3( vec2( 1, aspect ) ) * translate_m3( pivot ); } vec2 applyMatrix_m3v2( mat3 matrix, vec2 point ) { float x = point.x; float y = point.y; // float ox = matrix[ 0 ] * x + matrix[ 3 ] * y + matrix[ 6 ]; // float oy = matrix[ 1 ] * x + matrix[ 4 ] * y + matrix[ 7 ]; // 0 1 2 0 3 6 // 3 4 5 1 4 7 // 6 7 8 2 5 8 vec3 mx = matrix[ 0 ]; vec3 my = matrix[ 1 ]; float ox = mx.x * x + mx.y * y + mx.z; float oy = my.x * x + my.y * y + my.z; return vec2( ox, oy ); } vec2 applyMatrixBase_m3v2( mat3 matrix, vec2 point ) { float x = point.x; float y = point.y; vec3 mx = matrix[ 0 ]; vec3 my = matrix[ 1 ]; float ox = mx.x * x + mx.y * y; float oy = my.x * x + my.y * y; return vec2( ox, oy ); }