ker wrote:
Shanee, you seem to have gotten the hang of it, texatlas + triplanar texturing...
can you give me some code snippets of your rendering and shader code?
Sorry about the mess!
Rendering has nothing special. Also my texture atlas is still buggy
mip mapping doesn't work and so does filtering properly.
Also I don't know if my way is the best way, I just wrote this shader in a few seconds to try out more materials.
TextureAtlas.fx
Code:
#ifndef TEXTUREATLAS
#define TEXTUREATLAS
float2 GetAtlasUV(float2 uv, float material, float numMatsX, float numMatsY)
{
// First make sure u/v are between 0 and 1.
while (uv.x > 1)
{
uv.x -= 1;
}
while (uv.x < 0)
{
uv.x += 1;
}
while (uv.y > 1)
{
uv.y -= 1;
}
while (uv.y < 0)
{
uv.y += 1;
}
// Divide by the number of materials to get proper texture UV coordinates
uv.x /= numMatsX;
uv.y /= numMatsY;
float yPos = 0;
while (material >= numMatsX)
{
yPos += 1;
material -= numMatsX;
}
uv.x += 1 / numMatsX * material;
uv.y += 1 / numMatsY * yPos;
return uv;
}
#endif
VoxelShaderAtlas.fx
Code:
#include "BlinnPhong.fx"
#include "TextureAtlas.fx"
float4x4 World;
float4x4 View;
float4x4 Projection;
float textureScale;
uniform extern float3 gEyePos;
texture gTex0;
sampler ColorMapSampler = sampler_state
{
Texture = <gTex0>;
/*MinFilter = ANISOTROPIC;
MagFilter = ANISOTROPIC;
MipFilter = Linear; */
MinFilter = NONE;
MagFilter = NONE;
MipFilter = NONE;
AddressU = Clamp;
AddressV = Clamp;
};
// TODO: add effect parameters here.
struct VertexShaderInput
{
float4 Position : POSITION0;
float3 Normal : NORMAL0;
float1 Material : TEXCOORD0;
// TODO: add input channels such as texture
// coordinates and vertex colors here.
};
struct VertexShaderOutput
{
float4 Position : POSITION0;
float3 Normal : TEXCOORD0;
float3 worldPosition : TEXCOORD1;
float1 Material : TEXCOORD2;
// TODO: add vertex shader outputs such as colors and texture
// coordinates here. These values will automatically be interpolated
// over the triangle, and provided as input to your pixel shader.
};
VertexShaderOutput VertexShaderFunction(VertexShaderInput input)
{
VertexShaderOutput output;
float4 worldPosition = mul(input.Position, World);
float4 viewPosition = mul(worldPosition, View);
output.Position = mul(viewPosition, Projection);
output.worldPosition = input.Position.xyz / input.Position.w;
output.Normal = normalize(input.Normal);
output.Material = input.Material;
// TODO: add your vertex shader code here.
return output;
}
float4 PixelShaderFunction(VertexShaderOutput input) : COLOR0
{
float3 Normal = normalize(input.Normal);
float3 absNormal = abs(Normal);
float3 blend_weights = absNormal;
blend_weights = blend_weights - 0.2679f;
blend_weights = max(blend_weights, 0);
// force sum to 1.0
blend_weights /= (blend_weights.x + blend_weights.y + blend_weights.z).xxx;
float4 blended_color;
float tex_scale = 0.1f;
float2 coord1 = GetAtlasUV(input.worldPosition.yz * tex_scale, input.Material, 4, 4);
float2 coord2 = GetAtlasUV(input.worldPosition.zx * tex_scale, input.Material, 4, 4);
float2 coord3 = GetAtlasUV(input.worldPosition.xy * tex_scale, input.Material, 4, 4);
float4 col1 = tex2D(ColorMapSampler, coord1);// * 0.01 + float4(1.0,0.0,0.0,1.0); // uncomment to see the blending in red/green/blue only
float4 col2 = tex2D(ColorMapSampler, coord2);// * 0.01 + float4(0.0,1.0,0.0,1.0);
float4 col3 = tex2D(ColorMapSampler, coord3);// * 0.01 + float4(0.0,0.0,1.0,1.0);
blended_color = col1.xyzw * blend_weights.xxxx +
col2.xyzw * blend_weights.yyyy +
col3.xyzw * blend_weights.zzzz;
// Compute the vector from the vertex to the eye position.
float3 viewDir = normalize(gEyePos - input.worldPosition);
Lighting lightColor = GetDirectionalLight(viewDir, -Normal);
float3 finalLight = float3(0,0,0);
for (int i = 0; i < MAX_LIGHTS; i++)
{
float3 lightDir = gLights[i].position - input.worldPosition; // FIND THE VECTOR BETWEEN THE 3D POSITION IN SPACE OF THE SURFACE
Lighting lightColor2 = GetPointLight(gLights[i], viewDir, -Normal, lightDir);
lightColor.Diffuse += lightColor2.Diffuse;
lightColor.Specular += lightColor2.Specular;
}
// Combine texture color with color generated by lighting.
finalLight += AmbientLight;
finalLight += lightColor.Diffuse;
//return float4((Normal+1)/2, 1);
return float4(finalLight * blended_color.xyz, 1);
}
technique Technique1
{
pass Pass1
{
// TODO: set renderstates here.
CULLMODE = CCW;
ZENABLE = TRUE;
ZWRITEENABLE = TRUE;
VertexShader = compile vs_3_0 VertexShaderFunction();
PixelShader = compile ps_3_0 PixelShaderFunction();
}
}
BlinnPhong.fx
Code:
#ifndef BLINNPHON_FX
#define BLINNPHON_FX
struct Lighting
{
float3 Diffuse;
float3 Specular;
};
struct PointLight
{
float3 position;
float3 diffuseColor;
float diffusePower;
float3 specularColor;
float specularPower;
};
struct DirectionalLight
{
float3 Diffuse;
float DiffusePower;
float3 Specular;
float SpecularPower;
float3 Direction;
};
struct Mtrl
{
float4 Diffuse;
float4 Ambient;
float4 Specular;
float4 Emissive;
float SpecularPower;
};
/*uniform extern texture gNormalMap;
sampler NormalMapS = sampler_state
{
Texture = <gNormalMap>;
MinFilter = ANISOTROPIC;
MaxAnisotropy = 8;
MagFilter = LINEAR;
MipFilter = LINEAR;
AddressU = WRAP;
AddressV = WRAP;
};*/
uniform extern Mtrl Material;
DirectionalLight gDirectionalLight;
#define MAX_LIGHTS 8
uniform extern PointLight gLights[MAX_LIGHTS];
float3 AmbientLight = float3(0.2,0.2,0.2);
static float specularHardness = 25.0f;
Lighting GetPointLightOld(PointLight light, float3 viewDir, float3 normal, float3 lightDir)
{
Lighting OUT;
if(light.diffusePower > 0)
{
//normal = normalize(normal);
float distance = length(lightDir); // GET THE DISTANCE OF THIS VECTOR
distance = distance * distance; // USES INVERSE SQUARE FOR DISTANCE ATTENUATION
lightDir = normalize(lightDir); // NORMALIZE THE VECTOR
// INTENSITY OF THE DIFFUSE LIGHT
// SATURATE TO KEEP WITHIN THE 0-1 RANGE
// DOT PRODUCT OF THE LIGHT DIRECTION VECTOR AND THE SURFACE NORMAL
float i = saturate(dot(lightDir, normal));
OUT.Diffuse = i * light.diffuseColor * light.diffusePower / distance; // CALCULATE THE DIFFUSE LIGHT FACTORING IN LIGHT COLOUR, POWER AND THE ATTENUATION
//CALCULATE THE HALF VECTOR BETWEEN THE LIGHT VECTOR AND THE VIEW VECTOR. THIS IS CHEAPER THEN CALCULATING THE ACTUAL REFLECTIVE VECTOR
float3 h = normalize(lightDir + viewDir);
// INTENSITY OF THE SPECULAR LIGHT
// DOT PRODUCT OF NORMAL VECTOR AND THE HALF VECTOR TO THE POWER OF THE SPECULAR HARDNESS
i = pow(saturate(dot(normal, h)), specularHardness);
OUT.Specular = i * light.specularColor * light.specularPower / distance; // CALCULATE THE SPECULAR LIGHT FACTORING IN LIGHT SPECULAR COLOUR, POWER AND THE ATTENUATION
}
return OUT;
}
Lighting GetDirectionalLightOld(float3 viewDir, float3 normal)
{
Lighting OUT;
if(gDirectionalLight.DiffusePower > 0)
{
normal = normalize(normal);
float lightDir = normalize(gDirectionalLight.Direction); // NORMALIZE THE VECTOR
// INTENSITY OF THE DIFFUSE LIGHT
// SATURATE TO KEEP WITHIN THE 0-1 RANGE
// DOT PRODUCT OF THE LIGHT DIRECTION VECTOR AND THE SURFACE NORMAL
//float i = saturate(dot(lightDir, normal));
float i = saturate(dot(normal, lightDir));
OUT.Diffuse = i * gDirectionalLight.Diffuse * gDirectionalLight.DiffusePower ; // CALCULATE THE DIFFUSE LIGHT FACTORING IN LIGHT COLOUR, POWER AND THE ATTENUATION
//CALCULATE THE HALF VECTOR BETWEEN THE LIGHT VECTOR AND THE VIEW VECTOR. THIS IS CHEAPER THEN CALCULATING THE ACTUAL REFLECTIVE VECTOR
float3 h = normalize(lightDir + viewDir);
// INTENSITY OF THE SPECULAR LIGHT
// DOT PRODUCT OF NORMAL VECTOR AND THE HALF VECTOR TO THE POWER OF THE SPECULAR HARDNESS
i = pow(saturate(dot(normal, h)), specularHardness);
OUT.Specular = i * gDirectionalLight.Specular * gDirectionalLight.SpecularPower ; // CALCULATE THE SPECULAR LIGHT FACTORING IN LIGHT SPECULAR COLOUR, POWER AND THE ATTENUATION
}
return OUT;
}
Lighting GetDirectionalLight(float3 viewDir, float3 normal)
{
Lighting OUT;
/*normal = normalize(normal);
float3 lightVec = normalize(gDirectionalLight.Direction);
float3 halfVec = normalize(lightVec + viewDir);
OUT.Diffuse = saturate(dot(normal, lightVec)) * gDirectionalLight.Diffuse * gDirectionalLight.DiffusePower;
OUT.Specular = pow(saturate(dot(normal, halfVec)), 8) * gDirectionalLight.Specular * gDirectionalLight.SpecularPower;*/
/*normal = normalize(normal);
float3 lightVec = normalize(gDirectionalLight.Direction);
float3 ViewDir = normalize(viewDir);
OUT.Diffuse = saturate(dot(normal, lightVec)); // diffuse component
// R = 2 * (N.L) * N - L
float3 Reflect = normalize(2 * OUT.Diffuse * normal - lightVec);
OUT.Specular = pow(saturate(dot(Reflect, ViewDir)), 8); // R.V^n */
normal = normalize(normal);
float3 lightVec = normalize(gDirectionalLight.Direction);
// Compute the reflection vector.
float3 r = reflect(lightVec, normal);
// Determine how much (if any) specular light makes it
// into the eye.
float t = pow(max(dot(r, viewDir), 0.0f), gDirectionalLight.SpecularPower);
// Determine the diffuse light intensity that strikes the vertex.
float s = max(dot(-lightVec, normal), 0.0f);
// Compute the ambient, diffuse, and specular terms separately.
OUT.Specular = t*(gDirectionalLight.Specular).rgb;
OUT.Diffuse = s*(gDirectionalLight.Diffuse).rgb;
return OUT;
}
Lighting GetPointLight(PointLight light, float3 viewDir, float3 normal, float3 lightDir)
{
Lighting OUT;
normal = normalize(normal);
float distance = length(lightDir); // GET THE DISTANCE OF THIS VECTOR
distance = distance * distance; // USES INVERSE SQUARE FOR DISTANCE ATTENUATION
lightDir = normalize(lightDir); // NORMALIZE THE VECTOR
float3 halfVec = normalize(lightDir + viewDir);
OUT.Diffuse = saturate(dot(normal, lightDir)) * light.diffuseColor * light.diffusePower / distance;
OUT.Specular = pow(saturate(dot(normal, halfVec)), specularHardness) * light.specularColor * light.specularPower / distance;
return OUT;
}
Lighting GetPointLightNormal(PointLight light, float3 viewDir, float3 normal, float3 lightDir, float3 distance)
{
Lighting OUT;
normal = normalize(normal);
distance = length(distance); // GET THE DISTANCE OF THIS VECTOR
distance = distance * distance; // USES INVERSE SQUARE FOR DISTANCE ATTENUATION
lightDir = normalize(lightDir); // NORMALIZE THE VECTOR
float3 halfVec = normalize(lightDir + viewDir);
OUT.Diffuse = saturate(dot(normal, lightDir)) * light.diffuseColor * light.diffusePower / distance;
OUT.Specular = pow(saturate(dot(normal, halfVec)), specularHardness) * light.specularColor * light.specularPower / distance;
return OUT;
}
Lighting GetDirectionalLightBormal(float3 LightDir, float3 viewDir, float3 normal)
{
Lighting OUT;
/*normal = normalize(normal);
float3 lightVec = normalize(LightDir);
float3 halfVec = normalize(lightVec + viewDir);
OUT.Diffuse = saturate(dot(normal, lightVec)) * gDirectionalLight.Diffuse * gDirectionalLight.DiffusePower;
OUT.Specular = pow(saturate(dot(normal, halfVec)), 8) * gDirectionalLight.Specular * gDirectionalLight.SpecularPower;*/
/*normal = normalize(normal);
float3 lightVec = normalize(LightDir);
float3 ViewDir = normalize(viewDir);
OUT.Diffuse = saturate(dot(normal, lightVec)); // diffuse component
// R = 2 * (N.L) * N - L
float3 Reflect = normalize(2 * OUT.Diffuse * normal - lightVec);
OUT.Specular = pow(saturate(dot(Reflect, ViewDir)), 8); // R.V^n */
normal = normalize(normal);
float3 lightVec = normalize(LightDir);
// Compute the reflection vector.
float3 r = reflect(lightVec, normal);
// Determine how much (if any) specular light makes it
// into the eye.
float t = pow(max(dot(r, viewDir), 0.0f), gDirectionalLight.SpecularPower);
// Determine the diffuse light intensity that strikes the vertex.
float s = max(dot(-lightVec, normal), 0.0f);
if(s <= 0.0f)
t = 0.0f;
// Compute the ambient, diffuse, and specular terms separately.
OUT.Specular = t*(gDirectionalLight.Specular).rgb;
OUT.Diffuse = s*(gDirectionalLight.Diffuse).rgb;
return OUT;
}
#endif