Difference between revisions of "Shader Creation"
m (→Making a custom shader) |
m (→Making a custom shader) |
||
Line 89: | Line 89: | ||
# Start editing <code>'''Data/GLSL/EnvobjectEx.vert'''</code> and <code>'''Data/GLSL/EnvobjectEx.frag'''</code> to set your own custom behavior. | # Start editing <code>'''Data/GLSL/EnvobjectEx.vert'''</code> and <code>'''Data/GLSL/EnvobjectEx.frag'''</code> to set your own custom behavior. | ||
− | The <code>'''envobject.*'''</code> shader programs have a lot of code in them | + | The <code>'''envobject.*'''</code> shader programs that you copied the code from have a lot of extra code in them. |
+ | It might be useful to start by very carefully cutting out code out that you know doesn't apply. | ||
This will be code between <code>'''#ifdef'''</code> or <code>'''"#if define(...)'''</code> sections, and their corresponding <code>'''#endif'''</code>. | This will be code between <code>'''#ifdef'''</code> or <code>'''"#if define(...)'''</code> sections, and their corresponding <code>'''#endif'''</code>. | ||
Be careful, these can be nested, and it may be hard to figure out what is what, unless you're carefully cutting or selecting line-by-line. | Be careful, these can be nested, and it may be hard to figure out what is what, unless you're carefully cutting or selecting line-by-line. |
Revision as of 23:29, 29 January 2018
Contents
Shader file structure
Shaders are a programmable code for each of the OpenGL standard rendering pipeline stages. These are used to modify the geometry and per-fragment ("pixel") rendering of a given object.
In Overgrowth, they are programmed in the GLSL shader language.
They are generally stored in the Data/GLSL
folder. Shaders that go together have the same base filename, but have a different extension for each shader stage.
.vert shader
.vert corresponds to the per-vertex shader stage.
This stage is always required
This comes first in the shader pipeline.
Vertex shaders are used most often for calculating interpolated data for the fragment shader to use (e.g. vertex coloring/lighting), or to calculate things in-shader, but once per vertex instead of once per pixel (which often makes it cheaper).
.frag shader
.frag corresponds to the per-fragment shader stage.
This stage is always required
This comes last in the shader pipeline.
Fragment shaders are used for calculating the color on a per-fragment ("pixel") basis.
Note: a "pixel" is a simple way to think about it, but if you're doing AA, or full-screen effects that span multiple pixels per single fragment, or rendering to a texture, than there isn't always a 1:1 mapping of "pixels on the screen" to fragments. This is useful to keep in mind in special cases, but generally for regular objects, a fragment is a "pixel".
other shader stages
.geom, .tess_eval, and .tess_ctrl are other shader stages that the engine supports. However, the engine only supports these stages in special cases. For the most part there's no need to worry about or try to work with these shader types.
Object file specification
You set the shader you want to use for a given object by editing that object's XML file, and specifying the shader you want in the ShaderName
tag.
<ShaderName>my_example_shader</ShaderName>
This will tell the engine to use the Data/GLSL/my_example_shader.vert
and Data/GLSL/my_example_shader.frag
programs to render this object.
Reusing shader programs
If you want to reuse common parts of a shader program (or make optional parts you can turn on or turn off, per-object) then you can pass a set of #define
flags to the shader.
For example:
<ShaderName>my_example_shader #DO_SOMETHING</ShaderName>
Will automatically add this at the top of your shader files:
#define DO_SOMETHING
You can then use #if defined(DO_SOMETHING)
or #ifdef DO_SOMETHING
to block off optional code.
Overgrowth does this with most of its object shaders, putting a lot of common code inside the Data/GLSL/envobject.*
shader programs.
Special shader file names
Right now the engine automatically substitutes certain shader strings with a different/expanded string with extra options in place.
This means, even if an object seems to be using one of the shaders inside the Data/GLSL
folder, the engine is actually replacing it with envobject
, with an extra set of flags.
As of this writing, here is an exhaustive list of these substitutions:
-
cubemap
->envobject #TANGENT
-
cubemapobj
orcubemapobjchar
orcubemapobjitem
->envobject
-
cubemapalpha
->envobject #TANGENT #ALPHA
-
plant
orplant_less_movement
->envobject #TANGENT #ALPHA #PLANT
-
plant_foliage
->envobject #TANGENT #ALPHA #PLANT #NO_DECALS
-
detailmap4
->envobject #DETAILMAP4 #TANGENT
-
detailmap4tangent
->envobject #DETAILMAP4 #TANGENT #BASE_TANGENT
-
MagmaFloor
->envobject #MAGMA_FLOOR
-
MagmaFlow
->envobject #MAGMA_FLOW
This means that, for example, even though there are Data/GLSL/MagmaFlow.vert
and Data/GLSL/MagmaFlow.frag
files, they aren't actually used by the game. The shader code for those is inside Data/GLSL/envobject.*
Making a custom shader
To create or modify an existing shader:
- Copy the
Data/GLSL/envobject.*
files and paste them onData/GLSL
folder inside your mod. - Rename the
envobject.*
files to another name, so they won't conflict with those from the game (for our example, we will useEnvobjectEx.*
). - Edit the object .XML file, and change the
ShaderName
element to look like this:<ShaderName>EnvobjectEx</ShaderName>
- Start editing
Data/GLSL/EnvobjectEx.vert
andData/GLSL/EnvobjectEx.frag
to set your own custom behavior.
The envobject.*
shader programs that you copied the code from have a lot of extra code in them.
It might be useful to start by very carefully cutting out code out that you know doesn't apply.
This will be code between #ifdef
or "#if define(...)
sections, and their corresponding #endif
.
Be careful, these can be nested, and it may be hard to figure out what is what, unless you're carefully cutting or selecting line-by-line.