In the following code, I try to use indexes passed in as uv.x and uv.y to look up the tangent, normal, and actual uv for the vertex. I set up a mesh with a appropriate data (a cube) but the result is that the cube is always drawn black (the worldNormal always ends up as zero).
I’ve tried sending in a mesh with no normals, and no tangents, and I’ve also tried sending in a mesh with dummy normals and tangents. Neither seems to work.
Is there some way to make this sort of thing work? Is there some general way to pass in custom data, and use it to generate the actual vertex data?
I’ve included the shader and C# script code I use to build the mesh.
Here’s the shader. Take a look at the vertex_unpacker function.
Shader "Custom/CubeShader" {
Properties {
_MainTex ("Base (RGB)", 2D) = "white" {}
}
SubShader {
Tags { "RenderType"="Opaque" }
CGPROGRAM
// Upgrade NOTE: excluded shader from DX11, Xbox360, OpenGL ES 2.0 because it uses unsized arrays
#pragma exclude_renderers gles flash
//d3d11 xbox360
#pragma surface surf Lambert vertex:vertex_unpacker
sampler2D _MainTex;
float3 _normals[6] =
{
float3(1,0,0),
float3(-1,0,0),
float3(0,0,1),
float3(0,0,-1),
float3(0,1,0),
float3(0,-1,0)
};
float4 _tangents[6] =
{
float4(0,0,1,1),
float4(0,0,-1,1),
float4(-1,0,0,1),
float4(1,0,0,1),
float4(0,0,1,1),
float4(0,0,-1,1)
};
float4 _uvs[4] =
{
float4(0,0,0,0),
float4(1,0,0,0),
float4(0,1,0,0),
float4(1,1,0,0)
};
struct Input {
float3 worldNormal;
};
void vertex_unpacker(inout appdata_full i) {
int face = i.texcoord.x;
int vx = i.texcoord.y;
i.normal = _normals[face];
i.tangent = _tangents[face];
i.texcoord = _uvs[vx];
}
void surf (Input IN, inout SurfaceOutput o) {
o.Albedo = IN.worldNormal.xyz;
o.Alpha = 1;
}
ENDCG
}
FallBack "Diffuse"
}
And here’s the script that builds the cube:
using UnityEngine;
using System.Collections;
public class CubeBuilder : MonoBehaviour {
// Use this for initialization
enum Faces
{
POSX,
NEGX,
POSZ,
NEGZ,
POSY,
NEGY
};
enum C
{
RUF,
RUB,
LUF,
LUB,
RLF,
RLB,
LLF,
LLB,
};
void Start ()
{
MeshFilter filter = GetComponent<MeshFilter>();
if (filter != null)
{
Mesh mesh = new Mesh();
filter.sharedMesh = mesh;
Vector3[] cubeCorners = new Vector3[8];
Vector3 v3 = Vector3.zero;
for (int i = 0; i < 8; i++)
{
v3.x = (i & 2) == 0 ? 1 : -1;
v3.y = (i & 4) == 0 ? 1 : -1;
v3.z = (i & 1) == 0 ? 1 : -1;
cubeCorners *= v3;*
-
}*
-
Vector3[] faceVertexes = new Vector3[24]*
-
{*
-
cubeCorners[(int)C.RUB],*
-
cubeCorners[(int)C.RUF],*
-
cubeCorners[(int)C.RLB],*
-
cubeCorners[(int)C.RLF],*
-
cubeCorners[(int)C.LUF],*
-
cubeCorners[(int)C.LUB],*
-
cubeCorners[(int)C.LLF],*
-
cubeCorners[(int)C.LLB],*
-
cubeCorners[(int)C.RUF],*
-
cubeCorners[(int)C.LUF],*
-
cubeCorners[(int)C.RLF],*
-
cubeCorners[(int)C.LLF],*
-
cubeCorners[(int)C.LUB],*
-
cubeCorners[(int)C.RUB],*
-
cubeCorners[(int)C.LLB],*
-
cubeCorners[(int)C.RLB],*
-
cubeCorners[(int)C.LUF],*
-
cubeCorners[(int)C.RUF],*
-
cubeCorners[(int)C.LUB],*
-
cubeCorners[(int)C.RUB],*
-
cubeCorners[(int)C.RLF],*
-
cubeCorners[(int)C.LLF],*
-
cubeCorners[(int)C.RLB],*
-
cubeCorners[(int)C.LLB],*
-
};*
-
Vector2[] faceUVs = new Vector2[24];*
-
for(int face = 0; face < 6; face++)*
-
for(int i = 0; i < 4; i++)*
-
{*
_ faceUVs[face*4+i] = new Vector2(face,i);_
-
}*
-
int[] indexes = new int[36];*
-
for (int i = 0; i < 6; i++)*
-
{*
_ int j = i6;_
_ int vxcount = i4;_
-
indexes[j++] = vxcount;*
-
indexes[j++] = vxcount+1;*
-
indexes[j++] = vxcount+2;*
-
indexes[j++] = vxcount+2;*
-
indexes[j++] = vxcount+1;*
-
indexes[j++] = vxcount+3;*
-
}*
-
mesh.vertices = faceVertexes;*
-
mesh.uv = faceUVs;*
-
mesh.triangles = indexes;*
-
}*
-
}*
-
// Update is called once per frame*
-
void Update () {*
-
}*
}