export default { attributes: ['uv', 'position', 'world0', 'world1', 'world2', 'world3'], uniforms: ['view', 'projection', 'worldViewProjection', 'world', 'fireworkLight', 'fireworkLightPosition', 'haveShadowLight', 'lightSpaceMatrix', 'shadowSampler', 'isYUV', 'focal_width_height', 'texture_video'], defines: ["#define SHADOWFULLFLOAT", "#define NUM_BONE_INFLUENCERS 0", "#define NUM_MORPH_INFLUENCERS 0"], samplers: ['shadowSampler', 'texture_video'], vertex: ` precision highp float; varying vec3 ModelPos; varying vec4 vPositionFromLight; varying float fireworkDistance; varying float fireworkCosTheta; attribute vec2 uv; attribute vec3 position; attribute vec4 world0; attribute vec4 world1; attribute vec4 world2; attribute vec4 world3; #ifdef NORMAL attribute vec3 normal; #endif uniform vec3 fireworkLightPosition; uniform mat4 view; uniform mat4 projection; uniform mat4 lightSpaceMatrix; uniform mat4 world; uniform mat4 worldViewProjection; float DistanceCalculation(vec3 Q, vec3 P) { return (Q.x - P.x) * (Q.x - P.x) + (Q.y - P.y) * (Q.y - P.y) + (Q.z - P.z) * (Q.z - P.z); } float CosThetaCalculation(vec3 Q, vec3 P) { return max(0.,dot(Q, P)); } void main() { #include vPositionFromLight = lightSpaceMatrix * finalWorld * vec4(position, 1.0); fireworkDistance = distance(vec3(finalWorld * vec4(position, 1.0)), fireworkLightPosition); fireworkCosTheta = 1.0; #ifdef NORMAL vec3 directionFirework = fireworkLightPosition.xyz - vec3(finalWorld * vec4(position, 1.0)); directionFirework = normalize(directionFirework); fireworkCosTheta = CosThetaCalculation(directionFirework, normal); #endif ModelPos = vec3( view * finalWorld * vec4(position , 1.0)); gl_Position = projection * view * finalWorld * vec4(position , 1.0); } `, fragment: ` precision highp float; varying vec3 ModelPos; uniform float isYUV; // false: 0, true: 1.0 uniform sampler2D texture_video; uniform float haveShadowLight; varying vec4 vPositionFromLight; uniform float fireworkLight; varying float fireworkDistance; varying float fireworkCosTheta; uniform sampler2D shadowSampler; uniform vec3 focal_width_height; const float inv_2_PI = 0.1591549; // 1 / (2 * pi) const float inv_PI = 0.3183099; // 1 / ( pi) const vec2 invAtan = vec2(0.1591549, 0.3183099); float unpack(vec4 color) { const vec4 bit_shift = vec4(1.0 / (255.0 * 255.0 * 255.0), 1.0 / (255.0 * 255.0), 1.0 / 255.0, 1.0); return dot(color, bit_shift); } float ShadowCalculation(vec4 vPositionFromLight, sampler2D ShadowMap) { vec3 projCoords = vPositionFromLight.xyz / vPositionFromLight.w; vec3 depth = 0.5 * projCoords + vec3(0.5); vec2 uv = depth.xy; if (uv.x < 0.0 || uv.x > 1.0 || uv.y < 0.0 || uv.y > 1.0) { return 1.0; } #ifndef SHADOWFULLFLOAT float shadow = unpack(texture2D(ShadowMap, uv)); #else float shadow = texture2D(ShadowMap, uv).x; #endif if (depth.z > shadow - 1e-4) { return 0.7; } else { return 1.0; } } vec2 SampleTex(vec3 pt3d) { return focal_width_height.x / focal_width_height.yz *pt3d.xy/pt3d.z + 0.5; } void main() { vec3 yuv; vec3 rgb; vec2 uv; vec3 color = vec3(0,0,0); vec3 flash_color = fireworkLight * 1000.0 / fireworkDistance * fireworkCosTheta * vec3(1,0,0); float shadow = 1.0; if (haveShadowLight > 0.5) { shadow = ShadowCalculation(vPositionFromLight, shadowSampler); } uv = SampleTex( normalize(ModelPos) ); if( isYUV < 0.5 ) { color = texture2D(texture_video, uv).rgb; }else{ const mat4 YUV2RGB = mat4 ( 1.1643828125, 0, 1.59602734375, -.87078515625, 1.1643828125, -.39176171875, -.81296875, .52959375, 1.1643828125, 2.017234375, 0, -1.081390625, 0, 0, 0, 1 ); vec4 result = vec4( texture2D( texture_video, vec2( uv.x, uv.y * 0.666666 + 0.333333 ) ).x, texture2D( texture_video, vec2( uv.x * 0.5, uv.y * 0.333333 ) ).x, texture2D( texture_video, vec2( 0.5 + uv.x * 0.5, uv.y * 0.333333 ) ).x, 1 ) * YUV2RGB; color = clamp(result.rgb, 0.0, 1.0); } if( uv.x < 0.0 || uv.x > 1.0 || uv.y < 0.0 || uv.y > 1.0 ) { color = vec3(0,0,0); } gl_FragColor = vec4(shadow * (color + flash_color) * 1.0, 1.0); } ` }