0
$\begingroup$

I was following this guide for drawing circles using shadertoy. Now I am trying to mimic the examples behaviour in WebGL.

Here is a working shadertoy example I try to mimic. The code is not mine, see link above:

float Circle(vec2 uv, vec2 p, float r, float blur) {
    float d = length(uv-p);
    float c = smoothstep(r, r - blur, d);
    return c;
}

void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
    // Normalized pixel coordinates (from 0 to 1)
    vec2 uv = fragCoord.xy/iResolution.xy;
    uv -= .5;
    uv.x *= iResolution.x / iResolution.y;

    float c = Circle(uv, vec2(.2, -.1), .1, .01);

    // Output to screen
    fragColor = vec4(vec3(c), 1.0);
}

And this is the fragment shader I am using:

#version 300 es
precision mediump float;

uniform vec2 iResolution;

out vec4 outColor;

float Circle(vec2 uv, vec2 p, float r, float blur) {
    float d = length(uv-p);
    float c = smoothstep(r, r - blur, d);
    return c;
}

void main()
{
    // Normalized pixel coordinates (from 0 to 1)
    vec2 uv = gl_FragCoord.xy/iResolution.xy;
    uv -= .5;
    uv.x *= iResolution.x / iResolution.y;

    float c = Circle(uv, vec2(-.5, .2), .1, .01);

    // I am discarding all "blackish" values in order to discard "transparent" pixels
    if (c < .1 ){
        discard;
    }
    outColor = vec4(vec3(c), 1.0);
}

I am using another program before rendering this one for transparency I am discarding some pixels, see comment.

And this is the my drawing class, basically I am drawing two Triangles:

class Hud {
  constructor(gl, hudShader) {
    this.hudShader = hudShader;
    this.gl = gl;
    this.glCanvas = document.getElementById("glcanvas");

    const positionBuffer = this.gl.createBuffer();
    gl.bindBuffer(this.gl.ARRAY_BUFFER, positionBuffer);

    gl.bufferData(
      gl.ARRAY_BUFFER,
      new Float32Array([
        -1.0, -1.0,
        1.0, -1.0,
        -1.0, 1.0,
        -1.0, 1.0,
        1.0, -1.0,
        1.0, 1.0
      ]),
      this.gl.STATIC_DRAW
    );
  }

  Update() {}

  Draw() {
    this.gl.useProgram(this.hudShader.program);

    this.gl.uniform2f(
      this.hudShader.config.uniformLocations.iResolution,
      this.glCanvas.clientWidth,
      this.glCanvas.clientHeight
    );

    this.gl.enableVertexAttribArray(
      this.hudShader.config.attributeLocations.position
    );
    this.gl.vertexAttribPointer(
      this.hudShader.config.attributeLocations.position,
      2, this.gl.FLOAT, false, 0, 0);

    this.gl.drawArrays(gl.TRIANGLES, 0, 6);
  }
}

This produces weird behaviour. For example the position of the circle does not correspond to the example. Also if I scale the viewport the circle seems to change position and scale:

enter image description here

What am I doing wrong?

$\endgroup$
0
$\begingroup$

I did not go into much detail with your code but the first thing that comes to mind is that you are rendering with respect to the resolution passed into the shader.

ec2 uv = fragCoord.xy/iResolution.xy;

hope this helps.

maybe do an aspect Ratio calculation ?

float aspect = float(iResolution.x) / float(iResolution.y ? iResolution.y: 1);
$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.