A request for a simple example of using shaders
Moderators: winston, another_commander
- Shipbuilder
- ---- E L I T E ----
- Posts: 877
- Joined: Thu May 10, 2012 9:41 pm
- Location: Derby
A request for a simple example of using shaders
I was wondering if anyone would be willing and able to post a `simple` example of how to specify shaders for models used in oxps.
What I would be looking for if possible would be as very basic example possibly with a few notes of explanation.
As a suggestion perhaps just a cube with the following -
1) One face flashing from say green to black.
2) Another face gradually changing colour from red, through orange and then to yellow.
3) An example of how code can be used in conjunction with shaders for example one face changing colour gradually as the speed increases.
What I would be looking for if possible would be as very basic example possibly with a few notes of explanation.
As a suggestion perhaps just a cube with the following -
1) One face flashing from say green to black.
2) Another face gradually changing colour from red, through orange and then to yellow.
3) An example of how code can be used in conjunction with shaders for example one face changing colour gradually as the speed increases.
The GalTech Industries Corporation - Building ships to populate the galaxies.
Increase the variety of ships within your Ooniverse by downloading my OXPs
Flying the [wiki]Serpent_Class_Cruiser[/wiki] "Thargoid's Bane"
Increase the variety of ships within your Ooniverse by downloading my OXPs
Flying the [wiki]Serpent_Class_Cruiser[/wiki] "Thargoid's Bane"
- Griff
- Oolite 2 Art Director
- Posts: 2483
- Joined: Fri Jul 14, 2006 12:29 pm
- Location: Probably hugging his Air Fryer
Re: A request for a simple example of using shaders
I can write up some of these examples for you if you like but probably not until the weekend if you can hang on that long, i'm not sure about how to do the first shader with the surface switching between 2 different colours, I imagine something some thing based on the timer code from Jens animated billboard shader could do this, hmm...
Wiki homepage for my OXP: http://wiki.alioth.net/index.php/Griff_Industries
Re: A request for a simple example of using shaders
The third one is fairly standard engine heat shader code - there are several examples of that around (my Vortex for example, plus most of Griff's ships I think).
I have an example around somewhere of a cube whose face image changes as its energy decreases (ie when you shoot it). It's not quite what you wanted, but you're welcome to it if it'd be useful (the code for it is in my Swarm OXP as well).
I have an example around somewhere of a cube whose face image changes as its energy decreases (ie when you shoot it). It's not quite what you wanted, but you're welcome to it if it'd be useful (the code for it is in my Swarm OXP as well).
My OXPs via Boxspace or from my Wiki pages .
Thargoid TV
Dropbox Referral Link
Thargoid TV
Dropbox Referral Link
- Shipbuilder
- ---- E L I T E ----
- Posts: 877
- Joined: Thu May 10, 2012 9:41 pm
- Location: Derby
Re: A request for a simple example of using shaders
Wow that would be great thanks Griff much appreciated.
I think that once I get my head around a couple of simple examples I should hopefully get to understand how these things work.
I think that once I get my head around a couple of simple examples I should hopefully get to understand how these things work.
The GalTech Industries Corporation - Building ships to populate the galaxies.
Increase the variety of ships within your Ooniverse by downloading my OXPs
Flying the [wiki]Serpent_Class_Cruiser[/wiki] "Thargoid's Bane"
Increase the variety of ships within your Ooniverse by downloading my OXPs
Flying the [wiki]Serpent_Class_Cruiser[/wiki] "Thargoid's Bane"
- Shipbuilder
- ---- E L I T E ----
- Posts: 877
- Joined: Thu May 10, 2012 9:41 pm
- Location: Derby
Re: A request for a simple example of using shaders
That would be fantastic thanks Thargoid.
The GalTech Industries Corporation - Building ships to populate the galaxies.
Increase the variety of ships within your Ooniverse by downloading my OXPs
Flying the [wiki]Serpent_Class_Cruiser[/wiki] "Thargoid's Bane"
Increase the variety of ships within your Ooniverse by downloading my OXPs
Flying the [wiki]Serpent_Class_Cruiser[/wiki] "Thargoid's Bane"
- Shipbuilder
- ---- E L I T E ----
- Posts: 877
- Joined: Thu May 10, 2012 9:41 pm
- Location: Derby
Re: A request for a simple example of using shaders
Is there a list of events/conditions that can be used in conjunction with shaders ?
For example I know that shader effects can be linked to a ship's energy levels, speed and I think laser temperature.
For example I know that shader effects can be linked to a ship's energy levels, speed and I think laser temperature.
The GalTech Industries Corporation - Building ships to populate the galaxies.
Increase the variety of ships within your Ooniverse by downloading my OXPs
Flying the [wiki]Serpent_Class_Cruiser[/wiki] "Thargoid's Bane"
Increase the variety of ships within your Ooniverse by downloading my OXPs
Flying the [wiki]Serpent_Class_Cruiser[/wiki] "Thargoid's Bane"
- Commander McLane
- ---- E L I T E ----
- Posts: 9520
- Joined: Thu Dec 14, 2006 9:08 am
- Location: a Hacker Outpost in a moderately remote area
- Contact:
Re: A request for a simple example of using shaders
Have you seen the relevant Wiki pages? [wiki]Shaders in Oolite[/wiki] and Shaders in Oolite: uniforms? I guess they should answer most of your questions. There is for instance a list on the latter page. I don't know, however, how up to date they are.
By the way: I found these pages simply on the scripting category index page, where you find everything related to creating OXPs.
By the way: I found these pages simply on the scripting category index page, where you find everything related to creating OXPs.
- submersible
- Commodore
- Posts: 264
- Joined: Thu Nov 10, 2011 7:49 am
Re: A request for a simple example of using shaders
And now that you know how to fish.. since I have just been reading up on those effects , the interesting uniforms you're looking for are , , .
Code: Select all
hullHeatLevel
Code: Select all
laserHeatLevel
Code: Select all
speedFactor
Povray Planets - Planet textures for your galaxy
- Griff
- Oolite 2 Art Director
- Posts: 2483
- Joined: Fri Jul 14, 2006 12:29 pm
- Location: Probably hugging his Air Fryer
Re: A request for a simple example of using shaders
Here's Example one - Cube with one side switching colour between red & green
I've not included any lighting calculations in this example so the shader code is as short as possible, here's the vertex shader, it's just a text file saved in this case with the file extension .vertex and can be opened in any text editor
This simple vertex shader just calculates and passes the texture cooordinates for the current polygon fragment to the fragment shader as a vec2 called 'vTexCoord'
A 'vec' is just a collection of floating point numbers grouped together under a single variable name and since a texture is just a flat 2d image with an X axis (width) and a Y axis (height) then we only need 2 numbers to describe any pixels position on it so we use a vec2 to hold this data.
When we get to the fragment shader we're going to store colours using vec4's. Since a colour needs 4 components to describe it (the Red colour Value, the Green colour value, the blue Colour Value and the Alpha (Transparency) value we'll need four numbers to store those (and XYZ vertex positions could be stored in a vec3 if this vertex shader was going to be doing any transforms on the actual objects geometry.
To pass a vec to the fragment shader write 'varying' before its definition, see the line varying vec2 vTexCoord; above, this exact same line needs to be duplicated in the fragment shader to complete the 'link'.
You can pass data from the vertex shader to the fragment shader but not the other way around.
gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex; is dealing with the objects geometry, i must confess i don't really know what this is doing but it's a line that needs to be in the shader otherwise the whole thing fails to compile, 'gl_position' 'gl_ModelViewProjectionMatrix' and 'gl_Vertex' are all reserved openGl keywords
The shader needs to be saved to your OXP's Shaders folder (file and folder names are case sensitive) and listed in your ships Shader definitions in shipdata.plist
eg see lines 15 & 16 in shipdata.plist in Example_one_no_lighting.oxp
Here's the fragment shader, notice the 'varying vec2 vTexCoord;' line linking this vec2 back to the same named one from the vertex shader.
To work in an useful way shaders often need links back to Oolite's game engine, these links are called 'Uniforms' and are defined in your shader and also in your shipdata.plist. Textures need to be sent from Oolite to your shader as uniforms, see the lines
uniform sampler2D uDiffuseMap; and uniform sampler2D uMaskMap; that start off our fragment shader and lines 24 & 25 in the shipdata.plist:-
Make sure the uniform names in shipdata.plist(here they are uDiffuseMap & uMaskMap) match in the shader, the way you list your textures in shipdata.plist is important too
keep this order when you list them as uniforms (the shader snippet below also adds an extra uniform linking a variable called 'UTime' to Oolite's universalTime (oolites own 'gameclock')
I hope that's not too confusing, let's take a look at the fragment shader, i've added comments to the code that should hopefully explain stuff, just post on the forum for more detail on particular things, a lot of the code i can't follow myself especially the lighting code, i just know it has to be there and not fiddled with too much
OK, so to do the red/green texture colour switch we'll need to code up a timer, we've already got our shader uniform binding 'UTime' which is linking our shader to Oolite's Gameclock, since the gameclock will start at 0 seconds and just keep counting up for as long as the game is running it's not much use to us as a timer to switch between two settings, so what we'll do in this line in shader...
...is to make a sine wave from current time value, then use a function called step to turn the sinewave into a square wave and then use the value of the squarewave (always either 0.0 or 1.0) to decide if either Red or Green gets added into the colour mix, here's a graph showing the sinewave generated from the game clock
when the value of the sine wave is above 0.0 the step function overwrites the value to 1.0 and when the sine wave falls below 0.0 the step function overwrites the value to 0.0 (shown as a blue line on the graph)
right, so now whe have a floating point number called 'SwitchTime' that is alternating between 0.0 and 1.0 every few seconds or so, we can use this along with a command called 'mix' to create our red/green switching colour and add it into the final colour result, we'll do this in the following line
as this is turning into a bit of an epic post i'll let the comments in the shader code posted below explain how this is working but think of it as two pots of paint with a mix percentage of paint from the second pot determining the final colour we get, as our mix percentage is either 0% and 100% because of our square wave then we either just get paint from the first pot (green) or paint from the second pot (red)
OXP download and rendermonkey file ( http://developer.amd.com/resources/arch ... toolsuite/ note: Rendermonkey is Windows Only) is available here
https://www.box.com/s/druvgqm7fe6tnqntkx2s
There are 2 versions of the oxp, one with lighting code and one without, just install one or the other not both at once as they'll clash
The oxp has a script.js that will spawn 6 of the example cubes nearby when you launch from a station, they're like_shipped to asteroids so will appear on the scanner as grey lollypops and will also appear in the demoships parade on the 'load commander y/n' title screen
I've not included any lighting calculations in this example so the shader code is as short as possible, here's the vertex shader, it's just a text file saved in this case with the file extension .vertex and can be opened in any text editor
Code: Select all
varying vec2 vTexCoord;
void main(void)
{
vTexCoord = gl_MultiTexCoord0.st;
gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
}
A 'vec' is just a collection of floating point numbers grouped together under a single variable name and since a texture is just a flat 2d image with an X axis (width) and a Y axis (height) then we only need 2 numbers to describe any pixels position on it so we use a vec2 to hold this data.
When we get to the fragment shader we're going to store colours using vec4's. Since a colour needs 4 components to describe it (the Red colour Value, the Green colour value, the blue Colour Value and the Alpha (Transparency) value we'll need four numbers to store those (and XYZ vertex positions could be stored in a vec3 if this vertex shader was going to be doing any transforms on the actual objects geometry.
To pass a vec to the fragment shader write 'varying' before its definition, see the line varying vec2 vTexCoord; above, this exact same line needs to be duplicated in the fragment shader to complete the 'link'.
You can pass data from the vertex shader to the fragment shader but not the other way around.
gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex; is dealing with the objects geometry, i must confess i don't really know what this is doing but it's a line that needs to be in the shader otherwise the whole thing fails to compile, 'gl_position' 'gl_ModelViewProjectionMatrix' and 'gl_Vertex' are all reserved openGl keywords
The shader needs to be saved to your OXP's Shaders folder (file and folder names are case sensitive) and listed in your ships Shader definitions in shipdata.plist
eg see lines 15 & 16 in shipdata.plist in Example_one_no_lighting.oxp
Code: Select all
vertex_shader = "example_one.vertex";
fragment_shader = "example_one.fragment";
To work in an useful way shaders often need links back to Oolite's game engine, these links are called 'Uniforms' and are defined in your shader and also in your shipdata.plist. Textures need to be sent from Oolite to your shader as uniforms, see the lines
uniform sampler2D uDiffuseMap; and uniform sampler2D uMaskMap; that start off our fragment shader and lines 24 & 25 in the shipdata.plist:-
Code: Select all
uDiffuseMap = { type = texture; value = 0; };
uMaskMap = { type = texture; value = 1; };
Code: Select all
textures =
(
"Example_one_DiffuseTexture.png",
"Example_one_MaskTexture.png"
);
Code: Select all
uniforms =
{
uDiffuseMap = { type = texture; value = 0; };
uMaskMap = { type = texture; value = 1; };
uTime = "universalTime";
};
OK, so to do the red/green texture colour switch we'll need to code up a timer, we've already got our shader uniform binding 'UTime' which is linking our shader to Oolite's Gameclock, since the gameclock will start at 0 seconds and just keep counting up for as long as the game is running it's not much use to us as a timer to switch between two settings, so what we'll do in this line in shader...
Code: Select all
float SwitchTime = step(0.0, sin(uTime));
when the value of the sine wave is above 0.0 the step function overwrites the value to 1.0 and when the sine wave falls below 0.0 the step function overwrites the value to 0.0 (shown as a blue line on the graph)
right, so now whe have a floating point number called 'SwitchTime' that is alternating between 0.0 and 1.0 every few seconds or so, we can use this along with a command called 'mix' to create our red/green switching colour and add it into the final colour result, we'll do this in the following line
Code: Select all
SwitchingColour = mix(Green, Red, SwitchTime);
Code: Select all
// Uniforms from Oolite
uniform sampler2D uDiffuseMap;
uniform sampler2D uMaskMap;
uniform float uTime;
// Information from Vertex Shader
varying vec2 vTexCoord;
const vec4 Red = vec4(1.0, 0.0, 0.0, 1.0); // store the Red Colour in a vec4 called 'Red', the 4 numbers are the Red, Green, Blue and Alpha values, range is 0.000000 - 1.000000
const vec4 Green = vec4(0.0, 1.0, 0.0, 1.0); // store the Green Colour in a vec4 called 'Green'
void main(void)
{
/* - this symbol marks the start of a /comments section' which allow us to annotate the code
this symbol marks the end of our comments -> */
// two slashes like this // can also be used to add comments on a per line basis
/*
Calculate a sin wave powered by a 'link' back to Oolite's game clock, these links are knows as 'Uniforms'
the results from the sin wave calculation are being stored as a floating point number in a variable called
'SwitchTime', the word float that starts the line is telling the shader this.
Around our sin wave result is an openGL function called step, the definition of the step function is:
Step(edge, x) Returns 0.0 if x < edge, otherwise it returns 1.0
Basically doing this changes our sin wave to a square wave
where the output is either 0.0 (when the sin wave result is below 0.0) or 1.0 when the sin wave result is above 0.0
*/
float SwitchTime = step(0.0, sin(uTime));
/*
we could use a different function to step called smoothstep if we'd like the colour
to gradually change between red and green rather than instantly switch, to test this
comment out the 'float SwitchTime' line above and uncomment the float SwitchTime line below, remove the //'s
*/
// float SwitchTime = smoothstep(-1.0, 1.0, sin(uTime));
/*
OK, so now we have a floating point number that switches between 0.0 and 1.0 every few seconds, we'll use this
value in a 'mix' function and store the colour in a new vec4 called SwitchingColour
'mix' definition: mix(x,y,a) Returns x * (1-a) + y * a i.e. a linear blend of x and y
So basically this means mix together colour choice 1 'Green', colour choice 2 'Red', and how much percentage of
each colour goes into the final result ('SwitchTime') and since SwitchTime is only ever 0.0 or 1.0 the mix
amount is either going to 100% colour choice 1 'Green' (when SwitchTime = 0.0) or 100% colour choice two 'Red' (When SwitchTime = 1.0)
*/
vec4 SwitchingColour = mix(Green, Red, SwitchTime);
// initialise the vec4 that will contain the final colour result from this shader, fill it with zero's (the colour value for Black)
vec4 finalColor = vec4(0.0);
// Get the Texture Coordinates from the vertex shader, the UV map coordinates basically
vec2 texCoord = vTexCoord;
// Read in the texture map using the texture co-ordinates to locate the correct pixels for the polygon fragment we're currently working on, store them in a vec4 called diffuseMapColor
vec4 diffuseMapColor = texture2D(uDiffuseMap, texCoord);
// Read in the effects texture that is used as a mask texture to control the visibility of our colour changer effect
vec4 EffectMask = texture2D(uMaskMap, texCoord);
/*
Add in either the results of our Red/Green mix calculation above, multiply this by the mask texture so only areas in this texture
that have a colour value greater than 0.0 get the effect since as multiplying anything by 0.0 results in 0.0
(or no change to the originalcolour value we're adding 0.0 to it)
*/
diffuseMapColor += SwitchingColour * EffectMask;
// output the final colour result to the frame buffer for displaying on screen
gl_FragColor = diffuseMapColor;
}
https://www.box.com/s/druvgqm7fe6tnqntkx2s
There are 2 versions of the oxp, one with lighting code and one without, just install one or the other not both at once as they'll clash
The oxp has a script.js that will spawn 6 of the example cubes nearby when you launch from a station, they're like_shipped to asteroids so will appear on the scanner as grey lollypops and will also appear in the demoships parade on the 'load commander y/n' title screen
Wiki homepage for my OXP: http://wiki.alioth.net/index.php/Griff_Industries
- Smivs
- Retired Assassin
- Posts: 8408
- Joined: Tue Feb 09, 2010 11:31 am
- Location: Lost in space
- Contact:
Re: A request for a simple example of using shaders
Ha, you lost me after 'Here's Example one'
Commander Smivs, the friendliest Gourd this side of Riedquat.
- Star Gazer
- ---- E L I T E ----
- Posts: 633
- Joined: Sat Aug 14, 2004 4:55 pm
- Location: North Norfolk, UK, (Average Agricultural, Feudal States,Tech Level 8)
Re: A request for a simple example of using shaders
Yep. Fascinating, the different perspective knowledgeable people have on the word 'simple', as in:
This simple vertex shader just...
Very funny, Scotty, now beam down my clothes...
- Griff
- Oolite 2 Art Director
- Posts: 2483
- Joined: Fri Jul 14, 2006 12:29 pm
- Location: Probably hugging his Air Fryer
Re: A request for a simple example of using shaders
heh, I don't really know what i'm on about to be honest, the main workings of that vertex shader is really only two lines, and one of which I don't know what it does other than something to do with the objects geometry and if the line isn't there oolite generates a shader errorStar Gazer wrote:Yep. Fascinating, the different perspective knowledgeable people have on the word 'simple', as in:This simple vertex shader just...
Wiki homepage for my OXP: http://wiki.alioth.net/index.php/Griff_Industries
- Cody
- Sharp Shooter Spam Assassin
- Posts: 16081
- Joined: Sat Jul 04, 2009 9:31 pm
- Location: The Lizard's Claw
- Contact:
Re: A request for a simple example of using shaders
<chortles> I resemble that remark!Griff wrote:I don't really know what i'm on about to be honest...
I would advise stilts for the quagmires, and camels for the snowy hills
And any survivors, their debts I will certainly pay. There's always a way!
And any survivors, their debts I will certainly pay. There's always a way!
Re: A request for a simple example of using shaders
I think it's the line that works out the position of the point (pixel) that the shader is actually working on, from the model information and the vertex that you're dealing with (ie which fragment of the model's information).
Hence without it the fragment shader doesn't know what to apply its code to.
From a bit of research on t'net, the ModelViewProjectionMatrix is explained as:
Hence without it the fragment shader doesn't know what to apply its code to.
From a bit of research on t'net, the ModelViewProjectionMatrix is explained as:
The model, view and projection matrices are three separate matrices. Model maps from an object's local coordinate space into world space, view from world space to camera space, projection from camera to screen.
If you compose all three, you can use the one result to map all the way from object space to screen space, making you able to work out what you need to pass on to the next stage of a programmable pipeline from the incoming vertex positions.
In the fixed functionality pipelines of old, you'd apply model and view together, then work out lighting using another result derived from them (with some fixes so that e.g. normals are still unit length even if you've applied some scaling to the object), then apply projection. You can see that reflected in OpenGL, which never separates the model and view matrices — keeping them as a single modelview matrix stack. You therefore also sometimes see that reflected in shaders.
So: the composed model view projection matrix is often used by shaders to map from the vertices you loaded for each model to the screen. It's not required, there are lots of ways of achieving the same thing, it's just usual because it allows all possible linear transforms. Because of that, a lesser composed version of it was also the norm in ye olde fixed pipeline world.
My OXPs via Boxspace or from my Wiki pages .
Thargoid TV
Dropbox Referral Link
Thargoid TV
Dropbox Referral Link
- Shipbuilder
- ---- E L I T E ----
- Posts: 877
- Joined: Thu May 10, 2012 9:41 pm
- Location: Derby
Re: A request for a simple example of using shaders
Wow so much information to read and digest thanks very much guys.
Using information received from Thargoid and Griff plus suggestions in this thread including Captain McLane's referral to the Wiki pages I have managed to get a shader to work which changes a ships texture as it's energy levels change.
I have also managed to get shaders to make engine glow change to suit a ship's speed.
I still need to fill in gaps in my knowledge but thanks to the help offered I have finally started to understand and be able to use shaders.
What I may do, if there is a call for it, once I have studied further is prepare a shaders for dummies style document to cover the basics along with some worked examples.
I'll have to make myself a coffee shortly and read through Griff's detailed post above.
Thanks again for all your help.
Using information received from Thargoid and Griff plus suggestions in this thread including Captain McLane's referral to the Wiki pages I have managed to get a shader to work which changes a ships texture as it's energy levels change.
I have also managed to get shaders to make engine glow change to suit a ship's speed.
I still need to fill in gaps in my knowledge but thanks to the help offered I have finally started to understand and be able to use shaders.
What I may do, if there is a call for it, once I have studied further is prepare a shaders for dummies style document to cover the basics along with some worked examples.
I'll have to make myself a coffee shortly and read through Griff's detailed post above.
Thanks again for all your help.
Last edited by Shipbuilder on Sat Mar 09, 2013 5:34 pm, edited 1 time in total.
The GalTech Industries Corporation - Building ships to populate the galaxies.
Increase the variety of ships within your Ooniverse by downloading my OXPs
Flying the [wiki]Serpent_Class_Cruiser[/wiki] "Thargoid's Bane"
Increase the variety of ships within your Ooniverse by downloading my OXPs
Flying the [wiki]Serpent_Class_Cruiser[/wiki] "Thargoid's Bane"