On rendering particles as unit spheres everything works fine, but obivously calculation of normals
for an ellipsoid fails in my code. OptiX API uses RH and Y UP axis, right?
The particles (using water material desinged as in OptiX Introduction in Advanced Samples) are actually
ellipsoids. Each of them has 3 vectors (U, V, W) and a 3D-scale. W is the normal vector when applied with ellipsoid spatting on a rasterizer.
Intersection checking is done by simply using a sphere on transformed RayOrigin and transformed RayDirection.
The transform is performed using an inverse matrix containing all U,V,W vectors and xyz scales. That seems to work.
The normals I simply calculate from the spherical coord angles theta and phi; based on this answer:
That calc seems to be Z UP axis, so I changed my code to Y UP axis.
But yet the normals are invalid (cause the reflection+refraction of the water material should behave “upside-done” in an ellipsoid also)
I’m glad for any advice, cause this took hours, but no result yet…
in my source file ellipsoid_texcoord_tangent.cu:
OO = OO - center; #ifdef SPHERE_TEST float radius = sphere.w; #else // then ellipsoid // then apply inverse matrix (rotation and scale on Origin OO and direction DD) const float radius = 1.0f; OO = make_float3( make_float4(OO.x, OO.y, OO.z, 1.0f) * invTransMatrix ); DD = make_float3( make_float4(DD.x, DD.y, DD.z, 0.0f) * invTransMatrix ); float len = length(DD); float _1div_len = 1.0f / len; DD = make_float3(DD.x * _1div_len, DD.y * _1div_len, DD.z * _1div_len); // unit length #endif // ... calculate intersection as on a unit sphere (as in sphere_texcoord_tangent.cu of optixMDLsphere SDK sample) // on potential intersection: float3 p = (OO + (root1 + root11)*D); #ifdef SPHERE_TEST shading_normal = geometric_normal = p/radius; #else const float phi = atan2f(p.z, p.x); // Azimuth angle -180° .. +180° const float theta = acosf(clamp(p.y, -1.0f, 1.0f)); // Polar angle 0..180° // pre-calc sin+cos for phi and theta float sin_phi, cos_phi, sin_theta, cos_theta; sincosf(phi, &sin_phi, &cos_phi); sincosf(theta, &sin_theta, &cos_theta); /* // is Z UP coord obviously (here the transform matrix also contained scaling) float nx = cos_theta * cos_phi; float ny = cos_theta * sin_phi; float nz = sin_theta; */ // Y UP // the TransMatrix only contains the rotation; no scaling float nx = cos_theta * cos_phi / scales.x; float nz = cos_theta * sin_phi / scales.z; float ny = sin_theta / scales.y; float3 norm = make_float3(nx, ny, nz); // rotation transform this point back to final coords norm = make_float3( make_float4(norm.x, norm.y, norm.z, 1.0f) * TransMatrix ); // point transform (w=1) direction transform (w=0) norm = normalize(norm); shading_normal = geometric_normal = norm; #endif