I’m hoping someone can shed some light on how texture sampling works with Texture3D and tex3d. I am seeing different results when sampling from a 2D texture then when sampling from a similar 3D texture.
As a simple test case, I create a 3D texture in code, and have a shader that maps a slice of that 3D texture to a 2D quad. The texture is 8x8x8, and is gradient (or step) from black to white in the x/u direction. So for a given value of x/u, all values of y/v and z/w are the same.
When sampling in the shader, I map the u and v from the vertex positions as you would with any 2D texture, and set the w to a fixed value.
At the same time as I create the 3D texture, I also create a 2D texture, using the same pixel values as the 3D texture for one slice in the z-direction, when z = 0.
Both textures have point filtering and clamp wrap mode.
Why are the colors brighter on the 3D version?
Here is the code to create the textures:
for(int k = 0; k < texDim; k++)
{
for(int j = 0; j < texDim; j++)
{
for(int i = 0; i < texDim; i++)
{
byte colorByte = (byte)(255 * i / (float)(texDim - 1));
pixels[i + (j * texDim) + (k * texDim * texDim)].r = colorByte;
pixels[i + (j * texDim) + (k * texDim * texDim)].g = colorByte;
pixels[i + (j * texDim) + (k * texDim * texDim)].b = colorByte;
pixels[i + (j * texDim) + (k * texDim * texDim)].a = 1;
if(k == 0)
{
pixels2d[i + (j * texDim)].r = colorByte;
pixels2d[i + (j * texDim)].g = colorByte;
pixels2d[i + (j * texDim)].b = colorByte;
pixels2d[i + (j * texDim)].a = 1;
}
}
}
}
tex3d.SetPixels32(pixels);
tex3d.wrapMode = TextureWrapMode.Clamp;
tex3d.filterMode = FilterMode.Point;
tex3d.Apply();
tex2d.SetPixels32(pixels2d);
tex2d.wrapMode = TextureWrapMode.Clamp;
tex2d.filterMode = FilterMode.Point;
tex2d.Apply();
Here is the 3d shader code:
struct appdata
{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
};
struct v2f
{
float2 uv : TEXCOORD0;
float4 vertex : SV_POSITION;
};
sampler3D _Tex3d;
float _Slice;
v2f vert (appdata v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
o.uv = v.uv;
return o;
}
fixed4 frag (v2f i) : SV_Target
{
// sample the texture
float3 uvw = float3(i.uv.x, i.uv.y, _Slice);
fixed4 col = tex3D(_Tex3d, uvw);
return col;
}
And 2D shader code:
struct appdata
{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
};
struct v2f
{
float2 uv : TEXCOORD0;
float4 vertex : SV_POSITION;
};
sampler2D _MainTex;
v2f vert(appdata v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
o.uv = v.uv;
return o;
}
fixed4 frag(v2f i) : SV_Target
{
fixed4 col = tex2D(_MainTex, i.uv);
return col;
}