Demonstrates basic operations with the Redshift renderer in Cinema 4D.
About
With S26 the Redshift render engine has been integrated with Cinema 4D. While the render engine has already previously been available to Cinema 4D users, it was then a plugin and therefor not part of the public Cinema 4D SDK. With the integration come also architectural changes as for example the unification of camera and light types and a unified nodes model.
Current Limitations
In the current form of Redshift integration there are no Redshift specific frameworks yet exposed. But the core features of Redshift can be accessed through the Cinema API and Nodes API. Currently missing from the public API are also the Redshift render engine ID and the Redshift node space ID for node materials. They must be provided manually in third party code at the moment as demonstrated by the examples here.
Redshift has also an anti-tampering mechanism which ensures Redshift is being run with a valid license. This mechanism triggers when a debugger, as for example provided by Visual Studio and Xcode, is attached to Cinema 4D. The anti-tampering mechanism then obfuscates the rendering output of Redshift as shown in Figure I. Plugins making use of Redshift can still be debugged as any other plugin, but to see the final output of a plugin which generates for example a Redshift node material setup, the plugin must be compiled and loaded by a normal instance of the Cinema 4D application without a debugger attached.
Examples
Set Render Engine to Redshift
Sets the render engine of the active render data of a document to Redshift.
Also assures that the required Redshift video post node is present in the render data. This example requires defining the Redshift renderer plugin ID as shown here, as the ID is currently not exposed in the SDK.
{
if (!doc->StartUndo())
RenderData* rdata = doc->GetActiveRenderData();
if (rdata == nullptr)
return maxon::UnexpectedError(
auto FindVideoPost = [](RenderData* rdata,
Int32 videoPostType) -> BaseVideoPost*
{
if (rdata == nullptr)
return nullptr;
BaseVideoPost* videoPost = rdata->GetFirstVideoPost();
while (videoPost)
{
if (videoPost->IsInstanceOf(videoPostType))
return videoPost;
videoPost = videoPost->GetNext();
}
return nullptr;
};
{
BaseVideoPost* redshiftVideoPost = BaseVideoPost::Alloc(
VPrsrenderer);
if (!redshiftVideoPost)
return maxon::OutOfMemoryError(
rdata->InsertVideoPost(redshiftVideoPost);
}
if (!doc->EndUndo())
}
@ RDATA_RENDERENGINE
Definition: drendersettings.h:39
CHANGE
Any change to an object, including hierarchy modifications, modification in positioning,...
Definition: ge_prepass.h:2
NEWOBJ
A new object, material, tag, or other Cinema API node instance has been inserted into the document....
Definition: ge_prepass.h:7
return OK
Definition: apibase.h:2783
#define MAXON_SOURCE_LOCATION
Definition: memoryallocationbase.h:69
#define VPrsrenderer
Videopost plugin 'Redshift'. @PublicExposure.
Definition: c4d_videopostdata.h:250
class CINEWARE_SINGLEINHERITANCE BaseContainer
Definition: lib_noise.h:75
maxon::Int32 Int32
Definition: ge_sys_math.h:51
class CINEWARE_SINGLEINHERITANCE BaseDocument
Definition: customgui_inexclude.h:18
#define iferr_scope
Definition: resultbase.h:1482
Simple Rendering of a Document
Demonstrates how to render a document in OCIO mode using convenience functions which streamline the process. This is the recommended way to render OCIO documents, as it ensures that all OCIO color spaces and transforms are correctly applied to the rendering.
{
finally
{
MultipassBitmap::Free(bmp1);
MultipassBitmap::Free(bmp2);
};
return maxon::OutOfMemoryError(
ShowBitmap(bmp2,
"AUTO_SETUP | OCIO_BAKE_RENDERING Rendered Image");
}
NONE
Definition: asset_browser.h:1
Definition: c4d_basedocument.h:553
RenderData * GetActiveRenderData()
Returns the data for the active render settings in the document.
const BaseContainer & GetDataInstanceRef() const
Definition: c4d_baselist.h:2625
OK
User has selected a font.
Definition: customgui_fontchooser.h:0
@ RDATA_FORMATDEPTH_16
Definition: drendersettings.h:74
@ RDATA_FORMATDEPTH_32
Definition: drendersettings.h:75
@ RDATA_FORMATDEPTH
Definition: drendersettings.h:72
USE16BITCHANNELS
Use 16-bit channels.
Definition: ge_prepass.h:4
AUTO_SETUP
Alias for EXTERNAL | OCIO_RAW_RENDERING. This is the recommended flags combination to use as a base f...
Definition: ge_prepass.h:18
OCIO_BAKE_RENDERING
Shorthand for calling cinema::BakeOcioViewToBitmap on the render result bitmap, baking down all OCIO ...
Definition: ge_prepass.h:16
USE32BITCHANNELS
Use 32-bit channels.
Definition: ge_prepass.h:8
#define C4D_PATH_DESKTOP
OS desktop directory.
Definition: c4d_file.h:1984
#define FILTER_PSD
PSD.
Definition: ge_prepass.h:183
RENDERFLAGS
Definition: ge_prepass.h:4854
SAVEBIT
Definition: ge_prepass.h:267
#define MAXON_UNLIKELY(...)
Definition: compilerdetection.h:401
const Filename GeGetC4DPath(Int32 whichpath)
Bool ShowBitmap(const Filename &fn)
RENDERRESULT RenderDocument(BaseDocument *doc, const BaseContainer &rdata, ProgressHook *prog, void *private_data, BaseBitmap *bmp, RENDERFLAGS renderflags, BaseThread *th, WriteProgressHook *wprog=nullptr, void *data=nullptr)
MultipassBitmap * AllocateRenderBitmap(const BaseContainer *renderData)
Allocates a bitmap for rendering a document according to the passed render data container.
Complex Rendering of a Document
Demonstrates how to manually setup and OCIO document for rendering, giving you more control over the rendering process.
{
return maxon::UnexpectedError(
MultipassBitmap* bmp = nullptr;
finally
{
if (bmp)
MultipassBitmap::Free(bmp);
if (bakedBmp)
BaseBitmap::Free(bakedBmp);
};
if (isOcioDocument)
if (!bmp)
if (!bmp->AddChannel(true, true))
{
};
return maxon::UnexpectedError(
}
EXTERNAL
Some external state (for example document settings) will be accessed. This flag may only be used for ...
Definition: c4d_accessedobjects.h:67
Int32 GetInt32(Int32 id, Int32 preset=0) const
Definition: c4d_basecontainer.h:346
@ DOCUMENT_COLOR_MANAGEMENT
Definition: ddoc.h:155
@ DOCUMENT_COLOR_MANAGEMENT_OCIO
Definition: ddoc.h:157
@ RDATA_BAKE_OCIO_VIEW_TRANSFORM_RENDER
Definition: drendersettings.h:89
@ RDATA_XRES
Definition: drendersettings.h:154
@ RDATA_YRES
Definition: drendersettings.h:155
DURINGRENDERING
During rendering.
Definition: ge_prepass.h:1
RGBf
32-bit floating point RGB channels.
Definition: ge_prepass.h:30
int32_t Int32
32 bit signed integer datatype.
Definition: apibase.h:184
RENDERPROGRESSTYPE
Definition: ge_prepass.h:4777
RENDERRESULT
Definition: ge_prepass.h:425
#define ApplicationOutput(formatString,...)
Definition: debugdiagnostics.h:204
#define FormatString(...)
Definition: string.h:2280
class CINEWARE_SINGLEINHERITANCE BaseBitmap
Definition: c4d_graphview.h:30
maxon::Result< BaseBitmap * > BakeOcioViewToBitmap(BaseBitmap *bmp, const BaseContainer &renderData, SAVEBIT flags)
Bakes the OCIO transforms associated with bmp into the image.
maxon::Bool Bool
Definition: ge_sys_math.h:46
void StatusClear()
Clears the status bar text.
maxon::Float Float
Definition: ge_sys_math.h:57
void StatusSetText(const maxon::String &str)
#define iferr_return
Definition: resultbase.h:1617
Create a Redshift Camera
Instantiates a Redshift camera and inserts it into a document.
Also modifies the projection mode, the near clipping plane and the transform of the new camera to demonstrate setting up a camera in more detail.
{
BaseObject* redshiftCamera = BaseObject::Alloc(
Orscamera);
if (redshiftCamera == nullptr)
redshiftCamera->SetMg(transform);
doc->InsertObject(redshiftCamera, nullptr, nullptr);
BaseDraw* renderBaseDraw = doc->GetRenderBaseDraw();
if (!renderBaseDraw)
renderBaseDraw->SetSceneCamera(redshiftCamera);
BaseObject* convertStdCamera = BaseObject::Alloc(
Ocamera);
if (!convertStdCamera)
convertStdCamera->SetParameter(
const Float stdCameraApperatureValue = 50.0;
BaseObject* convertRsCamera = BaseObject::Alloc(
Orscamera);
if (!convertRsCamera)
return maxon::OutOfMemoryError(
convertRsCamera->SetParameter(
convertStdCamera->SetName("Conversion Redshift->Standard"_s);
convertRsCamera->SetName("Conversion Standard->Redshift"_s);
doc->InsertObject(convertRsCamera, nullptr, nullptr);
doc->InsertObject(convertStdCamera, nullptr, nullptr);
}
constexpr MAXON_ATTRIBUTE_FORCE_INLINE Float32 DegToRad(Float32 r)
Converts float value from degrees to radians.
Definition: apibasemath.h:469
#define Orscamera
New Camera Object (Redshift)
Definition: ge_prepass.h:1053
#define Ocamera
Camera - CameraObject.
Definition: ge_prepass.h:1052
#define ConstDescID(...)
Definition: lib_description.h:611
maxon::Mat3< maxon::Vector64 > Matrix
Definition: ge_math.h:141
maxon::Vec3< maxon::Float64, 1 > Vector
Definition: ge_math.h:122
@ CAMERAOBJECT_APERTURE
Definition: ocamera.h:42
@ RSCAMERAOBJECT_PROJECTION_ORTHOGRAPHIC
Definition: orscamera.h:233
@ RSCAMERAOBJECT_NEAR_CLIPPING_ENABLE
Definition: orscamera.h:18
@ RSCAMERAOBJECT_APERTURE
Definition: orscamera.h:46
@ RSCAMERAOBJECT_PROJECTION
Definition: orscamera.h:10
@ RSCAMERAOBJECT_NEAR_CLIPPING
Definition: orscamera.h:17
Create a Redshift Light Object
Instantiates a Redshift light object and inserts it into a document.
Also modifies the light type and shape, the color and intensity and the transform of the new light object to demonstrate setting up a light object in more detail. Finally, adds a target tag to the light object to orient towards a dummy geometry created alongside with this example.
{
BaseObject* redshiftLight = BaseObject::Alloc(
Orslight);
if (redshiftLight == nullptr)
redshiftLight->SetMg(transform);
doc->InsertObject(redshiftLight, nullptr, nullptr);
BaseObject* cubeObject = BaseObject::Alloc(
Ocube);
if (cubeObject == nullptr)
doc->InsertObject(cubeObject, nullptr, nullptr);
if (targetTag == nullptr)
bc = targetTag->GetDataInstance();
}
#define Orslight
Redshift light.
Definition: ge_prepass.h:1051
#define Ocube
Cube.
Definition: ge_prepass.h:1128
#define Ttargetexpression
Target expression.
Definition: ge_prepass.h:1451
Vector HSLtoRGB(const Vector &col)
@ REDSHIFT_LIGHT_AREA_GEOMETRY_DISC
Definition: orslight.h:216
@ REDSHIFT_LIGHT_PHYSICAL_COLOR
Definition: orslight.h:54
@ REDSHIFT_LIGHT_TYPE
Definition: orslight.h:9
@ REDSHIFT_LIGHT_TYPE_PHYSICAL_AREA
Definition: orslight.h:205
@ REDSHIFT_LIGHT_PHYSICAL_INTENSITY
Definition: orslight.h:58
@ REDSHIFT_LIGHT_PHYSICAL_AREA_GEOMETRY
Definition: orslight.h:64
@ TARGETEXPRESSIONTAG_LINK
Definition: ttargetexpression.h:6
Create a Redshift Material
Creates a Redshift node material, modifies its node graph and inserts the material into a document.
The example adds two Texture nodes, a Color Mix node, and a Maxon Noise node to the node graph of the material and creates connections between these nodes. The two texture nodes are setup to reference texture assets delivered with Cinema 4D. See Asset API for more information on the asset system of Cinema 4D which is used here.
{
NodeMaterial* material;
Bool didInsertMaterial =
false;
{
"Could not unroll or finalize undo stack upon error handling."_s };
"Critical error while aggregating errors."_s };
if (doc && material && didInsertMaterial)
{
if (!isUndoError)
{
material->Remove();
isUndoError = !doc->EndUndo();
}
if (isUndoError)
{
iferr (aggError.AddError(maxon::Error(err)))
return critError;
iferr (aggError.AddError(undoError))
return critError;
return aggError;
}
}
return maxon::Error(err);
};
if (!doc)
if (!doc->StartUndo())
return maxon::IllegalStateError(
const maxon::Url rustTextureUrl {
"asset:///file_edb3eb584c0d905c"_s };
const maxon::Url sketchTextureUrl {
"asset:///file_3b194acc5a745a2c"_s };
material =
static_cast<NodeMaterial*
>(BaseMaterial::Alloc(
Mmaterial));
if (!material)
const maxon::LiteralId redshiftId(
"com.redshift3d.redshift4c4d.class.nodespace");
const maxon::nodes::NodesGraphModelRef& graph = material->GetGraph(redshiftId)
iferr_return;
doc->InsertMaterial(material);
didInsertMaterial = true;
return maxon::IllegalStateError(
const maxon::Id outputNodeTypeId(
"com.redshift3d.redshift4c4d.node.output");
const maxon::Id materialNodeTypeId(
"com.redshift3d.redshift4c4d.nodes.core.standardmaterial");
const maxon::Id colormixNodeTypeId(
"com.redshift3d.redshift4c4d.nodes.core.rscolormix");
const maxon::Id noiseNodeTypeId(
"com.redshift3d.redshift4c4d.nodes.core.maxonnoise");
const maxon::Id textureNodeTypeId(
"com.redshift3d.redshift4c4d.nodes.core.texturesampler");
maxon::DataDictionary userData;
{
maxon::Id(
"com.redshift3d.redshift4c4d.nodes.core.texturesampler.tex0")).FindChild(
maxon::Id(
"com.redshift3d.redshift4c4d.nodes.core.texturesampler.tex0")).FindChild(
if (!doc->EndUndo())
}
Definition: errorbase.h:126
Result< typename SFINAEHelper< GraphNode, BASE >::type > GetOutputs() const
Definition: graph.h:1214
Result< typename SFINAEHelper< GraphNode, BASE >::type > GetInputs() const
Definition: graph.h:1203
Result< void > Connect(const GraphNode &target, Wires modes=WIRE_MODE::CONNECT_DEFAULT, Bool reverse=false) const
Definition: graph.h:1512
Result< Bool > SetPortValue(T &&value) const
Definition: graph.h:1810
Result< void > Commit(const DataDictionary &userData=GetPtrSizedZeroRef< DataDictionary >(), Bool validate=true)
Definition: apibaseid.h:243
Definition: apibaseid.h:28
DELETEOBJ
An object, node, tag, or other Cinema API node instance is about to be deleted. Must to be called bef...
Definition: ge_prepass.h:8
#define Mmaterial
Standard material.
Definition: ge_prepass.h:1014
@ NOISE_WAVY_TURB
Wavy turbulence.
Definition: lib_noise.h:59
#define iferr(...)
Definition: errorbase.h:388
Bool GeIsMainThreadAndNoDrawThread()
@ ADD
Add an undo entry, but don't start a new undo.
#define iferr_scope_handler
Definition: resultbase.h:1500