Hi,
I have always had this problem with Optix and material transparency defined in obj files. This problem has always happened in Optix version 2, 3 and now 4 and is always changing.
If you look at this image you can see that it gets the transparency for the sunglasses lens.
This was made using Optix 3.5.1. I changed the obj_material.cu file to include alpha. In Optix 2 I did some different method and now in 4.5 I have no idea how this should be done. Looking at OptixMesh.cpp it doesn’t seem to consider parameters “d” or “Tr”.
OptixMesh.cpp
optix::Material createOptiXMaterial(
optix::Context context,
optix::Program closest_hit,
optix::Program any_hit,
const MaterialParams& mat_params,
bool use_textures
)
{
optix::Material mat = context->createMaterial();
mat->setClosestHitProgram( 0u, closest_hit );
mat->setAnyHitProgram( 1u, any_hit ) ;
if( use_textures )
mat[ "Kd_map"]->setTextureSampler( sutil::loadTexture( context, mat_params.Kd_map, optix::make_float3(mat_params.Kd) ) );
else
mat[ "Kd_map"]->setTextureSampler( sutil::loadTexture( context, "", optix::make_float3(mat_params.Kd) ) );
mat[ "Kd_mapped" ]->setInt( use_textures );
mat[ "Kd" ]->set3fv( mat_params.Kd );
mat[ "Ks" ]->set3fv( mat_params.Ks );
mat[ "Kr" ]->set3fv( mat_params.Kr );
mat[ "Ka" ]->set3fv( mat_params.Ka );
mat[ "phong_exp" ]->setFloat( mat_params.exp );
return mat;
}
Does anyone know how this should be done in versions >= 4.5.
obj_material.cu
/*
* Copyright (c) 2008 - 2009 NVIDIA Corporation. All rights reserved.
*
* NVIDIA Corporation and its licensors retain all intellectual property and proprietary
* rights in and to this software, related documentation and any modifications thereto.
* Any use, reproduction, disclosure or distribution of this software and related
* documentation without an express license agreement from NVIDIA Corporation is strictly
* prohibited.
*
* TO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE LAW, THIS SOFTWARE IS PROVIDED *AS IS*
* AND NVIDIA AND ITS SUPPLIERS DISCLAIM ALL WARRANTIES, EITHER EXPRESS OR IMPLIED,
* INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE. IN NO EVENT SHALL NVIDIA OR ITS SUPPLIERS BE LIABLE FOR ANY
* SPECIAL, INCIDENTAL, INDIRECT, OR CONSEQUENTIAL DAMAGES WHATSOEVER (INCLUDING, WITHOUT
* LIMITATION, DAMAGES FOR LOSS OF BUSINESS PROFITS, BUSINESS INTERRUPTION, LOSS OF
* BUSINESS INFORMATION, OR ANY OTHER PECUNIARY LOSS) ARISING OUT OF THE USE OF OR
* INABILITY TO USE THIS SOFTWARE, EVEN IF NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGES
*/
#include <optix.h>
#include <optixu/optixu_math_namespace.h>
#include "commonStructs.h"
struct PerRayData_radiance
{
float3 result;
float importance;
int depth;
};
struct PerRayData_shadow
{
float3 attenuation;
};
using namespace optix;
rtDeclareVariable(float3, ambient_light_color, , );
rtBuffer<BasicLight> lights;
rtDeclareVariable(int, max_depth, , );
rtDeclareVariable(unsigned int, radiance_ray_type, , );
rtDeclareVariable(unsigned int, shadow_ray_type, , );
rtDeclareVariable(float, scene_epsilon, , );
rtDeclareVariable(rtObject, top_object, , );
rtDeclareVariable(rtObject, top_shadower, , );
rtTextureSampler<float4, 2> ambient_map; //
rtTextureSampler<float4, 2> diffuse_map; // Correspond to OBJ mtl params
rtTextureSampler<float4, 2> specular_map; //
rtDeclareVariable(float, phong_exp, , ); //
rtDeclareVariable(float, alpha, , ); //
rtDeclareVariable(int, illum, , ); //
rtDeclareVariable(optix::Ray, ray, rtCurrentRay, );
rtDeclareVariable(float, t_hit, rtIntersectionDistance, );
rtDeclareVariable(float3, texcoord, attribute texcoord, );
rtDeclareVariable(float3, geometric_normal, attribute geometric_normal, );
rtDeclareVariable(float3, shading_normal, attribute shading_normal, );
rtDeclareVariable(PerRayData_radiance, prd_radiance, rtPayload, );
rtDeclareVariable(PerRayData_shadow, prd_shadow, rtPayload, );
rtDeclareVariable(float3, bg_color, , );
rtTextureSampler<float4, 2> envmap;
static __device__ __inline__ float3 exp( const float3& x )
{
return make_float3(exp(x.x), exp(x.y), exp(x.z));
}
RT_PROGRAM void any_hit_shadow()
{
// this material is opaque, so it fully attenuates all shadow rays
prd_shadow.attenuation = optix::make_float3(1.0 - alpha);
rtTerminateRay();
}
RT_PROGRAM void closest_hit_radiance()
{
float3 direction = ray.direction;
float3 hit_point = ray.origin + t_hit * ray.direction;
float3 world_shading_normal = normalize( rtTransformNormal( RT_OBJECT_TO_WORLD, shading_normal ) );
float3 world_geometric_normal = normalize( rtTransformNormal( RT_OBJECT_TO_WORLD, geometric_normal ) );
float3 ffnormal = faceforward( world_shading_normal, -direction, world_geometric_normal );
float3 uv = texcoord;
float u = ray.direction.x;
float v = ray.direction.y;
float3 env_color = make_float3( tex2D(envmap, u, v) );
float3 black = make_float3(0.0f, 0.0f, 0.0f);
float3 reflectivity_n = make_float3(0.2f, 0.2f, 0.2f);
float importance_cutoff = 1e-2f;
// grab values from textures
// support only MTL illumination modes 0-3 (Ks is for now used as reflectivity)
// ( see http://local.wasp.uwa.edu.au/~pbourke/dataformats/mtl/ )
float3 Kd = make_float3( tex2D( diffuse_map, uv.x, uv.y ) );
float3 Ka = (illum < 1) ? black : make_float3( tex2D( ambient_map, uv.x, uv.y ) );
float3 Ks = (illum < 2) ? black : make_float3( tex2D( specular_map, uv.x, uv.y ) );
float3 Kr = make_float3(0.2f, 0.2f, 0.2f);
// ambient contribution
float3 result = Ks * ambient_light_color;
if (alpha > 0.01 && alpha < 1.0)
{
// intersection vectors
float reflection = 1.0f;
float3 cutoff_color = env_color;
float fresnel_exponent = 3.0f;
float fresnel_minimum = 0.1f;
float fresnel_maximum = 1.0f;
float refraction_index = 1.1f;
float3 refraction_color = make_float3(1.0f - alpha);
float3 reflection_color = make_float3(0.2f);
int refraction_maxdepth = 100;
int reflection_maxdepth = 100;
float3 extinction_constant = make_float3(log(.80f), log(.89f), log(.75f));
float3 beer_attenuation;
if(dot(world_shading_normal, ray.direction) > 0){
// Beer's law attenuation
beer_attenuation = exp(extinction_constant * t_hit);
} else {
beer_attenuation = make_float3(1);
}
// refraction
if (prd_radiance.depth < min(refraction_maxdepth, max_depth))
{
float3 t; // transmission direction
if ( refract(t, direction, world_shading_normal, refraction_index) )
{
// check for external or internal reflection
float cos_theta = dot(direction, world_shading_normal);
if (cos_theta < 0.0f)
cos_theta = -cos_theta;
else
cos_theta = dot(t, world_shading_normal);
reflection = fresnel_schlick(cos_theta, fresnel_exponent, fresnel_minimum, fresnel_maximum);
float importance = prd_radiance.importance * (1.0f-reflection) * optix::luminance( refraction_color * beer_attenuation );
if ( importance > importance_cutoff ) {
optix::Ray ray( hit_point, t, radiance_ray_type, scene_epsilon );
PerRayData_radiance refr_prd;
refr_prd.depth = prd_radiance.depth+1;
refr_prd.importance = importance;
rtTrace( top_object, ray, refr_prd );
result += (1.0f - reflection) * refraction_color * refr_prd.result;
} else
{
result += (1.0f - reflection) * refraction_color * cutoff_color;
}
}
// else TIR
}
// reflection
if (prd_radiance.depth < min(reflection_maxdepth, max_depth))
{
float3 r = reflect(direction, world_shading_normal);
float importance = prd_radiance.importance * reflection * optix::luminance( reflection_color * beer_attenuation );
if ( importance > importance_cutoff ) {
optix::Ray ray( hit_point, r, radiance_ray_type, scene_epsilon );
PerRayData_radiance refl_prd;
refl_prd.depth = prd_radiance.depth+1;
refl_prd.importance = importance;
rtTrace( top_object, ray, refl_prd );
result += reflection * reflection_color * refl_prd.result;
} else {
result += reflection * reflection_color * cutoff_color;
}
}
result = result * beer_attenuation;
}
else
{
// compute direct lighting
unsigned int num_lights = lights.size();
for(int i = 0; i < num_lights; ++i) {
BasicLight light = lights[i];
float Ldist = optix::length(light.pos - hit_point);
float3 L = optix::normalize(light.pos - hit_point);
float nDl = optix::dot( ffnormal, L);
// cast shadow ray
float3 light_attenuation = make_float3(static_cast<float>( nDl > 0.0f ));
if ( nDl > 0.0f && light.casts_shadow )
{
PerRayData_shadow shadow_prd;
shadow_prd.attenuation = make_float3(1.0f);
optix::Ray shadow_ray = optix::make_Ray( hit_point, L, shadow_ray_type, scene_epsilon, Ldist );
rtTrace(top_object, shadow_ray, shadow_prd);
light_attenuation = shadow_prd.attenuation;
}
// If not completely shadowed, light the hit point
if( fmaxf(light_attenuation) > 0.0f ) {
float3 Lc = light.color * light_attenuation;
result += Kd * nDl * Lc;
float3 H = optix::normalize(L - ray.direction);
float nDh = optix::dot( ffnormal, H );
if(nDh > 0) {
float power = pow(nDh, phong_exp);
result += Ks * power * Lc;
}
}
}
if( fmaxf( Kr ) > 0 )
{
// ray tree attenuation
PerRayData_radiance new_prd;
new_prd.importance = prd_radiance.importance * optix::luminance( Kr );
new_prd.depth = prd_radiance.depth + 1;
// reflection ray
if( new_prd.importance >= 0.01f && new_prd.depth <= max_depth)
{
float3 R = optix::reflect( ray.direction, ffnormal );
optix::Ray refl_ray = optix::make_Ray( hit_point, R, radiance_ray_type, scene_epsilon, RT_DEFAULT_MAX );
rtTrace(top_object, refl_ray, new_prd);
result += Kr * new_prd.result;
}
}
}
if (alpha < 0.01)
{
if (result.x < 0.5 && result.y < 0.5 && result.z < 0.5)
result *= env_color;
else
result = env_color;
}
// pass the color back up the tree
prd_radiance.result = result;
}