## Normal Maps: WIP

with one comment

For the record, the below image is not yet correct, but here’s a first-pass at normal mapping in LxEngine:

The tangent vectors are calculated by GLGeom. The algorithm I’m using is somewhat…custom. I haven’t seen an implementation similar to how I’m attempting it – and thus suspect that I’ve missed a key point or two. That’s okay, however – this is for fun and to learn something.

The basic approach is to define a function F(p,v) = dUV, a function that takes a point on the surface of the mesh and a direction vector and returns the change in UV at that point in that direction. If we constraint this function to only be valid at vertices of the mesh (which is fine, since we’re only going to use this function at vertex points), then we can define F(p,v) as the weighted average of all the edges adjacent to the vertex at p – with the weights corresponding to the dot product between v and the direction of that edge.  So if we have F(p,v) defined, that we can find tangent and bitangent by finding directions v where F is at a local maximum. This can be done by simple calculus: where the derivative of a function is 0, it is at a local maximum or minimum. Given that F(p,v) is a fairly simple weighted average, the derivative is not complex and solving for where it is 0 is not complex. Thus we end up with the directions in which U increases most and V increase most…which, until I locate the flaw in my understanding of the problem, are theoretically the tangent and bitangent directions.

We’ll see. For now, I have compiling code and a screenshot. That’s enough for today. Testing and debugging will follow

Written by arthur

April 13th, 2012 at 8:19 pm

Posted in lxengine

## Material System

Work continues on the LxEngine material system…

The above is a simple “toon” shader on the Suzanne model. The shader code is based on the simple example provided at LightHouse3d, but bases the color on a 1d texture look-up on a slightly blurred color texture rather discrete if-else statements.

### The Video

Here’s a quick video of some of the material effects:

### The Code

At the highest-level, the implementation of the new shader is very simple. The new shader is defined by creating a new directory “ToonSimple” in the materials sub-directory of the media directory. This directory contains a vertex shader, a fragment shader, and JSON parameters description.

The material is then loaded in the C++ code via a call to

pRasterizer->acquireMaterial("ToonSimple")

and attached to the Instance‘s spMaterial member. LxEngine handles all the shader loading and parameter activation.

On to the details…

The vertex shader code is quite simple and uses a fixed light direction:

uniform mat4    unifProjMatrix;
uniform mat4    unifViewMatrix;
uniform mat3    unifNormalMatrix;

in      vec3    vertNormal;

varying out float fragIntensity;

void main()
{
// Keep it simple and use a fixed light direction
vec3 lightDir = vec3(.5,-.5, 1.0);

// The fragIntensity is effectively just the intensity of the diffuse
// value from the Phong reflection model.
//
fragIntensity = dot(normalize(lightDir), unifNormalMatrix * vertNormal);

gl_Position = unifProjMatrix * unifViewMatrix * gl_Vertex;
}

The uniforms – unifProjMatrix, unifViewMatrix, unifNormalMatrix – are all “standard” LxEngine names, therefore it will automatically set the correct matrix values when activating the shader. Likewise with the attribute vertNormal; it too will be set automatically by the existing engine code. (This will be explained momentarily.)

The fragment shader is quite simple:

#version 150
#extension GL_ARB_explicit_attrib_location : enable

uniform sampler1D unifTexture0;

in      float fragIntensity;

layout(location = 0) out vec4 outColor;

void main()
{
outColor = texture(unifTexture0, fragIntensity);
}

Now the fragment shader does have an interesting detail: the uniform unifTexture0 is not a “standard” LxEngine uniform. (How could it be? The transformation matrices are common to many shaders, as are properties like the geometry’s normals, but is a texture map ever going to be “standard” enough that the engine would know what to set?)

This is a custom uniform, but it still does not require any C++ code for the engine to set it’s value properly. We’ll get to that momentarily.

### Automatically setting the shader variables

The automatic setting of uniforms and attributes is done via calls to getActiveUniform and getActiveAttrib after the GLSL program is compiled. The MaterialClass class wraps the GLSL program and provides iteration functions that exemplify the use of these OpenGL calls:

void
MaterialClass::iterateUniforms (std::function<void(const Uniform& uniform)> f)
{
int uniformCount;
gl->getProgramiv(mProgram, GL_ACTIVE_UNIFORMS, &uniformCount);
for (int i = 0; i < uniformCount; ++i)
{
Uniform uniform;
char    uniformName[128];
GLsizei uniformNameLength;

gl->getActiveUniform(mProgram, GLuint(i), sizeof(uniformName), &uniformNameLength, &uniform.size, &uniform.type, uniformName);

if (uniformNameLength >= sizeof(uniformName))
{
throw lx_error_exception("GLSL program contains a uniform with too long a name size!");
}
else
{
uniform.name = uniformName;
uniform.location = gl->getUniformLocation(mProgram, uniformName);
f(uniform);
}
}
}

The LxEngine internal rasterizer code, after compiling a GLSL shader for the first time, will iterate over the uniforms and attributes to generate a set of values that need to be set whenever that material is made active. The set of “instructions” necessary to set those values is encapsulated in a std::vector<std::function<void()>> – which, in effect, allows a sort of dynamic code generation at the expense of a bit of overhead to the std::function calls. The flexibility and simplicity definitely win out over the efficiency loss for the purposes of LxEngine.

For example, below is a code snippet from the shader attribute instruction generation function (or see the latest version of the material source code for more details):

std::function<void()>
Material::_generateInstruction(RasterizerGL* pRasterizer, const Attribute& attribute, lx0::lxvar& value)
{
...

if (attribute.name == "vertNormal")
{
return [=]() {
auto& vboNormals = pRasterizer->mContext.spGeometry->mVboNormal;
if (vboNormals)
{
gl->bindBuffer(GL_ARRAY_BUFFER, vboNormals);
gl->vertexAttribPointer(location, 3, GL_FLOAT, GL_FALSE, 0, 0);
gl->enableVertexAttribArray(location);
}
else
gl->disableVertexAttribArray(location);

check_glerror();
};
}

### Setting a custom uniform

The non-standard unifTexture0 uniform is set somewhat differently. The material definition – in addition to the vertex and fragment shaders – also includes a simple JSON parameter description file. In this case, it contains only one parameter:

{
parameters: {
}
}

In this case, the _generateInstruction() method loops over all unrecognized uniform names and searches for a user-specified parameter value for that uniform. In this case, it finds “unifTexture0″ as both an unrecognized uniform and a value in the parameter mapping.

Since the information about the uniform also includes the data type (GL_SAMPLER_1D), LxEngine can figure out to interpret that string value as an image filename, can load that file and store it in the texture cache, and generate an instruction to set that texture when activating the material:

else if (uniform.type == GL_SAMPLER_1D)
{
auto filename = value.as<std::string>();

TexturePtr spTexture = pRasterizer->mTextureCache.findOrCreate(filename );
GLuint textureId = spTexture->mId;

// Activate the corresponding texture unit and set *that* to the GL id
return [=]() {
const auto unit = pRasterizer->mContext.textureUnit++;

// Set the shader uniform to the *texture unit* containing the texture (NOT
// the GL id of the texture)
gl->uniform1i(loc, unit);

gl->activeTexture(GL_TEXTURE0 + unit);
gl->bindTexture(GL_TEXTURE_1D, textureId);

// Set the parameters on the texture unit
gl->texParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, mFilter);
gl->texParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, mFilter);
gl->enable(GL_TEXTURE_1D);
check_glerror();
};
}

The point really is that adding a simple shader, like this toon shader, is simple to do. The new material system in LxEngine makes it trivial as common uniforms and attributes are automatically set up and the mechanism for specifying custom uniforms is quite easy.

The objective is an engine designed to make experimentation and research simple.

The toon shader run with an alternate texture (i.e. same material “class” / shader program, different material “instance” / parameterization) displayed with a 2-pass, 9×9 Gaussian fullscreen blur active.

### What’s Next? LxEngine Tutorial 4

I’m currently working on cleaning up and writing up a good description of “Tutorial 4″ of LxEngine. I want to add a couple more effects to make the tutorial feel a bit more substantial first (perhaps add shadow mapping?), but would also like to get a finished tutorial out the door. As a preview, the fourth tutorial will include at least the following: writing an application via Javascript, geometry generated from scripts, multipass rendering, multithreading, time-lapse events, and…well, probably more if I don’t hurry up and finish this off!

Written by arthur

March 22nd, 2012 at 10:29 pm

Posted in lxengine

## JQuery Seamless Image Preview

with one comment

I wrote a brief JQuery plug-in which transforms a normal <IMG> element into a dynamic, tiled version of the image with a slider for controlling the size of the image tiles.

### Purpose

The purpose would be to preview quickly seamless textures. I wrote this mostly to get a bit more experience with HTML5 and JQuery.

I also like the idea of improving this enough that I could a site like OpenGameArt.org could use it for images tagged with ‘seamless’ – but we’ll see about that: it needs more polish before I would feel right contacting anyone over there.

### Conclusion

Anyway, good to get something demonstrable and graphical back up on the blog!

Written by arthur

November 27th, 2011 at 2:17 pm

Posted in company

## Bug

Interesting image from a typo causing LxEngine’s noise function to temporarily break:

That's not right...

All in all, the image suggests that canyon generation might be a good feature to add to the Terrain sample. At the moment, I’m ripping apart and restructuring the Terrain sample match some of the architectural developments in LxEngine over the last couple months (i.e. in short summary, cleaner and more concise MVC structuring to the classes). However, the Terrain sample currently renders the terrain as a surface and I have been tempted to move it to a voxel-based/Minecraft-like structure instead. We’ll see. Clean-up first.

Written by arthur

May 19th, 2011 at 6:33 pm

Posted in lxengine

Tagged with , , ,