POV-Ray : Newsgroups : povray.advanced-users : L*C*h(uv) color solid Server Time
30 Jun 2024 15:04:16 EDT (-0400)
  L*C*h(uv) color solid (Message 33 to 42 of 82)  
<<< Previous 10 Messages Goto Latest 10 Messages Next 10 Messages >>>
From: Mike Horvath
Subject: Re: L*C*h(uv) color solid
Date: 20 Nov 2016 03:51:11
Message: <583163ff$1@news.povray.org>
On 11/19/2016 9:26 PM, clipka wrote:
> Am 20.11.2016 um 03:04 schrieb Mike Horvath:
>> On 11/19/2016 8:48 PM, clipka wrote:
>>> Am 20.11.2016 um 02:33 schrieb Mike Horvath:
>>>> On 11/18/2016 2:22 AM, Mike Horvath wrote:
>>>>> I would like to create a three-dimensional representation of the
>>>>> L*C*h(uv) color space in the form of a cylinder.
>>>>>
>>>>> How would I do that?
>>>>>
>>>>> I may limit myself to colors that also exist in the sRGB color space.
>>>>>
>>>>> Mike
>>>>
>>>> I guess my only option is to use individually painted voxels, as I don't
>>>> see how you can enter conditional statements into a function
>>>> declaration.
>>>
>>> Did you try the `select` function?
>>>
>>
>> No I didn't!
>>
>> Can I create and store local variables too?
>
> Nope; the virtual machine currently used by POV-Ray to execute
> user-defined functions was designed solely for genuine functions; it
> doesn't do anything remotely resembling programming.
>

Do you think I could make the shape using lots of little functions?

Mike


Post a reply to this message

From: clipka
Subject: Re: L*C*h(uv) color solid
Date: 20 Nov 2016 08:14:00
Message: <5831a198@news.povray.org>
Am 20.11.2016 um 06:51 schrieb Mike Horvath:

> Which other converter did you use, BTW? I need to do the same for
> LAB>XYZ and XYZ>RGB as well.

Actually it was a colour picker that auto-converted upon changing the
colour model:

http://davidjohnstone.net/pages/lch-lab-colour-gradient-picker


For the most common conversion needs I found this one earlier:

http://davengrace.com/dave/cspace/


Post a reply to this message

From: Mike Horvath
Subject: Re: L*C*h(uv) color solid
Date: 21 Nov 2016 12:32:00
Message: <58332f90@news.povray.org>
So, I created a bunch of functions. Now how do I turn them into pigments?

(See p.t.s-f)

Mike


Post a reply to this message

From: Mike Horvath
Subject: Re: L*C*h(uv) color solid
Date: 21 Nov 2016 15:04:24
Message: <58335348$1@news.povray.org>
On 11/21/2016 12:31 PM, Mike Horvath wrote:
> So, I created a bunch of functions. Now how do I turn them into pigments?
>
> (See p.t.s-f)
>
> Mike

Disregard. I already know how to create an approixmation of the pigment. 
Sorry.


Mike


Post a reply to this message

From: Mike Horvath
Subject: Re: L*C*h(uv) color solid
Date: 21 Nov 2016 16:31:35
Message: <583367b7$1@news.povray.org>
On 11/19/2016 3:25 PM, Le_Forgeron wrote:
> Le 19/11/2016 à 19:19, Mike Horvath a écrit :
>> On 11/19/2016 12:59 PM, Le_Forgeron wrote:
>>> Le 19/11/2016 à 18:47, Mike Horvath a écrit :
>>>>
>>>> I think it would be pretty easy to produce a macro that does all of the
>>>> above. But how do I turn that into a POV-Ray function? The function
>>>> needs to work as a color as well as an isosurface I think.
>>>
>>>
>>> Basic of povray: the shape is not bound to the texture (excepted for
>>> uv_mapping).
>>>
>>> Make the work for the shape, and separately the work to map 3D
>>> coordinates to colour.
>>>
>>
>> Okay. But how?
>
> Within the attached include file, you could replace uv_vertex with your
> computed position.
>
> The top macro is UVMeshable, first parameter is an object, just
> ignore/remove it
> The two others are the resolutions... you can simplify too for your
> usage (getting ride of uv_min & uv_max).
>
> mesh{
> UVMeshable...
>
> then you insert the uv_mapped texture (and I already provided some code
> for that part in this thread)
>
> et voila.
>

I don't understand how to use these macros. Do you have examples I can 
look at?

Mike


Post a reply to this message

From: Mike Horvath
Subject: Re: L*C*h(uv) color solid
Date: 23 Nov 2016 04:03:32
Message: <58355b64$1@news.povray.org>
On 11/18/2016 8:37 AM, Christian Froeschlin wrote:
> 1. Define three separate float functions yielding R, G, B separately
>
> f_R(x,y,z)
> f_B(x,y,z)
> f_G(x,y,z)
>
> 2. Create red / green / blue pigments from that using function
> pattern and red / green / blue color_maps
>
> 3. Join the 3 pigments into RGB pigment via "average" pattern.

With these three functions, do I fade them from a pure color to black, 
or a pure color to transparent?

Mike


Post a reply to this message

From: Mike Horvath
Subject: Re: L*C*h(uv) color solid
Date: 23 Nov 2016 04:05:06
Message: <58355bc2@news.povray.org>
On 11/18/2016 8:37 AM, Christian Froeschlin wrote:
> Still it would probably be useful to implement the coordinate
> transformation (including appropriate scaling of intervals) in
> a separate set of functions f_L, f_u, f_v since you need them
> multiple times in the definition of f_R, f_G, f_B.
>

Are you suggesting I use a parametric instead of an isosurface?

Mike


Post a reply to this message

From: Mike Horvath
Subject: Re: L*C*h(uv) color solid
Date: 23 Nov 2016 04:40:08
Message: <583563f8$1@news.povray.org>
On 11/23/2016 4:05 AM, Mike Horvath wrote:
> On 11/18/2016 8:37 AM, Christian Froeschlin wrote:
>> Still it would probably be useful to implement the coordinate
>> transformation (including appropriate scaling of intervals) in
>> a separate set of functions f_L, f_u, f_v since you need them
>> multiple times in the definition of f_R, f_G, f_B.
>>
>
> Are you suggesting I use a parametric instead of an isosurface?
>
> Mike

I think I would need a third parameter in addition to u and v to make it 
work.


Mike


Post a reply to this message

From: Mike Horvath
Subject: Re: L*C*h(uv) color solid
Date: 24 Nov 2016 14:09:50
Message: <58373afe$1@news.povray.org>
On 11/23/2016 8:51 PM, clipka wrote:
 > Am 24.11.2016 um 01:27 schrieb Mike Horvath:
 >> On 11/23/2016 7:22 PM, Christian Froeschlin wrote:
 >>> No threshold will give the desired result using the color
 >>> conversion function directly, as clipka explained you need
 >>> a define a "distance" function for this purpose.
 >>>
 >>> Alternatively you could try to render the clipped function
 >>> (set to 0 outside the gamut) as strongly scattering media but
 >>> it may be fiddly and you don't get the look of a "surface"
 >>> regarding finish and lighting etc.
 >>>
 >>
 >> What is a "distance" function?
 >>
 >> The "convertLCH2RGBb2(y*100,sqrt(x*x+z*z)*100,atan2d(x,z))" bit is what
 >> clipka showed me.
 >
 > You may need to deconstruct the problem into easy-to-handle building
 > blocks, and tackle each of them separately.
 >
 > One building block you need is a function that maps a single RGB colour
 > component to a distance-ish scalar telling you how "far away" the colour
 > component is from the valid range (this time, just for giggles, I'm
 > contructing the function in such a way that <0 is inside, >0 is outside):
 >
 >     #declare fD = function(C) { abs(C-0.5)-0.5 }
 >
 > Another building block you need is a function that combines three such
 > distance-ish scalars, such that you get a positive value if one or more
 > parameters is positive, or a negative value if all are negative, in a
 > manner that avoid steps:
 >
 >     #declare fDist = function(Dr,Dg,Db) { max(Dr,Dg,Db) }
 >
 >
 > That's kind of all you need to know about the "distance" functions;
 > however, those functions alone don't get you anywhere.
 >
 >
 > Another necessary building block is a set of functions that map Lch 
to RGB:
 >
 >     #declare fR = function(L,c,h) { ... }
 >     #declare fG = function(L,c,h) { ... }
 >     #declare fB = function(L,c,h) { ... }
 >
 > And the final building block is a set of functions that map 3D cartesian
 > space to Lch:
 >
 >     #declare fL = function(x,y,z) { y*100 }
 >     #declare fc = function(x,y,z) { sqrt(x*x+z*z)*100 }
 >     #declare fh = function(x,y,z) { atan2d(x,z) }
 >
 >
 > Once you have all these building blocks, all that's left is to plug them
 > all together.
 >
 > The final result to be compared to the threshold by the isosurface is
 > the result of the `fDist` function, so that's where you start:
 >
 >     isosurface {
 >       threshold 0
 >       function { fDist (Dr,Dg,Db) }
 >     }
 >
 > The isosurface doesn't know what `Dr`, `Dg` and `Db` are, but we know
 > they are supposed to be results of the `fD` function, using the three
 > colour channels as input:
 >
 >     isosurface {
 >       threshold 0
 >       function { fDist (
 >         fD (R),
 >         fD (G),
 >         fD (B)
 >       ) }
 >     }
 >
 > Again the isosurface doesn't know `R`, `G` and `B`:
 >
 >     isosurface {
 >       threshold 0
 >       function { fDist (
 >         fD ( fR (L,c,h) ),
 >         fD ( fG (L,c,h) ),
 >         fD ( fB (L,c,h) )
 >       ) }
 >     }
 >
 > Still not done yet, as the isosurface doesn't know `L`, `c` and `h` 
either:
 >
 >     isosurface {
 >       threshold 0
 >       function { fDist (
 >         fD ( fR (fL(x,y,z),fc(x,y,z),fh(x,y,z)) ),
 >         fD ( fG (fL(x,y,z),fc(x,y,z),fh(x,y,z)) ),
 >         fD ( fB (fL(x,y,z),fc(x,y,z),fh(x,y,z)) )
 >       ) }
 >     }
 >
 > Now we have only `x`, `y` and `z` left as parameters, which is what the
 > isosurface can handle.
 >
 >
 > For bonus points, you could eliminate the multiple invocation of
 > `fL(x,y,z)`, `fc(x,y,z)` and `fh(x,y,z)`. To this end, you need to
 > provide a function that does not compute these values itself, but rather
 > takes them as parameters:
 >
 >     #declare fFinal = function(L,c,h) { fDist (
 >       fD ( fR (L,c,h) ),
 >       fD ( fG (L,c,h) ),
 >       fD ( fB (L,c,h) )
 >     ) }
 >
 >     isosurface {
 >       threshold 0
 >       function { fFinal (fL(x,y,z),fc(x,y,z),fh(x,y,z)) }
 >     }
 >
 >
 > And of course you'll want to use different names; I chose the above for
 > brevity.
 >

Next issue: What is the best way to create an accurate pigment to paint
the isosurface?

I was thinking of repurposing the following:

//------------------------------
// HSL Cylinder

#declare CSolid_HSLCylinder_Hue = pigment
{
	function {-f_th(x,y,z)/pi/2}
	color_map
	{
		// need to replace these with calls to CHSL2RGB() or CH2RGB(), then
increase the number of steps
		[0/6 srgb <1,0,0,>]
		[1/6 srgb <1,1,0,>]
		[2/6 srgb <0,1,0,>]
		[3/6 srgb <0,1,1,>]
		[4/6 srgb <0,0,1,>]
		[5/6 srgb <1,0,1,>]
		[6/6 srgb <1,0,0,>]
	}
}
#declare CSolid_HSLCylinder_Saturation = pigment
{
	cylindrical
	pigment_map
	{
		[0 CSolid_HSLCylinder_Hue]
		[1 color srgb 1/2]
	}
	scale	(1 + CSolid_Offset)
}
#declare CSolid_HSLCylinder_Lightness = pigment
{
	gradient y
	pigment_map
	{
		[0/2 color srgb 0]
		[1/2 CSolid_HSLCylinder_Saturation]
		[2/2 color srgb 1]
	}
	scale		(1 + CSolid_Offset)
	translate	-y * CSolid_Offset/2
}
#declare CSolid_HSLCylinder_Pigment = pigment {CSolid_HSLCylinder_Lightness}

Except, in this case using LCH conversion formula to create the gradients:

	[0/6 srgb <convertLCH2RGBb1(50, 50, 0),convertLCH2RGBb2(50, 50,
0),convertLCH2RGBb3(50, 50, 0)>]
	[1/6 srgb <convertLCH2RGBb1(50, 50, 60),convertLCH2RGBb2(50, 50,
60),convertLCH2RGBb3(50, 50, 60)>]
	[2/6 srgb <convertLCH2RGBb1(50, 50, 120),convertLCH2RGBb2(50, 50,
120),convertLCH2RGBb3(50, 50, 120)>]
	[3/6 srgb <convertLCH2RGBb1(50, 50, 180),convertLCH2RGBb2(50, 50,
180),convertLCH2RGBb3(50, 50, 180)>]
	[4/6 srgb <convertLCH2RGBb1(50, 50, 240),convertLCH2RGBb2(50, 50,
240),convertLCH2RGBb3(50, 50, 240)>]
	[5/6 srgb <convertLCH2RGBb1(50, 50, 300),convertLCH2RGBb2(50, 50,
300),convertLCH2RGBb3(50, 50, 300)>]
	[6/6 srgb <convertLCH2RGBb1(50, 50, 360),convertLCH2RGBb2(50, 50,
360),convertLCH2RGBb3(50, 50, 360)>]


Is this maybe a bad idea?

Mike


Post a reply to this message

From: clipka
Subject: Re: L*C*h(uv) color solid
Date: 24 Nov 2016 14:33:30
Message: <5837408a$1@news.povray.org>
Am 24.11.2016 um 20:10 schrieb Mike Horvath:

> Next issue: What is the best way to create an accurate pigment to paint
> the isosurface?

The main problem to solve is that POV-Ray's mechanisms to generate
gradient-ish pigments only supports 1-dimensional gradients.

A common solution is to construct three 1-dimensional gradient-ish
pigments -- one for each colour component -- and then mix them together
using the `average` pseudo-pattern:

    #declare FinalPigment = pigment {
      average
      pigment_map {
        [ 1.0 RedPigment   ]
        [ 1.0 GreenPigment ]
        [ 1.0 BluePigment  ]
      }
    }

Each of the `RedPigment`, `GreenPigment` and `BluePigment` component
patterns is designed in such a way that it only has the corresponding
component set to non-zero.

An important thing to note here is that the `average` pseudo-pattern
does not add colours, but averages them; so in order to achieve the full
range of colours, the component patterns must have colour ranges from 0
to 3 for the corresponding channel:

    #declare RedPigment = pigment {
      function { fR(fL(x,y,z),fc(x,y,z),fh(x,y,z), }
      colour_map {
        [ 0.0 colour rgb <0,0,0> ]
        [ 1.0 colour rgb <3,0,0> ]
      }
    }

Note that there is no need for clipping the function result: This is
automatically achieved by the colour_map.


Post a reply to this message

<<< Previous 10 Messages Goto Latest 10 Messages Next 10 Messages >>>

Copyright 2003-2023 Persistence of Vision Raytracer Pty. Ltd.