Not logged inOpenClonk Forum
Up Topic Easier Shading Concept

This board is threaded (i.e. has a tree structure). Please use the Reply button of the specific post you are referring to, not just any random button. If you want to reply to the topic in general, use the Post button near the top and bottom of the page.

Post Reply
In Response to Foaly

>A clear disadvantage would be that it wouldn't work in ogre meshy anymore. And that we would have to write our own exporters for blender & co.


It's true, the materials would not work in ogre meshy.
But even now, once you start using a custom shader, you can't really preview it with ogre meshy.
To see how the shading really looks, you'll always have to view it in openclonk.

And yes, a modified exporter for Blender will be necessary. This should not be too much work, as the mesh file format stays the same.
And to be honest, the current exporter does not generate very good materials, they have to be edited by hand almost every time.
In the meanwhile, it will still be possible to load "legacy" material files in openclonk.

>I have to admit I don't get the advantage of the changed syntax.


I once tried to create a fake reflective material (which worked as far as I can remember).
It should have two matcaps added on top of each other, of which one would have a color tint and the other would not.
In the end, it should all be multiplied with an ambient occlusion map.
This is what the shader / material looked like:

=== Material ===

fragment_program shiny_matcap_fragment glsl
{
    source shiny_matcap_fragment.glsl
}

material WizTurret_Sphere
{
    receive_shadows on
    technique
    {
        pass
        {
            ambient 1.0 1.0 1.0 1.0
            diffuse 1.0 1.0 1.0 1.0
            specular 0.5 0.5 0.5 1.0 12.5
            emissive 1.0 1.0 1.0 1.0

            texture_unit
            {
                texture WizTurret_Diffuse.jpg
                tex_address_mode wrap
                filtering trilinear
            }
            texture_unit
            {
                texture WizTurret_Color.jpg
                tex_address_mode wrap
                filtering trilinear
            }
            texture_unit
            {
                texture WizTurret_Gloss.jpg
                tex_address_mode wrap
                filtering trilinear
            }
            fragment_program_ref shiny_matcap_fragment
            {
                param_named diffuseTex int 0
                param_named reflectionTintTex int 1
                param_named reflectionTex int 2
            }
        }
    }
}

=== Shader ===

uniform sampler2D diffuseTex;
uniform sampler2D reflectionTintTex;
uniform sampler2D reflectionTex;
uniform vec3 oc_PlayerColor;

#ifndef OPENCLONK
in vec2 texcoord;
out vec4 fragColor;
#define slice(x)
void main()
{
  fragColor = vec4(1.0, 1.0, 1.0, 1.0);
#endif

slice(texture+1)
{
  vec2 normalTCoord = (vtxNormal.xy + vec2(1.0, 1.0)) / 2;
  vec4 colorReflectionSample = texture2D(reflectionTex, normalTCoord);
  vec4 colorReflectionTintSample = texture2D(reflectionTintTex, normalTCoord);
  vec4 colorAOSample = texture2D(diffuseTex, texcoord);
}

slice(color+1)
{
  color = (colorReflectionTintSample * vec4(oc_PlayerColor.rgb, 1.0) + colorReflectionSample) * colorAOSample;
}

#ifndef OPENCLONK
}
#endif


And this is what I wish it looked like:

=== Shader ===
Shader(MatcapShader_Example)
{
  BlendMode = Solid;
  NormalMapping = Supported;
  Textures = {diffuseTex, reflectionTintTex, reflectionTex};
  Parameters =
  {
    //none
  };
}

float4 shaderMain()
{
  float2 texCoordMatcap = getMatcapTextureCoords(getNormals());
  float3 reflectionTint = sampleTexture(reflectionTintTex, texCoordMatcap).rgb * getTeamColor();
  float3 reflection = sampleTexture(reflectionTex, texCoordMatcap).rgb;
  float3 ambientOcclusion = sampleTextureAuto(diffuseTex);
 
  float3 finalColor = (reflectionTint + reflection) * ambientOcclusion;
  return float4(finalColor, 1.0);
}

=== Material ===
Material(MatcapShader_Example)
{
  Shader = MatcapShader_Example;
  Textures =
  {
    diffuseTex = WizTurret_Diffuse.jpg,
    reflectionTintTex = WizTurret_Color.jpg,
    reflectionTex = WizTurret_Gloss.jpg,
  };
  Parameters =
  {
    //none
  };
}


Especially the material definition itself is much shorter, and for most cases you will be using existing shaders.
Also, it is possible to read the shaderMain() from top to bottom and you know what happens.
No code is automatically inserted in between, it is much easier to understand in what order things happen.
And for the material properties (ambient, diffuse, etc.), they are not used at all in the shader and could be removed (I'm actually not sure whether it would complain currently if they were missing).
However, with the new system, if someone tried to use them in the .material file, they would get a warning because the shader does not specify them.

Also the new syntax has a few general advantages:
No need to specify the textures in a certain order in the material file / setting indices. That all happens automatically.
It easily possible to provide custom parameters for a shader, that can be set in a material file.
No need to know in which order slices are processed and which variable names they use (because there won't be slices).
For sampling a texture, it is not required to specify texture coordinates, if it just uses the default UV coordinates.

When working with the current system, I had weird compilation errors all the time and had to dig through the source files to find out what was happening internally.
With the new system, it should not be necessary at all to read the shader sources the engine uses in order to write a new shader, only the documentation.
So this project will also consist of writing a good documentation that explains everything.

Generally, the main idea is to make shaders more readable and easy to understand.

P. S. Sorry for posting so much source code which makes this look kind of messy :/

Powered by mwForum 2.29.7 © 1999-2015 Markus Wichitill