Reflex/ Red Dot / Holographic Sight Shader (VR Compatible)

todo

 

 

Shader code
shader_type spatial;
render_mode blend_mix, cull_back;

// Multiply by MOA to get radians
const float MOA_TO_RADIANS = 0.000290888;
// Multiply by MIL to get radians
const float MIL_TO_RADIANS = 0.001;

/** Expects a transparent texture where white values are the reticle elements */
uniform sampler2D reticle_texture: source_color, repeat_disable; 
/** Color modulation for the reticle_texture */
uniform vec4 reticle_color: source_color = vec4(1.0);
/** Color modulation for the glass */
uniform vec4 glass_color: source_color = vec4(1.0, 1.0, 1.0, 0.1);
/** Reticle light level */
uniform float reticle_emission: hint_range(0.0, 32.0) = 1.0;
/** Size of a reference element (e.g. the center dot) as a fraction of total image size where 1.0
is the full texture. EX: In a texture where the center dot takes up 5% of the total texture set
'ref_element_size' value to 0.05. If 'ref_target_moa' is set to 2.0 the dot will
be resized to 2 MOA. */
uniform float ref_element_size: hint_range(0.01, 1.0, 0.01) = 1.0;
/** Size to make a reference element (e.g. the center dot) in terms of MOA. Used in combination
with 'ref_element_size'. EX: In a texture where the center dot takes up 5% of the total
texture set 'ref_element_size' value to 0.05. If 'ref_target_moa' is set to 2.0
the dot will be resized to 2 MOA. */
uniform float ref_target_moa: hint_range(0.01, 100.0) = 65.0;


group_uniforms point_of_aim;
/** Determines if point-of-aim adjustments (poa_elevation, poa_windage) are performed in MOA
if 1.0, or MIL if 0.0 */
uniform float poa_use_moa: hint_range(0.0, 1.0, 1.0) = 0.0;
/** Subdivisions of poa_elevation and poa_windage. A value of 0.25 will make quarter MOA or quarter
MIL adjustments. */
uniform float poa_subdivision : hint_range(0.0, 1.0, 0.05) = 1.0;
/** Verticle adjustment. To move the point-of-impact upwards increase the value. The reticle will
shift downwards, requiring the weapon to be rotated upwards to put the reticle on target. This
results in the impact shifting up. */
uniform int poa_elevation = 0;
/** Horizontal adjustment. To move the point-of-impact rightwards increase the value. The reticle
will shift leftwards, requiring the weapon to be rotated rightwards to put the reticle on target.
This results in the impact shifting right. */
uniform int poa_windage = 0;


float mask(vec2 uv) {
	return step(0.01, uv.x) * step(uv.x, 0.99) * step(0.01, uv.y) * step(uv.y, 0.99);
}


// Rotate along the x-axis (moves reticle up/down) and y-axis (moves reticle left/ right)
// Credit (CC0) https://godotshaders.com/shader/3d-transformations/
mat3 rotate_poa() {
	// Zeroing Adjustments
	float radians_per_click = poa_subdivision * mix(MOA_TO_RADIANS, MIL_TO_RADIANS, poa_use_moa);
	float radians_x = float(poa_elevation) * radians_per_click;
	float radians_y = float(-poa_windage) * radians_per_click;

	mat3 mat_x = mat3(
		vec3(1, 0, 0),
		vec3(0, cos(radians_x), -sin(radians_x)),
		vec3(0, sin(radians_x),  cos(radians_x))
	);
	mat3 mat_y = mat3(
		vec3(cos(radians_y), 0, sin(radians_y)),
		vec3( 0, 1, 0),
		vec3(-sin(radians_y), 0, cos(radians_y))
	);
	return mat_y * mat_x;
}


void fragment() {
	// Convert from pixel to angular measurements
	float tex_total_moa = ref_target_moa / ref_element_size;
	float tex_rad_width = tex_total_moa * MOA_TO_RADIANS;

	// Get view rotated by point-of-aim adjustments
	vec3 view_dir = (normalize(VIEW * rotate_poa()));

	// Use 'transpose' as a fast inversion (rotation matrix only)
	// Inverse MODELVIEW matrix to bring back to local coords
	vec3 view_local = transpose(mat3(VIEW_MATRIX * MODEL_MATRIX)) * view_dir;

	// Recenter and scale
	vec2 uv = 0.5 + (view_local.xy / tex_rad_width);

	// Mask to in-bounds to discard reticle artifacting at low sizes
	float mask = mask(uv);
	vec4 reticle_sample = texture(reticle_texture, uv);
	reticle_sample.rgb = mix(reticle_sample.rgb, reticle_color.rgb, reticle_color.a);
	reticle_sample.a *= mask;

	// Mask for emission
	float reticle_mask = reticle_sample.a * mask;

	// Make small reticles emit disproportionally more
	float emission_size_factor = 1.0 / sqrt(tex_rad_width);

	// Make sure to enable WorldEnvironment glow
	ALPHA = max(reticle_sample.a, glass_color.a);
	ALBEDO = mix(glass_color.rgb, reticle_color.rgb, reticle_sample.a);
	EMISSION = reticle_sample.rgb * reticle_color.rgb * reticle_mask * (reticle_emission*emission_size_factor);
}
Live Preview
Tags
FPS, gun, holographic, optic, Red Dot, red dot sight, reflex, rifle sight, Sight, VR, weapon sight, XR
The shader code and all code snippets in this post are under CC0 license and can be used freely without the author's permission. Images and videos, and assets depicted in those, do not fall under this license. For more info, see our License terms.

More from squid_iwl

Related shaders

guest

0 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments