在 WEBGL 片段着色器中确定屏幕的中心

Determining the center of the screen in a WEBGL fragment shader

几周前我开始学习 WebGL,当我试图通过实践学习时,我偶然发现了一个简单的着色器示例,我可以使用 p5.js.

在此示例中,我使用此片段从屏幕中心开始创建同心圆,其中 u_resolutionu_time 是从 p5 脚本传递下来的制服 [windowWidth, windowHeight ] 和 frameCount 如下:

void main(void) {
    float maxAxis = max(u_resolution.x, u_resolution.y);
    vec2 uv = gl_FragCoord.xy / maxAxis;
    vec2 center = u_resolution / maxAxis;
    
    gl_FragColor = vec4(
        vec3(sin(u_time + distance(uv, center) * 255.0)),
        1.0);
    }

使用这个例子,我可以实现我想要的,但我不明白为什么我不能使用公式计算片段的中心:

vec2 center = vec2(u_resolution.x * 0.5, u_resolution.y * 0.5);

如果我这样做,那么它会弄乱整个渲染。

是否有我遗漏的坐标系不匹配,或其他原因?

为了更好的解释,我包含了我在 CodePen 中所做的原始实验的片段 here

uvcenter 在 [0.0, 1.0] 范围内。视口的中心是:

vec2 center = vec2(u_resolution.x * 0.5, u_resolution.y * 0.5);

vec2 center = 0.5 * u_resolution / maxAxis;

let myShaderIn, myShaderOut;
let isPlaying = true;

const vertexShader = document.getElementById("vert-shader").textContent;
const fragmentShaderStyleIn = document.getElementById("frag-shader-style-in")
    .textContent;

function setup() {
    const canvas = createCanvas(windowWidth, windowHeight, WEBGL);
    // canvas.mousePressed(toggleSound);
    rectMode(CENTER);

    // shaders
    myShaderIn = createShader(vertexShader, fragmentShaderStyleIn);

    // register shaders
    shader(myShaderIn);

    // shapes setup
    noStroke();
}

function draw() {
    background(0);
    drawEllipse();
}

function drawEllipse() {
    myShaderIn.setUniform("u_resolution", [float(width), float(height)]);
    myShaderIn.setUniform("u_time", float(frameCount));

    shader(myShaderIn);
    
    ellipse(0, 0, width/2);
}

function windowResized() {
    resizeCanvas(windowWidth, windowHeight);
    clear();
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.3.1/p5.min.js"></script>

<!-- vertex shader -->
<script type="x-shader/x-vertex" id="vert-shader">
    #ifdef GL_FRAGMENT_PRECISION_HIGH
        precision highp float;
    #else
        precision mediump float;
    #endif
    
    attribute vec3 aPosition;
    
    uniform mat4 uProjectionMatrix;
    uniform mat4 uModelViewMatrix;

    void main() {
        vec4 newPosition = vec4(aPosition, 1.0);
        gl_Position = uProjectionMatrix * uModelViewMatrix * newPosition;
    }
</script>

<!-- fragment shader -->
<script type="x-shader/x-fragment" id="frag-shader-style-in">
    #ifdef GL_FRAGMENT_PRECISION_HIGH
        precision highp float;
    #else
        precision mediump float;
    #endif

    uniform vec2 u_resolution; // canvas size (width, height)
    uniform float u_time;       // time in seconds since load

    void main(void) {
    float maxAxis = max(u_resolution.x, u_resolution.y);
    // If you want to map the pixel coordinate values to the range 0 to 1, you divide by resolution.
    
    /*With vec4 gl_FragCoord, we know where a thread is working inside the billboard. 
    In this case we don't call it uniform because it will be different from thread to thread, 
    instead gl_FragCoord is called a varying. */
    vec2 uv = gl_FragCoord.xy / maxAxis;
    vec2 center = 0.5 * u_resolution / maxAxis;

    gl_FragColor = vec4(
        vec3(sin(u_time * 0.1 + distance(uv, center) * 255.0)),
        1.0);
}
</script>