Does Q2E support HLSL/.fx shaders, or does it use an arbitrary proprietary shader model format?
If .fx is supported, I could throw together a generic parallax shader to add true depth to all the normal maps in the game. (Or specifically for those objects with worldspace normals, since deformations often look silly with parallax bump mapping.)
o'dium, a question about q2e
o'dium, a question about q2e
[img]http://members.cox.net/anticsensue/rep_june.gif[/img]
No, you can grab the displacement/offset information from the normal map. It adds a stage to the shader, but doesn't add another image asset.
Soft shadows can be achieved with .fx as well, and they're not that expensive, especially if you just tag them onto dynamic models.
Soft shadows can be achieved with .fx as well, and they're not that expensive, especially if you just tag them onto dynamic models.
[img]http://members.cox.net/anticsensue/rep_june.gif[/img]
Ever hear of steep parallax mapping? Rofl... Try this on for size:
Edit: Rofl, someone got relief mapping to work in DOOM 3 by adding a depth (height) map generated from the normals to the alpha channel of the specular map, and a little shader wizardry.
Code: Select all
/** Color texture (with alpha) */
uniform sampler2D texture;
uniform vec3 wsEyePos;
/** xyz = normal, w = bump height */
uniform sampler2D normalBumpMap;
/** Multiplier for bump map. Typically on the range [0, 0.05]
This increases with texture scale and bump height. */
uniform float bumpScale;
varying vec3 tsL;
varying vec3 _tsE;
varying vec2 texCoord;
varying vec4 tan_X, tan_Y, tan_Z, tan_W;
void main(void) {
// We are at height bumpScale. March forward until we hit a hair or the
// base surface. Instead of dropping down discrete y-voxels we should be
// marching in texels and dropping our y-value accordingly (TODO: fix)
float height = 1.0;
// Number of height divisions
float numSteps = 5;
/** Texture coordinate marched forward to intersection point */
vec2 offsetCoord = texCoord.xy;
vec4 NB = texture2D(normalBumpMap, offsetCoord);
vec3 tsE = normalize(_tsE);
// Increase steps at oblique angles
// Note: tsE.z = N dot V
numSteps = mix(numSteps*2, numSteps, tsE.z);
// We have to negate tsE because we're walking away from the eye.
//vec2 delta = vec2(-_tsE.x, _tsE.y) * bumpScale / (_tsE.z * numSteps);
float step;
vec2 delta;
// Constant in z
step = 1.0 / numSteps;
delta = vec2(-_tsE.x, _tsE.y) * bumpScale / (_tsE.z * numSteps);
// Can also step along constant in xy; the results are essentially
// the same in each case.
// delta = 1.0 / (25.6 * numSteps) * vec2(-tsE.x, tsE.y);
// step = tsE.z * bumpScale * (25.6 * numSteps) / (length(tsE.xy) * 400);
while (NB.a < height) {
height -= step;
offsetCoord += delta;
NB = texture2D(normalBumpMap, offsetCoord);
}
height = NB.a;
// Choose the color at the location we hit
const vec3 color = texture2D(texture, offsetCoord).rgb;
tsL = normalize(tsL);
// Use the normals out of the bump map
vec3 tsN = NB.xyz * 2 - 1;
// Smooth normals locally along gradient to avoid making slices visible.
// The magnitude of the step should be a function of the resolution and
// of the bump scale and number of steps.
// tsN = normalize(texture2D(normalBumpMap, offsetCoord + vec2(tsN.x, -tsN.y) * mipScale).xyz * 2 - 1 + tsN);
const vec3 tsH = normalize(tsL + normalize(_tsE));
const float NdotL = max(0, tsL.z);
const float NdotH = max(0, dot(tsN, tsH));
float spec = NdotH * NdotH;
vec3 lightColor = vec3(1.5, 1.5, 1) * 0.9;
vec3 ambient = vec3(0.4,0.4,0.6) * 1.4;
float selfShadow = 0;
// Don't bother checking for self-shadowing if we're on the
// back side of an object.
if (NdotL > 0) {
// Trace a shadow ray along the light vector.
const int numShadowSteps = mix(60,5,tsL.z);
step = 1.0 / numShadowSteps;
delta = vec2(tsL.x, -tsL.y) * bumpScale / (numShadowSteps * tsL.z);
// We start one iteration out to avoid shadow acne
// (could start bumped a little without going
// a whole iteration).
height = NB.a + step * 0.1;
while ((NB.a < height) && (height < 1)) {
height += step;
offsetCoord += delta;
NB = texture2D(normalBumpMap, offsetCoord);
}
// We are in shadow if we left the loop because
// we hit a point
selfShadow = (NB.a < height);
// Shadows will make the whole scene darker, so up the light contribution
lightColor = lightColor * 1.2;
}
}
gl_FragColor.rgb =
color * ambient + color * NdotL * selfShadow * lightColor;
}
[img]http://members.cox.net/anticsensue/rep_june.gif[/img]