Skip to content

Releases: jac18281828/gman

GMAN 1.0.0

Choose a tag to compare

@github-actions github-actions released this 29 Sep 18:15
1.0.0
c4b982f
  • gman path-traces: gman -r gmanpathtracer scene.rib. A unidirectional path tracer with next-event estimation renders every primitive the ray tracer does, samples each surface's BSDF, and ends a path by Russian roulette from its third vertex. Option "pathtracer" "integer samples" [n] sets the paths per pixel. It renders on one thread. An ambientlight lights nothing under it and is skipped with one warning; a point, distant or spot light casts a shadow ray from every vertex. A camera path through a surface with Opacity below 1 passes through it as the ray tracer does, and a path that reaches the pass-through cap stays opaque
  • Area lights. AreaLightSource "arealight" turns the Sphere or Disk that follows it into an emitter of intensity × lightcolor, one-sided on its outward face. The path tracer samples an emitter uniformly by area, aims each shadow ray at a point offset off the emitter's surface so an opaque lamp shadows correctly at any scene scale, and places the sampling density and power through the emitter's own transform, so Scale on a lamp is exact. Next-event estimation picks a light in proportion to its power over distance squared. The z-buffer and the ray tracer render area-light geometry as ordinary surfaces and warn once
  • Multiple importance sampling. Next-event estimation and BSDF-sampled bounces that reach the same area light are weighted by the power heuristic at every vertex, so a sharp glossy lobe under a large light converges without fireflies. A point on an emitter's own surface never chooses that emitter for its shadow ray, since a lamp cannot light itself. An area light seen through glass counts once, carried by the shadow ray through the dielectric's thin transmittance; a glass lens focusing a lamp onto a floor waits for caustics
  • The ray tracer adds bounce light through a radiosity pass: Option "render" "string indirect" ["radiosity"]. Under -r gmanraytracer, the pass dices the scene into patches, solves the diffuse light bouncing between them by progressive refinement, through translucent surfaces attenuated by 1 - Os, and hands each shaded point its indirect irradiance; ambient() adds it to the ambient lights, so each surface weights it by its own Ka, colour bleeding included. Reflected and refracted hits get it too. Option "radiosity" "float elementsize" sets the patch size, defaulting to an eighth of the scene's largest side; a size finer than the mesh's division cap allows warns once, prefixed Radiosity:, and dices at the finest resolution available. The plugin builds by default and installs as libradiosity.so, so the release downloads carry it. Without the Option, no image changes
  • Every built-in shader returns a BSDF. GMANSurfaceShader::bsdf returns the gman::BSDF closure the path tracer samples: Lambert of Cs by default; a GGX microfacet lobe beside the diffuse one for plastic, paintedplastic, metal and shinymetal; exact-Fresnel delta lobes for mirror and glass, whose shadow rays pass through glass by its thin transmittance. albedo() reports each shader's diffuse reflectance
  • 1.0 breaks the plugin ABI; every shader and renderer plugin rebuilds. GMANLoadShader takes GMANParameterList const& and constructs one shader instance per Surface call, and GMANDestroyShader(GMANShader*) is a required entry point, both declared extern "C" GMAN_EXPORT in gmanshader.h; computeCi/computeOi are const and return colour by value; GMANSurfaceEnv gains the texture cache it shades through, one per worker. bsdf and albedo are new virtuals on GMANSurfaceShader. An out-of-tree shader drops any mutable state and function-local statics, and may override bsdf; one that overrides bsdf must not call the base albedo, since the two would recurse. GMANShader::set(GMANParameterList&), set(GMANRenderer&) and the protected pl and renderer members are gone; GMANLoadableShader's constructor takes (char const*, GMANParameterList const&) and its copy and move are deleted. GMANAttributes::setSurface, setDisplacement, setAtmosphere, setInterior, setExterior and GMANOptions::setImager lose their GMANRenderer& parameter; GMANAttributes::getSurface returns std::shared_ptr<GMANSurfaceShader const> and getSurfaceParameters is gone; GMANOptions::imagerModule becomes a std::shared_ptr<GMANLoadableShader>, moving every GMANOptions member after it. GMANSurfaceEnv gains a trailing indirect member (GMANColor const*, null by default), which ambient(), inline in the installed header, adds; gman::shade gains two trailing parameters, TextureCache* then GMANColor const* indirect, changing its mangled name. gmantexture.h installs as <gman/gmantexture.h> with gman::TextureCache exported, so an out-of-tree renderer can build its own cache. GMANObjectManager's four polygon virtuals give way to one pure virtual, getRSPolygonMesh, over the exported GMANPolygonMesh; an object manager outside this tree implements it. GMANQuantize becomes a four-field aggregate (one, min, max, ditheramplitude). New exports: gman::IndirectPass and gman::loadIndirectPass (gmanindirectpass.h), gman::hitSurfacePoint and gman::albedo (gmanshading.h), gman::resolveLoadableShader, and GMAN_EXPORT on GMANParametric; a pass module exports GMANGetLoadableInfo, GMANCreateIndirectPass and GMANDestroyIndirectPass as extern "C". GMANPoint::operator*(GMANMatrix4 const&) and GMANVector::operator*(GMANMatrix4 const&), column-vector products this tree never used, are gone; gman::transformPoint and gman::transformDirection are the row-vector forms. gmanslapi.h stops declaring distance, ptlined and rotate, which were never defined
  • gman stops a file at any error reported at RIE_ERROR or above; 0.9.1 rendered on and exited 0. gman installs its own RtErrorHandler: it prints each report exactly as RiErrorPrint does, then at RIE_ERROR or above throws a stop that ends the file, so no image is written, the exit status is 1, and the run moves on to the next file on the command line. A scene that names a token neither declared nor built in, such as Surface "plastic" "Kdd" [0.2], printed ERROR: RIE_BADTOKEN -- GMANDictionary: TOKEN_NOT_FOUND, dropped that parameter, rendered and exited 0; it prints the same line now and exits 1 with no image. A stop before WorldBegin leaves the next file free to render; a stop inside a WorldBegin block leaves every later file failing with WARNING: RIE_ILLSTATE -- Invalid mode for procedure and writing nothing. An error the parser throws rather than reports keeps its behaviour, exit 1 at every severity with the same line. The library's own default handler is still RiErrorPrint, so an embedder that installs none sees no change, and RiErrorHandler installs a different policy
  • gman -r gmanradiosity no longer renders. The 0.9.1 radiosity renderer, which built OFF and rendered nothing, is gone; libgmanradiosity.so becomes libradiosity.so, loaded as a pass by name. A pass that fails to load logs one warning beginning Indirect-light pass "radiosity":, and the frame renders without indirect light
  • A Surface that will not load reports RIE_NOSHADER at RIE_ERROR and names the request. 0.9.1 reported a missing module at RIE_SEVERE, SEVERE: RIE_SYSTEM -- Unable to open shared object specified by: libnosuchshader.so: ..., and a module with no GMANLoadShader or a shader of the wrong type the same way. The report reads ERROR: RIE_NOSHADER -- Surface "nosuchshader" failed to load; the default surface shades instead: followed by the loader's own message, and the request binds the default surface with none of the failed request's parameters. Under gman the report is a stop like any other RIE_ERROR, so the exit is still 1 with no image; the default surface shades for an embedder whose handler returns, RiErrorPrint or RiErrorIgnore. Through the C API, a RiSurface after a missing module used to keep the previously bound surface and binds the default now
  • RiDisplacement, RiAtmosphere, RiInterior, RiExterior and RiImager resolve a module name as Surface does. Each passed its token to dlopen as given, so RiDisplacement("matte", ...) looked for a file named matte; a token maps to lib<name>.so now. A caller that spelled the exact file, "libmatte.so", looks for liblibmatte.so.so now and fails. A failed load or a wrong type reports RIE_NOSHADER at RIE_ERROR in place of RIE_SEVERE, names the request and what renders instead (the surface renders undisplaced, no atmosphere shades the volume, the volume shades without an interior, the volume shades without an exterior, the frame renders without an imager), and resets the kind's module and typed pointer to null; a wrong-type module used to stay assigned. GMANOptions owns its imager module through a shared_ptr, so the copy of the options RiFrameBegin pushes no longer frees the outer options' imager when the frame loads its own. The RIB parser reads Atmosphere, Displacement and Imager and ignores them, and has no Interior or Exterior request, so only the C API reaches this
  • Output honours Quantize. RIB's Quantize request reaches the renderer: every driver rounds and dithers each channel by RISpec's rule into the request's [min, max], scaled by one, and clamps it there; the dither is a pure function of the pixel, so a render reproduces. A TIFF Display writes 16 bits a sample once max exceeds 255; PNG, JPEG and PNM stay 8-bit, and a request they cannot honour falls back to the default range with one warning. The nine sample PNGs and ten goldens were regenerated for rounded, dithered output. A plugin output driver's writeImage now receives packed samples and their bit depth in place of float colours, and GMANColorRGB is gone
  • **The framebuffer holds unclamp...
Read more

GMAN 0.9.1

Choose a tag to compare

@github-actions github-actions released this 25 Sep 03:17
0.9.1
0504662
  • The ray tracer draws GeneralPolygon, PointsPolygons and PointsGeneralPolygons, holes included. All three built nothing under -r gmanraytracer in 0.9.0. A GeneralPolygon's first loop is its outline and the rest are holes, each hole tested on its own ring by the even-odd rule, with no triangulation. A points mesh adds one primitive per request and one GMANRayPolygon per face; the BVH flattens it face by face, so a large mesh culls per face and a hit reports the face. A face under three vertices or otherwise degenerate is skipped. Every ray-traced polygon resolves s/t through one rule, gman::resolvePointTexCoords: the object-space default, then "st", then "s" and "t"
  • The z-buffer dices a polygon by its size on screen. 0.9.0 diced every ear-clipped triangle of a Polygon, GeneralPolygon, PointsPolygons or PointsGeneralPolygons into a fixed 16-per-edge grid. Each triangle now dices into n = clamp(ceil(L / sqrt(ShadingRate)), 1, 16) per edge, L its longest raster-space edge; a non-positive ShadingRate, a non-finite edge or a corner behind the eye falls back to 16. No scene dices finer than before. On 10,000 small quads at 1600×900, a render drops from 3.53 s and 904 MB peak to 0.61 s and 288 MB
  • A redeclared fov takes effect. After Declare "fov" "float", Projection "perspective" "fov" [30] rendered at 90° and warned "FOV not set", because RiWorldBegin looked the token up in a dictionary other than the one that declared it. It resolves through the renderer's own dictionary now
  • Ray geometry, the BVH and the shadow walk move into libgman, and a plugin can use them. GMANRayInterface, the eight ray primitives, GMANRayObjectManager, GMANRayBVH and GMANRayOccluder compiled only into the ray tracer plugin; they now live in gman_core, built whether or not GMAN_BUILD_RAYTRACER is on, and their headers install: gmanrayinterface.h, gmanraybbox.h, gmanraybvh.h, gmanrayobjectmanager.h, gmanrayoccluder.h, gmanraypolygon.h, gmanraypolygonmesh.h and one header per quadric. GMANRayBVH, GMANRayPolygonMesh and the occluder's helpers carry GMAN_EXPORT. The quadrics gain getObjectToCamera(), GMANRayPolygon gains getOuterLoop(), getHoles(), getPlaneNormal() and isDegenerate(), and GMANRayPolygonMesh gains getFaceCount() and getFace(). Each class states a const, re-entrant contract for concurrent callers. No rendered image changes
  • Radiosity groundwork. GMANRadiosityMesh dices every ray primitive into a camera-space element mesh, holes and mesh faces included, and GMANRadiositySolver solves diffuse interreflection over it by progressive refinement. Both live in renderers/radiosity/, which still builds OFF and renders nothing
  • The README is a front door. It opens on a ray-traced render of samples/vase.rib, gives a four-line download-and-render for Linux, and shows six one-line edits to the scene beside their renders. The sample itself gains a robot on six wheels, water in the tipping vase and a lamp over the table

GMAN 0.9.0

Choose a tag to compare

@github-actions github-actions released this 24 Sep 10:40
0.9.0
1270962
  • 0.9.0 breaks the plugin ABI again. GMANMatrix4::p3m/p4m are now const, changing both symbols' mangled names. gman::shade takes a trailing gman::Tracer const* defaulting to nullptr — a source caller that omits it still compiles, but the new mangled name means a plugin built against 0.8.x must rebuild before it links against this libgman. gman::Occluder::transmission and the new gman::Tracer::trace take a trailing RtFloat surfaceMagnitude with no default, since a default argument on a virtual binds by static type rather than the override actually called: a plugin implementing either must add the parameter. A shader author rebuilds too: GMANSurfaceEnv::diffuse() and specular(), inline in the installed include/gmanshaderenvironment.h, reach occludedContribution, which now passes surfaceMagnitude to transmission — a shader built against 0.8.3 calls it with one argument fewer. GMANSurfaceEnv gains tracer and surfaceMagnitude members and the trace() call that reaches them, and gman::SurfacePoint gains its own surfaceMagnitude, which gman::shade forwards to the renderer's own Occluder and Tracer; left at 0 it reports no surface. gman::Appearance and GMANAttributes gain a stored shader parameter list, and GMANSampleBuffer and GMANOutputPolygon/GMANOutVertex gain a per-sample or per-pixel GMANAlpha alongside colour (GMANSampleBuffer::zTestAndSet takes a trailing alpha argument too, and GMANOutVertex's is per vertex), so a plugin touching either layout rebuilds. GMANBitmap gains getAlpha and setAlpha, two new virtuals that shift the vtable slot of every virtual declared after them, so a plugin overriding one of those later virtuals rebuilds too. Separately, GMANAttributes, GMANWorldManager, GMANTorus and the light source, volume, displacement and imager shader bases now carry GMAN_EXPORT: a release build had hidden each one's constructor, destructor and typeinfo, so a plugin subclassing or copying one failed to link before and links now, with no plugin-side change needed. GMANPoint carries it too, for the out-of-line comparison operators it already had at 0.8.3; GMANBBox, for its out-of-line constructors and operator=; and GMANColorSamples, for its copy constructor, destructor and operator= — all hidden the same way
  • An existing scene renders differently under either renderer. The default background is black now, per the RenderMan spec, not opaque white: an uncovered pixel used to composite into white. A TIFF Display naming "rgba" writes real per-pixel coverage alpha, premultiplied into RGB, and tags it EXTRASAMPLE_ASSOCALPHA; one naming "rgb" writes 3 TIFF samples instead of 4 regardless, matching what its own DisplayMode asks for; libgman/gmanoutputpng.cpp still writes 255. A world block with no Display, or one explicitly naming "framebuffer", now raises RIE_ILLSTATE, "No display output to render into.", at RiWorldEnd instead of silently rendering into a 0x0 framebuffer stub. A surface named more than once in a scene — restored by AttributeEnd, or falling back to the default surface on a primitive with no Surface call after a parameterized "matte" — now shades with its own RiSurface parameters instead of the last call's, a bug both renderers carried since GMANLoadShader returns one static instance per plugin; under the ray tracer alone, the same bug showed on any two surfaces naming the same shader, since it shades every primitive only after every Surface call has run. A Polygon, GeneralPolygon, PointsPolygons or PointsGeneralPolygons under the z-buffer now dices into a fine facet grid before shading instead of Gouraud-blending a handful of once-shaded corners, textured or not: a textured one reads its texture correctly across the whole surface, and an untextured one under a point or spot light now resolves its highlight across the face instead of rendering one blend of corner shades. Measured on 10,000 quads under the z-buffer, dicing costs 0.08 s and 36 MB at 0.8.3 against 2.49 s and 741 MB now, about 31× the time and 21× the memory
  • gman no longer crashes running one file after another when the second has no WorldBegin, or when RiEnd follows a failed RiBegin. RiEnd left viewingSystem and the renderer's own pointers dangling instead of null, so a file that rendered followed by one with no WorldBegin freed the same pointer twice, and RiEnd after a failed RiBegin deleted an uninitialized renderer; every pointer RiEnd releases is null again once it returns
  • The ray tracer draws Torus now, and a same-z Hyperboloid it used to skip. A full or partial torus intersects and shades under -r gmanraytracer; a spindle or horn torus (minorradius >= majorradius) still draws nothing, pinned WILL_FAIL by torusspindle. Patch, PatchMesh, NuPatch, GeneralPolygon, PointsPolygons, PointsGeneralPolygons, Blobby, Points, Curves and SubdivisionMesh still build nothing. A Hyperboloid whose two points share a z, drawing nothing since 0.8.3, now intersects the flat annulus it sweeps. A textured ray-traced Polygon also interpolates its own s/t across each hit now, instead of reading (0, 0) everywhere and rendering one flat texel per polygon
  • The ray tracer scales past a linear scan of every primitive. Each primitive now carries a padded, camera-space bound (GMANBBox gains getMin()/getMax() and a two-point constructor), and the renderer builds an object-median bounding volume hierarchy over them each frame instead of testing every primitive's intersect() in turn; traversal visits the nearer child first and prunes a subtree whose interval clears neither the ray nor the best hit found so far. No rendered image changes
  • mirror and glass join the shader plugins, both using a new trace() shading call for real reflection and refraction. GMANSurfaceEnv::trace(R) casts a ray from the shading point and shades whatever it hits, recursing up to 4 levels deep before returning the renderer's own background; it shades only under -r gmanraytracer, since only the ray tracer binds a Tracer — under the default z-buffer it returns black, so both shaders render black there. mirror scales Kr by what it finds along the reflected direction, and glass weights the reflected and refracted directions by the Fresnel reflectance and transmittance at a fixed index of refraction, 1.5. A shader calling trace() must read every parameter before its first call and write Ci only after its last, since the call recurses back into shading the same loaded plugin instance
  • fresnel() returns physical reflectance and transmittance now. GMANSurfaceEnv::fresnel (the exported GMANFresnel) used the wrong tangent identity and the wrong sign for the incidence cosine, so it returned kr NaN at normal incidence and kr 127.6 with kt −126.6 at 45° for eta 1/1.5, dividing by zero at grazing incidence and taking the square root of a negative number at total internal reflection. Both overloads now clamp the incidence cosine and fix the identity and its sign: normal incidence returns 0.04, and 45° at eta 1/1.5 returns 0.050 with 0.950. An out-of-tree shader calling fresnel() renders differently
  • A ray-traced quadric or torus stays on its own surface far from the camera. The sphere, cone, cylinder, paraboloid and hyperboloid now solve their intersection in double from a shifted, near-the-surface origin instead of losing the discriminant to cancellation at distance; the disk and the flat-annulus Hyperboloid have no discriminant to cancel and solve in double from the unshifted origin instead. Every hit now lands within 1e-5 of its implicit surface at any distance tested

GMAN 0.8.3

Choose a tag to compare

@github-actions github-actions released this 22 Sep 18:37
0.8.3
00be6db
  • The ray tracer renders, builds by default and installs: gman -r gmanraytracer scene.rib. It traces Sphere, Disk, Polygon, Cylinder, Cone, Paraboloid and Hyperboloid; every other primitive, Torus and GeneralPolygon among them, still builds nothing under it, and a Hyperboloid whose two points share a z draws nothing, pinned WILL_FAIL. Each non-ambient light casts a shadow ray, an Opacity below 1 composites up to 16 layers front to back, and a shadow through a semi-transparent blocker attenuates by 1 - Os at every surface it crosses. -r <name> chooses any renderer plugin, glued -rNAME included; without it gman renders through the z-buffer as before. GMANViewingSystem::cameraRay now scales its ray by the field of view, which it ignored at any fov but 90; the z-buffer never called it, so no z-buffer render changes
  • libgman grows the public API a renderer plugin shades through. gmanshading.h installs gman::Appearance, gman::SurfacePoint, gman::Shading and gman::shade, the shading entry point both renderers now call; gmanocclude.h installs gman::Occluder, which a renderer passes to gman::shade to shadow each light. gmanpolygon.h installs gman::newellNormal and gman::isDegeneratePolygon, gmanmatrix4.h gains gman::transformPoint, transformDirection and transformNormal, and gmansamplebuffer.h gains gman::sampleCentre. GMANNormal, GMANDisk, GMANCone, GMANCylinder, GMANParaboloid and GMANHyperboloid gain GMAN_EXPORT, so a plugin can link against them in a release build. GMANSurfaceEnv gains a trailing occluder member; a shader built against 0.8.2's header ignores it until rebuilt
  • A parameter declared integer reaches its request as an RtInt, not as a float's bits. The RIB parser stored every numeric parameter as RtFloat and GMANParameterList read an integer one back through an RtInt* cast, so [4] arrived as 1082130432. A float literal in a declared-integer slot is now RIE_SYNTAX; an undeclared token reads as a float, as before
  • A RIB string decodes its escapes, so an escaped quote no longer closes it. \n, \r, \t, \b, \f, \\, \", an octal escape and a backslash-newline decode; an unknown escape yields the character after the backslash. Before, the first quote after a backslash ended the string, and one inside an array desynced the rest of the file
  • A RIB integer that does not fit RtInt raises RIE_RANGE instead of wrapping. The tokenizer bounds every integer literal where it reads it, so an out-of-range integer is an error even where a float is wanted: Kd [4294967297] now fails, and 4294967297.0 means the float. A Declare array size past RtInt's range raises RIE_RANGE where it used to abort on std::bad_alloc once a request used the token. An inline declaration with a bracket after its seventh word raises RIE_SYNTAX where it used to write past the parser's word array and return silently
  • A short array on Polygon or a quadric clamps with a warning instead of reading past its allocation. Those eight requests passed no lengths to their parameter lists, so Sphere 1 -1 1 360 "N" [0 0 1] overran a 12-float varying normal. They now take the lengths the RIB supplies, as GeneralPolygon and five others already did, zero-fill the shortfall and name the parameter and both lengths
  • Two installed declarations change. gmancolor.h's twelve GMANConvert* colour-space conversions are gone; none carried GMAN_EXPORT, so no release build could link them. GMANToken stores its integer as RtInt and renames getLongInt() to getInt(). An unknown token type now reports SEVERE: RIE_BUG -- Unknown token type rather than RIE_NOMEM, whose code its transposed arguments had borrowed

GMAN 0.8.2

Choose a tag to compare

@github-actions github-actions released this 19 Sep 11:15
0.8.2
c8fe977
  • 0.8.2 breaks the installed ABI, which CMakeLists.txt's own policy reserves for a minor release. A plugin calling a symbol GMAN_EXPORT no longer tags moves to the tagged surface, or gman itself needs a local patch and rebuild to re-export it. A release build now hides everything the tag omits: measured with nm -gU on the release preset, libgman_core exported 1604 symbols in 0.8.1 and 793 now, 29 classes tagged alongside ri.h and the shading-language, error and logging headers a shader calls. Hiding follows BUILD_TESTING, so a plain cmake -B build configure still exports everything; any configure with BUILD_TESTING off is trimmed, the release preset and its tarballs among them
  • gman installs as a real CMake package for the first time. 0.8.1's install(TARGETS) named no export set and skipped gman_shinymetal outright, so an installed gman could not load libshinymetal.so, and no gmanConfig.cmake let a programmer find_package(gman). gman_core now installs through an EXPORT gmanTargets set with a generated gmanConfig.cmake and a SameMinorVersion gmanConfigVersion.cmake: a consumer writes find_package(gman CONFIG REQUIRED) and links gman::gman_core. SameMinorVersion treats every 0.8.x release as compatible; this one is not, since it trims the exported ABI
  • 16 headers move out of include/ and stop installing, gmanparallel.h among them — the header 0.8.0 named as the one threading seam. No installed header includes any of the 16, so only a consumer that included one directly must change. The tree's own shaders adopt namespace gmanshader too, as gmanshader::plastic and its siblings, the convention a new shader plugin now follows. Three diagnostics lose a stale class-name prefix: RiErrorHandler reports No active context rather than GMANContext: No active context, invalid Context Handle loses the same GMANContext: prefix, and an inline-declared parameter's syntax errors drop their GMANInlineParse: prefix
  • RiBegin on a name ending .rib now writes RIB, instead of trying and failing to load it as a renderer. RiBegin(name) always built a GMANRenderManImpl and tried to dlopen lib<name>.so, so RiBegin("scene.rib") looked for libscene.rib.so, and no scene ever reached GMANASCII, the class that writes RIB. A name ending .rib now loads libgmanrib.so instead, a plugin dlopened the way a renderer is; any other name, RI_NULL included, builds a renderer as before. A failed .rib load raises the load error and leaves no context current, so every later request raises RIE_NOTSTARTED until RiBegin or RiContext selects one. gman_rib, a plain shared library in 0.8.1 with no gman:: target, is gone; RiBegin("x.rib") is the only way to reach the writer
  • RtBoolean is a fixed short, not bool in C++ or unsigned char in C, and every C++ signature carrying one changes its mangled name. A plugin subclassing GMANRenderMan or GMANRenderManImpl, or calling GMANRIBParse::addHandler, must rebuild. RI_NULL was the wrong width: a bare 0 passed through a variadic Ri* call's ... supplies an int-sized slot where va_arg reads a pointer, wrong on any LP64 platform; RI_NULL is now (RtToken)0, pointer-width. Assigning it to a handle type — RtLightHandle, RtObjectHandle or RtContextHandle — needs an explicit cast in C++, and warns without one in C. ri.h's #define NCOMPS 3 and __GMAN_RI_H include guard are both gone, the guard replaced by #pragma once
  • RiIlluminate and RiTransformEnd are spelled correctly in ri.h. Both were already defined under their correct names in gmancapi.cpp, but ri.h declared RiIllumnate and RiTranformEnd, so no program built against the header could link either call. Both misspellings are gone, not kept alongside the fix
  • RiExposure's gain and gamma now correct before a pixel narrows to a byte, not after. Every driver's save() called setExposure from the same option and narrowed to GMANColorRGB first, then looked its byte value up in a table built by pow; a channel below 1/255 had already narrowed to 0, and the table's own zero entry meant no gamma could lift it. gman::gammaCorrected now runs on the float GMANColor before narrowing, in all four drivers. A render at the default gain 1, gamma 1 is bit-for-bit unchanged; gain above 1 can still overflow narrowing to GMANColorRGB, as it did in 0.8.1. Code calling GMANGammaCorrect or GMANOutput::setExposure loses both, deleted; gman::gammaCorrected(color, gain, gamma) in the installed gmangamma.h is the replacement
  • A textured full sphere's texture turns half a turn, and a partial sweep starts at the spec's +x instead of -x. GMANSphere::getLocation subtracted half a turn before scaling theta by thetamax, the only one of the seven quadrics carrying that offset, so u=0 landed opposite where the RISpec and every other quadric put it. A Sphere with thetamax below 360 now draws its wedge half a turn from where 0.8.1 drew it; an untextured full sphere changes only where its tessellation crossed the old seam
  • A C-API program that passes a shader a parameter no longer crashes at exit, or at its next RiBegin/RiEnd cycle. RiEnd deletes the context's GMANDictionary, but a shader plugin stays loaded for the process's life; its static GMANShader kept a GMANParameterList built against that freed pointer, read again by the next cycle's GMANShader::set or by exit. The gman CLI never reached this path; any C program that called RiEnd after passing a shader a parameter did, at exit after a single render. Each list now owns its arrays behind a unique_ptr chosen at construction, so a throw partway through construction frees what it already allocated instead of leaking, and destroying a list never touches the dictionary again. operator= returns GMANParameterList&, not const GMANParameterList&, on this exported class

GMAN 0.8.1

Choose a tag to compare

@github-actions github-actions released this 17 Sep 22:41
0.8.1
9cdfe21
  • 0.8.0 shipped one tarball of three; this release ships all three. On the 0.8.0 tag push softprops/action-gh-release@v2 failed with "Error creating asset temp dir" on ubuntu-24.04-arm and macos-latest, twice each — the small .sha256 uploaded and the tarball beside it did not. The release workflow now creates the release and attaches every asset with gh, which ships on the runner image itself rather than arriving as a third-party action holding contents: write. The create step edits an existing release in place and the upload passes --clobber, so rerunning one partly-failed leg replaces that leg's assets instead of colliding with them
  • The documentation no longer cites a file that is not there. 36 references to SPEC.md across 31 files pointed at a document deleted before 0.8.0
  • Groundwork for the ray tracer. include/gmanray.h gives GMANRay an origin, a normalized direction and a [tmin, tmax] interval, and GMANHit the record an intersection fills in; GMANViewingSystem::ray transforms a camera-space ray into world space. The ray-tracing plugin remains non-functional and built OFF, and no rendered image changes

GMAN 0.8.0

Choose a tag to compare

@github-actions github-actions released this 17 Sep 21:03
0.8.0
956dde2
  • libtiff is now required. GMAN_WITH_TIFF is gone, and configure fails without libtiff rather than building a renderer that cannot write its own default output. TIFF is the Display default and the format every texture is read from, so the option only ever chose between a working build and a crippled one
  • C++20 is the floor, and the 1999 pthread wrapper is gone. GCC 13 or Clang 17 with <format> builds gman; an older compiler does not. gmanguard.h, gmanmutex.h and gmanthread.h are deleted — nothing called them and two of their methods had empty bodies. gmanParallelFor in include/gmanparallel.h is the one threading seam, and tests/threadcontainment_test.cpp fails any other file that names a thread primitive
  • The PNG and JPEG drivers are optional, and their headers left include/. Each driver compiles only where its library is present; GMAN_WITH_PNG and GMAN_WITH_JPEG force the question and fail configure when the library is missing. gmanoutputpng.h and gmanoutputjpeg.h are no longer installed. gman --version now lists the drivers a build carries, and a Display naming one it lacks fails with RIE_BADFILE instead of writing nothing
  • A plugin no longer declares a copyright. GMANLoadableObjectInfo lost its copyright field, and GMANLoadable::getCopyright and GMANLog::copyright are gone: an out-of-tree plugin drops that initializer and rebuilds against name, author, description. gman opens with one line — gman 0.8.0 -- LGPL-2.1-or-later, see COPYING — where it printed four lines of license text through a format string that silently dropped both the Pixar notice and the version
  • Texturing. MakeTexture turns a rendered image into a texture and texture(name, s, t) samples it from a surface shader, honoring the swrap and twrap modes recorded when it was made. Polygons carry per-vertex s and t, parametric surfaces shade with their own parameterization, and a cache holds each texture's pixels for the render rather than re-reading the file per shade
  • Environment maps, and a shinymetal shader that uses them. MakeLatLongEnvironment builds a latitude-longitude map and environment(name, R) samples it along a reflection direction. The shader now receives the camera-to-world matrix that a world-space reflection needs; environment() is indexed in world space, per RISpec A.2.4
  • spotlight. LightSource "spotlight" joins ambient, distant and point lights, with coneangle, conedeltaangle and beamdistribution in radians as the RISpec specifies — a scene asking for "coneangle" [30] asks for 30 radians
  • GeneralPolygon and PointsGeneralPolygons render, holes and all. Concave outlines triangulate by ear clipping, and each interior loop is bridged into the outline before triangulation. The classification is dimensionless, so a polygon renders the same at any scale or placement
  • PointsPolygons renders. One shared vertex array, one vertex count per polygon, with per-vertex parameters indexed through it
  • NuPatch renders. A NURBS surface evaluates against its knot vectors and rasterizes with the rest; TrimCurve is parsed and stored, and trims nothing yet
  • The tree is clang-format clean and gated. Every source file is formatted to .clang-format — 120 columns, left-bound pointers, includes grouped into standard, system, library and gman blocks — with clang-format 22.1.8, and format-check fails on any drift. A patch written against an earlier tree needs reformatting before it applies
  • gman -l wrote one byte past its buffer. The log file name was sized strlen(rib) + 4 where appending .log needs five, and a RIB path shorter than four characters also read before the buffer. Setting the log file no longer deadlocks on the log's own lock
  • A malformed RIB no longer leaks memory. Every duplicated string and every pending parameter key is released when array conversion throws partway through, and a Declare whose array size overflows is rejected rather than truncated. A bitmap whose pixel count overflows int is rejected at construction, and assigning one now copies both of its dimensions
  • The JPEG driver reports a file it cannot open. A failed fopen in GMANOutputJPEG::save fell into an empty else branch, so the render reported success with nothing on disk; it now throws the RIE_SYSTEM error the PNG and PNM drivers already threw

Known gaps. No shadows: MakeShadow is accepted and ignored, shadow() does not exist, and every light illuminates through geometry. No bump() — MakeBump is accepted and ignored too. Points and Curves parse and draw nothing. Rendering is still single-threaded: gmanParallelFor is the seam, and no renderer runs through it yet. The REYES, ray-tracing and radiosity plugins remain non-functional and built OFF. Shaders are C++ plugins; the shading-language compiler was never finished.

GMAN 0.7.1

Choose a tag to compare

@github-actions github-actions released this 08 Sep 22:47
0.7.1
5c36030
  • A malformed RIB could make the renderer read past the end of a heap allocation. Patch "bilinear" "P" [-1 -1 0 1 -1 0] declares four vertices — twelve floats — and supplies six. GMANParameterList sized its destination from the declared class and copied that many elements from the supplied array, running off the end of the parser's buffer and rendering whatever happened to be next in memory as vertex coordinates. Short arrays are now clamped and zero-filled, with a warning naming the parameter and both lengths. All three copy paths are covered — float, integer and string — since each carried the identical unbounded loop
  • This affected 0.6.0 and 0.7.0. The defect predates PatchMesh, where review found it: the trace above is a plain Patch. Anyone running an earlier release should upgrade. A renderer's whole job is parsing files it did not write, which makes an out-of-bounds read on malformed input a defect in the primary input path rather than an edge case
  • The parser already knew the length and threw it away. parseParameterList recorded each array's element count and discarded it. The Ri*V entry points cannot carry it — those signatures are fixed by the RenderMan interface — so the count now travels beside the call rather than through it. Supplying no count still means "trust the caller", which keeps the public C API's contract intact: a program calling RiPatchV directly owns that memory, while a RIB file is untrusted
  • A zero basis step no longer divides by zero. validBicubicMeshDim's nonperiodic branch computed (n - 4) % step with no guard on step, where its periodic sibling rejected step < 1 outright. Unreachable through RIB, which rejects a bad step earlier, and reachable through GMANPatchPolyObjectManager directly
  • The memcheck leg tests more than two files. Valgrind in CI ran sphere.rib and corpus/menger.rib and nothing else, so no PatchMesh fixture and no malformed input ever reached a sanitizer there. That is why the overflow above survived review and a merge. A periodic bicubic PatchMesh now runs under memcheck

GMAN 0.7.0

Choose a tag to compare

@github-actions github-actions released this 08 Sep 01:05
0.7.0
30e961e
  • Anti-aliasing. PixelSamples and PixelFilter were parsed, stored and discarded; every render was one sample per pixel whatever the scene asked for. A per-sample buffer now sits behind the z-buffer renderer, and the pixel filter convolves over its support rather than the renderer averaging within a pixel. Every image the renderer produces changes. Samples land at (j+0.5)/n within a pixel — a truncating placement would have shifted every image a fraction of a pixel, which no surviving test would have caught
  • Patch renders, bilinear and bicubic. It had parsed and drawn nothing since 1999. Landing it exposed the defect that had kept it dark: GMANVector4::operator*=(const GMANMatrix4 &) sliced itself to a 3D temporary, transformed that, and threw it away, so a projective transform of a 4-component point silently did nothing. The header had documented that exact bug shape as already fixed for its sibling overloads. Bicubic also needed its tangents normalized before crossing them, or the surface normal scaled with the parameterization
  • PatchMesh renders, bilinear and bicubic, periodic and non-periodic. Includes B-spline, Bezier, Catmull-Rom and Hermite bases through RiBasis, and mixed uwrap/vwrap. Two arithmetic defects came out of it: the last sub-patch of a periodic mesh read one row past the grid instead of wrapping to the first, and a zero-step basis divided by zero before any control point was touched
  • Two of the five pixel filters were wrong, and nothing had ever called them. RiTriangleFilter returned nonzero — sometimes negative — weights outside its support, so a filter that should vanish at its edge instead subtracted light beyond it. RiGaussianFilter was missing the RISpec's 2/width rescale of its argument, leaving the kernel at 61% of peak at the support edge where the reference sits at 13.5%. Both were found by evaluating the functions rather than by reading them. Box, Catmull-Rom and sinc are pinned as-found by tests rather than "fixed"
  • The golden-image tolerance is measured rather than guessed. It had accepted 24/255 per channel across up to 1% of pixels — values picked for one scene during the revival and adopted tree-wide. That window absorbed a real regression: reverting the perspective screen-window clip fix moved 732 of 120,000 pixels and the shaders golden still passed. Measuring the actual cross-platform spread found macOS matching every pixel exactly and Linux differing by at most six pixels in one scene, so the fraction tightened to 0.1% — about 180x headroom over the worst case observed. That same revert now turns shaders red
  • The test suite carries labels, timeouts and a real skip. Every test declares LABELS and a TIMEOUT; the JPEG driver test skips rather than fails where libjpeg is absent. 34 tests, up from 31
  • Intel Mac binaries are gone from releases. The macos-13 leg of 0.6.0 sat queued for five hours without ever being assigned a runner and published six assets where eight were expected. The matrix is now the three legs that actually get runners: linux-x86_64, linux-arm64, macos-arm64. Building on an Intel Mac is still supported; nobody ships you a binary for it

Known gaps. No texturing — texture(), environment(), shadow() and bump() do not exist, though s/t reach the shader. No shadows: a light illuminates through geometry. No spotlight. NuPatch, curves and points parse but do not rasterize. Single-threaded — the 1999 pthread wrapper is still present, still uncalled, and two of its methods are empty bodies. The REYES, ray-tracing and radiosity plugins remain non-functional and built OFF. Shaders are C++ plugins; the shading-language compiler was never finished.

GMAN 0.6.0

Choose a tag to compare

@github-actions github-actions released this 06 Sep 20:05
0.6.0
659eb61
  • The first release in 24 years. GMAN was written between 1999 and 2002, shelved at 0.1.0, and resumed in 2026. Everything below is the revival arc; the entries under it are the original history, kept verbatim from the ChangeLog this file replaces
  • It renders. All seven RenderMan quadrics — Sphere, Cone, Cylinder, Hyperboloid, Paraboloid, Torus, Disk — plus convex Polygon, shaded by matte, plastic or metal, lit by ambientlight, distantlight and pointlight, written out as TIFF, PNG, JPEG or PNM. At the start of the revival gman sphere.rib exited 1 with TOKEN_NOT_FOUND and produced no file
  • Builds with CMake 3.25 presets and C++23. Autotools is gone, along with the Windows tree and the GMANDLL macro (now GMAN_EXPORT, across 95 files). Three presets: dev is RelWithDebInfo, debug adds ASan and UBSan, release is Release
  • The coordinate chain works end to end. Object → world → camera → screen → NDC → raster. GMANMatrix4::prjPersp was rewritten; RiWorldBegin had shadowed the field of view with its default, and the output driver leaked on every frame
  • Array parameters reached the renderer for the first time. fov [45] parsed, then was silently dropped, so every scene rendered at the default field of view whatever it asked for. This defect is why the revival ran phases 0 → 2 → 1 rather than in order
  • Transform composition order was backwards. buildTransform accumulated CTM_old · Local for a row-vector chain that requires Local · CTM_old, so an in-world Rotate orbited its primitive around the camera instead of the world origin — a sphere's silhouette centroid moved 99 → 192 px across 0 → 30° of rotation and left the frame entirely by 45°. Invisible to the whole test suite at the time, because every rendering fixture used only Translate
  • Perspective clipping honors the screen window. GMANPolygonClipper::clip tested perspective geometry against fixed ±1 side planes while computing the correct planes for orthographic. At 640×400 the default window is x ∈ [-1.6, 1.6], so only columns 120–520 of 640 ever drew and 37% of every wide frame was background
  • Convex Polygon rasterizes. GMANPolygon had been declared and wired to nothing. Landing it exposed two more defects it made observable: RiPolygonV sized its parameters wrongly, and GMANRIBParse::parsePolygon hardcoded a vertex count of zero
  • Primitives carry normals, and shading runs. calcNormal is wired, backface culling is real rather than assumed, lights illuminate, and C++ surface shaders execute against a populated shading environment
  • Loading two shaders in one scene no longer aborts. GMANLoadableShader let its dlopen handle refcount reach zero at AttributeEnd and closed the module while a later AttributeBegin still referenced the address the loader recycled. Handles are now retained for the life of the process
  • GMANQuantize::doColor stopped logging once per pixel. A 640×400 render emitted 256,000 identical warnings; it now warns once
  • The RIB front end covers a working subset of RISpec 3.2. Camera and transform setup, lights, surface shaders, array and inline-declared parameters, facevarying parameters, gzip'd streams and ReadArchive with cycle detection. Any request GMAN does not implement warns once, skips and keeps parsing, so an unsupported scene degrades instead of aborting — 23 requests take that path deliberately. Aqsis' menger.rib parses end to end
  • A real test suite and CI. Golden-image regression over a checked-in RIB corpus, unit tests for the matrix and space chain, and seven CI legs: macOS and Linux against both gcc and clang, an ASan/UBSan build, valgrind memcheck, and a clang-format check. The Linux legs caught what macOS clang cannot see — 26 delete on new[], an incompatible function type, ignored-qualifier casts and a 1,332-byte-per-context leak
  • The license position is settled. LGPL-2.1-or-later with SPDX identifiers across 220 files; the pre-2005 FSF address is corrected and "GNU GMAN Library" is retired — GMAN was never an accepted GNU package. The name is now "GMAN, a RenderMan-compatible renderer", which drops a trademark use that was the project's only real legal exposure
  • Documentation describes the renderer that exists. The README is markdown and leads with what GMAN does; CONTRIBUTING.md replaces a coding guide written in 2001; AGENTS.md covers the conventions and traps for an AI agent working the tree; the 1999 LaTeX manual no longer cites headers that never existed or a compiler from 1998. INSTALL, disclaimer.txt and the old ChangeLog are deleted

Known gaps. No texturing. No anti-aliasing — one sample per pixel, though PixelSamples and PixelFilter parse and five filter kernels are implemented. Patch, PatchMesh, NuPatch, curves and points parse but do not rasterize. The REYES, ray-tracing and radiosity renderer plugins are present, non-functional and built OFF by default. Shaders are C++ plugins; the shading-language compiler was never finished and is kept only as a record.