2

I am trying to modify the color of a 3d model (three.js) which uses GLSL shaders (frag and vert files). To be honest I am not experienced at all with shader language.

.frag file

precision highp float;

uniform sampler2D uTexture;

varying vec2 vPUv;
varying vec2 vUv;

void main() {
    vec4 color = vec4(0.0);
    vec2 uv = vUv;
    vec2 puv = vPUv;

    // pixel color
    vec4 colA = texture2D(uTexture, puv);

    // greyscale
    float grey = colA.r * 0.31 + colA.g * 0.71 + colA.b * 0.07;
    vec4 colB = vec4(grey, grey, grey, 1.0);

    // circle
    float border = 0.3;
    float radius = 0.5;
    float dist = radius - distance(uv, vec2(0.5));
    float t = smoothstep(0.0, border, dist);

    // final color
    color = colB;
    color.a = t;

    gl_FragColor = color;
}

.vert file

precision highp float;

attribute float pindex;
attribute vec3 position;
attribute vec3 offset;
attribute vec2 uv;
attribute float angle;

uniform mat4 modelViewMatrix;
uniform mat4 projectionMatrix;

uniform float uTime;
uniform float uRandom;
uniform float uDepth;
uniform float uSize;
uniform vec2 uTextureSize;
uniform sampler2D uTexture;
uniform sampler2D uTouch;

varying vec2 vPUv;
varying vec2 vUv;

#pragma glslify: snoise2 = require(glsl-noise/simplex/2d)

float random(float n) {
    return fract(sin(n) * 43758.5453123);
}

void main() {
    vUv = uv;

    // particle uv
    vec2 puv = offset.xy / uTextureSize;
    vPUv = puv;

    // pixel color
    vec4 colA = texture2D(uTexture, puv);
    float grey = colA.r * 0.21 + colA.g * 0.71 + colA.b * 0.07;

    // displacement
    vec3 displaced = offset;
    // randomise
    displaced.xy += vec2(random(pindex) - 0.5, random(offset.x + pindex) - 0.5) * uRandom;
    float rndz = (random(pindex) + snoise_1_2(vec2(pindex * 0.1, uTime * 0.1)));
    displaced.z += rndz * (random(pindex) * 2.0 * uDepth);
    // center
    displaced.xy -= uTextureSize * 0.5;

    // touch
    float t = texture2D(uTouch, puv).r;
    displaced.z += t * 20.0 * rndz;
    displaced.x += cos(angle) * t * 20.0 * rndz;
    displaced.y += sin(angle) * t * 20.0 * rndz;

    // particle size
    float psize = (snoise_1_2(vec2(uTime, pindex) * 0.5) + 2.0);
    psize *= max(grey, 0.2);
    psize *= uSize;

    // final position
    vec4 mvPosition = modelViewMatrix * vec4(displaced, 1.0);
    mvPosition.xyz += position * psize;
    vec4 finalPosition = projectionMatrix * mvPosition;

    gl_Position = finalPosition;
}

This creates particles from a very dark grey tone up to white like you see in the example. I would like to change only the color of the very dark tones to match the background color. I've played with some color values I've found here but unfortunately the results are not what I expected. enter image description here

Maybe somebody has a quick hint for me?

1 Answers1

0

I would like to change only the color of the very dark tones to match the background color.

Actually you create a gray scale color. But what you actually want is that the "dark tones to match the background" and the light tones are white. Hence you want a gradient from the background to white.

Either blend a white color with the back ground dependent on the grayscale:

void main()
{
    vec4 color = vec4(0.0);

    // [...]

    // final color
    color.rgb = vec3(1.0);
    color.a = t * grey;
    
    gl_FragColor = color;
}

You have to mix the back ground color and white dependent on the gray scale. For this you have to know the background color in the fragment shader:

void main()
{
    vec4 color = vec4(0.0);
    vec3 backgroundColor = vec3(42.0, 67.0, 101.0) / 255.0;

    // [...]

    // final color
    color.rgb = mix(backgroundColor.rgb, vec3(1.0), gray);
    color.a = t;

    gl_FragColor = color;
}
Rabbid76
  • 202,892
  • 27
  • 131
  • 174
  • hey thanks for your clarification! still not sure where exactly I have to put your code. I've copied to the bottom of my .frag file and replaced the gl_FragColor line with it. How can I define the "backgroundColor" here? also why do you add vec4 and backgroundColor on the top? – ccc1da70-5e63-4879-a4cb-adb604 Sep 27 '20 at 07:05
  • @MarcMintel I've changes the answer. The background color can be a constant in the shader or you can by stored in a [Uniform](https://www.khronos.org/opengl/wiki/Uniform_(GLSL)) variable. A uniform variable has to be set by the application. Anyway I've provided 2 solutions. The first one should work, too. – Rabbid76 Sep 27 '20 at 07:09
  • thanks for your fast response! I just tried passing rgb values to `vec3 backgroundColor = vec3(0.42, 0.67, 0.101);` but I expected them to be blue, instead it's green. My rgb values are simply `(42, 67, 101)`, also changing them to `vec3 backgroundColor = vec3(42, 67, 101);` doesn't lead to expected result. – ccc1da70-5e63-4879-a4cb-adb604 Sep 27 '20 at 07:14
  • @MarcMintel `vec3 backgroundColor = vec3(42.0, 67.0, 101.0) / 255.0;` – Rabbid76 Sep 27 '20 at 07:18