1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170
|
// Copyright 2009 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
// ospray
#include "Material.h"
#include "render/bsdfs/MicrofacetAlbedoTables.h"
#include "texture/Texture.h"
#ifndef OSPRAY_TARGET_SYCL
// ispc
#include "render/Material_ispc.h"
#endif
namespace ospray {
// Material definitions ///////////////////////////////////////////////////////
Ref<MicrofacetAlbedoTables> Material::microfacetAlbedoTables;
Material::Material(api::ISPCDevice &device, const FeatureFlagsOther ffo)
: AddStructShared(device.getDRTDevice(), device), featureFlags(ffo)
{
managedObjectType = OSP_MATERIAL;
#ifndef OSPRAY_TARGET_SYCL
getSh()->getTransparency =
reinterpret_cast<ispc::Material_GetTransparencyFunc>(
ispc::Material_getTransparency_addr());
getSh()->selectNextMedium =
reinterpret_cast<ispc::Material_SelectNextMediumFunc>(
ispc::Material_selectNextMedium_addr());
getSh()->getEmission = reinterpret_cast<ispc::Material_GetEmissionFunc>(
ispc::Material_getEmission_addr());
#endif
if (!microfacetAlbedoTables) {
microfacetAlbedoTables = new MicrofacetAlbedoTables(device);
// Release the extra local ref
microfacetAlbedoTables->refDec();
} else {
microfacetAlbedoTables->refInc();
}
getSh()->microfacetAlbedoTables = microfacetAlbedoTables->getSh();
}
Material::~Material()
{
if (microfacetAlbedoTables) {
const bool lastReference = microfacetAlbedoTables->useCount() == 1;
// The last material referencing the albedo tables should null out the
// pointer so we don't try to call refDec again and know to re-create it
// when a new material is made
if (lastReference) {
microfacetAlbedoTables = nullptr;
} else {
microfacetAlbedoTables->refDec();
}
}
}
std::string Material::toString() const
{
return "ospray::Material";
}
void Material::commit() {}
ispc::TextureParam Material::getTextureParam(
const char *texture_name, const Ref<Texture> &ref_tex)
{
if (ref_tex)
featureFlags |= FFO_TEXTURE_IN_MATERIAL;
// Get 2D transformation if exists
int transformFlags = ispc::TRANSFORM_FLAG_NONE;
affine2f xfm2f = affine2f(one);
utility::Optional<affine2f> xform2f = getTextureTransform2f(texture_name);
if (xform2f.has_value()) {
xfm2f = xform2f.value();
transformFlags |= ispc::TRANSFORM_FLAG_2D;
}
// Get 3D transformation if exists
affine3f xfm3f = affine3f(one);
auto xform3f =
getOptParam<affine3f>((std::string(texture_name) + ".transform").c_str());
if (xform3f.has_value()) {
xfm3f = xform3f.value();
transformFlags |= ispc::TRANSFORM_FLAG_3D;
}
// Initialize ISPC structure
ispc::TextureParam param;
param.ptr = ref_tex ? ref_tex->getSh() : nullptr;
param.transformFlags = (ispc::TransformFlags)transformFlags;
param.xform2f = xfm2f;
param.scale2f = sqrt(xfm2f.l.det());
param.xform3f = xfm3f;
// Done
return param;
}
MaterialParam1f Material::getMaterialParam1f(
const char *name, float valIfNotFound)
{
const std::string mapName = "map_" + std::string(name);
MaterialParam1f param;
param.ref_tex = getParamObject<Texture>(mapName.c_str());
param.tex = getTextureParam(mapName.c_str(), param.ref_tex);
param.rot = ((linear2f *)(¶m.tex.xform2f.l))->orthogonal().transposed();
param.factor = getParam<float>(name, param.tex.ptr ? 1.f : valIfNotFound);
return param;
}
MaterialParam3f Material::getMaterialParam3f(
const char *name, vec3f valIfNotFound)
{
const std::string mapName = "map_" + std::string(name);
MaterialParam3f param;
param.ref_tex = getParamObject<Texture>(mapName.c_str());
param.tex = getTextureParam(mapName.c_str(), param.ref_tex);
param.rot = ((linear2f *)(¶m.tex.xform2f.l))->orthogonal().transposed();
param.factor =
getParam<vec3f>(name, param.tex.ptr ? vec3f(1.f) : valIfNotFound);
return param;
}
utility::Optional<affine2f> Material::getTextureTransform2f(
const char *_texname)
{
std::string texname(_texname);
texname += ".";
utility::Optional<affine2f> xform;
// Apply translation
const utility::Optional<vec2f> translation =
getOptParam<vec2f>((texname + "translation").c_str());
if (translation.has_value())
xform = affine2f::translate(-translation.value());
// Apply scale
const utility::Optional<vec2f> scale =
getOptParam<vec2f>((texname + "scale").c_str());
if (scale.has_value()) {
xform = xform.value_or(affine2f(one)) * affine2f::translate(vec2f(0.5f));
xform = *xform * affine2f::scale(rcp(scale.value()));
xform = *xform * affine2f::translate(vec2f(-0.5f));
}
// Apply rotation
const utility::Optional<float> rotation =
getOptParam<float>((texname + "rotation").c_str());
if (rotation.has_value()) {
xform = xform.value_or(affine2f(one)) * affine2f::translate(vec2f(0.5f));
xform = *xform * affine2f::rotate(-deg2rad(rotation.value()));
xform = *xform * affine2f::translate(vec2f(-0.5f));
}
// Apply complete transformation
const utility::Optional<linear2f> transf =
getOptParam<linear2f>((texname + "transform").c_str());
if (transf.has_value())
xform = xform.value_or(affine2f(one)) * affine2f(transf.value());
return xform;
}
OSPTYPEFOR_DEFINITION(Material *);
} // namespace ospray
|