Jump to content
  • Advertisement
  • entries
    3
  • comments
    7
  • views
    5202

About this blog

A journal of my experiences and learnings as I use OpenGL in various ways with different languages and platforms.

Entries in this blog

 

JS Environment and Testing

[font=Arial][background=transparent]When I first tried my hand at programming something that employed real time rendering automated testing was not even a thing I was aware of. Sure I was a young lad at the time and had much to learn but the mention of writing a test was absent from any and every article I claimed as a learning resource. Working with web services and business development has taught me the great power that comes from automated testing, and this advantage has made my work increasingly better in quality. There still stands the simple fact that automated testing can not cover all quality cases of a product for example overall "user experience" (game quality?). [/background][/font]
[font=Arial][background=transparent].[/background][/font]
[font=Arial] [background=transparent]The Environment[/background][/font]
[font=Arial][background=transparent].[/background][/font]
[font=Arial][background=transparent]It is my believe that in order to establish a quality control environment one must establish a development environment as well as a process that properly facilitates this quality control. It is certainly an achievement to implement quality control after a product is established. In my journey with WebGL there is no shortage of tools to use and I'm writing once again from my OS-X environment. My initial journal entry described the basic local development environment I use and with this going I have the ability to use a package manager and boost my WebGL project with other libraries.[/background][/font]
[font=Arial][background=transparent].[/background][/font]
[font=Arial][background=transparent]Install the Node Package Manager: with OS-X it's best to use homebrew for this otherwise your Linux package manager should have a recent version, and there is a Windows installer available.[/background][/font]
.brew install npmsudo apt-get install npmsudo yum install npm
[font=Arial][background=transparent]. [/background][/font]
[font=Arial][background=transparent]Once you have npm installed you will be able to create a "package configuration" for your JS project which contains many things, including any dependencies your application has. The package configuration is saved in a file in the root directory of your project called 'package.json' and we can generate this very easily.[/background][/font]
[font=Arial][background=transparent].[/background][/font]cd /to/your/projectnpm init # and follow the instructions...
[font=Arial][background=transparent]. [/background][/font]
[font=Arial][background=transparent]This will ask you some questions about your project (including Git remote repo location) and store this in the package.json file. Now that we have the configuration it's time to install the most important package for Node users, RequireJS (http://requirejs.org/). [/background][/font]
.
[font=Arial][background=transparent]Dependency Mangagement [/background][/font]
[font=Arial][background=transparent].[/background][/font]
[font=Arial][background=transparent]As with many technologies the demands of a Javascript project are often tightly coupled with the client that is responsible for running that script. There is of course the most common use case of distributing JS to a browser from a web-server and running it on a client browser. Then there is the case of running it on a web-server and processing requests using the JS. More recently the language has found a way with being a client only language in that a local engine (such as Node) can be used to run JS for many purposes. With so many ways to use the language there is a challenge of managing the dependencies and libraries a project uses.[/background][/font]
[font=Arial][background=transparent].[/background][/font]
[font=Arial][background=transparent]A typical web application would simply load the Javascript from an HTML page that is delivered to the client. This is simple and the browser does all the work of requesting the resource and loading it in the browser. What about a library however, or a server side application? How are the different files and resources called upon loaded by the client that is to execute/use those resources? This is where a convention known as AMD comes in (Asynchronous module definition). This is a standard way of creating modules of code that can be loaded in an asynch. fashion in many different environments, including the client-side browser. Read more on the benefits of using AMD in your JS here - http://requirejs.org/docs/whyamd.html[/background][/font]
.
RequireJS is a library that complies to loading standard AMD and is very easy to configure for any environment including the client-side browser. This library has a "main entry point" that can be configured through an HTML tag, or simply called with a JS function.
.
First to install requireJS with NPM -
.npm install --save requirejs
.
This will install the library to the 'node_modules' directory local to your project, the --save option saves the dependency requirement to your local package.json (for easy distribution). Once installed you can include requireJS into ordinary HTML and define your main entry point with a script tag.
.[code=html:0]
.
Where the script in data-main is your entry point. This should look something like the following, but please do read through RequireJS documentation (http://requirejs.org/docs/start.html)
.[code=js:0]requirejs.config({ baseUrl: '/J3L'});requirejs(['J3L', './path/to/module-foo'], function(J3L, moduleFoo) { var testApp = new J3L.App("Test App"); var window = testApp.createWindow(800, 600); testApp.start();});
.
The initial call is to configure your environment and there are many options available here (again see the docs). The Requirejs method is what starts your application and the array included defines the dependencies your application needs. The function provided is a callback that is fired when those dependencies have finished loading.
.
In order to define a module you must follow the AMD convention, without going into detail this looks something like this:
.[code=js:0]define('FrameListener', ['./Class'], function(Class) { //Create some type of object to return that represents the "FrameListener" module var FrameListener = Class.extend({ init: function() {}, onUpdate: function() {} }); return FrameListener;});
.
The define function is key for AMD and defines information about your module including what dependencies are needed. These dependencies are "injected" into the callback method that follows making other modules instantly available by including them in the array/function callback.
.
To Test or Not To Test
.
While I've started establishing unit tests for the WebGL projects I've been working on, functional tests remain a mystery to me. The idea of writing a black box test against code that is so coupled with real time rendering seems daunting, but my mind tells me there has to be a way. The mass amount of research I have done is not promising and mostly generally points to a very specific solution to a very specific product. People will write bots that automate through the game and others capture rendering output as base64 and compare to future changes for automated regression. What has become quite clear is that black box integration/functional testing of real time rendering software is a giant black hole.
.
While I am learning how to use and manipulate WebGL/OpengL(ES) in every way possible, I will constantly be looking for a way to test the output of a system that is seemingly non-deterministic. Otherwise I have provided more fuel for an article series I keep promising, and this is the kind of thought out material that will be included. As always I want to provide an example that does more then get your feet wet, it gives you a serous nudge in how to gain the struts for a real time rendering application in place.
.
Until next time, Cheers!

roblane09

roblane09

 

I'm sensing a pattern here

[color=rgb(0,0,0)][font=Arial] [background=transparent]With this second entry I find myself ecstatic over my own personal introduction to WebGL. This subject gives me the opportunity to invest myself in a new community and it stamps the beginning of a new journey. A journey that will no doubt last as long, if not longer than what I've experienced as a software engineer to date. The obstacles in front of me look familiar and there is a familiar taste to everything, I think this will be a long lasting friendship...[/background][/font][/color]
.
[color=rgb(0,0,0)][font=Arial][background=transparent]Beyond the Basics[/background][/font][/color]
.
[color=rgb(0,0,0)][font=Arial][background=transparent]I'm not ready to jump into an entry or article series that walks you through writing shaders, interpolation of colors, how we can properly create lights or any of that today. It's a tempting task to perform for sure, provide a community something "meaty" they can use to bootstrap something fun. The payoff here is really not great though because honestly, anything I can give you in a quick entry is already covered by MDN or some other person who has invested far more time here. If I'm giving you a series on JS then it's going to be meaningful, useable code because that's what I believe in distributing.[/background][/font][/color]
.
[color=rgb(0,0,0)][font=Arial][background=transparent]That being said I've come to a point that I often do when learning a subject when I've poured over countless articles, tutorials and read the same API method doc. 10 times. I'm ready to apply to a problem, because that's where the bridge lies for this developer. After the past week or so the world of WebGL engines has opened up to me, and three candidates have made my short list for contributions so far:[/background][/font][/color]
.
[background=transparent]Three.js (threejs.org) - I'm very impressed with the code quality of this project, and there seems to be a good number of projects using the engine. I'm a fan of the underlying modular architecture, not just to say it uses AMD for dependency management, but the fact that we can swap sub-systems.[/background]
[background=transparent]BabylonJS ([/background][color=rgb(17,85,204)][background=transparent]http://www.babylonjs.com/[/background][/color] [background=transparent]) - I like the editor included here and the project has some very good examples demonstrating various shaders. The community seems very active and I can see many issues I could potentially sink my teeth into.[/background]
[background=transparent]PlayCanvas ([/background][color=rgb(17,85,204)][background=transparent]https://playcanvas.com/[/background][/color] [background=transparent]) - Seems to be a more popular commercial choice and includes a hosting service which makes it easier to get your game distributed and get ad content into your game. I'm more interested in contributions to graphics here, but it gave me an idea take away for data persistence through web sockets.[/background]

.
[color=rgb(0,0,0)][font=Arial][background=transparent]Otherwise I looked at other C++ engines to see if a port to WebGL was worthwhile and the short answer is no. It seems tools that can generate JS code from low level code make any sort of port a waste of time.[/background][/font][/color]
.
[color=rgb(0,0,0)][font=Arial][background=transparent]A simple pattern[/background][/font][/color]
[color=rgb(0,0,0)][font=Arial][background=transparent]While a great deal of my time will be spent contributing to the projects mentioned above, it's important for me to have something that I can just "play with." Really what I mean by this is a simple project that I can build upon slowly over time. The underlying idea is surely not unique (as few are) and revenue is not even on the list of goals here. I'm looking to take what I know about web application architecture and apply it to what I'm learning about graphics rendering.[/background][/font][/color]
.
[color=rgb(0,0,0)][font=Arial][background=transparent]Engineering is about solving problems to achieve a goal and the solutions we generate become repetitive until patterns emerge in the way things are "done." The persistence and sharing of data is a common problem with any domain which extends to those that could benefit from graphics rendering. This rendering is likely to be real time as persistence and distribution of data is essentially for the benefit of easily and quickly viewing that data.[/background][/font][/color]
.
[color=rgb(0,0,0)][font=Arial][background=transparent]Real time rendering involves a great deal of assets in one way or another, and these define the virtual world that we are rendering and how it should present to a viewer. These assets are in fact persisted pieces of data that make their way from memory, to CPU to GPU. The benefit of storing this data on a central server has already been seen in many applications. The nature of an HTTP application, specifically one using persisted websockets seems to match this problem set.[/background][/font][/color]
.
[color=rgb(0,0,0)][font=Arial][background=transparent]Concluding[/background][/font][/color]
.
[color=rgb(0,0,0)][font=Arial][background=transparent]I will be honest this post was very much me getting myself on the level, and trying to set the tone for the future work I will be producing. While I plan to post a great deal on the inner workings of render pipeline and shaders, I'm also getting heavy with some JS and web technologies. I hope you have kept with me thus far and I promise next I write I will provide you with much more "juicy" details.[/background][/font][/color]
.
[color=rgb(0,0,0)][font=Arial][background=transparent]Until then, cheers![/background][/font][/color]

roblane09

roblane09

 

Bootstrapping with WebGL

Why WebGL
.
A vast majority of my knowledge and experience in software engineering has revolved around web applications development. While most of my professional duties involve back-end development (mostly Ruby), I have more then a fair share of front end web development skills(i.e. JavaScript, CSS(3) and HTML). Prior to my maturity as a developer before much practice with any specific language I had an interest in video game technology. More specifically the real time rendering and components of DirectX and OpenGL.
.
After some great advice on the "For Beginners" forums (https://www.gamedev.net/topic/673606-direction-for-a-seasoned-web-dev/) I decided to begin my journey with WebGL. Since I've been using OS X and Ubuntu for the past 5 years to develop on, I opened up the MacBook and shut down the Windows machine for another day.
.
My Environment
.
With OS X I have several editors and IDEs I like to use depending on the situation but in this case I want to keep things simple. My simple editor of choice here is VIM using a handful of plugins including:
CtrlP
CTags w/CtrlP search
NerdTree
Syntastic
Vim-fugitive
Vim-l9

.
With WebGL I have the option to open my html files directly from a browser but this has limitations on linking and resource access. For this reason a simple Nginx server is fitting here. Using a package manager for OS X called Homebrew I install nginx with a barebones configuration. A quick configuration of the server giving it a name ending in 'local' such as webgl.local and an addition to my hosts file allows me to serve and access content just as if hosting on a remote server.
.
My OS X terminal is configured to use bash (sorry zsh people) and I use tmux when developing with vim.
.
Easy to Instantiate
.
WebGL contexts are served from the canvas element and can be considered standard or experimental. It is my understanding that standard is what you will get in modern browsers and experimental is a fallback. I've been using the following site for a baseline of support here - http://caniuse.com/#feat=webgl
.canvas = document.getElementById("glcanvas");gl = canvas.getContext("webgl") || canvast.getContext("experimental-webgl");
.
It's then simple to clear the color of the canvas rendering viewport.
.gl.clearColor(0.0, 0.0, 0.0, 1.0);gl.enable(gl.DEPTH_TEST);gl.depthFunc(gl.LEQUAL);gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
.
Shaders in my DOM
.
Using an HTML script element, I am able to define shaders directly in an HTML file, and reference these elements from my script by their ID. Once the element is stored in a JS object I can read all children and siblings representing the text of the shader. I then follow the standard OpenGL process of compiling the text, attach it to a program along with any other compiled scripts and link the program.
.
.
Math and a quick shortcut
.
One thing I knew was at some point I would run into some math that I would need to set aside time to learn. At this point with Javascript there seems to be a library for almost everything on GitHub and Matrix/Vector arithmetic was no exception. Once I had this component I was able to create a standard interface for creating perspective matrices.
.perspectiveMatrix = makePerspective(45, vertAspect, 0.1, 100.0);
.
Plugging and chugging
The remainder of the process so far has been very "standard" use of the methods defined by OpenGL ES. Tasks such as creating, binding and populating buffers or drawing a triangle list. After establishing the rendering process in a draw scene method I was able to use some simple JavaScript to establish a rendering loop. This is the definition of simple and I'm sure has more then a few problems, but it's fine for my own learning purposes.
.setInterval(drawScene, 15);
.
In Conclusion
.
More progress has been made such as textures and lighting, but I will leave remaining details for another time. It would also be nice to put a simple article together to describe how to get a scene going and where to reference some nice JS tools (e.g. testing). Otherwise It has become very clear to me that I will need to get a very solid grasp of this shader language in all steps of the pipeline if I want to be solid in controlling real time rendering. Off to discover more, please leave questions or comments if you have any!
.
Until next time, Cheers!

roblane09

roblane09

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!