How To ... Create a MonoChrome RenderEffect(如何创建灰度渲染效果)
2010-04-07 23:05
423 查看
How To ... Create a MonoChrome RenderEffect
MAXScript:
plugin RenderEffect MonoChrome
name:
"MonoChrome"
classID:#(0x9e6e9e77, 0xbe815df4)
(
rollout
about_rollout
"About..."
(
label about_label
"MonoChrome Filter"
)
on
apply r_image progressCB:
do
(
progressCB.setTitle
"MonoChrome Effect"
local
oldEscapeEnable = escapeEnable
escapeEnable = false
bmp_w = r_image.width
bmp_h = r_image.height
for
y = 0
to
bmp_h-1
do
(
if
progressCB.progress y (bmp_h-1)
then
exit
pixel_line = getPixels r_image [0,y] bmp_w
for
x = 1
to
bmp_w
do
(
p_v
= pixel_line[x].value
pixel_line[x] = color p_v p_v p_v pixel_line[x].alpha
)--end x loop
setPixels r_image [0,y] pixel_line
)
--end y loop
escapeEnable = oldEscapeEnable
)
--end on apply
)
--end plugin
Step-By-Step:
plugin RenderEffect MonoChrome
name:"MonoChrome"
classID:#(0x9e6e9e77, 0xbe815df4)
(
A
scripted plug-in starts with the constructor plugin
followed by the superclass of the scripted plug-in (
renderEffect
) and the class name of
the plug-in (
MonoChrome
). In addition, we have
to provide the name
which will appear in the effects list, and a unique classID
.
The
classID
is used by 3ds
Max
to
recognize the plug-in class when loading the scene. To generate a new unique ID,
you can use the GenclassID
() method in the Listener
and copy the result into the script.
To keep
all versions of this plug-in compatible around the world, it is recommended to
copy the above classID though.
Scripted
Plug-ins
Scripted RenderEffect
Plug-ins
classID
rollout about_rollout "About..."
(
label about_label "MonoChrome Filter"
)
The
plug-in will have no controls. We will create a very simple rollout containing a
single line of text just to show the user he has loaded something.
Rollout
Clauses
Label
on
apply r_image progressCB: do
(
A
renderEffect plug-in has a main handler which will be executed each time the
effect is applied to the image. The image buffer of the renderer will be passed
as the only parameter to the handler - we use a user variable named
r_image
which will contain the image we will work on. Also, we define a progress
callback object in order to update the main renderer progress bar while
processing the image.
Scripted RenderEffect
Plug-ins
RenderEffect Progress
Callback Mechanism
progressCB.setTitle "MonoChrome Effect"
Using
the setTitle
method in the progressCB
object, we define the
name to be displayed in the Rendering Effect progress window resp. the Renderer
Progress window during processing. In the former case, the line will read
"Currently Updating: MonoChrome Effect". In the latter case, the line will read
"Current Task: MonoChrome Effect".
RenderEffect Progress
Callback Mechanism
local oldEscapeEnable = escapeEnable
escapeEnable = false
In order
to be able to capture and process the pressing of the Escape key during the main
loop of the effect without actually breaking the script execution, we will have
to disable the MAXScript Escape key handling. For this purpose we will store the
current state of the Escape handling (
true
or false
) in a temporary user variable and then assign false
to the MAXScript System Global
variable controlling the Escape handling
. Later on, after the
main loop, we will set it back to its original state stored in the
oldEscapeEnable
user
variable.
bmp_w = r_image.width
We will
need the width
of the rendered image. We store the .width
property of the image in the user variable bmp_w
.
bmp_h = r_image.height
We will
also need the height
of the rendered image. We store the .height
property of the image in the user variable bmp_h
.
bitmap.height
for y = 0 to bmp_h-1 do
(
We will
loop through all lines in the image. Image pixel access requires 0-based
indexing, this means the upper left pixel of a 640x480 image has coordinates
[0,0] and the bottom right pixel has coordinates [639,479]. The variable
y
will be assigned the values from 0 to the height of the image minus 1 each time
the for loop repeats itself.
For Loop
if
progressCB.progress y (bmp_h-1) then exit
This
line does two things:
Since
the .
progress
method of the progress callback object returns true
when the user has pressed Escape and false
otherwise, we check the return value and exit the loop when
true
is returned. This will bring us to the line after the end of the
y
loop.
The same
method also accepts two arguments ?the current value and the max. value needed
to calculate the progress percentage. In our case, we supply the current line
and the total number of lines. For example, if we are on line 300 and the bitmap
has 600 lines, the progress bar will show 50% done...
RenderEffect Progress
Callback Mechanism
Loop Exit
pixel_line = getPixels r_image [0,y] bmp_w
The
getpixels
function reads pixels from the specified file starting at the position
supplied by the Point2 value and reads the number of pixels specified by the
last value. The result will be assigned as array to the user variable
pixel_line
. We start reading at the
first pixel to the left and read all bmp_w
pixels - a whole scanline contains as many pixels as the width of the
image.
getPixels
for x = 1 to bmp_w do
(
Now we
can loop through all values in the array of pixel values. Because arrays in
MAXScript are 1-Based, we count from 1 to the width of the image.
For Loop
p_v = pixel_line[x].value
pixel_line[x] = color p_v p_v p_v pixel_line[x].alpha
This is
the actual core of the code - we get the .Value property of the color (its
greyscale intensity) and generate a new color value with Red, Green and Blue
values equal to the .Value of the original pixel. To keep the alpha channel
untouched, we just add the original alpha value to the RGBA color. We store the
result at the same position in the array and thus overwrite the color
information with a grayscale version!
Color
Values
)--end x loop
setPixels r_image [0,y] pixel_line
After
processing all pixels of a scanline, the setpixels
function writes the array pixel_line
containing the new
grayscale values back into the image starting at the same position. This
overwrites the colors in the current line y
.
setPixels
)--end y loop
We are
ready with the loops and the whole bitmap has been changed. The on
apply
handler will return the resulting bitmap to the system and it will be shown in
the Virtual Frame Buffer.
escapeEnable = oldEscapeEnable
As
mentioned before, we will have to set the MAXScript Escape key handling to its
original state before the render effect loop.
)--end on apply
)--end plugin
Using the Script
After
evaluating the script, a new plug-in effect called "MonoChrome" will appear on
the Renderer > Effects... > Add... list. Add it to the effects queue and
render the scene. The result will be a monochrome version of the rendering. Note
that scripted renderEffects are relatively slow compared to "real" plug-ins
written with the SDK, but are very flexible and fast to prototype.
In the
Virtual Frame Buffer, you can take a look at the Alpha and Monochrome version of
the image - the Alpha should be unchanged, and the Monochrome version should be
identical to the RGB image generated by the renderEffect.
Where to go from here
A
relatively easy change to this basic script would be the change of only every
Nth line of the bitmap. By just adding a by
2
option
to the for y loop you will affect only every second line!
for y = 0 to bmp_h-1 by 2 do
Adding
by
2
to the
x loop too will affect only a grid of pixels! You could play with values higher
than 2, or even add UI controls for user-defined line and pixel
steps.
A more
complex change to the script would be the tinting of the monochrome image by
using different proportions of the monochrome value in the R, G and B channels.
To do this, you could add a rollout and a paramBlock defining 3 Float values and
let the user specify how much of each channel to be used. Then multiply the p_v
value by the 3 values while assigning them to the R, G and B values of the
image.
MAXScript:
plugin RenderEffect MonoChrome
name:
"MonoChrome"
classID:#(0x9e6e9e77, 0xbe815df4)
(
rollout
about_rollout
"About..."
(
label about_label
"MonoChrome Filter"
)
on
apply r_image progressCB:
do
(
progressCB.setTitle
"MonoChrome Effect"
local
oldEscapeEnable = escapeEnable
escapeEnable = false
bmp_w = r_image.width
bmp_h = r_image.height
for
y = 0
to
bmp_h-1
do
(
if
progressCB.progress y (bmp_h-1)
then
exit
pixel_line = getPixels r_image [0,y] bmp_w
for
x = 1
to
bmp_w
do
(
p_v
= pixel_line[x].value
pixel_line[x] = color p_v p_v p_v pixel_line[x].alpha
)--end x loop
setPixels r_image [0,y] pixel_line
)
--end y loop
escapeEnable = oldEscapeEnable
)
--end on apply
)
--end plugin
Step-By-Step:
plugin RenderEffect MonoChromename:"MonoChrome"
classID:#(0x9e6e9e77, 0xbe815df4)
(
A
scripted plug-in starts with the constructor plugin
followed by the superclass of the scripted plug-in (
renderEffect
) and the class name of
the plug-in (
MonoChrome
). In addition, we have
to provide the name
which will appear in the effects list, and a unique classID
.
The
classID
is used by 3ds
Max
to
recognize the plug-in class when loading the scene. To generate a new unique ID,
you can use the GenclassID
() method in the Listener
and copy the result into the script.
To keep
all versions of this plug-in compatible around the world, it is recommended to
copy the above classID though.
Scripted
Plug-ins
Scripted RenderEffect
Plug-ins
classID
rollout about_rollout "About..."
(
label about_label "MonoChrome Filter"
)
The
plug-in will have no controls. We will create a very simple rollout containing a
single line of text just to show the user he has loaded something.
Rollout
Clauses
Label
on
apply r_image progressCB: do
(
A
renderEffect plug-in has a main handler which will be executed each time the
effect is applied to the image. The image buffer of the renderer will be passed
as the only parameter to the handler - we use a user variable named
r_image
which will contain the image we will work on. Also, we define a progress
callback object in order to update the main renderer progress bar while
processing the image.
Scripted RenderEffect
Plug-ins
RenderEffect Progress
Callback Mechanism
progressCB.setTitle "MonoChrome Effect"
Using
the setTitle
method in the progressCB
object, we define the
name to be displayed in the Rendering Effect progress window resp. the Renderer
Progress window during processing. In the former case, the line will read
"Currently Updating: MonoChrome Effect". In the latter case, the line will read
"Current Task: MonoChrome Effect".
RenderEffect Progress
Callback Mechanism
local oldEscapeEnable = escapeEnable
escapeEnable = false
In order
to be able to capture and process the pressing of the Escape key during the main
loop of the effect without actually breaking the script execution, we will have
to disable the MAXScript Escape key handling. For this purpose we will store the
current state of the Escape handling (
true
or false
) in a temporary user variable and then assign false
to the MAXScript System Global
variable controlling the Escape handling
. Later on, after the
main loop, we will set it back to its original state stored in the
oldEscapeEnable
user
variable.
bmp_w = r_image.width
We will
need the width
of the rendered image. We store the .width
property of the image in the user variable bmp_w
.
bmp_h = r_image.height
We will
also need the height
of the rendered image. We store the .height
property of the image in the user variable bmp_h
.
bitmap.height
for y = 0 to bmp_h-1 do
(
We will
loop through all lines in the image. Image pixel access requires 0-based
indexing, this means the upper left pixel of a 640x480 image has coordinates
[0,0] and the bottom right pixel has coordinates [639,479]. The variable
y
will be assigned the values from 0 to the height of the image minus 1 each time
the for loop repeats itself.
For Loop
if
progressCB.progress y (bmp_h-1) then exit
This
line does two things:
Since
the .
progress
method of the progress callback object returns true
when the user has pressed Escape and false
otherwise, we check the return value and exit the loop when
true
is returned. This will bring us to the line after the end of the
y
loop.
The same
method also accepts two arguments ?the current value and the max. value needed
to calculate the progress percentage. In our case, we supply the current line
and the total number of lines. For example, if we are on line 300 and the bitmap
has 600 lines, the progress bar will show 50% done...
RenderEffect Progress
Callback Mechanism
Loop Exit
pixel_line = getPixels r_image [0,y] bmp_w
The
getpixels
function reads pixels from the specified file starting at the position
supplied by the Point2 value and reads the number of pixels specified by the
last value. The result will be assigned as array to the user variable
pixel_line
. We start reading at the
first pixel to the left and read all bmp_w
pixels - a whole scanline contains as many pixels as the width of the
image.
getPixels
for x = 1 to bmp_w do
(
Now we
can loop through all values in the array of pixel values. Because arrays in
MAXScript are 1-Based, we count from 1 to the width of the image.
For Loop
p_v = pixel_line[x].value
pixel_line[x] = color p_v p_v p_v pixel_line[x].alpha
This is
the actual core of the code - we get the .Value property of the color (its
greyscale intensity) and generate a new color value with Red, Green and Blue
values equal to the .Value of the original pixel. To keep the alpha channel
untouched, we just add the original alpha value to the RGBA color. We store the
result at the same position in the array and thus overwrite the color
information with a grayscale version!
Color
Values
)--end x loop
setPixels r_image [0,y] pixel_line
After
processing all pixels of a scanline, the setpixels
function writes the array pixel_line
containing the new
grayscale values back into the image starting at the same position. This
overwrites the colors in the current line y
.
setPixels
)--end y loop
We are
ready with the loops and the whole bitmap has been changed. The on
apply
handler will return the resulting bitmap to the system and it will be shown in
the Virtual Frame Buffer.
escapeEnable = oldEscapeEnable
As
mentioned before, we will have to set the MAXScript Escape key handling to its
original state before the render effect loop.
)--end on apply
)--end plugin
Using the Script
Afterevaluating the script, a new plug-in effect called "MonoChrome" will appear on
the Renderer > Effects... > Add... list. Add it to the effects queue and
render the scene. The result will be a monochrome version of the rendering. Note
that scripted renderEffects are relatively slow compared to "real" plug-ins
written with the SDK, but are very flexible and fast to prototype.
In the
Virtual Frame Buffer, you can take a look at the Alpha and Monochrome version of
the image - the Alpha should be unchanged, and the Monochrome version should be
identical to the RGB image generated by the renderEffect.
Where to go from here
Arelatively easy change to this basic script would be the change of only every
Nth line of the bitmap. By just adding a by
2
option
to the for y loop you will affect only every second line!
for y = 0 to bmp_h-1 by 2 do
Adding
by
2
to the
x loop too will affect only a grid of pixels! You could play with values higher
than 2, or even add UI controls for user-defined line and pixel
steps.
A more
complex change to the script would be the tinting of the monochrome image by
using different proportions of the monochrome value in the R, G and B channels.
To do this, you could add a rollout and a paramBlock defining 3 Float values and
let the user specify how much of each channel to be used. Then multiply the p_v
value by the 3 values while assigning them to the R, G and B values of the
image.
相关文章推荐
- how to sign an assembly with a strong name & how to create a pair key怎样通过强名给程序集签名以及如何创建钥匙对?
- How to create a zip file in NetSuite SuiteScript 2.0 如何在现有SuiteScript中创建和下载ZIP压缩文档
- BW--如何创建一个BW的数据源(How to Create a Generic Datasource)
- [转]how to sign an assembly with a strong name & how to create a pair key怎样通过强名给程序集签名以及如何创建钥匙对?
- BW--如何创建一个BW的数据源(How to Create a Generic Datasource)
- How To Create Custom Skins For DotText(如何为DotText创建自定义风格的皮肤)
- RevitAPI: 如何创建云线?How to create RevisionCloud
- jQuery:如何创建一个最基本的插件(How to Create a Basic Plugin)
- 如何在SharePoint 2013 创建Power pivot 库(How to create a PowerPivot Gallery )及错误解决方法
- How to create an XTR file from XML in Delphi XE4 using XML Mapper?(delphi中如何通过xmlmapper创建xtr文件)
- 如何创建一个基本的魔兽全图外挂 HowTo create a basic Maphack by Chaotic
- 如何创建软链接 how to create a symbolic link in clearcase
- BW--如何创建一个BW的数据源(How to Create a Generic Datasource)
- BW--如何创建一个BW的数据源(How to Create a Generic Datasource)
- SAP-MM-02 How To Create A Purchasing Order 创建采购订单
- 如何在Solaris下面build Mono(How to build Mono on Solaris)
- Android中实现振动效果 (How to Imeplement Vibration Effect In Andoid)
- MaxScript Plug-in 如何创建反色渲染效果
- How to Create a Self Signed Certificate in IIS 7& Chrome setting
- Ray Kurzweil-How to create a mind(如何创造思维)