123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150 |
- #ifndef TO_WORLD_GLSLV
- #define TO_WORLD_GLSLV
- #include <math.glslv>
- /*==============================================================================
- VARS
- ==============================================================================*/
- #var BILLBOARD_ALIGN BILLBOARD_ALIGN_VIEW
- #var USE_INSTANCED_PARTCLS 0
- #var BILLBOARD_SPHERICAL 0
- #var BILLBOARD_RANDOM 0
- #var BILLBOARD 0
- #var BILLBOARD_JITTERED 0
- #var BILLBOARD_PRES_GLOB_ORIENTATION 0
- #var STATIC_BATCH 0
- #var REFLECTION_PASS REFL_PASS_NONE
- /*============================================================================*/
- #define MAX_BILLBOARD_ANGLE M_PI_4
- #if BILLBOARD_SPHERICAL || !BILLBOARD && (BILLBOARD_ALIGN == BILLBOARD_ALIGN_VIEW)
- mat3 billboard_spherical(vec3 center_pos, mat3 view_tsr) {
- vec4 bb_q = vec4(view_tsr[1][1], view_tsr[1][2], view_tsr[2][0],view_tsr[2][1]);
- // NOTE: camera is rotated downward by default,
- // inversed vertex order during reflection pass
- #if REFLECTION_PASS == REFL_PASS_PLANE
- vec4 right_q = qsetAxisAngle(RIGHT_VECTOR, -M_PI/2.0);
- #else
- vec4 right_q = qsetAxisAngle(RIGHT_VECTOR, M_PI/2.0);
- #endif
- bb_q = qmult(right_q, bb_q);
- bb_q = qinv(bb_q);
- mat3 bb_tsr = tsr_identity();
- bb_tsr[0] = center_pos;
- bb_tsr = tsr_set_quat(bb_q, bb_tsr);
- return bb_tsr;
- }
- #else
- mat3 billboard_cylindrical(vec3 camera_eye, vec3 center_pos) {
- vec3 center_to_cam = camera_eye - center_pos;
- center_to_cam.z = 0.0;
- center_to_cam = normalize(center_to_cam);
- vec4 bb_q = qfrom_dir(center_to_cam, TOWARD_VECTOR);
- mat3 bb_tsr = tsr_identity();
- bb_tsr[0] = center_pos;
- bb_tsr = tsr_set_quat(bb_q, bb_tsr);
- return bb_tsr;
- }
- #endif // BILLBOARD_SPHERICAL
- #if BILLBOARD_JITTERED
- mat3 bend_jitter_rotate_tsr(in vec3 wind_world, float wind_param, float jitter_amp,
- float jitter_freq, vec3 vec_seed, mat3 model_tsr) {
- float seed = fract(length(vec_seed) / 0.17); // [0, 1]
- float rand_freq = jitter_freq + seed / 10.0; // + 0%-10%
- float rand_phase = seed;
- if (jitter_freq != 0.0)
- rand_phase /= jitter_freq ; // [0, 1/freq]
- wind_world *= 1.0 + 0.5 * sin(wind_param); // make wind gusty
- // jitter rotation angle
- float bj_angle = length(wind_world) * jitter_amp * sin(2.0*3.14 * wind_param
- * rand_freq + rand_phase);
- vec4 bj_quat = qsetAxisAngle(TOWARD_VECTOR, bj_angle);
- // rotate tsr from the right
- vec4 model_quat = vec4(model_tsr[1][1], model_tsr[1][2], model_tsr[2][0], model_tsr[2][1]);
- model_quat = qmult(model_quat, bj_quat);
- model_tsr = tsr_set_quat(model_quat, model_tsr);
- return model_tsr;
- }
- #endif
- mat3 billboard_tsr(in vec3 camera_eye, in vec3 wcen, in mat3 view_tsr) {
- #if BILLBOARD_SPHERICAL || !BILLBOARD && (BILLBOARD_ALIGN == BILLBOARD_ALIGN_VIEW)
- mat3 bill_tsr = billboard_spherical(wcen, view_tsr);
- #elif BILLBOARD_RANDOM
- // get initial random rotation angle
- float seed = fract((wcen.x * 1.43 - wcen.z * 0.123 + wcen.y * 6.1));
- float alpha_rand = 2.0 * M_PI * seed;
- vec4 view_quat = vec4(view_tsr[1][1], view_tsr[1][2], view_tsr[2][0], view_tsr[2][1]);
- float alpha_cam = asin(2.0 * (view_quat.x * view_quat.y - view_quat.z * view_quat.w));
- float alpha_diff = alpha_cam - alpha_rand;
- if (alpha_diff < 0.0)
- alpha_diff = 2.0 * M_PI + alpha_diff;
- float res_angle = alpha_rand;
- if (alpha_diff <= MAX_BILLBOARD_ANGLE)
- res_angle += alpha_diff;
- else if (alpha_diff <= M_PI - MAX_BILLBOARD_ANGLE)
- res_angle += MAX_BILLBOARD_ANGLE * (2.0 * alpha_diff - M_PI)
- / (2.0 * MAX_BILLBOARD_ANGLE - M_PI);
- else if (alpha_diff <= M_PI + MAX_BILLBOARD_ANGLE)
- res_angle += alpha_diff - M_PI;
- else if (alpha_diff <= 2.0 * M_PI - MAX_BILLBOARD_ANGLE)
- res_angle += MAX_BILLBOARD_ANGLE * (2.0 * alpha_diff - M_PI)
- / (2.0 * MAX_BILLBOARD_ANGLE - M_PI) + M_PI;
- else
- res_angle += alpha_diff - 2.0 * M_PI;
- vec4 bill_quat = qsetAxisAngle(UP_VECTOR, res_angle);
- mat3 bill_tsr;
- bill_tsr[0] = wcen;
- bill_tsr[1][0] = 1.0;
- bill_tsr = tsr_set_quat(bill_quat, bill_tsr);
- #else
- mat3 bill_tsr = billboard_cylindrical(camera_eye, wcen);
- #endif
- return bill_tsr;
- }
- #if BILLBOARD_PRES_GLOB_ORIENTATION && !STATIC_BATCH || USE_INSTANCED_PARTCLS
- mat3 billboard_tsr_global(in vec3 camera_eye, in vec3 wcen, in mat3 view_tsr,
- in mat3 model_tsr) {
- mat3 bill_tsr = billboard_tsr(camera_eye, wcen, view_tsr);
- // NOTE: translation is already in bill_tsr
- model_tsr[0] = vec3(0.0, 0.0, 0.0);
- bill_tsr = tsr_multiply(bill_tsr, model_tsr);
- return bill_tsr;
- }
- #endif
- vertex to_world(in vec3 pos, in vec3 cen, in vec3 tng, in vec3 shd_tng, in vec3 bnr,
- in vec3 nrm, in mat3 model_tsr) {
- pos = tsr9_transform(model_tsr, pos);
- cen = tsr9_transform(model_tsr, cen);
- tng = tsr9_transform_dir(model_tsr, tng);
- shd_tng = tsr9_transform_dir(model_tsr, shd_tng);
- bnr = tsr9_transform_dir(model_tsr, bnr);
- nrm = tsr9_transform_dir(model_tsr, nrm);
- return tbn_norm(vertex(pos, cen, tng, shd_tng, bnr, nrm, vec3(0.0)));
- }
- #endif
|