Giter Club home page Giter Club logo

opengl-js's People

Contributors

cxd4 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar

opengl-js's Issues

Command ordering glitch with EnableClientState and ColorPointer.

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.

"packing limits" for GLSL programs?

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

Memory allocation is unstable and might leak.

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.

glColor4f only updates 1 of the 3 possible vertex size state combinations.

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? */

GLSL sometimes fails to read attribute locations.

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.

Client-side emulation of vertex arrays is not present.

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:

  • I don't know how to do it in JavaScript. In C, 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).
  • It is removed anyway. Server-side vertex arrays are faster because drawing the arrays doesn't need to constantly read from CPU-side system memory at the pointer address specified by the last call to VertexPointer.
  • To demonstrate that deprecating these functions was naively overzealous. Many people play "follow the leader" with Khronos' insistence to deprecate and remove these functions as a stereotypical gesture of enforcing low-level-only, performance-only graphics programming. For example, ES 2.0 replaces 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:

  • promotes better performance, esp. if re-using the same video memory over and over
  • successfully represents a transitive, mutually compliant practice of GL programming in between GL ES 1.1 and ES 2.0

pixel transfers not implemented

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:

  • a) Do nothing and decide it's not worth worrying over. :)
  • b) Implement glTexImage2D with glTexCoordPointer to support all generic 3-D texturing.
  • c) Implement the infamous 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:

  • bitmap images from user's hard disk (easier with C than with JS)
  • the OpenGL rendering canvas itself, converted to a bitmap (using glReadPixels as discussed)
  • another data source outside the scope of the OpenGL thread/application (like CPU RAM in an emulator that reads from RAM supplied by an external plugin or process)
  • huge JavaScript arrays initialized out of nowhere with thousands of pixel elements with red, green, and blue color components to form effective text-based image file formats from binary images

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.

Blocked by LibreJS

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.

Broken glDrawElements on implementations with deferred rendering.

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 DrawElements
  • buffer "orphaning"--typically detachment and re-attachment of the element array buffer
  • Use glBufferData, not glBufferSubData.
  • Cycle between a set of multiple buffer objects.
  • Re-buffer the data again to a dummy copy between the previous buffer command and the draw.
  • https://www.opengl.org/registry/specs/ARB/buffer_storage.txt

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.