Jump to content
Search In
  • More options...
Find results that contain...
Find results in...

Shadertoy/ShaderFrog to Leadwerks tutorial


Recommended Posts

So someone asked for a tutorial on this so here goes. I wouldn't consider myself much of a coder, but luckily translating these over to Leadwerks isn't hard to do. I don't know why all of it works the way it does but here's a go:
 

Shadertoy shaders are all post-effect shaders, so you can just use the vertex information from any Leadwerks post-effect shader with it. And there's no "in/out" variables so really none of it has to do with the vertex information. You have to use a certain language with some things in Leadwerks (I think Josh posted a list somewhere around here maybe if you know where it is you could drop it in this thread). Leadwerks understands "uniform vec3 cameraposition" for instance, but not " uniform vec3 cameraPosition" (with a capital P).  Here's a checklist of things I always see, the equivalencies from Shadertoy:

iResolution =  use "buffersize"
iChannel0 = use "texture0" (and so on with textures. In the post-effect you want to use texture1 instead. As a model shader you want texture0. You might have to mess with it a bit)
fragCoord.xy  = use "gl_FragCoord.xy"
iTime = currenttime
    (then float time = currenttime/1000;) // and use "time"
fragColor = use "fragData0"  (I think you can use fragColor as long as you have it as a vec4 out. You have to tell the shader what the output is. I just write "out vec4 fragData0" before the "main" somewhere )
void mainImage( out vec4 fragColor, in vec2 fragCoord ) = just use "void main ()"
//---------------------------------------------------------------------------------------------------------------------

So you want Leadwerks post-effect vertex information, and at the top of your fragment shader you want all this information:

uniform float currenttime;
float time = currenttime/1000;
uniform vec2 buffersize;
uniform sampler2D texture0;
uniform sampler2D texture1;
out vec4 fragData0;

Edit: first things first: Make sure you put at the top of your fragment shader as the very first two lines:

#version 400
#define BFN_ENABLED 1

... and at the top of your vertex:

#version 400
#define MAX_INSTANCES 256

//---------------------------------------------------------------------------------------------------------------------

Then go through and change all the language as necessary. Hopefully I didn't miss anything. Sometimes you'll see "iMouse" on Shadertoy and I've never really messed with that but I think you can get away with just inserting a "vec2(1,1)" in it's place.
One thing that messed me up at first was seeing this: " *= "  or " += " , "  -= " , and " /= " .  That's just a simplified way to multiply, or add etc. So in Lua you might write: "time = time * 1.3". In GLSL you can just say "time *= 1.3".

Also while I'm going through a shader conversion I'll get rid of anything that says "uniform " or "const" or "highp" before it (only on the Shadertoy variables, though) because for whatever reason those will just default to zero or something. And if you write a shader and want to access your variables from a script, you want to use "uniform" and then adjust the values in the script. I don't know why this is.

(For the super-noob: to see a post-effects shader go to the "Scene" tab, click "Root" then find the Post-Effects box and click "Add")





Here's the working Leadwerks equivalent of this shader. See if you can do it before you look at the answer:

https://www.shadertoy.com/view/4slGRM



 

//Fragment
#version 400

//https://www.shadertoy.com/view/4slGRM

out vec4 fragData0;

uniform float currenttime;
float time = currenttime/1000;

uniform vec2 buffersize;

uniform sampler2D texture0;
uniform sampler2D texture1;
uniform sampler2D texture2;
uniform sampler2D texture3;

// Simple Water shader. (c) Victor Korsun, bitekas@gmail.com; 2012.
//
// Attribution-ShareAlike CC License.

#ifdef GL_ES
precision highp float;
#endif

float PI = 3.1415926535897932;

// play with these parameters to custimize the effect
// ===================================================

//speed
float speed = 0.2;
float speed_x = 0.3;
float speed_y = 0.3;

// refraction
float emboss = 0.50;
float intensity = 2.4;
int steps = 8;
float frequency = 6.0;
int angle = 7; // better when a prime

// reflection
float delta = 60.;
float intence = 700.;

float reflectionCutOff = 0.012;
float reflectionIntence = 200000.;

// ===================================================


  float col(vec2 coord,float time)
  {
    float delta_theta = 2.0 * PI / float(angle);
    float col = 0.0;
    float theta = 0.0;
    for (int i = 0; i < steps; i++)
    {
      vec2 adjc = coord;
      theta = delta_theta*float(i);
      adjc.x += cos(theta)*time*speed + time * speed_x;
      adjc.y -= sin(theta)*time*speed - time * speed_y;
      col = col + cos( (adjc.x*cos(theta) - adjc.y*sin(theta))*frequency)*intensity;
    }

    return cos(col);
  }

//---------- main

void main()
{
    time *= 1.3;

    vec2 p = (gl_FragCoord.xy) / buffersize.xy, c1 = p, c2 = p;
    float cc1 = col(c1,time);

    c2.x += buffersize.x/delta;
    float dx = emboss*(cc1-col(c2,time))/delta;

    c2.x = p.x;
    c2.y += buffersize.y/delta;
    float dy = emboss*(cc1-col(c2,time))/delta;

    c1.x += dx*2.;
    c1.y = -(c1.y+dy*2.);

    float alpha = 1.+dot(dx,dy)*intence;
        
    float ddx = dx - reflectionCutOff;
    float ddy = dy - reflectionCutOff;
    if (ddx > 0. && ddy > 0.)
        alpha = pow(alpha, ddx*ddy*reflectionIntence);
        
    vec4 col = texture(texture1,c1)*(alpha);
    fragData0 = col;
}

//Vertex (straight outta leadwerks)
#version 400

uniform mat4 projectionmatrix;
uniform mat4 drawmatrix;
uniform vec2 offset;
uniform vec2 position[4];

in vec3 vertex_position;

void main(void)
{
    gl_Position = projectionmatrix * (drawmatrix * vec4(position[gl_VertexID]+offset, 0.0, 1.0));
}

More to come....

 

  • Like 2
  • Thanks 1
Link to post

So let's say you want this Shadertoy shader but you want to use it on a model. Luckily this is pretty easy to do as well. Just a couple changes:


First change is you need model shader vertex information. Probably the best one to use for this kind of thing in general is the Leadwerks "diffuse + normal + specular" shader.

The steps:
Copy/Paste all of the vertex information from Leadwerks' "diffuse + normal + specular"  shader to the vertex part of your shader.

Copy paste everything above the "main"  from Leadwerks' "diffuse + normal + specular"  fragment shader to your fragment shader (don't erase the variables from the shadertoy shader!).

Change anything that says "gl_FragCoord.xy/buffersize.xy" or anywhere it says "buffersize" to your texture coordinates instead. This is an "in vec2" from your vertex. It's something like "in vec2 vTexCoords0" or "in vec2 ex_texcoords0." (for the super-noobs: notice that all the outputs that go "out" from vertex also have to come "in" to the fragment shader).

Remember I mentioned you want to change the "texture1" from the post-effect shader to "texture0" for the model shader. "texture0" is the diffuse texture slot. "texture1" is the normals. If you leave it as "texture1" still it's going to look like the normals rather than the diffuse.

Find a material, double click it and set the shader to the material in the Material Editor/shaders.
//---------------------------------------------------------------------------------------------------------------------

That's the gist of it. There's more you can do like add all the normal and specular fragment information in but I'm too lazy to do it and you can probably figure it out. Mostly just a lot of copy/pasting.

 

 

Here's the working Leadwerks equivalent of this MODEL shader. You can see it wobbling the texture around. See if you can do it before you look at the answer:

https://www.shadertoy.com/view/4slGRM

 

 

 

 

 

 

//Fragment
#version 400
#define BFN_ENABLED 1

//https://www.shadertoy.com/view/4slGRM

//Uniforms
uniform sampler2D texture0;//diffuse map
uniform sampler2D texture1;//normal map
uniform sampler2D texture2;//specular map
uniform vec4 materialcolorspecular;
uniform vec4 lighting_ambient;
uniform samplerCube texture15;
uniform vec2 camerarange;
uniform vec2 buffersize;
uniform float camerazoom;
uniform int decalmode;
uniform float materialroughness;
uniform float currenttime;
float time = currenttime/1000;

//Inputs
in vec2 ex_texcoords0;
in vec4 ex_color;
in float ex_selectionstate;
in vec3 ex_VertexCameraPosition;
in vec3 ex_normal;
in vec3 ex_tangent;
in vec3 ex_binormal;
in float clipdistance0;

//Outputs
out vec4 fragData0;
out vec4 fragData1;
out vec4 fragData2;
out vec4 fragData3;

// Simple Water shader. (c) Victor Korsun, bitekas@gmail.com; 2012.
//
// Attribution-ShareAlike CC License.

#ifdef GL_ES
precision highp float;
#endif

float PI = 3.1415926535897932;

// play with these parameters to custimize the effect
// ===================================================

//speed
float speed = 0.2;
float speed_x = 0.3;
float speed_y = 0.3;

// refraction
float emboss = 0.50;
float intensity = 2.4;
int steps = 8;
float frequency = 6.0;
int angle = 7; // better when a prime

// reflection
float delta = 60.;
float intence = 700.;

float reflectionCutOff = 0.012;
float reflectionIntence = 200000.;

// ===================================================


 float col(vec2 coord,float time)
  {
    float delta_theta = 2.0 * PI / float(angle);
    float col = 0.0;
    float theta = 0.0;
    for (int i = 0; i < steps; i++)
    {
      vec2 adjc = coord;
      theta = delta_theta*float(i);
      adjc.x += cos(theta)*time*speed + time * speed_x;
      adjc.y -= sin(theta)*time*speed - time * speed_y;
      col = col + cos( (adjc.x*cos(theta) - adjc.y*sin(theta))*frequency)*intensity;
    }

    return cos(col);
  }

//---------- main

void main()
{
    time *= 1.3;

    vec2 p = ex_texcoords0, c1 = p, c2 = p;
    float cc1 = col(c1,time);

    c2.x += ex_texcoords0.x/delta;
    float dx = emboss*(cc1-col(c2,time))/delta;

    c2.x = p.x;
    c2.y += ex_texcoords0.y/delta;
    float dy = emboss*(cc1-col(c2,time))/delta;

    c1.x += dx*2.;
    c1.y = -(c1.y+dy*2.);

    float alpha = 1.+dot(dx,dy)*intence;
        
    float ddx = dx - reflectionCutOff;
    float ddy = dy - reflectionCutOff;
    if (ddx > 0. && ddy > 0.)
        alpha = pow(alpha, ddx*ddy*reflectionIntence);
        
    vec4 col = texture(texture0,c1)*(alpha);
    fragData0 = col;
}

 

//Vertex
#version 400
#define MAX_INSTANCES 256

//Uniforms
uniform vec4 materialcolordiffuse;
uniform mat4 projectioncameramatrix;
uniform mat4 camerainversematrix;
uniform instancematrices { mat4 matrix[MAX_INSTANCES];} entity;
uniform vec4 clipplane0 = vec4(0.0);
uniform mat4 cameramatrix;

//Attributes
in vec3 vertex_position;
in vec4 vertex_color;
in vec2 vertex_texcoords0;
in vec3 vertex_normal;
in vec3 vertex_binormal;
in vec3 vertex_tangent;
//in vec4 vertex_boneweights;
//in ivec4 vertex_boneindices;

//Outputs
out vec4 ex_color;
out vec2 ex_texcoords0;
out float ex_selectionstate;
out vec3 ex_VertexCameraPosition;
out vec3 ex_normal;
out vec3 ex_tangent;
out vec3 ex_binormal;
out float clipdistance0;

void main()
{
    mat4 entitymatrix = entity.matrix[gl_InstanceID];
    mat4 entitymatrix_=entitymatrix;
    entitymatrix_[0][3]=0.0;
    entitymatrix_[1][3]=0.0;
    entitymatrix_[2][3]=0.0;
    entitymatrix_[3][3]=1.0;
    
    vec4 modelvertexposition = entitymatrix_ * vec4(vertex_position,1.0);
    
    //Clip planes
    if (length(clipplane0.xyz)>0.0001)
    {
        clipdistance0 = modelvertexposition.x*clipplane0.x + modelvertexposition.y*clipplane0.y + modelvertexposition.z*clipplane0.z + clipplane0.w;
    }
    else
    {
        clipdistance0 = 0.0;
    }    
    
    ex_VertexCameraPosition = vec3(camerainversematrix * modelvertexposition);
    gl_Position = projectioncameramatrix * modelvertexposition;
    
    mat3 nmat = mat3(entitymatrix);
    ex_normal = normalize(nmat * vertex_normal);    
    ex_tangent = normalize(nmat * vertex_tangent);
    ex_binormal = normalize(nmat * vertex_binormal);
    
    ex_texcoords0 = vertex_texcoords0;
    
    ex_color = vec4(entitymatrix[0][3],entitymatrix[1][3],entitymatrix[2][3],entitymatrix[3][3]);
    
    //ex_color = vec4(vertex_boneindices[0]) * 60.0;

    //If an object is selected, 10 is subtracted from the alpha color.
    //This is a bit of a hack that packs a per-object boolean into the alpha value.
    ex_selectionstate = 0.0;
    if (ex_color.a<-5.0)
    {
        ex_color.a += 10.0;
        ex_selectionstate = 1.0;
    }
    ex_color *= vec4(1.0-vertex_color.r,1.0-vertex_color.g,1.0-vertex_color.b,vertex_color.a) * materialcolordiffuse;
}

Shaderfrog next....

wobbly.jpg

  • Thanks 1
Link to post

Actually I had messed with the above shader before. Here's some variation of it. I don't even remember what I did to this but sometimes a comparison can help. And the vertex part of the shader is the same:

//Fragment

#version 400
#define BFN_ENABLED 1

//Uniforms
uniform sampler2D texture0;//diffuse map
uniform sampler2D texture1;//light map
uniform vec4 materialcolorspecular;
uniform vec4 lighting_ambient;
uniform samplerCube texture15;
uniform int decalmode;
uniform float materialroughness;
uniform float currenttime;

float time = currenttime/1000;

//Inputs
in vec2 ex_texcoords0;
in vec4 ex_color;
in float ex_selectionstate;
in vec3 ex_VertexCameraPosition;
in vec3 ex_normal;
in vec3 ex_tangent;
in vec3 ex_binormal;
in float clipdistance0;

out vec4 fragData0;
out vec4 fragData1;
out vec4 fragData2;
out vec4 fragData3;

 

const float PI = 3.1415926535897932;

// play with these parameters to custimize the effect
// ===================================================

//speed
const float speed = 0.1;
const float speed_x = 0.2;
const float speed_y = 0.2;

// refraction
const float emboss = 0.50;
const float intensity = 2.9;
const int steps = 2;
const float frequency = 18.0;
const int angle = 5; // better when a prime

// reflection
const float delta = 55.;
const float intence = 700.;

const float reflectionCutOff = 0.012;
const float reflectionIntence = 200000.;

// ===================================================

float rand(float s) {
    float r = fract(6.2 - 3.14);
    float p = floor(30.0);
    for (float i=0; i < 4.0; i++) {
        r = r/r/r* sin(p);
        s = (r*2.0)/p;
    }
    return s;
}

  float col(vec2 coord,float time)
  {
    float delta_theta = 2.0 * PI / float(angle);
    float col = 0.0;
    float theta = 0.0;
    for (int i = 0; i < steps; i++)
    {
      vec2 adjc = coord;
      theta = delta_theta*float(i);
      adjc.x += cos(theta)*time*speed + time * speed_x;
      adjc.y -= sin(theta)*time*speed - time * speed_y;
      col = col + cos( (adjc.x*cos(theta) - adjc.y*sin(theta))*frequency)*intensity;
      col *= vec4(1.0,1.0,1.0,0.5).r;
    }

    return cos(col);
  }

//---------- main

void main()
{
    float time = time*0.5;

    vec2 p = ex_texcoords0.xy, c1 = p, c2 = p;
    float cc1 = col(c1,time);

    c2.x += ex_texcoords0.x;
    float dx = emboss*(cc1-col(c2,time))/delta;

    c2.x = p.x;
    c2.y += ex_texcoords0.y;
    float dy = emboss*(cc1-col(c2,time))/delta;

    c1.x += dx*2.;
    c1.y = -(c1.y+dy*2.);

    float alpha = 1.+dot(dx,dy)*intence;
        
    float ddx = dx - reflectionCutOff;
    float ddy = dy - reflectionCutOff;
    if (ddx > 0. && ddy > 0.)
        alpha = pow(alpha, ddx*ddy*reflectionIntence);

#define amp 0.005

    vec2 tc = ex_texcoords0;
    tc -= 0.5;
    vec2 p2 = -1.0 + 4.0 * tc;
    float len = length(p)*sin(3.0);
    c1 += tc + (p2/len)*cos(len*10.0-time*3.0)*rand(len)-p2;
    c1 += ((vec2(.5)-texture(texture0, c1*0.3+vec2(time/7.0*0.9, sin(time)/7.0*0.25)).xy)*amp +
          (vec2(p2)-texture(texture0, c1*0.3-vec2(-time/5.0*0.25, time/5.0*0.025)).xy)*amp);
    
    //vec4 col = texture(texture0,uv);
        
    vec4 col = texture(texture0,c1)*(alpha);
    fragData0 = col;
}




//vertex

#version 400
#define MAX_INSTANCES 256

//Uniforms
uniform vec4 materialcolordiffuse;
uniform mat4 projectioncameramatrix;
uniform mat4 camerainversematrix;
uniform instancematrices { mat4 matrix[MAX_INSTANCES];} entity;
uniform vec4 clipplane0 = vec4(0.0);

//Attributes
in vec3 vertex_position;
in vec4 vertex_color;
in vec2 vertex_texcoords0;
in vec3 vertex_normal;
in vec3 vertex_binormal;
in vec3 vertex_tangent;

//Outputs
out vec4 ex_color;
out vec2 ex_texcoords0;
out float ex_selectionstate;
out vec3 ex_VertexCameraPosition;
out vec3 ex_normal;
out vec3 ex_tangent;
out vec3 ex_binormal;
out float clipdistance0;

void main()
{
    mat4 entitymatrix = entity.matrix[gl_InstanceID];
    mat4 entitymatrix_=entitymatrix;
    entitymatrix_[0][3]=0.0;
    entitymatrix_[1][3]=0.0;
    entitymatrix_[2][3]=0.0;
    entitymatrix_[3][3]=1.0;
    
    vec4 modelvertexposition = entitymatrix_ * vec4(vertex_position,1.0);
    
    //Clip planes
    if (length(clipplane0.xyz)>0.0001)
    {
        clipdistance0 = modelvertexposition.x*clipplane0.x + modelvertexposition.y*clipplane0.y + modelvertexposition.z*clipplane0.z + clipplane0.w;
    }
    else
    {
        clipdistance0 = 0.0;
    }    
    
    ex_VertexCameraPosition = vec3(camerainversematrix * modelvertexposition);
    gl_Position = projectioncameramatrix * modelvertexposition;

    //mat3 nmat = mat3(camerainversematrix[0].xyz,camerainversematrix[1].xyz,camerainversematrix[2].xyz);//39
    //nmat = nmat * mat3(entitymatrix[0].xyz,entitymatrix[1].xyz,entitymatrix[2].xyz);//40
    mat3 nmat = mat3(entitymatrix);
    ex_normal = normalize(nmat * vertex_normal);    
    ex_tangent = normalize(nmat * vertex_tangent);
    ex_binormal = normalize(nmat * vertex_binormal);
    
    ex_texcoords0 = vertex_texcoords0;
    
    ex_color = vec4(entitymatrix[0][3],entitymatrix[1][3],entitymatrix[2][3],entitymatrix[3][3]);
    
    //If an object is selected, 10 is subtracted from the alpha color.
    //This is a bit of a hack that packs a per-object boolean into the alpha value.
    ex_selectionstate = 0.0;
    
    if (ex_color.a<-5.0)
    {
        ex_color.a += 10.0;
        ex_selectionstate = 1.0;
    }
    ex_color *= vec4(1.0-vertex_color.r,1.0-vertex_color.g,1.0-vertex_color.b,vertex_color.a) * materialcolordiffuse;
}

  • Thanks 1
Link to post

I like ShaderFrog because it's all model shaders, which is my big interest at the moment.

So this is the basic vertex shader in ShaderFrog:

    vNormal = normal;
    vUv = uv;
    vUv2 = uv2;
    vPosition = position;

    gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );

To translate these over the "projectionMatrix = "projectioncameramatrix" in Leadwerks and the "modelViewMatrix" = " entitymatrix." "position" = "vertex_position" in Leadwerks. If you try to use this, however, it won't work. For whatever reason the matrixes aren't there. The Leadwerks vertex shader is superior anyway so again I just use that and rarely bother with ShaderFrog shaders that are heavy on vertex changes. Good to know, though, if you want to do something like a vertex displacement shader or something.
ShaderFrog has some shaders that are called "composed shaders" and you can't really use those - (or at least I can't) because they're made with nodes using other ShaderFrog shaders. But often you can find a regular shader that is similar to a composed one.

Let's do this rim lighting shader:
https://shaderfrog.com/app/view/2716?view=shader
//---------------------------------------------------------------------------------------------------------------------

The steps are similar to Shadertoy shaders:
Copy/paste the vertex part of the "diffuse+normal+specular" to your vertex. You notice a line that says "vec4 modelvertexposition = entitymatrix_ * vec4(vertex_position, 1.0);"? Erase "vec4" so that it just says "modelvertexposition = entitymatrix_ * vec4(vertex_position, 1.0);" and instead under your Outputs section write "out vec4 modelvertexposition"

Copy/paste everything above "void main ()" from the fragment part of the "diffuse+normal+specular" to your shader. Under the "Inputs" section write "in vec4 modelvertexposition". Now you're passing "modelvertexposition" from your vertex to fragment shader.

Copy/paste the fragment part of the ShaderFrog shader under the information in the previous step into your fragment shader. At this point you should have a vertex shader from Leadwerks and a bunch of variables from Leadwerks in the fragment shader, and your entire "void main()" from ShaderFrog and a few variables from ShaderFrog (that may say "uniform" in front of them and you don't want that because you want to adjust them yourself). Sort of this weird hybrid shader that doesn't work at all.
//---------------------------------------------------------------------------------------------------------------------
Maybe the best thing to do at this point is break this shader down line by line. It's a bit tedious but once you confront these problems a few times you can do it fast:

The first line of this shader is:
    vec3 worldPosition = ( modelMatrix * vec4( vPosition, 1.0 )).xyz;
 I don't know why they do it this way but this line here is the same as this line in the Leadwerks vertex shader:
    modelvertexposition = entitymatrix_ * vec4(vertex_position, 1.0);
 So you don't need it. You can delete it.  Instead of "worldPosition" just use the "modelvertexposition" that you passed from the vertex shader. One thing to note is that "modelvertexposition" Is a vec4 and "worldPosition" is a vec3. The fix is simple. Whenever you need "modelvertexposition" as a vec3 just use "modelvertexposition.xyz" Also, if at some point you need to change a vec3 to a vec4 you can do that by adding an arbitrary "1.0" to the end of it. For instance "vec3 worldPosition" as a vec4 is simply "vec4(worldPosition,1.0)".

The next line is:
        vec3 worldNormal = normalize( vec3( modelMatrix * vec4( vNormal, 0.0 ) ) );
This is also done already in the Leadwerks vertex shader here. ShaderFrog doesn't use the tangents and binormals I guess, but Leadwerks does. It's better and it's already set up:
    mat3 nmat = mat3(entitymatrix);
    ex_normal = normalize(nmat * vertex_normal);    
    ex_tangent = normalize(nmat * vertex_tangent);
    ex_binormal = normalize(nmat * vertex_binormal);
So you don't  need it. In some of the lines to come instead of "worldNormal" use "normal" which is a section of about 5 lines already in the fragment part of of the Leadwerks "diffuse+normal+specular" shader which makes the normals work the same all around the model. So delete this  worldNormal line and paste in this:
     vec3 normal = ex_normal;
    normal = normalize(texture(texture1,ex_texcoords0).xyz * 2.0 - 1.0);
    float ao = normal.z;
    normal = ex_tangent * normal.x + ex_binormal * normal.y + ex_normal * normal.z;    
    normal = normalize(normal);

Next we have:
        vec3 lightVector = normalize( lightPosition - worldPosition );
We don't have a "lightPosition" anywhere so we need to make one. Above this line write "vec3 lightPosition;" If you add no "=" sign it just defaults to 0, which is fine for us here. Then, since we have "modelvertexposition" instead of "worldPosition" this line should look like this:
    vec3 lightVector = normalize(lightPosition - modelvertexposition.xyz);


For viewVector we have neither "cameraPosition" nor "worldPosition." So up at the top with your other uniforms add "uniform vec3 cameraposition" (one word, no capitals). This is one of those built-in words that Leadwerks recognizes but it has to be written exactly like that. So this line should be:
        vec3 viewVector = normalize(cameraposition - modelvertexposition.xyz);

(I actually went back later and changed the line to multiplication because it wasn't working all the way around the model)

       vec3 viewVector = normalize(cameraposition * modelvertexposition.xyz);

 


Next line is:
        float rimndotv =  max(0.0, rimWidth - clamp(dot(worldNormal, viewVector), 0.0, 1.0));
We don't have rimWidth, among other things so to make this quick just copy/paste these variables above this line:
    vec3 albedoColor = vec3(1,1,1);
    vec3 sunColor = vec3(0.8,0.8,1.0);
    float sunStrength = 0.5;    
    float rimWidth = 0.8;
    vec3 rimColor = vec3(0.5,0.7,1);
    float rimStrength = 0.5;
    float iblStrength = 0.5;
    vec3 iblColor = vec3(0,1,1);
And because "worldNormal" is now "normal" this line should be:
    float rimndotv = max(0.0, rimWidth - clamp(dot(normal, viewVector),0.0,1.0));

Next line is easy. No changes:
    vec3 rimLight = rimndotv * rimColor * rimStrength;

Next line should be:
    vec3 reflection = reflect(-viewVector, normal);


Next line we have "reflection" as our texture coordinates, which is a vec3, rather than the vec2 of our texture coords. It's a cube map so what we need to do is add at the top of our shader with our other uniforms this: "uniform samplerCube texture5;" ( "texture5" is arbitrary. It's just far enough out of the way in case I want to add a height map later, etc.). Then in this line we simply use "texture" rather than "textureCube" and because texture5 is a cubemap it will allow us to use the vec3 texture coordinates. So this line:
        vec3 iblLight = iblColor * textureCube(iblCube, reflection).rgb * iblStrength;
Should look like this:
    vec3 iblLight = iblColor * texture(texture5,reflection).rgb*iblStrength; //"rgb" or "xyz"


Next line change "worldNormal" to "normal":
    float ndotl = max(0.0, dot(normal, lightVector));


Next no change:
        vec3 sunLight = sunColor * sunStrength * ndotl;

Next no change:
        vec3 finalLight = rimLight + iblLight + sunLight;

And finally:
        gl_FragColor = vec4( albedoColor * finalLight, 1.0 );
should be:
    fragData0 = vec4(albedoColor * finalLight,1.0);


Ok so this will work but it as it is your diffuse texture is black. That's no good. So the solution is to put it in the fragData2 output which handles emission:

Go back to your "diffuse+normal+specular" fragment shader and copy/paste everything under the "fragData0" line into your shader under the same "fragData0" line.

Copy/paste these lines from the "diffuse+normal+specular" shader into your shader up near the top within the "void main ()":
    if (clipdistance0>0.0) discard;
    vec4 outcolor = ex_color; //"ex_color" is a vec4 being passed in from the vertex
    outcolor *= texture(texture0,ex_texcoords0);

Change your fragData0 line to:
    fragData0 = outcolor;

Move down to the fragData2 line and change  it to:
    fragData2 = vec4( albedoColor * finalLight, specular );


And voila!


//---------------------------------------------------------------------------------------------------------------------

 

Here's the working Leadwerks equivalent of this shader. See if you can do it before you look at the answer:
https://shaderfrog.com/app/view/2716?view=fragment


//Fragment
#version 400
#define BFN_ENABLED 1

//Uniforms    
uniform sampler2D texture0;//diffuse map
uniform sampler2D texture1;//normal map
uniform sampler2D texture2;//specular map
uniform samplerCube texture5;//cube map
uniform samplerCube texture15;//BFN map
uniform mat4 cameramatrix;
uniform mat4 projectioncameramatrix;
uniform vec2 camerarange;
uniform float camerazoom;
uniform vec2 buffersize;
uniform mat4 camerainversematrix;
uniform vec4 ambientlight;
uniform vec4 materialcolorspecular;
uniform mat3 cameranormalmatrix;
uniform vec3 cameraposition;
uniform int decalmode;
uniform float materialroughness;

//Inputs
in vec4 ex_vertexposition;
in vec2 ex_texcoords0;
in vec2 ex_texcoords1;
in vec4 ex_color;
in float ex_selectionstate;
in vec3 ex_normal;
in vec3 ex_tangent;
in vec3 ex_binormal;
in float clipdistance0;
in vec3 ex_VertexCameraPosition;
in mat4 ex_entitymat;

out vec4 fragData0;
out vec4 fragData1;
out vec4 fragData2;
out vec4 fragData3;

void main()
{
    //Clip plane discard
    if (clipdistance0>0.0) discard;

    vec4 outcolor = ex_color;

    //Modulate blend with diffuse map
    outcolor *= texture(texture0,ex_texcoords0);

    //Normal map
    vec3 normal = ex_normal;
    normal = normalize(texture(texture1,ex_texcoords0).xyz * 2.0 - 1.0);
    float ao = normal.z;
    normal = ex_tangent * normal.x + ex_binormal * normal.y + ex_normal * normal.z;    
    normal = normalize(normal);
    
    //Rim Lighting
    //from https://shaderfrog.com/app/view/2716?view=fragment
    //-------------------------------------------------------
    vec3 albedoColor = vec3(1,1,1);
    vec3 sunColor = vec3(0.8,0.8,1.0);
    float sunStrength = 0.5;    
    float rimWidth = 0.8;
    vec3 rimColor = vec3(0.5,0.7,1);
    float rimStrength = 0.5;
    float iblStrength = 0.5;
    vec3 lightPosition;

    vec3 viewVector = normalize(cameraposition - ex_vertexposition.xyz);//viewVector
    vec3 lightVector = normalize(lightPosition * ex_vertexposition.xyz);//lightVector

    float rimndotv = max(0.0, rimWidth - clamp(dot(normal, viewVector),0.0,1.0));
        vec3 rimLight = rimndotv * rimColor * rimStrength;

    vec3 reflection = reflect(-viewVector,normal);

    float normdot1 = max(0.0, dot(normal, lightVector));
    vec3 sunLight = sunColor * sunStrength * normdot1;
    vec3 iblLight = 0.0 * texture(texture5,reflection).rgb*iblStrength;
    vec3 finalLight = rimLight + iblLight + sunLight;
    //-------------------------------------------------------

    //Output
    fragData0 = outcolor;

#if BFN_ENABLED==1
    //Best-fit normals
    fragData1 = texture(texture15,normalize(vec3(normal.x,-normal.y,normal.z)));
    fragData1.a = fragData0.a;
#else
    //Low-res normals
    fragData1 = vec4(normalize(normal)*0.5+0.5,fragData0.a);
#endif
    float specular = materialcolorspecular.r * 0.299 + materialcolorspecular.g * 0.587 + materialcolorspecular.b * 0.114;
    int materialflags=1;
    if (ex_selectionstate>0.0) materialflags += 2;
    if (decalmode==1) materialflags += 4;//brush
    if (decalmode==2) materialflags += 8;//model
    if (decalmode==4) materialflags += 16;//terrain

    fragData1.a = materialflags/255.0;
    fragData2 = vec4( albedoColor * finalLight, specular );//Rim/Lighting
    fragData3 = vec4(ex_VertexCameraPosition,1.0f);
}

 

//Vertex
#version 400
#define MAX_INSTANCES 256

//Uniforms
uniform vec4 materialcolordiffuse;
uniform mat4 cameramatrix;
uniform mat4 camerainversematrix;
uniform mat4 projectioncameramatrix;
uniform instancematrices { mat4 matrix[MAX_INSTANCES];} entity;
uniform vec4 clipplane0 = vec4(0.0);

//Attributes
in vec3 vertex_position;
in vec4 vertex_color;
in vec2 vertex_texcoords0;
in vec3 vertex_normal;
in vec3 vertex_tangent;
in vec3 vertex_binormal;

//Outputs
out vec4 ex_vertexposition;
out vec4 ex_color;
out vec2 ex_texcoords0;
out vec2 ex_texcoords1;
out float ex_selectionstate;
out vec3 ex_normal;
out vec3 ex_tangent;
out vec3 ex_binormal;
out float clipdistance0;
out vec3 ex_VertexCameraPosition;

void main()
{
    mat4 entitymatrix = entity.matrix[gl_InstanceID];
    mat4 entitymatrix_=entitymatrix;
    entitymatrix_[0][3]=0.0;
    entitymatrix_[1][3]=0.0;
    entitymatrix_[2][3]=0.0;
    entitymatrix_[3][3]=1.0;
    
    ex_vertexposition = entitymatrix_ * vec4(vertex_position, 1.0);
    
    //Clip planes
    if (length(clipplane0.xyz)>0.0001)
    {
        clipdistance0 = ex_vertexposition.x*clipplane0.x + ex_vertexposition.y*clipplane0.y + ex_vertexposition.z*clipplane0.z + clipplane0.w;
    }
    else
    {
        clipdistance0 = 0.0;
    }        
    
    gl_Position = projectioncameramatrix * ex_vertexposition;

    mat3 nmat = mat3(entitymatrix);
    ex_normal = normalize(nmat * vertex_normal);    
    ex_tangent = normalize(nmat * vertex_tangent);
    ex_binormal = normalize(nmat * vertex_binormal);

    ex_texcoords0 = vertex_texcoords0;
    
    ex_color = vec4(entitymatrix[0][3],entitymatrix[1][3],entitymatrix[2][3],entitymatrix[3][3]);
    
    //If an object is selected, 10 is subtracted from the alpha color.
    //This is a bit of a hack that packs a per-object boolean into the alpha value.
    ex_selectionstate = 0.0;
    if (ex_color.a<-5.0)
    {
        ex_color.a += 10.0;
        ex_selectionstate = 1.0;
    }
    ex_color *= vec4(1.0-vertex_color.r,1.0-vertex_color.g,1.0-vertex_color.b,vertex_color.a) * materialcolordiffuse;
}

 

rimlight.jpg

  • Like 1
  • Thanks 1
Link to post

Actually I made a mistake above I multiplied the lightPosition, not the cameraposition:

    vec3 lightVector = normalize(lightPosition * modelvertexposition.xyz);//lightVector

    vec3 viewVector = normalize(cameraposition - modelvertexposition.xyz);//viewVector
 

Link to post

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Facebook Twitter Youtube Github Steam
×
×
  • Create New...