【问题标题】:Determining the center of the screen in a WEBGL fragment shader在 WEBGL 片段着色器中确定屏幕的中心
【发布时间】:2021-08-01 01:43:21
【问题描述】:

几周前我开始学习 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 中所做的原始实验的 sn-p 包含在 here 中。

【问题讨论】:

    标签: javascript shader webgl p5.js fragment-shader


    【解决方案1】:

    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>

    【讨论】:

      猜你喜欢
      • 2014-05-17
      • 1970-01-01
      • 2014-09-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-05-30
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多