1. made distance affecting the light strength (without attenuation, something simple and hard-coded)
2. made optimization to reduce passes - takes two lights every pass instead of one
anyway I'm a little new to Ogre materials system so what I'm basically asking is if someone would review it and tell me if there is room for improvement or if I'm doing something stupid there. basically it works, but I'd be happy to improve it.
also, feel free to use it.
here it is -
parallax.cg:
Code: Select all
void OneTexture_vp(float4 position : POSITION,
float2 uv : TEXCOORD0,
out float4 oPosition : POSITION,
out float2 oUv : TEXCOORD0,
uniform float4x4 worldViewProj,
uniform float scale)
{
oPosition = mul(worldViewProj, position);
oUv = uv * scale;
}
void Ambient_vp(float4 position : POSITION,
out float4 oPosition : POSITION,
out float4 colour : COLOR,
uniform float4x4 worldViewProj,
uniform float4 ambient)
{
oPosition = mul(worldViewProj, position);
colour = ambient;
}
// Expand a range-compressed vector
float3 expand(float3 v)
{
return (v - 0.5) * 2;
}
// optimize version of the offset vertex shader which takes two lights every pass
void Offset_Vert_Optimized(
float4 position : POSITION,
float3 normal : NORMAL,
float2 uv : TEXCOORD0,
float3 tangent : TEXCOORD1,
out float4 oPosition : POSITION,
out float2 oUv : TEXCOORD0,
out float3 oLightDir1 : TEXCOORD1,
out float3 oLightDir2 : TEXCOORD2,
out float3 oEyeDir : TEXCOORD3,
out float3 oHalfAngle1 : TEXCOORD4,
out float3 oHalfAngle2 : TEXCOORD5,
out float2 oDistanceFactor : TEXCOORD6, // x = distance factor for light1, y = distance factor for light2
uniform float scale,
uniform float4 lightPosition1, // object space
uniform float4 lightPosition2, // object space
uniform float3 eyePosition, // object space
uniform float4x4 worldviewproj)
{
//why normalize lightDir if don't normalize eyeDir? both will be mul-ed
//by matrix!
oPosition = mul(worldviewproj , position);
oUv = uv * scale;
float3 eyeDir = eyePosition - position.xyz;
float3 binormal = cross(tangent, normal);
float3x3 rotation = float3x3(tangent, binormal, normal);
eyeDir = normalize(mul(rotation, eyeDir));
float3 lightDir;
// LIGHT 1
oDistanceFactor.x = 1.0f / distance(position, lightPosition1);
if (oDistanceFactor.x > 0.001f)
{
lightDir = normalize(lightPosition1.xyz - (position * lightPosition1.w));
lightDir = normalize(mul(rotation, lightDir));
oHalfAngle1 = normalize(eyeDir + lightDir);
oLightDir1 = lightDir;
}
else
{
oHalfAngle1 = 0;
oLightDir1 = 0;
oDistanceFactor.x = 0;
}
// LIGHT 2
oDistanceFactor.y = 1.0f / distance(position, lightPosition2);
if (oDistanceFactor.y > 0.001f)
{
lightDir = normalize(lightPosition2.xyz - (position * lightPosition2.w));
lightDir = normalize(mul(rotation, lightDir));
oHalfAngle2 = normalize(eyeDir + lightDir);
oLightDir2 = lightDir;
}
else
{
oHalfAngle2 = 0;
oLightDir2 = 0;
oDistanceFactor.y = 0;
}
oEyeDir = eyeDir;
}
// this version takes two lights every time so we'll have less passes
void Offset_Frag_Optimized(
float2 uv : TEXCOORD0,
float3 lightVec1 : TEXCOORD1,
float3 lightVec2 : TEXCOORD2,
float3 eyeDir : TEXCOORD3,
float3 halfAngle1: TEXCOORD4,
float3 halfAngle2: TEXCOORD5,
float2 distanceFactor : TEXCOORD6,
out float4 oColor : COLOR,
uniform float4 lightDiffuse1,
uniform float4 lightSpecular1,
uniform float4 lightDiffuse2,
uniform float4 lightSpecular2,
uniform float exponent,
uniform float4 scaleBias,
uniform sampler2D normalHeightMap : register(s0)
)
{
float height = tex2D(normalHeightMap, uv).a;
float scale = scaleBias.x;
float bias = scaleBias.y;
float spec = scaleBias.z;
float displacement = (height * scale) + bias;
float3 uv2 = float3(uv, 1);
float2 newTexCoord = ((eyeDir * displacement) + uv2).xy;
float3 bumpVec = expand(tex2D(normalHeightMap, newTexCoord ).xyz);
float3 N = normalize(bumpVec);
float NdotL;
float NdotH;
float4 Lit;
// LIGHT 1
if (distanceFactor.x > 0)
{
NdotL = dot(lightVec1, N);
NdotH = dot(normalize(halfAngle1), N);
Lit = lit(NdotL,NdotH,exponent);
oColor = lightDiffuse1 * distanceFactor.x * Lit.y + (lightSpecular1 * spec * distanceFactor.x) * Lit.z ;
}
else
{
oColor = 0;
}
// LIGHT 2
if (distanceFactor.y > 0)
{
NdotL = dot(lightVec2, N);
NdotH = dot(normalize(halfAngle2), N);
Lit = lit(NdotL,NdotH,exponent);
oColor += lightDiffuse2 * distanceFactor.y * Lit.y + (lightSpecular2 * spec * distanceFactor.y) * Lit.z ;
}
}
Code: Select all
vertex_program Offset_Vert_Optimized cg
{
source parallax.cg
default_params
{
param_named_auto lightPosition1 light_position_object_space 0
param_named_auto lightPosition2 light_position_object_space 1
param_named_auto eyePosition camera_position_object_space
param_named_auto worldviewproj worldviewproj_matrix
}
entry_point Offset_Vert_Optimized
profiles vs_1_1 arbvp1
}
vertex_program OneTexture cg
{
source parallax.cg
default_params
{
param_named_auto worldViewProj worldviewproj_matrix
}
entry_point OneTexture_vp
profiles vs_1_1 arbvp1
}
vertex_program Ambient cg
{
source parallax.cg
default_params
{
param_named_auto worldViewProj worldviewproj_matrix
param_named_auto ambient ambient_light_colour
}
entry_point Ambient_vp
profiles vs_1_1 arbvp1
}
vertex_program Ogre/BasicVertexPrograms/AmbientOneTexture cg
{
source parallax.cg
entry_point AmbientOneTexture_vp
profiles vs_1_1 arbvp1
}
fragment_program Offset_Frag_Default_Optimized cg
{
source parallax.cg
default_params
{
param_named_auto lightDiffuse1 light_diffuse_colour 0
param_named_auto lightSpecular1 light_specular_colour 0
param_named_auto lightDiffuse2 light_diffuse_colour 1
param_named_auto lightSpecular2 light_specular_colour 1
param_named exponent float 127
param_named scaleBias float4 0.04 -0.02 4 0
}
entry_point Offset_Frag_Optimized
profiles ps_2_0 arbfp1
}
// ACTUAL USAGE:
material GrassMat
{
technique
{
pass
{
vertex_program_ref Ambient
{
}
}
pass
{
// do this for each light
iteration 1 per_n_lights 2
scene_blend add
// Vertex program reference
vertex_program_ref Offset_Vert_Optimized
{
param_named scale float 2
}
// Fragment program
fragment_program_ref Offset_Frag_Default_Optimized
{
}
// Base bump map
texture_unit
{
texture grass_NH.tga
filtering bilinear
}
}
//Decal pass
pass
{
lighting off
vertex_program_ref OneTexture
{
param_named scale float 2
}
scene_blend modulate
texture_unit
{
filtering bilinear
texture grass.png
}
}
}
technique fallback
{
pass
{
lighting on
ambient 1 1 1 1
diffuse 1 1 1 1
specular 1 1 1 10
emissive 0 0 0 1
texture_unit
{
texture grass.png
scale 0.5 0.5
}
}
}
}
I'm especially interested in ways to optimize this (although fps are pretty good, looking for something faster).
thanks
PS this is how it looks:
