1
$\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$
1
  • $\begingroup$ is iResolution correctly set C-side ? Beside, in your video I see warnings about setDimension. $\endgroup$ Commented Jan 28, 2023 at 16:24

1 Answer 1

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.

vec2 uv = fragCoord.xy/iResolution.xy;

hope this helps.

Maybe calculate the aspect ratio?

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 and acknowledge you have read our privacy policy.

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