@woosh/meep-engine
Version:
Pure JavaScript game engine. Fully featured and production ready.
174 lines (125 loc) • 5.43 kB
JavaScript
import { GLSL3, ShaderMaterial, Vector2, Vector3 } from "three";
import { ParameterLookupTable } from "../../../particles/particular/engine/parameter/ParameterLookupTable.js";
import { Sampler2D } from "../../../texture/sampler/Sampler2D.js";
import sampler2d_to_texture from "../../../texture/sampler/sampler2d_to_texture.js";
const v_shader = `
varying vec3 v_v3_clip_position;
void main()
{
vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );
mat4 mat = projectionMatrix;
gl_Position = projectionMatrix * mvPosition;
vec3 ndc = gl_Position.xyz / gl_Position.w;
v_v3_clip_position = (ndc)*0.5 + 0.5;
// convert clip coordinate to linear scale
//v_v3_clip_position.z = convert_depth_to_linear(v_v3_clip_position.z);
}
`;
const f_shader = `
precision mediump usampler3D;
uniform usampler3D fp_t_light_tiles;
uniform vec3 fp_v3_light_cluster_resolution;
uniform float fp_f_camera_near;
uniform float fp_f_camera_far;
uniform sampler2D t_heatmap_lookup;
uniform vec2 fp_resolution;
uniform mat4 projectionMatrix;
varying vec3 v_v3_clip_position;
out vec4 pc_fragColor;
float convert_depth_to_linear_m(in float depth){
float f = fp_f_camera_far;
float n = fp_f_camera_near;
float z_diff = f - n;
float A = projectionMatrix[2][2];
float B = projectionMatrix[3][2];
float z_ndc = 2.0 * depth - 1.0;
float z_eye = B / (A + z_ndc);
return z_eye / z_diff;
}
float convert_depth_to_linear(in float d){
float d_n = 2.0*d - 1.0;
float f = fp_f_camera_far;
float n = fp_f_camera_near;
float fn = f*n;
float z_diff = f - n;
float denominator = (f + n - d_n * z_diff );
float z_view = (2.0*fn) / denominator;
return (z_view - n) / z_diff;
}
void main(){
vec3 clip_v = vec3(gl_FragCoord.xy / fp_resolution, convert_depth_to_linear( gl_FragCoord.z));
ivec3 v3_cluster_resolution = textureSize(fp_t_light_tiles, 0);
ivec3 v3_cluster_position = ivec3( ( 1.0 - clip_v.x) * float(v3_cluster_resolution.x), clip_v.y*float(v3_cluster_resolution.y), (clip_v.z)*float(v3_cluster_resolution.z) );
uvec3 cluster_metadata = texelFetch(fp_t_light_tiles, v3_cluster_position , 0).rgb;
// gl_FragColor = vec4(v_v3_clip_position, 1.0);
vec4 color = texture2D( t_heatmap_lookup, vec2(float(cluster_metadata.y)/16.0, 0.5) ).rgba;
// gl_FragColor = texture2D( t_heatmap_lookup, vec2(gl_FragCoord.z, 0.5) ).rgba;
// gl_FragColor = texture2D( t_heatmap_lookup, vec2(clip_v.z, 0.5) ).rgba;
pc_fragColor = vec4(color.rgb, 1.0);
// gl_FragColor = vec4(clip_v.zzz, 1.0);
// gl_FragColor = vec4(gl_FragCoord.z,gl_FragCoord.z/2.0+ 0.5,1.0, 1.0);
// gl_FragColor = vec4(gl_FragCoord.z*0.5+0.5,gl_FragCoord.z*0.5+0.5,1.0, 1.0);
}
`;
export class FPlusDebugMaterial extends ShaderMaterial {
constructor() {
super({
uniforms: {
fp_t_light_tiles: {
type: 't',
value: null
},
fp_v3_light_cluster_resolution: {
type: 'v3',
value: new Vector3()
},
fp_f_camera_near: {
type: 'f',
value: 0
},
fp_f_camera_far: {
type: 'f',
value: 0
},
fp_resolution: {
type: 'v2',
value: new Vector2()
},
t_heatmap_lookup: {
type: 't',
value: null
}
},
vertexShader: v_shader,
fragmentShader: f_shader,
glslVersion: GLSL3
});
const heatmap_lut = new ParameterLookupTable(4);
heatmap_lut.write([
0, 0, 0, 255,
80, 0, 100, 255,
0, 0, 255, 255,
0, 179, 179, 255,
0, 255, 0, 255,
255, 255, 0, 255,
255, 5, 5, 255
]);
const heatmap_sampler = Sampler2D.uint8(4, 32, 1);
const r = [];
for (let i = 0; i < heatmap_sampler.width; i++) {
heatmap_lut.sample(i / (heatmap_sampler.width - 1), r);
heatmap_sampler.write(i, 0, r);
}
const heatmap_texture = sampler2d_to_texture(heatmap_sampler);
this.uniforms.t_heatmap_lookup.value = heatmap_texture;
}
/**
*
* @param {LightManager} light_manager
*/
attach_lights(light_manager) {
const uniforms = this.uniforms;
uniforms['fp_t_light_tiles'].value = light_manager.getTextureClusters();
uniforms['fp_v3_light_cluster_resolution'].value.copy(light_manager.getResolution());
}
}