Index: src/client/renderer/r_local.h =================================================================== --- src/client/renderer/r_local.h (Revision 29336) +++ src/client/renderer/r_local.h (Arbeitskopie) @@ -89,6 +89,7 @@ extern cvar_t *r_postprocess; extern cvar_t *r_shownormals; extern cvar_t *r_bumpmap; +extern cvar_t *r_reliefmap; extern cvar_t *r_specular; extern cvar_t *r_hardness; extern cvar_t *r_parallax; Index: src/client/renderer/r_main.c =================================================================== --- src/client/renderer/r_main.c (Revision 29336) +++ src/client/renderer/r_main.c (Arbeitskopie) @@ -89,6 +89,7 @@ cvar_t *r_geoscape_overlay; cvar_t *r_shownormals; cvar_t *r_bumpmap; +cvar_t *r_reliefmap; cvar_t *r_specular; cvar_t *r_hardness; cvar_t *r_parallax; @@ -216,6 +217,11 @@ r_deluxemap->modified = qfalse; } + if (r_reliefmap->modified) { + R_RestartPrograms_f(); + r_reliefmap->modified = qfalse; + } + if (r_programs->modified) { R_RestartPrograms_f(); r_programs->modified = qfalse; @@ -444,6 +450,7 @@ r_programs->modified = qfalse; r_shownormals = Cvar_Get("r_shownormals", "0", CVAR_ARCHIVE, "Show normals on bsp surfaces"); r_bumpmap = Cvar_Get("r_bumpmap", "1.0", CVAR_ARCHIVE | CVAR_R_PROGRAMS, "Activate bump mapping"); + r_reliefmap = Cvar_Get("r_reliefmap", "0", CVAR_ARCHIVE | CVAR_R_PROGRAMS, "Activates relief mapping (r_bumpmap must be activated, too)"); r_specular = Cvar_Get("r_specular", "1.0", CVAR_ARCHIVE, "Controls specular parameters"); r_hardness = Cvar_Get("r_hardness", "1.0", CVAR_ARCHIVE, "Hardness controll for GLSL shaders (specular, bump, ...)"); r_parallax = Cvar_Get("r_parallax", "1.0", CVAR_ARCHIVE, "Controls parallax parameters"); Index: src/client/renderer/r_program.c =================================================================== --- src/client/renderer/r_program.c (Revision 29334) +++ src/client/renderer/r_program.c (Arbeitskopie) @@ -489,6 +489,7 @@ R_ProgramParameter1f("PARALLAX", 1.0); R_ProgramParameter1f("HARDNESS", 0.2); R_ProgramParameter1f("SPECULAR", 1.0); + R_ProgramParameter1f("DEPTH_FACTOR", 0.05); } static void R_InitMeshProgram (r_program_t *prog) Index: base/shaders/world_fs.glsl =================================================================== --- base/shaders/world_fs.glsl (Revision 29330) +++ base/shaders/world_fs.glsl (Arbeitskopie) @@ -1,11 +1,8 @@ // default fragment shader -#include "light_fs.glsl" -#include "bump_fs.glsl" -#include "fog_fs.glsl" - uniform int BUMPMAP; +/* diffuse */ uniform sampler2D SAMPLER0; /* lightmap */ uniform sampler2D SAMPLER1; @@ -17,7 +14,11 @@ const vec3 two = vec3(2.0); const vec3 negHalf = vec3(-0.5); +#include "light_fs.glsl" +#include "bump_fs.glsl" +#include "fog_fs.glsl" + /* * main */ Index: base/shaders/bump_fs.glsl =================================================================== --- base/shaders/bump_fs.glsl (Revision 29330) +++ base/shaders/bump_fs.glsl (Arbeitskopie) @@ -6,18 +6,88 @@ uniform float PARALLAX; uniform float HARDNESS; uniform float SPECULAR; +uniform float DEPTH_FACTOR; vec3 eye; +#if r_reliefmap +/* + * RayIntersect + */ +float RayIntersect(sampler2D normalMap, vec2 dp, vec2 ds) { + const int linearSearchSteps = 16; + const int binarySearchSteps = 6; + float depthStep = 1.0 / float(linearSearchSteps); + + // current size of search window + float size = depthStep; + + // current depth position + float depth = 0.0; + + // best match found (starts with last position 1.0) + float bestDepth = 1.0; + + // search front to back for first point inside object + for(int i = 0; i < linearSearchSteps - 1; ++i){ + depth += size; + + vec4 t = texture2D(normalMap, dp + ds * depth); + + if(bestDepth > 0.996) // if no depth found yet + if(depth >= t.w) + bestDepth = depth; // store best depth + } + + depth = bestDepth; + + // recurse around first point (depth) for closest match + for(int i = 0; i < binarySearchSteps; ++i){ + size *= 0.5; + + vec4 t = texture2D(normalMap, dp + ds * depth); + + if(depth >= t.w) + if(depth <= t.z){ + bestDepth = depth; + depth -= 2.0 * size; + } + + depth += size; + } + + return bestDepth; +} + /* + * BumpFragmentRelief + */ +vec2 BumpFragmentRelief(sampler2D normalMap){ + // size and start position of search in texture space + vec2 S = eye.xy * -DEPTH_FACTOR / eye.z; + + vec2 normalmap = texture2D(normalMap, gl_TexCoord[0].st).xzy; + float depth = RayIntersect(normalMap, normalmap, S); + + // compute texcoords offset + vec2 texOffset = S * depth; + return texOffset; +} +#endif + +/* * BumpTexcoord */ vec2 BumpTexcoord(in float height){ eye = normalize(eyedir); - return vec2(height * PARALLAX * 0.04 - 0.02) * eye.xy; + vec2 offset = vec2(height * PARALLAX * 0.04 - 0.02) * eye.xy; +#if r_reliefmap + offset += BumpFragmentRelief(SAMPLER3); +#endif + return offset; }