This JavaScript program demonstrates how to draw a linear spline interpolation in WebGL.
<!DOCTYPE html> <html> <head> <title>XoaX.net's WebGL</title> <script id="idVertexShader" type="c"> attribute vec2 av2Vertex; void main() { gl_Position = vec4(av2Vertex, 0.0, 1.0); } </script> <script id="idFragmantShader" type="c"> precision mediump float; // This will paint the portion of the grid line color over the previous color and return it vec4 DrawGraphLines(vec4 v4InitColor, float fCoord, float fPixelSize, float fGridSpace) { vec4 v4GraphLineColor = vec4(0.85, 0.85, 0.85, 1.0); // Find the closest line - constant time float fSpaceMultiple = fCoord/fGridSpace; float fNearest = floor(fSpaceMultiple+.5); if (fNearest != 0.0) { float fDistToLine = abs(fSpaceMultiple - fNearest); if (fDistToLine < fPixelSize) { float fFill = fDistToLine/fPixelSize; return (1.0 - fFill)*v4GraphLineColor + fFill*v4InitColor; } } return v4InitColor; } vec4 DrawAxis(vec4 v4InitColor, float fCoord, float fPixelSize) { vec4 v4AxisColor = vec4(0.5, 0.5, 0.5, 1.0); float fDistToAxis = abs(fCoord); if (fDistToAxis < fPixelSize) { float fFill = fDistToAxis/fPixelSize; return (1.0 - fFill)*v4AxisColor + fFill*v4InitColor; } return v4InitColor; } vec4 DrawLinearInterpolationGraph(vec4 v4InitColor, float fCoordX, float fCoordY, float fPixelHeight) { vec4 v4GraphColor = vec4(1.0, 0.0, 0.0, 1.0); float faPts[17]; faPts[0] = .3; faPts[1] = .5; faPts[2] = .2; faPts[3] = .1; faPts[4] = -.5; faPts[5] = -.7; faPts[6] = -1.0; faPts[7] = -.9; faPts[8] = -.5; faPts[9] = -.3; faPts[10] = .4; faPts[11] = -.2; faPts[12] = .3; faPts[13] = .6; faPts[14] = .8; faPts[15] = 1.0; faPts[16] = .5; // Find the interval that the point is in. // This would be ideal with non-constant indices, but we do not have that ability. float fPointCount = 17.0; float fInterval = 2.0*(fCoordX + 4.0); int kiIndex = int(floor(fInterval)); float fOffset = (fInterval - float(kiIndex)); float fInterpolatedY = 0.0; // This is an odd way to find the interval for interpolation, but non-constant indices are not allowed. for(int i = 0; i < 17; ++i) { if (i == kiIndex) { float fInterpolatedY = faPts[i]*(1.0 - fOffset) + fOffset*faPts[i + 1]; float fDiffY = abs(fCoordY - fInterpolatedY); if (fDiffY < fPixelHeight) { // Anti-alias by square root of the distance on the other channels float fFill = fDiffY/fPixelHeight; v4InitColor = (1.0 - fFill)*v4GraphColor + fFill*v4InitColor; return v4InitColor; } } } return v4InitColor; } uniform float ufCanvasWidth; uniform float ufCanvasHeight; float fScale = 4.0; float fPixelWidth = fScale*2.0/ufCanvasWidth; float fPixelHeight = fScale*2.0/ufCanvasHeight; void main() { // Scale and shift to the range [-fScale, fScale] // (gl_FragCoord.x, gl_FragCoord.y) is a position in canvas coordinates [0.5, width-.5] and [0.5, height-.5] float fX = fScale*(2.0*gl_FragCoord.x/ufCanvasWidth - 1.0); float fY = fScale*(2.0*gl_FragCoord.y/ufCanvasHeight - 1.0); // Distance from the sin graph in the y direction // Get the background color vec4 v4BackColor = vec4(1.0, 1.0, 1.0, 1.0); vec4 v4GraphColor = vec4(0.0, 1.0, 0.0, 1.0); gl_FragColor = v4BackColor; gl_FragColor = DrawGraphLines(gl_FragColor, fX, fPixelWidth, 1.0); gl_FragColor = DrawGraphLines(gl_FragColor, fY, fPixelHeight, 1.0); gl_FragColor = DrawAxis(gl_FragColor, fX, fPixelWidth); gl_FragColor = DrawAxis(gl_FragColor, fY, fPixelHeight); gl_FragColor = DrawLinearInterpolationGraph(gl_FragColor, fX, fY, 2.0*fPixelHeight); } </script> <script type="text/javascript" src="LinearSplineInterpolation.js"></script> </head> <body onload="Initialization();"> <canvas id="idCanvasWebGL" width="800", height="800" style="border:4px ridge lightgray"></canvas> </body> </html>
var gqProgram = null; var gqGL = null; function CreateProgramAndContext() { // Get the WebGL Context var qCanvas = document.querySelector("#idCanvasWebGL"); gqGL = qCanvas.getContext("webgl"); // Compile the vertex shader var sVertexShaderCode = document.querySelector("#idVertexShader").text; var qVertexShader = gqGL.createShader(gqGL.VERTEX_SHADER); gqGL.shaderSource(qVertexShader, sVertexShaderCode); gqGL.compileShader(qVertexShader); // Compile the fragment shader var sFragmentShaderCode = document.querySelector("#idFragmantShader").text; var qFragmentShader = gqGL.createShader(gqGL.FRAGMENT_SHADER); gqGL.shaderSource(qFragmentShader, sFragmentShaderCode); gqGL.compileShader(qFragmentShader); // Compile and link the program gqProgram = gqGL.createProgram(); gqGL.attachShader(gqProgram, qVertexShader); gqGL.attachShader(gqProgram, qFragmentShader); gqGL.linkProgram(gqProgram); gqGL.useProgram(gqProgram); } function CreateBuffers() { // The vertex buffer for the graph range var faVertices = new Float32Array([1.0, 1.0, -1.0, 1.0, 1.0, -1.0, -1.0, -1.0]); var qVerticesBuffer = gqGL.createBuffer(); gqGL.bindBuffer(gqGL.ARRAY_BUFFER, qVerticesBuffer); gqGL.bufferData(gqGL.ARRAY_BUFFER, faVertices, gqGL.STATIC_DRAW); var qVertexLoc = gqGL.getAttribLocation(gqProgram, 'av2Vertex'); gqGL.vertexAttribPointer(qVertexLoc, 2, gqGL.FLOAT, false, 0, 0); gqGL.enableVertexAttribArray(qVertexLoc); // Unbind the buffer gqGL.bindBuffer(gqGL.ARRAY_BUFFER, null); } function Initialization() { CreateProgramAndContext(); CreateBuffers(); var fCanvasWidth = gqGL.getUniformLocation(gqProgram, 'ufCanvasWidth'); var fCanvasHeight = gqGL.getUniformLocation(gqProgram, 'ufCanvasHeight'); gqGL.uniform1f(fCanvasWidth, gqGL.drawingBufferWidth); gqGL.uniform1f(fCanvasHeight, gqGL.drawingBufferHeight); gqGL.clearColor(0.0, 0.0, 0.0, 1.0); gqGL.clear(gqGL.COLOR_BUFFER_BIT); gqGL.drawArrays(gqGL.TRIANGLE_STRIP, 0, 4); }
© 20072025 XoaX.net LLC. All rights reserved.