Okay, I got texture atlas working. There are some imperfections however.
1. There were random streaks of lines along the border. This is seemingly fixed by using linear filtering (linear point point point in Ogre material to be more specific).
2. There are color bleeding, which is expected. Now I am wondering what texture atlas program are there that can handle this for me (if there are any). I remember seeing it referenced on the forums here a while back but I wanted to see if anyone has any updates on it.
Here is what I am talking about:

It's a lot more clearer with grass:

Here is my Ogre.material:
Code:
vertex_program VoxelTexture_VP cg
{
source VoxelTexture.cg
entry_point voxeltexture_vp
profiles vs_1_1
default_params
{
param_named_auto world world_matrix
param_named_auto viewProj viewproj_matrix
}
}
fragment_program VoxelTexture_FP cg
{
source VoxelTexture.cg
entry_point voxeltexture_fp
profiles ps3_0 ps_2_x ps_2_0
}
material VoxelTexture
{
receive_shadows on
technique
{
pass
{
vertex_program_ref VoxelTexture_VP
{
}
fragment_program_ref VoxelTexture_FP
{
}
texture_unit
{
texture TextureAtlas.png 2d
filtering point point point
tex_address_mode clamp
}
}
}
}
Here is my CG Shader code:
Code:
#define VOXELCENTEROFFSET 0.5
#define WORLDSCALE 1.0
#define NUM_TEX_PER_ROW 4
#define TEX_WIDTH_NORMALIZED (1.0 / NUM_TEX_PER_ROW)
void voxeltexture_vp(
float4 inPosition : POSITION,
float4 inColor : COLOR,
out float4 outPosition : POSITION,
out float4 outWorldPosition : TEXCOORD0,
out float4 outColor : TEXCOORD1,
uniform float4x4 world,
uniform float4x4 viewProj)
{
outWorldPosition = mul(world, inPosition);
outPosition = mul(viewProj, outWorldPosition);
outColor = inColor;
}
void voxeltexture_fp(
float4 inWorldPosition : TEXCOORD0,
float4 inColor : TEXCOORD1,
out float4 outColor : COLOR,
uniform sampler2D texture)
{
float3 worldNormal = cross(ddy(inWorldPosition.xyz / WORLDSCALE), ddx(inWorldPosition.xyz / WORLDSCALE));
worldNormal = normalize(worldNormal);
float2 pos;
//Right
if(worldNormal.x > 0.5)
{
pos = frac(inWorldPosition.zy + VOXELCENTEROFFSET); //Only divide by WORLDSCALE if it isn't a whole number
pos.x = 1 - pos.x;
pos.y = 1 - pos.y;
}
//Left
if(worldNormal.x < -0.5)
{
pos = frac(inWorldPosition.zy + VOXELCENTEROFFSET);
pos.y = 1 - pos.y;
}
//Top
if(worldNormal.y > 0.5)
{
pos = frac(inWorldPosition.xz + VOXELCENTEROFFSET);
}
//Bottom
if(worldNormal.y < -0.5)
{
pos = frac(inWorldPosition.xz + VOXELCENTEROFFSET);
pos.y = 1 - pos.y;
}
//Front
if(worldNormal.z > 0.5)
{
pos = frac(inWorldPosition.xy + VOXELCENTEROFFSET);
pos.y = 1 - pos.y;
}
//Back
if(worldNormal.z < -0.5)
{
pos = frac(inWorldPosition.xy + VOXELCENTEROFFSET);
pos.x = 1 - pos.x;
pos.y = 1 - pos.y;
}
//Texture atlas handling
pos *= TEX_WIDTH_NORMALIZED;
if(inColor.x != 0)
{
pos.x += inColor.x;
}
if(inColor.y != 0)
{
pos.y += inColor.y;
}
outColor = tex2D(texture, pos);
}
Here is my C++ code that is pertinent to this (this is inside the Vertices loop):
Code:
Ogre::ColourValue val;
VoxelMat vMat = vecItr->getMaterial();
uint16_t mat = vMat.getMaterial() - NUM_NONTEX_MATERIALS;
/*
r = u coords where the texture starts
g = v coords where the texture starts
b = direction of the block with 0.0, 0.25, 0.5, 0.75 as North, East, South, West
a = maybe used to flag that one of the faces uses a different texture?
*/
val.r = mat % NUM_TEX_PER_ROW * TEX_WIDTH_NORMALIZED;
val.g = mat / NUM_TEX_PER_ROW * TEX_WIDTH_NORMALIZED;
val.b = 0.0f;
val.a = 1.0f;
obj->colour(val);
In addition I have some questions:
1. When you use a frac, doesn't this mean that there is nothing on the entire [1, 1]? Could this be the thing I am seeing instead of color bleeding?
2. I would need to handle blocks with directions and this would mean using a different texture to show this. In addition, some blocks may have different textures on top and on bottom. For this, wouldn't handling this in the shader code be extremely slow? I think I read somewhere that shader codes aren't meant to do a bunch of conditionals.
3. Related to 2, is there a way to transport all of these calculation (normal and tex coords) to the vertex (which would mean I cannot use ddy and ddx to determine the normals as that is a pixel shader only thing). This is because the pixel shader is a lot more expensive than the vertex shader.
4. Is there a way to actually do this in the C++ code itself?
5. Would you suggest doing lighting in the vertex shader or the pixel shader?
Edit on 4:
So if I print the indices out in triplets I would end up getting these coordinates as vertices (first 2 triangles):
(31.5,15.5,0.5)
(29.5,15.5,0.5)
(0.5,17.5,-0.5)
(31.5,15.5,0.5)
(0.5,17.5,-0.5)
(-0.5,17.5,-0.5)
As you can tell the third point doesn't match up to the expectation of a triangle of a face of a cube. I assume this is because CubicSurfaceExtractor has the built in decimation thus producing this. Is this correct? If so you can't set texture coordinates on the vertex like this.