For some reason I cannot access the values from user input into the text fields I set up in my HTML document, when I use document.getElementbyId().value in my JS file. I've checked everything and can't find the issue. Could someone direct me to the right solution?
UPDATE: Here is a clearer explanation of the problem and output:
I am trying to make a customizable (by color and # of triangles), triangle fan. When I try to access any values inputted I believe they return null, because I cannot get a numeric value to use for the fan's RGB, thus I just get a black square as output (the background canvas).
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Rendering (colorful)</title>
<body>
<p> Number of Triangles <input id="numTris" type="number"></p>
<p>
R1 <input id="R1" type="number"/>
G1 <input id="G1" type="number"/>
B1 <input id="B1" type="number">
</p>
<p>
R2 <input id="R2" type="number"/>
G2 <input id="G2" type="number"/>
B2 <input id="B2" type="number"/>
</p>
<p>
<input type="button" onclick="solid(); start()" value="Solid?">
<input type="button" onclick="interp(); start()" value="Interpolated?">
</p>
<script type="text/javascript" src="js/rendering-filled-circle.js"></script>
</body>
<script type="text/javascript">
// WebGL rendering context
var colorType = false;
var size = height;
var gl = null;
function solid(){
colorType = true;
}
function interp(){
colorType = false;
}
function draw() {
renderTriangle(gl);
}
function start() {
var canvas = document.getElementById("canvas");
// Initialize the OpenGL rendering context
gl = canvas.getContext("experimental-webgl");
// Only continue if WebGL is available and working
if (gl) {
// initialize shader programs
initShaders(gl);
// initialize a very simple scene, a triangle
initBuffers(gl, colorType, size);
// call the draw() function every 20 milliseconds
setInterval(draw, 20);
}
else {
alert("WebGL initialization failed! Your browser does not support WebGL or it is not properly configured.");
}
}
</script>
</head>
<body
<center>
<canvas id="canvas" width="800" height="800">
If you are seeing this message your web browser does not support the HTML5 <canvas>> element.
</canvas>
</center>
</body>
</html>
Let me know if you have any questions!
Thank you
UPDATE: Here is the JS which features the .value usage and yes I know I do not use the RGB values yet.
var shaderProgram = null;
var vertexBuffer = null;
var vertexColorBuffer = null;
var aPositionIndex = -1;
var aVertexColor = -1;
var r1 = document.getElementById("R1").value;
var g1 = document.getElementById("G1").value;
var b1 = document.getElementById("B1").value;
var r2 = document.getElementById("R2").value;
var g2 = document.getElementById("G2").value;
var b2 = document.getElementById("B2").value;
var numTriangles = document.getElementById("numTris").value;
var numSides = numTriangles * numTriangles;
var numVertices = numTriangles * 3.0;
var PI2 = 2.0 * 3.1415926535897932384626433832795;
///// Initialize the data buffer to pass to the rendering pipeline
///// the geometry and its attributes.
function colorConverter(val){
if(val < 0){
val = 0;
}
if(val > 255){
val = 255;
}
val = val/255.0;
return val;
}
function initBuffers(gl, colorType, size) {
var coloring = colorType;
r1 = colorConverter(r1);
g1 = colorConverter(g1);
b1 = colorConverter(b1);
r2 = colorConverter(r2);
g2 = colorConverter(g2);
b2 = colorConverter(b2);
var radius = size/2;
var xVal = 0.0;
var yVal = 1.0;
triangleVertices = new Float32Array(numVertices * 2);
triangleVertices[0] = xVal;
triangleVertices[1] = yVal;
for(a = 2; a < numVertices*2; a++){
triangleVertices[a] = xVal + (radius * Math.cos(a * PI2 / numSides));
a += 1;
triangleVertices[a] = yVal + (radius * Math.sin(a * PI2 / numSides));
}
triangleVerticesColor = new Float32Array(numVertices*3);
for(a = 0; a < numVertices*3; a++){
if(coloring == true){
var v = 1.0;
}
else{
v = 0.5;
}
triangleVerticesColor[a] = v;
}
vertexBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
gl.bufferData(gl.ARRAY_BUFFER, triangleVertices, gl.STATIC_DRAW);
gl.bindBuffer(gl.ARRAY_BUFFER, null);
vertexColorBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, vertexColorBuffer);
gl.bufferData(gl.ARRAY_BUFFER, triangleVerticesColor, gl.STATIC_DRAW);
gl.bindBuffer(gl.ARRAY_BUFFER, null);
}
///// Define and compile a very simple shader.
function initShaders(gl) {
var vertexShaderSource = "\
attribute vec3 a_position; \n\
attribute vec3 a_color; \n\
varying vec3 vertexcolor; \n\
void main(void) \n\
{ \n\
vertexcolor = a_color; \n\
gl_Position = vec4(a_position, 1.0); \n\
} \n\
";
var fragmentShaderSource = "\
precision highp float; \n\
varying vec3 vertexcolor; \n\
void main(void) \n\
{ \n\
gl_FragColor = vec4(vertexcolor, 1.0); \n\
} \n\
";
// create the vertex shader
var vertexShader = gl.createShader(gl.VERTEX_SHADER);
gl.shaderSource(vertexShader, vertexShaderSource);
gl.compileShader(vertexShader);
// create the fragment shader
var fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);
gl.shaderSource(fragmentShader, fragmentShaderSource);
gl.compileShader(fragmentShader);
// Create the shader program
shaderProgram = gl.createProgram();
gl.attachShader(shaderProgram, vertexShader);
gl.attachShader(shaderProgram, fragmentShader);
gl.linkProgram(shaderProgram);
// If creating the shader program failed, we show compilation and linking errors.
if (!gl.getProgramParameter(shaderProgram, gl.LINK_STATUS)) {
alert("Unable to initialize the shader program.");
var str = "";
str += "VS:\n" + gl.getShaderInfoLog(vertexShader) + "\n\n";
str += "FS:\n" + gl.getShaderInfoLog(fragmentShader) + "\n\n";
str += "PROG:\n" + gl.getProgramInfoLog(shaderProgram);
alert(str);
}
}
///// Draw the given triangle interpolating vertices color.
function renderTriangle(gl) {
// Clear the framebuffer of the rendering context
gl.clearColor(0.0, 0.0, 0.0, 1.0);
gl.clear(gl.COLOR_BUFFER_BIT);
// enable the current shader program
gl.useProgram(shaderProgram);
// connect the buffer containing the vertices of the triangle with the position attribute
gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
aPositionIndex = gl.getAttribLocation(shaderProgram, "a_position");
gl.enableVertexAttribArray(aPositionIndex);
gl.vertexAttribPointer(aPositionIndex, 3, gl.FLOAT, false, 0, 0);
// connect the buffer containing the color of each vertex with the color attribute
gl.bindBuffer(gl.ARRAY_BUFFER, vertexColorBuffer);
aVertexColor = gl.getAttribLocation(shaderProgram, "a_color");
gl.enableVertexAttribArray(aVertexColor);
gl.vertexAttribPointer(aVertexColor, 3, gl.FLOAT, false, 0, 0);
// start to draw (!)
gl.drawArrays(gl.TRIANGLES, 0, numVertices);
// disable the current shading program
gl.useProgram(null);
}
I changed your code a bit. See if it works:
<html>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Rendering (colorful)</title>
<body>
<p> Number of Triangles <input id="numTris" type="number"></p>
<p>
R1 <input id="R1" type="number"/>
G1 <input id="G1" type="number"/>
B1 <input id="B1" type="number">
</p><p>
R2 <input id="R2" type="number"/>
G2 <input id="G2" type="number"/>
B2 <input id="B2" type="number"/>
</p><p>
<input type="button" onclick="solid(); start()" value="Solid?">
<input type="button" onclick="interp(); start()" value="Interpolated?">
</p>
<script type="text/javascript" src="js/rendering-filled-circle.js"></script>
<center>
<canvas id="canvas" width="800" height="800">
If you are seeing this message your web browser does not support the HTML5 <canvas> element.
</canvas>
</center>
</body>
<script type="text/javascript">
// WebGL rendering context
var colorType = false;
var size = height;
var gl = null;
function solid(){
colorType = true;
}
function interp(){
colorType = false;
}
function draw() {
renderTriangle(gl);
}
function start() {
var canvas = document.getElementById("canvas");
// Initialize the OpenGL rendering context
gl = canvas.getContext("experimental-webgl");
// Only continue if WebGL is available and working
if (gl) {
// initialize shader programs
initShaders(gl);
// initialize a very simple scene, a triangle
initBuffers(gl, colorType, size);
// call the draw() function every 20 milliseconds
setInterval(draw, 20);
}
else {
alert("WebGL initialization failed! Your browser does not support WebGL or it is not properly configured.");
}
}
</script>
</html>
In my JS, I was trying to set global variables to the values from the input boxes in my HTML.
In my HTML I called functions that were within the JS, but of course these functions had no access to the global variables with the proper values, because these values were not set yet.
I fixed the problem by simply calling getElementByID() within the individual functions in my JS that my HTML was calling, instead of doing so outside the functions, as global variables.
Related
I've been working on a WebGl animation program where there are buttons that you can choose to alter a triangle vertice location based on where you click on the screen as well as a slider that runs a recursive function that divides the triangle based on the input. The part i'm stuck on is my last radio button that is supposed to constantly rotate my triangle including the edits to whatever previous changed were made to the triangle with the buttons.
Every time I run my application it gives me a warning pointing to javascript line 149 my render2 function: gl.uniform1f(thetaLoc, theta); saying: sierpinski-extended.js:149 WebGL: INVALID_OPERATION: uniform1f: location not for current program.
The code below isn't going to work because I need to add external libraries and i'm not sure how to. Though I have uploaded my project on my website: https://www.cis.gvsu.edu/~nunezjo/labs/sierpinski-extended/sierpinski-extended.html
Here's an example of my working rotation with no other attributes or buttons added to the mix.
https://www.cis.gvsu.edu/~nunezjo/labs/triangle-rotate/triangle-rotate.html
You can inspect element there if needed. Any help would be awesome! I'm so stuck.
JAVASCRIPT
"use strict";
var canvas;
var gl;
var points = [];
var numTimesToSubdivide = 0;
var theta = 0.0;
var thetaLoc;
var x1 = -1;
var y1 = -1;
var x2 = 0;
var y2 = 1;
var x3 = 1;
var y3 = -1;
function init() {
canvas = document.getElementById("gl-canvas");
gl = WebGLUtils.setupWebGL(canvas);
if (!gl) {
alert("WebGL isn't available");
}
//
// Initialize our data for the Sierpinski Gasket
//
// First, initialize the corners of our gasket with three points.
var vertices = [
vec2(x1, y1),
vec2(x2, y2),
vec2(x3, y3)
];
divideTriangle(vertices[0], vertices[1], vertices[2],
numTimesToSubdivide);
//
// Configure WebGL
//
gl.viewport(0, 0, canvas.width, canvas.height);
gl.clearColor(1.0, 1.0, 1.0, 1.0);
// Load shaders and initialize attribute buffers
var program = initShaders(gl, "vertex-shader", "fragment-shader");
gl.useProgram(program);
// Load the data into the GPU
var bufferId = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, bufferId);
gl.bufferData(gl.ARRAY_BUFFER, 50000, gl.STATIC_DRAW);
gl.bufferSubData(gl.ARRAY_BUFFER, 0, flatten(points));
// Associate out shader variables with our data buffer
var vPosition = gl.getAttribLocation(program, "vPosition");
gl.vertexAttribPointer(vPosition, 2, gl.FLOAT, false, 0, 0);
gl.enableVertexAttribArray(vPosition);
document.getElementById("slider").onchange = function(event) {
numTimesToSubdivide = parseInt(event.target.value);
};
canvas.addEventListener("mouseup", function(event) {
var rect = gl.canvas.getBoundingClientRect();
var newx = (event.clientX - rect.left) / canvas.width * 2 - 1;
var newy = (event.clientY - rect.top) / canvas.height * -2 + 1;
console.log(newx, newy);
var vertex_id = document.querySelector('input[name="vertex"]:checked').value;
if (vertex_id == 0) {
x1 = newx;
y1 = newy;
} else if (vertex_id == 1) {
x2 = newx;
y2 = newy;
} else if (vertex_id == 2) {
x3 = newx;
y3 = newy;
} else {
thetaLoc = gl.getUniformLocation(program, "theta");
render2(vertex_id);
}
});
render1();
};
function triangle(a, b, c) {
points.push(a, b, c);
}
function divideTriangle(a, b, c, count) {
// check for end of recursion
if (count === 0) {
triangle(a, b, c);
} else {
//bisect the sides
var ab = mix(a, b, 0.5);
var ac = mix(a, c, 0.5);
var bc = mix(b, c, 0.5);
--count;
// three new triangles
divideTriangle(a, ab, ac, count);
divideTriangle(c, ac, bc, count);
divideTriangle(b, bc, ab, count);
}
}
window.onload = init;
function render1() {
gl.clear(gl.COLOR_BUFFER_BIT);
gl.drawArrays(gl.TRIANGLES, 0, points.length);
points = [];
requestAnimFrame(init);
}
function render2(button_id) {
gl.clear(gl.COLOR_BUFFER_BIT);
theta += 0.092;// this is the amount that will be rotating the object the bigger the number the faster.
gl.uniform1f(thetaLoc, theta);
gl.drawArrays(gl.TRIANGLE_STRIP, 0, points.length);
while (button_id == 3) { // while rotate button is pressed run loop on render 2 else call init
init(); // running init first so it can keep track if the button_id changes.
requestAnimFrame(render2);
}
}
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8">
<title> Sierpinski Extended</title>
<script id="vertex-shader" type="x-shader/x-vertex">
attribute vec4 vPosition; uniform float theta; void main() { gl_Position = vPosition; float s = sin( theta ); float c = cos( theta ); gl_Position.x = -s * vPosition.y + c * vPosition.x; gl_Position.y = s * vPosition.x + c * vPosition.y; gl_Position.z
= 0.0; gl_Position.w = 1.0; }
</script>
<script id="fragment-shader" type="x-shader/x-fragment">
precision mediump float; void main() { gl_FragColor = vec4( 1.0, 0.0, 0.0, 1.0 ); }
</script>
<script type="text/javascript" src="../Common/webgl-utils.js"></script>
<script type="text/javascript" src="../Common/initShaders.js"></script>
<script type="text/javascript" src="../Common/MV.js"></script>
<script type="text/javascript" src="sierpinski-extended.js"></script>
</head>
<body>
<div>
recursive steps 0 <input id="slider" type="range" min="0" max="6" step="1" value="0" /> 6
</div>
<div>
Vertex:
<input type="radio" name="vertex" value="0" checked> 0
<input type="radio" name="vertex" value="1"> 1
<input type="radio" name="vertex" value="2"> 2
<input type="radio" name="vertex" value="3"> rotate
</div>
<canvas id="gl-canvas" width="512" height="512">
Oops ... your browser doesn't support the HTML5 canvas element
</canvas>
</body>
</html>
Okay so I'm new to html and javascript right now. My task is to draw circles, I have looked at countless examples and my code doesn't draw anything. Here is what I have so far.
<script id="vertex-shader" type="x-shader/x-vertex">
attribute vec4 vPos;
void main()
{
gl_PointSize = 10.0;
gl_Position = vPos;
}
</script>
<script id="fragment-shader" type="x-shader/x-fragment">
precision mediump float;
uniform vec4 u_color;
void main() {
gl_FragColor = u_color;
}
</script>
<script type="text/javascript" src="webgl-utils.js"></script>
<script type="text/javascript" src="initshaders.js"></script>
<script type="text/javascript" src="lines.js"></script>
<script type="text/javascript">
var canvas;
var gl;
window.onload = init;
function init() {
canvas = document.getElementById("gl-canvas");
gl = WebGLUtils.setupWebGL(canvas);
if (!gl) {
alert("WebGL isn't available");
}
var program = initShaders(gl, "vertex-shader", "fragment-shader");
var vPos = gl.getAttribLocation(program, "vPos");
var colorUniformLocation = gl.getUniformLocation(program, "u_color");
var buffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW);
gl.viewport(0, 0, canvas.width, canvas.height);
gl.clearColor(0.9, 0.9, 0.9, 1.0);
gl.clear(gl.COLOR_BUFFER_BIT);
gl.useProgram(program);
gl.enableVertexAttribArray(vPos);
gl.vertexAttribPointer(vPos, 2, gl.FLOAT, false, 0, 0);
var red = 0.0;
var green = 0.0;
var blue = 1.0;
var vertices = circle(100,100,200);
for (var i=0; i<vertices.length; i++)
{
gl.uniform4f(colorUniformLocation, red, green, blue, 1.0);
gl.drawArrays(gl.POINTS, i, 1);
}
}
</script>
<body>
<canvas id="gl-canvas" width="1000" height="1000">
Oops... your browser doesn't support HTML5's Canvas elements!
</canvas>
</body>
</html>
The error seems to happen at var vertices = circle(100,100,200);
My circle function looks like this.
function getPoints(x,y)
{
var points = [];
points.push(x+x0,y+y0);
points.push(-x+x0,y+y0);
points.push(x+x0,-y+y0);
points.push(-x+x0,-y+y0);
points.push(y+y0,x+x0);
points.push(-y+y0,x+x0);
points.push(y+y0,-x+x0);
points.push(-y+y0,-x+x0);
return points;
}
function circle(x0, y0, radius)
{
var vertices = [];
var points = [];
var pk = 1- radius;
var xk = radius;
var yk = 0;
//var pk = ((xk +1)^2) + ((yk -.5)^2) - (radius^2);
points = getPoints(x0,y0);
for(var i = 0 ; i < points.length; i++)
{
vertices.push(points[i]);
}
while(xk>yk)
{
yk++;
if(pk <0)
{
points = getPoints(xk+1,yk);
pk = pk + (2* yk)+1;
}
else
{
points = getPoints(xk+1,yk-1);
xk--;
pk = pk + (2* yk) -(2* xk)+1;
}
for(var i = 0 ; i < points.length; i++)
{
vertices.push(points[i]);
}
}
return vertices;
}
From what I can tell the algorithm is correct, but for some reason the var vertices isn't returning correctly, because when I launch the file it draws the background but the circle is nowhere to be seen. Please help!
UPDATE
So I have fixed one problem, but my program is still not printing anything out. my circle function now looks like this.
function drawCircle(x0, y0, radius)
{
var vertices = [];
var pk = 1- radius;
var xk = 0;
var yk = radius;
//vertices.push(100,100); I am using these for error checking
//vertices.push(200,100); To see if vertices returns anything at all
//vertices.push(300,100); and from what i can tell it doesnt.
//vertices.push(400,100);
while(xk<yk)
{
xk++;
if(pk <0)
{
pk = pk + (2* xk)+1;
}
else
{
yk--;
pk = pk + (2* xk) -(2* yk)+1;
}
vertices.push(x+x0,y+y0); //This should be adding all symmetric
vertices.push(-x+x0,y+y0); //points from the first one around the
vertices.push(x+x0,-y+y0); //circle
vertices.push(-x+x0,-y+y0);
vertices.push(y+y0,x+x0);
vertices.push(-y+y0,x+x0);
vertices.push(y+y0,-x+x0);
vertices.push(-y+y0,-x+x0);
}
return vertices;
}
I've recently started learning Javascript/ WebGL and I've learned enough to put together a simple Mandelbrot fractal renderer. The program works fine but for some reason it won't let me zoom in more than about 20 times, and it starts looking pixellated if I zoom in more. I've had this problem before in other fractal drawing programs I've made, but it usually doesn't become noticeable until about 2^45 zoom. I was thinking maybe it has to do with the max float size in GLSL, but I'm really not sure what the problem is or even how to go about finding the problem. I was just wondering if anyone knows what the cause of this zoom limit is and if there's any way I can increase it? Here's my HTML/ GLSL code:
<html>
<head>
<title>Mandelbrot Set</title>
<style>
body {
margin = 0;
padding = 0;
}
</style>
</head>
<body>
<h3>Click on the fractal to zoom in.</h3>
<canvas id = "canvas" width = "500" height = "500" onclick = "drawFractal();">
Sorry, your browser does not support HTML5.
</canvas>
<script id = "vertexshader" type = "vertexshader">
attribute vec2 a_position;
void main(){
gl_Position = vec4(a_position, 0, 0);
}
</script>
<script id = "fragmentshader" type = "fragmentshader">
precision mediump float;
uniform vec2 u_resolution;
uniform vec2 u_zoomCenter;
uniform float u_zoom;
uniform int u_maxIterations;
uniform float u_colorDiversity;
vec2 f(vec2 z, vec2 c)
{
return vec2(z.x*z.x - z.y*z.y, z.x*z.y*2.0) + c;
}
// Credit to hughsk on GitHub for this hsv to rgb converter
vec3 hsv2rgb(vec3 c) {
vec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);
vec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www);
return c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y);
}
void main(){
vec2 zeroToOne = gl_FragCoord.xy / u_resolution;
vec2 c = u_zoomCenter + (zeroToOne * 4.0 - vec2(2.0)) / u_zoom;
vec2 z = vec2(0.0);
bool escaped = false;
float iterations = 0.0;
for (int i = 0; i < 100000; i++)
{
if (i > u_maxIterations) break;
z = f(z, c);
if (length(z) > 2.0)
{
escaped = true;
iterations = float(i);
break;
}
}
gl_FragColor = escaped ? vec4(hsv2rgb(vec3(iterations * u_colorDiversity, 1.0, 1.0)), 1.0) : vec4(vec3(0.0), 1.0);
}
</script>
<script src = "webgl.js"></script>
</body>
</html>
Here's my "webgl.js" file:
// Compile and link shaders and create program
function createShader(gl, type, source){
var shader = gl.createShader(type);
gl.shaderSource(shader, source);
gl.compileShader(shader);
if (gl.getShaderParameter(shader, gl.COMPILE_STATUS)) return shader;
console.log(gl.getShaderInfoLog(shader));
gl.deleteShader(shader);
alert("Error: failed to create shader. Check the console for more information.");
}
function createProgram(gl, vertexShader, fragmentShader){
var program = gl.createProgram();
gl.attachShader(program, vertexShader);
gl.attachShader(program, fragmentShader);
gl.linkProgram(program);
if (gl.getProgramParameter(program, gl.LINK_STATUS)) return program;
console.log(gl.getProgramInfoLog(program));
gl.deleteProgram(program);
alert("Error: failed to create program. Check the console for more information.");
}
// WebGL setup
var canvas = document.getElementById("canvas");
var gl = canvas.getContext("webgl");
if (!gl){
var gl = canvas.getContext("experimental-webgl");
console.log("WebGL not supported, falling back on experimental WebGL.");
}
if (!gl){
console.log("Experimental WebGL not supported.");
alert("Your browser does not support WebGL. Check the console for more information.");
}
// Create shaders and program
var vertexShaderSource = document.getElementById("vertexshader").text;
var fragmentShaderSource = document.getElementById("fragmentshader").text;
var vertexShader = createShader(gl, gl.VERTEX_SHADER, vertexShaderSource);
var fragmentShader = createShader(gl, gl.FRAGMENT_SHADER, fragmentShaderSource);
var program = createProgram(gl, vertexShader, fragmentShader);
gl.useProgram(program);
// Set up position buffer
var screen = new Float32Array([
-1, -1,
1, -1,
1, 1,
1, 1,
-1, 1,
-1, -1]);
var positionBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
gl.bufferData(gl.ARRAY_BUFFER, screen, gl.STATIC_DRAW);
// Set up position attribute in vertex shader
var a_positionLocation = gl.getAttribLocation(program, "a_position");
gl.enableVertexAttribArray(a_positionLocation);
gl.vertexAttribPointer(a_positionLocation, 2, gl.FLOAT, false, 0, 0);
// Set up WebGL window
gl.viewport(0, 0, 500, 500);
gl.clearColor(0, 0, 0, 0);
// Set up uniforms in fragment shader
var u_resolutionLocation = gl.getUniformLocation(program, "u_resolution");
var u_zoomCenterLocation = gl.getUniformLocation(program, "u_zoomCenter");
var u_zoomLocation = gl.getUniformLocation(program, "u_zoom");
var u_maxIterationsLocation = gl.getUniformLocation(program, "u_maxIterations");
var u_colorDiversityLocation = gl.getUniformLocation(program, "u_colorDiversity");
gl.uniform2f(u_resolutionLocation, 500, 500);
// Set up some global variables
var offset_x = 0;
var offset_y = 0;
var zoom = 1;
var iterations = 10000;
var colorDiversity = 0.01;
// Update uniforms based on global variables
function updateUniforms()
{
gl.uniform2f(u_zoomCenterLocation, offset_x, offset_y);
gl.uniform1f(u_zoomLocation, zoom);
gl.uniform1i(u_maxIterationsLocation, iterations);
gl.uniform1f(u_colorDiversityLocation, colorDiversity);
}
// Get mouse position
function getMousePos() {
var rect = canvas.getBoundingClientRect();
return [(event.clientX - rect.left - 250) / 125, (event.clientY - rect.top - 250) / 125];
}
// Draw the fractal
function drawFractal() {
mousePos = getMousePos();
offset_x += mousePos[0] / zoom;
offset_y -= mousePos[1] / zoom;
zoom *= 2;
updateUniforms();
gl.drawArrays(gl.TRIANGLES, 0, 6);
}
// Draw fractal when the page loads
updateUniforms();
gl.drawArrays(gl.TRIANGLES, 0, 6);
Maximal possible zoom depends on the precision of the floating point number you use and your algorithm.
You can increase precision using arbitrary precision numbers, for example mpfr, mpc or arb library
I am under a situation that i have two canvas, and i want to display the same object in both canvas (in fact i have to display different objects in each canvas, but i want to start by showing same object in both), but i am not able to do this,
could some one please hlep me in doing this ?
My try to do it is: (i have two canvas (canvas ans canvas2) in grey and it display mutiple square in both, but it is displayed in only one), how to display in both.
My code to try is :
<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head>
<script class="WebGL">
var gl,gl2;
function createProgram(gl, vertexShader, fragmentShader)
{
var vs = gl.createShader(gl.VERTEX_SHADER);
gl.shaderSource(vs, vertexShader);
gl.compileShader(vs);
if (!gl.getShaderParameter(vs, gl.COMPILE_STATUS))
alert(gl.getShaderInfoLog(vs));
//////
var fs = gl.createShader(gl.FRAGMENT_SHADER);
gl.shaderSource(fs, fragmentShader);
gl.compileShader(fs);
if (!gl.getShaderParameter(fs, gl.COMPILE_STATUS))
alert(gl.getShaderInfoLog(fs));
program = gl.createProgram();
gl.attachShader(program, vs);
gl.attachShader(program, fs);
gl.linkProgram(program);
if (!gl.getProgramParameter(program, gl.LINK_STATUS))
alert(gl.getProgramInfoLog(program));
return program;
}
function createShaderFromScriptElement(gl , shaderName)
{
var Shader = document.getElementById(shaderName).firstChild.nodeValue;
return Shader;
}
function start()
{
var canvas = document.getElementById("canvas");
canvas2 = document.getElementById("canvas2");
gl = canvas.getContext("experimental-webgl");
gl2 = canvas2.getContext("experimental-webgl");
if (!gl) { alert("error while GL load"); }
if (!gl2) { alert("error while GL load"); }
// var vertexShader2 = createShaderFromScriptElement(gl, "2d-vertex-shader");
// var fragmentShader2 = createShaderFromScriptElement(gl, "2d-fragment-shader");
var vertexShader = createShaderFromScriptElement(gl, "2d-vertex-shader");
var fragmentShader = createShaderFromScriptElement(gl, "2d-fragment-shader");
var program = createProgram(gl, vertexShader, fragmentShader);
gl.useProgram(program);
var positionLocation = gl.getAttribLocation(program, "a_position");
var colorLocation = gl.getUniformLocation(program, "u_color");
var resolutionLocation = gl.getUniformLocation(program, "u_resolution");
var buffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
gl.uniform2f(resolutionLocation, 200, 200);
gl.enableVertexAttribArray(positionLocation);
gl.vertexAttribPointer(positionLocation, 2, gl.FLOAT, false, 0, 0);
for (var ii = 0; ii < 5005; ++ii)
{
// Setup a random rectangle
setRectangle(gl, randomInt(300), randomInt(300), 50, 50);
// Set a random color.
gl.uniform4f(colorLocation, Math.random(), Math.random(), Math.random(), 1);
// Draw the rectangle.
gl.drawArrays(gl.TRIANGLES, 0, 3);
gl2.drawArrays(gl2.TRIANGLES, 0, 3);
}
function randomInt(range)
{
return Math.floor(Math.random() * range);
}
// Fills the buffer with the values that define a rectangle.
function setRectangle(gl, x, y, width, height)
{
var x1 = x;
var x2 = x + width;
var y1 = y;
var y2 = y + height;
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([
x1, y1,
x1, -y1,
-x1, y1,
]), gl.STATIC_DRAW);
}
}
</script>
<script id="2d-vertex-shader" type="x-shader/x-vertex">
attribute vec2 a_position;
uniform vec2 u_resolution;
void main() {
// convert the rectangle from pixels to 0.0 to 1.0
vec2 zeroToOne = a_position / u_resolution;
// convert from 0->1 to 0->2
vec2 zeroToTwo = zeroToOne * 2.0;
// convert from 0->2 to -1->+1 (clipspace)
vec2 clipSpace = zeroToTwo - 1.0;
gl_Position = vec4(clipSpace* vec2(1, -1), 0, 1);
}
</script>
<script id="2d-fragment-shader" type="x-shader/x-fragment">
precision mediump float;
uniform vec4 u_color;
void main()
{
gl_FragColor = u_color; // green
}
</script>
</head>
<body onload="start()">
<div style="text-align: center">
</div>
<table style="width:100%; height: 10%;">
<tr>
<td style="width:200px; max-width:200px; background-color:gray ">
<canvas id="canvas" width="300" height="300"></canvas>
</td>
<td style="width:200px; max-width:200px; background-color:gray; ">
<canvas id="canvas2" width="300" height="300"></canvas>
</td>
</tr>
</table>
</body>
</html>
No, unfortunately you can not share WebGL objects across canvases in WebGL 1.0
What are you trying to accomplish?
Some solutions:
Split 1 canvas
If you need multiple views like many 3D modeling programs you can split a single canvas using gl.enable(gl.SCISSOR_TEST), gl.scissor and gl.viewport. Here's one example
Draw to one canvas, then copy to other canvases
In this case you render to an offscreen canvas with WebGL then
use multiple visible canvas 2d canvases to display by using
drawImage.
gl = offscreenCanvas.getContext("webgl");
ctx1 = onscreenCanvas1.getContext("2d");
ctx2 = onscreenCanvas2.getContext("2d");
// render whatever you want to appear in onscreenCanvas1
renderScene(scene1Settings, gl);
// copy the result to offscreenCanvas1
ctx1.drawImage(gl.canvas, ...);
// render whatever you want to appear in onscreenCanvas2
renderScene(scene2Settings, gl);
// copy the result to offsceenCanvas2
ctx2.drawImage(gl,canvas, ...);
Make 1 canvas the size of the window, put it in the background, use the first technique (scissor, viewport) and getBoundingClientRect to render exactly where some other element is.
In this case you make a single WebGL canvas the size of the window
and using CSS put it in the background. Then you create a placeholder
<div> or other element to represent where you want a canvas to
appear.
You can then ask the browser exactly where that element appears and
use that info to set the viewport and scissor and then render to
that area to make it appear like it's a canvas
Example1,
Example2
var canvas = document.getElementById("canvas"),
canvas2 = document.getElementById("canvas2");
gl = canvas.getContext("experimental-webgl");
gl2 = canvas.getContext("experimental-webgl");
I think you missed the reference to the second canvas element
I have to draw sphere using multiple squares(i am also allowed to use triangles even, but i found some existing code for help in square, so i used it). I have successfully drawn multiple squares (5000).But i don't have to use any inbuit function to create sphere . My code is below :
<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head>
<script class="WebGL">
var gl;
function createProgram(gl, vertexShader, fragmentShader)
{
var vs = gl.createShader(gl.VERTEX_SHADER);
gl.shaderSource(vs, vertexShader);
gl.compileShader(vs);
if (!gl.getShaderParameter(vs, gl.COMPILE_STATUS))
alert(gl.getShaderInfoLog(vs));
//////
var fs = gl.createShader(gl.FRAGMENT_SHADER);
gl.shaderSource(fs, fragmentShader);
gl.compileShader(fs);
if (!gl.getShaderParameter(fs, gl.COMPILE_STATUS))
alert(gl.getShaderInfoLog(fs));
program = gl.createProgram();
gl.attachShader(program, vs);
gl.attachShader(program, fs);
gl.linkProgram(program);
if (!gl.getProgramParameter(program, gl.LINK_STATUS))
alert(gl.getProgramInfoLog(program));
return program;
}
function createShaderFromScriptElement(gl , shaderName)
{
var Shader = document.getElementById(shaderName).firstChild.nodeValue;
return Shader;
}
function start()
{
var canvas = document.getElementById("canvas");
gl = canvas.getContext("experimental-webgl");
if (!gl) { alert("error while GL load"); }
var vertexShader = createShaderFromScriptElement(gl, "2d-vertex-shader");
var fragmentShader = createShaderFromScriptElement(gl, "2d-fragment-shader");
var program = createProgram(gl, vertexShader, fragmentShader);
gl.useProgram(program);
var positionLocation = gl.getAttribLocation(program, "a_position");
var colorLocation = gl.getUniformLocation(program, "u_color");
var resolutionLocation = gl.getUniformLocation(program, "u_resolution");
var buffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
gl.uniform2f(resolutionLocation, 200, 200);
gl.enableVertexAttribArray(positionLocation);
gl.vertexAttribPointer(positionLocation, 2, gl.FLOAT, false, 0, 0);
for (var ii = 0; ii < 5000; ++ii)
{
// Setup a random rectangle
setRectangle(gl, randomInt(300), randomInt(300), 10, 10);
// Set a random color.
gl.uniform4f(colorLocation, Math.random(), Math.random(), Math.random(), 1);
// Draw the rectangle.
gl.drawArrays(gl.TRIANGLES, 0, 6);
}
function randomInt(range)
{
return Math.floor(Math.random() * range);
}
// Fills the buffer with the values that define a rectangle.
function setRectangle(gl, x, y, width, height)
{
var x1 = x;
var x2 = x + width;
var y1 = y;
var y2 = y + height;
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([
x1, y1,
x2, y1,
x1, y2,
x1, y2,
x2, y1,
x2, y2]), gl.STATIC_DRAW);
}
}
</script>
<script id="2d-vertex-shader" type="x-shader/x-vertex">
attribute vec2 a_position;
uniform vec2 u_resolution;
void main() {
// convert the rectangle from pixels to 0.0 to 1.0
vec2 zeroToOne = a_position / u_resolution;
// convert from 0->1 to 0->2
vec2 zeroToTwo = zeroToOne * 2.0;
// convert from 0->2 to -1->+1 (clipspace)
vec2 clipSpace = zeroToTwo - 1.0;
gl_Position = vec4(clipSpace* vec2(1, -1), 0, 1);
}
</script>
<script id="2d-fragment-shader" type="x-shader/x-fragment">
precision mediump float;
uniform vec4 u_color;
void main()
{
gl_FragColor = u_color; // green
}
</script>
</head>
<body onload="start()">
<div style="text-align: center">
<canvas id="canvas" width="1000" height="800"></canvas>
</div>
</body>
</html>
What i am asked is to draw sphere using multiple objects which i have no idea how to do.And my try was first to draw the multiple objects (5000 in my case) and then try for drawing sphere using it(i mean using these 5000 squares, my next step is to create sphere).
But i don't know how to proceed further to draw sphere using these squares ?
Which i am not able to understand how to do. Could some one please help me ?
One of approaches is constructing sphere from rectangular tiles in vertex shader.
Generally, the thing is to cover [0, 2*M_PI] x [0, M_PI] region with tiles. Say, you have N tiles where N = m*k, m is amount of tiles in a row and k is amount of tiles in column.
You can create N unit squares and assign to each of them its unique position in m * k matrix. Then pass these positions and width/height of tiles (2*M_PI / m and M_PI / k) as uniforms to vertex shader (or as attributes).
In vertex shader knowing position of tile and its width/height compute vertice's coords on [0, 2*M_PI] x [0, M_PI] (they would be phi and ksi). And then compute actual vertex position on sphere:
coord.x = sin(ksi) * cos(phi);
coord.y = sin(ksi) * sin(phi);
coord.z = cos(ksi);
Also note you should set up perspective projection for this.
Choosing m and k is up to you. I recommend to start with square tiles. Here is the picture of result i got this way: