I’ve been banging my head on this for a while now. I have an indexed PlaneBufferGeometry I’m using for a GPGPU cloth physics simulation, and I can’t for the life of me calculate the normals correctly in the final vertex shader after rendering the simulation to the texture.
This is my current setup (relevant parts included), and I think it’s not working because I need a way to know the order of the current vert and it’s neighbours in the “face”. Just can’t quite get it right.
javascript:
// get faces
const indices = geometry.index.array;
const faces = [];
for(let i = 0; i < indices.length; i += 3)
{
faces.push([indices[i + 0] * 3, indices[i + 1] * 3, indices[i + 2] * 3]);
}
const vertices = geometry.attributes.position.array;
// begin loop
// initializing data texture vertex positions
dataTexturePixels[index * 4 + 0] = vertices[index * 3 + 0];
dataTexturePixels[index * 4 + 1] = vertices[index * 3 + 1];
dataTexturePixels[index * 4 + 2] = vertices[index * 3 + 2];
dataTexturePixels[index * 4 + 3] = 0;
// storing lookup uv's in an attribute for looking up positions
positionReference[index * 3 + 0] = (index % size) / size;
positionReference[index * 3 + 1] = Math.floor(index / size) / size;
// end loop
This is where my brain is tripping up. I’ve tried using the face index values from the faces array in various ways, but because indices are duplicated, data’s being overwritten. Can’t think of how to properly store the vertex index information for each face so it can be looked up in the vertex shader using the positionReference (or some other way).
vertex shader / after simulation runs:
// how I'd calculate the normals if I could get a proper ordered reference
vec2 coord1 = faceVert1UvReference.xy;
vec3 pos1 = texture2D(tPositions, coord1).xyz;
vec2 coord2 = faceVert2UvReference.xy;
vec3 pos2 = texture2D(tPositions, coord2).xyz;
vec2 coord3 = faceVert3UvReference.xy;
vec3 pos3 = texture2D(tPositions, coord3).xyz;
vec3 tangent = pos3 - pos2;
vec3 bitangent = pos1 - pos2;
vec3 normal = normalMatrix * normalize(cross(tangent, bitangent));
fragment shader / lighting:
vec3 lightDirection = normalize(lightPosition); // also tried normalize(lightPosition - vWorldPosition);
vec3 normal = normalize(vNormal);
float lightValue = max(0.0, dot(normal, lightDirection)) * lightIntensity;
finalColor.rgb *= lightValue;
Not sure if I’m missing something obvious/doing something dumb, or this problem is indeed hard. Without posting the many failed ways I’ve tried does anyone have any ideas?
Any help is greatly appreciated.
Edit: I’ve added a couple examples, this one that uses flat shading with face normals, and this one showing my current messed up smooth vertex normals progress. Having a hard time finding my error…