Get linear shaders
-
On 14/11/2014 at 18:36, xxxxxxxx wrote:
Using shader.initRender() I am rendering out a shader, however I can't get the InitRenderStruct() to be linear. In the docs I have found InitRenderStruct.linear_workflow but this feature is read only. how do I set this value to True?
-
On 17/11/2014 at 06:34, xxxxxxxx wrote:
Hello,
the Python implementation expects the IRS to be initiated by Cinema. So I'm afraid it is not possible to edit an ad hoc created IRS.
Best wishes,
Sebastian -
On 08/01/2015 at 10:35, xxxxxxxx wrote:
Finally got the chance to pick this project back up. It seems that I may not be facing a linear issue. Here are some examples of output:
Original (How the cinema shader preview sees it) :
_<_img src="http://shawnfrueh.com/references/c4d/original_cinemaoutput.png" height="512" width="512" border="0" /_>_This is what I get when I use initRender() :
<_<_img src="http://shawnfrueh.com/references/c4d/original_initoutput.png" height="512" width="512" border="0" /_>_" />and here is what I get when I add a Gamma correction:_r="0" />
So as you mentioned before I am guessing the IRS is not respecting the project color-space. Is there a way around this? How is the shader preview being rendered?
-
On 09/01/2015 at 07:23, xxxxxxxx wrote:
Hi Shawn,
InitRenderStruct.linear_workflow is passed to InitRender() so that shaders can check if they have to perform some color conversion to InitRenderStruct.document_colorprofile.
c4d.utils.TransformColor() can then be called to return the expected color from Output(). -
On 09/01/2015 at 08:23, xxxxxxxx wrote:
I really appreciate the help Yannick, worked like a charm! Thank you.
-
On 09/01/2015 at 12:54, xxxxxxxx wrote:
Looks like I spoke to soon. The scene I was testing in had the color profile disabled. This is what it looks like in a default scene:
COLORSPACETRANSFORMATION_NONE:
_<_img src="http://shawnfrueh.com/references/c4d/colorspace_nOne.gif" height="278" width="633" border="0" /_>_COLORSPACETRANSFORMATION_LINEAR_TO_SRGB:
<_<_img src="http://shawnfrueh.com/references/c4d/colorspace_linear_to_srgb.gif.gif" height="278" width="633" border="0" /_>_" />COLORSPACETRANSFORMATION_SRGB_TO_LINEAR:_r="0" />
COLORSPACETRANSFORMATION_LINEAR_TO_VIEW_<_img src="http://shawnfrueh.com/references/c4d/colorspace_linear_to_view.gif" height="278" width="633" border="0" /_>_order="0" />
COLORSPACETRANSFORMATION_SRGB_TO__<_img src="http://shawnfrueh.com/references/c4d/colorspace_srgb_to_view.gif" height="278" width="633" border="0" /_>_3" border="0" />
So, I guess I'm Back to the drawing board. Am I missing something?
-
On 09/01/2015 at 12:59, xxxxxxxx wrote:
This is how I am getting the color:
s = shader.Sample(cd) s = c4d.utils.TransformColor(s,profile) r = int(s.x * 255) g = int(s.y * 255) b = int(s.z * 255) bmp.SetPixel(x, y, r, g, b)
-
On 12/01/2015 at 01:39, xxxxxxxx wrote:
Hi Shawn,
The Cinema 4D shaders usually transform their input colors (in InitRender()) using irs.TransformColor() that calls the global TransformColor() according to the irs.linear_workflow state and irs.document_colorprofile.
InitRenderStruct.TransformColor() isn't defined in the Python API but its code is simple and included in the C++ API. Following is its code converted to Python:def TransformColor(irs, input) : if irs.linear_workflow and irs.document_colorprofile is c4d.DOCUMENT_COLORPROFILE_SRGB: return c4d.utils.TransformColor(input, c4d.COLORSPACETRANSFORMATION_SRGB_TO_LINEAR); elif not irs.linear_workflow and irs.document_colorprofile is c4d.DOCUMENT_COLORPROFILE_LINEAR: return c4d.utils.TransformColor(input, c4d.COLORSPACETRANSFORMATION_LINEAR_TO_SRGB); return input;
You should use this TransformColor() for the color sampled in your shader.
Note that c4d.utils.TransformColor() expects a COLORSPACETRANSFORMATION value as second parameter, not a DOCUMENT_COLORPROFILE value.
Also be sure that the bitmap in your shader uses the appropriate color profile. -
On 12/01/2015 at 14:50, xxxxxxxx wrote:
I am not sure I follow. Using your code above I get the same result: the output is not the same. So when you say that the bitmap must use the correct profile. Does that mean that the bitmap I am creating must also have a profile attached to it?
playing with c4d.bitmaps.ColorProfile.GetDefaultLinearRGB() and adding it to the bitmap has no influence on the output.
here is the code I have for better understanding:
from __future__ import division import c4d,timeit from c4d import Vector, bitmaps, gui from c4d.bitmaps import ShowBitmap from c4d.modules.render import ChannelData, InitRenderStruct # Bitmap maker created by Shawn Frueh class BasicDialog(gui.GeDialog) : RENDER = 10000 SHADERLINK = 10001 GROUP_SIZE = 10002 WIDTH_TEXT = 10003 WIDTH = 10004 HEIGHT_TEXT = 10005 HEIGHT = 10006 GROUPFIT = 10007 PROGRESS = 10008 GROUP_PERCENT = 10009 PROGRESS_SLIDER = 10010 GROUP_OF_GROUPS = 10011 RENDER_BIT = 10012 GROUP_ALL = 10013 PROFILESELECT = 10014 RENDERINFO = 10015 CS_NONE = c4d.COLORSPACETRANSFORMATION_NONE CS_L_TO_S = c4d.COLORSPACETRANSFORMATION_LINEAR_TO_SRGB CS_S_TO_L = c4d.COLORSPACETRANSFORMATION_SRGB_TO_LINEAR CS_L_TO_V = c4d.COLORSPACETRANSFORMATION_LINEAR_TO_VIEW CS_S_TO_V = c4d.COLORSPACETRANSFORMATION_SRGB_TO_VIEW def CreateLayout(self) : self.SetTitle("Shader Renderer") self.GroupBegin(self.GROUPFIT,c4d.BFH_SCALEFIT, cols = 2) bc = c4d.BaseContainer() bc.SetLong(c4d.BITMAPBUTTON_ICONID1, c4d.RESOURCEIMAGE_MOVE) bc.SetBool(c4d.BITMAPBUTTON_BUTTON, True) self.myBitButton=self.AddCustomGui(self.RENDER_BIT, c4d.CUSTOMGUI_BITMAPBUTTON, "Bend", c4d.BFH_CENTER | c4d.BFV_CENTER, 64, 64, bc) bmp = bitmaps.BaseBitmap() bmp.Init(120,120,24) self.myBitButton.SetImage(bmp) self.GroupBegin(self.GROUP_ALL, c4d.BFH_SCALEFIT, cols = 1) self.GroupBorderSpace(4,4,4,4) self.AddComboBox(self.PROFILESELECT, c4d.BFH_SCALEFIT) self.AddCustomGui(self.SHADERLINK, pluginid=c4d.CUSTOMGUI_LINKBOX, name="Link", flags=c4d.BFH_SCALEFIT, minw=200, minh=0) self.GroupBegin(self.GROUP_SIZE,c4d.BFH_SCALEFIT, cols = 4, title = "Render Size") self.AddStaticText(self.WIDTH_TEXT, c4d.BFH_LEFT, name = "Width") self.AddEditNumber(self.WIDTH, c4d.BFH_SCALEFIT) self.AddStaticText(self.HEIGHT_TEXT, c4d.BFH_LEFT, name = "Height") self.AddEditNumber(self.HEIGHT, c4d.BFH_SCALEFIT) self.GroupEnd() self.GroupBegin(self.GROUP_PERCENT,c4d.BFH_SCALEFIT, cols = 3) self.GroupBorderSpace(4,4,4,4) self.AddButton(self.RENDER, c4d.BFH_LEFT, name = "Render") self.AddStaticText(self.PROGRESS,c4d.BFH_LEFT,name = " 100%!") self.AddSlider(self.PROGRESS_SLIDER, c4d.BFH_SCALEFIT) self.GroupEnd() self.AddStaticText(self.RENDERINFO, c4d.BFH_LEFT, name = "Please add a shader.", initw = 500) self.GroupEnd() self.GroupEnd() return True def InitValues(self) : self.SetString(self.PROGRESS," 0%") self.SetReal(self.PROGRESS_SLIDER, 0.0,min = 0, max = 100.0) self.SetInt32(self.WIDTH, 512, max = c4d.MAXLONGl) self.SetInt32(self.HEIGHT, 512, max = c4d.MAXLONGl) self.AddChild(self.PROFILESELECT, self.CS_NONE,"None") self.AddChild(self.PROFILESELECT, self.CS_L_TO_S,"Linear to SRGB") self.AddChild(self.PROFILESELECT, self.CS_S_TO_L,"SRGB to Linear") self.AddChild(self.PROFILESELECT, self.CS_L_TO_V,"Linear to View") self.AddChild(self.PROFILESELECT, self.CS_S_TO_V,"SRGB to View") return True def Command(self, id, msg) : link = self.FindCustomGui(self.SHADERLINK,c4d.CUSTOMGUI_LINKBOX) sh = link.GetLink(doc,0) def GetProfile(p) : if p == 0: return self.CS_NONE if p == 1: return self.CS_L_TO_S if p == 2: return self.CS_S_TO_L if p == 10: return self.CS_L_TO_V if p == 11: return self.CS_S_TO_V def RenderShader(w,h,sh) : global percent global Pget shader = sh start = timeit.default_timer() irs = InitRenderStruct() ##### shader.InitRender(irs) ##### cd = ChannelData() cd.p = Vector(.5,.5,0) bmp = bitmaps.BaseBitmap() bmp.Init(w,h,24) c4d.StatusSetBar(0.0) pget = 100/w percent = 0.0 profile = self.GetInt32(self.PROFILESELECT) profile = GetProfile(profile)# possibly not neccesarry? c4d.StatusSetText("Rendering: "+shader.GetName()+" shader") for x in xrange(w) : c4d.StatusSetBar(percent) self.SetReal(self.PROGRESS_SLIDER, percent,min = 0, max = 100.0) self.SetString(self.PROGRESS," "+str(percent)+"%") for y in xrange(h) : PX = x/w PY = y/h cd.p = Vector(PX,PY,0) s = shader.Sample(cd) s = c4d.utils.TransformColor(s,profile) r = int(s.x * 255) g = int(s.y * 255) b = int(s.z * 255) bmp.SetPixel(x, y, r, g, b) percent = percent + pget shader.FreeRender() stop = timeit.default_timer() c4d.StatusClear() self.SetString(self.PROGRESS," 100%!") self.SetReal(self.PROGRESS_SLIDER, 100,min = 0, max = 100.0) OutInfo = shader.GetName()+" shader rendered in "+str(stop - start)+" seconds" self.SetString(self.RENDERINFO, OutInfo) return bmp if id == self.RENDER: w = self.GetInt32(self.WIDTH) h = self.GetInt32(self.HEIGHT) Abmp = RenderShader(w,h,sh) ShowBitmap(Abmp) if id == self.RENDER_BIT: Ibmp = RenderShader(120,120,sh) self.myBitButton.SetImage(Ibmp) self.SetString(self.PROGRESS,"0%") self.SetReal(self.PROGRESS_SLIDER, 0,min = 0, max = 100.0) self.myBitButton.SetImage(Ibmp) if id == self.SHADERLINK: Ibmp = RenderShader(120,120,sh) self.myBitButton.SetImage(Ibmp) self.SetString(self.PROGRESS,"0%") self.SetReal(self.PROGRESS_SLIDER, 0,min = 0, max = 100.0) self.myBitButton.SetImage(Ibmp) if id == self.PROFILESELECT: Ibmp = RenderShader(120,120,sh) self.myBitButton.SetImage(Ibmp) self.SetString(self.PROGRESS,"0%") self.SetReal(self.PROGRESS_SLIDER, 0,min = 0, max = 100.0) self.myBitButton.SetImage(Ibmp) return True dlg = BasicDialog() dlg.Open(dlgtype=c4d.DLG_TYPE_ASYNC, xpos=-1, ypos=-1)
-
On 14/01/2015 at 00:43, xxxxxxxx wrote:
Hi Shawn,
Thanks for posting your code. I should have asked in which context you where calling InitRender().
I thought you were invoking InitRender() from a ShaderData plugin.
Unfortunately InitRenderStruct.linear_workflow and InitRenderStruct.document_colorprofile are read-only in the Python API and can't be set.
I'll report this limitation to the development team.