diff --git a/CMakeLists.txt b/CMakeLists.txt index 36b94e0..802ef6d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -48,6 +48,9 @@ set(RAPIDJSON_INCLUDE_DIR ${RapidJSON_SOURCE_DIR}/rapidjson-1.1.0/include/rapidj ##################################################################################### # Adding DRACO if selected +if(POLICY CMP0148) + cmake_policy(SET CMP0148 OLD) +endif() option(USE_DRACO "Use Draco for compression" OFF) include(cmake/draco.cmake) if(USE_DRACO) diff --git a/README.md b/README.md index faa9c50..5ad8ccf 100644 --- a/README.md +++ b/README.md @@ -337,3 +337,29 @@ The Nvml is a tool that allows to see the status of the GPU. It is possible to s ### Tangent Space There is a tangent space tool that allows to fix or to recreate the tangent space of the model. This is useful when the normal map is not looking right or there are errors with the tangents in the scene. + +## Utilities + +### gltf-material-modifier.py + +Modify materials in a GLTF file and optionally reorient the scene from Z-up to Y-up. + +``` +usage: gltf-material-modifier.py [-h] [--metallic METALLIC] [--roughness ROUGHNESS] [--override] [--reorient] + input_file output_file +``` + +positional arguments: +``` + input_file Path to the input GLTF file. + output_file Path to save the modified GLTF file. +``` + +options: +``` + -h, --help show this help message and exit + --metallic METALLIC Set the metallic factor (default: 0.1). + --roughness ROUGHNESS Set the roughness factor (default: 0.1). + --override Override existing material values if set. + --reorient Reorient the scene from Z-up to Y-up. +``` \ No newline at end of file diff --git a/shaders/get_hit.h b/shaders/get_hit.h index 25e8d3b..0f04cd9 100644 --- a/shaders/get_hit.h +++ b/shaders/get_hit.h @@ -44,9 +44,10 @@ HitState getHitState(in RenderPrimitive renderPrim, // Buffer containing al // Normal hit.nrm = hit.geonrm; + vec3 N = Ng; if(hasVertexNormal(renderPrim)) { - vec3 N = getInterpolatedVertexNormal(renderPrim, triangleIndex, barycentrics); + N = getInterpolatedVertexNormal(renderPrim, triangleIndex, barycentrics); hit.nrm = normalize(vec3(N * worldToObject)); } @@ -69,7 +70,7 @@ HitState getHitState(in RenderPrimitive renderPrim, // Buffer containing al } else { - vec4 t = makeFastTangent(hit.nrm); + vec4 t = makeFastTangent(N); tng[0] = t; tng[1] = t; tng[2] = t; diff --git a/shaders/pathtrace.comp.glsl b/shaders/pathtrace.comp.glsl index d343f0b..2f751ff 100644 --- a/shaders/pathtrace.comp.glsl +++ b/shaders/pathtrace.comp.glsl @@ -39,7 +39,7 @@ HitPayload hitPayload; // Global hit payload layout(local_size_x = WORKGROUP_SIZE, local_size_y = WORKGROUP_SIZE) in; -#include "rt_payload.h" +#include "rt_layout.h" #include "nvvkhl/shaders/pbr_mat_eval.h" // Need texturesMap[] #include "nvvkhl/shaders/hdr_env_sampling.h" // nedd envSamplingData[] diff --git a/shaders/pathtrace.rahit.glsl b/shaders/pathtrace.rahit.glsl index 8a3cc42..3c863d5 100644 --- a/shaders/pathtrace.rahit.glsl +++ b/shaders/pathtrace.rahit.glsl @@ -33,7 +33,7 @@ #include "payload.h" layout(location = 0) rayPayloadInEXT HitPayload hitPayload; -#include "rt_payload.h" +#include "rt_layout.h" #include "nvvkhl/shaders/pbr_mat_eval.h" // Need texturesMap[] diff --git a/shaders/pathtrace.rgen.glsl b/shaders/pathtrace.rgen.glsl index 4f84bd4..915b13e 100644 --- a/shaders/pathtrace.rgen.glsl +++ b/shaders/pathtrace.rgen.glsl @@ -36,7 +36,7 @@ layout(location = 0) rayPayloadEXT HitPayload hitPayload; -#include "rt_payload.h" +#include "rt_layout.h" #include "nvvkhl/shaders/pbr_mat_eval.h" // Need texturesMap[] #include "nvvkhl/shaders/hdr_env_sampling.h" // nedd envSamplingData[] diff --git a/shaders/raster.frag.glsl b/shaders/raster.frag.glsl index d7fdc59..32c8262 100644 --- a/shaders/raster.frag.glsl +++ b/shaders/raster.frag.glsl @@ -233,7 +233,7 @@ void main() for(int i = 0; i < frameInfo.nbLights; i++) { Light light = frameInfo.light[i]; - LightContrib lightContrib = singleLightContribution(light, hit.pos, pbrMat.N, -worldRayDirection); + LightContrib lightContrib = singleLightContribution(light, hit.pos, pbrMat.N); BsdfEvaluateData evalData; evalData.k1 = -worldRayDirection; diff --git a/shaders/rt_common.h b/shaders/rt_common.h index 138289d..a884940 100644 --- a/shaders/rt_common.h +++ b/shaders/rt_common.h @@ -46,7 +46,7 @@ vec3 sampleLights(in vec3 pos, vec3 normal, in vec3 worldRayDirection, inout uin { int lightIndex = min(int(rand(seed) * sceneDesc.numLights), sceneDesc.numLights - 1); Light light = RenderLightBuf(sceneDesc.lightAddress)._[lightIndex]; - LightContrib contrib = singleLightContribution(light, pos, normal, worldRayDirection, vec2(rand(seed), rand(seed))); + LightContrib contrib = singleLightContribution(light, pos, normal, vec2(rand(seed), rand(seed))); lightDir = -contrib.incidentVector; lightPdf = (1.0 / sceneDesc.numLights) * lightWeight; lightRadiance = contrib.intensity / lightPdf; @@ -296,7 +296,7 @@ SampleResult pathTrace(Ray r, inout uint seed) else { // Continue path - bool isSpecular = (sampleData.event_type & BSDF_EVENT_SPECULAR) != 0; + bool isSpecular = (sampleData.event_type & BSDF_EVENT_IMPULSE) != 0; bool isTransmission = (sampleData.event_type & BSDF_EVENT_TRANSMISSION) != 0; vec3 offsetDir = dot(r.direction, hit.geonrm) > 0 ? hit.geonrm : -hit.geonrm; diff --git a/shaders/rt_payload.h b/shaders/rt_layout.h similarity index 100% rename from shaders/rt_payload.h rename to shaders/rt_layout.h diff --git a/utils/gltf-material-modifier.py b/utils/gltf-material-modifier.py new file mode 100644 index 0000000..203aaa4 --- /dev/null +++ b/utils/gltf-material-modifier.py @@ -0,0 +1,91 @@ +import json +import argparse +import math +import logging + +NINETY_DEG_X_ROTATION = [math.sqrt(0.5), 0, 0, math.sqrt(0.5)] + +def reorient_scene(gltf_data): + if not gltf_data.get('scenes') or not gltf_data['scenes'][0].get('nodes'): + logging.warning("No valid scene or nodes found in the glTF file.") + return gltf_data + + scene = gltf_data['scenes'][0] + + if len(scene['nodes']) == 1: + root_node = gltf_data['nodes'][scene['nodes'][0]] + if 'rotation' in root_node: + logging.info("Applying rotation to existing root node.") + root_node['rotation'] = multiply_quaternions(root_node['rotation'], NINETY_DEG_X_ROTATION) + else: + root_node['rotation'] = NINETY_DEG_X_ROTATION + else: + logging.info("Creating new root node for reorientation.") + new_root = { + "name": "ReorientedRoot", + "rotation": NINETY_DEG_X_ROTATION, + "children": scene['nodes'] + } + scene['nodes'] = [len(gltf_data['nodes'])] + gltf_data['nodes'].append(new_root) + + return gltf_data + +def multiply_quaternions(q1, q2): + return [ + q1[0]*q2[0] - q1[1]*q2[1] - q1[2]*q2[2] - q1[3]*q2[3], + q1[0]*q2[1] + q1[1]*q2[0] + q1[2]*q2[3] - q1[3]*q2[2], + q1[0]*q2[2] - q1[1]*q2[3] + q1[2]*q2[0] + q1[3]*q2[1], + q1[0]*q2[3] + q1[1]*q2[2] - q1[2]*q2[1] + q1[3]*q2[0] + ] + +def modify_gltf(input_file, output_file, metallic_factor, roughness_factor, override, reorient): + logging.info(f"Reading input file: {input_file}") + try: + with open(input_file, 'r') as f: + gltf_data = json.load(f) + except IOError as e: + logging.error(f"Error reading input file: {e}") + return + + if reorient: + logging.info("Reorienting scene...") + gltf_data = reorient_scene(gltf_data) + + if 'materials' in gltf_data: + logging.info("Modifying materials...") + for material in gltf_data['materials']: + pbr = material.setdefault('pbrMetallicRoughness', {}) + if 'metallicFactor' not in pbr or override: + pbr['metallicFactor'] = max(0, min(1, metallic_factor)) + if 'roughnessFactor' not in pbr or override: + pbr['roughnessFactor'] = max(0, min(1, roughness_factor)) + else: + logging.warning("No materials found in the glTF file.") + + logging.info(f"Writing output file: {output_file}") + try: + with open(output_file, 'w') as f: + json.dump(gltf_data, f, indent=2) + logging.info("Modification complete.") + except IOError as e: + logging.error(f"Error writing output file: {e}") + +def main(): + parser = argparse.ArgumentParser(description="Modify materials in a GLTF file and optionally reorient the scene.") + parser.add_argument("input_file", help="Path to the input GLTF file") + parser.add_argument("output_file", help="Path to save the modified GLTF file") + parser.add_argument("--metallic", type=float, default=0.1, help="Set the metallic factor (default: 0.1)") + parser.add_argument("--roughness", type=float, default=0.1, help="Set the roughness factor (default: 0.1)") + parser.add_argument("--override", action="store_true", help="Override existing material values if set") + parser.add_argument("--reorient", action="store_true", help="Reorient the scene from Z-up to Y-up") + parser.add_argument("--log", choices=['DEBUG', 'INFO', 'WARNING', 'ERROR'], default='INFO', help="Set the logging level") + + args = parser.parse_args() + + logging.basicConfig(level=getattr(logging, args.log), format='%(levelname)s: %(message)s') + + modify_gltf(args.input_file, args.output_file, args.metallic, args.roughness, args.override, args.reorient) + +if __name__ == "__main__": + main() \ No newline at end of file