cxd4 / opengl-js Goto Github PK
View Code? Open in Web Editor NEWExperimental interface for C-style OpenGL functions for faster cross-testing in JavaScript WebGL.
License: GNU General Public License v3.0
Experimental interface for C-style OpenGL functions for faster cross-testing in JavaScript WebGL.
License: GNU General Public License v3.0
A couple times already, I've stumbled on a strange issue where the order of these mattered.
Really, their order shouldn't matter. The following code:
glColorPointer(number_of_channels, GL_FLOAT, stride, &vertex_cache[0]);
glEnableClientState(GL_COLOR_ARRAY);
... should be equivalent also to saying ...
glEnableClientState(GL_COLOR_ARRAY);
glColorPointer(number_of_channels, GL_FLOAT, stride, &vertex_cache[0]);
You're supposed to be able to switch the two lines around and get the same result, but I've found in some cases that only the former works with my wrapper while the latter style fails. I have yet to see the bug enough times to really pinpoint what the issue is here.
All programs continue to function as they have, but some recent upgrades to modern browsers running over Linux seem to have found a new pickiness with the WebGL specifications. I have yet to have the time to investigate it exactly.
Timestamp: 05/01/2017 01:08:12 AM
Warning: Error: WebGL: linkProgram: Statically used varyings do not fit within packing limits. (see GLSL ES Specification 1.0.17, p111)
Source File: http://cxd4.github.io/OpenGL-js/gl.js
Line: 621
After testing more closely, the amount of RAM (not video RAM but system memory--i.e., CPU RAM as shown in a task manager) sometimes is volatile. It seems to mostly go just up and down repeatedly on WebGL implementations on Microsoft Windows.
I've more recently discovered that on Slackware Linux, FireFox continues to eat up more and more RAM. This eventually gets out of hand until it can lose the context or even freeze kernel responsiveness.
I discovered that my constant re-sourcing and re-compilation of GLSL shaders when modifying vertex attributes through my wrapper is to blame for this. Several resources suggest that compiling GLSL should preferably be a one-time thing. I may have to remove my emulation of glColor4f
to allow myself to have an array of compiled and linked shader programs that I can instantly cycle between, rather than just re-linking the same, singular dummy_shader_program
every single time.
I noticed this bug by changing coordinates_per_vertex = 4;
to 2 or 3.
Once a call to glVertexPointer
in my wrapper changes the size, the effects of my emulation of glColor4f
no longer apply to that program in the linked vertex programs array once glUseProgram
has switched the currently active program.
We would therefore have to say something less efficient like:
glColor4f(0.333, 0, 0.667, 0.80);
glVertexPointer(4, GL_FLOAT, 0, &vertex_cache[0]);
glColor4f(0.333, 0, 0.667, 0.80);
glVertexPointer(3, GL_FLOAT, 0, &sphere[0]);
glColor4f(0.333, 0, 0.667, 0.80);
glVertexPointer(2, GL_FLOAT, 0, &circle[0]);
glColor4f(0.333, 0, 0.667, 0.80);
/* I don't think size=1 was ever made a legal input, was it? */
Drawing the RGB-shaded triangle works on Windows (both on Pale Moon and Internet Explorer 11, also on Chrome I hear) but fails on Linux (Slackware and Ubuntu) for some reason.
The JavaScript console reports:
Error: WebGL: enableVertexAttribArray: -1 is not a valid `index`.
This value probably comes from a getAttribLocation() call, where this return value -1 means that the passed name didn't correspond to an active attribute in the specified program.
Again, this doesn't happen on Windows 7 (possibly because of OpenGL ES being wrapped around by DirectX). On FireFox for Linux however, GL.getAttribLocation()
does indeed return -1:
dummy_ID_col = GL.getAttribLocation(dummy_shader_program, "col");
index = dummy_ID_col;
break; // index = -1; so getAttribLocation has failed us
Apparently, the fact that I am emulating the deprecated glColor4f(float, float, float, float)
and using it in my test OpenGL/WebGL program seems to induce my dummy GLSL script, which at the time of that function was then attached without actually using the "col"
GLSL attribute name within the fragment shader itself. Somehow this causes the script compiler to fail to find a suitable attachment on Linux at least, but succeed still on Windows.
The whole script does seem successful without errors if I do this hack to fix it:
dummy_ID_col = 1; // GL.getAttribLocation(dummy_shader_program, "col");
index = dummy_ID_col;
... as it is pretty common that the vertex attribute ID is 0, while the color attrib ID is 1.
It seems I have successfully implemented glVertexPointer
(not to mention glColorPointer
) in my wrapper on top of the necessary WebGL (ES 2.0) calls, but there is one fundamental difference remaining, which is quite an important one.
The difference is that these two functions, strictly speaking, represent the deprecated feature of client-side vertex arrays. In modern OpenGL, server-side (cached to the GPU's video RAM, in OpenGL server-side memory) vertex arrays are the only way to go. Deprecating these two functions was not really a matter of the functions themselves being obsolete, so much as it was the technical detail behind them that they referred to CPU-side system memory.
That is what I am not emulating in this wrapper.
In example: You can do this in GL [ES] 1.x.
#include <GL/gl.h>
static GLfloat vertex_array[] = {
-1, +1,
-1, -1,
+1, -1,
};
void draw_right_triangle(void)
{
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(2, GL_FLOAT, 0, &vertex_array[0]);
glDrawArrays(GL_TRIANGLES, 0, 3);
vertex_array[1*2 + 0] = +1;
vertex_array[1*2 + 1] = +1; /* Now the right angle is at (1, 1), not (-1, -1). */
glDrawArrays(GL_TRIANGLES, 0, 3);
}
In my current wrapper, this will not work because my implementation of glVertexPointer
does not go through global state machine flags to pre-buffer the vertex array's pointer address to be uploaded for the next time that any and every subsequent call to DrawArrays or DrawElements is done.
It would need to be done this way at the moment if using my wrapper:
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(2, GL_FLOAT, 0, &vertex_array[0]);
glDrawArrays(GL_TRIANGLES, 0, 3);
vertex_array[1*2 + 0] = +1;
vertex_array[1*2 + 1] = +1;
// Re-upload the updated vertex_array[] to server-side VRAM.
glVertexPointer(2, GL_FLOAT, 0, &vertex_array[0]);
glDrawArrays(GL_TRIANGLES, 0, 3);
The long and short of it is that currently I have to call glVertexPointer
repeatedly for every time I want to use the C language (or JavaScript or whatever) to update the vertex array that is about to be drawn to the screen.
Reasons I have not (yet?) implemented the client-side vertex array behavior:
glVertexPointer
sends the address to system memory to a C array where your vertices are all currently looked at every time the array is drawn to primitives, but in JavaScript, I don't have any clue how to pass addresses (or references, I guess).glVertexPointer
with almost the exact same function but under a different name with only 2 differences (neither of which, the function name represents): a) being per-attribute, where each attribute is customizable/inventable within GLSL scripting, and b) setting the pointer to server-side video memory, not client-side vertex memory in C language arrays.Maybe in the future, if I do see a way to construct reference-able symbols out of JavaScript arrays, I can implement the remaining client-side and deprecated portion of glVertexPointer
's behavior, but until then, I think the current server-side method of handling it:
I have yet to decide how (and possibly even whether at all) to implement frame buffer pixel uploads.
The only pixel transfer that currently can be done through this wrapper is the universal, effortless-to-implement glReadPixels
function. This is enough to read up to the entire WebGL viewport and rendering surface into a BMP file or whatever, though with JavaScript I think that saving files to your hard disk probably doesn't work through the same channels. (And FireFox + Chrome have a "Save Image As..." that you can use to save the GL viewport to a PNG image anyway.)
However, in WebGL, what can we do with this pixel array? With this wrapper alone, we can't draw it back into a scaled texture (frame buffer read from the pixel array's color buffer of the final rendered screen, then draw to a texture rectangle inside the screen we just read out to form said texture).
My goal with this issue most likely will be to either:
glTexImage2D
with glTexCoordPointer
to support all generic 3-D texturing.glDrawPixels
, which may run on top of the Khronos texture rectangle frame buffer extension/feature.Either b) or c) will require implementing loads of other texture unit drawing control functions.
I am not even sure that this issue really is important since texturing in OpenGL often sources things like either:
glReadPixels
as discussed)So for a simple application, it may not be as much use, though I would still like to see how hard it is to subtly extend my dummy GLSL shader scripts to account for texture image support anyway at some point.
No clear license is defined inside of gl.js
, so Mozilla IceCat and Mozilla Firefox with the GNU LibreJS add-on installed both block the script from running. I respect the efforts of the free software movement and want my script to pass.
One of my recent wrapper tests--the "twelve signs" rendering--fails on Slackware, with the Mesa3D software implementation of OpenGL. It turns out that this is due to deferred rendering in between calls to glBufferSubData
and glDrawElements
.
Put into context, the exact issue is:
// Draw the 4 intersecting compatibility triangles forming our dodecagram.
glDrawElements(GL_LINE_LOOP, 3, GL_UNSIGNED_BYTE, [Rat, Dragon, Monkey]);
glDrawElements(GL_LINE_LOOP, 3, GL_UNSIGNED_BYTE, [Ox, Snake, Rooster]);
glDrawElements(GL_LINE_LOOP, 3, GL_UNSIGNED_BYTE, [Tiger, Horse, Dog]);
glDrawElements(GL_LINE_LOOP, 3, GL_UNSIGNED_BYTE, [Rabbit, Sheep, Boar]);
The program will only render the fourth, blue triangle (Rabbit, Sheep and Pig). (Debugging with glFlush()
shows that rarely, it may render the third and even the second triangles, sometimes and randomly.) This is because the vertex buffer uploads in use by the drawing comments seem to delay when the DrawElements command is finally executed.
It's an annoying synchronicity issue that can always be fixed using one of these known ways:
glFinish(void)
between steps in my wrapper of simulating DrawElementsglBufferData
, not glBufferSubData
.A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.