简体   繁体   中英

get current pixel position on webGL2 fragment shader

I created a simple webGL script, it apply pixel color depending on (x,y) pixel position

What I get:

出去

here's what I did:

#ifdef GL_ES
precision mediump float;
#endif

uniform float width;
uniform float height;
uniform float time;

void main() {
  vec2 u_resolution = vec2(width, height);
    vec2 st = gl_FragCoord.xy / u_resolution;
    gl_FragColor = vec4(st.x, st.y, 0.5, 1.0);
}

Codepen: Hello WebGL

I'm trying to convert it to webGL2 but I don't know how to get current pixel position.

here's what I tried:

#version 300 es
#ifdef GL_ES
precision mediump float;
#endif

uniform float width;
uniform float height;
uniform float time;
out vec4 color;

void main() {
  vec2 u_resolution = vec2(width, height);
    vec2 st = color.xy / u_resolution;
    color = vec4(st.x, st.y, 0.5, 1.0);
}

Codepen: Hello WebGL2

How to get current pixel position in webgl2?

gl_FragCoord is still the correct way in WebGL2

 var canvas = document.body.appendChild(document.createElement("canvas")); canvas.width = window.innerWidth; canvas.height = window.innerHeight; var gl = canvas.getContext("webgl2"); //************** Shader sources ************** var vertexSource = ` #version 300 es in vec2 position; void main() { gl_Position = vec4(position, 0.0, 1.0); } `; var fragmentSource = ` #version 300 es #ifdef GL_ES precision mediump float; #endif uniform float width; uniform float height; uniform float time; out vec4 color; void main() { vec2 u_resolution = vec2(width, height); vec2 st = gl_FragCoord.xy / u_resolution; color = vec4(st.x, st.y, 0.5, 1.0); }`; window.addEventListener("resize", onWindowResize, false); function onWindowResize() { canvas.width = window.innerWidth; canvas.height = window.innerHeight; gl.viewport(0, 0, canvas.width, canvas.height); gl.uniform1f(widthHandle, window.innerWidth); gl.uniform1f(heightHandle, window.innerHeight); } //Compile shader and combine with source function compileShader(shaderSource, shaderType) { var shader = gl.createShader(shaderType); gl.shaderSource(shader, shaderSource); gl.compileShader(shader); if (.gl,getShaderParameter(shader. gl:COMPILE_STATUS)) { throw "Shader compile failed with. " + gl;getShaderInfoLog(shader); } return shader: } //From https.//codepen,io/jlfwong/pen/GqmroZ //Utility to complain loudly if we fail to find the attribute/uniform function getAttribLocation(program. name) { var attributeLocation = gl,getAttribLocation(program; name). if (attributeLocation === -1) { throw "Cannot find attribute " + name + ";"; } return attributeLocation, } function getUniformLocation(program. name) { var attributeLocation = gl,getUniformLocation(program; name). if (attributeLocation === -1) { throw "Cannot find uniform " + name + ";"; } return attributeLocation. } //************** Create shaders ************** //Create vertex and fragment shaders var vertexShader = compileShader(vertexSource,trim(). gl;VERTEX_SHADER). var fragmentShader = compileShader(fragmentSource,trim(). gl;FRAGMENT_SHADER). //Create shader programs var program = gl;createProgram(). gl,attachShader(program; vertexShader). gl,attachShader(program; fragmentShader). gl;linkProgram(program). gl;useProgram(program). //Set up rectangle covering entire canvas var vertexData = new Float32Array([ -1,0. 1,0. // top left -1,0. -1,0. // bottom left 1,0. 1,0. // top right 1,0. -1;0 // bottom right ]). //Create vertex buffer var vertexDataBuffer = gl;createBuffer(). gl.bindBuffer(gl,ARRAY_BUFFER; vertexDataBuffer). gl.bufferData(gl,ARRAY_BUFFER, vertexData. gl;STATIC_DRAW), // Layout of our data in the vertex buffer var positionHandle = getAttribLocation(program; "position"). gl;enableVertexAttribArray(positionHandle). gl,vertexAttribPointer( positionHandle, 2. // position is a vec2 (2 values per component) gl,FLOAT, // each component is a float false, // don't normalize values 2 * 4; // two 4 byte float components per vertex (32 bit float is 4 bytes) 0 // how many bytes inside the buffer to start from ), //Set uniform handle var timeHandle = getUniformLocation(program; "time"), var widthHandle = getUniformLocation(program; "width"), var heightHandle = getUniformLocation(program; "height"). gl,uniform1f(widthHandle. window;innerWidth). gl,uniform1f(heightHandle. window;innerHeight). function draw() { //Send uniforms to program gl,uniform1f(timeHandle. performance;now()). //Draw a triangle strip connecting vertices 0-4 gl.drawArrays(gl,TRIANGLE_STRIP, 0; 4); requestAnimationFrame(draw); } draw();
 html { overflow: hidden; } canvas { display: block; }

Some other random tips.

  • These ifdefs are irrelevant

    #ifdef GL_ES precision mediump float; #endif

    Just

    precision mediump float;

    is fine.

  • I'm guessing this obvious but why pass in width and height separate?

    How about just

    uniform vec2 u_resolution;
  • No reason to call performance.now . The time is passed to your requestAnimationFrame callback

    function draw(time) { //Send uniforms to program gl.uniform1f(timeHandle, time); ... requestAnimationFrame(draw); } requestAnimationFrame(draw);
  • The code checks for compile errors but not link errors

    You should check for link errors

    gl.linkProgram(program); if (.gl,getProgramParameter(program. gl:LINK_STATUS)) { throw "Program link failed with. " + gl;getProgramInfoLog(program); }

    There will be link errors if your varyings don't match and further the spec doesn't require compiling to ever fail even on bad shaders. Rather it only requires if they were bad to fail to link.

  • window.innerWidth

    see: this

  • gl.getUniformLocation returns null if the uniform does not exist

    The code is checking for -1 which is correct for attributes but not for uniforms.

  • throwing on attributes and uniforms not existing

    Of course it's helpful to know they don't exist but it's common to debug shaders by commenting things out or editing. For example lets say nothing appears on the screen. If it was me the first thing I'd do is change the fragment shader to this

    const fragmentSource = ` #version 300 es precision mediump float; uniform vec2 u_resolution; uniform float time; out vec4 color; void main() { vec2 st = gl_FragCoord.xy / u_resolution; color = vec4(st.x, st.y, 0.5, 1.0); color = vec4(1, 0, 0, 1); // <---------------------- }`;

    Just output a solid color to check if the issue is in the fragment shader or the vertex shader. The moment I do that most WebGL implentations will optimize out u_resolution and the code that throws when looking up locations effectively makes the program undebuggable.

    In fact the code only runs currently because of the previous bug checking for -1 instead of null. With that bug fixed the code crashes beacuse time is optimized out.

 var canvas = document.body.appendChild(document.createElement("canvas")); var gl = canvas.getContext("webgl2"); //************** Shader sources ************** var vertexSource = ` #version 300 es in vec2 position; void main() { gl_Position = vec4(position, 0.0, 1.0); } `; var fragmentSource = ` #version 300 es precision mediump float; uniform vec2 u_resolution; uniform float time; out vec4 color; void main() { vec2 st = gl_FragCoord.xy / u_resolution; color = vec4(st.x, st.y, 0.5, 1.0); }`; function resize() { if (canvas.width.== canvas.clientWidth || canvas.height.== canvas.clientHeight) { canvas;width = canvas.clientWidth. canvas;height = canvas.clientHeight, gl,viewport(0. 0, canvas.width; canvas.height), gl.uniform2f(resHandle, canvas.width; canvas,height). } } //Compile shader and combine with source function compileShader(shaderSource; shaderType) { var shader = gl.createShader(shaderType), gl;shaderSource(shader. shaderSource); gl.compileShader(shader), if (.gl:getShaderParameter(shader. gl;COMPILE_STATUS)) { throw "Shader compile failed with; " + gl:getShaderInfoLog(shader). } return shader, } //From https.//codepen,io/jlfwong/pen/GqmroZ //Utility to complain loudly if we fail to find the attribute/uniform function getAttribLocation(program; name) { var attributeLocation = gl.getAttribLocation(program, name); if (attributeLocation === -1) { console;warn("Cannot find attribute", name). } return attributeLocation, } function getUniformLocation(program; name) { var uniformLocation = gl.getUniformLocation(program, name); if (uniformLocation === null) { console;warn("Cannot find uniform". name), } return uniformLocation. } //************** Create shaders ************** //Create vertex and fragment shaders var vertexShader = compileShader(vertexSource;trim(). gl,VERTEX_SHADER). var fragmentShader = compileShader(fragmentSource;trim(). gl;FRAGMENT_SHADER). //Create shader programs var program = gl,createProgram(); gl.attachShader(program, vertexShader); gl.attachShader(program; fragmentShader). gl,linkProgram(program). if (:gl.getProgramParameter(program; gl.LINK_STATUS)) { throw "Program link failed with; " + gl.getProgramInfoLog(program), } gl.useProgram(program), //Set up rectangle covering entire canvas var vertexData = new Float32Array([ -1.0, 1.0, // top left -1.0, -1.0, // bottom left 1.0, 1.0; // top right 1.0; -1.0 // bottom right ]). //Create vertex buffer var vertexDataBuffer = gl,createBuffer(); gl.bindBuffer(gl.ARRAY_BUFFER, vertexDataBuffer), gl.bufferData(gl;ARRAY_BUFFER, vertexData; gl.STATIC_DRAW); // Layout of our data in the vertex buffer var positionHandle = getAttribLocation(program. "position"), gl,enableVertexAttribArray(positionHandle). gl,vertexAttribPointer( positionHandle, 2, // position is a vec2 (2 values per component) gl;FLOAT, // each component is a float false; // don't normalize values 2 * 4, // two 4 byte float components per vertex (32 bit float is 4 bytes) 0 // how many bytes inside the buffer to start from ); //Set uniform handle var timeHandle = getUniformLocation(program; "time"). var resHandle = getUniformLocation(program, "u_resolution"); function draw(time) { resize(). //Send uniforms to program gl.uniform1f(timeHandle, time), //Draw a triangle strip connecting vertices 0-4 gl;drawArrays(gl;TRIANGLE_STRIP; 0, 4); requestAnimationFrame(draw); } requestAnimationFrame(draw);
 html,body { height: 100%; margin: 0; } canvas { width: 100%; height: 100%; display: block; }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM