Game Development Community

Shader on GUI controls?

by Kevin Rogers · in Torque 3D Professional · 09/16/2014 (1:13 pm) · 12 replies

I have searched around GG for any info, but it's pretty sparse, so. . .

Does anyone know how to hook up a shader to a GUI control? I need to be able to do effects like edge outlining, animated glow/highlighting; stuff like that.

#1
09/16/2014 (1:16 pm)
You'd end up doing a ton of work. The traditional way of doing that is with animated gui elements using sprite sheets and the like.
#2
09/16/2014 (3:16 pm)
Uh, thanks? Never mind how much work it entails or what the alternatives are. Does any one have experience/information with using shaders with GUI controls?


#3
09/16/2014 (4:07 pm)
You would have to hook up gui controls to use materials to achieve that.
#4
09/16/2014 (4:40 pm)
@Kevn - Sorry boss, like Tim says, Torque's GUI controls don't support materials and therefore shaders. Ergo, it is very unlikely that anyone has the experience or information you're looking for.

If one felt the unavoidable need to use shaders for GUI controls then Tim's suggestion is the direction I would head.
#5
09/16/2014 (4:57 pm)
Ok, thanks. Any suggestions for how to begin hooking up gui controls to use materials?
#6
09/16/2014 (5:06 pm)
I've got a series of silly questions:

What are you trying to accomplish? Is this for a in-game HUD elements? Or for menu items? Could you perhaps use SceneObjects as GUI elements and use a scene for the GUI (or, in the case of a HUD, add them to the current PlayGUI HUD)?

Mainly because I'm really not sure where the other road starts....
#7
09/16/2014 (5:25 pm)
First thing to realize is the onrender for the controls are using GFXDrawUtil that disables shaders and i believe uses fixed function code. SO your two options for starting would be:

1. Removed fixed function rendering of GFXDrawUtil and set it up to use materials. Create a basic material with a simple shader/material for drawing gui. Then create a way to override the material. Then you can setup the gui control to pass in a material to override the default.

2. In whatever controls you want to use shaders, replace the GFXDrawUtil with custom drawing code and use the material you setup in the control.

Either way your looking at moving gui from fixed function to programmable pipeline. In my opinion #1 is your best option. Its reusable and how GFXDrawUtil should work anyway.

If you go the #1 route take a look at GFXD3D9Device::setupGenericShaders(enum) This function on the DX side is disabling the shaders, but on the opengl side where you dont have fixed function it sets up generic shaders like i was talking about based on the passed in enum. DX should work this way too. You will need to do extra work on setting up the ability to override the generic material as the opengl side does not have that. You'll have to take a look at the opengl branch in beamng's github if you want to see how it works.
#8
09/16/2014 (9:58 pm)
@Richard: I have seen some cool menus done fully 3D, e.g. Metro 2033, but right now I just want some basic shader effects on my 2D GUI. And knowing that the 2D elements really are rendered in 3D (as an orthographic projection), I know it can be done.

@Tim: That's what I'm looking for! Thank you very much!

Honestly, I don't know what I'll come up with; there are plenty of things to spend time on, so if it gets too involved, it'll get backburnered for sure. But it is something that I would like to explore further.

#9
09/16/2014 (11:53 pm)
I think Andrew Mac did something similar to that, might want to contact him on IRC or something.
#10
09/17/2014 (5:25 am)
EDIT: I didn't read Tim's post before I made this one. I just skimmed the thread and saw my name and did a little write up. I'll leave it here in case it's useful.

You don't need a material to use a shader. You just need to call GFX->setShader before your render call (assuming we're not dealing with render instances, which in the case of GUI controls, we're not.)

The problem is, almost all the GUI controls are rendered through calls to GFXDrawUtil, which sets up the generic shaders for each render. Take for instance the button control:
github.com/GarageGames/Torque3D/blob/development/Engine/source/gui/buttons/guiBu...

Which is calling drawRectFill. Now check out these last two lines in drawRectFill:
github.com/GarageGames/Torque3D/blob/69838bdc8c9bc055b9b1ae76f42b0f28d2a33909/En...

If you were to replace mDevice->setupGenericShaders() call with mDevice->setShader(your shader) then it would render the control through that shader. The problem is these GFXDrawUtil commands are used extensively and you can't just alter the functions or lots of things will be running through your shader.

You could a) add an optional shader parameter to the GFXDrawUtil and build it so you can override the shader with a supplied for one for any particular call to GFXDrawUtil.

or b) write your own render function for your gui control like you see in the button control but don't use GFXDrawUtil. This allows you to set your own shader, do your own draw call, and have complete control over the result.
#11
09/17/2014 (8:30 am)
I'm aware that virtually everything in Torque is actually rendered in 3D. I agree that it can be done. But, I've seen hundreds of very cool menus that did not use anything more complex than normal "2D" animations.

My suggestions/questions are simply in the vein of "Torque's scene objects already support what you want, so it might be worth your time to leverage that" and not in the spirit of "you're being nonsensical, stop that now." Nor am I trying to imply that you aren't capable - I'm sure you are. I'm just a pragmatist and I was thinking that you might want to spend more time on game and less on revamping GUI rendering; I know I would.

TLDR: I'm just trying to find the "easy" solution man - not trying to be rude.
#12
09/17/2014 (9:58 pm)
@Andrew Mac: Thanks, good to know! I'm leaning towards B since it would be on custom controls anyway.

@Richard: Yeah, I didn't figure you were trying to be rude. . . although admittedly I was a little bugged: "Dude, stop trying to rain on my parade!" =) But yeah, like I said, if it gets too involved it'll get back-burnered in favor of more important things.