$ mvn -C clean install
<dependency> <groupId>com.io7m.r2</groupId> <artifactId>io7m-r2-main</artifactId> <version>0.3.0-SNAPSHOT</version> </dependency>
Copyright © 2016 <code@io7m.com> http://io7m.com Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies. THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
cube = {
(-0.5, -0.5, -0.5),
( 0.5, -0.5, -0.5),
( 0.5, -0.5, 0.5),
(-0.5, -0.5, 0.5),
(-0.5, 0.5, -0.5),
( 0.5, 0.5, -0.5),
( 0.5, 0.5, 0.5),
(-0.5, 0.5, 0.5)
}After clipping and division by w, depth coordinates range from -1 to 1, corresponding to the near and far clipping planes. glDepthRange specifies a linear mapping of the normalized depth coordinates in this range to window depth coordinates. Regardless of the actual depth buffer implementation, window coordinate depth values are treated as though they range from 0 through 1 (like color components). Thus, the values accepted by glDepthRange are both clamped to this range before they are accepted. The setting of (0,1) maps the near plane to 0 and the far plane to 1. With this mapping, the depth buffer range is fully utilized.
| Index | Type | Description |
|---|---|---|
| 0 | vec3 | The object-space position of the vertex |
| 1 | vec2 | The UV coordinates of the vertex |
| 2 | vec3 | The object-space normal vector of the vertex |
| 3 | vec4 | The tangent vector of the vertex |
#include <com.io7m.r2.shaders.core/R2Bilinear.h> vec3 x = R2_bilinearInterpolate3(...);
| Shader | Description |
|---|---|
| R2SurfaceShaderBasicSingle | Basic textured surface with normal mapping, specular mapping, emission mapping, and conditional discarding based on alpha. |
| R2SurfaceShaderBasicReflectiveSingle | Basic textured surface with pseudo reflections from a cube map, normal mapping, specular mapping, emission mapping, and conditional discarding based on alpha. |
module LightDiffuse where
import qualified Color3
import qualified Direction
import qualified Normal
import qualified Spaces
import qualified Vector3f
diffuse :: Direction.T Spaces.Eye -> Normal.T -> Color3.T -> Float -> Vector3f.T
diffuse stl n light_color light_intensity =
let
factor = max 0.0 (Vector3f.dot3 stl n)
light_scaled = Vector3f.scale light_color light_intensity
in
Vector3f.scale light_scaled factormodule LightSpecular where
import qualified Color3
import qualified Direction
import qualified Normal
import qualified Reflection
import qualified Spaces
import qualified Specular
import qualified Vector3f
specularPhong :: Direction.T Spaces.Eye -> Direction.T Spaces.Eye -> Normal.T -> Color3.T -> Float -> Specular.T -> Vector3f.T
specularPhong stl view n light_color light_intensity (Specular.S surface_spec surface_exponent) =
let
reflection = Reflection.reflection view n
factor = (max 0.0 (Vector3f.dot3 reflection stl)) ** surface_exponent
light_raw = Vector3f.scale light_color light_intensity
light_scaled = Vector3f.scale light_raw factor
in
Vector3f.mult3 light_scaled surface_spec
specularBlinnPhong :: Direction.T Spaces.Eye -> Direction.T Spaces.Eye -> Normal.T -> Color3.T -> Float -> Specular.T -> Vector3f.T
specularBlinnPhong stl view n light_color light_intensity (Specular.S surface_spec surface_exponent) =
let
reflection = Reflection.reflection view n
factor = (max 0.0 (Vector3f.dot3 reflection stl)) ** surface_exponent
light_raw = Vector3f.scale light_color light_intensity
light_scaled = Vector3f.scale light_raw factor
in
Vector3f.mult3 light_scaled surface_specmodule Attenuation where attenuation_from_inverses :: Float -> Float -> Float -> Float attenuation_from_inverses inverse_maximum_range inverse_falloff distance = max 0.0 (1.0 - (distance * inverse_maximum_range) ** inverse_falloff) attenuation :: Float -> Float -> Float -> Float attenuation maximum_range falloff distance = attenuation_from_inverses (1.0 / maximum_range) (1.0 / falloff) distance
module Directional where
import qualified Color4
import qualified Direction
import qualified LightDirectional
import qualified LightDiffuse
import qualified LightSpecular
import qualified Normal
import qualified Position3
import qualified Spaces
import qualified Specular
import qualified Vector3f
import qualified Vector4f
directional :: Direction.T Spaces.Eye -> Normal.T -> Position3.T Spaces.Eye -> LightDirectional.T -> Specular.T -> Color4.T -> Vector3f.T
directional view n position light specular (Vector4f.V4 sr sg sb _) =
let
stl = Vector3f.normalize (Vector3f.negation position)
light_color = LightDirectional.color light
light_intensity = LightDirectional.intensity light
light_d = LightDiffuse.diffuse stl n light_color light_intensity
light_s = LightSpecular.specularBlinnPhong stl view n light_color light_intensity specular
lit_d = Vector3f.mult3 (Vector3f.V3 sr sg sb) light_d
lit_s = Vector3f.add3 lit_d light_s
in
lit_s
module Spherical where
import qualified Attenuation
import qualified Color4
import qualified Direction
import qualified LightDiffuse
import qualified LightSpecular
import qualified LightSpherical
import qualified Normal
import qualified Position3
import qualified Specular
import qualified Spaces
import qualified Vector3f
import qualified Vector4f
spherical :: Direction.T Spaces.Eye -> Normal.T -> Position3.T Spaces.Eye -> LightSpherical.T -> Specular.T -> Color4.T -> Vector3f.T
spherical view n surface_position light specular (Vector4f.V4 sr sg sb _) =
let
position_diff = Position3.sub3 surface_position (LightSpherical.origin light)
stl = Vector3f.normalize (Vector3f.negation position_diff)
distance = Vector3f.magnitude (position_diff)
attenuation = Attenuation.attenuation (LightSpherical.radius light) (LightSpherical.falloff light) distance
light_color = LightSpherical.color light
light_intensity = LightSpherical.intensity light
light_d = LightDiffuse.diffuse stl n light_color light_intensity
light_s = LightSpecular.specularBlinnPhong stl view n light_color light_intensity specular
light_da = Vector3f.scale light_d attenuation
light_sa = Vector3f.scale light_s attenuation
lit_d = Vector3f.mult3 (Vector3f.V3 sr sg sb) light_da
lit_s = Vector3f.add3 lit_d light_sa
in
lit_s
module Projective where
import qualified Attenuation
import qualified Color3
import qualified Color4
import qualified Direction
import qualified LightDiffuse
import qualified LightSpecular
import qualified LightProjective
import qualified Normal
import qualified Position3
import qualified Specular
import qualified Spaces
import qualified Vector3f
import qualified Vector4f
projective :: Direction.T Spaces.Eye -> Normal.T -> Position3.T Spaces.Eye -> LightProjective.T -> Specular.T -> Float -> Color3.T -> Color4.T -> Vector3f.T
projective view n surface_position light specular shadow texture (Vector4f.V4 sr sg sb _) =
let
position_diff = Position3.sub3 surface_position (LightProjective.origin light)
stl = Vector3f.normalize (Vector3f.negation position_diff)
distance = Vector3f.magnitude (position_diff)
attenuation_raw = Attenuation.attenuation (LightProjective.radius light) (LightProjective.falloff light) distance
attenuation = attenuation_raw * shadow
light_color = Vector3f.mult3 (LightProjective.color light) texture
light_intensity = LightProjective.intensity light
light_d = LightDiffuse.diffuse stl n light_color light_intensity
light_s = LightSpecular.specularBlinnPhong stl view n light_color light_intensity specular
light_da = Vector3f.scale light_d attenuation
light_sa = Vector3f.scale light_s attenuation
lit_d = Vector3f.mult3 (Vector3f.V3 sr sg sb) light_da
lit_s = Vector3f.add3 lit_d light_sa
in
lit_s
module ProjectiveMatrix where
import qualified Matrix4f
projective_matrix :: Matrix4f.T -> Matrix4f.T -> Matrix4f.T -> Matrix4f.T
projective_matrix camera_view light_view light_projection =
case Matrix4f.inverse camera_view of
Just cv -> Matrix4f.mult (Matrix4f.mult light_projection light_view) cv
Nothing -> undefined -- A view matrix is always invertible
module ShadowVarianceChebyshev0 where
chebyshev :: (Float, Float) -> Float -> Float
chebyshev (d, ds) t =
let p = if t <= d then 1.0 else 0.0
variance = ds - (d * d)
du = t - d
p_max = variance / (variance + (du * du))
in max p p_max
factor :: (Float, Float) -> Float -> Float
factor = chebyshev
module ShadowVarianceChebyshev1 where
data T = T {
minimum_variance :: Float
} deriving (Eq, Show)
chebyshev :: (Float, Float) -> Float -> Float -> Float
chebyshev (d, ds) min_variance t =
let p = if t <= d then 1.0 else 0.0
variance = max (ds - (d * d)) min_variance
du = t - d
p_max = variance / (variance + (du * du))
in max p p_max
factor :: T -> (Float, Float) -> Float -> Float
factor shadow (d, ds) t =
chebyshev (d, ds) (minimum_variance shadow) t
module ShadowVarianceChebyshev2 where
data T = T {
minimum_variance :: Float,
bleed_reduction :: Float
} deriving (Eq, Show)
chebyshev :: (Float, Float) -> Float -> Float -> Float
chebyshev (d, ds) min_variance t =
let p = if t <= d then 1.0 else 0.0
variance = max (ds - (d * d)) min_variance
du = t - d
p_max = variance / (variance + (du * du))
in max p p_max
clamp :: Float -> (Float, Float) -> Float
clamp x (lower, upper) = max (min x upper) lower
linear_step :: Float -> Float -> Float -> Float
linear_step lower upper x = clamp ((x - lower) / (upper - lower)) (0.0, 1.0)
factor :: T -> (Float, Float) -> Float -> Float
factor shadow (d, ds) t =
let u = chebyshev (d, ds) (minimum_variance shadow) t in
linear_step (bleed_reduction shadow) 1.0 u
module NormalCompress where
import qualified Vector3f
import qualified Vector2f
import qualified Normal
compress :: Normal.T -> Vector2f.T
compress n =
let p = sqrt ((Vector3f.z n * 8.0) + 8.0)
x = (Vector3f.x n / p) + 0.5
y = (Vector3f.y n / p) + 0.5
in Vector2f.V2 x ymodule NormalDecompress where
import qualified Vector3f
import qualified Vector2f
import qualified Normal
decompress :: Vector2f.T -> Normal.T
decompress v =
let fn = Vector2f.V2 ((Vector2f.x v * 4.0) - 2.0) ((Vector2f.y v * 4.0) - 2.0)
f = Vector2f.dot2 fn fn
g = sqrt (1.0 - (f / 4.0))
x = (Vector2f.x fn) * g
y = (Vector2f.y fn) * g
z = 1.0 - (f / 2.0)
in Vector3f.V3 x y zmodule ScreenToTexture where
import qualified Vector2f
screen_to_texture :: Vector2f.T -> Float -> Float -> Vector2f.T
screen_to_texture position width height =
let u = (Vector2f.x position) / width
v = (Vector2f.y position) / height
in Vector2f.V2 u v
module ScreenDepthToNDC where screen_depth_to_ndc :: Float -> Float screen_depth_to_ndc screen_depth = (screen_depth * 2.0) - 1.0
module ClipSpaceZLong where
import qualified Matrix4f as M4x4;
import qualified Vector4f as V4;
clip_z_long :: M4x4.T -> V4.T -> Float
clip_z_long m eye =
let
m20 = M4x4.row_column m (2, 0)
m21 = M4x4.row_column m (2, 1)
m22 = M4x4.row_column m (2, 2)
m23 = M4x4.row_column m (2, 3)
k0 = (V4.x eye) * m20
k1 = (V4.y eye) * m21
k2 = (V4.z eye) * m22
k3 = (V4.w eye) * m23
in
k0 + k1 + k2 + k3
module ClipSpaceWLong where
import qualified Matrix4f as M4x4;
import qualified Vector4f as V4;
clip_w_long :: M4x4.T -> V4.T -> Float
clip_w_long m eye =
let
m30 = M4x4.row_column m (3, 0)
m31 = M4x4.row_column m (3, 1)
m32 = M4x4.row_column m (3, 2)
m33 = M4x4.row_column m (3, 3)
k0 = (V4.x eye) * m30
k1 = (V4.y eye) * m31
k2 = (V4.z eye) * m32
k3 = (V4.w eye) * m33
in
k0 + k1 + k2 + k3
module ClipSpaceZSimple where
import qualified Matrix4f as M4x4;
import qualified Vector4f as V4;
clip_z_simple :: M4x4.T -> V4.T -> Float
clip_z_simple m eye =
let
m22 = M4x4.row_column m (2, 2)
m23 = M4x4.row_column m (2, 3)
in
((V4.z eye) * m22) + m23
module ClipSpaceWSimple where
import qualified Matrix4f as M4x4;
import qualified Vector4f as V4;
clip_w_simple :: M4x4.T -> V4.T -> Float
clip_w_simple m eye =
let
m32 = M4x4.row_column m (3, 2)
m33 = M4x4.row_column m (3, 3)
in
((V4.z eye) * m32) + m33
module EyeSpaceZ where
import qualified Matrix4f as M4x4;
eye_z :: M4x4.T -> Float -> Float
eye_z m ndc_z =
let
m22 = M4x4.row_column m (2, 2)
m23 = M4x4.row_column m (2, 3)
m32 = M4x4.row_column m (3, 2)
m33 = M4x4.row_column m (3, 3)
a = (ndc_z * m33) - m32
b = (ndc_z * m23) - m22
in
- (a / b)
module NDCCorners where import qualified Vector4f as V4 near_x0y0 :: V4.T near_x0y0 = V4.V4 (-1.0) (-1.0) (-1.0) 1.0 near_x1y0 :: V4.T near_x1y0 = V4.V4 1.0 (-1.0) (-1.0) 1.0 near_x0y1 :: V4.T near_x0y1 = V4.V4 (-1.0) 1.0 (-1.0) 1.0 near_x1y1 :: V4.T near_x1y1 = V4.V4 1.0 1.0 (-1.0) 1.0 far_x0y0 :: V4.T far_x0y0 = V4.V4 (-1.0) (-1.0) 1.0 1.0 far_x1y0 :: V4.T far_x1y0 = V4.V4 1.0 (-1.0) 1.0 1.0 far_x0y1 :: V4.T far_x0y1 = V4.V4 (-1.0) 1.0 1.0 1.0 far_x1y1 :: V4.T far_x1y1 = V4.V4 1.0 1.0 1.0 1.0
module RayAndQ where
import qualified Matrix4f as M4x4
import qualified Vector4f as V4
-- | Calculate @(ray, q)@ for the given inverse projection matrix and frustum corners
ray_and_q :: M4x4.T -> (V4.T, V4.T) -> (V4.T, V4.T)
ray_and_q inverse_m (near, far) =
let
-- Unproject the NDC coordinates to eye-space
near_hom = M4x4.mult_v inverse_m near
near_eye = V4.div_s near_hom (V4.w near_hom)
far_hom = M4x4.mult_v inverse_m far
far_eye = V4.div_s far_hom (V4.w far_hom)
-- Calculate a ray with ray.z == 1.0
ray_initial = V4.sub4 far_eye near_eye
ray = V4.div_s ray_initial (V4.z ray_initial)
-- Subtract the scaled ray from the near corner to calculate q
q = V4.sub4 near_eye (V4.scale ray (V4.z near_eye))
in
(ray, q)
module RayAndQAll where
import qualified NDCCorners
import qualified RayAndQ
import qualified Matrix4f as M4x4
import qualified Vector4f as V4
data T = T {
q_x0y0 :: V4.T,
q_x1y0 :: V4.T,
q_x0y1 :: V4.T,
q_x1y1 :: V4.T,
ray_x0y0 :: V4.T,
ray_x1y0 :: V4.T,
ray_x0y1 :: V4.T,
ray_x1y1 :: V4.T
} deriving (Eq, Ord, Show)
-- | Calculate all rays and qs for the four pairs of near/far frustum corners
calculate :: M4x4.T -> T
calculate inverse_m =
let
(x0y0_ray, x0y0_q) = RayAndQ.ray_and_q inverse_m (NDCCorners.near_x0y0, NDCCorners.far_x0y0)
(x1y0_ray, x1y0_q) = RayAndQ.ray_and_q inverse_m (NDCCorners.near_x1y0, NDCCorners.far_x1y0)
(x0y1_ray, x0y1_q) = RayAndQ.ray_and_q inverse_m (NDCCorners.near_x0y1, NDCCorners.far_x0y1)
(x1y1_ray, x1y1_q) = RayAndQ.ray_and_q inverse_m (NDCCorners.near_x1y1, NDCCorners.far_x1y1)
in
T {
q_x0y0 = x0y0_q,
q_x1y0 = x1y0_q,
q_x0y1 = x0y1_q,
q_x1y1 = x1y1_q,
ray_x0y0 = x0y0_ray,
ray_x1y0 = x1y0_ray,
ray_x0y1 = x0y1_ray,
ray_x1y1 = x1y1_ray
}
module Bilinear4 where
import qualified Vector2f as V2
import qualified Vector4f as V4
interpolate :: (V4.T, V4.T, V4.T, V4.T) -> V2.T -> V4.T
interpolate (x0y0, x1y0, x0y1, x1y1) position =
let u0 = V4.interpolate x0y0 (V2.x position) x1y0
u1 = V4.interpolate x0y1 (V2.x position) x1y1
in V4.interpolate u0 (V2.y position) u1
#ifndef R2_LOG_DEPTH_H
#define R2_LOG_DEPTH_H
/// \file R2LogDepth.h
/// \brief Logarithmic depth functions.
///
/// Prepare an eye-space Z value for encoding. See R2_logDepthEncodePartial.
///
/// @param z An eye-space Z value
/// @return The prepared value
///
float
R2_logDepthPrepareEyeZ(
const float z)
{
return 1.0 + (-z);
}
///
/// Partially encode the given _positive_ eye-space Z value. This partial encoding
/// can be used when performing part of the encoding in a vertex shader
/// and the rest in a fragment shader (for efficiency reasons) - See R2_logDepthPrepareEyeZ.
///
/// @param z An eye-space Z value
/// @param depth_coefficient The depth coefficient used to encode \a z
///
/// @return The encoded depth
///
float
R2_logDepthEncodePartial(
const float z,
const float depth_coefficient)
{
float half_co = depth_coefficient * 0.5;
float clamp_z = max (0.000001, z);
return log2 (clamp_z) * half_co;
}
///
/// Fully encode the given eye-space Z value.
///
/// @param z An eye-space Z value
/// @param depth_coefficient The depth coefficient used to encode \a z
/// @return The fully encoded depth
///
float
R2_logDepthEncodeFull(
const float z,
const float depth_coefficient)
{
float half_co = depth_coefficient * 0.5;
float clamp_z = max (0.000001, z + 1.0);
return log2 (clamp_z) * half_co;
}
///
/// Decode a depth value that was encoded with the given depth coefficient.
/// Note that in most cases, this will yield a _positive_ eye-space Z value,
/// and must be negated to yield a conventional negative eye-space Z value.
///
/// @param z The depth value
/// @param depth_coefficient The coefficient used during encoding
///
/// @return The original (positive) eye-space Z value
///
float
R2_logDepthDecode(
const float z,
const float depth_coefficient)
{
float half_co = depth_coefficient * 0.5;
float exponent = z / half_co;
return pow (2.0, exponent) - 1.0;
}
#endif // R2_LOG_DEPTH_H
#ifndef R2_POSITION_RECONSTRUCTION_H
#define R2_POSITION_RECONSTRUCTION_H
/// \file R2PositionReconstruction.h
/// \brief Functions for performing position reconstruction during deferred rendering.
#include "R2Bilinear.h"
#include "R2ViewRays.h"
///
/// Reconstruct an eye-space position from the given parameters.
///
/// @param eye_z The eye-space Z value of the position
/// @param uv The current position on the screen in UV coordinates
/// @param view_rays The current set of view rays
///
vec4
R2_positionReconstructFromEyeZ(
const float eye_z,
const vec2 uv,
const R2_view_rays_t view_rays)
{
vec3 origin =
R2_bilinearInterpolate3(
view_rays.origin_x0y0,
view_rays.origin_x1y0,
view_rays.origin_x0y1,
view_rays.origin_x1y1,
uv
);
vec3 ray_normal =
R2_bilinearInterpolate3(
view_rays.ray_x0y0,
view_rays.ray_x1y0,
view_rays.ray_x0y1,
view_rays.ray_x1y1,
uv
);
vec3 ray =
(ray_normal * eye_z) + origin;
return vec4 (ray, 1.0);
}
#endif // R2_POSITION_RECONSTRUCTION_H
#ifndef R2_VIEW_RAYS_H
#define R2_VIEW_RAYS_H
/// \file R2ViewRays.h
/// \brief View ray types
/// The type of view rays used to reconstruct positions during deferred rendering.
struct R2_view_rays_t {
/// The bottom left origin
vec3 origin_x0y0;
/// The bottom right origin
vec3 origin_x1y0;
/// The top left origin
vec3 origin_x0y1;
/// The top right origin
vec3 origin_x1y1;
/// The view ray pointing out of the bottom left origin
vec3 ray_x0y0;
/// The view ray pointing out of the bottom right origin
vec3 ray_x1y0;
/// The view ray pointing out of the top left origin
vec3 ray_x0y1;
/// The view ray pointing out of the top right origin
vec3 ray_x1y1;
};
#endif // R2_VIEW_RAYS_H
| Shader | Description |
|---|---|
| R2TranslucentShaderBasicPremultipliedSingle | Basic textured surface without lighting, with distance fading, producing premultiplied alpha output. |
module LogDepth where
newtype LogDepth =
LogDepth Float
deriving (Eq, Ord, Show)
type Depth = Float
log2 :: Float -> Float
log2 = logBase 2.0
depth_coefficient :: Float -> Float
depth_coefficient far = 2.0 / log2 (far + 1.0)
encode :: Float -> Depth -> LogDepth
encode depth_co depth =
let hco = depth_co * 0.5 in
LogDepth $ log2 (depth + 1.0) * hco
decode :: Float -> LogDepth -> Depth
decode depth_co (LogDepth depth) =
let hco = depth_co * 0.5 in
(2.0 ** (depth / hco)) - 1
#ifndef R2_LOG_DEPTH_H
#define R2_LOG_DEPTH_H
/// \file R2LogDepth.h
/// \brief Logarithmic depth functions.
///
/// Prepare an eye-space Z value for encoding. See R2_logDepthEncodePartial.
///
/// @param z An eye-space Z value
/// @return The prepared value
///
float
R2_logDepthPrepareEyeZ(
const float z)
{
return 1.0 + (-z);
}
///
/// Partially encode the given _positive_ eye-space Z value. This partial encoding
/// can be used when performing part of the encoding in a vertex shader
/// and the rest in a fragment shader (for efficiency reasons) - See R2_logDepthPrepareEyeZ.
///
/// @param z An eye-space Z value
/// @param depth_coefficient The depth coefficient used to encode \a z
///
/// @return The encoded depth
///
float
R2_logDepthEncodePartial(
const float z,
const float depth_coefficient)
{
float half_co = depth_coefficient * 0.5;
float clamp_z = max (0.000001, z);
return log2 (clamp_z) * half_co;
}
///
/// Fully encode the given eye-space Z value.
///
/// @param z An eye-space Z value
/// @param depth_coefficient The depth coefficient used to encode \a z
/// @return The fully encoded depth
///
float
R2_logDepthEncodeFull(
const float z,
const float depth_coefficient)
{
float half_co = depth_coefficient * 0.5;
float clamp_z = max (0.000001, z + 1.0);
return log2 (clamp_z) * half_co;
}
///
/// Decode a depth value that was encoded with the given depth coefficient.
/// Note that in most cases, this will yield a _positive_ eye-space Z value,
/// and must be negated to yield a conventional negative eye-space Z value.
///
/// @param z The depth value
/// @param depth_coefficient The coefficient used during encoding
///
/// @return The original (positive) eye-space Z value
///
float
R2_logDepthDecode(
const float z,
const float depth_coefficient)
{
float half_co = depth_coefficient * 0.5;
float exponent = z / half_co;
return pow (2.0, exponent) - 1.0;
}
#endif // R2_LOG_DEPTH_H
module Reflection where import qualified Vector3f as V3 reflection :: V3.T -> V3.T -> V3.T reflection v0 v1 = V3.sub3 v0 (V3.scale v1 (2.0 * (V3.dot3 v1 v0)))
module FogFactorZ where
clamp :: Float -> (Float, Float) -> Float
clamp x (lower, upper) = max (min x upper) lower
fogLinear :: Float -> (Float, Float) -> Float
fogLinear z (near, far) =
let r = (z - near) / (far - near) in
clamp r (0.0, 1.0)
fogQuadratic :: Float -> (Float, Float) -> Float
fogQuadratic z (near, far) =
let q = fogLinear z (near, far) in q * q
fogQuadraticInverse :: Float -> (Float, Float) -> Float
fogQuadraticInverse z (near, far) =
let q = fogLinear z (near, far) in sqrt(q)