question on textures, alpha values and lighting

Hi,

I’m continuing to work on my Rubik’s cube JOGL-learning project, and am putting in lighting to make it look more interesting.

In order to get specular highlights off the black edges of the cubelets (they are slightly rounded cubes), I have given each cubelet the following material properties:

Kd 0.039216 0.039216 0.039216
Ka 0.000000 0.000000 0.000000
Ks 0.850000 0.850000 0.850000
Ke 0.000000 0.000000 0.000000
Ns 30

I then bind a texture over the top of them - the texture has solid blocks of colour with rounded edges for the stickers, and alpha=0 areas elsewhere. I bind them together like this:

    gl.glBlendFunc(gl.GL_SRC_ALPHA, gl.GL_ONE_MINUS_SRC_ALPHA);
    gl.glTexEnvi(GL.GL_TEXTURE_ENV, GL.GL_TEXTURE_ENV_MODE, GL.GL_DECAL);

I am lighting the scene with a diffuse and specular light above, to the left and behind the camera and a secondary light above right and behind.

It looks like this, which I’m quite pleased with:

My question though is this:

How can I get the different faces of the cube to render in different shades as well, depending on their angle to the diffuse lights, eg in this example the blue face should be rendering darker. If I turn the texturing off but leave everything else the same, the different faces do render in different shades properly.

I guess I’m asking how can I shade the texture colours ?

(a lot of work for rendering a cheap plastic toy !)

It’s been a long time since I messed with the fixed-function lighting pipeline, but IIRC the “DECAL” texture env mode skips all lighting. Have you tried it without that glTexEnvi call? I think the default environment of “MODULATE” should give you what you want.

nah, tried all the alternatives:

  • Modulate - the gaps between stickers are transparent, and the stickers themselves still have their colour but have applied material on top (so appear black most of the time, but show a little bit of their colour if you can angle it just right to get some reflected specular light)

  • Replace - gaps are transparent, stickers just show their own colour (ie can only see the texture), no lighting effect

  • Blend - same as Modulate but the specular colour reflected is (1,1,1)-sticker colour

  • no call to textureEnv - same as Modulate

I’ve tried it with an alternative texture, where the non-sticker parts are black instead of alpha=0 - with Modulate, the gaps between the stickers render properly, but as above, the stickers don’t, they are black most of the time, and show colour only when reflecting specular

I guess what I need is for the alpha=0 parts of the texture to have one applied material, and the alpha=1 parts to have a different applied material - is that even possible ?

Cheers,

Stu

Are you using the same material for the stickers as the plastic? Assuming those Kd, Ks values are diffuse/specular/ambient material values then your plastic is very, very dark. If you use the same material values then your sticker colour is going to be multiplied by a very dark diffuse grey which would explain why you don’t see any colour except for when there are specular highlights.

Leave your texture env on MODULATE, and use a separate material for the stickers, with a diffuse colour of white (1.0, 1.0, 1.0). Alternatively use a single white sticker texture and change the colours by changing the diffuse material colour.

yeah. I presume I’ll need to draw a separate quad for each sticker so that I can give it a separate material, which a bit of a pain with the way it’s written, but maybe if I’m bored I’ll do it

Hi !
I think you can change the Texture Environment with the GL_COMBINE type which has ONE big advantage to REPLACE or MODULATE : it can use either/both alpha or color from CurrentColor and Texturing by laying in what order you need in three layers.
For instance I get on to produce a shadow quad that fits my texture shape, that is “blending” over the texture. THIS IS NO MULTI-TEXTURING but to COMBINE Color blend and Texture mapping together in one-pass.
// define the current Texture env. color to what you want as a “blending” layer


GL11.glTexEnv(GL11.GL_TEXTURE_ENV, GL11.GL_TEXTURE_ENV_COLOR, 
FloatBuffer.wrap(new float[]{
colorBlend[0], 
colorBlend[1], 
colorBlend[2], 
(alphaBlend[0] + alphaBlend[1] + alphaBlend[2] + alphaBlend[3]) / 4f * colorBlend[3]
}));

// set COMBINE


       GL11.glTexEnvi(GL11.GL_TEXTURE_ENV, GL11.GL_TEXTURE_ENV_MODE, GL13.GL_COMBINE);

// COLOR-Blending is MODULATE


       GL11.glTexEnvi(GL11.GL_TEXTURE_ENV, GL13.GL_COMBINE_RGB, GL11.GL_MODULATE);

// set source0_RGB (1st layer color) to the texture


       GL11.glTexEnvi(GL11.GL_TEXTURE_ENV, GL13.GL_SOURCE0_RGB, GL11.GL_TEXTURE);

// set source1_RGB (2nd layer color) to the CONSTANT, i.e. currentColor defined above


       GL11.glTexEnvi(GL11.GL_TEXTURE_ENV, GL13.GL_SOURCE1_RGB, GL13.GL_CONSTANT);

// set operand1_RGB (2nd layer operation between source0 and 1) to GL_SRC_COLOR (see alpha blending references like JOGL texture doc : http://download.java.net/media/jogl/builds/nightly/javadoc_public/com/sun/opengl/util/texture/Texture.html)


GL11.glTexEnvi(GL11.GL_TEXTURE_ENV, GL13.GL_OPERAND1_RGB, GL11.GL_SRC_COLOR);

// ALPHA-Blending is MODULATE, too


      GL11.glTexEnvi(GL11.GL_TEXTURE_ENV, GL13.GL_COMBINE_ALPHA, GL11.GL_MODULATE);

// set source0 (1st layer alpha) as the Texture alpha values


       GL11.glTexEnvi(GL11.GL_TEXTURE_ENV, GL13.GL_SOURCE0_ALPHA, GL11.GL_TEXTURE);

// set source1 (2nd layer alpha) as the current env. color alpha values


       GL11.glTexEnvi(GL11.GL_TEXTURE_ENV, GL13.GL_SOURCE1_ALPHA, GL13.GL_CONSTANT);

// operate on alpha for the 2nd alpha layer with GL_SRC_Alpha blending which will take the SOURCE0 alpha (that is the texture !!)


        GL11.glTexEnvi(GL11.GL_TEXTURE_ENV, GL13.GL_OPERAND1_ALPHA, GL11.GL_SRC_ALPHA);

        GL11.glBegin(GL11.GL_QUADS);
        GL11.glNormal3f(0, 0, 1);
        GL11.glColor4f(colorBlend[0], colorBlend[1], colorBlend[2], alphaBlend[0] * colorBlend[3]);
        if (texture != null) {
            GL11.glTexCoord2f(0f, 0f);
        }
        GL11.glVertex2d(bounds.getX(), bounds.getY());
        // ... UP TO GL_END
        

NOTICE : This code is NOT a complete overview of the COMBINE texture environment, which already has got default behaviours which you should pay attention to, in some OpenGL 2.0 official guide. That’s why some values are thoroughly NOT ignored, but stay masked in this sample code.

thanks, I’ll check that out (I’m about to go on holiday though, so won’t be for a couple of weeks ;D )

Finally got round to looking at this - that was pretty useful, thank very much.

had a good play around - gl.glTexEnvi(GL.GL_TEXTURE_ENV, GL.GL_COMBINE_RGB, GL.GL_ADD); was the closest to what I wanted, since it could display the stickers in their proper colour, but add on the shininess on top.

I still couldn’t get the stickers to have the right diffuse material properties that I wanted though.

Instead I’ve written a pixel shader program in Cg to do it - it reads the incoming texel alpha value and sets the material property differently depending on whether the alpha is 0 or 1.

It works, but I have a few Cg problems though, which I’ve posted on the nVidea site (here and here if there are any Cg experts who fancy a look)