Grab Viewport With Alpha


#1

The GrabViewport script linked below is fantastic for game artists because it lets you take high res viewport screen grabs of assets with DX shaders applied. DX shaders don’t render, for those that don’t know.

http://www.laurenscorijn.com/viewportshader

The one thing that script is missing is the option to include an alpha channel, so when you bring it into Photoshop you can throw it on a custom background and make a presentation sheet.

Is this possible? Perhaps there is some viewport equivalent of a render buffer that can be tapped into?

Marmoset Toolbag includes alpha channels with its screen grabs, I’m just looking to do the same out of Max.


#2

it’s possible. usually i share my solutions. but that’s… kinda a treasure…
so, dig and you get it. just know it’s possible.


#3

Wouldn’t you access the framebuffer or Gbuffer or something, I’m guessing… and extract it from there somehow? I thought I read somewhere on this forum how to do that…


#4

One hacky way to do it would be to have a script take the screen shot, then put a white self-illuminated material on everything in your scene, set the viewport background to black, save that as the alpha, then reset everything back the way it was.


#5

Why not just put a pure green on the viewport background, grab that and key it in photoshop? Dunno, might be a silly solution :slight_smile:


#6

Thats a good idea too :slight_smile: I like those kind of ideas. They are sorta hacky, but prob. just as affective, and alot easier to do if you don’t have the knowledge.


#7

Have you looked at metaSL and QuickSilver? Or DirectX and QuickSilver? That should allow you to get realtime shaders that can render the same as the viewport representation. If you need DirectX Scene Shaders, that is a different story.

-Eric


#8

That’s exactly what I’ve been doing. Not silly at all, but I would like to either find or make a script that saves me the trouble.

Yep, I’m using DX shaders. Xoliul and 3PointShader. Those are the two big ones folks use. Shader FX if you’ve got the money to spend.


#9

:slight_smile: My attempt to do the grab viewport script with alpha channel. :slight_smile:
Note that the script is not very fast( the creating of the alpha channel is slowing it down)

Credits to Borislav “Bobo” Petrov and Dave Wortley.


  --******************************************************************************************************
  -- Created: 		29-05-2011
  -- Last Updated:	29-05-2011
  -- Version:			1.0
  --
  -- Author :  Kostadin Kotev / miau_u@yahoo.com /
  -- Version:  3ds max 2009 (should work in older versions too!)
  --
  -- Discription: 
  --	Grab the active viewport and include an alpha channel.
  --	IMPORTANT: The script is not very fast. :)
  --******************************************************************************************************
  -- MODIFY THIS AT YOUR OWN RISK
  
  macroscript miauuGrabViewport
  category:"miauu"
  tooltip:"Grab Viewport"
  buttonText:"Grab Viewport"
  (
  	local grab_viewpBMP
  	local defaultVbkgColor
  	local grab_alphaBMP
  	local tempBMP
  	local viewport_name
  	local mfn
  	local gct
  	local bmp_name
  --////	credits to Borislav "Bobo" Petrov (MaxScript reference)
  	--	get viewport name
  	viewport_name = viewport.GetType() as string
  	--	cut the string
  	viewport_name = substring viewport_name 6 (viewport_name.count-5)
  	
  	if viewport_name == "camera" then --	if the remaining string is "camera"
  	( 
  		gac = getActiveCamera() --	get the camera
  		viewport_name = gac.name --	get the name of the camera
  	)
  	--	get max file name
  	mfn = MaxFileName
  	
  	if mfn == "" then --	if there is no name
  		mfn = "Untitled" --	use "Untitled"
  	else
  		mfn = getFileNameFile mfn --	use the file name without .MAX extension
  	
  	--	get current frame time
  	gct = SliderTime as string 
  	--	build the output file name
  	bmp_name = "VPGRAB_"+ mfn +"_" +viewport_name + "_" + gct
  
  	--	Display file save dialog
  	bmp_name = getSaveFileName caption:"Save Viewport to:" filename:bmp_name \
  	types:"TGA(*.tga)|*.tga|PNG(*.png)|*.png|TIFF(*.tif)|*.tif|JPG(*.jpg)|*.jpg|BMP(*.bmp)|*.bmp|"
  --////
  	if bmp_name != undefined then	--	if user has confirmed / entered a valid name
  	( 
  		forcecompleteredraw dodisabled:true
  		theHold.begin()
  		--	grab the viewport
  		grab_viewpBMP = gw.getViewportDib()
  		--	make all visible objects white
  		for o in objects where not o.isHidden do
  		(
  			o.displayByLayer = false
  			o.showVertexColors = true
  		)
  		--	save the default viewport color
  			--	defaultVbkgColor = getVPortBGColor()		-- not worked in max2010
  		defaultVbkgColor = GetUIColor 41
  		--	set the viewport color to pure black
  			--	setVPortBGColor  ((color 0 0 0) as Point4)		--	not worked in max2010
  		SetUIColor 41 ((color 0 0 0) as Point4)
  		colorMan.repaintUI #repaintAll
  		--	grab the bitmap that will be used as alpha channel
  		grab_alphaBMP = gw.getViewportDib()
  		
  		theHold.cancel()
  		
  			--	setVPortBGColor  defaultVbkgColor	--	not worked in max2010
  		SetUIColor 41 defaultVbkgColor
  		colorMan.repaintUI #repaintAll
  		
  	--////	credits to DaveWortley.
  		--create new temporary bitmap
  		tempBMP = bitmap grab_viewpBMP.width grab_viewpBMP.height
  
  		for i = 1 to grab_viewpBMP.height do
  		(
  			AR_thepixels_A = Getpixels grab_viewpBMP [0,i] grab_viewpBMP.width
  			AR_thepixels_B = Getpixels grab_alphaBMP [0,i] grab_alphaBMP.width
  			
  			for j = 1 to AR_thepixels_A.count do
  			(
  				alfaVal = 0.0
  				if AR_thepixels_B[j] == (color 0 0 0) do
  				(
  					swap AR_thepixels_A[j].a alfaVal
  				)
  			)
  			setpixels tempBMP [0,i] AR_thepixels_A
  		)
  		--close the original images so we can overwrite them
  		close grab_viewpBMP
  		close grab_alphaBMP	
  	--////
  		tempBMP.filename = bmp_name	--	set output name to the one entered in the save file dialog
  		save tempBMP
  		Close tempBMP
  		grab_viewpBMP = undefined
  		grab_alphaBMP = undefined
  		tempBMP = undefined
  	)
  
  	freeSceneBitmaps()
  	gc()
  )
  

#10

ha - just stumbled over that thread …

as i’m writing a preview creation script myself right now, this “make all obj’s temporary white on black background and grab for alpha” idea might call up my efforts to implement alpha channel support again…

thanks for this idea … :wink:


#11

I added the ability to take a screenshot that’s larger than the screen resolution.

--******************************************************************************************************
-- Created: 		29-05-2011
-- Last Updated:	29-05-2011
-- Version:			1.1
--
-- Author :  Kostadin Kotev / miau_u@yahoo.com /
-- Version:  3ds max 9 and up
--
-- Discription: 
--	Grab the active viewport and include an alpha channel. Use the spinners to expand the active viewport.
--	IMPORTANT: The script is not very fast. :)
--	
--******************************************************************************************************
-- MODIFY THIS AT YOUR OWN RISK

macroscript miauuGrabViewport
category:"miauu"
tooltip:"Grab Viewport"
buttonText:"Grab Viewport"
(
	global rol_miauuGrabViewport
	try(destroyDialog rol_miauuGrabViewport)catch()
	rollout rol_miauuGrabViewport "miauu's Grab Viewport v1.1"
	(
		local grab_viewpBMP
		local defaultVbkgColor
		local grab_alphaBMP
		local tempBMP
		local viewport_name
		local mfn
		local gct
		local bmp_name
		local winSizeX = gw.getWinSizeX() as float
		local winSizeY = gw.getWinSizeY() as float
		local ratio = (winSizeX/winSizeY)	
		
		spinner spn_height "Viewport height:" range:[1,999999,winSizeY] type:#float scale:1
		spinner spn_width "Viewport width:" range:[1,999999,winSizeX] type:#float scale:1
		button btn_grabViewport "Grab Viewport"
		
		on btn_grabViewport pressed do
		(
		--////	credits to Borislav "Bobo" Petrov (MaxScript reference)
			--	get viewport name
			viewport_name = viewport.GetType() as string
			--	cut the string
			viewport_name = substring viewport_name 6 (viewport_name.count-5)
			
			if viewport_name == "camera" then --	if the remaining string is "camera"
			( 
				gac = getActiveCamera() --	get the camera
				viewport_name = gac.name --	get the name of the camera
			)
			--	get max file name
			mfn = MaxFileName
			
			if mfn == "" then --	if there is no name
				mfn = "Untitled" --	use "Untitled"
			else
				mfn = getFileNameFile mfn --	use the file name without .MAX extension
			
			--	get current frame time
			gct = SliderTime as string 
			--	build the output file name
			bmp_name = "VPGRAB_"+ mfn +"_" +viewport_name + "_" + gct

			--	Display file save dialog
			bmp_name = getSaveFileName caption:"Save Viewport to:" filename:bmp_name \
			types:"TGA(*.tga)|*.tga|PNG(*.png)|*.png|TIFF(*.tif)|*.tif|JPG(*.jpg)|*.jpg|BMP(*.bmp)|*.bmp|"
		--////
			if bmp_name != undefined then	--	if user has confirmed / entered a valid name
			( 
				--	store the viewport height and width
				curVPheight = gw.getWinSizeY()
				curVPwidth = gw.getWinSizeX()				
				--	expand the viewport
				gw.setPos 0 0 spn_width.value spn_height.value
				forcecompleteredraw dodisabled:true
				theHold.begin()
				--	grab the viewport
				grab_viewpBMP = gw.getViewportDib()
				--	make all visible objects white
				for o in objects where not o.isHidden do
				(
					o.displayByLayer = false
					o.showVertexColors = true
				)
				--	save the default viewport color
					--	defaultVbkgColor = getVPortBGColor()		-- not worked in max2010
				defaultVbkgColor = GetUIColor 41
				--	set the viewport color to pure black
					--	setVPortBGColor  ((color 0 0 0) as Point4)		--	not worked in max2010
				SetUIColor 41 ((color 0 0 0) as Point4)
				colorMan.repaintUI #repaintAll
				--	grab the bitmap that will be used as alpha channel
				grab_alphaBMP = gw.getViewportDib()
				
				theHold.cancel()
				
					--	setVPortBGColor  defaultVbkgColor	--	not worked in max2010
				SetUIColor 41 defaultVbkgColor
				colorMan.repaintUI #repaintAll
				
			--////	credits to DaveWortley.
				--create new temporary bitmap
				tempBMP = bitmap grab_viewpBMP.width grab_viewpBMP.height

				for i = 1 to grab_viewpBMP.height do
				(
					AR_thepixels_A = Getpixels grab_viewpBMP [0,i] grab_viewpBMP.width
					AR_thepixels_B = Getpixels grab_alphaBMP [0,i] grab_alphaBMP.width
					
					for j = 1 to AR_thepixels_A.count do
					(
						alfaVal = 0.0
						if AR_thepixels_B[j] == (color 0 0 0) do
						(
							swap AR_thepixels_A[j].a alfaVal
						)
					)
					setpixels tempBMP [0,i] AR_thepixels_A
				)
				--close the original images so we can overwrite them
				close grab_viewpBMP
				close grab_alphaBMP	
			--////
				tempBMP.filename = bmp_name	--	set output name to the one entered in the save file dialog
				save tempBMP
				Close tempBMP
				grab_viewpBMP = undefined
				grab_alphaBMP = undefined
				tempBMP = undefined
			)
			freeSceneBitmaps()
			gc()
			--	restore the viewport
			gw.setPos 0 0 curVPwidth curVPheight
			forcecompleteredraw dodisabled:true
		)
		
		on spn_height changed val do
		(
			spn_width.value = spn_height.value*ratio		
		)
		on spn_width changed val do
		(
			spn_height.value = spn_width.value/ratio		
		)
	)
	createdialog rol_miauuGrabViewport style:#(#style_titlebar, #style_sysmenu, #style_toolwindow) 
)

#12

Nice, here’s a little idea: Why not send the image to photoshop?

A few interesting links i found:

http://www.just-joshing.com/2009/06/03/open-bitmaps-in-photoshop/
http://area.autodesk.com/forum/autodesk-3ds-max/maxscript/max-last-render-to-photoshop/


#13

just a short question ( as i did’nt test and install the script … )

i guess i does not work in Nitrous / Max2012 ? I see in the source that you are using gw.setPos, but that ( plus other gw related maxscript commands) is broken / do not work in nitrous …

UPDATE:
okay i tested it in Max 2012, and as expected it does’nt work, not even in Direct3D mode

in D3D mode it grabs an empty viewport, you might be able to repair this by doing the actual grabbing in a viewport redraw callback (see further docs [here (Max online Help)](here http://docs.autodesk.com/3DSMAX/14/ENU/MAXScript%20Help%202012/files/GUID-1B088FF0-6A36-420E-9F37-F0DBE9FB267-2008.htm) )

In Nitrous display mode the grabbing works, but the grabbed size always sticks to the size of the currently active viewport. ( As i mentioned above SetPos does’nt work in nitrous)
Additionally all shadows and AO are there in the alpha channel ( because of the method how you generate it ) . I guess you would have to switch off all advanced lighting and rendering options in the viewport for you alpha pass first…

Otherwise a reall usefull script :thumbsup:


#14

@tassel, one guy from policuont forum will add new things to the script - go to post #10.
May be hi will add “send the image to photoshop”. :slight_smile:

I can,t use max2012(my pc is too old). If you don’t mind - can you send me the maxscript help file from max2012, so I can see what is the new in maxscript for this 3ds max release. :slight_smile:


#15

ahh i see -the link is broken in that previous post of mine …

you can grab all from here (first entries)
http://usa.autodesk.com/adsk/servlet/item?siteID=123112&id=16707768

either browse online or download the maxscript help zip, you can extract it locally and browse it there ( just html files … )

Here’s the entry i wanted to link inmy previous post , but failed …
http://docs.autodesk.com/3DSMAX/14/ENU/MAXScript%20Help%202012/files/GUID-1B088FF0-6A36-420E-9F37-F0DBE9FB267-2008.htm


#16

@spacefrog, thank you for the links.


#17

This thread has been automatically closed as it remained inactive for 12 months. If you wish to continue the discussion, please create a new thread in the appropriate forum.