Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions devices/rtx/device/gpu/gpu_objects.h
Original file line number Diff line number Diff line change
Expand Up @@ -612,9 +612,8 @@ struct InstanceVolumeGPUData

struct InstanceLightGPUData
{
const DeviceObjectIndex *indices;
size_t numLights;
mat4 xfm;
DeviceObjectIndex lightIndex; // Index into registry.lights[]
mat4 xfm; // Transform for this light instance
};

// World //
Expand All @@ -632,7 +631,8 @@ struct WorldGPUData
const InstanceLightGPUData *lightInstances;
size_t numLightInstances;

DeviceObjectIndex hdri;
const InstanceLightGPUData *hdriLightInstances;
size_t numHdriLightInstances;
};

// Renderer //
Expand Down
28 changes: 22 additions & 6 deletions devices/rtx/device/gpu/gpu_util.h
Original file line number Diff line number Diff line change
Expand Up @@ -304,12 +304,28 @@ VISRTX_DEVICE vec4 getBackgroundImage(
VISRTX_DEVICE vec4 getBackground(
const FrameGPUData &fd, const vec2 &loc, const vec3 &rayDir)
{
const LightGPUData *hdri =
fd.world.hdri != -1 ? &fd.registry.lights[fd.world.hdri] : nullptr;
if (hdri && hdri->hdri.visible)
return vec4(sampleHDRI(*hdri, rayDir), 1.f);
else
return getBackgroundImage(fd.renderer, loc);
// Accumulate contributions from all visible HDRI lights
vec3 hdriContribution = vec3(0.f);
bool hasVisibleHDRI = false;

for (size_t i = 0; i < fd.world.numHdriLightInstances; i++) {
const auto &hdriLight = fd.world.hdriLightInstances[i];
const auto &light = fd.registry.lights[hdriLight.lightIndex];
if (light.hdri.visible) {
// Transform ray direction from world space to HDRI local space
// For orthonormal matrices, inverse = transpose
const mat3 xfmInv = glm::transpose(mat3(hdriLight.xfm));
const vec3 localRayDir = xfmInv * rayDir;
hdriContribution += sampleHDRI(light, localRayDir);
hasVisibleHDRI = true;
}
}

if (hasVisibleHDRI)
return vec4(hdriContribution, 1.f);

// No visible HDRI, use background image/color
return getBackgroundImage(fd.renderer, loc);
}

VISRTX_DEVICE uint32_t computeGeometryPrimId(const SurfaceHit &hit)
Expand Down
1 change: 1 addition & 0 deletions devices/rtx/device/gpu/renderer/raygen_helpers.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
#include "gpu/intersectRay.h"
#include "gpu/renderer/common.h"
#include "gpu/shadingState.h"
#include "gpu/volumeIntegration.h"

// Shared helper functions for ray generation across renderers

Expand Down
3 changes: 2 additions & 1 deletion devices/rtx/device/material/shaders/MDLShader_ptx.cu
Original file line number Diff line number Diff line change
Expand Up @@ -273,7 +273,8 @@ vec3 __direct_callable__evaluateTransmission(
const MDLShadingState *shadingState)
{
return mdlTransmission(
&shadingState->state, &shadingState->resData, shadingState->argBlock);
&shadingState->state, &shadingState->resData, shadingState->argBlock)
* 0.85f;
}

VISRTX_CALLABLE
Expand Down
153 changes: 75 additions & 78 deletions devices/rtx/device/renderer/DirectLight_ptx.cu
Original file line number Diff line number Diff line change
Expand Up @@ -39,11 +39,11 @@
#include "gpu/gpu_math.h"
#include "gpu/gpu_objects.h"
#include "gpu/intersectRay.h"
#include "gpu/renderer/common.h"
#include "gpu/renderer/raygen_helpers.h"
#include "gpu/sampleLight.h"
#include "gpu/shadingState.h"
#include "gpu/shading_api.h"
#include "gpu/renderer/common.h"
#include "gpu/renderer/raygen_helpers.h"

namespace visrtx {

Expand All @@ -53,43 +53,41 @@ DECLARE_FRAME_DATA(frameData)

struct DirectLightShadingPolicy
{
static VISRTX_DEVICE vec4 shadeSurface(const MaterialShadingState &shadingState,
ScreenSample &ss,
const Ray &ray,
const SurfaceHit &hit)
{
const auto &rendererParams = frameData.renderer;
const auto &directLightParams = rendererParams.params.directLight;

auto &world = frameData.world;

// Compute ambient light contribution //
const float aoFactor = directLightParams.aoSamples > 0
? computeAO(ss,
ray,
hit,
rendererParams.occlusionDistance,
directLightParams.aoSamples,
&surfaceAttenuation)
: 1.f;

vec3 contrib = materialEvaluateEmission(shadingState, -ray.dir);

// Handle ambient light contribution
if (rendererParams.ambientIntensity > 0.0f) {
contrib += rendererParams.ambientColor * rendererParams.ambientIntensity
* materialEvaluateTint(shadingState);
}

// Handle all lights contributions
for (size_t i = 0; i < world.numLightInstances; i++) {
auto *inst = world.lightInstances + i;
if (!inst)
continue;
static VISRTX_DEVICE vec4 shadeSurface(
const MaterialShadingState &shadingState,
ScreenSample &ss,
const Ray &ray,
const SurfaceHit &hit)
{
const auto &rendererParams = frameData.renderer;
const auto &directLightParams = rendererParams.params.directLight;

auto &world = frameData.world;

// Compute ambient light contribution //
const float aoFactor = directLightParams.aoSamples > 0
? computeAO(ss,
ray,
hit,
rendererParams.occlusionDistance,
directLightParams.aoSamples,
&surfaceAttenuation)
: 1.f;

vec3 contrib = materialEvaluateEmission(shadingState, -ray.dir);

// Handle ambient light contribution
if (rendererParams.ambientIntensity > 0.0f) {
contrib += rendererParams.ambientColor * rendererParams.ambientIntensity
* materialEvaluateTint(shadingState);
}

for (size_t l = 0; l < inst->numLights; l++) {
// Handle all lights contributions
for (size_t i = 0; i < world.numLightInstances; i++) {
const auto &light = world.lightInstances[i];
const auto lightSample =
sampleLight(ss, hit, inst->indices[l], inst->xfm);
sampleLight(ss, hit, light.lightIndex, light.xfm);

if (lightSample.pdf == 0.0f)
continue;

Expand All @@ -114,50 +112,49 @@ struct DirectLightShadingPolicy

contrib += thisLightContrib * attenuation;
}
}

// Take AO in account
contrib *= aoFactor;

// Then proceed with single bounce ray for indirect lighting
SurfaceHit bounceHit = hit;
NextRay nextRay = materialNextRay(shadingState, ray, ss.rs);
if (glm::any(glm::greaterThan(
nextRay.contributionWeight, glm::vec3(MIN_CONTRIBUTION_EPSILON)))) {
Ray bounceRay = {
bounceHit.hitpoint
+ bounceHit.Ng
* std::copysignf(
bounceHit.epsilon, dot(bounceHit.Ns, nextRay.direction)),
nextRay.direction,
};

// Only check for intersecting surfaces and background as secondary light
// interactions
bounceHit.foundHit = false;
intersectSurface(ss, bounceRay, RayType::PRIMARY, &bounceHit);

if (bounceHit.foundHit) {
// We hit something. Gather its contribution, cosine weighted diffuse
// only, we want this to be lightweight.
MaterialShadingState bounceShadingState;
materialInitShading(
&bounceShadingState, frameData, *bounceHit.material, bounceHit);

auto sampleDir = randomDir(ss.rs, bounceHit.Ns);
auto cosineT = dot(bounceHit.Ns, sampleDir);
auto color = materialEvaluateTint(bounceShadingState) * cosineT;
contrib += color * nextRay.contributionWeight;
} else {
// No hit, get background contribution directly (no surface to weight
// against)
const auto color = getBackground(frameData, ss.screen, bounceRay.dir);
contrib += vec3(color) * nextRay.contributionWeight;
// Take AO in account
contrib *= aoFactor;

// Then proceed with single bounce ray for indirect lighting
SurfaceHit bounceHit = hit;
NextRay nextRay = materialNextRay(shadingState, ray, ss.rs);
if (glm::any(glm::greaterThan(
nextRay.contributionWeight, glm::vec3(MIN_CONTRIBUTION_EPSILON)))) {
Ray bounceRay = {
bounceHit.hitpoint
+ bounceHit.Ng
* std::copysignf(
bounceHit.epsilon, dot(bounceHit.Ns, nextRay.direction)),
normalize(nextRay.direction),
};

// Only check for intersecting surfaces and background as secondary light
// interactions
bounceHit.foundHit = false;
intersectSurface(ss, bounceRay, RayType::PRIMARY, &bounceHit);

if (bounceHit.foundHit) {
// We hit something. Gather its contribution, cosine weighted diffuse
// only, we want this to be lightweight.
MaterialShadingState bounceShadingState;
materialInitShading(
&bounceShadingState, frameData, *bounceHit.material, bounceHit);

auto sampleDir = randomDir(ss.rs, bounceHit.Ns);
auto cosineT = dot(bounceHit.Ns, sampleDir);
auto color = materialEvaluateTint(bounceShadingState) * cosineT;
contrib += color * nextRay.contributionWeight;
} else {
// No hit, get background contribution directly (no surface to weight
// against)
const auto color = getBackground(frameData, ss.screen, bounceRay.dir);
contrib += vec3(color) * nextRay.contributionWeight;
}
}
}

float opacity = evaluateOpacity(shadingState);
return vec4(contrib, opacity);
float opacity = evaluateOpacity(shadingState);
return vec4(contrib, opacity);
}
};

Expand Down
Loading